Lines Matching +full:dma +full:- +full:requests
27 * way. There are changes in DOR register and DMA is not available.
33 #include "qemu/error-report.h"
38 #include "hw/qdev-properties.h"
39 #include "hw/qdev-properties-system.h"
42 #include "system/block-backend.h"
46 #include "qemu/main-loop.h"
50 #include "fdc-internal.h"
74 #define TYPE_FLOPPY_BUS "floppy-bus"
88 bus->fdc = fdc; in floppy_bus_create()
143 { FLOPPY_DRIVE_TYPE_NONE, -1, -1, 0, 0, },
159 #define GET_CUR_DRV(fdctrl) ((fdctrl)->cur_drv)
160 #define SET_CUR_DRV(fdctrl, drive) ((fdctrl)->cur_drv = (drive))
181 drv->last_sect = 0xFF; in fd_empty_seek_hack()
182 drv->max_track = 0xFF; in fd_empty_seek_hack()
188 drv->perpendicular = 0; in fd_init()
190 drv->disk = FLOPPY_DRIVE_TYPE_NONE; in fd_init()
191 drv->last_sect = 0; in fd_init()
192 drv->max_track = 0; in fd_init()
193 drv->ro = true; in fd_init()
194 drv->media_changed = 1; in fd_init()
197 #define NUM_SIDES(drv) ((drv)->flags & FDISK_DBL_SIDES ? 2 : 1)
202 return (((track * num_sides) + head) * last_sect) + sect - 1; in fd_sector_calc()
208 return fd_sector_calc(drv->head, drv->track, drv->sect, drv->last_sect, in fd_sector()
232 if (track > drv->max_track || in fd_seek()
233 (head != 0 && (drv->flags & FDISK_DBL_SIDES) == 0)) { in fd_seek()
236 (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1, in fd_seek()
237 drv->max_track, drv->last_sect); in fd_seek()
240 if (sect > drv->last_sect) { in fd_seek()
243 (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1, in fd_seek()
244 drv->max_track, drv->last_sect); in fd_seek()
247 sector = fd_sector_calc(head, track, sect, drv->last_sect, NUM_SIDES(drv)); in fd_seek()
254 head, track, sect, 1, drv->max_track, in fd_seek()
255 drv->last_sect); in fd_seek()
259 drv->head = head; in fd_seek()
260 if (drv->track != track) { in fd_seek()
261 if (drv->blk != NULL && blk_is_inserted(drv->blk)) { in fd_seek()
262 drv->media_changed = 0; in fd_seek()
266 drv->track = track; in fd_seek()
267 drv->sect = sect; in fd_seek()
270 if (drv->blk == NULL || !blk_is_inserted(drv->blk)) { in fd_seek()
288 * @return: 0 on success, -1 if the drive is empty.
292 BlockBackend *blk = drv->blk; in pick_geometry()
297 bool magic = drv->drive == FLOPPY_DRIVE_TYPE_AUTO; in pick_geometry()
300 if (!drv->blk || !blk_is_inserted(drv->blk) || in pick_geometry()
301 drv->drive == FLOPPY_DRIVE_TYPE_NONE) in pick_geometry()
303 return -1; in pick_geometry()
316 match = size_match = type_match = -1; in pick_geometry()
319 if (parse->drive == FLOPPY_DRIVE_TYPE_NONE) { in pick_geometry()
322 size = (parse->max_head + 1) * parse->max_track * parse->last_sect; in pick_geometry()
324 if (magic || parse->drive == drv->drive) { in pick_geometry()
325 /* (1) perfect match -- nb_sectors and drive type */ in pick_geometry()
327 } else if (drive_size(parse->drive) == drive_size(drv->drive)) { in pick_geometry()
328 /* (2) size match -- nb_sectors and physical medium size */ in pick_geometry()
329 match = (match == -1) ? i : match; in pick_geometry()
331 /* This is suspicious -- Did the user misconfigure? */ in pick_geometry()
332 size_match = (size_match == -1) ? i : size_match; in pick_geometry()
334 } else if (type_match == -1) { in pick_geometry()
335 if ((parse->drive == drv->drive) || in pick_geometry()
336 (magic && (parse->drive == get_fallback_drive_type(drv)))) { in pick_geometry()
337 /* (3) type match -- nb_sectors mismatch, but matches the type in pick_geometry()
346 if (match == -1) { in pick_geometry()
347 if (size_match != -1) { in pick_geometry()
352 FloppyDriveType_str(drv->drive), in pick_geometry()
354 FloppyDriveType_str(parse->drive)); in pick_geometry()
356 assert(type_match != -1 && "misconfigured fd_format"); in pick_geometry()
362 if (parse->max_head == 0) { in pick_geometry()
363 drv->flags &= ~FDISK_DBL_SIDES; in pick_geometry()
365 drv->flags |= FDISK_DBL_SIDES; in pick_geometry()
367 drv->max_track = parse->max_track; in pick_geometry()
368 drv->last_sect = parse->last_sect; in pick_geometry()
369 drv->disk = parse->drive; in pick_geometry()
370 drv->media_rate = parse->rate; in pick_geometry()
376 if (drv->drive != FLOPPY_DRIVE_TYPE_AUTO) { in pick_drive_type()
381 drv->drive = drv->disk; in pick_drive_type()
383 drv->drive = get_fallback_drive_type(drv); in pick_drive_type()
386 g_assert(drv->drive != FLOPPY_DRIVE_TYPE_AUTO); in pick_drive_type()
395 if (drv->blk != NULL) { in fd_revalidate()
396 drv->ro = !blk_is_writable(drv->blk); in fd_revalidate()
397 if (!blk_is_inserted(drv->blk)) { in fd_revalidate()
399 drv->disk = FLOPPY_DRIVE_TYPE_NONE; in fd_revalidate()
401 } else if (!drv->media_validated) { in fd_revalidate()
406 drv->media_validated = true; in fd_revalidate()
408 (drv->flags & FDISK_DBL_SIDES) ? 2 : 1, in fd_revalidate()
409 drv->max_track, drv->last_sect, in fd_revalidate()
410 drv->ro ? "ro" : "rw"); in fd_revalidate()
415 drv->last_sect = 0; in fd_revalidate()
416 drv->max_track = 0; in fd_revalidate()
417 drv->flags &= ~FDISK_DBL_SIDES; in fd_revalidate()
418 drv->drive = FLOPPY_DRIVE_TYPE_NONE; in fd_revalidate()
419 drv->disk = FLOPPY_DRIVE_TYPE_NONE; in fd_revalidate()
428 blk_set_perm(drive->blk, 0, BLK_PERM_ALL, &error_abort); in fd_change_cb()
430 if (!blkconf_apply_backend_options(drive->conf, in fd_change_cb()
431 !blk_supports_write_perm(drive->blk), in fd_change_cb()
437 drive->media_changed = 1; in fd_change_cb()
438 drive->media_validated = false; in fd_change_cb()
458 DEFINE_PROP_UINT32("unit", FloppyDrive, unit, -1),
460 DEFINE_PROP_SIGNED("drive-type", FloppyDrive, type,
468 FloppyBus *bus = FLOPPY_BUS(qdev->parent_bus); in floppy_drive_realize()
473 if (dev->unit == -1) { in floppy_drive_realize()
474 for (dev->unit = 0; dev->unit < MAX_FD; dev->unit++) { in floppy_drive_realize()
475 drive = get_drv(bus->fdc, dev->unit); in floppy_drive_realize()
476 if (!drive->blk) { in floppy_drive_realize()
482 if (dev->unit >= MAX_FD) { in floppy_drive_realize()
484 "only %d units", dev->unit, MAX_FD); in floppy_drive_realize()
488 drive = get_drv(bus->fdc, dev->unit); in floppy_drive_realize()
489 if (drive->blk) { in floppy_drive_realize()
490 error_setg(errp, "Floppy unit %d is in use", dev->unit); in floppy_drive_realize()
494 if (!dev->conf.blk) { in floppy_drive_realize()
495 dev->conf.blk = blk_create_empty_drive(); in floppy_drive_realize()
496 ret = blk_attach_dev(dev->conf.blk, qdev); in floppy_drive_realize()
500 * read-only node later */ in floppy_drive_realize()
503 read_only = !blk_bs(dev->conf.blk) || in floppy_drive_realize()
504 !blk_supports_write_perm(dev->conf.blk); in floppy_drive_realize()
507 if (!blkconf_blocksizes(&dev->conf, errp)) { in floppy_drive_realize()
511 if (dev->conf.logical_block_size != 512 || in floppy_drive_realize()
512 dev->conf.physical_block_size != 512) in floppy_drive_realize()
522 dev->conf.rerror = BLOCKDEV_ON_ERROR_AUTO; in floppy_drive_realize()
523 dev->conf.werror = BLOCKDEV_ON_ERROR_AUTO; in floppy_drive_realize()
525 if (!blkconf_apply_backend_options(&dev->conf, read_only, false, errp)) { in floppy_drive_realize()
529 /* 'enospc' is the default for -drive, 'report' is what blk_new() gives us in floppy_drive_realize()
531 if (blk_get_on_error(dev->conf.blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC && in floppy_drive_realize()
532 blk_get_on_error(dev->conf.blk, 0) != BLOCKDEV_ON_ERROR_REPORT) { in floppy_drive_realize()
536 if (blk_get_on_error(dev->conf.blk, 1) != BLOCKDEV_ON_ERROR_REPORT) { in floppy_drive_realize()
541 drive->conf = &dev->conf; in floppy_drive_realize()
542 drive->blk = dev->conf.blk; in floppy_drive_realize()
543 drive->fdctrl = bus->fdc; in floppy_drive_realize()
546 blk_set_dev_ops(drive->blk, &fd_block_ops, drive); in floppy_drive_realize()
548 /* Keep 'type' qdev property and FDrive->drive in sync */ in floppy_drive_realize()
549 drive->drive = dev->type; in floppy_drive_realize()
551 dev->type = drive->drive; in floppy_drive_realize()
559 k->realize = floppy_drive_realize; in floppy_drive_class_init()
560 set_bit(DEVICE_CATEGORY_STORAGE, k->categories); in floppy_drive_class_init()
561 k->bus_type = TYPE_FLOPPY_BUS; in floppy_drive_class_init()
563 k->desc = "virtual floppy drive"; in floppy_drive_class_init()
653 FD_CONFIG_PRETRK = 0xff, /* Pre-compensation set to track 0 */
754 * Data transfers, either DMA or non-DMA. For non-DMA transfers, the FIFO
777 return drv->fdctrl->fallback; in get_fallback_drive_type()
809 retval = (uint32_t)(-1); in fdctrl_read()
848 return (drive->blk != NULL && drive->media_changed != 1); in fdrive_media_changed_needed()
876 return drive->perpendicular != 0; in fdrive_perpendicular_needed()
925 if (fdctrl->msr & FD_MSR_NONDMA) { in reconstruct_phase()
927 } else if ((fdctrl->msr & FD_MSR_RQM) == 0) { in reconstruct_phase()
928 /* qemu 2.3 disabled RQM only during DMA transfers */ in reconstruct_phase()
930 } else if (fdctrl->msr & FD_MSR_DIO) { in reconstruct_phase()
941 s->dor_vmstate = s->dor | GET_CUR_DRV(s); in fdc_pre_save()
949 s->phase = FD_PHASE_RECONSTRUCT; in fdc_pre_load()
957 SET_CUR_DRV(s, s->dor_vmstate & FD_DOR_SELMASK); in fdc_post_load()
958 s->dor = s->dor_vmstate & ~FD_DOR_SELMASK; in fdc_post_load()
960 if (s->phase == FD_PHASE_RECONSTRUCT) { in fdc_post_load()
961 s->phase = reconstruct_phase(s); in fdc_post_load()
971 return s->reset_sensei != 0; in fdc_reset_sensei_needed()
989 return timer_pending(s->result_timer); in fdc_result_timer_needed()
1007 return reconstruct_phase(fdctrl) != fdctrl->phase; in fdc_phase_needed()
1070 fdctrl->status0 = 0; in fdctrl_reset_irq()
1071 if (!(fdctrl->sra & FD_SRA_INTPEND)) in fdctrl_reset_irq()
1074 qemu_set_irq(fdctrl->irq, 0); in fdctrl_reset_irq()
1075 fdctrl->sra &= ~FD_SRA_INTPEND; in fdctrl_reset_irq()
1080 if (!(fdctrl->sra & FD_SRA_INTPEND)) { in fdctrl_raise_irq()
1081 qemu_set_irq(fdctrl->irq, 1); in fdctrl_raise_irq()
1082 fdctrl->sra |= FD_SRA_INTPEND; in fdctrl_raise_irq()
1085 fdctrl->reset_sensei = 0; in fdctrl_raise_irq()
1086 FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", fdctrl->status0); in fdctrl_raise_irq()
1097 fdctrl->sra = 0; in fdctrl_reset()
1098 fdctrl->srb = 0xc0; in fdctrl_reset()
1099 if (!fdctrl->drives[1].blk) { in fdctrl_reset()
1100 fdctrl->sra |= FD_SRA_nDRV2; in fdctrl_reset()
1102 fdctrl->cur_drv = 0; in fdctrl_reset()
1103 fdctrl->dor = FD_DOR_nRESET; in fdctrl_reset()
1104 fdctrl->dor |= (fdctrl->dma_chann != -1) ? FD_DOR_DMAEN : 0; in fdctrl_reset()
1105 fdctrl->msr = FD_MSR_RQM; in fdctrl_reset()
1106 fdctrl->reset_sensei = 0; in fdctrl_reset()
1107 timer_del(fdctrl->result_timer); in fdctrl_reset()
1109 fdctrl->data_pos = 0; in fdctrl_reset()
1110 fdctrl->data_len = 0; in fdctrl_reset()
1111 fdctrl->data_state = 0; in fdctrl_reset()
1112 fdctrl->data_dir = FD_DIR_WRITE; in fdctrl_reset()
1114 fd_recalibrate(&fdctrl->drives[i]); in fdctrl_reset()
1117 fdctrl->status0 |= FD_SR0_RDYCHG; in fdctrl_reset()
1119 fdctrl->reset_sensei = FD_RESET_SENSEI_COUNT; in fdctrl_reset()
1125 return &fdctrl->drives[(fdctrl->tdr & FD_TDR_BOOTSEL) >> 2]; in drv0()
1130 if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (1 << 2)) in drv1()
1131 return &fdctrl->drives[1]; in drv1()
1133 return &fdctrl->drives[0]; in drv1()
1139 if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (2 << 2)) in drv2()
1140 return &fdctrl->drives[2]; in drv2()
1142 return &fdctrl->drives[1]; in drv2()
1147 if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (3 << 2)) in drv3()
1148 return &fdctrl->drives[3]; in drv3()
1150 return &fdctrl->drives[2]; in drv3()
1169 FDrive *cur_drv = get_drv(fdctrl, fdctrl->cur_drv); in get_cur_drv()
1171 if (!cur_drv->blk) { in get_cur_drv()
1175 * API calls within this model (CVE-2021-20196). in get_cur_drv()
1179 cur_drv->blk = blk_create_empty_drive(); in get_cur_drv()
1184 /* Status A register : 0x00 (read-only) */
1187 uint32_t retval = fdctrl->sra; in fdctrl_read_statusA()
1194 /* Status B register : 0x01 (read-only) */
1197 uint32_t retval = fdctrl->srb; in fdctrl_read_statusB()
1207 uint32_t retval = fdctrl->dor; in fdctrl_read_dor()
1210 retval |= fdctrl->cur_drv; in fdctrl_read_dor()
1222 fdctrl->srb |= FD_SRB_MTR0; in fdctrl_write_dor()
1224 fdctrl->srb &= ~FD_SRB_MTR0; in fdctrl_write_dor()
1226 fdctrl->srb |= FD_SRB_MTR1; in fdctrl_write_dor()
1228 fdctrl->srb &= ~FD_SRB_MTR1; in fdctrl_write_dor()
1232 fdctrl->srb |= FD_SRB_DR0; in fdctrl_write_dor()
1234 fdctrl->srb &= ~FD_SRB_DR0; in fdctrl_write_dor()
1238 if (fdctrl->dor & FD_DOR_nRESET) { in fdctrl_write_dor()
1242 if (!(fdctrl->dor & FD_DOR_nRESET)) { in fdctrl_write_dor()
1245 fdctrl->dsr &= ~FD_DSR_PWRDOWN; in fdctrl_write_dor()
1249 fdctrl->cur_drv = value & FD_DOR_SELMASK; in fdctrl_write_dor()
1251 fdctrl->dor = value; in fdctrl_write_dor()
1257 uint32_t retval = fdctrl->tdr; in fdctrl_read_tape()
1267 if (!(fdctrl->dor & FD_DOR_nRESET)) { in fdctrl_write_tape()
1273 fdctrl->tdr = value & FD_TDR_BOOTSEL; in fdctrl_write_tape()
1280 uint32_t retval = fdctrl->msr; in fdctrl_read_main_status()
1282 fdctrl->dsr &= ~FD_DSR_PWRDOWN; in fdctrl_read_main_status()
1283 fdctrl->dor |= FD_DOR_nRESET; in fdctrl_read_main_status()
1294 if (!(fdctrl->dor & FD_DOR_nRESET)) { in fdctrl_write_rate()
1301 fdctrl->dor &= ~FD_DOR_nRESET; in fdctrl_write_rate()
1303 fdctrl->dor |= FD_DOR_nRESET; in fdctrl_write_rate()
1308 fdctrl->dsr = value; in fdctrl_write_rate()
1315 if (!(fdctrl->dor & FD_DOR_nRESET)) { in fdctrl_write_ccr()
1324 fdctrl->dsr = (fdctrl->dsr & ~FD_DSR_DRATEMASK) | in fdctrl_write_ccr()
1330 return drv->media_changed; in fdctrl_media_changed()
1333 /* Digital input register : 0x07 (read-only) */
1351 fdctrl->phase = FD_PHASE_COMMAND; in fdctrl_to_command_phase()
1352 fdctrl->data_dir = FD_DIR_WRITE; in fdctrl_to_command_phase()
1353 fdctrl->data_pos = 0; in fdctrl_to_command_phase()
1354 fdctrl->data_len = 1; /* Accept command byte, adjust for params later */ in fdctrl_to_command_phase()
1355 fdctrl->msr &= ~(FD_MSR_CMDBUSY | FD_MSR_DIO); in fdctrl_to_command_phase()
1356 fdctrl->msr |= FD_MSR_RQM; in fdctrl_to_command_phase()
1363 fdctrl->phase = FD_PHASE_RESULT; in fdctrl_to_result_phase()
1364 fdctrl->data_dir = FD_DIR_READ; in fdctrl_to_result_phase()
1365 fdctrl->data_len = fifo_len; in fdctrl_to_result_phase()
1366 fdctrl->data_pos = 0; in fdctrl_to_result_phase()
1367 fdctrl->msr |= FD_MSR_CMDBUSY | FD_MSR_RQM | FD_MSR_DIO; in fdctrl_to_result_phase()
1374 fdctrl->fifo[0]); in fdctrl_unimplemented()
1375 fdctrl->fifo[0] = FD_SR0_INVCMD; in fdctrl_unimplemented()
1386 cur_drv->head, cur_drv->track, cur_drv->sect, in fdctrl_seek_to_next_sect()
1388 /* XXX: cur_drv->sect >= cur_drv->last_sect should be an in fdctrl_seek_to_next_sect()
1390 uint8_t new_head = cur_drv->head; in fdctrl_seek_to_next_sect()
1391 uint8_t new_track = cur_drv->track; in fdctrl_seek_to_next_sect()
1392 uint8_t new_sect = cur_drv->sect; in fdctrl_seek_to_next_sect()
1396 if (new_sect >= cur_drv->last_sect || in fdctrl_seek_to_next_sect()
1397 new_sect == fdctrl->eot) { in fdctrl_seek_to_next_sect()
1399 if (FD_MULTI_TRACK(fdctrl->data_state)) { in fdctrl_seek_to_next_sect()
1401 (cur_drv->flags & FDISK_DBL_SIDES) != 0) { in fdctrl_seek_to_next_sect()
1406 fdctrl->status0 |= FD_SR0_SEEK; in fdctrl_seek_to_next_sect()
1407 if ((cur_drv->flags & FDISK_DBL_SIDES) == 0) { in fdctrl_seek_to_next_sect()
1412 fdctrl->status0 |= FD_SR0_SEEK; in fdctrl_seek_to_next_sect()
1434 fdctrl->status0 &= ~(FD_SR0_DS0 | FD_SR0_DS1 | FD_SR0_HEAD); in fdctrl_stop_transfer()
1435 fdctrl->status0 |= GET_CUR_DRV(fdctrl); in fdctrl_stop_transfer()
1436 if (cur_drv->head) { in fdctrl_stop_transfer()
1437 fdctrl->status0 |= FD_SR0_HEAD; in fdctrl_stop_transfer()
1439 fdctrl->status0 |= status0; in fdctrl_stop_transfer()
1442 status0, status1, status2, fdctrl->status0); in fdctrl_stop_transfer()
1443 fdctrl->fifo[0] = fdctrl->status0; in fdctrl_stop_transfer()
1444 fdctrl->fifo[1] = status1; in fdctrl_stop_transfer()
1445 fdctrl->fifo[2] = status2; in fdctrl_stop_transfer()
1446 fdctrl->fifo[3] = cur_drv->track; in fdctrl_stop_transfer()
1447 fdctrl->fifo[4] = cur_drv->head; in fdctrl_stop_transfer()
1448 fdctrl->fifo[5] = cur_drv->sect; in fdctrl_stop_transfer()
1449 fdctrl->fifo[6] = FD_SECTOR_SC; in fdctrl_stop_transfer()
1450 fdctrl->data_dir = FD_DIR_READ; in fdctrl_stop_transfer()
1451 if (fdctrl->dma_chann != -1 && !(fdctrl->msr & FD_MSR_NONDMA)) { in fdctrl_stop_transfer()
1452 IsaDmaClass *k = ISADMA_GET_CLASS(fdctrl->dma); in fdctrl_stop_transfer()
1453 k->release_DREQ(fdctrl->dma, fdctrl->dma_chann); in fdctrl_stop_transfer()
1455 fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO; in fdctrl_stop_transfer()
1456 fdctrl->msr &= ~FD_MSR_NONDMA; in fdctrl_stop_transfer()
1462 /* Prepare a data transfer (either DMA or FIFO) */
1468 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); in fdctrl_start_transfer()
1470 kt = fdctrl->fifo[2]; in fdctrl_start_transfer()
1471 kh = fdctrl->fifo[3]; in fdctrl_start_transfer()
1472 ks = fdctrl->fifo[4]; in fdctrl_start_transfer()
1475 fd_sector_calc(kh, kt, ks, cur_drv->last_sect, in fdctrl_start_transfer()
1477 switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & FD_CONFIG_EIS)) { in fdctrl_start_transfer()
1481 fdctrl->fifo[3] = kt; in fdctrl_start_transfer()
1482 fdctrl->fifo[4] = kh; in fdctrl_start_transfer()
1483 fdctrl->fifo[5] = ks; in fdctrl_start_transfer()
1488 fdctrl->fifo[3] = kt; in fdctrl_start_transfer()
1489 fdctrl->fifo[4] = kh; in fdctrl_start_transfer()
1490 fdctrl->fifo[5] = ks; in fdctrl_start_transfer()
1495 fdctrl->fifo[3] = kt; in fdctrl_start_transfer()
1496 fdctrl->fifo[4] = kh; in fdctrl_start_transfer()
1497 fdctrl->fifo[5] = ks; in fdctrl_start_transfer()
1500 fdctrl->status0 |= FD_SR0_SEEK; in fdctrl_start_transfer()
1508 if ((fdctrl->dsr & FD_DSR_DRATEMASK) != cur_drv->media_rate) { in fdctrl_start_transfer()
1510 fdctrl->dsr & FD_DSR_DRATEMASK, cur_drv->media_rate); in fdctrl_start_transfer()
1512 fdctrl->fifo[3] = kt; in fdctrl_start_transfer()
1513 fdctrl->fifo[4] = kh; in fdctrl_start_transfer()
1514 fdctrl->fifo[5] = ks; in fdctrl_start_transfer()
1519 fdctrl->data_dir = direction; in fdctrl_start_transfer()
1520 fdctrl->data_pos = 0; in fdctrl_start_transfer()
1521 assert(fdctrl->msr & FD_MSR_CMDBUSY); in fdctrl_start_transfer()
1522 if (fdctrl->fifo[0] & 0x80) in fdctrl_start_transfer()
1523 fdctrl->data_state |= FD_STATE_MULTI; in fdctrl_start_transfer()
1525 fdctrl->data_state &= ~FD_STATE_MULTI; in fdctrl_start_transfer()
1526 if (fdctrl->fifo[5] == 0) { in fdctrl_start_transfer()
1527 fdctrl->data_len = fdctrl->fifo[8]; in fdctrl_start_transfer()
1530 fdctrl->data_len = 128 << (fdctrl->fifo[5] > 7 ? 7 : fdctrl->fifo[5]); in fdctrl_start_transfer()
1531 tmp = (fdctrl->fifo[6] - ks + 1); in fdctrl_start_transfer()
1535 fdctrl->fifo[3] = kt; in fdctrl_start_transfer()
1536 fdctrl->fifo[4] = kh; in fdctrl_start_transfer()
1537 fdctrl->fifo[5] = ks; in fdctrl_start_transfer()
1540 if (fdctrl->fifo[0] & 0x80) in fdctrl_start_transfer()
1541 tmp += fdctrl->fifo[6]; in fdctrl_start_transfer()
1542 fdctrl->data_len *= tmp; in fdctrl_start_transfer()
1544 fdctrl->eot = fdctrl->fifo[6]; in fdctrl_start_transfer()
1545 if (fdctrl->dor & FD_DOR_DMAEN) { in fdctrl_start_transfer()
1546 /* DMA transfer is enabled. */ in fdctrl_start_transfer()
1547 IsaDmaClass *k = ISADMA_GET_CLASS(fdctrl->dma); in fdctrl_start_transfer()
1549 FLOPPY_DPRINTF("direction=%d (%d - %d)\n", in fdctrl_start_transfer()
1550 direction, (128 << fdctrl->fifo[5]) * in fdctrl_start_transfer()
1551 (cur_drv->last_sect - ks + 1), fdctrl->data_len); in fdctrl_start_transfer()
1553 /* No access is allowed until DMA transfer has completed */ in fdctrl_start_transfer()
1554 fdctrl->msr &= ~FD_MSR_RQM; in fdctrl_start_transfer()
1557 * Now, we just have to wait for the DMA controller to in fdctrl_start_transfer()
1560 k->hold_DREQ(fdctrl->dma, fdctrl->dma_chann); in fdctrl_start_transfer()
1561 k->schedule(fdctrl->dma); in fdctrl_start_transfer()
1564 fdctrl_transfer_handler(fdctrl, fdctrl->dma_chann, 0, in fdctrl_start_transfer()
1565 fdctrl->data_len); in fdctrl_start_transfer()
1569 FLOPPY_DPRINTF("start non-DMA transfer\n"); in fdctrl_start_transfer()
1570 fdctrl->msr |= FD_MSR_NONDMA | FD_MSR_RQM; in fdctrl_start_transfer()
1572 fdctrl->msr |= FD_MSR_DIO; in fdctrl_start_transfer()
1588 /* handlers for DMA transfers */
1598 if (fdctrl->msr & FD_MSR_RQM) { in fdctrl_transfer_handler()
1599 FLOPPY_DPRINTF("Not in DMA transfer mode !\n"); in fdctrl_transfer_handler()
1602 k = ISADMA_GET_CLASS(fdctrl->dma); in fdctrl_transfer_handler()
1604 if (fdctrl->data_dir == FD_DIR_SCANE || fdctrl->data_dir == FD_DIR_SCANL || in fdctrl_transfer_handler()
1605 fdctrl->data_dir == FD_DIR_SCANH) in fdctrl_transfer_handler()
1607 if (dma_len > fdctrl->data_len) in fdctrl_transfer_handler()
1608 dma_len = fdctrl->data_len; in fdctrl_transfer_handler()
1609 if (cur_drv->blk == NULL) { in fdctrl_transfer_handler()
1610 if (fdctrl->data_dir == FD_DIR_WRITE) in fdctrl_transfer_handler()
1617 rel_pos = fdctrl->data_pos % FD_SECTOR_LEN; in fdctrl_transfer_handler()
1618 for (start_pos = fdctrl->data_pos; fdctrl->data_pos < dma_len;) { in fdctrl_transfer_handler()
1619 len = dma_len - fdctrl->data_pos; in fdctrl_transfer_handler()
1621 len = FD_SECTOR_LEN - rel_pos; in fdctrl_transfer_handler()
1623 "(%d-0x%08x 0x%08x)\n", len, dma_len, fdctrl->data_pos, in fdctrl_transfer_handler()
1624 fdctrl->data_len, GET_CUR_DRV(fdctrl), cur_drv->head, in fdctrl_transfer_handler()
1625 cur_drv->track, cur_drv->sect, fd_sector(cur_drv), in fdctrl_transfer_handler()
1627 if (fdctrl->data_dir != FD_DIR_WRITE || in fdctrl_transfer_handler()
1630 if (blk_pread(cur_drv->blk, fd_offset(cur_drv), BDRV_SECTOR_SIZE, in fdctrl_transfer_handler()
1631 fdctrl->fifo, 0) < 0) { in fdctrl_transfer_handler()
1635 memset(fdctrl->fifo, 0, FD_SECTOR_LEN); in fdctrl_transfer_handler()
1638 switch (fdctrl->data_dir) { in fdctrl_transfer_handler()
1641 k->write_memory(fdctrl->dma, nchan, fdctrl->fifo + rel_pos, in fdctrl_transfer_handler()
1642 fdctrl->data_pos, len); in fdctrl_transfer_handler()
1646 if (cur_drv->ro) { in fdctrl_transfer_handler()
1647 /* Handle readonly medium early, no need to do DMA, touch the in fdctrl_transfer_handler()
1656 k->read_memory(fdctrl->dma, nchan, fdctrl->fifo + rel_pos, in fdctrl_transfer_handler()
1657 fdctrl->data_pos, len); in fdctrl_transfer_handler()
1658 if (blk_pwrite(cur_drv->blk, fd_offset(cur_drv), BDRV_SECTOR_SIZE, in fdctrl_transfer_handler()
1659 fdctrl->fifo, 0) < 0) { in fdctrl_transfer_handler()
1674 k->read_memory(fdctrl->dma, nchan, tmpbuf, fdctrl->data_pos, in fdctrl_transfer_handler()
1676 ret = memcmp(tmpbuf, fdctrl->fifo + rel_pos, len); in fdctrl_transfer_handler()
1681 if ((ret < 0 && fdctrl->data_dir == FD_DIR_SCANL) || in fdctrl_transfer_handler()
1682 (ret > 0 && fdctrl->data_dir == FD_DIR_SCANH)) { in fdctrl_transfer_handler()
1689 fdctrl->data_pos += len; in fdctrl_transfer_handler()
1690 rel_pos = fdctrl->data_pos % FD_SECTOR_LEN; in fdctrl_transfer_handler()
1698 len = fdctrl->data_pos - start_pos; in fdctrl_transfer_handler()
1700 fdctrl->data_pos, len, fdctrl->data_len); in fdctrl_transfer_handler()
1701 if (fdctrl->data_dir == FD_DIR_SCANE || in fdctrl_transfer_handler()
1702 fdctrl->data_dir == FD_DIR_SCANL || in fdctrl_transfer_handler()
1703 fdctrl->data_dir == FD_DIR_SCANH) in fdctrl_transfer_handler()
1705 fdctrl->data_len -= len; in fdctrl_transfer_handler()
1720 fdctrl->dsr &= ~FD_DSR_PWRDOWN; in fdctrl_read_data()
1721 if (!(fdctrl->msr & FD_MSR_RQM) || !(fdctrl->msr & FD_MSR_DIO)) { in fdctrl_read_data()
1727 * wraps around while fdctrl->data_pos is the real position in the whole in fdctrl_read_data()
1729 pos = fdctrl->data_pos; in fdctrl_read_data()
1732 switch (fdctrl->phase) { in fdctrl_read_data()
1734 assert(fdctrl->msr & FD_MSR_NONDMA); in fdctrl_read_data()
1736 if (fdctrl->data_pos != 0) in fdctrl_read_data()
1742 if (blk_pread(cur_drv->blk, fd_offset(cur_drv), BDRV_SECTOR_SIZE, in fdctrl_read_data()
1743 fdctrl->fifo, 0) in fdctrl_read_data()
1748 memset(fdctrl->fifo, 0, FD_SECTOR_LEN); in fdctrl_read_data()
1752 if (++fdctrl->data_pos == fdctrl->data_len) { in fdctrl_read_data()
1753 fdctrl->msr &= ~FD_MSR_RQM; in fdctrl_read_data()
1759 assert(!(fdctrl->msr & FD_MSR_NONDMA)); in fdctrl_read_data()
1760 if (++fdctrl->data_pos == fdctrl->data_len) { in fdctrl_read_data()
1761 fdctrl->msr &= ~FD_MSR_RQM; in fdctrl_read_data()
1772 retval = fdctrl->fifo[pos]; in fdctrl_read_data()
1783 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); in fdctrl_format_sector()
1785 kt = fdctrl->fifo[6]; in fdctrl_format_sector()
1786 kh = fdctrl->fifo[7]; in fdctrl_format_sector()
1787 ks = fdctrl->fifo[8]; in fdctrl_format_sector()
1790 fd_sector_calc(kh, kt, ks, cur_drv->last_sect, in fdctrl_format_sector()
1792 switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & FD_CONFIG_EIS)) { in fdctrl_format_sector()
1796 fdctrl->fifo[3] = kt; in fdctrl_format_sector()
1797 fdctrl->fifo[4] = kh; in fdctrl_format_sector()
1798 fdctrl->fifo[5] = ks; in fdctrl_format_sector()
1803 fdctrl->fifo[3] = kt; in fdctrl_format_sector()
1804 fdctrl->fifo[4] = kh; in fdctrl_format_sector()
1805 fdctrl->fifo[5] = ks; in fdctrl_format_sector()
1810 fdctrl->fifo[3] = kt; in fdctrl_format_sector()
1811 fdctrl->fifo[4] = kh; in fdctrl_format_sector()
1812 fdctrl->fifo[5] = ks; in fdctrl_format_sector()
1815 fdctrl->status0 |= FD_SR0_SEEK; in fdctrl_format_sector()
1820 memset(fdctrl->fifo, 0, FD_SECTOR_LEN); in fdctrl_format_sector()
1821 if (cur_drv->blk == NULL || in fdctrl_format_sector()
1822 blk_pwrite(cur_drv->blk, fd_offset(cur_drv), BDRV_SECTOR_SIZE, in fdctrl_format_sector()
1823 fdctrl->fifo, 0) < 0) { in fdctrl_format_sector()
1827 if (cur_drv->sect == cur_drv->last_sect) { in fdctrl_format_sector()
1828 fdctrl->data_state &= ~FD_STATE_FORMAT; in fdctrl_format_sector()
1833 fdctrl->data_pos = 0; in fdctrl_format_sector()
1834 fdctrl->data_len = 4; in fdctrl_format_sector()
1841 fdctrl->lock = (fdctrl->fifo[0] & 0x80) ? 1 : 0; in fdctrl_handle_lock()
1842 fdctrl->fifo[0] = fdctrl->lock << 4; in fdctrl_handle_lock()
1851 fdctrl->fifo[0] = drv0(fdctrl)->track; in fdctrl_handle_dumpreg()
1852 fdctrl->fifo[1] = drv1(fdctrl)->track; in fdctrl_handle_dumpreg()
1854 fdctrl->fifo[2] = drv2(fdctrl)->track; in fdctrl_handle_dumpreg()
1855 fdctrl->fifo[3] = drv3(fdctrl)->track; in fdctrl_handle_dumpreg()
1857 fdctrl->fifo[2] = 0; in fdctrl_handle_dumpreg()
1858 fdctrl->fifo[3] = 0; in fdctrl_handle_dumpreg()
1861 fdctrl->fifo[4] = fdctrl->timer0; in fdctrl_handle_dumpreg()
1862 fdctrl->fifo[5] = (fdctrl->timer1 << 1) | (fdctrl->dor & FD_DOR_DMAEN ? 1 : 0); in fdctrl_handle_dumpreg()
1863 fdctrl->fifo[6] = cur_drv->last_sect; in fdctrl_handle_dumpreg()
1864 fdctrl->fifo[7] = (fdctrl->lock << 7) | in fdctrl_handle_dumpreg()
1865 (cur_drv->perpendicular << 2); in fdctrl_handle_dumpreg()
1866 fdctrl->fifo[8] = fdctrl->config; in fdctrl_handle_dumpreg()
1867 fdctrl->fifo[9] = fdctrl->precomp_trk; in fdctrl_handle_dumpreg()
1874 fdctrl->fifo[0] = fdctrl->version; in fdctrl_handle_version()
1880 fdctrl->fifo[0] = 0x41; /* Stepping 1 */ in fdctrl_handle_partid()
1889 drv0(fdctrl)->track = fdctrl->fifo[3]; in fdctrl_handle_restore()
1890 drv1(fdctrl)->track = fdctrl->fifo[4]; in fdctrl_handle_restore()
1892 drv2(fdctrl)->track = fdctrl->fifo[5]; in fdctrl_handle_restore()
1893 drv3(fdctrl)->track = fdctrl->fifo[6]; in fdctrl_handle_restore()
1896 fdctrl->timer0 = fdctrl->fifo[7]; in fdctrl_handle_restore()
1897 fdctrl->timer1 = fdctrl->fifo[8]; in fdctrl_handle_restore()
1898 cur_drv->last_sect = fdctrl->fifo[9]; in fdctrl_handle_restore()
1899 fdctrl->lock = fdctrl->fifo[10] >> 7; in fdctrl_handle_restore()
1900 cur_drv->perpendicular = (fdctrl->fifo[10] >> 2) & 0xF; in fdctrl_handle_restore()
1901 fdctrl->config = fdctrl->fifo[11]; in fdctrl_handle_restore()
1902 fdctrl->precomp_trk = fdctrl->fifo[12]; in fdctrl_handle_restore()
1903 fdctrl->pwrd = fdctrl->fifo[13]; in fdctrl_handle_restore()
1911 fdctrl->fifo[0] = 0; in fdctrl_handle_save()
1912 fdctrl->fifo[1] = 0; in fdctrl_handle_save()
1914 fdctrl->fifo[2] = drv0(fdctrl)->track; in fdctrl_handle_save()
1915 fdctrl->fifo[3] = drv1(fdctrl)->track; in fdctrl_handle_save()
1917 fdctrl->fifo[4] = drv2(fdctrl)->track; in fdctrl_handle_save()
1918 fdctrl->fifo[5] = drv3(fdctrl)->track; in fdctrl_handle_save()
1920 fdctrl->fifo[4] = 0; in fdctrl_handle_save()
1921 fdctrl->fifo[5] = 0; in fdctrl_handle_save()
1924 fdctrl->fifo[6] = fdctrl->timer0; in fdctrl_handle_save()
1925 fdctrl->fifo[7] = fdctrl->timer1; in fdctrl_handle_save()
1926 fdctrl->fifo[8] = cur_drv->last_sect; in fdctrl_handle_save()
1927 fdctrl->fifo[9] = (fdctrl->lock << 7) | in fdctrl_handle_save()
1928 (cur_drv->perpendicular << 2); in fdctrl_handle_save()
1929 fdctrl->fifo[10] = fdctrl->config; in fdctrl_handle_save()
1930 fdctrl->fifo[11] = fdctrl->precomp_trk; in fdctrl_handle_save()
1931 fdctrl->fifo[12] = fdctrl->pwrd; in fdctrl_handle_save()
1932 fdctrl->fifo[13] = 0; in fdctrl_handle_save()
1933 fdctrl->fifo[14] = 0; in fdctrl_handle_save()
1941 cur_drv->head = (fdctrl->fifo[1] >> 2) & 1; in fdctrl_handle_readid()
1942 timer_mod(fdctrl->result_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + in fdctrl_handle_readid()
1950 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); in fdctrl_handle_format_track()
1952 fdctrl->data_state |= FD_STATE_FORMAT; in fdctrl_handle_format_track()
1953 if (fdctrl->fifo[0] & 0x80) in fdctrl_handle_format_track()
1954 fdctrl->data_state |= FD_STATE_MULTI; in fdctrl_handle_format_track()
1956 fdctrl->data_state &= ~FD_STATE_MULTI; in fdctrl_handle_format_track()
1957 cur_drv->bps = in fdctrl_handle_format_track()
1958 fdctrl->fifo[2] > 7 ? 16384 : 128 << fdctrl->fifo[2]; in fdctrl_handle_format_track()
1960 cur_drv->last_sect = in fdctrl_handle_format_track()
1961 cur_drv->flags & FDISK_DBL_SIDES ? fdctrl->fifo[3] : in fdctrl_handle_format_track()
1962 fdctrl->fifo[3] / 2; in fdctrl_handle_format_track()
1964 cur_drv->last_sect = fdctrl->fifo[3]; in fdctrl_handle_format_track()
1966 /* TODO: implement format using DMA expected by the Bochs BIOS in fdctrl_handle_format_track()
1967 * and Linux fdformat (read 3 bytes per sector via DMA and fill in fdctrl_handle_format_track()
1970 fdctrl->data_state &= ~FD_STATE_FORMAT; in fdctrl_handle_format_track()
1976 fdctrl->timer0 = (fdctrl->fifo[1] >> 4) & 0xF; in fdctrl_handle_specify()
1977 fdctrl->timer1 = fdctrl->fifo[2] >> 1; in fdctrl_handle_specify()
1978 if (fdctrl->fifo[2] & 1) in fdctrl_handle_specify()
1979 fdctrl->dor &= ~FD_DOR_DMAEN; in fdctrl_handle_specify()
1981 fdctrl->dor |= FD_DOR_DMAEN; in fdctrl_handle_specify()
1990 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); in fdctrl_handle_sense_drive_status()
1992 cur_drv->head = (fdctrl->fifo[1] >> 2) & 1; in fdctrl_handle_sense_drive_status()
1994 fdctrl->fifo[0] = (cur_drv->ro << 6) | in fdctrl_handle_sense_drive_status()
1995 (cur_drv->track == 0 ? 0x10 : 0x00) | in fdctrl_handle_sense_drive_status()
1996 (cur_drv->head << 2) | in fdctrl_handle_sense_drive_status()
2006 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); in fdctrl_handle_recalibrate()
2011 fdctrl->status0 |= FD_SR0_SEEK; in fdctrl_handle_recalibrate()
2019 if (fdctrl->reset_sensei > 0) { in fdctrl_handle_sense_interrupt_status()
2020 fdctrl->fifo[0] = in fdctrl_handle_sense_interrupt_status()
2021 FD_SR0_RDYCHG + FD_RESET_SENSEI_COUNT - fdctrl->reset_sensei; in fdctrl_handle_sense_interrupt_status()
2022 fdctrl->reset_sensei--; in fdctrl_handle_sense_interrupt_status()
2023 } else if (!(fdctrl->sra & FD_SRA_INTPEND)) { in fdctrl_handle_sense_interrupt_status()
2024 fdctrl->fifo[0] = FD_SR0_INVCMD; in fdctrl_handle_sense_interrupt_status()
2028 fdctrl->fifo[0] = in fdctrl_handle_sense_interrupt_status()
2029 (fdctrl->status0 & ~(FD_SR0_HEAD | FD_SR0_DS1 | FD_SR0_DS0)) in fdctrl_handle_sense_interrupt_status()
2033 fdctrl->fifo[1] = cur_drv->track; in fdctrl_handle_sense_interrupt_status()
2036 fdctrl->status0 = FD_SR0_RDYCHG; in fdctrl_handle_sense_interrupt_status()
2043 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); in fdctrl_handle_seek()
2049 fd_seek(cur_drv, cur_drv->head, fdctrl->fifo[2], cur_drv->sect, 1); in fdctrl_handle_seek()
2051 fdctrl->status0 |= FD_SR0_SEEK; in fdctrl_handle_seek()
2059 if (fdctrl->fifo[1] & 0x80) in fdctrl_handle_perpendicular_mode()
2060 cur_drv->perpendicular = fdctrl->fifo[1] & 0x7; in fdctrl_handle_perpendicular_mode()
2067 fdctrl->config = fdctrl->fifo[2]; in fdctrl_handle_configure()
2068 fdctrl->precomp_trk = fdctrl->fifo[3]; in fdctrl_handle_configure()
2075 fdctrl->pwrd = fdctrl->fifo[1]; in fdctrl_handle_powerdown_mode()
2076 fdctrl->fifo[0] = fdctrl->fifo[1]; in fdctrl_handle_powerdown_mode()
2091 pos = fdctrl->data_pos - 1; in fdctrl_handle_drive_specification_command()
2093 if (fdctrl->fifo[pos] & 0x80) { in fdctrl_handle_drive_specification_command()
2095 if (fdctrl->fifo[pos] & 0x40) { in fdctrl_handle_drive_specification_command()
2096 fdctrl->fifo[0] = fdctrl->fifo[1]; in fdctrl_handle_drive_specification_command()
2097 fdctrl->fifo[2] = 0; in fdctrl_handle_drive_specification_command()
2098 fdctrl->fifo[3] = 0; in fdctrl_handle_drive_specification_command()
2103 } else if (fdctrl->data_len > 7) { in fdctrl_handle_drive_specification_command()
2105 fdctrl->fifo[0] = 0x80 | in fdctrl_handle_drive_specification_command()
2106 (cur_drv->head << 2) | GET_CUR_DRV(fdctrl); in fdctrl_handle_drive_specification_command()
2115 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); in fdctrl_handle_relative_seek_in()
2117 if (fdctrl->fifo[2] + cur_drv->track >= cur_drv->max_track) { in fdctrl_handle_relative_seek_in()
2118 fd_seek(cur_drv, cur_drv->head, cur_drv->max_track - 1, in fdctrl_handle_relative_seek_in()
2119 cur_drv->sect, 1); in fdctrl_handle_relative_seek_in()
2121 fd_seek(cur_drv, cur_drv->head, in fdctrl_handle_relative_seek_in()
2122 cur_drv->track + fdctrl->fifo[2], cur_drv->sect, 1); in fdctrl_handle_relative_seek_in()
2126 fdctrl->status0 |= FD_SR0_SEEK; in fdctrl_handle_relative_seek_in()
2134 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); in fdctrl_handle_relative_seek_out()
2136 if (fdctrl->fifo[2] > cur_drv->track) { in fdctrl_handle_relative_seek_out()
2137 fd_seek(cur_drv, cur_drv->head, 0, cur_drv->sect, 1); in fdctrl_handle_relative_seek_out()
2139 fd_seek(cur_drv, cur_drv->head, in fdctrl_handle_relative_seek_out()
2140 cur_drv->track - fdctrl->fifo[2], cur_drv->sect, 1); in fdctrl_handle_relative_seek_out()
2144 fdctrl->status0 |= FD_SR0_SEEK; in fdctrl_handle_relative_seek_out()
2213 if (!(fdctrl->dor & FD_DOR_nRESET)) { in fdctrl_write_data()
2217 if (!(fdctrl->msr & FD_MSR_RQM) || (fdctrl->msr & FD_MSR_DIO)) { in fdctrl_write_data()
2221 fdctrl->dsr &= ~FD_DSR_PWRDOWN; in fdctrl_write_data()
2226 * wraps around while fdctrl->data_pos is the real position in the whole in fdctrl_write_data()
2228 pos = fdctrl->data_pos++; in fdctrl_write_data()
2230 fdctrl->fifo[pos] = value; in fdctrl_write_data()
2232 if (fdctrl->data_pos == fdctrl->data_len) { in fdctrl_write_data()
2233 fdctrl->msr &= ~FD_MSR_RQM; in fdctrl_write_data()
2236 switch (fdctrl->phase) { in fdctrl_write_data()
2238 /* For DMA requests, RQM should be cleared during execution phase, so in fdctrl_write_data()
2240 assert(fdctrl->msr & FD_MSR_NONDMA); in fdctrl_write_data()
2243 if (pos == FD_SECTOR_LEN - 1 || in fdctrl_write_data()
2244 fdctrl->data_pos == fdctrl->data_len) { in fdctrl_write_data()
2246 if (blk_pwrite(cur_drv->blk, fd_offset(cur_drv), BDRV_SECTOR_SIZE, in fdctrl_write_data()
2247 fdctrl->fifo, 0) < 0) { in fdctrl_write_data()
2260 if (fdctrl->data_pos == fdctrl->data_len) { in fdctrl_write_data()
2266 assert(!(fdctrl->msr & FD_MSR_NONDMA)); in fdctrl_write_data()
2267 assert(fdctrl->data_pos < FD_SECTOR_LEN); in fdctrl_write_data()
2273 fdctrl->data_len = cmd->parameters + 1; in fdctrl_write_data()
2274 if (cmd->parameters) { in fdctrl_write_data()
2275 fdctrl->msr |= FD_MSR_RQM; in fdctrl_write_data()
2277 fdctrl->msr |= FD_MSR_CMDBUSY; in fdctrl_write_data()
2280 if (fdctrl->data_pos == fdctrl->data_len) { in fdctrl_write_data()
2282 fdctrl->phase = FD_PHASE_EXECUTION; in fdctrl_write_data()
2284 if (fdctrl->data_state & FD_STATE_FORMAT) { in fdctrl_write_data()
2289 cmd = get_command(fdctrl->fifo[0]); in fdctrl_write_data()
2290 FLOPPY_DPRINTF("Calling handler for '%s'\n", cmd->name); in fdctrl_write_data()
2291 cmd->handler(fdctrl, cmd->direction); in fdctrl_write_data()
2310 if (cur_drv->last_sect != 0) { in fdctrl_result_timer()
2311 cur_drv->sect = (cur_drv->sect % cur_drv->last_sect) + 1; in fdctrl_result_timer()
2314 if ((fdctrl->dsr & FD_DSR_DRATEMASK) != cur_drv->media_rate) { in fdctrl_result_timer()
2316 fdctrl->dsr & FD_DSR_DRATEMASK, cur_drv->media_rate); in fdctrl_result_timer()
2334 qdev_prop_set_enum(dev, "drive-type", FLOPPY_DRIVE_TYPE_AUTO); in fdctrl_init_drives()
2337 qdev_realize_and_unref(dev, &bus->bus, &error_fatal); in fdctrl_init_drives()
2348 if (fdctrl->fallback == FLOPPY_DRIVE_TYPE_AUTO) { in fdctrl_realize_common()
2356 for (i = ARRAY_SIZE(handlers) - 1; i >= 0; i--) { in fdctrl_realize_common()
2366 fdctrl->fifo = qemu_memalign(512, FD_SECTOR_LEN); in fdctrl_realize_common()
2367 memset(fdctrl->fifo, 0, FD_SECTOR_LEN); in fdctrl_realize_common()
2368 fdctrl->fifo_size = 512; in fdctrl_realize_common()
2369 fdctrl->result_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, in fdctrl_realize_common()
2372 fdctrl->version = 0x90; /* Intel 82078 controller */ in fdctrl_realize_common()
2373 fdctrl->config = FD_CONFIG_EIS | FD_CONFIG_EFIFO; /* Implicit seek, polling & FIFO enabled */ in fdctrl_realize_common()
2374 fdctrl->num_floppies = MAX_FD; in fdctrl_realize_common()
2376 floppy_bus_create(fdctrl, &fdctrl->bus, dev); in fdctrl_realize_common()
2379 drive = &fdctrl->drives[i]; in fdctrl_realize_common()
2380 drive->fdctrl = fdctrl; in fdctrl_realize_common()