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 69 FDRIVE_DRV_NONE = 0x03, /* No drive connected */
70 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 72 typedef enum fdisk_flags_t {
77 73 FDISK_DBL_SIDES = 0x01,
78 74 } fdisk_flags_t;
... ... @@ -81,7 +77,6 @@ typedef struct fdrive_t {
81 77 BlockDriverState *bs;
82 78 /* Drive status */
83 79 fdrive_type_t drive;
84   - fdrive_flags_t drflags;
85 80 uint8_t perpendicular; /* 2.88 MB access mode */
86 81 /* Position */
87 82 uint8_t head;
... ... @@ -103,7 +98,6 @@ static void fd_init (fdrive_t *drv, BlockDriverState *bs)
103 98 /* Drive */
104 99 drv->bs = bs;
105 100 drv->drive = FDRIVE_DRV_NONE;
106   - drv->drflags = 0;
107 101 drv->perpendicular = 0;
108 102 /* Disk */
109 103 drv->last_sect = 0;
... ... @@ -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 294 /* Intel 82078 floppy disk controller emulation */
319 295  
... ... @@ -337,7 +313,6 @@ static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl);
337 313  
338 314 enum {
339 315 FD_CTRL_ACTIVE = 0x01, /* XXX: suppress that */
340   - FD_CTRL_RESET = 0x02,
341 316 FD_CTRL_SLEEP = 0x04, /* XXX: suppress that */
342 317 FD_CTRL_BUSY = 0x08, /* dma transfer in progress */
343 318 };
... ... @@ -621,10 +596,6 @@ static CPUWriteMemoryFunc *fdctrl_mem_write_strict[3] = {
621 596  
622 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 599 qemu_put_8s(f, &fd->head);
629 600 qemu_put_8s(f, &fd->track);
630 601 qemu_put_8s(f, &fd->sect);
... ... @@ -662,10 +633,6 @@ static void fdc_save (QEMUFile *f, void *opaque)
662 633  
663 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 636 qemu_get_8s(f, &fd->head);
670 637 qemu_get_8s(f, &fd->track);
671 638 qemu_get_8s(f, &fd->sect);
... ... @@ -773,7 +740,7 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq)
773 740 if (!fdctrl->drives[1].bs)
774 741 fdctrl->sra |= FD_SRA_nDRV2;
775 742 fdctrl->cur_drv = 0;
776   - fdctrl->dor = 0;
  743 + fdctrl->dor = FD_DOR_nRESET;
777 744 fdctrl->dor |= (fdctrl->dma_chann != -1) ? FD_DOR_DMAEN : 0;
778 745 fdctrl->msr = 0;
779 746 /* FIFO state */
... ... @@ -782,7 +749,7 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq)
782 749 fdctrl->data_state = FD_STATE_CMD;
783 750 fdctrl->data_dir = FD_DIR_WRITE;
784 751 for (i = 0; i < MAX_FD; i++)
785   - fd_reset(&fdctrl->drives[i]);
  752 + fd_recalibrate(&fdctrl->drives[i]);
