Commit 1c346df2a2992339609338d900bc919cf152ed85

Authored by blueswir1
1 parent 368df94d

FDC fix 5/10 (Hervé Poussineau):

- Better handling of DOR register. DOR register drives external motors, but it not limited to existing drives.
- Use FD_DOR_nRESET flag instead of internal FD_CTRL_RESET flag.
- Support writing to DOR register even in reset mode (as said in specification)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4285 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 14 additions and 82 deletions
hw/fdc.c
@@ -69,10 +69,6 @@ typedef enum fdrive_type_t { @@ -69,10 +69,6 @@ typedef enum fdrive_type_t {
69 FDRIVE_DRV_NONE = 0x03, /* No drive connected */ 69 FDRIVE_DRV_NONE = 0x03, /* No drive connected */
70 } fdrive_type_t; 70 } fdrive_type_t;
71 71
72 -typedef enum fdrive_flags_t {  
73 - FDRIVE_MOTOR_ON = 0x01, /* motor on/off */  
74 -} fdrive_flags_t;  
75 -  
76 typedef enum fdisk_flags_t { 72 typedef enum fdisk_flags_t {
77 FDISK_DBL_SIDES = 0x01, 73 FDISK_DBL_SIDES = 0x01,
78 } fdisk_flags_t; 74 } fdisk_flags_t;
@@ -81,7 +77,6 @@ typedef struct fdrive_t { @@ -81,7 +77,6 @@ typedef struct fdrive_t {
81 BlockDriverState *bs; 77 BlockDriverState *bs;
82 /* Drive status */ 78 /* Drive status */
83 fdrive_type_t drive; 79 fdrive_type_t drive;
84 - fdrive_flags_t drflags;  
85 uint8_t perpendicular; /* 2.88 MB access mode */ 80 uint8_t perpendicular; /* 2.88 MB access mode */
86 /* Position */ 81 /* Position */
87 uint8_t head; 82 uint8_t head;
@@ -103,7 +98,6 @@ static void fd_init (fdrive_t *drv, BlockDriverState *bs) @@ -103,7 +98,6 @@ static void fd_init (fdrive_t *drv, BlockDriverState *bs)
103 /* Drive */ 98 /* Drive */
104 drv->bs = bs; 99 drv->bs = bs;
105 drv->drive = FDRIVE_DRV_NONE; 100 drv->drive = FDRIVE_DRV_NONE;
106 - drv->drflags = 0;  
107 drv->perpendicular = 0; 101 drv->perpendicular = 0;
108 /* Disk */ 102 /* Disk */
109 drv->last_sect = 0; 103 drv->last_sect = 0;
@@ -296,24 +290,6 @@ static void fd_revalidate (fdrive_t *drv) @@ -296,24 +290,6 @@ static void fd_revalidate (fdrive_t *drv)
296 } 290 }
297 } 291 }
298 292
299 -/* Motor control */  
300 -static void fd_start (fdrive_t *drv)  
301 -{  
302 - drv->drflags |= FDRIVE_MOTOR_ON;  
303 -}  
304 -  
305 -static void fd_stop (fdrive_t *drv)  
306 -{  
307 - drv->drflags &= ~FDRIVE_MOTOR_ON;  
308 -}  
309 -  
310 -/* Re-initialise a drives (motor off, repositioned) */  
311 -static void fd_reset (fdrive_t *drv)  
312 -{  
313 - fd_stop(drv);  
314 - fd_recalibrate(drv);  
315 -}  
316 -  
317 /********************************************************/ 293 /********************************************************/
318 /* Intel 82078 floppy disk controller emulation */ 294 /* Intel 82078 floppy disk controller emulation */
319 295
@@ -337,7 +313,6 @@ static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl); @@ -337,7 +313,6 @@ static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl);
337 313
338 enum { 314 enum {
339 FD_CTRL_ACTIVE = 0x01, /* XXX: suppress that */ 315 FD_CTRL_ACTIVE = 0x01, /* XXX: suppress that */
340 - FD_CTRL_RESET = 0x02,  
341 FD_CTRL_SLEEP = 0x04, /* XXX: suppress that */ 316 FD_CTRL_SLEEP = 0x04, /* XXX: suppress that */
342 FD_CTRL_BUSY = 0x08, /* dma transfer in progress */ 317 FD_CTRL_BUSY = 0x08, /* dma transfer in progress */
343 }; 318 };
@@ -621,10 +596,6 @@ static CPUWriteMemoryFunc *fdctrl_mem_write_strict[3] = { @@ -621,10 +596,6 @@ static CPUWriteMemoryFunc *fdctrl_mem_write_strict[3] = {
621 596
622 static void fd_save (QEMUFile *f, fdrive_t *fd) 597 static void fd_save (QEMUFile *f, fdrive_t *fd)
623 { 598 {
624 - uint8_t tmp;  
625 -  
626 - tmp = fd->drflags;  
627 - qemu_put_8s(f, &tmp);  
628 qemu_put_8s(f, &fd->head); 599 qemu_put_8s(f, &fd->head);
629 qemu_put_8s(f, &fd->track); 600 qemu_put_8s(f, &fd->track);
630 qemu_put_8s(f, &fd->sect); 601 qemu_put_8s(f, &fd->sect);
@@ -662,10 +633,6 @@ static void fdc_save (QEMUFile *f, void *opaque) @@ -662,10 +633,6 @@ static void fdc_save (QEMUFile *f, void *opaque)
662 633
663 static int fd_load (QEMUFile *f, fdrive_t *fd) 634 static int fd_load (QEMUFile *f, fdrive_t *fd)
664 { 635 {
665 - uint8_t tmp;  
666 -  
667 - qemu_get_8s(f, &tmp);  
668 - fd->drflags = tmp;  
669 qemu_get_8s(f, &fd->head); 636 qemu_get_8s(f, &fd->head);
670 qemu_get_8s(f, &fd->track); 637 qemu_get_8s(f, &fd->track);
671 qemu_get_8s(f, &fd->sect); 638 qemu_get_8s(f, &fd->sect);
@@ -773,7 +740,7 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq) @@ -773,7 +740,7 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq)
773 if (!fdctrl->drives[1].bs) 740 if (!fdctrl->drives[1].bs)
774 fdctrl->sra |= FD_SRA_nDRV2; 741 fdctrl->sra |= FD_SRA_nDRV2;
775 fdctrl->cur_drv = 0; 742 fdctrl->cur_drv = 0;
776 - fdctrl->dor = 0; 743 + fdctrl->dor = FD_DOR_nRESET;
777 fdctrl->dor |= (fdctrl->dma_chann != -1) ? FD_DOR_DMAEN : 0; 744 fdctrl->dor |= (fdctrl->dma_chann != -1) ? FD_DOR_DMAEN : 0;
778 fdctrl->msr = 0; 745 fdctrl->msr = 0;
779 /* FIFO state */ 746 /* FIFO state */
@@ -782,7 +749,7 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq) @@ -782,7 +749,7 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq)
782 fdctrl->data_state = FD_STATE_CMD; 749 fdctrl->data_state = FD_STATE_CMD;
783 fdctrl->data_dir = FD_DIR_WRITE; 750 fdctrl->data_dir = FD_DIR_WRITE;
784 for (i = 0; i < MAX_FD; i++) 751 for (i = 0; i < MAX_FD; i++)
785 - fd_reset(&fdctrl->drives[i]); 752 + fd_recalibrate(&fdctrl->drives[i]);
786 fdctrl_reset_fifo(fdctrl); 753 fdctrl_reset_fifo(fdctrl);
787 if (do_irq) 754 if (do_irq)
788 fdctrl_raise_irq(fdctrl, FD_SR0_RDYCHG); 755 fdctrl_raise_irq(fdctrl, FD_SR0_RDYCHG);
@@ -826,19 +793,8 @@ static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl) @@ -826,19 +793,8 @@ static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl)
826 /* Digital output register : 0x02 */ 793 /* Digital output register : 0x02 */
827 static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl) 794 static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl)
828 { 795 {
829 - uint32_t retval = 0; 796 + uint32_t retval = fdctrl->dor;
830 797
831 - /* Drive motors state indicators */  
832 - if (drv0(fdctrl)->drflags & FDRIVE_MOTOR_ON)  
833 - retval |= FD_DOR_MOTEN0;  
834 - if (drv1(fdctrl)->drflags & FDRIVE_MOTOR_ON)  
835 - retval |= FD_DOR_MOTEN1;  
836 - /* DMA enable */  
837 - if (fdctrl->dor & FD_DOR_DMAEN)  
838 - retval |= FD_DOR_DMAEN;  
839 - /* Reset indicator */  
840 - if (!(fdctrl->state & FD_CTRL_RESET))  
841 - retval |= FD_DOR_nRESET;  
842 /* Selected drive */ 798 /* Selected drive */
843 retval |= fdctrl->cur_drv; 799 retval |= fdctrl->cur_drv;
844 FLOPPY_DPRINTF("digital output register: 0x%02x\n", retval); 800 FLOPPY_DPRINTF("digital output register: 0x%02x\n", retval);
@@ -848,13 +804,6 @@ static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl) @@ -848,13 +804,6 @@ static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl)
848 804
849 static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value) 805 static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value)
850 { 806 {
851 - /* Reset mode */  
852 - if (fdctrl->state & FD_CTRL_RESET) {  
853 - if (!(value & FD_DOR_nRESET)) {  
854 - FLOPPY_DPRINTF("Floppy controller in RESET state !\n");  
855 - return;  
856 - }  
857 - }  
858 FLOPPY_DPRINTF("digital output register set to 0x%02x\n", value); 807 FLOPPY_DPRINTF("digital output register set to 0x%02x\n", value);
859 808
860 /* Motors */ 809 /* Motors */
@@ -873,31 +822,16 @@ static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value) @@ -873,31 +822,16 @@ static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value)
873 else 822 else
874 fdctrl->srb &= ~FD_SRB_DR0; 823 fdctrl->srb &= ~FD_SRB_DR0;
875 824
876 - /* Drive motors state indicators */  
877 - if (value & FD_DOR_MOTEN1)  
878 - fd_start(drv1(fdctrl));  
879 - else  
880 - fd_stop(drv1(fdctrl));  
881 - if (value & FD_DOR_MOTEN0)  
882 - fd_start(drv0(fdctrl));  
883 - else  
884 - fd_stop(drv0(fdctrl));  
885 - /* DMA enable */  
886 -#if 0  
887 - if (fdctrl->dma_chann != -1)  
888 - fdctrl->dma_en = value & FD_DOR_DMAEN ? 1 : 0;  
889 -#endif  
890 /* Reset */ 825 /* Reset */
891 if (!(value & FD_DOR_nRESET)) { 826 if (!(value & FD_DOR_nRESET)) {
892 - if (!(fdctrl->state & FD_CTRL_RESET)) { 827 + if (fdctrl->dor & FD_DOR_nRESET) {
893 FLOPPY_DPRINTF("controller enter RESET state\n"); 828 FLOPPY_DPRINTF("controller enter RESET state\n");
894 - fdctrl->state |= FD_CTRL_RESET;  
895 } 829 }
896 } else { 830 } else {
897 - if (fdctrl->state & FD_CTRL_RESET) { 831 + if (!(fdctrl->dor & FD_DOR_nRESET)) {
898 FLOPPY_DPRINTF("controller out of RESET state\n"); 832 FLOPPY_DPRINTF("controller out of RESET state\n");
899 fdctrl_reset(fdctrl, 1); 833 fdctrl_reset(fdctrl, 1);
900 - fdctrl->state &= ~(FD_CTRL_RESET | FD_CTRL_SLEEP); 834 + fdctrl->state &= ~FD_CTRL_SLEEP;
901 } 835 }
902 } 836 }
903 /* Selected drive */ 837 /* Selected drive */
@@ -922,7 +856,7 @@ static uint32_t fdctrl_read_tape (fdctrl_t *fdctrl) @@ -922,7 +856,7 @@ static uint32_t fdctrl_read_tape (fdctrl_t *fdctrl)
922 static void fdctrl_write_tape (fdctrl_t *fdctrl, uint32_t value) 856 static void fdctrl_write_tape (fdctrl_t *fdctrl, uint32_t value)
923 { 857 {
924 /* Reset mode */ 858 /* Reset mode */
925 - if (fdctrl->state & FD_CTRL_RESET) { 859 + if (!(fdctrl->dor & FD_DOR_nRESET)) {
926 FLOPPY_DPRINTF("Floppy controller in RESET state !\n"); 860 FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
927 return; 861 return;
928 } 862 }
@@ -937,7 +871,8 @@ static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl) @@ -937,7 +871,8 @@ static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl)
937 { 871 {
938 uint32_t retval = 0; 872 uint32_t retval = 0;
939 873
940 - fdctrl->state &= ~(FD_CTRL_SLEEP | FD_CTRL_RESET); 874 + fdctrl->dor |= FD_DOR_nRESET;
  875 + fdctrl->state &= ~FD_CTRL_SLEEP;
941 if (!(fdctrl->state & FD_CTRL_BUSY)) { 876 if (!(fdctrl->state & FD_CTRL_BUSY)) {
942 /* Data transfer allowed */ 877 /* Data transfer allowed */
943 retval |= FD_MSR_RQM; 878 retval |= FD_MSR_RQM;
@@ -959,16 +894,16 @@ static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl) @@ -959,16 +894,16 @@ static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl)
959 static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value) 894 static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value)
960 { 895 {
961 /* Reset mode */ 896 /* Reset mode */
962 - if (fdctrl->state & FD_CTRL_RESET) { 897 + if (!(fdctrl->dor & FD_DOR_nRESET)) {
963 FLOPPY_DPRINTF("Floppy controller in RESET state !\n"); 898 FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
964 return; 899 return;
965 } 900 }
966 FLOPPY_DPRINTF("select rate register set to 0x%02x\n", value); 901 FLOPPY_DPRINTF("select rate register set to 0x%02x\n", value);
967 /* Reset: autoclear */ 902 /* Reset: autoclear */
968 if (value & FD_DSR_SWRESET) { 903 if (value & FD_DSR_SWRESET) {
969 - fdctrl->state |= FD_CTRL_RESET; 904 + fdctrl->dor &= ~FD_DOR_nRESET;
970 fdctrl_reset(fdctrl, 1); 905 fdctrl_reset(fdctrl, 1);
971 - fdctrl->state &= ~FD_CTRL_RESET; 906 + fdctrl->dor |= FD_DOR_nRESET;
972 } 907 }
973 if (value & FD_DSR_PWRDOWN) { 908 if (value & FD_DSR_PWRDOWN) {
974 fdctrl->state |= FD_CTRL_SLEEP; 909 fdctrl->state |= FD_CTRL_SLEEP;
@@ -1618,7 +1553,6 @@ static void fdctrl_handle_seek (fdctrl_t *fdctrl, int direction) @@ -1618,7 +1553,6 @@ static void fdctrl_handle_seek (fdctrl_t *fdctrl, int direction)
1618 1553
1619 fdctrl->cur_drv = fdctrl->fifo[1] & FD_DOR_SELMASK; 1554 fdctrl->cur_drv = fdctrl->fifo[1] & FD_DOR_SELMASK;
1620 cur_drv = get_cur_drv(fdctrl); 1555 cur_drv = get_cur_drv(fdctrl);
1621 - fd_start(cur_drv);  
1622 if (fdctrl->fifo[2] <= cur_drv->track) 1556 if (fdctrl->fifo[2] <= cur_drv->track)
1623 cur_drv->dir = 1; 1557 cur_drv->dir = 1;
1624 else 1558 else
@@ -1640,7 +1574,7 @@ static void fdctrl_handle_perpendicular_mode (fdctrl_t *fdctrl, int direction) @@ -1640,7 +1574,7 @@ static void fdctrl_handle_perpendicular_mode (fdctrl_t *fdctrl, int direction)
1640 if (fdctrl->fifo[1] & 0x80) 1574 if (fdctrl->fifo[1] & 0x80)
1641 cur_drv->perpendicular = fdctrl->fifo[1] & 0x7; 1575 cur_drv->perpendicular = fdctrl->fifo[1] & 0x7;
1642 /* No result back */ 1576 /* No result back */
1643 - fdctrl_reset_fifo(fdctrl); 1577 + fdctrl_reset_fifo(fdctrl);
1644 } 1578 }
1645 1579
1646 static void fdctrl_handle_configure (fdctrl_t *fdctrl, int direction) 1580 static void fdctrl_handle_configure (fdctrl_t *fdctrl, int direction)
@@ -1692,7 +1626,6 @@ static void fdctrl_handle_relative_seek_out (fdctrl_t *fdctrl, int direction) @@ -1692,7 +1626,6 @@ static void fdctrl_handle_relative_seek_out (fdctrl_t *fdctrl, int direction)
1692 1626
1693 fdctrl->cur_drv = fdctrl->fifo[1] & FD_DOR_SELMASK; 1627 fdctrl->cur_drv = fdctrl->fifo[1] & FD_DOR_SELMASK;
1694 cur_drv = get_cur_drv(fdctrl); 1628 cur_drv = get_cur_drv(fdctrl);
1695 - fd_start(cur_drv);  
1696 cur_drv->dir = 0; 1629 cur_drv->dir = 0;
1697 if (fdctrl->fifo[2] + cur_drv->track >= cur_drv->max_track) { 1630 if (fdctrl->fifo[2] + cur_drv->track >= cur_drv->max_track) {
1698 cur_drv->track = cur_drv->max_track - 1; 1631 cur_drv->track = cur_drv->max_track - 1;
@@ -1709,7 +1642,6 @@ static void fdctrl_handle_relative_seek_in (fdctrl_t *fdctrl, int direction) @@ -1709,7 +1642,6 @@ static void fdctrl_handle_relative_seek_in (fdctrl_t *fdctrl, int direction)
1709 1642
1710 fdctrl->cur_drv = fdctrl->fifo[1] & FD_DOR_SELMASK; 1643 fdctrl->cur_drv = fdctrl->fifo[1] & FD_DOR_SELMASK;
1711 cur_drv = get_cur_drv(fdctrl); 1644 cur_drv = get_cur_drv(fdctrl);
1712 - fd_start(cur_drv);  
1713 cur_drv->dir = 1; 1645 cur_drv->dir = 1;
1714 if (fdctrl->fifo[2] > cur_drv->track) { 1646 if (fdctrl->fifo[2] > cur_drv->track) {
1715 cur_drv->track = 0; 1647 cur_drv->track = 0;
@@ -1772,7 +1704,7 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) @@ -1772,7 +1704,7 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value)
1772 1704
1773 cur_drv = get_cur_drv(fdctrl); 1705 cur_drv = get_cur_drv(fdctrl);
1774 /* Reset mode */ 1706 /* Reset mode */
1775 - if (fdctrl->state & FD_CTRL_RESET) { 1707 + if (!(fdctrl->dor & FD_DOR_nRESET)) {
1776 FLOPPY_DPRINTF("Floppy controller in RESET state !\n"); 1708 FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
1777 return; 1709 return;
1778 } 1710 }