Commit 1c346df2a2992339609338d900bc919cf152ed85
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 | } | ... | ... |