Commit b9b3d225163a07978d649af0bb560eacacf61b1a

Authored by blueswir1
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,12 +312,6 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value);
312 static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl); 312 static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl);
313 313
314 enum { 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 FD_DIR_WRITE = 0, 315 FD_DIR_WRITE = 0,
322 FD_DIR_READ = 1, 316 FD_DIR_READ = 1,
323 FD_DIR_SCANE = 2, 317 FD_DIR_SCANE = 2,
@@ -326,13 +320,9 @@ enum { @@ -326,13 +320,9 @@ enum {
326 }; 320 };
327 321
328 enum { 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 enum { 328 enum {
@@ -450,9 +440,6 @@ enum { @@ -450,9 +440,6 @@ enum {
450 FD_DIR_DSKCHG = 0x80, 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 #define FD_MULTI_TRACK(state) ((state) & FD_STATE_MULTI) 443 #define FD_MULTI_TRACK(state) ((state) & FD_STATE_MULTI)
457 #define FD_DID_SEEK(state) ((state) & FD_STATE_SEEK) 444 #define FD_DID_SEEK(state) ((state) & FD_STATE_SEEK)
458 #define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT) 445 #define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT)
@@ -470,6 +457,7 @@ struct fdctrl_t { @@ -470,6 +457,7 @@ struct fdctrl_t {
470 uint8_t sra; 457 uint8_t sra;
471 uint8_t srb; 458 uint8_t srb;
472 uint8_t dor; 459 uint8_t dor;
  460 + uint8_t dsr;
473 uint8_t msr; 461 uint8_t msr;
474 uint8_t state; 462 uint8_t state;
475 uint8_t dma_en; 463 uint8_t dma_en;
@@ -713,9 +701,11 @@ static void fdctrl_reset_irq (fdctrl_t *fdctrl) @@ -713,9 +701,11 @@ static void fdctrl_reset_irq (fdctrl_t *fdctrl)
713 701
714 static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status) 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 fdctrl->int_status = status; 709 fdctrl->int_status = status;
720 return; 710 return;
721 } 711 }
@@ -742,11 +732,11 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq) @@ -742,11 +732,11 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq)
742 fdctrl->cur_drv = 0; 732 fdctrl->cur_drv = 0;
743 fdctrl->dor = FD_DOR_nRESET; 733 fdctrl->dor = FD_DOR_nRESET;
744 fdctrl->dor |= (fdctrl->dma_chann != -1) ? FD_DOR_DMAEN : 0; 734 fdctrl->dor |= (fdctrl->dma_chann != -1) ? FD_DOR_DMAEN : 0;
745 - fdctrl->msr = 0; 735 + fdctrl->msr = FD_MSR_RQM;
746 /* FIFO state */ 736 /* FIFO state */
747 fdctrl->data_pos = 0; 737 fdctrl->data_pos = 0;
748 fdctrl->data_len = 0; 738 fdctrl->data_len = 0;
749 - fdctrl->data_state = FD_STATE_CMD; 739 + fdctrl->data_state = 0;
750 fdctrl->data_dir = FD_DIR_WRITE; 740 fdctrl->data_dir = FD_DIR_WRITE;
751 for (i = 0; i < MAX_FD; i++) 741 for (i = 0; i < MAX_FD; i++)
752 fd_recalibrate(&fdctrl->drives[i]); 742 fd_recalibrate(&fdctrl->drives[i]);
@@ -831,7 +821,7 @@ static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value) @@ -831,7 +821,7 @@ static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value)
831 if (!(fdctrl->dor & FD_DOR_nRESET)) { 821 if (!(fdctrl->dor & FD_DOR_nRESET)) {
832 FLOPPY_DPRINTF("controller out of RESET state\n"); 822 FLOPPY_DPRINTF("controller out of RESET state\n");
833 fdctrl_reset(fdctrl, 1); 823 fdctrl_reset(fdctrl, 1);
834 - fdctrl->state &= ~FD_CTRL_SLEEP; 824 + fdctrl->dsr &= ~FD_DSR_PWRDOWN;
835 } 825 }
836 } 826 }
837 /* Selected drive */ 827 /* Selected drive */
@@ -869,22 +859,11 @@ static void fdctrl_write_tape (fdctrl_t *fdctrl, uint32_t value) @@ -869,22 +859,11 @@ static void fdctrl_write_tape (fdctrl_t *fdctrl, uint32_t value)
869 /* Main status register : 0x04 (read) */ 859 /* Main status register : 0x04 (read) */
870 static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl) 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 fdctrl->dor |= FD_DOR_nRESET; 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 FLOPPY_DPRINTF("main status register: 0x%02x\n", retval); 867 FLOPPY_DPRINTF("main status register: 0x%02x\n", retval);
889 868
890 return retval; 869 return retval;
@@ -906,9 +885,9 @@ static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value) @@ -906,9 +885,9 @@ static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value)
906 fdctrl->dor |= FD_DOR_nRESET; 885 fdctrl->dor |= FD_DOR_nRESET;
907 } 886 }
908 if (value & FD_DSR_PWRDOWN) { 887 if (value & FD_DSR_PWRDOWN) {
909 - fdctrl->state |= FD_CTRL_SLEEP;  
910 fdctrl_reset(fdctrl, 1); 888 fdctrl_reset(fdctrl, 1);
911 } 889 }
  890 + fdctrl->dsr = value;