786 753 fdctrl_reset_fifo(fdctrl);
787 754 if (do_irq)
788 755 fdctrl_raise_irq(fdctrl, FD_SR0_RDYCHG);
... ... @@ -826,19 +793,8 @@ static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl)
826 793 /* Digital output register : 0x02 */
827 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 798 /* Selected drive */
843 799 retval |= fdctrl->cur_drv;
844 800 FLOPPY_DPRINTF("digital output register: 0x%02x\n", retval);
... ... @@ -848,13 +804,6 @@ static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl)
848 804  
849 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 807 FLOPPY_DPRINTF("digital output register set to 0x%02x\n", value);
859 808  
860 809 /* Motors */
... ... @@ -873,31 +822,16 @@ static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value)
873 822 else
874 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 825 /* Reset */
891 826 if (!(value & FD_DOR_nRESET)) {
892   - if (!(fdctrl->state & FD_CTRL_RESET)) {
  827 + if (fdctrl->dor & FD_DOR_nRESET) {
893 828 FLOPPY_DPRINTF("controller enter RESET state\n");
894   - fdctrl->state |= FD_CTRL_RESET;
895 829 }
896 830 } else {
897   - if (fdctrl->state & FD_CTRL_RESET) {
  831 + if (!(fdctrl->dor & FD_DOR_nRESET)) {
898 832 FLOPPY_DPRINTF("controller out of RESET state\n");
899 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 837 /* Selected drive */
... ... @@ -922,7 +856,7 @@ static uint32_t fdctrl_read_tape (fdctrl_t *fdctrl)
922 856 static void fdctrl_write_tape (fdctrl_t *fdctrl, uint32_t value)
923 857 {
924 858 /* Reset mode */
925   - if (fdctrl->state & FD_CTRL_RESET) {
  859 + if (!(fdctrl->dor & FD_DOR_nRESET)) {
926 860 FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
927 861 return;
928 862 }
... ... @@ -937,7 +871,8 @@ static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl)
937 871 {
938 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 876 if (!(fdctrl->state & FD_CTRL_BUSY)) {
942 877 /* Data transfer allowed */
943 878 retval |= FD_MSR_RQM;
... ... @@ -959,16 +894,16 @@ static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl)
959 894 static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value)
960 895 {
961 896 /* Reset mode */
962   - if (fdctrl->state & FD_CTRL_RESET) {
  897 + if (!(fdctrl->dor & FD_DOR_nRESET)) {
963 898 FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
964 899 return;
965 900 }
966 901 FLOPPY_DPRINTF("select rate register set to 0x%02x\n", value);
967 902 /* Reset: autoclear */
968 903 if (value & FD_DSR_SWRESET) {
969   - fdctrl->state |= FD_CTRL_RESET;
  904 + fdctrl->dor &= ~FD_DOR_nRESET;
970 905 fdctrl_reset(fdctrl, 1);
971   - fdctrl->state &= ~FD_CTRL_RESET;
  906 + fdctrl->dor |= FD_DOR_nRESET;
972 907 }
973 908 if (value & FD_DSR_PWRDOWN) {
974 909 fdctrl->state |= FD_CTRL_SLEEP;
... ... @@ -1618,7 +1553,6 @@ static void fdctrl_handle_seek (fdctrl_t *fdctrl, int direction)
1618 1553  
1619 1554 fdctrl->cur_drv = fdctrl->fifo[1] & FD_DOR_SELMASK;
1620 1555 cur_drv = get_cur_drv(fdctrl);
1621   - fd_start(cur_drv);
1622 1556 if (fdctrl->fifo[2] <= cur_drv->track)
1623 1557 cur_drv->dir = 1;
1624 1558 else
... ... @@ -1640,7 +1574,7 @@ static void fdctrl_handle_perpendicular_mode (fdctrl_t *fdctrl, int direction)
1640 1574 if (fdctrl->fifo[1] & 0x80)
1641 1575 cur_drv->perpendicular = fdctrl->fifo[1] & 0x7;
1642 1576 /* No result back */
1643   - fdctrl_reset_fifo(fdctrl);
  1577 + fdctrl_reset_fifo(fdctrl);
1644 1578 }
1645 1579  
1646 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 1626  
1693 1627 fdctrl->cur_drv = fdctrl->fifo[1] & FD_DOR_SELMASK;
1694 1628 cur_drv = get_cur_drv(fdctrl);
1695   - fd_start(cur_drv);
1696 1629 cur_drv->dir = 0;
1697 1630 if (fdctrl->fifo[2] + cur_drv->track >= cur_drv->max_track) {
1698 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 1642  
1710 1643 fdctrl->cur_drv = fdctrl->fifo[1] & FD_DOR_SELMASK;
1711 1644 cur_drv = get_cur_drv(fdctrl);
1712   - fd_start(cur_drv);
1713 1645 cur_drv->dir = 1;
1714 1646 if (fdctrl->fifo[2] > cur_drv->track) {
1715 1647 cur_drv->track = 0;
... ... @@ -1772,7 +1704,7 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value)
1772 1704  
1773 1705 cur_drv = get_cur_drv(fdctrl);
1774 1706 /* Reset mode */
1775   - if (fdctrl->state & FD_CTRL_RESET) {
  1707 + if (!(fdctrl->dor & FD_DOR_nRESET)) {
1776 1708 FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
1777 1709 return;
1778 1710 }
... ...