Commit b9b3d225163a07978d649af0bb560eacacf61b1a
1 parent
1c346df2
FDC fix 6/10 (Hervé Poussineau):
- Stores controller state in MSR register instead of internal state field. This simplifies the fdctrl_read_main_status() function, which may be called in some tight loops. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4286 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
32 additions
and
51 deletions
hw/fdc.c
| ... | ... | @@ -312,12 +312,6 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value); |
| 312 | 312 | static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl); |
| 313 | 313 | |
| 314 | 314 | enum { |
| 315 | - FD_CTRL_ACTIVE = 0x01, /* XXX: suppress that */ | |
| 316 | - FD_CTRL_SLEEP = 0x04, /* XXX: suppress that */ | |
| 317 | - FD_CTRL_BUSY = 0x08, /* dma transfer in progress */ | |
| 318 | -}; | |
| 319 | - | |
| 320 | -enum { | |
| 321 | 315 | FD_DIR_WRITE = 0, |
| 322 | 316 | FD_DIR_READ = 1, |
| 323 | 317 | FD_DIR_SCANE = 2, |
| ... | ... | @@ -326,13 +320,9 @@ enum { |
| 326 | 320 | }; |
| 327 | 321 | |
| 328 | 322 | enum { |
| 329 | - FD_STATE_CMD = 0x00, | |
| 330 | - FD_STATE_STATUS = 0x01, | |
| 331 | - FD_STATE_DATA = 0x02, | |
| 332 | - FD_STATE_STATE = 0x03, | |
| 333 | - FD_STATE_MULTI = 0x10, | |
| 334 | - FD_STATE_SEEK = 0x20, | |
| 335 | - FD_STATE_FORMAT = 0x40, | |
| 323 | + FD_STATE_MULTI = 0x01, /* multi track flag */ | |
| 324 | + FD_STATE_FORMAT = 0x02, /* format flag */ | |
| 325 | + FD_STATE_SEEK = 0x04, /* seek flag */ | |
| 336 | 326 | }; |
| 337 | 327 | |
| 338 | 328 | enum { |
| ... | ... | @@ -450,9 +440,6 @@ enum { |
| 450 | 440 | FD_DIR_DSKCHG = 0x80, |
| 451 | 441 | }; |
| 452 | 442 | |
| 453 | -#define FD_STATE(state) ((state) & FD_STATE_STATE) | |
| 454 | -#define FD_SET_STATE(state, new_state) \ | |
| 455 | -do { (state) = ((state) & ~FD_STATE_STATE) | (new_state); } while (0) | |
| 456 | 443 | #define FD_MULTI_TRACK(state) ((state) & FD_STATE_MULTI) |
| 457 | 444 | #define FD_DID_SEEK(state) ((state) & FD_STATE_SEEK) |
| 458 | 445 | #define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT) |
| ... | ... | @@ -470,6 +457,7 @@ struct fdctrl_t { |
| 470 | 457 | uint8_t sra; |
| 471 | 458 | uint8_t srb; |
| 472 | 459 | uint8_t dor; |
| 460 | + uint8_t dsr; | |
| 473 | 461 | uint8_t msr; |
| 474 | 462 | uint8_t state; |
| 475 | 463 | uint8_t dma_en; |
| ... | ... | @@ -713,9 +701,11 @@ static void fdctrl_reset_irq (fdctrl_t *fdctrl) |
| 713 | 701 | |
| 714 | 702 | static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status) |
| 715 | 703 | { |
| 716 | - // Sparc mutation | |
| 717 | - if (fdctrl->sun4m && !fdctrl->dma_en) { | |
| 718 | - fdctrl->state &= ~FD_CTRL_BUSY; | |
| 704 | + /* Sparc mutation */ | |
| 705 | + if (fdctrl->sun4m && (fdctrl->msr & FD_MSR_CMDBUSY)) { | |
| 706 | + /* XXX: not sure */ | |
| 707 | + fdctrl->msr &= ~FD_MSR_CMDBUSY; | |
| 708 | + fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO; | |
| 719 | 709 | fdctrl->int_status = status; |
| 720 | 710 | return; |
| 721 | 711 | } |
| ... | ... | @@ -742,11 +732,11 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq) |
| 742 | 732 | fdctrl->cur_drv = 0; |
| 743 | 733 | fdctrl->dor = FD_DOR_nRESET; |
| 744 | 734 | fdctrl->dor |= (fdctrl->dma_chann != -1) ? FD_DOR_DMAEN : 0; |
| 745 | - fdctrl->msr = 0; | |
| 735 | + fdctrl->msr = FD_MSR_RQM; | |
| 746 | 736 | /* FIFO state */ |
| 747 | 737 | fdctrl->data_pos = 0; |
| 748 | 738 | fdctrl->data_len = 0; |
| 749 | - fdctrl->data_state = FD_STATE_CMD; | |
| 739 | + fdctrl->data_state = 0; | |
| 750 | 740 | fdctrl->data_dir = FD_DIR_WRITE; |
| 751 | 741 | for (i = 0; i < MAX_FD; i++) |
| 752 | 742 | fd_recalibrate(&fdctrl->drives[i]); |
| ... | ... | @@ -831,7 +821,7 @@ static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value) |
| 831 | 821 | if (!(fdctrl->dor & FD_DOR_nRESET)) { |
| 832 | 822 | FLOPPY_DPRINTF("controller out of RESET state\n"); |
| 833 | 823 | fdctrl_reset(fdctrl, 1); |
| 834 | - fdctrl->state &= ~FD_CTRL_SLEEP; | |
| 824 | + fdctrl->dsr &= ~FD_DSR_PWRDOWN; | |
| 835 | 825 | } |
| 836 | 826 | } |
| 837 | 827 | /* Selected drive */ |
| ... | ... | @@ -869,22 +859,11 @@ static void fdctrl_write_tape (fdctrl_t *fdctrl, uint32_t value) |
| 869 | 859 | /* Main status register : 0x04 (read) */ |
| 870 | 860 | static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl) |
| 871 | 861 | { |
| 872 | - uint32_t retval = 0; | |
| 862 | + uint32_t retval = fdctrl->msr; | |
| 873 | 863 | |
| 864 | + fdctrl->dsr &= ~FD_DSR_PWRDOWN; | |
| 874 | 865 | fdctrl->dor |= FD_DOR_nRESET; |
| 875 | - fdctrl->state &= ~FD_CTRL_SLEEP; | |
| 876 | - if (!(fdctrl->state & FD_CTRL_BUSY)) { | |
| 877 | - /* Data transfer allowed */ | |
| 878 | - retval |= FD_MSR_RQM; | |
| 879 | - /* Data transfer direction indicator */ | |
| 880 | - if (fdctrl->data_dir == FD_DIR_READ) | |
| 881 | - retval |= FD_MSR_DIO; | |
| 882 | - } | |
| 883 | - /* Should handle FD_MSR_NONDMA for SPECIFY command */ | |
| 884 | - /* Command busy indicator */ | |
| 885 | - if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA || | |
| 886 | - FD_STATE(fdctrl->data_state) == FD_STATE_STATUS) | |
| 887 | - retval |= FD_MSR_CMDBUSY; | |
| 866 | + | |
| 888 | 867 | FLOPPY_DPRINTF("main status register: 0x%02x\n", retval); |
| 889 | 868 | |
| 890 | 869 | return retval; |
| ... | ... | @@ -906,9 +885,9 @@ static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value) |
| 906 | 885 | fdctrl->dor |= FD_DOR_nRESET; |
| 907 | 886 | } |
| 908 | 887 | if (value & FD_DSR_PWRDOWN) { |
| 909 | - fdctrl->state |= FD_CTRL_SLEEP; | |
| 910 | 888 | fdctrl_reset(fdctrl, 1); |
| 911 | 889 | } |
| 890 | + fdctrl->dsr = value; | |
| 912 | 891 | } |
| 913 | 892 | |
| 914 | 893 | static int fdctrl_media_changed(fdrive_t *drv) |
| ... | ... | @@ -943,7 +922,7 @@ static void fdctrl_reset_fifo (fdctrl_t *fdctrl) |
| 943 | 922 | { |
| 944 | 923 | fdctrl->data_dir = FD_DIR_WRITE; |
| 945 | 924 | fdctrl->data_pos = 0; |
| 946 | - FD_SET_STATE(fdctrl->data_state, FD_STATE_CMD); | |
| 925 | + fdctrl->msr &= ~(FD_MSR_CMDBUSY | FD_MSR_DIO); | |
| 947 | 926 | } |
| 948 | 927 | |
| 949 | 928 | /* Set FIFO status for the host to read */ |
| ... | ... | @@ -952,7 +931,7 @@ static void fdctrl_set_fifo (fdctrl_t *fdctrl, int fifo_len, int do_irq) |
| 952 | 931 | fdctrl->data_dir = FD_DIR_READ; |
| 953 | 932 | fdctrl->data_len = fifo_len; |
| 954 | 933 | fdctrl->data_pos = 0; |
| 955 | - FD_SET_STATE(fdctrl->data_state, FD_STATE_STATUS); | |
| 934 | + fdctrl->msr |= FD_MSR_CMDBUSY | FD_MSR_RQM | FD_MSR_DIO; | |
| 956 | 935 | if (do_irq) |
| 957 | 936 | fdctrl_raise_irq(fdctrl, 0x00); |
| 958 | 937 | } |
| ... | ... | @@ -1029,8 +1008,8 @@ static void fdctrl_stop_transfer (fdctrl_t *fdctrl, uint8_t status0, |
| 1029 | 1008 | fdctrl->data_dir = FD_DIR_READ; |
| 1030 | 1009 | if (!(fdctrl->msr & FD_MSR_NONDMA)) { |
| 1031 | 1010 | DMA_release_DREQ(fdctrl->dma_chann); |
| 1032 | - fdctrl->state &= ~FD_CTRL_BUSY; | |
| 1033 | 1011 | } |
| 1012 | + fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO; | |
| 1034 | 1013 | fdctrl->msr &= ~FD_MSR_NONDMA; |
| 1035 | 1014 | fdctrl_set_fifo(fdctrl, 7, 1); |
| 1036 | 1015 | } |
| ... | ... | @@ -1079,10 +1058,11 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction) |
| 1079 | 1058 | default: |
| 1080 | 1059 | break; |
| 1081 | 1060 | } |
| 1061 | + | |
| 1082 | 1062 | /* Set the FIFO state */ |
| 1083 | 1063 | fdctrl->data_dir = direction; |
| 1084 | 1064 | fdctrl->data_pos = 0; |
| 1085 | - FD_SET_STATE(fdctrl->data_state, FD_STATE_DATA); /* FIFO ready for data */ | |
| 1065 | + fdctrl->msr |= FD_MSR_CMDBUSY; | |
| 1086 | 1066 | if (fdctrl->fifo[0] & 0x80) |
| 1087 | 1067 | fdctrl->data_state |= FD_STATE_MULTI; |
| 1088 | 1068 | else |
| ... | ... | @@ -1116,7 +1096,7 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction) |
| 1116 | 1096 | (direction == FD_DIR_WRITE && dma_mode == 2) || |
| 1117 | 1097 | (direction == FD_DIR_READ && dma_mode == 1)) { |
| 1118 | 1098 | /* No access is allowed until DMA transfer has completed */ |
| 1119 | - fdctrl->state |= FD_CTRL_BUSY; | |
| 1099 | + fdctrl->msr &= ~FD_MSR_RQM; | |
| 1120 | 1100 | /* Now, we just have to wait for the DMA controller to |
| 1121 | 1101 | * recall us... |
| 1122 | 1102 | */ |
| ... | ... | @@ -1129,6 +1109,8 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction) |
| 1129 | 1109 | } |
| 1130 | 1110 | FLOPPY_DPRINTF("start non-DMA transfer\n"); |
| 1131 | 1111 | fdctrl->msr |= FD_MSR_NONDMA; |
| 1112 | + if (direction != FD_DIR_WRITE) | |
| 1113 | + fdctrl->msr |= FD_MSR_DIO; | |
| 1132 | 1114 | /* IO based transfer: calculate len */ |
| 1133 | 1115 | fdctrl_raise_irq(fdctrl, 0x00); |
| 1134 | 1116 | |
| ... | ... | @@ -1154,7 +1136,7 @@ static int fdctrl_transfer_handler (void *opaque, int nchan, |
| 1154 | 1136 | uint8_t status0 = 0x00, status1 = 0x00, status2 = 0x00; |
| 1155 | 1137 | |
| 1156 | 1138 | fdctrl = opaque; |
| 1157 | - if (!(fdctrl->state & FD_CTRL_BUSY)) { | |
| 1139 | + if (fdctrl->msr & FD_MSR_RQM) { | |
| 1158 | 1140 | FLOPPY_DPRINTF("Not in DMA transfer mode !\n"); |
| 1159 | 1141 | return 0; |
| 1160 | 1142 | } |
| ... | ... | @@ -1263,9 +1245,9 @@ static uint32_t fdctrl_read_data (fdctrl_t *fdctrl) |
| 1263 | 1245 | int pos; |
| 1264 | 1246 | |
| 1265 | 1247 | cur_drv = get_cur_drv(fdctrl); |
| 1266 | - fdctrl->state &= ~FD_CTRL_SLEEP; | |
| 1267 | - if (FD_STATE(fdctrl->data_state) == FD_STATE_CMD) { | |
| 1268 | - FLOPPY_ERROR("can't read data in CMD state\n"); | |
| 1248 | + fdctrl->dsr &= ~FD_DSR_PWRDOWN; | |
| 1249 | + if (!(fdctrl->msr & FD_MSR_RQM) || !(fdctrl->msr & FD_MSR_DIO)) { | |
| 1250 | + FLOPPY_ERROR("controller not ready for reading\n"); | |
| 1269 | 1251 | return 0; |
| 1270 | 1252 | } |
| 1271 | 1253 | pos = fdctrl->data_pos; |
| ... | ... | @@ -1708,11 +1690,11 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) |
| 1708 | 1690 | FLOPPY_DPRINTF("Floppy controller in RESET state !\n"); |
| 1709 | 1691 | return; |
| 1710 | 1692 | } |
| 1711 | - fdctrl->state &= ~FD_CTRL_SLEEP; | |
| 1712 | - if (FD_STATE(fdctrl->data_state) == FD_STATE_STATUS) { | |
| 1713 | - FLOPPY_ERROR("can't write data in status mode\n"); | |
| 1693 | + if (!(fdctrl->msr & FD_MSR_RQM) || (fdctrl->msr & FD_MSR_DIO)) { | |
| 1694 | + FLOPPY_ERROR("controller not ready for writing\n"); | |
| 1714 | 1695 | return; |
| 1715 | 1696 | } |
| 1697 | + fdctrl->dsr &= ~FD_DSR_PWRDOWN; | |
| 1716 | 1698 | /* Is it write command time ? */ |
| 1717 | 1699 | if (fdctrl->msr & FD_MSR_NONDMA) { |
| 1718 | 1700 | /* FIFO data write */ |
| ... | ... | @@ -1729,7 +1711,7 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) |
| 1729 | 1711 | /* Switch from transfer mode to status mode |
| 1730 | 1712 | * then from status mode to command mode |
| 1731 | 1713 | */ |
| 1732 | - if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) | |
| 1714 | + if (fdctrl->data_pos == fdctrl->data_len) | |
| 1733 | 1715 | fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00); |
| 1734 | 1716 | return; |
| 1735 | 1717 | } |
| ... | ... | @@ -1812,7 +1794,6 @@ static fdctrl_t *fdctrl_init_common (qemu_irq irq, int dma_chann, |
| 1812 | 1794 | fd_init(&fdctrl->drives[i], fds[i]); |
| 1813 | 1795 | } |
| 1814 | 1796 | fdctrl_reset(fdctrl, 0); |
| 1815 | - fdctrl->state = FD_CTRL_ACTIVE; | |
| 1816 | 1797 | register_savevm("fdc", io_base, 1, fdc_save, fdc_load, fdctrl); |
| 1817 | 1798 | qemu_register_reset(fdctrl_external_reset, fdctrl); |
| 1818 | 1799 | for (i = 0; i < MAX_FD; i++) { | ... | ... |