912 } 891 }
913 892
914 static int fdctrl_media_changed(fdrive_t *drv) 893 static int fdctrl_media_changed(fdrive_t *drv)
@@ -943,7 +922,7 @@ static void fdctrl_reset_fifo (fdctrl_t *fdctrl) @@ -943,7 +922,7 @@ static void fdctrl_reset_fifo (fdctrl_t *fdctrl)
943 { 922 {
944 fdctrl->data_dir = FD_DIR_WRITE; 923 fdctrl->data_dir = FD_DIR_WRITE;
945 fdctrl->data_pos = 0; 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 /* Set FIFO status for the host to read */ 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,7 +931,7 @@ static void fdctrl_set_fifo (fdctrl_t *fdctrl, int fifo_len, int do_irq)
952 fdctrl->data_dir = FD_DIR_READ; 931 fdctrl->data_dir = FD_DIR_READ;
953 fdctrl->data_len = fifo_len; 932 fdctrl->data_len = fifo_len;
954 fdctrl->data_pos = 0; 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 if (do_irq) 935 if (do_irq)
957 fdctrl_raise_irq(fdctrl, 0x00); 936 fdctrl_raise_irq(fdctrl, 0x00);
958 } 937 }
@@ -1029,8 +1008,8 @@ static void fdctrl_stop_transfer (fdctrl_t *fdctrl, uint8_t status0, @@ -1029,8 +1008,8 @@ static void fdctrl_stop_transfer (fdctrl_t *fdctrl, uint8_t status0,
1029 fdctrl->data_dir = FD_DIR_READ; 1008 fdctrl->data_dir = FD_DIR_READ;
1030 if (!(fdctrl->msr & FD_MSR_NONDMA)) { 1009 if (!(fdctrl->msr & FD_MSR_NONDMA)) {
1031 DMA_release_DREQ(fdctrl->dma_chann); 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 fdctrl->msr &= ~FD_MSR_NONDMA; 1013 fdctrl->msr &= ~FD_MSR_NONDMA;
1035 fdctrl_set_fifo(fdctrl, 7, 1); 1014 fdctrl_set_fifo(fdctrl, 7, 1);
1036 } 1015 }
@@ -1079,10 +1058,11 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction) @@ -1079,10 +1058,11 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction)
1079 default: 1058 default:
1080 break; 1059 break;
1081 } 1060 }
  1061 +
1082 /* Set the FIFO state */ 1062 /* Set the FIFO state */
1083 fdctrl->data_dir = direction; 1063 fdctrl->data_dir = direction;
1084 fdctrl->data_pos = 0; 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 if (fdctrl->fifo[0] & 0x80) 1066 if (fdctrl->fifo[0] & 0x80)
1087 fdctrl->data_state |= FD_STATE_MULTI; 1067 fdctrl->data_state |= FD_STATE_MULTI;
1088 else 1068 else
@@ -1116,7 +1096,7 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction) @@ -1116,7 +1096,7 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction)
1116 (direction == FD_DIR_WRITE && dma_mode == 2) || 1096 (direction == FD_DIR_WRITE && dma_mode == 2) ||
1117 (direction == FD_DIR_READ && dma_mode == 1)) { 1097 (direction == FD_DIR_READ && dma_mode == 1)) {
1118 /* No access is allowed until DMA transfer has completed */ 1098 /* No access is allowed until DMA transfer has completed */
1119 - fdctrl->state |= FD_CTRL_BUSY; 1099 + fdctrl->msr &= ~FD_MSR_RQM;
1120 /* Now, we just have to wait for the DMA controller to 1100 /* Now, we just have to wait for the DMA controller to
1121 * recall us... 1101 * recall us...
1122 */ 1102 */
@@ -1129,6 +1109,8 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction) @@ -1129,6 +1109,8 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction)
1129 } 1109 }
1130 FLOPPY_DPRINTF("start non-DMA transfer\n"); 1110 FLOPPY_DPRINTF("start non-DMA transfer\n");
1131 fdctrl->msr |= FD_MSR_NONDMA; 1111 fdctrl->msr |= FD_MSR_NONDMA;
  1112 + if (direction != FD_DIR_WRITE)
  1113 + fdctrl->msr |= FD_MSR_DIO;
