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