Lines Matching defs:fdctrl

101 #define GET_CUR_DRV(fdctrl) ((fdctrl)->cur_drv)
102 #define SET_CUR_DRV(fdctrl, drive) ((fdctrl)->cur_drv = (drive))
505 static void fdctrl_reset(fdctrl_t *fdctrl, int do_irq);
506 static void fdctrl_reset_fifo(fdctrl_t *fdctrl);
517 static void fdctrl_raise_irq(fdctrl_t *fdctrl, uint8_t status0);
518 static fdrive_t *get_cur_drv(fdctrl_t *fdctrl);
521 static uint32_t fdctrl_read_statusA(fdctrl_t *fdctrl);
522 static uint32_t fdctrl_read_statusB(fdctrl_t *fdctrl);
523 static uint32_t fdctrl_read_dor(fdctrl_t *fdctrl);
524 static void fdctrl_write_dor(fdctrl_t *fdctrl, uint32_t value);
525 static uint32_t fdctrl_read_tape(fdctrl_t *fdctrl);
526 static void fdctrl_write_tape(fdctrl_t *fdctrl, uint32_t value);
527 static uint32_t fdctrl_read_main_status(fdctrl_t *fdctrl);
528 static void fdctrl_write_rate(fdctrl_t *fdctrl, uint32_t value);
529 static uint32_t fdctrl_read_data(fdctrl_t *fdctrl);
530 static void fdctrl_write_data(fdctrl_t *fdctrl, uint32_t value);
531 static uint32_t fdctrl_read_dir(fdctrl_t *fdctrl);
532 static void fdctrl_write_ccr(fdctrl_t *fdctrl, uint32_t value);
699 fdctrl_t *fdctrl;
764 fdctrl_t *fdctrl = (fdctrl_t *)opaque;
769 retval = fdctrl_read_statusA(fdctrl);
772 retval = fdctrl_read_statusB(fdctrl);
775 retval = fdctrl_read_dor(fdctrl);
778 retval = fdctrl_read_tape(fdctrl);
781 retval = fdctrl_read_main_status(fdctrl);
784 retval = fdctrl_read_data(fdctrl);
787 retval = fdctrl_read_dir(fdctrl);
800 fdctrl_t *fdctrl = (fdctrl_t *)opaque;
806 fdctrl_write_dor(fdctrl, value);
809 fdctrl_write_tape(fdctrl, value);
812 fdctrl_write_rate(fdctrl, value);
815 fdctrl_write_data(fdctrl, value);
818 fdctrl_write_ccr(fdctrl, value);
826 static void fdctrl_reset_irq(fdctrl_t *fdctrl)
828 if (!(fdctrl->sra & FD_SRA_INTPEND))
832 PDMDevHlpISASetIrq (fdctrl->pDevIns, fdctrl->irq_lvl, 0);
834 qemu_set_irq(fdctrl->irq, 0);
836 fdctrl->sra &= ~FD_SRA_INTPEND;
839 static void fdctrl_raise_irq(fdctrl_t *fdctrl, uint8_t status0)
841 if (!(fdctrl->sra & FD_SRA_INTPEND)) {
844 PDMDevHlpISASetIrq (fdctrl->pDevIns, fdctrl->irq_lvl, 1);
846 qemu_set_irq(fdctrl->irq, 1);
848 fdctrl->sra |= FD_SRA_INTPEND;
854 cur_drv = get_cur_drv(fdctrl);
859 fdctrl->reset_sensei = 0;
860 fdctrl->status0 = status0;
861 FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", fdctrl->status0);
865 static void fdctrl_reset(fdctrl_t *fdctrl, int do_irq)
870 fdctrl_reset_irq(fdctrl);
872 fdctrl->sra = 0;
873 fdctrl->srb = 0xc0;
875 if (!fdctrl->drives[1].pDrvBlock)
877 if (!fdctrl->drives[1].bs)
879 fdctrl->sra |= FD_SRA_nDRV2;
880 fdctrl->cur_drv = 0;
881 fdctrl->dor = FD_DOR_nRESET;
882 fdctrl->dor |= (fdctrl->dma_chann != 0xff) ? FD_DOR_DMAEN : 0;
883 fdctrl->msr = FD_MSR_RQM;
885 fdctrl->data_pos = 0;
886 fdctrl->data_len = 0;
887 fdctrl->data_state = 0;
888 fdctrl->data_dir = FD_DIR_WRITE;
890 fd_recalibrate(&fdctrl->drives[i]);
891 fdctrl_reset_fifo(fdctrl);
893 fdctrl_raise_irq(fdctrl, FD_SR0_RDYCHG);
894 fdctrl->reset_sensei = FD_RESET_SENSEI_COUNT;
898 static inline fdrive_t *drv0(fdctrl_t *fdctrl)
900 return &fdctrl->drives[(fdctrl->tdr & FD_TDR_BOOTSEL) >> 2];
903 static inline fdrive_t *drv1(fdctrl_t *fdctrl)
905 if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (1 << 2))
906 return &fdctrl->drives[1];
908 return &fdctrl->drives[0];
912 static inline fdrive_t *drv2(fdctrl_t *fdctrl)
914 if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (2 << 2))
915 return &fdctrl->drives[2];
917 return &fdctrl->drives[1];
920 static inline fdrive_t *drv3(fdctrl_t *fdctrl)
922 if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (3 << 2))
923 return &fdctrl->drives[3];
925 return &fdctrl->drives[2];
929 static fdrive_t *get_cur_drv(fdctrl_t *fdctrl)
931 switch (fdctrl->cur_drv) {
932 case 0: return drv0(fdctrl);
933 case 1: return drv1(fdctrl);
935 case 2: return drv2(fdctrl);
936 case 3: return drv3(fdctrl);
943 static uint32_t fdctrl_read_statusA(fdctrl_t *fdctrl)
945 uint32_t retval = fdctrl->sra;
953 static uint32_t fdctrl_read_statusB(fdctrl_t *fdctrl)
955 uint32_t retval = fdctrl->srb;
963 static uint32_t fdctrl_read_dor(fdctrl_t *fdctrl)
965 uint32_t retval = fdctrl->dor;
968 retval |= fdctrl->cur_drv;
974 static void fdctrl_write_dor(fdctrl_t *fdctrl, uint32_t value)
980 fdctrl->srb |= FD_SRB_MTR0;
982 fdctrl->srb &= ~FD_SRB_MTR0;
984 fdctrl->srb |= FD_SRB_MTR1;
986 fdctrl->srb &= ~FD_SRB_MTR1;
990 fdctrl->srb |= FD_SRB_DR0;
992 fdctrl->srb &= ~FD_SRB_DR0;
996 if (fdctrl->dor & FD_DOR_nRESET) {
1000 if (!(fdctrl->dor & FD_DOR_nRESET)) {
1002 fdctrl_reset(fdctrl, 1);
1003 fdctrl->dsr &= ~FD_DSR_PWRDOWN;
1007 fdctrl->cur_drv = value & FD_DOR_SELMASK;
1009 fdctrl->dor = value;
1013 static uint32_t fdctrl_read_tape(fdctrl_t *fdctrl)
1015 uint32_t retval = fdctrl->tdr;
1022 static void fdctrl_write_tape(fdctrl_t *fdctrl, uint32_t value)
1025 if (!(fdctrl->dor & FD_DOR_nRESET)) {
1031 fdctrl->tdr = value & FD_TDR_BOOTSEL;
1036 static uint32_t fdctrl_read_main_status(fdctrl_t *fdctrl)
1038 uint32_t retval = fdctrl->msr;
1040 fdctrl->dsr &= ~FD_DSR_PWRDOWN;
1041 fdctrl->dor |= FD_DOR_nRESET;
1049 static void fdctrl_write_rate(fdctrl_t *fdctrl, uint32_t value)
1052 if (!(fdctrl->dor & FD_DOR_nRESET)) {
1059 fdctrl->dor &= ~FD_DOR_nRESET;
1060 fdctrl_reset(fdctrl, 1);
1061 fdctrl->dor |= FD_DOR_nRESET;
1064 fdctrl_reset(fdctrl, 1);
1066 fdctrl->dsr = value;
1070 static void fdctrl_write_ccr(fdctrl_t *fdctrl, uint32_t value)
1073 if (!(fdctrl->dor & FD_DOR_nRESET)) {
1082 fdctrl->dsr = (fdctrl->dsr & ~FD_DSR_DRATEMASK) | (value & FD_DSR_DRATEMASK);
1103 static uint32_t fdctrl_read_dir(fdctrl_t *fdctrl)
1112 if (fdctrl_media_changed(get_cur_drv(fdctrl))
1113 && (fdctrl->dor & (0x10 << fdctrl->cur_drv)))
1115 if (fdctrl_media_changed(drv0(fdctrl))
1116 || fdctrl_media_changed(drv1(fdctrl))
1118 || fdctrl_media_changed(drv2(fdctrl))
1119 || fdctrl_media_changed(drv3(fdctrl))
1131 static void fdctrl_reset_fifo(fdctrl_t *fdctrl)
1133 fdctrl->data_dir = FD_DIR_WRITE;
1134 fdctrl->data_pos = 0;
1135 fdctrl->msr &= ~(FD_MSR_CMDBUSY | FD_MSR_DIO);
1139 static void fdctrl_set_fifo(fdctrl_t *fdctrl, int fifo_len, int do_irq)
1141 fdctrl->data_dir = FD_DIR_READ;
1142 fdctrl->data_len = fifo_len;
1143 fdctrl->data_pos = 0;
1144 fdctrl->msr |= FD_MSR_CMDBUSY | FD_MSR_RQM | FD_MSR_DIO;
1146 fdctrl_raise_irq(fdctrl, 0x00);
1150 static void fdctrl_unimplemented(fdctrl_t *fdctrl, int direction)
1152 FLOPPY_ERROR("unimplemented command 0x%02x\n", fdctrl->fifo[0]);
1153 fdctrl->fifo[0] = FD_SR0_INVCMD;
1154 fdctrl_set_fifo(fdctrl, 1, 0);
1158 static int fdctrl_seek_to_next_sect(fdctrl_t *fdctrl, fdrive_t *cur_drv)
1166 cur_drv->sect == fdctrl->eot) {
1168 if (FD_MULTI_TRACK(fdctrl->data_state)) {
1192 static void fdctrl_stop_transfer(fdctrl_t *fdctrl, uint8_t status0,
1197 cur_drv = get_cur_drv(fdctrl);
1200 status0 | (cur_drv->head << 2) | GET_CUR_DRV(fdctrl));
1201 fdctrl->fifo[0] = status0 | (cur_drv->head << 2) | GET_CUR_DRV(fdctrl);
1202 fdctrl->fifo[1] = status1;
1203 fdctrl->fifo[2] = status2;
1204 fdctrl->fifo[3] = cur_drv->ltrk;
1205 fdctrl->fifo[4] = cur_drv->head;
1206 fdctrl->fifo[5] = cur_drv->sect;
1207 fdctrl->fifo[6] = FD_SECTOR_SC;
1209 fdctrl->fifo[0], fdctrl->fifo[1], fdctrl->fifo[2], fdctrl->fifo[3],
1210 fdctrl->fifo[4], fdctrl->fifo[5], fdctrl->fifo[6]);
1212 fdctrl->data_dir = FD_DIR_READ;
1213 if (!(fdctrl->msr & FD_MSR_NONDMA)) {
1215 PDMDevHlpDMASetDREQ (fdctrl->pDevIns, fdctrl->dma_chann, 0);
1217 DMA_release_DREQ(fdctrl->dma_chann);
1220 fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO;
1221 fdctrl->msr &= ~FD_MSR_NONDMA;
1222 fdctrl_set_fifo(fdctrl, 7, 1);
1226 static void fdctrl_start_transfer(fdctrl_t *fdctrl, int direction)
1232 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
1233 cur_drv = get_cur_drv(fdctrl);
1234 kt = fdctrl->fifo[2];
1235 kh = fdctrl->fifo[3];
1236 ks = fdctrl->fifo[4];
1238 GET_CUR_DRV(fdctrl), kh, kt, ks,
1241 fdctrl->fifo[0], fdctrl->fifo[1], fdctrl->fifo[2],
1242 fdctrl->fifo[3], fdctrl->fifo[4], fdctrl->fifo[5],
1243 fdctrl->fifo[6], fdctrl->fifo[7], fdctrl->fifo[8]);
1244 switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & FD_CONFIG_EIS)) {
1247 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
1248 fdctrl->fifo[3] = kt;
1249 fdctrl->fifo[4] = kh;
1250 fdctrl->fifo[5] = ks;
1254 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_EC, 0x00);
1255 fdctrl->fifo[3] = kt;
1256 fdctrl->fifo[4] = kh;
1257 fdctrl->fifo[5] = ks;
1261 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
1262 fdctrl->fifo[3] = kt;
1263 fdctrl->fifo[4] = kh;
1264 fdctrl->fifo[5] = ks;
1276 if ((fdctrl->dsr & FD_DSR_DRATEMASK) != cur_drv->media_rate) {
1278 fdctrl->dsr & FD_DSR_DRATEMASK, cur_drv->media_rate);
1279 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA, FD_SR2_MD);
1280 fdctrl->fifo[3] = kt;
1281 fdctrl->fifo[4] = kh;
1282 fdctrl->fifo[5] = ks;
1287 fdctrl->data_dir = direction;
1288 fdctrl->data_pos = 0;
1289 fdctrl->msr |= FD_MSR_CMDBUSY;
1290 if (fdctrl->fifo[0] & 0x80)
1291 fdctrl->data_state |= FD_STATE_MULTI;
1293 fdctrl->data_state &= ~FD_STATE_MULTI;
1295 fdctrl->data_state |= FD_STATE_SEEK;
1297 fdctrl->data_state &= ~FD_STATE_SEEK;
1298 if (fdctrl->fifo[5] == 00) {
1299 fdctrl->data_len = fdctrl->fifo[8];
1302 fdctrl->data_len = 128 << (fdctrl->fifo[5] > 7 ? 7 : fdctrl->fifo[5]);
1303 tmp = (fdctrl->fifo[6] - ks + 1);
1304 if (fdctrl->fifo[0] & 0x80)
1305 tmp += fdctrl->fifo[6];
1306 fdctrl->data_len *= tmp;
1308 fdctrl->eot = fdctrl->fifo[6];
1309 if (fdctrl->dor & FD_DOR_DMAEN) {
1313 dma_mode = DMA_get_channel_mode(fdctrl->dma_chann);
1315 dma_mode = PDMDevHlpDMAGetChannelMode (fdctrl->pDevIns, fdctrl->dma_chann);
1320 (128 << fdctrl->fifo[5]) *
1321 (cur_drv->last_sect - ks + 1), fdctrl->data_len);
1327 fdctrl->msr &= ~FD_MSR_RQM;
1332 DMA_hold_DREQ(fdctrl->dma_chann);
1333 DMA_schedule(fdctrl->dma_chann);
1335 PDMDevHlpDMASetDREQ (fdctrl->pDevIns, fdctrl->dma_chann, 1);
1336 PDMDevHlpDMASchedule (fdctrl->pDevIns);
1344 fdctrl->msr |= FD_MSR_NONDMA;
1346 fdctrl->msr |= FD_MSR_DIO;
1348 fdctrl_raise_irq(fdctrl, 0x00);
1354 static void fdctrl_start_format(fdctrl_t *fdctrl)
1359 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
1360 cur_drv = get_cur_drv(fdctrl);
1362 kh = (fdctrl->fifo[1] & 0x04) >> 2;
1363 ns = fdctrl->fifo[3];
1364 dp = fdctrl->fifo[5];
1367 GET_CUR_DRV(fdctrl), kh, kt, ns, dp,
1372 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
1373 fdctrl->fifo[3] = kt;
1374 fdctrl->fifo[4] = kh;
1375 fdctrl->fifo[5] = ks;
1379 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_EC, 0x00);
1380 fdctrl->fifo[3] = kt;
1381 fdctrl->fifo[4] = kh;
1382 fdctrl->fifo[5] = ks;
1386 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
1387 fdctrl->fifo[3] = kt;
1388 fdctrl->fifo[4] = kh;
1389 fdctrl->fifo[5] = ks;
1401 if ((fdctrl->dsr & FD_DSR_DRATEMASK) != cur_drv->media_rate) {
1403 fdctrl->dsr & FD_DSR_DRATEMASK, cur_drv->media_rate);
1404 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA, FD_SR2_MD);
1405 fdctrl->fifo[3] = kt;
1406 fdctrl->fifo[4] = kh;
1407 fdctrl->fifo[5] = ks;
1412 fdctrl->data_dir = FD_DIR_FORMAT;
1413 fdctrl->data_pos = 0;
1414 fdctrl->msr |= FD_MSR_CMDBUSY;
1415 fdctrl->data_state &= ~(FD_STATE_MULTI | FD_STATE_SEEK);
1416 fdctrl->data_len = ns * 4;
1417 fdctrl->eot = ns;
1418 if (fdctrl->dor & FD_DOR_DMAEN) {
1422 dma_mode = DMA_get_channel_mode(fdctrl->dma_chann);
1424 dma_mode = PDMDevHlpDMAGetChannelMode (fdctrl->pDevIns, fdctrl->dma_chann);
1428 dma_mode, fdctrl->data_dir,
1429 (128 << fdctrl->fifo[2]) *
1430 (cur_drv->last_sect + 1), fdctrl->data_len);
1431 if (fdctrl->data_dir == FD_DIR_FORMAT && dma_mode == 2) {
1433 fdctrl->msr &= ~FD_MSR_RQM;
1438 DMA_hold_DREQ(fdctrl->dma_chann);
1439 DMA_schedule(fdctrl->dma_chann);
1441 PDMDevHlpDMASetDREQ (fdctrl->pDevIns, fdctrl->dma_chann, 1);
1442 PDMDevHlpDMASchedule (fdctrl->pDevIns);
1446 FLOPPY_ERROR("dma_mode=%d direction=%d\n", dma_mode, fdctrl->data_dir);
1450 fdctrl->msr |= FD_MSR_NONDMA;
1452 fdctrl_raise_irq(fdctrl, 0x00);
1458 static void fdctrl_start_transfer_del(fdctrl_t *fdctrl, int direction)
1465 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
1518 fdctrl_t *fdctrl;
1529 fdctrl = (fdctrl_t *)opaque;
1530 if (fdctrl->msr & FD_MSR_RQM) {
1534 cur_drv = get_cur_drv(fdctrl);
1535 if (fdctrl->data_dir == FD_DIR_SCANE || fdctrl->data_dir == FD_DIR_SCANL ||
1536 fdctrl->data_dir == FD_DIR_SCANH)
1538 if (dma_len > fdctrl->data_len)
1539 dma_len = fdctrl->data_len;
1546 if (fdctrl->data_dir == FD_DIR_WRITE)
1547 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
1549 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
1557 if (fdctrl->data_dir == FD_DIR_WRITE || fdctrl->data_dir == FD_DIR_FORMAT)
1562 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, FD_SR1_NW,
1571 rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;
1572 for (start_pos = fdctrl->data_pos; fdctrl->data_pos < dma_len;) {
1573 len = dma_len - fdctrl->data_pos;
1577 "(%d-0x%08x 0x%08x)\n", len, dma_len, fdctrl->data_pos,
1578 fdctrl->data_len, GET_CUR_DRV(fdctrl), cur_drv->head,
1581 if (fdctrl->data_dir != FD_DIR_FORMAT &&
1582 (fdctrl->data_dir != FD_DIR_WRITE ||
1586 rc = blk_read(cur_drv, fd_sector(cur_drv), fdctrl->fifo, 1);
1590 fdctrl->fifo, 1) < 0)
1596 memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
1599 switch (fdctrl->data_dir) {
1605 int rc2 = PDMDevHlpDMAWriteMemory(fdctrl->pDevIns, nchan,
1606 fdctrl->fifo + rel_pos,
1607 fdctrl->data_pos,
1612 DMA_write_memory (nchan, fdctrl->fifo + rel_pos,
1613 fdctrl->data_pos, len);
1615 /* cpu_physical_memory_write(addr + fdctrl->data_pos, */
1616 /* fdctrl->fifo + rel_pos, len); */
1623 int rc2 = PDMDevHlpDMAReadMemory(fdctrl->pDevIns, nchan,
1624 fdctrl->fifo + rel_pos,
1625 fdctrl->data_pos,
1630 rc = blk_write(cur_drv, fd_sector(cur_drv), fdctrl->fifo, 1);
1633 DMA_read_memory (nchan, fdctrl->fifo + rel_pos,
1634 fdctrl->data_pos, len);
1636 fdctrl->fifo, 1) < 0)
1640 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
1648 uint8_t eot = fdctrl->fifo[3];
1649 uint8_t filler = fdctrl->fifo[5];
1652 int rc2 = PDMDevHlpDMAReadMemory(fdctrl->pDevIns, nchan,
1653 fdctrl->fifo + rel_pos,
1654 fdctrl->data_pos,
1661 memset(fdctrl->fifo, filler, FD_SECTOR_LEN);
1664 rc = blk_write(cur_drv, fd_sector(cur_drv), fdctrl->fifo, 1);
1668 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
1671 fdctrl_seek_to_next_sect(fdctrl, cur_drv);
1683 int rc2 = PDMDevHlpDMAReadMemory (fdctrl->pDevIns, nchan, tmpbuf,
1684 fdctrl->data_pos, len, &read);
1687 DMA_read_memory (nchan, tmpbuf, fdctrl->data_pos, len);
1689 ret = memcmp(tmpbuf, fdctrl->fifo + rel_pos, len);
1694 if ((ret < 0 && fdctrl->data_dir == FD_DIR_SCANL) ||
1695 (ret > 0 && fdctrl->data_dir == FD_DIR_SCANH)) {
1702 fdctrl->data_pos += len;
1703 rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;
1706 if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv))
1711 len = fdctrl->data_pos - start_pos;
1713 fdctrl->data_pos, len, fdctrl->data_len);
1714 if (fdctrl->data_dir == FD_DIR_SCANE ||
1715 fdctrl->data_dir == FD_DIR_SCANL ||
1716 fdctrl->data_dir == FD_DIR_SCANH)
1718 if (FD_DID_SEEK(fdctrl->data_state))
1720 fdctrl->data_len -= len;
1721 fdctrl_stop_transfer(fdctrl, status0, status1, status2);
1728 static uint32_t fdctrl_read_data(fdctrl_t *fdctrl)
1737 cur_drv = get_cur_drv(fdctrl);
1738 fdctrl->dsr &= ~FD_DSR_PWRDOWN;
1739 if (!(fdctrl->msr & FD_MSR_RQM) || !(fdctrl->msr & FD_MSR_DIO)) {
1743 pos = fdctrl->data_pos;
1744 if (fdctrl->msr & FD_MSR_NONDMA) {
1747 if (fdctrl->data_pos != 0)
1748 if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) {
1754 rc = blk_read(cur_drv, fd_sector(cur_drv), fdctrl->fifo, 1);
1757 if (bdrv_read(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0)
1763 memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
1767 retval = fdctrl->fifo[pos];
1768 if (++fdctrl->data_pos == fdctrl->data_len) {
1769 fdctrl->data_pos = 0;
1773 if (fdctrl->msr & FD_MSR_NONDMA) {
1774 fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00);
1776 fdctrl_reset_fifo(fdctrl);
1777 fdctrl_reset_irq(fdctrl);
1785 static void fdctrl_format_sector(fdctrl_t *fdctrl)
1793 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
1794 cur_drv = get_cur_drv(fdctrl);
1795 kt = fdctrl->fifo[6];
1796 kh = fdctrl->fifo[7];
1797 ks = fdctrl->fifo[8];
1799 GET_CUR_DRV(fdctrl), kh, kt, ks,
1801 switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & FD_CONFIG_EIS)) {
1804 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
1805 fdctrl->fifo[3] = kt;
1806 fdctrl->fifo[4] = kh;
1807 fdctrl->fifo[5] = ks;
1811 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_EC, 0x00);
1812 fdctrl->fifo[3] = kt;
1813 fdctrl->fifo[4] = kh;
1814 fdctrl->fifo[5] = ks;
1818 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
1819 fdctrl->fifo[3] = kt;
1820 fdctrl->fifo[4] = kh;
1821 fdctrl->fifo[5] = ks;
1824 fdctrl->data_state |= FD_STATE_SEEK;
1829 memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
1832 rc = blk_write(cur_drv, fd_sector(cur_drv), fdctrl->fifo, 1);
1835 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
1843 bdrv_write(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) {
1845 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
1849 fdctrl->data_state &= ~FD_STATE_FORMAT;
1851 if (FD_DID_SEEK(fdctrl->data_state))
1852 fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00);
1854 fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
1857 fdctrl->data_pos = 0;
1858 fdctrl->data_len = 4;
1863 static void fdctrl_handle_lock(fdctrl_t *fdctrl, int direction)
1865 fdctrl->lock = (fdctrl->fifo[0] & 0x80) ? 1 : 0;
1866 fdctrl->fifo[0] = fdctrl->lock << 4;
1867 fdctrl_set_fifo(fdctrl, 1, 0);
1870 static void fdctrl_handle_dumpreg(fdctrl_t *fdctrl, int direction)
1872 fdrive_t *cur_drv = get_cur_drv(fdctrl);
1875 fdctrl->fifo[0] = drv0(fdctrl)->track;
1876 fdctrl->fifo[1] = drv1(fdctrl)->track;
1878 fdctrl->fifo[2] = drv2(fdctrl)->track;
1879 fdctrl->fifo[3] = drv3(fdctrl)->track;
1881 fdctrl->fifo[2] = 0;
1882 fdctrl->fifo[3] = 0;
1885 fdctrl->fifo[4] = fdctrl->timer0;
1886 fdctrl->fifo[5] = (fdctrl->timer1 << 1) | (fdctrl->dor & FD_DOR_DMAEN ? 1 : 0);
1887 fdctrl->fifo[6] = cur_drv->last_sect;
1888 fdctrl->fifo[7] = (fdctrl->lock << 7) |
1890 fdctrl->fifo[8] = fdctrl->config;
1891 fdctrl->fifo[9] = fdctrl->precomp_trk;
1892 fdctrl_set_fifo(fdctrl, 10, 0);
1895 static void fdctrl_handle_version(fdctrl_t *fdctrl, int direction)
1898 fdctrl->fifo[0] = fdctrl->version;
1899 fdctrl_set_fifo(fdctrl, 1, 0);
1902 static void fdctrl_handle_partid(fdctrl_t *fdctrl, int direction)
1904 fdctrl->fifo[0] = 0x01; /* Stepping 1 */
1905 fdctrl_set_fifo(fdctrl, 1, 0);
1908 static void fdctrl_handle_restore(fdctrl_t *fdctrl, int direction)
1910 fdrive_t *cur_drv = get_cur_drv(fdctrl);
1913 drv0(fdctrl)->track = fdctrl->fifo[3];
1914 drv1(fdctrl)->track = fdctrl->fifo[4];
1916 drv2(fdctrl)->track = fdctrl->fifo[5];
1917 drv3(fdctrl)->track = fdctrl->fifo[6];
1920 fdctrl->timer0 = fdctrl->fifo[7];
1921 fdctrl->timer1 = fdctrl->fifo[8];
1922 cur_drv->last_sect = fdctrl->fifo[9];
1923 fdctrl->lock = fdctrl->fifo[10] >> 7;
1924 cur_drv->perpendicular = (fdctrl->fifo[10] >> 2) & 0xF;
1925 fdctrl->config = fdctrl->fifo[11];
1926 fdctrl->precomp_trk = fdctrl->fifo[12];
1927 fdctrl->pwrd = fdctrl->fifo[13];
1928 fdctrl_reset_fifo(fdctrl);
1931 static void fdctrl_handle_save(fdctrl_t *fdctrl, int direction)
1933 fdrive_t *cur_drv = get_cur_drv(fdctrl);
1935 fdctrl->fifo[0] = 0;
1936 fdctrl->fifo[1] = 0;
1938 fdctrl->fifo[2] = drv0(fdctrl)->track;
1939 fdctrl->fifo[3] = drv1(fdctrl)->track;
1941 fdctrl->fifo[4] = drv2(fdctrl)->track;
1942 fdctrl->fifo[5] = drv3(fdctrl)->track;
1944 fdctrl->fifo[4] = 0;
1945 fdctrl->fifo[5] = 0;
1948 fdctrl->fifo[6] = fdctrl->timer0;
1949 fdctrl->fifo[7] = fdctrl->timer1;
1950 fdctrl->fifo[8] = cur_drv->last_sect;
1951 fdctrl->fifo[9] = (fdctrl->lock << 7) |
1953 fdctrl->fifo[10] = fdctrl->config;
1954 fdctrl->fifo[11] = fdctrl->precomp_trk;
1955 fdctrl->fifo[12] = fdctrl->pwrd;
1956 fdctrl->fifo[13] = 0;
1957 fdctrl->fifo[14] = 0;
1958 fdctrl_set_fifo(fdctrl, 15, 0);
1961 static void fdctrl_handle_readid(fdctrl_t *fdctrl, int direction)
1963 fdrive_t *cur_drv = get_cur_drv(fdctrl);
1965 FLOPPY_DPRINTF("CMD:%02x SEL:%02x\n", fdctrl->fifo[0], fdctrl->fifo[1]);
1968 cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
1970 TMTimerSetMillies(fdctrl->result_timer, 1000 / 50);
1972 qemu_mod_timer(fdctrl->result_timer,
1977 static void fdctrl_handle_format_track(fdctrl_t *fdctrl, int direction)
1982 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
1983 cur_drv = get_cur_drv(fdctrl);
1984 fdctrl->data_state &= ~(FD_STATE_MULTI | FD_STATE_SEEK);
1985 ns = fdctrl->fifo[3];
1986 dp = fdctrl->fifo[5];
1989 cur_drv->track, GET_CUR_DRV(fdctrl), ns, dp);
1991 fdctrl->fifo[0], fdctrl->fifo[1], fdctrl->fifo[2],
1992 fdctrl->fifo[3], fdctrl->fifo[4], fdctrl->fifo[5]);
1998 if (cur_drv->last_sect != ns || fdctrl->fifo[2] != 2)
1999 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_NW, 0);
2002 cur_drv->bps = fdctrl->fifo[2] > 7 ? 16384 : 128 << fdctrl->fifo[2];
2005 fdctrl_start_format(fdctrl);
2009 static void fdctrl_handle_specify(fdctrl_t *fdctrl, int direction)
2011 fdctrl->timer0 = (fdctrl->fifo[1] >> 4) & 0xF;
2012 fdctrl->timer1 = fdctrl->fifo[2] >> 1;
2013 if (fdctrl->fifo[2] & 1)
2014 fdctrl->dor &= ~FD_DOR_DMAEN;
2016 fdctrl->dor |= FD_DOR_DMAEN;
2018 fdctrl_reset_fifo(fdctrl);
2021 static void fdctrl_handle_sense_drive_status(fdctrl_t *fdctrl, int direction)
2025 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
2026 cur_drv = get_cur_drv(fdctrl);
2027 cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
2029 fdctrl->fifo[0] = (cur_drv->ro << 6) |
2032 GET_CUR_DRV(fdctrl) |
2034 fdctrl_set_fifo(fdctrl, 1, 0);
2037 static void fdctrl_handle_recalibrate(fdctrl_t *fdctrl, int direction)
2042 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
2043 cur_drv = get_cur_drv(fdctrl);
2045 fdctrl_reset_fifo(fdctrl);
2046 st0 = FD_SR0_SEEK | GET_CUR_DRV(fdctrl);
2051 fdctrl_raise_irq(fdctrl, st0);
2054 static void fdctrl_handle_sense_interrupt_status(fdctrl_t *fdctrl, int direction)
2056 fdrive_t *cur_drv = get_cur_drv(fdctrl);
2058 FLOPPY_DPRINTF("CMD:%02x\n", fdctrl->fifo[0]);
2059 if(fdctrl->reset_sensei > 0) {
2060 fdctrl->fifo[0] =
2061 FD_SR0_RDYCHG + FD_RESET_SENSEI_COUNT - fdctrl->reset_sensei;
2062 fdctrl->reset_sensei--;
2067 fdctrl->fifo[0] =
2068 FD_SR0_SEEK | (cur_drv->head << 2) | GET_CUR_DRV(fdctrl);
2070 if (fdctrl->status0 & FD_SR0_EQPMT)
2071 fdctrl->fifo[0] = fdctrl->status0;
2074 fdctrl->fifo[1] = cur_drv->track;
2075 fdctrl_set_fifo(fdctrl, 2, 0);
2076 FLOPPY_DPRINTF("ST0:%02x PCN:%02x\n", fdctrl->fifo[0], fdctrl->fifo[1]);
2077 fdctrl->status0 = FD_SR0_RDYCHG;
2080 static void fdctrl_handle_seek(fdctrl_t *fdctrl, int direction)
2084 FLOPPY_DPRINTF("CMD:%02x SEL:%02x NCN:%02x\n", fdctrl->fifo[0],
2085 fdctrl->fifo[1], fdctrl->fifo[2]);
2087 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
2088 cur_drv = get_cur_drv(fdctrl);
2089 fdctrl_reset_fifo(fdctrl);
2094 cur_drv->track = fdctrl->fifo[2];
2096 cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
2098 fdctrl_raise_irq(fdctrl, FD_SR0_SEEK | GET_CUR_DRV(fdctrl));
2100 if (fdctrl->fifo[2] > cur_drv->max_track) {
2101 fdctrl_raise_irq(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK);
2103 cur_drv->track = fdctrl->fifo[2];
2105 fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
2110 static void fdctrl_handle_perpendicular_mode(fdctrl_t *fdctrl, int direction)
2112 fdrive_t *cur_drv = get_cur_drv(fdctrl);
2114 if (fdctrl->fifo[1] & 0x80)
2115 cur_drv->perpendicular = fdctrl->fifo[1] & 0x7;
2117 fdctrl_reset_fifo(fdctrl);
2120 static void fdctrl_handle_configure(fdctrl_t *fdctrl, int direction)
2122 fdctrl->config = fdctrl->fifo[2];
2123 fdctrl->precomp_trk = fdctrl->fifo[3];
2125 fdctrl_reset_fifo(fdctrl);
2128 static void fdctrl_handle_powerdown_mode(fdctrl_t *fdctrl, int direction)
2130 fdctrl->pwrd = fdctrl->fifo[1];
2131 fdctrl->fifo[0] = fdctrl->fifo[1];
2132 fdctrl_set_fifo(fdctrl, 1, 0);
2135 static void fdctrl_handle_option(fdctrl_t *fdctrl, int direction)
2138 fdctrl_reset_fifo(fdctrl);
2141 static void fdctrl_handle_drive_specification_command(fdctrl_t *fdctrl, int direction)
2143 fdrive_t *cur_drv = get_cur_drv(fdctrl);
2145 if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x80) {
2147 if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x40) {
2148 fdctrl->fifo[0] = fdctrl->fifo[1];
2149 fdctrl->fifo[2] = 0;
2150 fdctrl->fifo[3] = 0;
2151 fdctrl_set_fifo(fdctrl, 4, 0);
2153 fdctrl_reset_fifo(fdctrl);
2155 } else if (fdctrl->data_len > 7) {
2157 fdctrl->fifo[0] = 0x80 |
2158 (cur_drv->head << 2) | GET_CUR_DRV(fdctrl);
2159 fdctrl_set_fifo(fdctrl, 1, 0);
2163 static void fdctrl_handle_relative_seek_out(fdctrl_t *fdctrl, int direction)
2167 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
2168 cur_drv = get_cur_drv(fdctrl);
2169 if (fdctrl->fifo[2] + cur_drv->track >= cur_drv->max_track) {
2172 cur_drv->track += fdctrl->fifo[2];
2174 fdctrl_reset_fifo(fdctrl);
2176 fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
2179 static void fdctrl_handle_relative_seek_in(fdctrl_t *fdctrl, int direction)
2183 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
2184 cur_drv = get_cur_drv(fdctrl);
2185 if (fdctrl->fifo[2] > cur_drv->track) {
2188 cur_drv->track -= fdctrl->fifo[2];
2190 fdctrl_reset_fifo(fdctrl);
2192 fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
2200 void (*handler)(fdctrl_t *fdctrl, int direction);
2239 static void fdctrl_write_data(fdctrl_t *fdctrl, uint32_t value)
2244 cur_drv = get_cur_drv(fdctrl);
2246 if (!(fdctrl->dor & FD_DOR_nRESET)) {
2250 if (!(fdctrl->msr & FD_MSR_RQM) || (fdctrl->msr & FD_MSR_DIO)) {
2254 fdctrl->dsr &= ~FD_DSR_PWRDOWN;
2256 if (fdctrl->msr & FD_MSR_NONDMA) {
2258 pos = fdctrl->data_pos++;
2260 fdctrl->fifo[pos] = value;
2262 fdctrl->data_pos == fdctrl->data_len) {
2264 blk_write(cur_drv, fd_sector(cur_drv), fdctrl->fifo, 1);
2267 fdctrl->fifo, 1);
2273 if (fdctrl->data_pos == fdctrl->data_len)
2274 fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00);
2277 if (fdctrl->data_pos == 0) {
2279 fdctrl_reset_irq(fdctrl); /* If pending from previous seek/recalibrate. */
2282 fdctrl->data_len = handlers[pos].parameters + 1;
2283 fdctrl->msr |= FD_MSR_CMDBUSY;
2287 fdctrl->fifo[fdctrl->data_pos++] = value;
2288 if (fdctrl->data_pos == fdctrl->data_len) {
2292 if (fdctrl->data_state & FD_STATE_FORMAT) {
2293 fdctrl_format_sector(fdctrl);
2297 pos = command_to_handler[fdctrl->fifo[0] & 0xff];
2299 (*handlers[pos].handler)(fdctrl, handlers[pos].direction);
2305 fdctrl_t *fdctrl = (fdctrl_t *)opaque;
2306 fdrive_t *cur_drv = get_cur_drv(fdctrl);
2319 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA | FD_SR1_ND, FD_SR2_MD);
2320 } else if ((fdctrl->dsr & FD_DSR_DRATEMASK) != cur_drv->media_rate) {
2322 fdctrl->dsr & FD_DSR_DRATEMASK, cur_drv->media_rate);
2323 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA | FD_SR1_ND, FD_SR2_MD);
2328 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA | FD_SR1_ND, FD_SR2_MD);
2332 fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
2345 fdctrl_t *fdctrl = (fdctrl_t *)pvUser;
2346 fdctrl_result_timer(fdctrl);
2728 fdctrl_t *fdctrl = PDMINS_2_DATA(pDevIns, fdctrl_t *);
2749 drv = &fdctrl->drives[iLUN];