1132 /* IO based transfer: calculate len */ 1114 /* IO based transfer: calculate len */
1133 fdctrl_raise_irq(fdctrl, 0x00); 1115 fdctrl_raise_irq(fdctrl, 0x00);
1134 1116
@@ -1154,7 +1136,7 @@ static int fdctrl_transfer_handler (void *opaque, int nchan, @@ -1154,7 +1136,7 @@ static int fdctrl_transfer_handler (void *opaque, int nchan,
1154 uint8_t status0 = 0x00, status1 = 0x00, status2 = 0x00; 1136 uint8_t status0 = 0x00, status1 = 0x00, status2 = 0x00;
1155 1137
1156 fdctrl = opaque; 1138 fdctrl = opaque;
1157 - if (!(fdctrl->state & FD_CTRL_BUSY)) { 1139 + if (fdctrl->msr & FD_MSR_RQM) {
1158 FLOPPY_DPRINTF("Not in DMA transfer mode !\n"); 1140 FLOPPY_DPRINTF("Not in DMA transfer mode !\n");
1159 return 0; 1141 return 0;
1160 } 1142 }
@@ -1263,9 +1245,9 @@ static uint32_t fdctrl_read_data (fdctrl_t *fdctrl) @@ -1263,9 +1245,9 @@ static uint32_t fdctrl_read_data (fdctrl_t *fdctrl)
1263 int pos; 1245 int pos;
1264 1246
1265 cur_drv = get_cur_drv(fdctrl); 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 return 0; 1251 return 0;
1270 } 1252 }
1271 pos = fdctrl->data_pos; 1253 pos = fdctrl->data_pos;
@@ -1708,11 +1690,11 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) @@ -1708,11 +1690,11 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value)
1708 FLOPPY_DPRINTF("Floppy controller in RESET state !\n"); 1690 FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
1709 return; 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 return; 1695 return;
1715 } 1696 }
  1697 + fdctrl->dsr &= ~FD_DSR_PWRDOWN;
1716 /* Is it write command time ? */ 1698 /* Is it write command time ? */
1717 if (fdctrl->msr & FD_MSR_NONDMA) { 1699 if (fdctrl->msr & FD_MSR_NONDMA) {
1718 /* FIFO data write */ 1700 /* FIFO data write */
@@ -1729,7 +1711,7 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) @@ -1729,7 +1711,7 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value)
1729 /* Switch from transfer mode to status mode 1711 /* Switch from transfer mode to status mode
1730 * then from status mode to command mode 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 fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00); 1715 fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00);
1734 return; 1716 return;
1735 } 1717 }
@@ -1812,7 +1794,6 @@ static fdctrl_t *fdctrl_init_common (qemu_irq irq, int dma_chann, @@ -1812,7 +1794,6 @@ static fdctrl_t *fdctrl_init_common (qemu_irq irq, int dma_chann,
1812 fd_init(&fdctrl->drives[i], fds[i]); 1794 fd_init(&fdctrl->drives[i], fds[i]);
1813 } 1795 }
1814 fdctrl_reset(fdctrl, 0); 1796 fdctrl_reset(fdctrl, 0);
1815 - fdctrl->state = FD_CTRL_ACTIVE;  
1816 register_savevm("fdc", io_base, 1, fdc_save, fdc_load, fdctrl); 1797 register_savevm("fdc", io_base, 1, fdc_save, fdc_load, fdctrl);
1817 qemu_register_reset(fdctrl_external_reset, fdctrl); 1798 qemu_register_reset(fdctrl_external_reset, fdctrl);
1818 for (i = 0; i < MAX_FD; i++) { 1799 for (i = 0; i < MAX_FD; i++) {