- Timestamp:
- Nov 25, 2019 8:13:52 AM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevFdc.cpp
r82025 r82152 465 465 static void fdctrl_reset(fdctrl_t *fdctrl, int do_irq); 466 466 static void fdctrl_reset_fifo(fdctrl_t *fdctrl); 467 static void fdctrl_raise_irq(fdctrl_t *fdctrl, uint8_t status0);468 467 static fdrive_t *get_cur_drv(fdctrl_t *fdctrl); 469 468 … … 651 650 /* Controller state */ 652 651 TMTIMERHANDLE hResultTimer; 652 653 /* Interrupt delay timers. */ 654 TMTIMERHANDLE hXferDelayTimer; 655 TMTIMERHANDLE hIrqDelayTimer; 656 uint16_t uIrqDelayMsec; 657 uint8_t st0; 658 uint8_t st1; 659 uint8_t st2; 660 653 661 uint8_t sra; 654 662 uint8_t srb; … … 770 778 } 771 779 772 static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status0)780 static void fdctrl_raise_irq_now(fdctrl_t *fdctrl, uint8_t status0) 773 781 { 774 782 if (!(fdctrl->sra & FD_SRA_INTPEND)) { … … 789 797 fdctrl->status0 = status0; 790 798 FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", fdctrl->status0); 799 } 800 801 static void fdctrl_raise_irq(fdctrl_t *fdctrl, uint8_t status0) 802 { 803 if (!fdctrl->uIrqDelayMsec) 804 { 805 /* If not IRQ delay needed, trigger the interrupt now. */ 806 fdctrl_raise_irq_now(fdctrl, status0); 807 } 808 else 809 { 810 /* Otherwise schedule completion after a short while. */ 811 fdctrl->st0 = status0; 812 PDMDevHlpTimerSetMillies(fdctrl->pDevIns, fdctrl->hIrqDelayTimer, fdctrl->uIrqDelayMsec); 813 } 791 814 } 792 815 … … 1094 1117 1095 1118 /* Callback for transfer end (stop or abort) */ 1096 static void fdctrl_stop_transfer (fdctrl_t *fdctrl, uint8_t status0,1097 uint8_t status1, uint8_t status2)1119 static void fdctrl_stop_transfer_now(fdctrl_t *fdctrl, uint8_t status0, 1120 uint8_t status1, uint8_t status2) 1098 1121 { 1099 1122 fdrive_t *cur_drv; … … 1121 1144 fdctrl->msr &= ~FD_MSR_NONDMA; 1122 1145 fdctrl_set_fifo(fdctrl, 7, 1); 1146 } 1147 1148 static void fdctrl_stop_transfer(fdctrl_t *fdctrl, uint8_t status0, 1149 uint8_t status1, uint8_t status2) 1150 { 1151 if (!fdctrl->uIrqDelayMsec) 1152 { 1153 /* If not IRQ delay needed, just stop the transfer and trigger IRQ now. */ 1154 fdctrl_stop_transfer_now(fdctrl, status0, status1, status2); 1155 } 1156 else 1157 { 1158 /* Otherwise schedule completion after a short while. */ 1159 fdctrl->st0 = status0; 1160 fdctrl->st1 = status1; 1161 fdctrl->st2 = status2; 1162 PDMDevHlpTimerSetMillies(fdctrl->pDevIns, fdctrl->hXferDelayTimer, fdctrl->uIrqDelayMsec); 1163 } 1123 1164 } 1124 1165 … … 1242 1283 if (direction != FD_DIR_WRITE) 1243 1284 fdctrl->msr |= FD_MSR_DIO; 1285 1244 1286 /* IO based transfer: calculate len */ 1245 1287 fdctrl_raise_irq(fdctrl, 0x00); 1246 1247 1288 return; 1248 1289 } … … 2168 2209 FLOPPY_DPRINTF("read id when no disk in drive\n"); 2169 2210 /// @todo This is wrong! Command should not complete. 2170 fdctrl_stop_transfer (fdctrl, FD_SR0_ABNTERM, FD_SR1_MA | FD_SR1_ND, FD_SR2_MD);2211 fdctrl_stop_transfer_now(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA | FD_SR1_ND, FD_SR2_MD); 2171 2212 } else if ((fdctrl->dsr & FD_DSR_DRATEMASK) != cur_drv->media_rate) { 2172 2213 FLOPPY_DPRINTF("read id rate mismatch (fdc=%d, media=%d)\n", 2173 2214 fdctrl->dsr & FD_DSR_DRATEMASK, cur_drv->media_rate); 2174 fdctrl_stop_transfer (fdctrl, FD_SR0_ABNTERM, FD_SR1_MA | FD_SR1_ND, FD_SR2_MD);2215 fdctrl_stop_transfer_now(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA | FD_SR1_ND, FD_SR2_MD); 2175 2216 } else if (cur_drv->track >= cur_drv->max_track) { 2176 2217 FLOPPY_DPRINTF("read id past last track (%d >= %d)\n", 2177 2218 cur_drv->track, cur_drv->max_track); 2178 2219 cur_drv->ltrk = 0; 2179 fdctrl_stop_transfer (fdctrl, FD_SR0_ABNTERM, FD_SR1_MA | FD_SR1_ND, FD_SR2_MD);2220 fdctrl_stop_transfer_now(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA | FD_SR1_ND, FD_SR2_MD); 2180 2221 } 2181 2222 else 2182 fdctrl_stop_transfer (fdctrl, 0x00, 0x00, 0x00);2223 fdctrl_stop_transfer_now(fdctrl, 0x00, 0x00, 0x00); 2183 2224 } 2184 2225 … … 2233 2274 2234 2275 /** 2276 * @callback_method_impl{FNTMTIMERDEV} 2277 */ 2278 static DECLCALLBACK(void) fdcTransferDelayTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser) 2279 { 2280 RT_NOREF(pDevIns, pTimer); 2281 fdctrl_t *fdctrl = (fdctrl_t *)pvUser; 2282 fdctrl_stop_transfer_now(fdctrl, fdctrl->st0, fdctrl->st1, fdctrl->st2); 2283 } 2284 2285 /** 2286 * @callback_method_impl{FNTMTIMERDEV} 2287 */ 2288 static DECLCALLBACK(void) fdcIrqDelayTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser) 2289 { 2290 RT_NOREF(pDevIns, pTimer); 2291 fdctrl_t *fdctrl = (fdctrl_t *)pvUser; 2292 fdctrl_raise_irq_now(fdctrl, fdctrl->st0); 2293 } 2294 2295 2296 2297 /* -=-=-=-=-=-=-=-=- I/O Port Access Handlers -=-=-=-=-=-=-=-=- */ 2298 /** 2235 2299 * @callback_method_impl{FNIOMIOPORTNEWIN, Handling 0x3f1..0x3f5 accesses.} 2236 2300 */ … … 2291 2355 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; 2292 2356 unsigned int i; 2357 int rc; 2293 2358 2294 2359 /* Save the FDC I/O registers... */ … … 2338 2403 pHlp->pfnSSMPutU8(pSSM, d->sect); 2339 2404 } 2405 rc = pHlp->pfnTimerSave(pDevIns, pThis->hXferDelayTimer, pSSM); 2406 if (RT_FAILURE(rc)) 2407 return rc; 2408 2409 rc = pHlp->pfnTimerSave(pDevIns, pThis->hIrqDelayTimer, pSSM); 2410 if (RT_FAILURE(rc)) 2411 return rc; 2412 2340 2413 return pHlp->pfnTimerSave(pDevIns, pThis->hResultTimer, pSSM); 2341 2414 } … … 2758 2831 * Validate configuration. 2759 2832 */ 2760 PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "IRQ|DMA|MemMapped|IOBase|StatusA ", "");2833 PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "IRQ|DMA|MemMapped|IOBase|StatusA|IRQDelay", ""); 2761 2834 2762 2835 /* … … 2775 2848 rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "MemMapped", &fMemMapped, false); 2776 2849 AssertMsgRCReturn(rc, ("Configuration error: Failed to read bool value MemMapped rc=%Rrc\n", rc), rc); 2850 2851 uint16_t uIrqDelay; 2852 rc = CFGMR3QueryU16Def(pCfg, "IRQDelay", &uIrqDelay, 0); 2853 AssertMsgRCReturn(rc, ("Configuration error: Failed to read U16 IRQDelay, rc=%Rrc\n", rc), rc); 2777 2854 2778 2855 bool fStatusA; … … 2822 2899 TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "FDC Timer", &pThis->hResultTimer); 2823 2900 AssertRCReturn(rc, rc); 2901 2902 /* 2903 * Create the transfer delay timer. 2904 */ 2905 rc = PDMDevHlpTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, fdcTransferDelayTimer, pThis, 2906 TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "FDC Transfer Delay Timer", &pThis->hXferDelayTimer); 2907 if (RT_FAILURE(rc)) 2908 return rc; 2909 2910 /* 2911 * Create the IRQ delay timer. 2912 */ 2913 rc = PDMDevHlpTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, fdcIrqDelayTimer, pThis, 2914 TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "FDC IRQ Delay Timer", &pThis->hIrqDelayTimer); 2915 if (RT_FAILURE(rc)) 2916 return rc; 2917 2918 pThis->uIrqDelayMsec = uIrqDelay; 2824 2919 2825 2920 /*
Note:
See TracChangeset
for help on using the changeset viewer.