1 /* 2 * QEMU Floppy disk emulator (Intel 82078) 3 * 4 * Copyright (c) 2003, 2007 Jocelyn Mayer 5 * Copyright (c) 2008 Hervé Poussineau 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 * THE SOFTWARE. 24 */ 25 /* 26 * The controller is used in Sun4m systems in a slightly different 27 * way. There are changes in DOR register and DMA is not available. 28 */ 29 30 #include "hw/hw.h" 31 #include "hw/block/fdc.h" 32 #include "qemu/error-report.h" 33 #include "qemu/timer.h" 34 #include "hw/isa/isa.h" 35 #include "hw/sysbus.h" 36 #include "sysemu/block-backend.h" 37 #include "sysemu/blockdev.h" 38 #include "sysemu/sysemu.h" 39 #include "qemu/log.h" 40 41 /********************************************************/ 42 /* debug Floppy devices */ 43 //#define DEBUG_FLOPPY 44 45 #ifdef DEBUG_FLOPPY 46 #define FLOPPY_DPRINTF(fmt, ...) \ 47 do { printf("FLOPPY: " fmt , ## __VA_ARGS__); } while (0) 48 #else 49 #define FLOPPY_DPRINTF(fmt, ...) 50 #endif 51 52 /********************************************************/ 53 /* Floppy drive emulation */ 54 55 typedef enum FDriveRate { 56 FDRIVE_RATE_500K = 0x00, /* 500 Kbps */ 57 FDRIVE_RATE_300K = 0x01, /* 300 Kbps */ 58 FDRIVE_RATE_250K = 0x02, /* 250 Kbps */ 59 FDRIVE_RATE_1M = 0x03, /* 1 Mbps */ 60 } FDriveRate; 61 62 typedef struct FDFormat { 63 FDriveType drive; 64 uint8_t last_sect; 65 uint8_t max_track; 66 uint8_t max_head; 67 FDriveRate rate; 68 } FDFormat; 69 70 static const FDFormat fd_formats[] = { 71 /* First entry is default format */ 72 /* 1.44 MB 3"1/2 floppy disks */ 73 { FDRIVE_DRV_144, 18, 80, 1, FDRIVE_RATE_500K, }, 74 { FDRIVE_DRV_144, 20, 80, 1, FDRIVE_RATE_500K, }, 75 { FDRIVE_DRV_144, 21, 80, 1, FDRIVE_RATE_500K, }, 76 { FDRIVE_DRV_144, 21, 82, 1, FDRIVE_RATE_500K, }, 77 { FDRIVE_DRV_144, 21, 83, 1, FDRIVE_RATE_500K, }, 78 { FDRIVE_DRV_144, 22, 80, 1, FDRIVE_RATE_500K, }, 79 { FDRIVE_DRV_144, 23, 80, 1, FDRIVE_RATE_500K, }, 80 { FDRIVE_DRV_144, 24, 80, 1, FDRIVE_RATE_500K, }, 81 /* 2.88 MB 3"1/2 floppy disks */ 82 { FDRIVE_DRV_288, 36, 80, 1, FDRIVE_RATE_1M, }, 83 { FDRIVE_DRV_288, 39, 80, 1, FDRIVE_RATE_1M, }, 84 { FDRIVE_DRV_288, 40, 80, 1, FDRIVE_RATE_1M, }, 85 { FDRIVE_DRV_288, 44, 80, 1, FDRIVE_RATE_1M, }, 86 { FDRIVE_DRV_288, 48, 80, 1, FDRIVE_RATE_1M, }, 87 /* 720 kB 3"1/2 floppy disks */ 88 { FDRIVE_DRV_144, 9, 80, 1, FDRIVE_RATE_250K, }, 89 { FDRIVE_DRV_144, 10, 80, 1, FDRIVE_RATE_250K, }, 90 { FDRIVE_DRV_144, 10, 82, 1, FDRIVE_RATE_250K, }, 91 { FDRIVE_DRV_144, 10, 83, 1, FDRIVE_RATE_250K, }, 92 { FDRIVE_DRV_144, 13, 80, 1, FDRIVE_RATE_250K, }, 93 { FDRIVE_DRV_144, 14, 80, 1, FDRIVE_RATE_250K, }, 94 /* 1.2 MB 5"1/4 floppy disks */ 95 { FDRIVE_DRV_120, 15, 80, 1, FDRIVE_RATE_500K, }, 96 { FDRIVE_DRV_120, 18, 80, 1, FDRIVE_RATE_500K, }, 97 { FDRIVE_DRV_120, 18, 82, 1, FDRIVE_RATE_500K, }, 98 { FDRIVE_DRV_120, 18, 83, 1, FDRIVE_RATE_500K, }, 99 { FDRIVE_DRV_120, 20, 80, 1, FDRIVE_RATE_500K, }, 100 /* 720 kB 5"1/4 floppy disks */ 101 { FDRIVE_DRV_120, 9, 80, 1, FDRIVE_RATE_250K, }, 102 { FDRIVE_DRV_120, 11, 80, 1, FDRIVE_RATE_250K, }, 103 /* 360 kB 5"1/4 floppy disks */ 104 { FDRIVE_DRV_120, 9, 40, 1, FDRIVE_RATE_300K, }, 105 { FDRIVE_DRV_120, 9, 40, 0, FDRIVE_RATE_300K, }, 106 { FDRIVE_DRV_120, 10, 41, 1, FDRIVE_RATE_300K, }, 107 { FDRIVE_DRV_120, 10, 42, 1, FDRIVE_RATE_300K, }, 108 /* 320 kB 5"1/4 floppy disks */ 109 { FDRIVE_DRV_120, 8, 40, 1, FDRIVE_RATE_250K, }, 110 { FDRIVE_DRV_120, 8, 40, 0, FDRIVE_RATE_250K, }, 111 /* 360 kB must match 5"1/4 better than 3"1/2... */ 112 { FDRIVE_DRV_144, 9, 80, 0, FDRIVE_RATE_250K, }, 113 /* end */ 114 { FDRIVE_DRV_NONE, -1, -1, 0, 0, }, 115 }; 116 117 static void pick_geometry(BlockBackend *blk, int *nb_heads, 118 int *max_track, int *last_sect, 119 FDriveType drive_in, FDriveType *drive, 120 FDriveRate *rate) 121 { 122 const FDFormat *parse; 123 uint64_t nb_sectors, size; 124 int i, first_match, match; 125 126 blk_get_geometry(blk, &nb_sectors); 127 match = -1; 128 first_match = -1; 129 for (i = 0; ; i++) { 130 parse = &fd_formats[i]; 131 if (parse->drive == FDRIVE_DRV_NONE) { 132 break; 133 } 134 if (drive_in == parse->drive || 135 drive_in == FDRIVE_DRV_NONE) { 136 size = (parse->max_head + 1) * parse->max_track * 137 parse->last_sect; 138 if (nb_sectors == size) { 139 match = i; 140 break; 141 } 142 if (first_match == -1) { 143 first_match = i; 144 } 145 } 146 } 147 if (match == -1) { 148 if (first_match == -1) { 149 match = 1; 150 } else { 151 match = first_match; 152 } 153 parse = &fd_formats[match]; 154 } 155 *nb_heads = parse->max_head + 1; 156 *max_track = parse->max_track; 157 *last_sect = parse->last_sect; 158 *drive = parse->drive; 159 *rate = parse->rate; 160 } 161 162 #define GET_CUR_DRV(fdctrl) ((fdctrl)->cur_drv) 163 #define SET_CUR_DRV(fdctrl, drive) ((fdctrl)->cur_drv = (drive)) 164 165 /* Will always be a fixed parameter for us */ 166 #define FD_SECTOR_LEN 512 167 #define FD_SECTOR_SC 2 /* Sector size code */ 168 #define FD_RESET_SENSEI_COUNT 4 /* Number of sense interrupts on RESET */ 169 170 typedef struct FDCtrl FDCtrl; 171 172 /* Floppy disk drive emulation */ 173 typedef enum FDiskFlags { 174 FDISK_DBL_SIDES = 0x01, 175 } FDiskFlags; 176 177 typedef struct FDrive { 178 FDCtrl *fdctrl; 179 BlockBackend *blk; 180 /* Drive status */ 181 FDriveType drive; 182 uint8_t perpendicular; /* 2.88 MB access mode */ 183 /* Position */ 184 uint8_t head; 185 uint8_t track; 186 uint8_t sect; 187 /* Media */ 188 FDiskFlags flags; 189 uint8_t last_sect; /* Nb sector per track */ 190 uint8_t max_track; /* Nb of tracks */ 191 uint16_t bps; /* Bytes per sector */ 192 uint8_t ro; /* Is read-only */ 193 uint8_t media_changed; /* Is media changed */ 194 uint8_t media_rate; /* Data rate of medium */ 195 } FDrive; 196 197 static void fd_init(FDrive *drv) 198 { 199 /* Drive */ 200 drv->drive = FDRIVE_DRV_NONE; 201 drv->perpendicular = 0; 202 /* Disk */ 203 drv->last_sect = 0; 204 drv->max_track = 0; 205 } 206 207 #define NUM_SIDES(drv) ((drv)->flags & FDISK_DBL_SIDES ? 2 : 1) 208 209 static int fd_sector_calc(uint8_t head, uint8_t track, uint8_t sect, 210 uint8_t last_sect, uint8_t num_sides) 211 { 212 return (((track * num_sides) + head) * last_sect) + sect - 1; 213 } 214 215 /* Returns current position, in sectors, for given drive */ 216 static int fd_sector(FDrive *drv) 217 { 218 return fd_sector_calc(drv->head, drv->track, drv->sect, drv->last_sect, 219 NUM_SIDES(drv)); 220 } 221 222 /* Seek to a new position: 223 * returns 0 if already on right track 224 * returns 1 if track changed 225 * returns 2 if track is invalid 226 * returns 3 if sector is invalid 227 * returns 4 if seek is disabled 228 */ 229 static int fd_seek(FDrive *drv, uint8_t head, uint8_t track, uint8_t sect, 230 int enable_seek) 231 { 232 uint32_t sector; 233 int ret; 234 235 if (track > drv->max_track || 236 (head != 0 && (drv->flags & FDISK_DBL_SIDES) == 0)) { 237 FLOPPY_DPRINTF("try to read %d %02x %02x (max=%d %d %02x %02x)\n", 238 head, track, sect, 1, 239 (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1, 240 drv->max_track, drv->last_sect); 241 return 2; 242 } 243 if (sect > drv->last_sect) { 244 FLOPPY_DPRINTF("try to read %d %02x %02x (max=%d %d %02x %02x)\n", 245 head, track, sect, 1, 246 (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1, 247 drv->max_track, drv->last_sect); 248 return 3; 249 } 250 sector = fd_sector_calc(head, track, sect, drv->last_sect, NUM_SIDES(drv)); 251 ret = 0; 252 if (sector != fd_sector(drv)) { 253 #if 0 254 if (!enable_seek) { 255 FLOPPY_DPRINTF("error: no implicit seek %d %02x %02x" 256 " (max=%d %02x %02x)\n", 257 head, track, sect, 1, drv->max_track, 258 drv->last_sect); 259 return 4; 260 } 261 #endif 262 drv->head = head; 263 if (drv->track != track) { 264 if (drv->blk != NULL && blk_is_inserted(drv->blk)) { 265 drv->media_changed = 0; 266 } 267 ret = 1; 268 } 269 drv->track = track; 270 drv->sect = sect; 271 } 272 273 if (drv->blk == NULL || !blk_is_inserted(drv->blk)) { 274 ret = 2; 275 } 276 277 return ret; 278 } 279 280 /* Set drive back to track 0 */ 281 static void fd_recalibrate(FDrive *drv) 282 { 283 FLOPPY_DPRINTF("recalibrate\n"); 284 fd_seek(drv, 0, 0, 1, 1); 285 } 286 287 /* Revalidate a disk drive after a disk change */ 288 static void fd_revalidate(FDrive *drv) 289 { 290 int nb_heads, max_track, last_sect, ro; 291 FDriveType drive; 292 FDriveRate rate; 293 294 FLOPPY_DPRINTF("revalidate\n"); 295 if (drv->blk != NULL) { 296 ro = blk_is_read_only(drv->blk); 297 pick_geometry(drv->blk, &nb_heads, &max_track, 298 &last_sect, drv->drive, &drive, &rate); 299 if (!blk_is_inserted(drv->blk)) { 300 FLOPPY_DPRINTF("No disk in drive\n"); 301 } else { 302 FLOPPY_DPRINTF("Floppy disk (%d h %d t %d s) %s\n", nb_heads, 303 max_track, last_sect, ro ? "ro" : "rw"); 304 } 305 if (nb_heads == 1) { 306 drv->flags &= ~FDISK_DBL_SIDES; 307 } else { 308 drv->flags |= FDISK_DBL_SIDES; 309 } 310 drv->max_track = max_track; 311 drv->last_sect = last_sect; 312 drv->ro = ro; 313 drv->drive = drive; 314 drv->media_rate = rate; 315 } else { 316 FLOPPY_DPRINTF("No drive connected\n"); 317 drv->last_sect = 0; 318 drv->max_track = 0; 319 drv->flags &= ~FDISK_DBL_SIDES; 320 } 321 } 322 323 /********************************************************/ 324 /* Intel 82078 floppy disk controller emulation */ 325 326 static void fdctrl_reset(FDCtrl *fdctrl, int do_irq); 327 static void fdctrl_to_command_phase(FDCtrl *fdctrl); 328 static int fdctrl_transfer_handler (void *opaque, int nchan, 329 int dma_pos, int dma_len); 330 static void fdctrl_raise_irq(FDCtrl *fdctrl); 331 static FDrive *get_cur_drv(FDCtrl *fdctrl); 332 333 static uint32_t fdctrl_read_statusA(FDCtrl *fdctrl); 334 static uint32_t fdctrl_read_statusB(FDCtrl *fdctrl); 335 static uint32_t fdctrl_read_dor(FDCtrl *fdctrl); 336 static void fdctrl_write_dor(FDCtrl *fdctrl, uint32_t value); 337 static uint32_t fdctrl_read_tape(FDCtrl *fdctrl); 338 static void fdctrl_write_tape(FDCtrl *fdctrl, uint32_t value); 339 static uint32_t fdctrl_read_main_status(FDCtrl *fdctrl); 340 static void fdctrl_write_rate(FDCtrl *fdctrl, uint32_t value); 341 static uint32_t fdctrl_read_data(FDCtrl *fdctrl); 342 static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value); 343 static uint32_t fdctrl_read_dir(FDCtrl *fdctrl); 344 static void fdctrl_write_ccr(FDCtrl *fdctrl, uint32_t value); 345 346 enum { 347 FD_DIR_WRITE = 0, 348 FD_DIR_READ = 1, 349 FD_DIR_SCANE = 2, 350 FD_DIR_SCANL = 3, 351 FD_DIR_SCANH = 4, 352 FD_DIR_VERIFY = 5, 353 }; 354 355 enum { 356 FD_STATE_MULTI = 0x01, /* multi track flag */ 357 FD_STATE_FORMAT = 0x02, /* format flag */ 358 }; 359 360 enum { 361 FD_REG_SRA = 0x00, 362 FD_REG_SRB = 0x01, 363 FD_REG_DOR = 0x02, 364 FD_REG_TDR = 0x03, 365 FD_REG_MSR = 0x04, 366 FD_REG_DSR = 0x04, 367 FD_REG_FIFO = 0x05, 368 FD_REG_DIR = 0x07, 369 FD_REG_CCR = 0x07, 370 }; 371 372 enum { 373 FD_CMD_READ_TRACK = 0x02, 374 FD_CMD_SPECIFY = 0x03, 375 FD_CMD_SENSE_DRIVE_STATUS = 0x04, 376 FD_CMD_WRITE = 0x05, 377 FD_CMD_READ = 0x06, 378 FD_CMD_RECALIBRATE = 0x07, 379 FD_CMD_SENSE_INTERRUPT_STATUS = 0x08, 380 FD_CMD_WRITE_DELETED = 0x09, 381 FD_CMD_READ_ID = 0x0a, 382 FD_CMD_READ_DELETED = 0x0c, 383 FD_CMD_FORMAT_TRACK = 0x0d, 384 FD_CMD_DUMPREG = 0x0e, 385 FD_CMD_SEEK = 0x0f, 386 FD_CMD_VERSION = 0x10, 387 FD_CMD_SCAN_EQUAL = 0x11, 388 FD_CMD_PERPENDICULAR_MODE = 0x12, 389 FD_CMD_CONFIGURE = 0x13, 390 FD_CMD_LOCK = 0x14, 391 FD_CMD_VERIFY = 0x16, 392 FD_CMD_POWERDOWN_MODE = 0x17, 393 FD_CMD_PART_ID = 0x18, 394 FD_CMD_SCAN_LOW_OR_EQUAL = 0x19, 395 FD_CMD_SCAN_HIGH_OR_EQUAL = 0x1d, 396 FD_CMD_SAVE = 0x2e, 397 FD_CMD_OPTION = 0x33, 398 FD_CMD_RESTORE = 0x4e, 399 FD_CMD_DRIVE_SPECIFICATION_COMMAND = 0x8e, 400 FD_CMD_RELATIVE_SEEK_OUT = 0x8f, 401 FD_CMD_FORMAT_AND_WRITE = 0xcd, 402 FD_CMD_RELATIVE_SEEK_IN = 0xcf, 403 }; 404 405 enum { 406 FD_CONFIG_PRETRK = 0xff, /* Pre-compensation set to track 0 */ 407 FD_CONFIG_FIFOTHR = 0x0f, /* FIFO threshold set to 1 byte */ 408 FD_CONFIG_POLL = 0x10, /* Poll enabled */ 409 FD_CONFIG_EFIFO = 0x20, /* FIFO disabled */ 410 FD_CONFIG_EIS = 0x40, /* No implied seeks */ 411 }; 412 413 enum { 414 FD_SR0_DS0 = 0x01, 415 FD_SR0_DS1 = 0x02, 416 FD_SR0_HEAD = 0x04, 417 FD_SR0_EQPMT = 0x10, 418 FD_SR0_SEEK = 0x20, 419 FD_SR0_ABNTERM = 0x40, 420 FD_SR0_INVCMD = 0x80, 421 FD_SR0_RDYCHG = 0xc0, 422 }; 423 424 enum { 425 FD_SR1_MA = 0x01, /* Missing address mark */ 426 FD_SR1_NW = 0x02, /* Not writable */ 427 FD_SR1_EC = 0x80, /* End of cylinder */ 428 }; 429 430 enum { 431 FD_SR2_SNS = 0x04, /* Scan not satisfied */ 432 FD_SR2_SEH = 0x08, /* Scan equal hit */ 433 }; 434 435 enum { 436 FD_SRA_DIR = 0x01, 437 FD_SRA_nWP = 0x02, 438 FD_SRA_nINDX = 0x04, 439 FD_SRA_HDSEL = 0x08, 440 FD_SRA_nTRK0 = 0x10, 441 FD_SRA_STEP = 0x20, 442 FD_SRA_nDRV2 = 0x40, 443 FD_SRA_INTPEND = 0x80, 444 }; 445 446 enum { 447 FD_SRB_MTR0 = 0x01, 448 FD_SRB_MTR1 = 0x02, 449 FD_SRB_WGATE = 0x04, 450 FD_SRB_RDATA = 0x08, 451 FD_SRB_WDATA = 0x10, 452 FD_SRB_DR0 = 0x20, 453 }; 454 455 enum { 456 #if MAX_FD == 4 457 FD_DOR_SELMASK = 0x03, 458 #else 459 FD_DOR_SELMASK = 0x01, 460 #endif 461 FD_DOR_nRESET = 0x04, 462 FD_DOR_DMAEN = 0x08, 463 FD_DOR_MOTEN0 = 0x10, 464 FD_DOR_MOTEN1 = 0x20, 465 FD_DOR_MOTEN2 = 0x40, 466 FD_DOR_MOTEN3 = 0x80, 467 }; 468 469 enum { 470 #if MAX_FD == 4 471 FD_TDR_BOOTSEL = 0x0c, 472 #else 473 FD_TDR_BOOTSEL = 0x04, 474 #endif 475 }; 476 477 enum { 478 FD_DSR_DRATEMASK= 0x03, 479 FD_DSR_PWRDOWN = 0x40, 480 FD_DSR_SWRESET = 0x80, 481 }; 482 483 enum { 484 FD_MSR_DRV0BUSY = 0x01, 485 FD_MSR_DRV1BUSY = 0x02, 486 FD_MSR_DRV2BUSY = 0x04, 487 FD_MSR_DRV3BUSY = 0x08, 488 FD_MSR_CMDBUSY = 0x10, 489 FD_MSR_NONDMA = 0x20, 490 FD_MSR_DIO = 0x40, 491 FD_MSR_RQM = 0x80, 492 }; 493 494 enum { 495 FD_DIR_DSKCHG = 0x80, 496 }; 497 498 /* 499 * See chapter 5.0 "Controller phases" of the spec: 500 * 501 * Command phase: 502 * The host writes a command and its parameters into the FIFO. The command 503 * phase is completed when all parameters for the command have been supplied, 504 * and execution phase is entered. 505 * 506 * Execution phase: 507 * Data transfers, either DMA or non-DMA. For non-DMA transfers, the FIFO 508 * contains the payload now, otherwise it's unused. When all bytes of the 509 * required data have been transferred, the state is switched to either result 510 * phase (if the command produces status bytes) or directly back into the 511 * command phase for the next command. 512 * 513 * Result phase: 514 * The host reads out the FIFO, which contains one or more result bytes now. 515 */ 516 enum { 517 /* Only for migration: reconstruct phase from registers like qemu 2.3 */ 518 FD_PHASE_RECONSTRUCT = 0, 519 520 FD_PHASE_COMMAND = 1, 521 FD_PHASE_EXECUTION = 2, 522 FD_PHASE_RESULT = 3, 523 }; 524 525 #define FD_MULTI_TRACK(state) ((state) & FD_STATE_MULTI) 526 #define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT) 527 528 struct FDCtrl { 529 MemoryRegion iomem; 530 qemu_irq irq; 531 /* Controller state */ 532 QEMUTimer *result_timer; 533 int dma_chann; 534 uint8_t phase; 535 /* Controller's identification */ 536 uint8_t version; 537 /* HW */ 538 uint8_t sra; 539 uint8_t srb; 540 uint8_t dor; 541 uint8_t dor_vmstate; /* only used as temp during vmstate */ 542 uint8_t tdr; 543 uint8_t dsr; 544 uint8_t msr; 545 uint8_t cur_drv; 546 uint8_t status0; 547 uint8_t status1; 548 uint8_t status2; 549 /* Command FIFO */ 550 uint8_t *fifo; 551 int32_t fifo_size; 552 uint32_t data_pos; 553 uint32_t data_len; 554 uint8_t data_state; 555 uint8_t data_dir; 556 uint8_t eot; /* last wanted sector */ 557 /* States kept only to be returned back */ 558 /* precompensation */ 559 uint8_t precomp_trk; 560 uint8_t config; 561 uint8_t lock; 562 /* Power down config (also with status regB access mode */ 563 uint8_t pwrd; 564 /* Floppy drives */ 565 uint8_t num_floppies; 566 FDrive drives[MAX_FD]; 567 int reset_sensei; 568 uint32_t check_media_rate; 569 /* Timers state */ 570 uint8_t timer0; 571 uint8_t timer1; 572 }; 573 574 #define TYPE_SYSBUS_FDC "base-sysbus-fdc" 575 #define SYSBUS_FDC(obj) OBJECT_CHECK(FDCtrlSysBus, (obj), TYPE_SYSBUS_FDC) 576 577 typedef struct FDCtrlSysBus { 578 /*< private >*/ 579 SysBusDevice parent_obj; 580 /*< public >*/ 581 582 struct FDCtrl state; 583 } FDCtrlSysBus; 584 585 #define ISA_FDC(obj) OBJECT_CHECK(FDCtrlISABus, (obj), TYPE_ISA_FDC) 586 587 typedef struct FDCtrlISABus { 588 ISADevice parent_obj; 589 590 uint32_t iobase; 591 uint32_t irq; 592 uint32_t dma; 593 struct FDCtrl state; 594 int32_t bootindexA; 595 int32_t bootindexB; 596 } FDCtrlISABus; 597 598 static uint32_t fdctrl_read (void *opaque, uint32_t reg) 599 { 600 FDCtrl *fdctrl = opaque; 601 uint32_t retval; 602 603 reg &= 7; 604 switch (reg) { 605 case FD_REG_SRA: 606 retval = fdctrl_read_statusA(fdctrl); 607 break; 608 case FD_REG_SRB: 609 retval = fdctrl_read_statusB(fdctrl); 610 break; 611 case FD_REG_DOR: 612 retval = fdctrl_read_dor(fdctrl); 613 break; 614 case FD_REG_TDR: 615 retval = fdctrl_read_tape(fdctrl); 616 break; 617 case FD_REG_MSR: 618 retval = fdctrl_read_main_status(fdctrl); 619 break; 620 case FD_REG_FIFO: 621 retval = fdctrl_read_data(fdctrl); 622 break; 623 case FD_REG_DIR: 624 retval = fdctrl_read_dir(fdctrl); 625 break; 626 default: 627 retval = (uint32_t)(-1); 628 break; 629 } 630 FLOPPY_DPRINTF("read reg%d: 0x%02x\n", reg & 7, retval); 631 632 return retval; 633 } 634 635 static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value) 636 { 637 FDCtrl *fdctrl = opaque; 638 639 FLOPPY_DPRINTF("write reg%d: 0x%02x\n", reg & 7, value); 640 641 reg &= 7; 642 switch (reg) { 643 case FD_REG_DOR: 644 fdctrl_write_dor(fdctrl, value); 645 break; 646 case FD_REG_TDR: 647 fdctrl_write_tape(fdctrl, value); 648 break; 649 case FD_REG_DSR: 650 fdctrl_write_rate(fdctrl, value); 651 break; 652 case FD_REG_FIFO: 653 fdctrl_write_data(fdctrl, value); 654 break; 655 case FD_REG_CCR: 656 fdctrl_write_ccr(fdctrl, value); 657 break; 658 default: 659 break; 660 } 661 } 662 663 static uint64_t fdctrl_read_mem (void *opaque, hwaddr reg, 664 unsigned ize) 665 { 666 return fdctrl_read(opaque, (uint32_t)reg); 667 } 668 669 static void fdctrl_write_mem (void *opaque, hwaddr reg, 670 uint64_t value, unsigned size) 671 { 672 fdctrl_write(opaque, (uint32_t)reg, value); 673 } 674 675 static const MemoryRegionOps fdctrl_mem_ops = { 676 .read = fdctrl_read_mem, 677 .write = fdctrl_write_mem, 678 .endianness = DEVICE_NATIVE_ENDIAN, 679 }; 680 681 static const MemoryRegionOps fdctrl_mem_strict_ops = { 682 .read = fdctrl_read_mem, 683 .write = fdctrl_write_mem, 684 .endianness = DEVICE_NATIVE_ENDIAN, 685 .valid = { 686 .min_access_size = 1, 687 .max_access_size = 1, 688 }, 689 }; 690 691 static bool fdrive_media_changed_needed(void *opaque) 692 { 693 FDrive *drive = opaque; 694 695 return (drive->blk != NULL && drive->media_changed != 1); 696 } 697 698 static const VMStateDescription vmstate_fdrive_media_changed = { 699 .name = "fdrive/media_changed", 700 .version_id = 1, 701 .minimum_version_id = 1, 702 .fields = (VMStateField[]) { 703 VMSTATE_UINT8(media_changed, FDrive), 704 VMSTATE_END_OF_LIST() 705 } 706 }; 707 708 static bool fdrive_media_rate_needed(void *opaque) 709 { 710 FDrive *drive = opaque; 711 712 return drive->fdctrl->check_media_rate; 713 } 714 715 static const VMStateDescription vmstate_fdrive_media_rate = { 716 .name = "fdrive/media_rate", 717 .version_id = 1, 718 .minimum_version_id = 1, 719 .fields = (VMStateField[]) { 720 VMSTATE_UINT8(media_rate, FDrive), 721 VMSTATE_END_OF_LIST() 722 } 723 }; 724 725 static bool fdrive_perpendicular_needed(void *opaque) 726 { 727 FDrive *drive = opaque; 728 729 return drive->perpendicular != 0; 730 } 731 732 static const VMStateDescription vmstate_fdrive_perpendicular = { 733 .name = "fdrive/perpendicular", 734 .version_id = 1, 735 .minimum_version_id = 1, 736 .fields = (VMStateField[]) { 737 VMSTATE_UINT8(perpendicular, FDrive), 738 VMSTATE_END_OF_LIST() 739 } 740 }; 741 742 static int fdrive_post_load(void *opaque, int version_id) 743 { 744 fd_revalidate(opaque); 745 return 0; 746 } 747 748 static const VMStateDescription vmstate_fdrive = { 749 .name = "fdrive", 750 .version_id = 1, 751 .minimum_version_id = 1, 752 .post_load = fdrive_post_load, 753 .fields = (VMStateField[]) { 754 VMSTATE_UINT8(head, FDrive), 755 VMSTATE_UINT8(track, FDrive), 756 VMSTATE_UINT8(sect, FDrive), 757 VMSTATE_END_OF_LIST() 758 }, 759 .subsections = (VMStateSubsection[]) { 760 { 761 .vmsd = &vmstate_fdrive_media_changed, 762 .needed = &fdrive_media_changed_needed, 763 } , { 764 .vmsd = &vmstate_fdrive_media_rate, 765 .needed = &fdrive_media_rate_needed, 766 } , { 767 .vmsd = &vmstate_fdrive_perpendicular, 768 .needed = &fdrive_perpendicular_needed, 769 } , { 770 /* empty */ 771 } 772 } 773 }; 774 775 /* 776 * Reconstructs the phase from register values according to the logic that was 777 * implemented in qemu 2.3. This is the default value that is used if the phase 778 * subsection is not present on migration. 779 * 780 * Don't change this function to reflect newer qemu versions, it is part of 781 * the migration ABI. 782 */ 783 static int reconstruct_phase(FDCtrl *fdctrl) 784 { 785 if (fdctrl->msr & FD_MSR_NONDMA) { 786 return FD_PHASE_EXECUTION; 787 } else if ((fdctrl->msr & FD_MSR_RQM) == 0) { 788 /* qemu 2.3 disabled RQM only during DMA transfers */ 789 return FD_PHASE_EXECUTION; 790 } else if (fdctrl->msr & FD_MSR_DIO) { 791 return FD_PHASE_RESULT; 792 } else { 793 return FD_PHASE_COMMAND; 794 } 795 } 796 797 static void fdc_pre_save(void *opaque) 798 { 799 FDCtrl *s = opaque; 800 801 s->dor_vmstate = s->dor | GET_CUR_DRV(s); 802 } 803 804 static int fdc_pre_load(void *opaque) 805 { 806 FDCtrl *s = opaque; 807 s->phase = FD_PHASE_RECONSTRUCT; 808 return 0; 809 } 810 811 static int fdc_post_load(void *opaque, int version_id) 812 { 813 FDCtrl *s = opaque; 814 815 SET_CUR_DRV(s, s->dor_vmstate & FD_DOR_SELMASK); 816 s->dor = s->dor_vmstate & ~FD_DOR_SELMASK; 817 818 if (s->phase == FD_PHASE_RECONSTRUCT) { 819 s->phase = reconstruct_phase(s); 820 } 821 822 return 0; 823 } 824 825 static bool fdc_reset_sensei_needed(void *opaque) 826 { 827 FDCtrl *s = opaque; 828 829 return s->reset_sensei != 0; 830 } 831 832 static const VMStateDescription vmstate_fdc_reset_sensei = { 833 .name = "fdc/reset_sensei", 834 .version_id = 1, 835 .minimum_version_id = 1, 836 .fields = (VMStateField[]) { 837 VMSTATE_INT32(reset_sensei, FDCtrl), 838 VMSTATE_END_OF_LIST() 839 } 840 }; 841 842 static bool fdc_result_timer_needed(void *opaque) 843 { 844 FDCtrl *s = opaque; 845 846 return timer_pending(s->result_timer); 847 } 848 849 static const VMStateDescription vmstate_fdc_result_timer = { 850 .name = "fdc/result_timer", 851 .version_id = 1, 852 .minimum_version_id = 1, 853 .fields = (VMStateField[]) { 854 VMSTATE_TIMER_PTR(result_timer, FDCtrl), 855 VMSTATE_END_OF_LIST() 856 } 857 }; 858 859 static bool fdc_phase_needed(void *opaque) 860 { 861 FDCtrl *fdctrl = opaque; 862 863 return reconstruct_phase(fdctrl) != fdctrl->phase; 864 } 865 866 static const VMStateDescription vmstate_fdc_phase = { 867 .name = "fdc/phase", 868 .version_id = 1, 869 .minimum_version_id = 1, 870 .fields = (VMStateField[]) { 871 VMSTATE_UINT8(phase, FDCtrl), 872 VMSTATE_END_OF_LIST() 873 } 874 }; 875 876 static const VMStateDescription vmstate_fdc = { 877 .name = "fdc", 878 .version_id = 2, 879 .minimum_version_id = 2, 880 .pre_save = fdc_pre_save, 881 .pre_load = fdc_pre_load, 882 .post_load = fdc_post_load, 883 .fields = (VMStateField[]) { 884 /* Controller State */ 885 VMSTATE_UINT8(sra, FDCtrl), 886 VMSTATE_UINT8(srb, FDCtrl), 887 VMSTATE_UINT8(dor_vmstate, FDCtrl), 888 VMSTATE_UINT8(tdr, FDCtrl), 889 VMSTATE_UINT8(dsr, FDCtrl), 890 VMSTATE_UINT8(msr, FDCtrl), 891 VMSTATE_UINT8(status0, FDCtrl), 892 VMSTATE_UINT8(status1, FDCtrl), 893 VMSTATE_UINT8(status2, FDCtrl), 894 /* Command FIFO */ 895 VMSTATE_VARRAY_INT32(fifo, FDCtrl, fifo_size, 0, vmstate_info_uint8, 896 uint8_t), 897 VMSTATE_UINT32(data_pos, FDCtrl), 898 VMSTATE_UINT32(data_len, FDCtrl), 899 VMSTATE_UINT8(data_state, FDCtrl), 900 VMSTATE_UINT8(data_dir, FDCtrl), 901 VMSTATE_UINT8(eot, FDCtrl), 902 /* States kept only to be returned back */ 903 VMSTATE_UINT8(timer0, FDCtrl), 904 VMSTATE_UINT8(timer1, FDCtrl), 905 VMSTATE_UINT8(precomp_trk, FDCtrl), 906 VMSTATE_UINT8(config, FDCtrl), 907 VMSTATE_UINT8(lock, FDCtrl), 908 VMSTATE_UINT8(pwrd, FDCtrl), 909 VMSTATE_UINT8_EQUAL(num_floppies, FDCtrl), 910 VMSTATE_STRUCT_ARRAY(drives, FDCtrl, MAX_FD, 1, 911 vmstate_fdrive, FDrive), 912 VMSTATE_END_OF_LIST() 913 }, 914 .subsections = (VMStateSubsection[]) { 915 { 916 .vmsd = &vmstate_fdc_reset_sensei, 917 .needed = fdc_reset_sensei_needed, 918 } , { 919 .vmsd = &vmstate_fdc_result_timer, 920 .needed = fdc_result_timer_needed, 921 } , { 922 .vmsd = &vmstate_fdc_phase, 923 .needed = fdc_phase_needed, 924 } , { 925 /* empty */ 926 } 927 } 928 }; 929 930 static void fdctrl_external_reset_sysbus(DeviceState *d) 931 { 932 FDCtrlSysBus *sys = SYSBUS_FDC(d); 933 FDCtrl *s = &sys->state; 934 935 fdctrl_reset(s, 0); 936 } 937 938 static void fdctrl_external_reset_isa(DeviceState *d) 939 { 940 FDCtrlISABus *isa = ISA_FDC(d); 941 FDCtrl *s = &isa->state; 942 943 fdctrl_reset(s, 0); 944 } 945 946 static void fdctrl_handle_tc(void *opaque, int irq, int level) 947 { 948 //FDCtrl *s = opaque; 949 950 if (level) { 951 // XXX 952 FLOPPY_DPRINTF("TC pulsed\n"); 953 } 954 } 955 956 /* Change IRQ state */ 957 static void fdctrl_reset_irq(FDCtrl *fdctrl) 958 { 959 fdctrl->status0 = 0; 960 if (!(fdctrl->sra & FD_SRA_INTPEND)) 961 return; 962 FLOPPY_DPRINTF("Reset interrupt\n"); 963 qemu_set_irq(fdctrl->irq, 0); 964 fdctrl->sra &= ~FD_SRA_INTPEND; 965 } 966 967 static void fdctrl_raise_irq(FDCtrl *fdctrl) 968 { 969 if (!(fdctrl->sra & FD_SRA_INTPEND)) { 970 qemu_set_irq(fdctrl->irq, 1); 971 fdctrl->sra |= FD_SRA_INTPEND; 972 } 973 974 fdctrl->reset_sensei = 0; 975 FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", fdctrl->status0); 976 } 977 978 /* Reset controller */ 979 static void fdctrl_reset(FDCtrl *fdctrl, int do_irq) 980 { 981 int i; 982 983 FLOPPY_DPRINTF("reset controller\n"); 984 fdctrl_reset_irq(fdctrl); 985 /* Initialise controller */ 986 fdctrl->sra = 0; 987 fdctrl->srb = 0xc0; 988 if (!fdctrl->drives[1].blk) { 989 fdctrl->sra |= FD_SRA_nDRV2; 990 } 991 fdctrl->cur_drv = 0; 992 fdctrl->dor = FD_DOR_nRESET; 993 fdctrl->dor |= (fdctrl->dma_chann != -1) ? FD_DOR_DMAEN : 0; 994 fdctrl->msr = FD_MSR_RQM; 995 fdctrl->reset_sensei = 0; 996 timer_del(fdctrl->result_timer); 997 /* FIFO state */ 998 fdctrl->data_pos = 0; 999 fdctrl->data_len = 0; 1000 fdctrl->data_state = 0; 1001 fdctrl->data_dir = FD_DIR_WRITE; 1002 for (i = 0; i < MAX_FD; i++) 1003 fd_recalibrate(&fdctrl->drives[i]); 1004 fdctrl_to_command_phase(fdctrl); 1005 if (do_irq) { 1006 fdctrl->status0 |= FD_SR0_RDYCHG; 1007 fdctrl_raise_irq(fdctrl); 1008 fdctrl->reset_sensei = FD_RESET_SENSEI_COUNT; 1009 } 1010 } 1011 1012 static inline FDrive *drv0(FDCtrl *fdctrl) 1013 { 1014 return &fdctrl->drives[(fdctrl->tdr & FD_TDR_BOOTSEL) >> 2]; 1015 } 1016 1017 static inline FDrive *drv1(FDCtrl *fdctrl) 1018 { 1019 if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (1 << 2)) 1020 return &fdctrl->drives[1]; 1021 else 1022 return &fdctrl->drives[0]; 1023 } 1024 1025 #if MAX_FD == 4 1026 static inline FDrive *drv2(FDCtrl *fdctrl) 1027 { 1028 if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (2 << 2)) 1029 return &fdctrl->drives[2]; 1030 else 1031 return &fdctrl->drives[1]; 1032 } 1033 1034 static inline FDrive *drv3(FDCtrl *fdctrl) 1035 { 1036 if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (3 << 2)) 1037 return &fdctrl->drives[3]; 1038 else 1039 return &fdctrl->drives[2]; 1040 } 1041 #endif 1042 1043 static FDrive *get_cur_drv(FDCtrl *fdctrl) 1044 { 1045 switch (fdctrl->cur_drv) { 1046 case 0: return drv0(fdctrl); 1047 case 1: return drv1(fdctrl); 1048 #if MAX_FD == 4 1049 case 2: return drv2(fdctrl); 1050 case 3: return drv3(fdctrl); 1051 #endif 1052 default: return NULL; 1053 } 1054 } 1055 1056 /* Status A register : 0x00 (read-only) */ 1057 static uint32_t fdctrl_read_statusA(FDCtrl *fdctrl) 1058 { 1059 uint32_t retval = fdctrl->sra; 1060 1061 FLOPPY_DPRINTF("status register A: 0x%02x\n", retval); 1062 1063 return retval; 1064 } 1065 1066 /* Status B register : 0x01 (read-only) */ 1067 static uint32_t fdctrl_read_statusB(FDCtrl *fdctrl) 1068 { 1069 uint32_t retval = fdctrl->srb; 1070 1071 FLOPPY_DPRINTF("status register B: 0x%02x\n", retval); 1072 1073 return retval; 1074 } 1075 1076 /* Digital output register : 0x02 */ 1077 static uint32_t fdctrl_read_dor(FDCtrl *fdctrl) 1078 { 1079 uint32_t retval = fdctrl->dor; 1080 1081 /* Selected drive */ 1082 retval |= fdctrl->cur_drv; 1083 FLOPPY_DPRINTF("digital output register: 0x%02x\n", retval); 1084 1085 return retval; 1086 } 1087 1088 static void fdctrl_write_dor(FDCtrl *fdctrl, uint32_t value) 1089 { 1090 FLOPPY_DPRINTF("digital output register set to 0x%02x\n", value); 1091 1092 /* Motors */ 1093 if (value & FD_DOR_MOTEN0) 1094 fdctrl->srb |= FD_SRB_MTR0; 1095 else 1096 fdctrl->srb &= ~FD_SRB_MTR0; 1097 if (value & FD_DOR_MOTEN1) 1098 fdctrl->srb |= FD_SRB_MTR1; 1099 else 1100 fdctrl->srb &= ~FD_SRB_MTR1; 1101 1102 /* Drive */ 1103 if (value & 1) 1104 fdctrl->srb |= FD_SRB_DR0; 1105 else 1106 fdctrl->srb &= ~FD_SRB_DR0; 1107 1108 /* Reset */ 1109 if (!(value & FD_DOR_nRESET)) { 1110 if (fdctrl->dor & FD_DOR_nRESET) { 1111 FLOPPY_DPRINTF("controller enter RESET state\n"); 1112 } 1113 } else { 1114 if (!(fdctrl->dor & FD_DOR_nRESET)) { 1115 FLOPPY_DPRINTF("controller out of RESET state\n"); 1116 fdctrl_reset(fdctrl, 1); 1117 fdctrl->dsr &= ~FD_DSR_PWRDOWN; 1118 } 1119 } 1120 /* Selected drive */ 1121 fdctrl->cur_drv = value & FD_DOR_SELMASK; 1122 1123 fdctrl->dor = value; 1124 } 1125 1126 /* Tape drive register : 0x03 */ 1127 static uint32_t fdctrl_read_tape(FDCtrl *fdctrl) 1128 { 1129 uint32_t retval = fdctrl->tdr; 1130 1131 FLOPPY_DPRINTF("tape drive register: 0x%02x\n", retval); 1132 1133 return retval; 1134 } 1135 1136 static void fdctrl_write_tape(FDCtrl *fdctrl, uint32_t value) 1137 { 1138 /* Reset mode */ 1139 if (!(fdctrl->dor & FD_DOR_nRESET)) { 1140 FLOPPY_DPRINTF("Floppy controller in RESET state !\n"); 1141 return; 1142 } 1143 FLOPPY_DPRINTF("tape drive register set to 0x%02x\n", value); 1144 /* Disk boot selection indicator */ 1145 fdctrl->tdr = value & FD_TDR_BOOTSEL; 1146 /* Tape indicators: never allow */ 1147 } 1148 1149 /* Main status register : 0x04 (read) */ 1150 static uint32_t fdctrl_read_main_status(FDCtrl *fdctrl) 1151 { 1152 uint32_t retval = fdctrl->msr; 1153 1154 fdctrl->dsr &= ~FD_DSR_PWRDOWN; 1155 fdctrl->dor |= FD_DOR_nRESET; 1156 1157 FLOPPY_DPRINTF("main status register: 0x%02x\n", retval); 1158 1159 return retval; 1160 } 1161 1162 /* Data select rate register : 0x04 (write) */ 1163 static void fdctrl_write_rate(FDCtrl *fdctrl, uint32_t value) 1164 { 1165 /* Reset mode */ 1166 if (!(fdctrl->dor & FD_DOR_nRESET)) { 1167 FLOPPY_DPRINTF("Floppy controller in RESET state !\n"); 1168 return; 1169 } 1170 FLOPPY_DPRINTF("select rate register set to 0x%02x\n", value); 1171 /* Reset: autoclear */ 1172 if (value & FD_DSR_SWRESET) { 1173 fdctrl->dor &= ~FD_DOR_nRESET; 1174 fdctrl_reset(fdctrl, 1); 1175 fdctrl->dor |= FD_DOR_nRESET; 1176 } 1177 if (value & FD_DSR_PWRDOWN) { 1178 fdctrl_reset(fdctrl, 1); 1179 } 1180 fdctrl->dsr = value; 1181 } 1182 1183 /* Configuration control register: 0x07 (write) */ 1184 static void fdctrl_write_ccr(FDCtrl *fdctrl, uint32_t value) 1185 { 1186 /* Reset mode */ 1187 if (!(fdctrl->dor & FD_DOR_nRESET)) { 1188 FLOPPY_DPRINTF("Floppy controller in RESET state !\n"); 1189 return; 1190 } 1191 FLOPPY_DPRINTF("configuration control register set to 0x%02x\n", value); 1192 1193 /* Only the rate selection bits used in AT mode, and we 1194 * store those in the DSR. 1195 */ 1196 fdctrl->dsr = (fdctrl->dsr & ~FD_DSR_DRATEMASK) | 1197 (value & FD_DSR_DRATEMASK); 1198 } 1199 1200 static int fdctrl_media_changed(FDrive *drv) 1201 { 1202 return drv->media_changed; 1203 } 1204 1205 /* Digital input register : 0x07 (read-only) */ 1206 static uint32_t fdctrl_read_dir(FDCtrl *fdctrl) 1207 { 1208 uint32_t retval = 0; 1209 1210 if (fdctrl_media_changed(get_cur_drv(fdctrl))) { 1211 retval |= FD_DIR_DSKCHG; 1212 } 1213 if (retval != 0) { 1214 FLOPPY_DPRINTF("Floppy digital input register: 0x%02x\n", retval); 1215 } 1216 1217 return retval; 1218 } 1219 1220 /* Clear the FIFO and update the state for receiving the next command */ 1221 static void fdctrl_to_command_phase(FDCtrl *fdctrl) 1222 { 1223 fdctrl->phase = FD_PHASE_COMMAND; 1224 fdctrl->data_dir = FD_DIR_WRITE; 1225 fdctrl->data_pos = 0; 1226 fdctrl->data_len = 1; /* Accept command byte, adjust for params later */ 1227 fdctrl->msr &= ~(FD_MSR_CMDBUSY | FD_MSR_DIO); 1228 fdctrl->msr |= FD_MSR_RQM; 1229 } 1230 1231 /* Update the state to allow the guest to read out the command status. 1232 * @fifo_len is the number of result bytes to be read out. */ 1233 static void fdctrl_to_result_phase(FDCtrl *fdctrl, int fifo_len) 1234 { 1235 fdctrl->phase = FD_PHASE_RESULT; 1236 fdctrl->data_dir = FD_DIR_READ; 1237 fdctrl->data_len = fifo_len; 1238 fdctrl->data_pos = 0; 1239 fdctrl->msr |= FD_MSR_CMDBUSY | FD_MSR_RQM | FD_MSR_DIO; 1240 } 1241 1242 /* Set an error: unimplemented/unknown command */ 1243 static void fdctrl_unimplemented(FDCtrl *fdctrl, int direction) 1244 { 1245 qemu_log_mask(LOG_UNIMP, "fdc: unimplemented command 0x%02x\n", 1246 fdctrl->fifo[0]); 1247 fdctrl->fifo[0] = FD_SR0_INVCMD; 1248 fdctrl_to_result_phase(fdctrl, 1); 1249 } 1250 1251 /* Seek to next sector 1252 * returns 0 when end of track reached (for DBL_SIDES on head 1) 1253 * otherwise returns 1 1254 */ 1255 static int fdctrl_seek_to_next_sect(FDCtrl *fdctrl, FDrive *cur_drv) 1256 { 1257 FLOPPY_DPRINTF("seek to next sector (%d %02x %02x => %d)\n", 1258 cur_drv->head, cur_drv->track, cur_drv->sect, 1259 fd_sector(cur_drv)); 1260 /* XXX: cur_drv->sect >= cur_drv->last_sect should be an 1261 error in fact */ 1262 uint8_t new_head = cur_drv->head; 1263 uint8_t new_track = cur_drv->track; 1264 uint8_t new_sect = cur_drv->sect; 1265 1266 int ret = 1; 1267 1268 if (new_sect >= cur_drv->last_sect || 1269 new_sect == fdctrl->eot) { 1270 new_sect = 1; 1271 if (FD_MULTI_TRACK(fdctrl->data_state)) { 1272 if (new_head == 0 && 1273 (cur_drv->flags & FDISK_DBL_SIDES) != 0) { 1274 new_head = 1; 1275 } else { 1276 new_head = 0; 1277 new_track++; 1278 fdctrl->status0 |= FD_SR0_SEEK; 1279 if ((cur_drv->flags & FDISK_DBL_SIDES) == 0) { 1280 ret = 0; 1281 } 1282 } 1283 } else { 1284 fdctrl->status0 |= FD_SR0_SEEK; 1285 new_track++; 1286 ret = 0; 1287 } 1288 if (ret == 1) { 1289 FLOPPY_DPRINTF("seek to next track (%d %02x %02x => %d)\n", 1290 new_head, new_track, new_sect, fd_sector(cur_drv)); 1291 } 1292 } else { 1293 new_sect++; 1294 } 1295 fd_seek(cur_drv, new_head, new_track, new_sect, 1); 1296 return ret; 1297 } 1298 1299 /* Callback for transfer end (stop or abort) */ 1300 static void fdctrl_stop_transfer(FDCtrl *fdctrl, uint8_t status0, 1301 uint8_t status1, uint8_t status2) 1302 { 1303 FDrive *cur_drv; 1304 cur_drv = get_cur_drv(fdctrl); 1305 1306 fdctrl->status0 &= ~(FD_SR0_DS0 | FD_SR0_DS1 | FD_SR0_HEAD); 1307 fdctrl->status0 |= GET_CUR_DRV(fdctrl); 1308 if (cur_drv->head) { 1309 fdctrl->status0 |= FD_SR0_HEAD; 1310 } 1311 fdctrl->status0 |= status0; 1312 1313 FLOPPY_DPRINTF("transfer status: %02x %02x %02x (%02x)\n", 1314 status0, status1, status2, fdctrl->status0); 1315 fdctrl->fifo[0] = fdctrl->status0; 1316 fdctrl->fifo[1] = status1; 1317 fdctrl->fifo[2] = status2; 1318 fdctrl->fifo[3] = cur_drv->track; 1319 fdctrl->fifo[4] = cur_drv->head; 1320 fdctrl->fifo[5] = cur_drv->sect; 1321 fdctrl->fifo[6] = FD_SECTOR_SC; 1322 fdctrl->data_dir = FD_DIR_READ; 1323 if (!(fdctrl->msr & FD_MSR_NONDMA)) { 1324 DMA_release_DREQ(fdctrl->dma_chann); 1325 } 1326 fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO; 1327 fdctrl->msr &= ~FD_MSR_NONDMA; 1328 1329 fdctrl_to_result_phase(fdctrl, 7); 1330 fdctrl_raise_irq(fdctrl); 1331 } 1332 1333 /* Prepare a data transfer (either DMA or FIFO) */ 1334 static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction) 1335 { 1336 FDrive *cur_drv; 1337 uint8_t kh, kt, ks; 1338 1339 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); 1340 cur_drv = get_cur_drv(fdctrl); 1341 kt = fdctrl->fifo[2]; 1342 kh = fdctrl->fifo[3]; 1343 ks = fdctrl->fifo[4]; 1344 FLOPPY_DPRINTF("Start transfer at %d %d %02x %02x (%d)\n", 1345 GET_CUR_DRV(fdctrl), kh, kt, ks, 1346 fd_sector_calc(kh, kt, ks, cur_drv->last_sect, 1347 NUM_SIDES(cur_drv))); 1348 switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & FD_CONFIG_EIS)) { 1349 case 2: 1350 /* sect too big */ 1351 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00); 1352 fdctrl->fifo[3] = kt; 1353 fdctrl->fifo[4] = kh; 1354 fdctrl->fifo[5] = ks; 1355 return; 1356 case 3: 1357 /* track too big */ 1358 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_EC, 0x00); 1359 fdctrl->fifo[3] = kt; 1360 fdctrl->fifo[4] = kh; 1361 fdctrl->fifo[5] = ks; 1362 return; 1363 case 4: 1364 /* No seek enabled */ 1365 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00); 1366 fdctrl->fifo[3] = kt; 1367 fdctrl->fifo[4] = kh; 1368 fdctrl->fifo[5] = ks; 1369 return; 1370 case 1: 1371 fdctrl->status0 |= FD_SR0_SEEK; 1372 break; 1373 default: 1374 break; 1375 } 1376 1377 /* Check the data rate. If the programmed data rate does not match 1378 * the currently inserted medium, the operation has to fail. */ 1379 if (fdctrl->check_media_rate && 1380 (fdctrl->dsr & FD_DSR_DRATEMASK) != cur_drv->media_rate) { 1381 FLOPPY_DPRINTF("data rate mismatch (fdc=%d, media=%d)\n", 1382 fdctrl->dsr & FD_DSR_DRATEMASK, cur_drv->media_rate); 1383 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA, 0x00); 1384 fdctrl->fifo[3] = kt; 1385 fdctrl->fifo[4] = kh; 1386 fdctrl->fifo[5] = ks; 1387 return; 1388 } 1389 1390 /* Set the FIFO state */ 1391 fdctrl->data_dir = direction; 1392 fdctrl->data_pos = 0; 1393 assert(fdctrl->msr & FD_MSR_CMDBUSY); 1394 if (fdctrl->fifo[0] & 0x80) 1395 fdctrl->data_state |= FD_STATE_MULTI; 1396 else 1397 fdctrl->data_state &= ~FD_STATE_MULTI; 1398 if (fdctrl->fifo[5] == 0) { 1399 fdctrl->data_len = fdctrl->fifo[8]; 1400 } else { 1401 int tmp; 1402 fdctrl->data_len = 128 << (fdctrl->fifo[5] > 7 ? 7 : fdctrl->fifo[5]); 1403 tmp = (fdctrl->fifo[6] - ks + 1); 1404 if (fdctrl->fifo[0] & 0x80) 1405 tmp += fdctrl->fifo[6]; 1406 fdctrl->data_len *= tmp; 1407 } 1408 fdctrl->eot = fdctrl->fifo[6]; 1409 if (fdctrl->dor & FD_DOR_DMAEN) { 1410 int dma_mode; 1411 /* DMA transfer are enabled. Check if DMA channel is well programmed */ 1412 dma_mode = DMA_get_channel_mode(fdctrl->dma_chann); 1413 dma_mode = (dma_mode >> 2) & 3; 1414 FLOPPY_DPRINTF("dma_mode=%d direction=%d (%d - %d)\n", 1415 dma_mode, direction, 1416 (128 << fdctrl->fifo[5]) * 1417 (cur_drv->last_sect - ks + 1), fdctrl->data_len); 1418 if (((direction == FD_DIR_SCANE || direction == FD_DIR_SCANL || 1419 direction == FD_DIR_SCANH) && dma_mode == 0) || 1420 (direction == FD_DIR_WRITE && dma_mode == 2) || 1421 (direction == FD_DIR_READ && dma_mode == 1) || 1422 (direction == FD_DIR_VERIFY)) { 1423 /* No access is allowed until DMA transfer has completed */ 1424 fdctrl->msr &= ~FD_MSR_RQM; 1425 if (direction != FD_DIR_VERIFY) { 1426 /* Now, we just have to wait for the DMA controller to 1427 * recall us... 1428 */ 1429 DMA_hold_DREQ(fdctrl->dma_chann); 1430 DMA_schedule(fdctrl->dma_chann); 1431 } else { 1432 /* Start transfer */ 1433 fdctrl_transfer_handler(fdctrl, fdctrl->dma_chann, 0, 1434 fdctrl->data_len); 1435 } 1436 return; 1437 } else { 1438 FLOPPY_DPRINTF("bad dma_mode=%d direction=%d\n", dma_mode, 1439 direction); 1440 } 1441 } 1442 FLOPPY_DPRINTF("start non-DMA transfer\n"); 1443 fdctrl->msr |= FD_MSR_NONDMA | FD_MSR_RQM; 1444 if (direction != FD_DIR_WRITE) 1445 fdctrl->msr |= FD_MSR_DIO; 1446 /* IO based transfer: calculate len */ 1447 fdctrl_raise_irq(fdctrl); 1448 } 1449 1450 /* Prepare a transfer of deleted data */ 1451 static void fdctrl_start_transfer_del(FDCtrl *fdctrl, int direction) 1452 { 1453 qemu_log_mask(LOG_UNIMP, "fdctrl_start_transfer_del() unimplemented\n"); 1454 1455 /* We don't handle deleted data, 1456 * so we don't return *ANYTHING* 1457 */ 1458 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00); 1459 } 1460 1461 /* handlers for DMA transfers */ 1462 static int fdctrl_transfer_handler (void *opaque, int nchan, 1463 int dma_pos, int dma_len) 1464 { 1465 FDCtrl *fdctrl; 1466 FDrive *cur_drv; 1467 int len, start_pos, rel_pos; 1468 uint8_t status0 = 0x00, status1 = 0x00, status2 = 0x00; 1469 1470 fdctrl = opaque; 1471 if (fdctrl->msr & FD_MSR_RQM) { 1472 FLOPPY_DPRINTF("Not in DMA transfer mode !\n"); 1473 return 0; 1474 } 1475 cur_drv = get_cur_drv(fdctrl); 1476 if (fdctrl->data_dir == FD_DIR_SCANE || fdctrl->data_dir == FD_DIR_SCANL || 1477 fdctrl->data_dir == FD_DIR_SCANH) 1478 status2 = FD_SR2_SNS; 1479 if (dma_len > fdctrl->data_len) 1480 dma_len = fdctrl->data_len; 1481 if (cur_drv->blk == NULL) { 1482 if (fdctrl->data_dir == FD_DIR_WRITE) 1483 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00); 1484 else 1485 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00); 1486 len = 0; 1487 goto transfer_error; 1488 } 1489 rel_pos = fdctrl->data_pos % FD_SECTOR_LEN; 1490 for (start_pos = fdctrl->data_pos; fdctrl->data_pos < dma_len;) { 1491 len = dma_len - fdctrl->data_pos; 1492 if (len + rel_pos > FD_SECTOR_LEN) 1493 len = FD_SECTOR_LEN - rel_pos; 1494 FLOPPY_DPRINTF("copy %d bytes (%d %d %d) %d pos %d %02x " 1495 "(%d-0x%08x 0x%08x)\n", len, dma_len, fdctrl->data_pos, 1496 fdctrl->data_len, GET_CUR_DRV(fdctrl), cur_drv->head, 1497 cur_drv->track, cur_drv->sect, fd_sector(cur_drv), 1498 fd_sector(cur_drv) * FD_SECTOR_LEN); 1499 if (fdctrl->data_dir != FD_DIR_WRITE || 1500 len < FD_SECTOR_LEN || rel_pos != 0) { 1501 /* READ & SCAN commands and realign to a sector for WRITE */ 1502 if (blk_read(cur_drv->blk, fd_sector(cur_drv), 1503 fdctrl->fifo, 1) < 0) { 1504 FLOPPY_DPRINTF("Floppy: error getting sector %d\n", 1505 fd_sector(cur_drv)); 1506 /* Sure, image size is too small... */ 1507 memset(fdctrl->fifo, 0, FD_SECTOR_LEN); 1508 } 1509 } 1510 switch (fdctrl->data_dir) { 1511 case FD_DIR_READ: 1512 /* READ commands */ 1513 DMA_write_memory (nchan, fdctrl->fifo + rel_pos, 1514 fdctrl->data_pos, len); 1515 break; 1516 case FD_DIR_WRITE: 1517 /* WRITE commands */ 1518 if (cur_drv->ro) { 1519 /* Handle readonly medium early, no need to do DMA, touch the 1520 * LED or attempt any writes. A real floppy doesn't attempt 1521 * to write to readonly media either. */ 1522 fdctrl_stop_transfer(fdctrl, 1523 FD_SR0_ABNTERM | FD_SR0_SEEK, FD_SR1_NW, 1524 0x00); 1525 goto transfer_error; 1526 } 1527 1528 DMA_read_memory (nchan, fdctrl->fifo + rel_pos, 1529 fdctrl->data_pos, len); 1530 if (blk_write(cur_drv->blk, fd_sector(cur_drv), 1531 fdctrl->fifo, 1) < 0) { 1532 FLOPPY_DPRINTF("error writing sector %d\n", 1533 fd_sector(cur_drv)); 1534 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00); 1535 goto transfer_error; 1536 } 1537 break; 1538 case FD_DIR_VERIFY: 1539 /* VERIFY commands */ 1540 break; 1541 default: 1542 /* SCAN commands */ 1543 { 1544 uint8_t tmpbuf[FD_SECTOR_LEN]; 1545 int ret; 1546 DMA_read_memory (nchan, tmpbuf, fdctrl->data_pos, len); 1547 ret = memcmp(tmpbuf, fdctrl->fifo + rel_pos, len); 1548 if (ret == 0) { 1549 status2 = FD_SR2_SEH; 1550 goto end_transfer; 1551 } 1552 if ((ret < 0 && fdctrl->data_dir == FD_DIR_SCANL) || 1553 (ret > 0 && fdctrl->data_dir == FD_DIR_SCANH)) { 1554 status2 = 0x00; 1555 goto end_transfer; 1556 } 1557 } 1558 break; 1559 } 1560 fdctrl->data_pos += len; 1561 rel_pos = fdctrl->data_pos % FD_SECTOR_LEN; 1562 if (rel_pos == 0) { 1563 /* Seek to next sector */ 1564 if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) 1565 break; 1566 } 1567 } 1568 end_transfer: 1569 len = fdctrl->data_pos - start_pos; 1570 FLOPPY_DPRINTF("end transfer %d %d %d\n", 1571 fdctrl->data_pos, len, fdctrl->data_len); 1572 if (fdctrl->data_dir == FD_DIR_SCANE || 1573 fdctrl->data_dir == FD_DIR_SCANL || 1574 fdctrl->data_dir == FD_DIR_SCANH) 1575 status2 = FD_SR2_SEH; 1576 fdctrl->data_len -= len; 1577 fdctrl_stop_transfer(fdctrl, status0, status1, status2); 1578 transfer_error: 1579 1580 return len; 1581 } 1582 1583 /* Data register : 0x05 */ 1584 static uint32_t fdctrl_read_data(FDCtrl *fdctrl) 1585 { 1586 FDrive *cur_drv; 1587 uint32_t retval = 0; 1588 uint32_t pos; 1589 1590 cur_drv = get_cur_drv(fdctrl); 1591 fdctrl->dsr &= ~FD_DSR_PWRDOWN; 1592 if (!(fdctrl->msr & FD_MSR_RQM) || !(fdctrl->msr & FD_MSR_DIO)) { 1593 FLOPPY_DPRINTF("error: controller not ready for reading\n"); 1594 return 0; 1595 } 1596 1597 /* If data_len spans multiple sectors, the current position in the FIFO 1598 * wraps around while fdctrl->data_pos is the real position in the whole 1599 * request. */ 1600 pos = fdctrl->data_pos; 1601 pos %= FD_SECTOR_LEN; 1602 1603 switch (fdctrl->phase) { 1604 case FD_PHASE_EXECUTION: 1605 assert(fdctrl->msr & FD_MSR_NONDMA); 1606 if (pos == 0) { 1607 if (fdctrl->data_pos != 0) 1608 if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) { 1609 FLOPPY_DPRINTF("error seeking to next sector %d\n", 1610 fd_sector(cur_drv)); 1611 return 0; 1612 } 1613 if (blk_read(cur_drv->blk, fd_sector(cur_drv), fdctrl->fifo, 1) 1614 < 0) { 1615 FLOPPY_DPRINTF("error getting sector %d\n", 1616 fd_sector(cur_drv)); 1617 /* Sure, image size is too small... */ 1618 memset(fdctrl->fifo, 0, FD_SECTOR_LEN); 1619 } 1620 } 1621 1622 if (++fdctrl->data_pos == fdctrl->data_len) { 1623 fdctrl->msr &= ~FD_MSR_RQM; 1624 fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00); 1625 } 1626 break; 1627 1628 case FD_PHASE_RESULT: 1629 assert(!(fdctrl->msr & FD_MSR_NONDMA)); 1630 if (++fdctrl->data_pos == fdctrl->data_len) { 1631 fdctrl->msr &= ~FD_MSR_RQM; 1632 fdctrl_to_command_phase(fdctrl); 1633 fdctrl_reset_irq(fdctrl); 1634 } 1635 break; 1636 1637 case FD_PHASE_COMMAND: 1638 default: 1639 abort(); 1640 } 1641 1642 retval = fdctrl->fifo[pos]; 1643 FLOPPY_DPRINTF("data register: 0x%02x\n", retval); 1644 1645 return retval; 1646 } 1647 1648 static void fdctrl_format_sector(FDCtrl *fdctrl) 1649 { 1650 FDrive *cur_drv; 1651 uint8_t kh, kt, ks; 1652 1653 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); 1654 cur_drv = get_cur_drv(fdctrl); 1655 kt = fdctrl->fifo[6]; 1656 kh = fdctrl->fifo[7]; 1657 ks = fdctrl->fifo[8]; 1658 FLOPPY_DPRINTF("format sector at %d %d %02x %02x (%d)\n", 1659 GET_CUR_DRV(fdctrl), kh, kt, ks, 1660 fd_sector_calc(kh, kt, ks, cur_drv->last_sect, 1661 NUM_SIDES(cur_drv))); 1662 switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & FD_CONFIG_EIS)) { 1663 case 2: 1664 /* sect too big */ 1665 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00); 1666 fdctrl->fifo[3] = kt; 1667 fdctrl->fifo[4] = kh; 1668 fdctrl->fifo[5] = ks; 1669 return; 1670 case 3: 1671 /* track too big */ 1672 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_EC, 0x00); 1673 fdctrl->fifo[3] = kt; 1674 fdctrl->fifo[4] = kh; 1675 fdctrl->fifo[5] = ks; 1676 return; 1677 case 4: 1678 /* No seek enabled */ 1679 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00); 1680 fdctrl->fifo[3] = kt; 1681 fdctrl->fifo[4] = kh; 1682 fdctrl->fifo[5] = ks; 1683 return; 1684 case 1: 1685 fdctrl->status0 |= FD_SR0_SEEK; 1686 break; 1687 default: 1688 break; 1689 } 1690 memset(fdctrl->fifo, 0, FD_SECTOR_LEN); 1691 if (cur_drv->blk == NULL || 1692 blk_write(cur_drv->blk, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) { 1693 FLOPPY_DPRINTF("error formatting sector %d\n", fd_sector(cur_drv)); 1694 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00); 1695 } else { 1696 if (cur_drv->sect == cur_drv->last_sect) { 1697 fdctrl->data_state &= ~FD_STATE_FORMAT; 1698 /* Last sector done */ 1699 fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00); 1700 } else { 1701 /* More to do */ 1702 fdctrl->data_pos = 0; 1703 fdctrl->data_len = 4; 1704 } 1705 } 1706 } 1707 1708 static void fdctrl_handle_lock(FDCtrl *fdctrl, int direction) 1709 { 1710 fdctrl->lock = (fdctrl->fifo[0] & 0x80) ? 1 : 0; 1711 fdctrl->fifo[0] = fdctrl->lock << 4; 1712 fdctrl_to_result_phase(fdctrl, 1); 1713 } 1714 1715 static void fdctrl_handle_dumpreg(FDCtrl *fdctrl, int direction) 1716 { 1717 FDrive *cur_drv = get_cur_drv(fdctrl); 1718 1719 /* Drives position */ 1720 fdctrl->fifo[0] = drv0(fdctrl)->track; 1721 fdctrl->fifo[1] = drv1(fdctrl)->track; 1722 #if MAX_FD == 4 1723 fdctrl->fifo[2] = drv2(fdctrl)->track; 1724 fdctrl->fifo[3] = drv3(fdctrl)->track; 1725 #else 1726 fdctrl->fifo[2] = 0; 1727 fdctrl->fifo[3] = 0; 1728 #endif 1729 /* timers */ 1730 fdctrl->fifo[4] = fdctrl->timer0; 1731 fdctrl->fifo[5] = (fdctrl->timer1 << 1) | (fdctrl->dor & FD_DOR_DMAEN ? 1 : 0); 1732 fdctrl->fifo[6] = cur_drv->last_sect; 1733 fdctrl->fifo[7] = (fdctrl->lock << 7) | 1734 (cur_drv->perpendicular << 2); 1735 fdctrl->fifo[8] = fdctrl->config; 1736 fdctrl->fifo[9] = fdctrl->precomp_trk; 1737 fdctrl_to_result_phase(fdctrl, 10); 1738 } 1739 1740 static void fdctrl_handle_version(FDCtrl *fdctrl, int direction) 1741 { 1742 /* Controller's version */ 1743 fdctrl->fifo[0] = fdctrl->version; 1744 fdctrl_to_result_phase(fdctrl, 1); 1745 } 1746 1747 static void fdctrl_handle_partid(FDCtrl *fdctrl, int direction) 1748 { 1749 fdctrl->fifo[0] = 0x41; /* Stepping 1 */ 1750 fdctrl_to_result_phase(fdctrl, 1); 1751 } 1752 1753 static void fdctrl_handle_restore(FDCtrl *fdctrl, int direction) 1754 { 1755 FDrive *cur_drv = get_cur_drv(fdctrl); 1756 1757 /* Drives position */ 1758 drv0(fdctrl)->track = fdctrl->fifo[3]; 1759 drv1(fdctrl)->track = fdctrl->fifo[4]; 1760 #if MAX_FD == 4 1761 drv2(fdctrl)->track = fdctrl->fifo[5]; 1762 drv3(fdctrl)->track = fdctrl->fifo[6]; 1763 #endif 1764 /* timers */ 1765 fdctrl->timer0 = fdctrl->fifo[7]; 1766 fdctrl->timer1 = fdctrl->fifo[8]; 1767 cur_drv->last_sect = fdctrl->fifo[9]; 1768 fdctrl->lock = fdctrl->fifo[10] >> 7; 1769 cur_drv->perpendicular = (fdctrl->fifo[10] >> 2) & 0xF; 1770 fdctrl->config = fdctrl->fifo[11]; 1771 fdctrl->precomp_trk = fdctrl->fifo[12]; 1772 fdctrl->pwrd = fdctrl->fifo[13]; 1773 fdctrl_to_command_phase(fdctrl); 1774 } 1775 1776 static void fdctrl_handle_save(FDCtrl *fdctrl, int direction) 1777 { 1778 FDrive *cur_drv = get_cur_drv(fdctrl); 1779 1780 fdctrl->fifo[0] = 0; 1781 fdctrl->fifo[1] = 0; 1782 /* Drives position */ 1783 fdctrl->fifo[2] = drv0(fdctrl)->track; 1784 fdctrl->fifo[3] = drv1(fdctrl)->track; 1785 #if MAX_FD == 4 1786 fdctrl->fifo[4] = drv2(fdctrl)->track; 1787 fdctrl->fifo[5] = drv3(fdctrl)->track; 1788 #else 1789 fdctrl->fifo[4] = 0; 1790 fdctrl->fifo[5] = 0; 1791 #endif 1792 /* timers */ 1793 fdctrl->fifo[6] = fdctrl->timer0; 1794 fdctrl->fifo[7] = fdctrl->timer1; 1795 fdctrl->fifo[8] = cur_drv->last_sect; 1796 fdctrl->fifo[9] = (fdctrl->lock << 7) | 1797 (cur_drv->perpendicular << 2); 1798 fdctrl->fifo[10] = fdctrl->config; 1799 fdctrl->fifo[11] = fdctrl->precomp_trk; 1800 fdctrl->fifo[12] = fdctrl->pwrd; 1801 fdctrl->fifo[13] = 0; 1802 fdctrl->fifo[14] = 0; 1803 fdctrl_to_result_phase(fdctrl, 15); 1804 } 1805 1806 static void fdctrl_handle_readid(FDCtrl *fdctrl, int direction) 1807 { 1808 FDrive *cur_drv = get_cur_drv(fdctrl); 1809 1810 cur_drv->head = (fdctrl->fifo[1] >> 2) & 1; 1811 timer_mod(fdctrl->result_timer, 1812 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + (get_ticks_per_sec() / 50)); 1813 } 1814 1815 static void fdctrl_handle_format_track(FDCtrl *fdctrl, int direction) 1816 { 1817 FDrive *cur_drv; 1818 1819 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); 1820 cur_drv = get_cur_drv(fdctrl); 1821 fdctrl->data_state |= FD_STATE_FORMAT; 1822 if (fdctrl->fifo[0] & 0x80) 1823 fdctrl->data_state |= FD_STATE_MULTI; 1824 else 1825 fdctrl->data_state &= ~FD_STATE_MULTI; 1826 cur_drv->bps = 1827 fdctrl->fifo[2] > 7 ? 16384 : 128 << fdctrl->fifo[2]; 1828 #if 0 1829 cur_drv->last_sect = 1830 cur_drv->flags & FDISK_DBL_SIDES ? fdctrl->fifo[3] : 1831 fdctrl->fifo[3] / 2; 1832 #else 1833 cur_drv->last_sect = fdctrl->fifo[3]; 1834 #endif 1835 /* TODO: implement format using DMA expected by the Bochs BIOS 1836 * and Linux fdformat (read 3 bytes per sector via DMA and fill 1837 * the sector with the specified fill byte 1838 */ 1839 fdctrl->data_state &= ~FD_STATE_FORMAT; 1840 fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00); 1841 } 1842 1843 static void fdctrl_handle_specify(FDCtrl *fdctrl, int direction) 1844 { 1845 fdctrl->timer0 = (fdctrl->fifo[1] >> 4) & 0xF; 1846 fdctrl->timer1 = fdctrl->fifo[2] >> 1; 1847 if (fdctrl->fifo[2] & 1) 1848 fdctrl->dor &= ~FD_DOR_DMAEN; 1849 else 1850 fdctrl->dor |= FD_DOR_DMAEN; 1851 /* No result back */ 1852 fdctrl_to_command_phase(fdctrl); 1853 } 1854 1855 static void fdctrl_handle_sense_drive_status(FDCtrl *fdctrl, int direction) 1856 { 1857 FDrive *cur_drv; 1858 1859 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); 1860 cur_drv = get_cur_drv(fdctrl); 1861 cur_drv->head = (fdctrl->fifo[1] >> 2) & 1; 1862 /* 1 Byte status back */ 1863 fdctrl->fifo[0] = (cur_drv->ro << 6) | 1864 (cur_drv->track == 0 ? 0x10 : 0x00) | 1865 (cur_drv->head << 2) | 1866 GET_CUR_DRV(fdctrl) | 1867 0x28; 1868 fdctrl_to_result_phase(fdctrl, 1); 1869 } 1870 1871 static void fdctrl_handle_recalibrate(FDCtrl *fdctrl, int direction) 1872 { 1873 FDrive *cur_drv; 1874 1875 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); 1876 cur_drv = get_cur_drv(fdctrl); 1877 fd_recalibrate(cur_drv); 1878 fdctrl_to_command_phase(fdctrl); 1879 /* Raise Interrupt */ 1880 fdctrl->status0 |= FD_SR0_SEEK; 1881 fdctrl_raise_irq(fdctrl); 1882 } 1883 1884 static void fdctrl_handle_sense_interrupt_status(FDCtrl *fdctrl, int direction) 1885 { 1886 FDrive *cur_drv = get_cur_drv(fdctrl); 1887 1888 if (fdctrl->reset_sensei > 0) { 1889 fdctrl->fifo[0] = 1890 FD_SR0_RDYCHG + FD_RESET_SENSEI_COUNT - fdctrl->reset_sensei; 1891 fdctrl->reset_sensei--; 1892 } else if (!(fdctrl->sra & FD_SRA_INTPEND)) { 1893 fdctrl->fifo[0] = FD_SR0_INVCMD; 1894 fdctrl_to_result_phase(fdctrl, 1); 1895 return; 1896 } else { 1897 fdctrl->fifo[0] = 1898 (fdctrl->status0 & ~(FD_SR0_HEAD | FD_SR0_DS1 | FD_SR0_DS0)) 1899 | GET_CUR_DRV(fdctrl); 1900 } 1901 1902 fdctrl->fifo[1] = cur_drv->track; 1903 fdctrl_to_result_phase(fdctrl, 2); 1904 fdctrl_reset_irq(fdctrl); 1905 fdctrl->status0 = FD_SR0_RDYCHG; 1906 } 1907 1908 static void fdctrl_handle_seek(FDCtrl *fdctrl, int direction) 1909 { 1910 FDrive *cur_drv; 1911 1912 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); 1913 cur_drv = get_cur_drv(fdctrl); 1914 fdctrl_to_command_phase(fdctrl); 1915 /* The seek command just sends step pulses to the drive and doesn't care if 1916 * there is a medium inserted of if it's banging the head against the drive. 1917 */ 1918 fd_seek(cur_drv, cur_drv->head, fdctrl->fifo[2], cur_drv->sect, 1); 1919 /* Raise Interrupt */ 1920 fdctrl->status0 |= FD_SR0_SEEK; 1921 fdctrl_raise_irq(fdctrl); 1922 } 1923 1924 static void fdctrl_handle_perpendicular_mode(FDCtrl *fdctrl, int direction) 1925 { 1926 FDrive *cur_drv = get_cur_drv(fdctrl); 1927 1928 if (fdctrl->fifo[1] & 0x80) 1929 cur_drv->perpendicular = fdctrl->fifo[1] & 0x7; 1930 /* No result back */ 1931 fdctrl_to_command_phase(fdctrl); 1932 } 1933 1934 static void fdctrl_handle_configure(FDCtrl *fdctrl, int direction) 1935 { 1936 fdctrl->config = fdctrl->fifo[2]; 1937 fdctrl->precomp_trk = fdctrl->fifo[3]; 1938 /* No result back */ 1939 fdctrl_to_command_phase(fdctrl); 1940 } 1941 1942 static void fdctrl_handle_powerdown_mode(FDCtrl *fdctrl, int direction) 1943 { 1944 fdctrl->pwrd = fdctrl->fifo[1]; 1945 fdctrl->fifo[0] = fdctrl->fifo[1]; 1946 fdctrl_to_result_phase(fdctrl, 1); 1947 } 1948 1949 static void fdctrl_handle_option(FDCtrl *fdctrl, int direction) 1950 { 1951 /* No result back */ 1952 fdctrl_to_command_phase(fdctrl); 1953 } 1954 1955 static void fdctrl_handle_drive_specification_command(FDCtrl *fdctrl, int direction) 1956 { 1957 FDrive *cur_drv = get_cur_drv(fdctrl); 1958 uint32_t pos; 1959 1960 pos = fdctrl->data_pos - 1; 1961 pos %= FD_SECTOR_LEN; 1962 if (fdctrl->fifo[pos] & 0x80) { 1963 /* Command parameters done */ 1964 if (fdctrl->fifo[pos] & 0x40) { 1965 fdctrl->fifo[0] = fdctrl->fifo[1]; 1966 fdctrl->fifo[2] = 0; 1967 fdctrl->fifo[3] = 0; 1968 fdctrl_to_result_phase(fdctrl, 4); 1969 } else { 1970 fdctrl_to_command_phase(fdctrl); 1971 } 1972 } else if (fdctrl->data_len > 7) { 1973 /* ERROR */ 1974 fdctrl->fifo[0] = 0x80 | 1975 (cur_drv->head << 2) | GET_CUR_DRV(fdctrl); 1976 fdctrl_to_result_phase(fdctrl, 1); 1977 } 1978 } 1979 1980 static void fdctrl_handle_relative_seek_in(FDCtrl *fdctrl, int direction) 1981 { 1982 FDrive *cur_drv; 1983 1984 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); 1985 cur_drv = get_cur_drv(fdctrl); 1986 if (fdctrl->fifo[2] + cur_drv->track >= cur_drv->max_track) { 1987 fd_seek(cur_drv, cur_drv->head, cur_drv->max_track - 1, 1988 cur_drv->sect, 1); 1989 } else { 1990 fd_seek(cur_drv, cur_drv->head, 1991 cur_drv->track + fdctrl->fifo[2], cur_drv->sect, 1); 1992 } 1993 fdctrl_to_command_phase(fdctrl); 1994 /* Raise Interrupt */ 1995 fdctrl->status0 |= FD_SR0_SEEK; 1996 fdctrl_raise_irq(fdctrl); 1997 } 1998 1999 static void fdctrl_handle_relative_seek_out(FDCtrl *fdctrl, int direction) 2000 { 2001 FDrive *cur_drv; 2002 2003 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); 2004 cur_drv = get_cur_drv(fdctrl); 2005 if (fdctrl->fifo[2] > cur_drv->track) { 2006 fd_seek(cur_drv, cur_drv->head, 0, cur_drv->sect, 1); 2007 } else { 2008 fd_seek(cur_drv, cur_drv->head, 2009 cur_drv->track - fdctrl->fifo[2], cur_drv->sect, 1); 2010 } 2011 fdctrl_to_command_phase(fdctrl); 2012 /* Raise Interrupt */ 2013 fdctrl->status0 |= FD_SR0_SEEK; 2014 fdctrl_raise_irq(fdctrl); 2015 } 2016 2017 /* 2018 * Handlers for the execution phase of each command 2019 */ 2020 typedef struct FDCtrlCommand { 2021 uint8_t value; 2022 uint8_t mask; 2023 const char* name; 2024 int parameters; 2025 void (*handler)(FDCtrl *fdctrl, int direction); 2026 int direction; 2027 } FDCtrlCommand; 2028 2029 static const FDCtrlCommand handlers[] = { 2030 { FD_CMD_READ, 0x1f, "READ", 8, fdctrl_start_transfer, FD_DIR_READ }, 2031 { FD_CMD_WRITE, 0x3f, "WRITE", 8, fdctrl_start_transfer, FD_DIR_WRITE }, 2032 { FD_CMD_SEEK, 0xff, "SEEK", 2, fdctrl_handle_seek }, 2033 { FD_CMD_SENSE_INTERRUPT_STATUS, 0xff, "SENSE INTERRUPT STATUS", 0, fdctrl_handle_sense_interrupt_status }, 2034 { FD_CMD_RECALIBRATE, 0xff, "RECALIBRATE", 1, fdctrl_handle_recalibrate }, 2035 { FD_CMD_FORMAT_TRACK, 0xbf, "FORMAT TRACK", 5, fdctrl_handle_format_track }, 2036 { FD_CMD_READ_TRACK, 0xbf, "READ TRACK", 8, fdctrl_start_transfer, FD_DIR_READ }, 2037 { FD_CMD_RESTORE, 0xff, "RESTORE", 17, fdctrl_handle_restore }, /* part of READ DELETED DATA */ 2038 { FD_CMD_SAVE, 0xff, "SAVE", 0, fdctrl_handle_save }, /* part of READ DELETED DATA */ 2039 { FD_CMD_READ_DELETED, 0x1f, "READ DELETED DATA", 8, fdctrl_start_transfer_del, FD_DIR_READ }, 2040 { FD_CMD_SCAN_EQUAL, 0x1f, "SCAN EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANE }, 2041 { FD_CMD_VERIFY, 0x1f, "VERIFY", 8, fdctrl_start_transfer, FD_DIR_VERIFY }, 2042 { FD_CMD_SCAN_LOW_OR_EQUAL, 0x1f, "SCAN LOW OR EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANL }, 2043 { FD_CMD_SCAN_HIGH_OR_EQUAL, 0x1f, "SCAN HIGH OR EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANH }, 2044 { FD_CMD_WRITE_DELETED, 0x3f, "WRITE DELETED DATA", 8, fdctrl_start_transfer_del, FD_DIR_WRITE }, 2045 { FD_CMD_READ_ID, 0xbf, "READ ID", 1, fdctrl_handle_readid }, 2046 { FD_CMD_SPECIFY, 0xff, "SPECIFY", 2, fdctrl_handle_specify }, 2047 { FD_CMD_SENSE_DRIVE_STATUS, 0xff, "SENSE DRIVE STATUS", 1, fdctrl_handle_sense_drive_status }, 2048 { FD_CMD_PERPENDICULAR_MODE, 0xff, "PERPENDICULAR MODE", 1, fdctrl_handle_perpendicular_mode }, 2049 { FD_CMD_CONFIGURE, 0xff, "CONFIGURE", 3, fdctrl_handle_configure }, 2050 { FD_CMD_POWERDOWN_MODE, 0xff, "POWERDOWN MODE", 2, fdctrl_handle_powerdown_mode }, 2051 { FD_CMD_OPTION, 0xff, "OPTION", 1, fdctrl_handle_option }, 2052 { FD_CMD_DRIVE_SPECIFICATION_COMMAND, 0xff, "DRIVE SPECIFICATION COMMAND", 5, fdctrl_handle_drive_specification_command }, 2053 { FD_CMD_RELATIVE_SEEK_OUT, 0xff, "RELATIVE SEEK OUT", 2, fdctrl_handle_relative_seek_out }, 2054 { FD_CMD_FORMAT_AND_WRITE, 0xff, "FORMAT AND WRITE", 10, fdctrl_unimplemented }, 2055 { FD_CMD_RELATIVE_SEEK_IN, 0xff, "RELATIVE SEEK IN", 2, fdctrl_handle_relative_seek_in }, 2056 { FD_CMD_LOCK, 0x7f, "LOCK", 0, fdctrl_handle_lock }, 2057 { FD_CMD_DUMPREG, 0xff, "DUMPREG", 0, fdctrl_handle_dumpreg }, 2058 { FD_CMD_VERSION, 0xff, "VERSION", 0, fdctrl_handle_version }, 2059 { FD_CMD_PART_ID, 0xff, "PART ID", 0, fdctrl_handle_partid }, 2060 { FD_CMD_WRITE, 0x1f, "WRITE (BeOS)", 8, fdctrl_start_transfer, FD_DIR_WRITE }, /* not in specification ; BeOS 4.5 bug */ 2061 { 0, 0, "unknown", 0, fdctrl_unimplemented }, /* default handler */ 2062 }; 2063 /* Associate command to an index in the 'handlers' array */ 2064 static uint8_t command_to_handler[256]; 2065 2066 static const FDCtrlCommand *get_command(uint8_t cmd) 2067 { 2068 int idx; 2069 2070 idx = command_to_handler[cmd]; 2071 FLOPPY_DPRINTF("%s command\n", handlers[idx].name); 2072 return &handlers[idx]; 2073 } 2074 2075 static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value) 2076 { 2077 FDrive *cur_drv; 2078 const FDCtrlCommand *cmd; 2079 uint32_t pos; 2080 2081 /* Reset mode */ 2082 if (!(fdctrl->dor & FD_DOR_nRESET)) { 2083 FLOPPY_DPRINTF("Floppy controller in RESET state !\n"); 2084 return; 2085 } 2086 if (!(fdctrl->msr & FD_MSR_RQM) || (fdctrl->msr & FD_MSR_DIO)) { 2087 FLOPPY_DPRINTF("error: controller not ready for writing\n"); 2088 return; 2089 } 2090 fdctrl->dsr &= ~FD_DSR_PWRDOWN; 2091 2092 FLOPPY_DPRINTF("%s: %02x\n", __func__, value); 2093 2094 /* If data_len spans multiple sectors, the current position in the FIFO 2095 * wraps around while fdctrl->data_pos is the real position in the whole 2096 * request. */ 2097 pos = fdctrl->data_pos++; 2098 pos %= FD_SECTOR_LEN; 2099 fdctrl->fifo[pos] = value; 2100 2101 if (fdctrl->data_pos == fdctrl->data_len) { 2102 fdctrl->msr &= ~FD_MSR_RQM; 2103 } 2104 2105 switch (fdctrl->phase) { 2106 case FD_PHASE_EXECUTION: 2107 /* For DMA requests, RQM should be cleared during execution phase, so 2108 * we would have errored out above. */ 2109 assert(fdctrl->msr & FD_MSR_NONDMA); 2110 2111 /* FIFO data write */ 2112 if (pos == FD_SECTOR_LEN - 1 || 2113 fdctrl->data_pos == fdctrl->data_len) { 2114 cur_drv = get_cur_drv(fdctrl); 2115 if (blk_write(cur_drv->blk, fd_sector(cur_drv), fdctrl->fifo, 1) 2116 < 0) { 2117 FLOPPY_DPRINTF("error writing sector %d\n", 2118 fd_sector(cur_drv)); 2119 break; 2120 } 2121 if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) { 2122 FLOPPY_DPRINTF("error seeking to next sector %d\n", 2123 fd_sector(cur_drv)); 2124 break; 2125 } 2126 } 2127 2128 /* Switch to result phase when done with the transfer */ 2129 if (fdctrl->data_pos == fdctrl->data_len) { 2130 fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00); 2131 } 2132 break; 2133 2134 case FD_PHASE_COMMAND: 2135 assert(!(fdctrl->msr & FD_MSR_NONDMA)); 2136 assert(fdctrl->data_pos < FD_SECTOR_LEN); 2137 2138 if (pos == 0) { 2139 /* The first byte specifies the command. Now we start reading 2140 * as many parameters as this command requires. */ 2141 cmd = get_command(value); 2142 fdctrl->data_len = cmd->parameters + 1; 2143 if (cmd->parameters) { 2144 fdctrl->msr |= FD_MSR_RQM; 2145 } 2146 fdctrl->msr |= FD_MSR_CMDBUSY; 2147 } 2148 2149 if (fdctrl->data_pos == fdctrl->data_len) { 2150 /* We have all parameters now, execute the command */ 2151 fdctrl->phase = FD_PHASE_EXECUTION; 2152 2153 if (fdctrl->data_state & FD_STATE_FORMAT) { 2154 fdctrl_format_sector(fdctrl); 2155 break; 2156 } 2157 2158 cmd = get_command(fdctrl->fifo[0]); 2159 FLOPPY_DPRINTF("Calling handler for '%s'\n", cmd->name); 2160 cmd->handler(fdctrl, cmd->direction); 2161 } 2162 break; 2163 2164 case FD_PHASE_RESULT: 2165 default: 2166 abort(); 2167 } 2168 } 2169 2170 static void fdctrl_result_timer(void *opaque) 2171 { 2172 FDCtrl *fdctrl = opaque; 2173 FDrive *cur_drv = get_cur_drv(fdctrl); 2174 2175 /* Pretend we are spinning. 2176 * This is needed for Coherent, which uses READ ID to check for 2177 * sector interleaving. 2178 */ 2179 if (cur_drv->last_sect != 0) { 2180 cur_drv->sect = (cur_drv->sect % cur_drv->last_sect) + 1; 2181 } 2182 /* READ_ID can't automatically succeed! */ 2183 if (fdctrl->check_media_rate && 2184 (fdctrl->dsr & FD_DSR_DRATEMASK) != cur_drv->media_rate) { 2185 FLOPPY_DPRINTF("read id rate mismatch (fdc=%d, media=%d)\n", 2186 fdctrl->dsr & FD_DSR_DRATEMASK, cur_drv->media_rate); 2187 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA, 0x00); 2188 } else { 2189 fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00); 2190 } 2191 } 2192 2193 static void fdctrl_change_cb(void *opaque, bool load) 2194 { 2195 FDrive *drive = opaque; 2196 2197 drive->media_changed = 1; 2198 fd_revalidate(drive); 2199 } 2200 2201 static const BlockDevOps fdctrl_block_ops = { 2202 .change_media_cb = fdctrl_change_cb, 2203 }; 2204 2205 /* Init functions */ 2206 static void fdctrl_connect_drives(FDCtrl *fdctrl, Error **errp) 2207 { 2208 unsigned int i; 2209 FDrive *drive; 2210 2211 for (i = 0; i < MAX_FD; i++) { 2212 drive = &fdctrl->drives[i]; 2213 drive->fdctrl = fdctrl; 2214 2215 if (drive->blk) { 2216 if (blk_get_on_error(drive->blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC) { 2217 error_setg(errp, "fdc doesn't support drive option werror"); 2218 return; 2219 } 2220 if (blk_get_on_error(drive->blk, 1) != BLOCKDEV_ON_ERROR_REPORT) { 2221 error_setg(errp, "fdc doesn't support drive option rerror"); 2222 return; 2223 } 2224 } 2225 2226 fd_init(drive); 2227 fdctrl_change_cb(drive, 0); 2228 if (drive->blk) { 2229 blk_set_dev_ops(drive->blk, &fdctrl_block_ops, drive); 2230 } 2231 } 2232 } 2233 2234 ISADevice *fdctrl_init_isa(ISABus *bus, DriveInfo **fds) 2235 { 2236 DeviceState *dev; 2237 ISADevice *isadev; 2238 2239 isadev = isa_try_create(bus, TYPE_ISA_FDC); 2240 if (!isadev) { 2241 return NULL; 2242 } 2243 dev = DEVICE(isadev); 2244 2245 if (fds[0]) { 2246 qdev_prop_set_drive_nofail(dev, "driveA", blk_by_legacy_dinfo(fds[0])); 2247 } 2248 if (fds[1]) { 2249 qdev_prop_set_drive_nofail(dev, "driveB", blk_by_legacy_dinfo(fds[1])); 2250 } 2251 qdev_init_nofail(dev); 2252 2253 return isadev; 2254 } 2255 2256 void fdctrl_init_sysbus(qemu_irq irq, int dma_chann, 2257 hwaddr mmio_base, DriveInfo **fds) 2258 { 2259 FDCtrl *fdctrl; 2260 DeviceState *dev; 2261 SysBusDevice *sbd; 2262 FDCtrlSysBus *sys; 2263 2264 dev = qdev_create(NULL, "sysbus-fdc"); 2265 sys = SYSBUS_FDC(dev); 2266 fdctrl = &sys->state; 2267 fdctrl->dma_chann = dma_chann; /* FIXME */ 2268 if (fds[0]) { 2269 qdev_prop_set_drive_nofail(dev, "driveA", blk_by_legacy_dinfo(fds[0])); 2270 } 2271 if (fds[1]) { 2272 qdev_prop_set_drive_nofail(dev, "driveB", blk_by_legacy_dinfo(fds[1])); 2273 } 2274 qdev_init_nofail(dev); 2275 sbd = SYS_BUS_DEVICE(dev); 2276 sysbus_connect_irq(sbd, 0, irq); 2277 sysbus_mmio_map(sbd, 0, mmio_base); 2278 } 2279 2280 void sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base, 2281 DriveInfo **fds, qemu_irq *fdc_tc) 2282 { 2283 DeviceState *dev; 2284 FDCtrlSysBus *sys; 2285 2286 dev = qdev_create(NULL, "SUNW,fdtwo"); 2287 if (fds[0]) { 2288 qdev_prop_set_drive_nofail(dev, "drive", blk_by_legacy_dinfo(fds[0])); 2289 } 2290 qdev_init_nofail(dev); 2291 sys = SYSBUS_FDC(dev); 2292 sysbus_connect_irq(SYS_BUS_DEVICE(sys), 0, irq); 2293 sysbus_mmio_map(SYS_BUS_DEVICE(sys), 0, io_base); 2294 *fdc_tc = qdev_get_gpio_in(dev, 0); 2295 } 2296 2297 static void fdctrl_realize_common(FDCtrl *fdctrl, Error **errp) 2298 { 2299 int i, j; 2300 static int command_tables_inited = 0; 2301 2302 /* Fill 'command_to_handler' lookup table */ 2303 if (!command_tables_inited) { 2304 command_tables_inited = 1; 2305 for (i = ARRAY_SIZE(handlers) - 1; i >= 0; i--) { 2306 for (j = 0; j < sizeof(command_to_handler); j++) { 2307 if ((j & handlers[i].mask) == handlers[i].value) { 2308 command_to_handler[j] = i; 2309 } 2310 } 2311 } 2312 } 2313 2314 FLOPPY_DPRINTF("init controller\n"); 2315 fdctrl->fifo = qemu_memalign(512, FD_SECTOR_LEN); 2316 fdctrl->fifo_size = 512; 2317 fdctrl->result_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, 2318 fdctrl_result_timer, fdctrl); 2319 2320 fdctrl->version = 0x90; /* Intel 82078 controller */ 2321 fdctrl->config = FD_CONFIG_EIS | FD_CONFIG_EFIFO; /* Implicit seek, polling & FIFO enabled */ 2322 fdctrl->num_floppies = MAX_FD; 2323 2324 if (fdctrl->dma_chann != -1) { 2325 DMA_register_channel(fdctrl->dma_chann, &fdctrl_transfer_handler, fdctrl); 2326 } 2327 fdctrl_connect_drives(fdctrl, errp); 2328 } 2329 2330 static const MemoryRegionPortio fdc_portio_list[] = { 2331 { 1, 5, 1, .read = fdctrl_read, .write = fdctrl_write }, 2332 { 7, 1, 1, .read = fdctrl_read, .write = fdctrl_write }, 2333 PORTIO_END_OF_LIST(), 2334 }; 2335 2336 static void isabus_fdc_realize(DeviceState *dev, Error **errp) 2337 { 2338 ISADevice *isadev = ISA_DEVICE(dev); 2339 FDCtrlISABus *isa = ISA_FDC(dev); 2340 FDCtrl *fdctrl = &isa->state; 2341 Error *err = NULL; 2342 2343 isa_register_portio_list(isadev, isa->iobase, fdc_portio_list, fdctrl, 2344 "fdc"); 2345 2346 isa_init_irq(isadev, &fdctrl->irq, isa->irq); 2347 fdctrl->dma_chann = isa->dma; 2348 2349 qdev_set_legacy_instance_id(dev, isa->iobase, 2); 2350 fdctrl_realize_common(fdctrl, &err); 2351 if (err != NULL) { 2352 error_propagate(errp, err); 2353 return; 2354 } 2355 } 2356 2357 static void sysbus_fdc_initfn(Object *obj) 2358 { 2359 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 2360 FDCtrlSysBus *sys = SYSBUS_FDC(obj); 2361 FDCtrl *fdctrl = &sys->state; 2362 2363 fdctrl->dma_chann = -1; 2364 2365 memory_region_init_io(&fdctrl->iomem, obj, &fdctrl_mem_ops, fdctrl, 2366 "fdc", 0x08); 2367 sysbus_init_mmio(sbd, &fdctrl->iomem); 2368 } 2369 2370 static void sun4m_fdc_initfn(Object *obj) 2371 { 2372 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 2373 FDCtrlSysBus *sys = SYSBUS_FDC(obj); 2374 FDCtrl *fdctrl = &sys->state; 2375 2376 memory_region_init_io(&fdctrl->iomem, obj, &fdctrl_mem_strict_ops, 2377 fdctrl, "fdctrl", 0x08); 2378 sysbus_init_mmio(sbd, &fdctrl->iomem); 2379 } 2380 2381 static void sysbus_fdc_common_initfn(Object *obj) 2382 { 2383 DeviceState *dev = DEVICE(obj); 2384 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 2385 FDCtrlSysBus *sys = SYSBUS_FDC(obj); 2386 FDCtrl *fdctrl = &sys->state; 2387 2388 qdev_set_legacy_instance_id(dev, 0 /* io */, 2); /* FIXME */ 2389 2390 sysbus_init_irq(sbd, &fdctrl->irq); 2391 qdev_init_gpio_in(dev, fdctrl_handle_tc, 1); 2392 } 2393 2394 static void sysbus_fdc_common_realize(DeviceState *dev, Error **errp) 2395 { 2396 FDCtrlSysBus *sys = SYSBUS_FDC(dev); 2397 FDCtrl *fdctrl = &sys->state; 2398 2399 fdctrl_realize_common(fdctrl, errp); 2400 } 2401 2402 FDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i) 2403 { 2404 FDCtrlISABus *isa = ISA_FDC(fdc); 2405 2406 return isa->state.drives[i].drive; 2407 } 2408 2409 static const VMStateDescription vmstate_isa_fdc ={ 2410 .name = "fdc", 2411 .version_id = 2, 2412 .minimum_version_id = 2, 2413 .fields = (VMStateField[]) { 2414 VMSTATE_STRUCT(state, FDCtrlISABus, 0, vmstate_fdc, FDCtrl), 2415 VMSTATE_END_OF_LIST() 2416 } 2417 }; 2418 2419 static Property isa_fdc_properties[] = { 2420 DEFINE_PROP_UINT32("iobase", FDCtrlISABus, iobase, 0x3f0), 2421 DEFINE_PROP_UINT32("irq", FDCtrlISABus, irq, 6), 2422 DEFINE_PROP_UINT32("dma", FDCtrlISABus, dma, 2), 2423 DEFINE_PROP_DRIVE("driveA", FDCtrlISABus, state.drives[0].blk), 2424 DEFINE_PROP_DRIVE("driveB", FDCtrlISABus, state.drives[1].blk), 2425 DEFINE_PROP_BIT("check_media_rate", FDCtrlISABus, state.check_media_rate, 2426 0, true), 2427 DEFINE_PROP_END_OF_LIST(), 2428 }; 2429 2430 static void isabus_fdc_class_init(ObjectClass *klass, void *data) 2431 { 2432 DeviceClass *dc = DEVICE_CLASS(klass); 2433 2434 dc->realize = isabus_fdc_realize; 2435 dc->fw_name = "fdc"; 2436 dc->reset = fdctrl_external_reset_isa; 2437 dc->vmsd = &vmstate_isa_fdc; 2438 dc->props = isa_fdc_properties; 2439 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); 2440 } 2441 2442 static void isabus_fdc_instance_init(Object *obj) 2443 { 2444 FDCtrlISABus *isa = ISA_FDC(obj); 2445 2446 device_add_bootindex_property(obj, &isa->bootindexA, 2447 "bootindexA", "/floppy@0", 2448 DEVICE(obj), NULL); 2449 device_add_bootindex_property(obj, &isa->bootindexB, 2450 "bootindexB", "/floppy@1", 2451 DEVICE(obj), NULL); 2452 } 2453 2454 static const TypeInfo isa_fdc_info = { 2455 .name = TYPE_ISA_FDC, 2456 .parent = TYPE_ISA_DEVICE, 2457 .instance_size = sizeof(FDCtrlISABus), 2458 .class_init = isabus_fdc_class_init, 2459 .instance_init = isabus_fdc_instance_init, 2460 }; 2461 2462 static const VMStateDescription vmstate_sysbus_fdc ={ 2463 .name = "fdc", 2464 .version_id = 2, 2465 .minimum_version_id = 2, 2466 .fields = (VMStateField[]) { 2467 VMSTATE_STRUCT(state, FDCtrlSysBus, 0, vmstate_fdc, FDCtrl), 2468 VMSTATE_END_OF_LIST() 2469 } 2470 }; 2471 2472 static Property sysbus_fdc_properties[] = { 2473 DEFINE_PROP_DRIVE("driveA", FDCtrlSysBus, state.drives[0].blk), 2474 DEFINE_PROP_DRIVE("driveB", FDCtrlSysBus, state.drives[1].blk), 2475 DEFINE_PROP_END_OF_LIST(), 2476 }; 2477 2478 static void sysbus_fdc_class_init(ObjectClass *klass, void *data) 2479 { 2480 DeviceClass *dc = DEVICE_CLASS(klass); 2481 2482 dc->props = sysbus_fdc_properties; 2483 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); 2484 } 2485 2486 static const TypeInfo sysbus_fdc_info = { 2487 .name = "sysbus-fdc", 2488 .parent = TYPE_SYSBUS_FDC, 2489 .instance_init = sysbus_fdc_initfn, 2490 .class_init = sysbus_fdc_class_init, 2491 }; 2492 2493 static Property sun4m_fdc_properties[] = { 2494 DEFINE_PROP_DRIVE("drive", FDCtrlSysBus, state.drives[0].blk), 2495 DEFINE_PROP_END_OF_LIST(), 2496 }; 2497 2498 static void sun4m_fdc_class_init(ObjectClass *klass, void *data) 2499 { 2500 DeviceClass *dc = DEVICE_CLASS(klass); 2501 2502 dc->props = sun4m_fdc_properties; 2503 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); 2504 } 2505 2506 static const TypeInfo sun4m_fdc_info = { 2507 .name = "SUNW,fdtwo", 2508 .parent = TYPE_SYSBUS_FDC, 2509 .instance_init = sun4m_fdc_initfn, 2510 .class_init = sun4m_fdc_class_init, 2511 }; 2512 2513 static void sysbus_fdc_common_class_init(ObjectClass *klass, void *data) 2514 { 2515 DeviceClass *dc = DEVICE_CLASS(klass); 2516 2517 dc->realize = sysbus_fdc_common_realize; 2518 dc->reset = fdctrl_external_reset_sysbus; 2519 dc->vmsd = &vmstate_sysbus_fdc; 2520 } 2521 2522 static const TypeInfo sysbus_fdc_type_info = { 2523 .name = TYPE_SYSBUS_FDC, 2524 .parent = TYPE_SYS_BUS_DEVICE, 2525 .instance_size = sizeof(FDCtrlSysBus), 2526 .instance_init = sysbus_fdc_common_initfn, 2527 .abstract = true, 2528 .class_init = sysbus_fdc_common_class_init, 2529 }; 2530 2531 static void fdc_register_types(void) 2532 { 2533 type_register_static(&isa_fdc_info); 2534 type_register_static(&sysbus_fdc_type_info); 2535 type_register_static(&sysbus_fdc_info); 2536 type_register_static(&sun4m_fdc_info); 2537 } 2538 2539 type_init(fdc_register_types) 2540