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 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++) {
... ...