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