Changeset 56413 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Jun 14, 2015 3:43:56 AM (10 years ago)
- Location:
- trunk/src/VBox/Devices/Storage
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevATA.cpp
r56408 r56413 528 528 PDMBOTHCBDECL(int) ataIOPortWrite1Data(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb); 529 529 PDMBOTHCBDECL(int) ataIOPortRead1Data(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *u32, unsigned cb); 530 PDMBOTHCBDECL(int) ataIOPortWriteStr1Data(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrSrc, PRTGCUINTREG pcTransfer, unsigned cb); 531 PDMBOTHCBDECL(int) ataIOPortReadStr1Data(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrDst, PRTGCUINTREG pcTransfer, unsigned cb); 530 PDMBOTHCBDECL(int) ataIOPortWriteStr1Data(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint8_t const *pbSrc, 531 uint32_t *pcTransfers, unsigned cb); 532 PDMBOTHCBDECL(int) ataIOPortReadStr1Data(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint8_t *pbDst, 533 uint32_t *pcTransfers, unsigned cb); 532 534 PDMBOTHCBDECL(int) ataIOPortWrite1Other(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb); 533 535 PDMBOTHCBDECL(int) ataIOPortRead1Other(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *u32, unsigned cb); … … 5020 5022 } 5021 5023 5022 #ifndef IN_RING0 /** @todo do this in ring-0 as well - after IEM specific interface rewrite! */5023 5024 5024 5025 /** … … 5026 5027 * @see FNIOMIOPORTINSTRING for details. 5027 5028 */ 5028 PDMBOTHCBDECL(int) ataIOPortReadStr1Data(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrDst,5029 PRTGCUINTREG pcTransfer, unsigned cb)5030 { 5031 uint32_t i = (uint32_t)(uintptr_t)pvUser;5029 PDMBOTHCBDECL(int) ataIOPortReadStr1Data(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint8_t *pbDst, 5030 uint32_t *pcTransfers, unsigned cb) 5031 { 5032 uint32_t i = (uint32_t)(uintptr_t)pvUser; 5032 5033 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *); 5033 PATACONTROLLER pCtl = &pThis->aCts[i]; 5034 int rc = VINF_SUCCESS; 5034 PATACONTROLLER pCtl = &pThis->aCts[i]; 5035 5035 5036 5036 Assert(i < 2); 5037 5037 Assert(Port == pCtl->IOPortBase1); 5038 5039 rc = PDMCritSectEnter(&pCtl->lock, VINF_IOM_R3_IOPORT_READ); 5040 if (rc == VINF_SUCCESS) 5041 { 5042 ATADevState *s = &pCtl->aIfs[pCtl->iSelectedIf]; 5043 uint32_t cTransAvailable; 5044 uint32_t cTransfer = *pcTransfer; 5045 uint32_t cbTransfer; 5046 RTGCPTR GCDst = *pGCPtrDst; 5047 Assert(cb == 2 || cb == 4); 5048 5049 cTransAvailable = (s->iIOBufferPIODataEnd - s->iIOBufferPIODataStart) / cb; 5050 # ifndef IN_RING3 5051 /* Deal with the unlikely case where no data (or not enough for the read length operation) is available; go back to ring 3. */ 5052 if (!cTransAvailable) 5053 { 5038 Assert(*pcTransfers > 0); 5039 5040 int rc; 5041 if (cb == 2 || cb == 4) 5042 { 5043 rc = PDMCritSectEnter(&pCtl->lock, VINF_IOM_R3_IOPORT_READ); 5044 if (rc == VINF_SUCCESS) 5045 { 5046 ATADevState *s = &pCtl->aIfs[pCtl->iSelectedIf]; 5047 5048 uint32_t const offStart = s->iIOBufferPIODataStart; 5049 if (offStart < s->iIOBufferPIODataEnd) 5050 { 5051 /* 5052 * Figure how much we can copy. Usually it's the same as the request. 5053 * The last transfer unit cannot be handled in RC, as it involves 5054 * thread communication. In R0 we let the non-string callback handle it, 5055 * and ditto for overflows/dummy data. 5056 */ 5057 uint32_t cAvailable = (s->iIOBufferPIODataEnd - offStart) / cb; 5058 #ifndef IN_RING3 5059 if (cAvailable > 0) 5060 cAvailable--; 5061 #endif 5062 uint32_t const cRequested = *pcTransfers; 5063 if (cAvailable > cRequested) 5064 cAvailable = cRequested; 5065 uint32_t const cbTransfer = cAvailable * cb; 5066 if ( offStart + cbTransfer <= s->cbIOBuffer 5067 && cbTransfer > 0) 5068 { 5069 /* 5070 * Do the transfer. 5071 */ 5072 uint8_t const *pbSrc = s->CTX_SUFF(pbIOBuffer) + offStart; 5073 memcpy(pbDst, pbSrc, cbTransfer); 5074 Log3(("%s: addr=%#x cb=%#x cbTransfer=%#x val=%.*Rhxd\n", 5075 __FUNCTION__, Port, cb, cbTransfer, cbTransfer, pbSrc)); 5076 s->iIOBufferPIODataStart = offStart + cbTransfer; 5077 5078 #ifdef IN_RING3 5079 if (s->iIOBufferPIODataStart >= s->iIOBufferPIODataEnd) 5080 ataHCPIOTransferFinish(pCtl, s); 5081 #endif 5082 *pcTransfers = cRequested - cAvailable; 5083 } 5084 else 5085 Log2(("%s: DUMMY/Overflow!\n", __FUNCTION__)); 5086 } 5087 else 5088 { 5089 /* 5090 * Dummy read (shouldn't happen) return 0xff like the non-string handler. 5091 */ 5092 Log2(("%s: DUMMY data (%#x bytes)\n", __FUNCTION__, *pcTransfers * cb)); 5093 memset(pbDst, 0xff, *pcTransfers * cb); 5094 *pcTransfers = 0; 5095 } 5096 5054 5097 PDMCritSectLeave(&pCtl->lock); 5055 return VINF_IOM_R3_IOPORT_READ; 5056 } 5057 /* The last transfer unit cannot be handled in GC, as it involves thread communication. */ 5058 cTransAvailable--; 5059 # endif /* !IN_RING3 */ 5060 /* Do not handle the dummy transfer stuff here, leave it to the single-word transfers. 5061 * They are not performance-critical and generally shouldn't occur at all. */ 5062 if (cTransAvailable > cTransfer) 5063 cTransAvailable = cTransfer; 5064 cbTransfer = cTransAvailable * cb; 5065 5066 rc = PGMPhysSimpleDirtyWriteGCPtr(PDMDevHlpGetVMCPU(pDevIns), GCDst, s->CTX_SUFF(pbIOBuffer) + s->iIOBufferPIODataStart, cbTransfer); 5067 # ifndef IN_RING3 5068 /* Paranoia. */ 5069 if (RT_FAILURE(rc)) 5070 { 5071 PDMCritSectLeave(&pCtl->lock); 5072 AssertFailed(); 5073 return VINF_IOM_R3_IOPORT_READ; 5074 } 5075 # else 5076 Assert(rc == VINF_SUCCESS); 5077 # endif 5078 5079 if (cbTransfer) 5080 Log3(("%s: addr=%#x val=%.*Rhxs\n", __FUNCTION__, Port, cbTransfer, s->CTX_SUFF(pbIOBuffer) + s->iIOBufferPIODataStart)); 5081 s->iIOBufferPIODataStart += cbTransfer; 5082 *pGCPtrDst = (RTGCPTR)((RTGCUINTPTR)GCDst + cbTransfer); 5083 *pcTransfer = cTransfer - cTransAvailable; 5084 # ifdef IN_RING3 5085 if (s->iIOBufferPIODataStart >= s->iIOBufferPIODataEnd) 5086 ataHCPIOTransferFinish(pCtl, s); 5087 # endif /* IN_RING3 */ 5088 PDMCritSectLeave(&pCtl->lock); 5098 } 5099 } 5100 /* 5101 * Let the non-string I/O callback handle 1 byte reads. 5102 */ 5103 else 5104 { 5105 Log2(("%s: 1 byte read (%#x transfers)\n", *pcTransfers)); 5106 AssertFailed(); 5107 rc = VINF_SUCCESS; 5089 5108 } 5090 5109 return rc; … … 5096 5115 * @see FNIOMIOPORTOUTSTRING for details. 5097 5116 */ 5098 PDMBOTHCBDECL(int) ataIOPortWriteStr1Data(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrSrc,5099 PRTGCUINTREG pcTransfer, unsigned cb)5100 { 5101 uint32_t i = (uint32_t)(uintptr_t)pvUser;5117 PDMBOTHCBDECL(int) ataIOPortWriteStr1Data(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint8_t const *pbSrc, 5118 uint32_t *pcTransfers, unsigned cb) 5119 { 5120 uint32_t i = (uint32_t)(uintptr_t)pvUser; 5102 5121 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *); 5103 PATACONTROLLER pCtl = &pThis->aCts[i]; 5104 int rc; 5122 PATACONTROLLER pCtl = &pThis->aCts[i]; 5105 5123 5106 5124 Assert(i < 2); 5107 5125 Assert(Port == pCtl->IOPortBase1); 5108 5109 rc = PDMCritSectEnter(&pCtl->lock, VINF_IOM_R3_IOPORT_WRITE); 5110 if (rc == VINF_SUCCESS) 5111 { 5112 ATADevState *s = &pCtl->aIfs[pCtl->iSelectedIf]; 5113 uint32_t cTransfer = *pcTransfer; 5114 uint32_t cbTransfer; 5115 RTGCPTR GCSrc = *pGCPtrSrc; 5116 Assert(cb == 2 || cb == 4); 5117 5118 uint32_t cTransAvailable = (s->iIOBufferPIODataEnd - s->iIOBufferPIODataStart) / cb; 5119 # ifndef IN_RING3 5120 /* Deal with the unlikely case where no data (or not enough for the read length operation) is available; go back to ring 3. */ 5121 if (!cTransAvailable) 5122 { 5126 Assert(*pcTransfers > 0); 5127 5128 int rc; 5129 if (cb == 2 || cb == 4) 5130 { 5131 rc = PDMCritSectEnter(&pCtl->lock, VINF_IOM_R3_IOPORT_WRITE); 5132 if (rc == VINF_SUCCESS) 5133 { 5134 ATADevState *s = &pCtl->aIfs[pCtl->iSelectedIf]; 5135 5136 uint32_t const offStart = s->iIOBufferPIODataStart; 5137 if (offStart < s->iIOBufferPIODataEnd) 5138 { 5139 /* 5140 * Figure how much we can copy. Usually it's the same as the request. 5141 * The last transfer unit cannot be handled in RC, as it involves 5142 * thread communication. In R0 we let the non-string callback handle it, 5143 * and ditto for overflows/dummy data. 5144 */ 5145 uint32_t cAvailable = (s->iIOBufferPIODataEnd - offStart) / cb; 5146 #ifndef IN_RING3 5147 if (cAvailable) 5148 cAvailable--; 5149 #endif 5150 uint32_t const cRequested = *pcTransfers; 5151 if (cAvailable > cRequested) 5152 cAvailable = cRequested; 5153 uint32_t const cbTransfer = cAvailable * cb; 5154 if ( offStart + cbTransfer <= s->cbIOBuffer 5155 && cbTransfer) 5156 { 5157 /* 5158 * Do the transfer. 5159 */ 5160 void *pvDst = s->CTX_SUFF(pbIOBuffer) + offStart; 5161 memcpy(pvDst, pbSrc, cbTransfer); 5162 Log3(("%s: addr=%#x val=%.*Rhxs\n", __FUNCTION__, Port, cbTransfer, pvDst)); 5163 s->iIOBufferPIODataStart = offStart + cbTransfer; 5164 5165 #ifdef IN_RING3 5166 if (s->iIOBufferPIODataStart >= s->iIOBufferPIODataEnd) 5167 ataHCPIOTransferFinish(pCtl, s); 5168 #endif 5169 *pcTransfers = cRequested - cAvailable; 5170 } 5171 else 5172 Log2(("%s: DUMMY/Overflow!\n", __FUNCTION__)); 5173 } 5174 else 5175 { 5176 Log2(("%s: DUMMY data (%#x bytes)\n", __FUNCTION__, *pcTransfers * cb)); 5177 *pcTransfers = 0; 5178 } 5179 5123 5180 PDMCritSectLeave(&pCtl->lock); 5124 return VINF_IOM_R3_IOPORT_WRITE; 5125 } 5126 /* The last transfer unit cannot be handled in GC, as it involves thread communication. */ 5127 cTransAvailable--; 5128 # endif /* !IN_RING3 */ 5129 /* Do not handle the dummy transfer stuff here, leave it to the single-word transfers. 5130 * They are not performance-critical and generally shouldn't occur at all. */ 5131 if (cTransAvailable > cTransfer) 5132 cTransAvailable = cTransfer; 5133 cbTransfer = cTransAvailable * cb; 5134 5135 rc = PGMPhysSimpleReadGCPtr(PDMDevHlpGetVMCPU(pDevIns), s->CTX_SUFF(pbIOBuffer) + s->iIOBufferPIODataStart, GCSrc, cbTransfer); 5136 # ifndef IN_RING3 5137 /* Paranoia. */ 5138 if (RT_FAILURE(rc)) 5139 { 5140 PDMCritSectLeave(&pCtl->lock); 5141 AssertFailed(); 5142 return VINF_IOM_R3_IOPORT_WRITE; 5143 } 5144 # else 5145 Assert(rc == VINF_SUCCESS); 5146 # endif 5147 5148 if (cbTransfer) 5149 Log3(("%s: addr=%#x val=%.*Rhxs\n", __FUNCTION__, Port, cbTransfer, s->CTX_SUFF(pbIOBuffer) + s->iIOBufferPIODataStart)); 5150 s->iIOBufferPIODataStart += cbTransfer; 5151 *pGCPtrSrc = (RTGCPTR)((RTGCUINTPTR)GCSrc + cbTransfer); 5152 *pcTransfer = cTransfer - cTransAvailable; 5153 # ifdef IN_RING3 5154 if (s->iIOBufferPIODataStart >= s->iIOBufferPIODataEnd) 5155 ataHCPIOTransferFinish(pCtl, s); 5156 # endif /* IN_RING3 */ 5157 PDMCritSectLeave(&pCtl->lock); 5158 } 5181 } 5182 } 5183 /* 5184 * Let the non-string I/O callback handle 1 byte reads. 5185 */ 5186 else 5187 { 5188 Log2(("%s: 1 byte write (%#x transfers)\n", *pcTransfers)); 5189 AssertFailed(); 5190 rc = VINF_SUCCESS; 5191 } 5192 5159 5193 return rc; 5160 5194 } 5161 5162 #endif /* !IN_RING0 */5163 5195 5164 5196 … … 7491 7523 if (fR0Enabled) 7492 7524 { 7493 #if 17525 #if 0 7494 7526 rc = PDMDevHlpIOPortRegisterR0(pDevIns, pThis->aCts[i].IOPortBase1, 1, (RTR0PTR)i, 7495 7527 "ataIOPortWrite1Data", "ataIOPortRead1Data", NULL, NULL, "ATA I/O Base 1 - Data"); -
trunk/src/VBox/Devices/Storage/DevBusLogic.cpp
r56292 r56413 2575 2575 * @see FNIOMIOPORTOUTSTRING for details. 2576 2576 */ 2577 static DECLCALLBACK(int) buslogicR3BiosIoPortWriteStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrSrc,2578 PRTGCUINTREG pcTransfer, unsigned cb)2577 static DECLCALLBACK(int) buslogicR3BiosIoPortWriteStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, 2578 uint8_t const *pbSrc, uint32_t *pcTransfers, unsigned cb) 2579 2579 { 2580 2580 PBUSLOGIC pBusLogic = PDMINS_2_DATA(pDevIns, PBUSLOGIC); 2581 int rc; 2582 2583 Log2(("#%d %s: pvUser=%#p cb=%d Port=%#x\n", 2584 pDevIns->iInstance, __FUNCTION__, pvUser, cb, Port)); 2585 2586 rc = vboxscsiWriteString(pDevIns, &pBusLogic->VBoxSCSI, (Port - BUSLOGIC_BIOS_IO_PORT), 2587 pGCPtrSrc, pcTransfer, cb); 2581 Log2(("#%d %s: pvUser=%#p cb=%d Port=%#x\n", pDevIns->iInstance, __FUNCTION__, pvUser, cb, Port)); 2582 2583 int rc = vboxscsiWriteString(pDevIns, &pBusLogic->VBoxSCSI, (Port - BUSLOGIC_BIOS_IO_PORT), pbSrc, pcTransfers, cb); 2588 2584 if (rc == VERR_MORE_DATA) 2589 2585 { … … 2601 2597 * @see FNIOMIOPORTINSTRING for details. 2602 2598 */ 2603 static DECLCALLBACK(int) buslogicR3BiosIoPortReadStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrDst,2604 PRTGCUINTREG pcTransfer, unsigned cb)2599 static DECLCALLBACK(int) buslogicR3BiosIoPortReadStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, 2600 uint8_t *pbDst, uint32_t *pcTransfers, unsigned cb) 2605 2601 { 2606 2602 PBUSLOGIC pBusLogic = PDMINS_2_DATA(pDevIns, PBUSLOGIC); 2607 2608 LogFlowFunc(("#%d %s: pvUser=%#p cb=%d Port=%#x\n", 2609 pDevIns->iInstance, __FUNCTION__, pvUser, cb, Port)); 2603 LogFlowFunc(("#%d %s: pvUser=%#p cb=%d Port=%#x\n", pDevIns->iInstance, __FUNCTION__, pvUser, cb, Port)); 2610 2604 2611 2605 return vboxscsiReadString(pDevIns, &pBusLogic->VBoxSCSI, (Port - BUSLOGIC_BIOS_IO_PORT), 2612 p GCPtrDst, pcTransfer, cb);2606 pbDst, pcTransfers, cb); 2613 2607 } 2614 2608 -
trunk/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp
r56292 r56413 3852 3852 */ 3853 3853 static DECLCALLBACK(int) lsilogicR3IsaIOPortWriteStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, 3854 PRTGCPTR pGCPtrSrc, PRTGCUINTREG pcTransfer, unsigned cb)3854 uint8_t const *pbSrc, uint32_t *pcTransfers, unsigned cb) 3855 3855 { 3856 3856 PLSILOGICSCSI pThis = PDMINS_2_DATA(pDevIns, PLSILOGICSCSI); … … 3860 3860 ? Port - LSILOGIC_BIOS_IO_PORT 3861 3861 : Port - LSILOGIC_SAS_BIOS_IO_PORT; 3862 int rc = vboxscsiWriteString(pDevIns, &pThis->VBoxSCSI, iRegister, p GCPtrSrc, pcTransfer, cb);3862 int rc = vboxscsiWriteString(pDevIns, &pThis->VBoxSCSI, iRegister, pbSrc, pcTransfers, cb); 3863 3863 if (rc == VERR_MORE_DATA) 3864 3864 { … … 3876 3876 * Port I/O Handler for primary port range IN string operations.} 3877 3877 */ 3878 static DECLCALLBACK(int) lsilogicR3IsaIOPortReadStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrDst,3879 PRTGCUINTREG pcTransfer, unsigned cb)3878 static DECLCALLBACK(int) lsilogicR3IsaIOPortReadStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, 3879 uint8_t *pbDst, uint32_t *pcTransfers, unsigned cb) 3880 3880 { 3881 3881 PLSILOGICSCSI pThis = PDMINS_2_DATA(pDevIns, PLSILOGICSCSI); 3882 3883 LogFlowFunc(("#%d %s: pvUser=%#p cb=%d Port=%#x\n", 3884 pDevIns->iInstance, __FUNCTION__, pvUser, cb, Port)); 3882 LogFlowFunc(("#%d %s: pvUser=%#p cb=%d Port=%#x\n", pDevIns->iInstance, __FUNCTION__, pvUser, cb, Port)); 3885 3883 3886 3884 uint8_t iRegister = pThis->enmCtrlType == LSILOGICCTRLTYPE_SCSI_SPI 3887 3885 ? Port - LSILOGIC_BIOS_IO_PORT 3888 3886 : Port - LSILOGIC_SAS_BIOS_IO_PORT; 3889 return vboxscsiReadString(pDevIns, &pThis->VBoxSCSI, iRegister, p GCPtrDst, pcTransfer, cb);3887 return vboxscsiReadString(pDevIns, &pThis->VBoxSCSI, iRegister, pbDst, pcTransfers, cb); 3890 3888 } 3891 3889 -
trunk/src/VBox/Devices/Storage/VBoxSCSI.cpp
r56292 r56413 39 39 * Resets the state. 40 40 */ 41 static void vboxscsiReset(PVBOXSCSI pVBoxSCSI) 42 { 43 pVBoxSCSI->regIdentify = 0; 41 static void vboxscsiReset(PVBOXSCSI pVBoxSCSI, bool fEverything) 42 { 43 if (fEverything) 44 { 45 pVBoxSCSI->regIdentify = 0; 46 pVBoxSCSI->fBusy = false; 47 } 44 48 pVBoxSCSI->cbCDB = 0; 45 memset(pVBoxSCSI->abCDB, 0, sizeof(pVBoxSCSI->abCDB));49 RT_ZERO(pVBoxSCSI->abCDB); 46 50 pVBoxSCSI->iCDB = 0; 47 pVBoxSCSI->fBusy = false;48 51 pVBoxSCSI->rcCompletion = 0; 49 52 pVBoxSCSI->uTargetDevice = 0; … … 52 55 if (pVBoxSCSI->pbBuf) 53 56 RTMemFree(pVBoxSCSI->pbBuf); 54 55 57 pVBoxSCSI->pbBuf = NULL; 56 58 pVBoxSCSI->enmState = VBOXSCSISTATE_NO_COMMAND; … … 66 68 { 67 69 pVBoxSCSI->pbBuf = NULL; 68 vboxscsiReset(pVBoxSCSI );70 vboxscsiReset(pVBoxSCSI, true /*fEverything*/); 69 71 70 72 return VINF_SUCCESS; … … 102 104 { 103 105 /* If we're not in the 'command ready' state, there may not even be a buffer yet. */ 104 if ((pVBoxSCSI->enmState == VBOXSCSISTATE_COMMAND_READY) && pVBoxSCSI->cbBuf > 0) 106 if ( pVBoxSCSI->enmState == VBOXSCSISTATE_COMMAND_READY 107 && pVBoxSCSI->cbBuf > 0) 105 108 { 106 109 AssertMsg(pVBoxSCSI->pbBuf, ("pBuf is NULL\n")); 107 Assert(pVBoxSCSI->enmState == VBOXSCSISTATE_COMMAND_READY);108 110 Assert(!pVBoxSCSI->fBusy); 109 111 uVal = pVBoxSCSI->pbBuf[pVBoxSCSI->iBuf]; 110 112 pVBoxSCSI->iBuf++; 111 113 pVBoxSCSI->cbBuf--; 114 115 /* When the guest reads the last byte from the data in buffer, clear 116 everything and reset command buffer. */ 112 117 if (pVBoxSCSI->cbBuf == 0) 113 { 114 /** The guest read the last byte from the data in buffer. 115 * Clear everything and reset command buffer. 116 */ 117 RTMemFree(pVBoxSCSI->pbBuf); 118 pVBoxSCSI->pbBuf = NULL; 119 pVBoxSCSI->cbCDB = 0; 120 pVBoxSCSI->iCDB = 0; 121 pVBoxSCSI->iBuf = 0; 122 pVBoxSCSI->rcCompletion = 0; 123 pVBoxSCSI->uTargetDevice = 0; 124 pVBoxSCSI->enmState = VBOXSCSISTATE_NO_COMMAND; 125 memset(pVBoxSCSI->abCDB, 0, sizeof(pVBoxSCSI->abCDB)); 126 } 118 vboxscsiReset(pVBoxSCSI, false /*fEverything*/); 127 119 } 128 120 break; … … 151 143 * 152 144 * @returns VBox status code. 153 * 145 * @retval VERR_MORE_DATA if a command is ready to be sent to the SCSI driver. 154 146 * @param pVBoxSCSI Pointer to the SCSI state. 155 147 * @param iRegister Index of the register to write to. … … 172 164 { 173 165 if (uVal != VBOXSCSI_TXDIR_FROM_DEVICE && uVal != VBOXSCSI_TXDIR_TO_DEVICE) 174 vboxscsiReset(pVBoxSCSI );166 vboxscsiReset(pVBoxSCSI, true /*fEverything*/); 175 167 else 176 168 { … … 181 173 else if (pVBoxSCSI->enmState == VBOXSCSISTATE_READ_CDB_SIZE_BUFHI) 182 174 { 183 uint8_t cbCDB = uVal & 0x0F; 184 175 uint8_t cbCDB = uVal & 0x0F; 185 176 if (cbCDB > VBOXSCSI_CDB_SIZE_MAX) 186 vboxscsiReset(pVBoxSCSI );177 vboxscsiReset(pVBoxSCSI, true /*fEverything*/); 187 178 else 188 179 { … … 231 222 break; 232 223 } 224 233 225 case 1: 234 226 { … … 237 229 { 238 230 /* Reset the state */ 239 vboxscsiReset(pVBoxSCSI );240 } 241 else 231 vboxscsiReset(pVBoxSCSI, true /*fEverything*/); 232 } 233 else if (pVBoxSCSI->cbBuf > 0) 242 234 { 243 235 pVBoxSCSI->pbBuf[pVBoxSCSI->iBuf++] = uVal; 244 if (pVBoxSCSI->iBuf == pVBoxSCSI->cbBuf) 236 pVBoxSCSI->cbBuf--; 237 if (pVBoxSCSI->cbBuf == 0) 245 238 { 246 239 rc = VERR_MORE_DATA; … … 248 241 } 249 242 } 250 break; 251 } 243 /* else: Ignore extra data, request pending or something. */ 244 break; 245 } 246 252 247 case 2: 253 248 { … … 255 250 break; 256 251 } 252 257 253 case 3: 258 254 { 259 255 /* Reset */ 260 vboxscsiReset(pVBoxSCSI); 261 break; 262 } 256 vboxscsiReset(pVBoxSCSI, true /*fEverything*/); 257 break; 258 } 259 263 260 default: 264 261 AssertMsgFailed(("Invalid register to write to %u\n", iRegister)); … … 335 332 336 333 if (pVBoxSCSI->uTxDir == VBOXSCSI_TXDIR_TO_DEVICE) 337 { 338 if (pVBoxSCSI->pbBuf) 339 RTMemFree(pVBoxSCSI->pbBuf); 340 pVBoxSCSI->pbBuf = NULL; 341 pVBoxSCSI->cbBuf = 0; 342 pVBoxSCSI->cbCDB = 0; 343 pVBoxSCSI->iCDB = 0; 344 pVBoxSCSI->iBuf = 0; 345 pVBoxSCSI->uTargetDevice = 0; 346 pVBoxSCSI->enmState = VBOXSCSISTATE_NO_COMMAND; 347 memset(pVBoxSCSI->abCDB, 0, sizeof(pVBoxSCSI->abCDB)); 348 } 334 vboxscsiReset(pVBoxSCSI, false /*fEverything*/); 349 335 350 336 pVBoxSCSI->rcCompletion = rcCompletion; … … 356 342 357 343 int vboxscsiReadString(PPDMDEVINS pDevIns, PVBOXSCSI pVBoxSCSI, uint8_t iRegister, 358 RTGCPTR *pGCPtrDst, PRTGCUINTREG pcTransfer, unsigned cb) 359 { 360 RTGCPTR GCDst = *pGCPtrDst; 361 uint32_t cbTransfer = *pcTransfer * cb; 362 363 LogFlowFunc(("pDevIns=%#p pVBoxSCSI=%#p iRegister=%d cTransfer=%u cb=%u\n", 364 pDevIns, pVBoxSCSI, iRegister, *pcTransfer, cb)); 344 uint8_t *pbDst, uint32_t *pcTransfers, unsigned cb) 345 { 346 LogFlowFunc(("pDevIns=%#p pVBoxSCSI=%#p iRegister=%d cTransfers=%u cb=%u\n", 347 pDevIns, pVBoxSCSI, iRegister, *pcTransfers, cb)); 348 349 /* 350 * Check preconditions, fall back to non-string I/O handler. 351 */ 352 Assert(*pcTransfers > 0); 365 353 366 354 /* Read string only valid for data in register. */ 367 AssertMsg (iRegister == 1, ("Hey only register 1 can be read from with string\n"));355 AssertMsgReturn(iRegister == 1, ("Hey! Only register 1 can be read from with string!\n"), VINF_SUCCESS); 368 356 369 357 /* Accesses without a valid buffer will be ignored. */ 370 if (!pVBoxSCSI->pbBuf) 371 return VINF_SUCCESS; 372 373 /* Also ignore attempts to read more data than is available. */ 374 Assert(cbTransfer <= pVBoxSCSI->cbBuf); 375 if (cbTransfer > pVBoxSCSI->cbBuf) 376 cbTransfer = pVBoxSCSI->cbBuf; /* Ignore excess data (not supposed to happen). */ 377 378 int rc = PGMPhysSimpleDirtyWriteGCPtr(PDMDevHlpGetVMCPU(pDevIns), GCDst, pVBoxSCSI->pbBuf + pVBoxSCSI->iBuf, cbTransfer); 379 AssertRC(rc); 380 381 *pGCPtrDst = (RTGCPTR)((RTGCUINTPTR)GCDst + cbTransfer); 382 *pcTransfer = 0; 383 384 /* Advance current buffer position. */ 385 pVBoxSCSI->iBuf += cbTransfer; 386 pVBoxSCSI->cbBuf -= cbTransfer; 387 388 if (pVBoxSCSI->cbBuf == 0) 389 { 390 /** The guest read the last byte from the data in buffer. 391 * Clear everything and reset command buffer. 392 */ 393 RTMemFree(pVBoxSCSI->pbBuf); 394 pVBoxSCSI->pbBuf = NULL; 395 pVBoxSCSI->cbCDB = 0; 396 pVBoxSCSI->iCDB = 0; 397 pVBoxSCSI->iBuf = 0; 398 pVBoxSCSI->uTargetDevice = 0; 399 pVBoxSCSI->enmState = VBOXSCSISTATE_NO_COMMAND; 400 memset(pVBoxSCSI->abCDB, 0, sizeof(pVBoxSCSI->abCDB)); 401 } 358 AssertReturn(!pVBoxSCSI->pbBuf, VINF_SUCCESS); 359 360 /* Check state. */ 361 AssertReturn(pVBoxSCSI->enmState == VBOXSCSISTATE_COMMAND_READY, VINF_SUCCESS); 362 Assert(!pVBoxSCSI->fBusy); 363 364 /* 365 * Also ignore attempts to read more data than is available. 366 */ 367 int rc = VINF_SUCCESS; 368 uint32_t cbTransfer = *pcTransfers * cb; 369 if (pVBoxSCSI->cbBuf > 0) /* Think cbBufLeft, not cbBuf! */ 370 { 371 Assert(cbTransfer <= pVBoxSCSI->cbBuf); 372 if (cbTransfer > pVBoxSCSI->cbBuf) 373 { 374 memset(pbDst + pVBoxSCSI->cbBuf, 0xff, cbTransfer - pVBoxSCSI->cbBuf); 375 cbTransfer = pVBoxSCSI->cbBuf; /* Ignore excess data (not supposed to happen). */ 376 } 377 378 /* Copy the data and adance the buffer position. */ 379 memcpy(pbDst, pVBoxSCSI->pbBuf + pVBoxSCSI->iBuf, cbTransfer); 380 381 /* Advance current buffer position. */ 382 pVBoxSCSI->iBuf += cbTransfer; 383 pVBoxSCSI->cbBuf -= cbTransfer; 384 385 /* When the guest reads the last byte from the data in buffer, clear 386 everything and reset command buffer. */ 387 if (pVBoxSCSI->cbBuf == 0) 388 vboxscsiReset(pVBoxSCSI, false /*fEverything*/); 389 } 390 else 391 { 392 AssertFailed(); 393 memset(pbDst, 0, cbTransfer); 394 } 395 *pcTransfers = 0; 402 396 403 397 return rc; … … 405 399 406 400 int vboxscsiWriteString(PPDMDEVINS pDevIns, PVBOXSCSI pVBoxSCSI, uint8_t iRegister, 407 RTGCPTR *pGCPtrSrc, PRTGCUINTREG pcTransfer, unsigned cb) 408 { 409 RTGCPTR GCSrc = *pGCPtrSrc; 410 uint32_t cbTransfer = *pcTransfer * cb; 411 401 uint8_t const *pbSrc, uint32_t *pcTransfers, unsigned cb) 402 { 403 /* 404 * Check preconditions, fall back to non-string I/O handler. 405 */ 406 Assert(*pcTransfers > 0); 412 407 /* Write string only valid for data in/out register. */ 413 AssertMsg (iRegister == 1, ("Hey only register 1 can be written to with string\n"));408 AssertMsgReturn(iRegister == 1, ("Hey! Only register 1 can be written to with string!\n"), VINF_SUCCESS); 414 409 415 410 /* Accesses without a valid buffer will be ignored. */ 416 if (!pVBoxSCSI->pbBuf) 417 return VINF_SUCCESS; 418 419 Assert(cbTransfer <= pVBoxSCSI->cbBuf); 420 if (cbTransfer > pVBoxSCSI->cbBuf) 421 cbTransfer = pVBoxSCSI->cbBuf; /* Ignore excess data (not supposed to happen). */ 422 423 int rc = PDMDevHlpPhysReadGCVirt(pDevIns, pVBoxSCSI->pbBuf + pVBoxSCSI->iBuf, GCSrc, cbTransfer); 424 AssertRC(rc); 425 426 /* Advance current buffer position. */ 427 pVBoxSCSI->iBuf += cbTransfer; 428 pVBoxSCSI->cbBuf -= cbTransfer; 429 430 *pGCPtrSrc = (RTGCPTR)((RTGCUINTPTR)GCSrc + cbTransfer); 431 *pcTransfer = 0; 432 433 ASMAtomicXchgBool(&pVBoxSCSI->fBusy, true); 434 return VERR_MORE_DATA; 411 AssertReturn(!pVBoxSCSI->pbBuf, VINF_SUCCESS); 412 413 /* State machine assumptions. */ 414 AssertReturn(pVBoxSCSI->enmState == VBOXSCSISTATE_COMMAND_READY, VINF_SUCCESS); 415 AssertReturn(pVBoxSCSI->uTxDir == VBOXSCSI_TXDIR_TO_DEVICE, VINF_SUCCESS); 416 417 /* 418 * Ignore excess data (not supposed to happen). 419 */ 420 int rc = VINF_SUCCESS; 421 if (pVBoxSCSI->cbBuf > 0) /* Think cbBufLeft, not cbBuf! */ 422 { 423 uint32_t cbTransfer = *pcTransfers * cb; 424 if (cbTransfer > pVBoxSCSI->cbBuf) /* Think cbBufLeft, not cbBuf! */ 425 { 426 /** @todo the non-string version of the code would cause a reset here. */ 427 cbTransfer = pVBoxSCSI->cbBuf; 428 } 429 430 /* Copy the data and adance the buffer position. */ 431 memcpy(pVBoxSCSI->pbBuf + pVBoxSCSI->iBuf, pbSrc, cbTransfer); 432 pVBoxSCSI->iBuf += cbTransfer; 433 pVBoxSCSI->cbBuf -= cbTransfer; 434 435 /* If we've reached the end, tell the caller to submit the command. */ 436 if (pVBoxSCSI->cbBuf == 0) 437 { 438 ASMAtomicXchgBool(&pVBoxSCSI->fBusy, true); 439 rc = VERR_MORE_DATA; 440 } 441 } 442 else 443 AssertFailed(); 444 *pcTransfers = 0; 445 446 return rc; 435 447 } 436 448 -
trunk/src/VBox/Devices/Storage/VBoxSCSI.h
r56292 r56413 111 111 /** Pointer to the buffer holding the data. */ 112 112 R3PTRTYPE(uint8_t *) pbBuf; 113 /** Size of the buffer in bytes. */ 113 /** Size of the buffer in bytes. 114 * 115 * @todo r=bird: Misleading docs and member name. This is actually not the 116 * buffer size, it's the number of bytes left to read/write in the 117 * buffer. It is decremented when the guest (BIOS) accesses 118 * the buffer data. */ 114 119 uint32_t cbBuf; 115 120 /** Current position in the buffer (offBuf if you like). */ … … 138 143 void vboxscsiSetRequestRedo(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest); 139 144 int vboxscsiWriteString(PPDMDEVINS pDevIns, PVBOXSCSI pVBoxSCSI, uint8_t iRegister, 140 RTGCPTR *pGCPtrSrc, PRTGCUINTREG pcTransfer, unsigned cb);145 uint8_t const *pbSrc, uint32_t *pcTransfers, unsigned cb); 141 146 int vboxscsiReadString(PPDMDEVINS pDevIns, PVBOXSCSI pVBoxSCSI, uint8_t iRegister, 142 RTGCPTR *pGCPtrDst, PRTGCUINTREG pcTransfer, unsigned cb);147 uint8_t *pbDst, uint32_t *pcTransfers, unsigned cb); 143 148 RT_C_DECLS_END 144 149 #endif /* IN_RING3 */
Note:
See TracChangeset
for help on using the changeset viewer.