Commit 368df94d16c030482adeae6b9d18220d9ad5fae3
1 parent
8c6a4d77
FDC fix 4/10 (Hervé Poussineau):
- Handles correctly FD_MSR_NONDMA/FD_DOR_NONDMA flags, and uses them when possible. Fixes a problem with SPECIFY command. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4284 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
21 additions
and
12 deletions
hw/fdc.c
| ... | ... | @@ -494,6 +494,8 @@ struct fdctrl_t { |
| 494 | 494 | QEMUTimer *result_timer; |
| 495 | 495 | uint8_t sra; |
| 496 | 496 | uint8_t srb; |
| 497 | + uint8_t dor; | |
| 498 | + uint8_t msr; | |
| 497 | 499 | uint8_t state; |
| 498 | 500 | uint8_t dma_en; |
| 499 | 501 | uint8_t cur_drv; |
| ... | ... | @@ -771,6 +773,9 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq) |
| 771 | 773 | if (!fdctrl->drives[1].bs) |
| 772 | 774 | fdctrl->sra |= FD_SRA_nDRV2; |
| 773 | 775 | fdctrl->cur_drv = 0; |
| 776 | + fdctrl->dor = 0; | |
| 777 | + fdctrl->dor |= (fdctrl->dma_chann != -1) ? FD_DOR_DMAEN : 0; | |
| 778 | + fdctrl->msr = 0; | |
| 774 | 779 | /* FIFO state */ |
| 775 | 780 | fdctrl->data_pos = 0; |
| 776 | 781 | fdctrl->data_len = 0; |
| ... | ... | @@ -829,7 +834,7 @@ static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl) |
| 829 | 834 | if (drv1(fdctrl)->drflags & FDRIVE_MOTOR_ON) |
| 830 | 835 | retval |= FD_DOR_MOTEN1; |
| 831 | 836 | /* DMA enable */ |
| 832 | - if (fdctrl->dma_en) | |
| 837 | + if (fdctrl->dor & FD_DOR_DMAEN) | |
| 833 | 838 | retval |= FD_DOR_DMAEN; |
| 834 | 839 | /* Reset indicator */ |
| 835 | 840 | if (!(fdctrl->state & FD_CTRL_RESET)) |
| ... | ... | @@ -897,6 +902,8 @@ static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value) |
| 897 | 902 | } |
| 898 | 903 | /* Selected drive */ |
| 899 | 904 | fdctrl->cur_drv = value & FD_DOR_SELMASK; |
| 905 | + | |
| 906 | + fdctrl->dor = value; | |
| 900 | 907 | } |
| 901 | 908 | |
| 902 | 909 | /* Tape drive register : 0x03 */ |
| ... | ... | @@ -1085,10 +1092,11 @@ static void fdctrl_stop_transfer (fdctrl_t *fdctrl, uint8_t status0, |
| 1085 | 1092 | fdctrl->fifo[5] = cur_drv->sect; |
| 1086 | 1093 | fdctrl->fifo[6] = FD_SECTOR_SC; |
| 1087 | 1094 | fdctrl->data_dir = FD_DIR_READ; |
| 1088 | - if (fdctrl->state & FD_CTRL_BUSY) { | |
| 1095 | + if (!(fdctrl->msr & FD_MSR_NONDMA)) { | |
| 1089 | 1096 | DMA_release_DREQ(fdctrl->dma_chann); |
| 1090 | 1097 | fdctrl->state &= ~FD_CTRL_BUSY; |
| 1091 | 1098 | } |
| 1099 | + fdctrl->msr &= ~FD_MSR_NONDMA; | |
| 1092 | 1100 | fdctrl_set_fifo(fdctrl, 7, 1); |
| 1093 | 1101 | } |
| 1094 | 1102 | |
| ... | ... | @@ -1159,7 +1167,7 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction) |
| 1159 | 1167 | fdctrl->data_len *= tmp; |
| 1160 | 1168 | } |
| 1161 | 1169 | fdctrl->eot = fdctrl->fifo[6]; |
| 1162 | - if (fdctrl->dma_en) { | |
| 1170 | + if (fdctrl->dor & FD_DOR_DMAEN) { | |
| 1163 | 1171 | int dma_mode; |
| 1164 | 1172 | /* DMA transfer are enabled. Check if DMA channel is well programmed */ |
| 1165 | 1173 | dma_mode = DMA_get_channel_mode(fdctrl->dma_chann); |
| ... | ... | @@ -1185,6 +1193,7 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction) |
| 1185 | 1193 | } |
| 1186 | 1194 | } |
| 1187 | 1195 | FLOPPY_DPRINTF("start non-DMA transfer\n"); |
| 1196 | + fdctrl->msr |= FD_MSR_NONDMA; | |
| 1188 | 1197 | /* IO based transfer: calculate len */ |
| 1189 | 1198 | fdctrl_raise_irq(fdctrl, 0x00); |
| 1190 | 1199 | |
| ... | ... | @@ -1325,7 +1334,7 @@ static uint32_t fdctrl_read_data (fdctrl_t *fdctrl) |
| 1325 | 1334 | return 0; |
| 1326 | 1335 | } |
| 1327 | 1336 | pos = fdctrl->data_pos; |
| 1328 | - if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) { | |
| 1337 | + if (fdctrl->msr & FD_MSR_NONDMA) { | |
| 1329 | 1338 | pos %= FD_SECTOR_LEN; |
| 1330 | 1339 | if (pos == 0) { |
| 1331 | 1340 | if (fdctrl->data_pos != 0) |
| ... | ... | @@ -1343,7 +1352,7 @@ static uint32_t fdctrl_read_data (fdctrl_t *fdctrl) |
| 1343 | 1352 | /* Switch from transfer mode to status mode |
| 1344 | 1353 | * then from status mode to command mode |
| 1345 | 1354 | */ |
| 1346 | - if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) { | |
| 1355 | + if (fdctrl->msr & FD_MSR_NONDMA) { | |
| 1347 | 1356 | fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00); |
| 1348 | 1357 | } else { |
| 1349 | 1358 | fdctrl_reset_fifo(fdctrl); |
| ... | ... | @@ -1438,7 +1447,7 @@ static void fdctrl_handle_dumpreg (fdctrl_t *fdctrl, int direction) |
| 1438 | 1447 | fdctrl->fifo[3] = 0; |
| 1439 | 1448 | /* timers */ |
| 1440 | 1449 | fdctrl->fifo[4] = fdctrl->timer0; |
| 1441 | - fdctrl->fifo[5] = (fdctrl->timer1 << 1) | fdctrl->dma_en; | |
| 1450 | + fdctrl->fifo[5] = (fdctrl->timer1 << 1) | (fdctrl->dor & FD_DOR_DMAEN ? 1 : 0); | |
| 1442 | 1451 | fdctrl->fifo[6] = cur_drv->last_sect; |
| 1443 | 1452 | fdctrl->fifo[7] = (fdctrl->lock << 7) | |
| 1444 | 1453 | (cur_drv->perpendicular << 2); |
| ... | ... | @@ -1547,7 +1556,10 @@ static void fdctrl_handle_specify (fdctrl_t *fdctrl, int direction) |
| 1547 | 1556 | { |
| 1548 | 1557 | fdctrl->timer0 = (fdctrl->fifo[1] >> 4) & 0xF; |
| 1549 | 1558 | fdctrl->timer1 = fdctrl->fifo[2] >> 1; |
| 1550 | - fdctrl->dma_en = 1 - (fdctrl->fifo[2] & 1) ; | |
| 1559 | + if (fdctrl->fifo[2] & 1) | |
| 1560 | + fdctrl->dor &= ~FD_DOR_DMAEN; | |
| 1561 | + else | |
| 1562 | + fdctrl->dor |= FD_DOR_DMAEN; | |
| 1551 | 1563 | /* No result back */ |
| 1552 | 1564 | fdctrl_reset_fifo(fdctrl); |
| 1553 | 1565 | } |
| ... | ... | @@ -1770,7 +1782,7 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) |
| 1770 | 1782 | return; |
| 1771 | 1783 | } |
| 1772 | 1784 | /* Is it write command time ? */ |
| 1773 | - if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) { | |
| 1785 | + if (fdctrl->msr & FD_MSR_NONDMA) { | |
| 1774 | 1786 | /* FIFO data write */ |
| 1775 | 1787 | fdctrl->fifo[fdctrl->data_pos++] = value; |
| 1776 | 1788 | if (fdctrl->data_pos % FD_SECTOR_LEN == (FD_SECTOR_LEN - 1) || |
| ... | ... | @@ -1862,10 +1874,7 @@ static fdctrl_t *fdctrl_init_common (qemu_irq irq, int dma_chann, |
| 1862 | 1874 | fdctrl->io_base = io_base; |
| 1863 | 1875 | fdctrl->config = FD_CONFIG_EIS | FD_CONFIG_EFIFO; /* Implicit seek, polling & FIFO enabled */ |
| 1864 | 1876 | if (fdctrl->dma_chann != -1) { |
| 1865 | - fdctrl->dma_en = 1; | |
| 1866 | 1877 | DMA_register_channel(dma_chann, &fdctrl_transfer_handler, fdctrl); |
| 1867 | - } else { | |
| 1868 | - fdctrl->dma_en = 0; | |
| 1869 | 1878 | } |
| 1870 | 1879 | for (i = 0; i < MAX_FD; i++) { |
| 1871 | 1880 | fd_init(&fdctrl->drives[i], fds[i]); |
| ... | ... | @@ -1915,7 +1924,7 @@ fdctrl_t *sun4m_fdctrl_init (qemu_irq irq, target_phys_addr_t io_base, |
| 1915 | 1924 | fdctrl_t *fdctrl; |
| 1916 | 1925 | int io_mem; |
| 1917 | 1926 | |
| 1918 | - fdctrl = fdctrl_init_common(irq, 0, io_base, fds); | |
| 1927 | + fdctrl = fdctrl_init_common(irq, -1, io_base, fds); | |
| 1919 | 1928 | fdctrl->sun4m = 1; |
| 1920 | 1929 | io_mem = cpu_register_io_memory(0, fdctrl_mem_read_strict, |
| 1921 | 1930 | fdctrl_mem_write_strict, | ... | ... |