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 | } | ... | ... |