Changeset 56413 in vbox
- Timestamp:
- Jun 14, 2015 3:43:56 AM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 101015
- Location:
- trunk
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/iem.h
r56291 r56413 94 94 VMM_INT_DECL(void) IEMNotifyIOPortRead(PVM pVM, RTIOPORT Port, size_t cbValue); 95 95 VMM_INT_DECL(void) IEMNotifyIOPortWrite(PVM pVM, RTIOPORT Port, uint32_t u32Value, size_t cbValue); 96 VMM_INT_DECL(void) IEMNotifyIOPortReadString(PVM pVM, RTIOPORT Port, RTGCPTR GCPtrDst, RTGCUINTREG cTransfers, size_t cbValue);97 VMM_INT_DECL(void) IEMNotifyIOPortWriteString(PVM pVM, RTIOPORT Port, RTGCPTR GCPtrSrc, RTGCUINTREG cTransfers, size_t cbValue);96 VMM_INT_DECL(void) IEMNotifyIOPortReadString(PVM pVM, RTIOPORT Port, void *pvDst, RTGCUINTREG cTransfers, size_t cbValue); 97 VMM_INT_DECL(void) IEMNotifyIOPortWriteString(PVM pVM, RTIOPORT Port, void const *pvSrc, RTGCUINTREG cTransfers, size_t cbValue); 98 98 #endif 99 99 -
trunk/include/VBox/vmm/iom.h
r56072 r56413 164 164 * @remarks Caller enters the device critical section. 165 165 */ 166 typedef DECLCALLBACK(int) FNIOMIOPORTIN(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);166 typedef DECLCALLBACK(int) FNIOMIOPORTIN(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t *pu32, unsigned cb); 167 167 /** Pointer to a FNIOMIOPORTIN(). */ 168 168 typedef FNIOMIOPORTIN *PFNIOMIOPORTIN; … … 177 177 * @param pvUser User argument. 178 178 * @param uPort Port number used for the IN operation. 179 * @param pGCPtrDst Pointer to the destination buffer (GC, incremented appropriately). 180 * @param pcTransfers Pointer to the number of transfer units to read, on return remaining transfer units. 179 * @param pbDst Pointer to the destination buffer. 180 * @param pcTransfers Pointer to the number of transfer units to read, on 181 * return remaining transfer units. 181 182 * @param cb Size of the transfer unit (1, 2 or 4 bytes). 182 183 * @remarks Caller enters the device critical section. 183 184 */ 184 typedef DECLCALLBACK(int) FNIOMIOPORTINSTRING(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrDst, PRTGCUINTREG pcTransfers, unsigned cb); 185 typedef DECLCALLBACK(int) FNIOMIOPORTINSTRING(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint8_t *pbDst, 186 uint32_t *pcTransfers, unsigned cb); 185 187 /** Pointer to a FNIOMIOPORTINSTRING(). */ 186 188 typedef FNIOMIOPORTINSTRING *PFNIOMIOPORTINSTRING; … … 198 200 * @remarks Caller enters the device critical section. 199 201 */ 200 typedef DECLCALLBACK(int) FNIOMIOPORTOUT(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);202 typedef DECLCALLBACK(int) FNIOMIOPORTOUT(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32, unsigned cb); 201 203 /** Pointer to a FNIOMIOPORTOUT(). */ 202 204 typedef FNIOMIOPORTOUT *PFNIOMIOPORTOUT; … … 210 212 * @param pvUser User argument. 211 213 * @param uPort Port number used for the OUT operation. 212 * @param pGCPtrSrc Pointer to the source buffer (GC, incremented appropriately). 213 * @param pcTransfers Pointer to the number of transfer units to write, on return remaining transfer units. 214 * @param pbSrc Pointer to the source buffer. 215 * @param pcTransfers Pointer to the number of transfer units to write, on 216 * return remaining transfer units. 214 217 * @param cb Size of the transfer unit (1, 2 or 4 bytes). 215 218 * @remarks Caller enters the device critical section. 216 219 */ 217 typedef DECLCALLBACK(int) FNIOMIOPORTOUTSTRING(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrSrc, PRTGCUINTREG pcTransfers, unsigned cb); 220 typedef DECLCALLBACK(int) FNIOMIOPORTOUTSTRING(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, const uint8_t *pbSrc, 221 uint32_t *pcTransfers, unsigned cb); 218 222 /** Pointer to a FNIOMIOPORTOUTSTRING(). */ 219 223 typedef FNIOMIOPORTOUTSTRING *PFNIOMIOPORTOUTSTRING; … … 271 275 VMMDECL(VBOXSTRICTRC) IOMIOPortRead(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t *pu32Value, size_t cbValue); 272 276 VMMDECL(VBOXSTRICTRC) IOMIOPortWrite(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t u32Value, size_t cbValue); 273 VMMDECL(VBOXSTRICTRC) IOMIOPortReadString(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, PRTGCPTR pGCPtrDst, PRTGCUINTREG pcTransfers, unsigned cb); 274 VMMDECL(VBOXSTRICTRC) IOMIOPortWriteString(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, PRTGCPTR pGCPtrSrc, PRTGCUINTREG pcTransfers, unsigned cb); 277 VMMDECL(VBOXSTRICTRC) IOMIOPortReadString(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, void *pvDst, 278 uint32_t *pcTransfers, unsigned cb); 279 VMMDECL(VBOXSTRICTRC) IOMIOPortWriteString(PVM pVM, PVMCPU pVCpu, RTIOPORT uPort, void const *pvSrc, 280 uint32_t *pcTransfers, unsigned cb); 275 281 VMMDECL(VBOXSTRICTRC) IOMInterpretINSEx(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, DISCPUMODE enmAddrMode, uint32_t cbTransfer); 276 282 VMMDECL(VBOXSTRICTRC) IOMInterpretOUTSEx(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, DISCPUMODE enmAddrMode, uint32_t cbTransfer); -
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 */ -
trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
r56287 r56413 9995 9995 9996 9996 9997 VMM_INT_DECL(void) IEMNotifyIOPortReadString(PVM pVM, RTIOPORT Port, RTGCPTR GCPtrDst, RTGCUINTREG cTransfers, size_t cbValue)9997 VMM_INT_DECL(void) IEMNotifyIOPortReadString(PVM pVM, RTIOPORT Port, void *pvDst, RTGCUINTREG cTransfers, size_t cbValue) 9998 9998 { 9999 9999 AssertFailed(); … … 10001 10001 10002 10002 10003 VMM_INT_DECL(void) IEMNotifyIOPortWriteString(PVM pVM, RTIOPORT Port, RTGCPTR GCPtrSrc, RTGCUINTREG cTransfers, size_t cbValue)10003 VMM_INT_DECL(void) IEMNotifyIOPortWriteString(PVM pVM, RTIOPORT Port, void const *pvSrc, RTGCUINTREG cTransfers, size_t cbValue) 10004 10004 { 10005 10005 AssertFailed(); -
trunk/src/VBox/VMM/VMMAll/IOMAll.cpp
r56403 r56413 236 236 * @param pVCpu Pointer to the virtual CPU structure of the caller. 237 237 * @param Port The port to read. 238 * @param pGCPtrDst Pointer to the destination buffer (RC, incremented 239 * appropriately). 238 * @param pvDst Pointer to the destination buffer. 240 239 * @param pcTransfers Pointer to the number of transfer units to read, on return remaining transfer units. 241 240 * @param cb Size of the transfer unit (1, 2 or 4 bytes). 242 241 */ 243 VMMDECL(VBOXSTRICTRC) IOMIOPortReadString(PVM pVM, PVMCPU pVCpu, RTIOPORT Port,244 PRTGCPTR pGCPtrDst, PRTGCUINTREGpcTransfers, unsigned cb)242 VMMDECL(VBOXSTRICTRC) IOMIOPortReadString(PVM pVM, PVMCPU pVCpu, RTIOPORT uPort, 243 void *pvDst, uint32_t *pcTransfers, unsigned cb) 245 244 { 246 245 /* Take the IOM lock before performing any device I/O. */ … … 252 251 AssertRC(rc2); 253 252 #if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3) 254 IEMNotifyIOPortReadString(pVM, Port, *pGCPtrDst, *pcTransfers, cb);253 IEMNotifyIOPortReadString(pVM, uPort, pvDst, *pcTransfers, cb); 255 254 #endif 256 255 257 256 #ifdef LOG_ENABLED 258 const RTGCUINTREGcTransfers = *pcTransfers;257 const uint32_t cTransfers = *pcTransfers; 259 258 #endif 260 259 #ifdef VBOX_WITH_STATISTICS … … 263 262 */ 264 263 PIOMIOPORTSTATS pStats = pVCpu->iom.s.CTX_SUFF(pStatsLastRead); 265 if (!pStats || pStats->Core.Key != Port)266 { 267 pStats = (PIOMIOPORTSTATS)RTAvloIOPortGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortStatTree, Port);264 if (!pStats || pStats->Core.Key != uPort) 265 { 266 pStats = (PIOMIOPORTSTATS)RTAvloIOPortGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortStatTree, uPort); 268 267 if (pStats) 269 268 pVCpu->iom.s.CTX_SUFF(pStatsLastRead) = pStats; … … 276 275 CTX_SUFF(PIOMIOPORTRANGE) pRange = pVCpu->iom.s.CTX_SUFF(pRangeLastRead); 277 276 if ( !pRange 278 || (unsigned) Port - (unsigned)pRange->Port >= (unsigned)pRange->cPorts)279 { 280 pRange = iomIOPortGetRange(pVM, Port);277 || (unsigned)uPort - (unsigned)pRange->Port >= (unsigned)pRange->cPorts) 278 { 279 pRange = iomIOPortGetRange(pVM, uPort); 281 280 if (pRange) 282 281 pVCpu->iom.s.CTX_SUFF(pRangeLastRead) = pRange; … … 314 313 { 315 314 STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfIn), a); 316 rcStrict = pfnInStrCallback(pDevIns, pvUser, Port, pGCPtrDst, pcTransfers, cb);315 rcStrict = pfnInStrCallback(pDevIns, pvUser, uPort, (uint8_t *)pvDst, pcTransfers, cb); 317 316 STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfIn), a); 318 317 } 319 318 else 320 319 #endif 321 rcStrict = pfnInStrCallback(pDevIns, pvUser, Port, pGCPtrDst, pcTransfers, cb);320 rcStrict = pfnInStrCallback(pDevIns, pvUser, uPort, (uint8_t *)pvDst, pcTransfers, cb); 322 321 PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo)); 323 322 … … 330 329 # endif 331 330 #endif 332 Log3(("IOMIOPortReadStr: Port=%RTiop pGCPtrDst=%p pcTransfer=%p:{%#x->%#x} cb=%d rc=%Rrc\n",333 Port, pGCPtrDst, pcTransfers, cTransfers, *pcTransfers, cb, VBOXSTRICTRC_VAL(rcStrict)));331 Log3(("IOMIOPortReadStr: uPort=%RTiop pvDst=%p pcTransfer=%p:{%#x->%#x} cb=%d rc=%Rrc\n", 332 uPort, pvDst, pcTransfers, cTransfers, *pcTransfers, cb, VBOXSTRICTRC_VAL(rcStrict))); 334 333 return rcStrict; 335 334 } … … 339 338 * Handler in ring-3? 340 339 */ 341 PIOMIOPORTRANGER3 pRangeR3 = iomIOPortGetRangeR3(pVM, Port);340 PIOMIOPORTRANGER3 pRangeR3 = iomIOPortGetRangeR3(pVM, uPort); 342 341 if (pRangeR3) 343 342 { … … 359 358 #endif 360 359 361 Log3(("IOMIOPortReadStr: Port=%RTiop pGCPtrDst=%p pcTransfer=%p:{%#x->%#x} cb=%d rc=VINF_SUCCESS\n",362 Port, pGCPtrDst, pcTransfers, cTransfers, *pcTransfers, cb));360 Log3(("IOMIOPortReadStr: uPort=%RTiop pvDst=%p pcTransfer=%p:{%#x->%#x} cb=%d rc=VINF_SUCCESS\n", 361 uPort, pvDst, pcTransfers, cTransfers, *pcTransfers, cb)); 363 362 IOM_UNLOCK_SHARED(pVM); 364 363 return VINF_SUCCESS; … … 516 515 * @param pVM Pointer to the VM. 517 516 * @param pVCpu Pointer to the virtual CPU structure of the caller. 518 * @param Port The port to write.519 * @param p GCPtrSrc Pointer to the source buffer (RC, incremented520 * appropriately).521 * @param pcTransfers Pointer to the number of transfer units to write, onreturn remaining transfer units.517 * @param uPort The port to write to. 518 * @param pvSrc The guest page to read from. 519 * @param pcTransfers Pointer to the number of transfer units to write, on 520 * return remaining transfer units. 522 521 * @param cb Size of the transfer unit (1, 2 or 4 bytes). 523 522 */ 524 VMMDECL(VBOXSTRICTRC) IOMIOPortWriteString(PVM pVM, PVMCPU pVCpu, RTIOPORT Port,525 PRTGCPTR pGCPtrSrc, PRTGCUINTREGpcTransfers, unsigned cb)523 VMMDECL(VBOXSTRICTRC) IOMIOPortWriteString(PVM pVM, PVMCPU pVCpu, RTIOPORT uPort, void const *pvSrc, 524 uint32_t *pcTransfers, unsigned cb) 526 525 { 526 Assert(cb == 1 || cb == 2 || cb == 4); 527 527 528 /* Take the IOM lock before performing any device I/O. */ 528 529 int rc2 = IOM_LOCK_SHARED(pVM); … … 533 534 AssertRC(rc2); 534 535 #if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3) 535 IEMNotifyIOPortWriteString(pVM, Port, *pGCPtrSrc, *pcTransfers, cb);536 IEMNotifyIOPortWriteString(pVM, uPort, pvSrc, *pcTransfers, cb); 536 537 #endif 537 538 538 539 #ifdef LOG_ENABLED 539 const RTGCUINTREGcTransfers = *pcTransfers;540 const uint32_t cTransfers = *pcTransfers; 540 541 #endif 541 542 #ifdef VBOX_WITH_STATISTICS … … 544 545 */ 545 546 PIOMIOPORTSTATS pStats = pVCpu->iom.s.CTX_SUFF(pStatsLastWrite); 546 if (!pStats || pStats->Core.Key != Port)547 { 548 pStats = (PIOMIOPORTSTATS)RTAvloIOPortGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortStatTree, Port);547 if (!pStats || pStats->Core.Key != uPort) 548 { 549 pStats = (PIOMIOPORTSTATS)RTAvloIOPortGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortStatTree, uPort); 549 550 if (pStats) 550 551 pVCpu->iom.s.CTX_SUFF(pStatsLastWrite) = pStats; … … 557 558 CTX_SUFF(PIOMIOPORTRANGE) pRange = pVCpu->iom.s.CTX_SUFF(pRangeLastWrite); 558 559 if ( !pRange 559 || (unsigned) Port - (unsigned)pRange->Port >= (unsigned)pRange->cPorts)560 { 561 pRange = iomIOPortGetRange(pVM, Port);560 || (unsigned)uPort - (unsigned)pRange->Port >= (unsigned)pRange->cPorts) 561 { 562 pRange = iomIOPortGetRange(pVM, uPort); 562 563 if (pRange) 563 564 pVCpu->iom.s.CTX_SUFF(pRangeLastWrite) = pRange; … … 595 596 { 596 597 STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfOut), a); 597 rcStrict = pfnOutStrCallback(pDevIns, pvUser, Port, pGCPtrSrc, pcTransfers, cb);598 rcStrict = pfnOutStrCallback(pDevIns, pvUser, uPort, (uint8_t const *)pvSrc, pcTransfers, cb); 598 599 STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfOut), a); 599 600 } 600 601 else 601 602 #endif 602 rcStrict = pfnOutStrCallback(pDevIns, pvUser, Port, pGCPtrSrc, pcTransfers, cb);603 rcStrict = pfnOutStrCallback(pDevIns, pvUser, uPort, (uint8_t const *)pvSrc, pcTransfers, cb); 603 604 PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo)); 604 605 … … 611 612 # endif 612 613 #endif 613 Log3(("IOMIOPortWriteStr: Port=%RTiop pGCPtrSrc=%p pcTransfer=%p:{%#x->%#x} cb=%d rcStrict=%Rrc\n",614 Port, pGCPtrSrc, pcTransfers, cTransfers, *pcTransfers, cb, VBOXSTRICTRC_VAL(rcStrict)));614 Log3(("IOMIOPortWriteStr: uPort=%RTiop pvSrc=%p pcTransfer=%p:{%#x->%#x} cb=%d rcStrict=%Rrc\n", 615 uPort, pvSrc, pcTransfers, cTransfers, *pcTransfers, cb, VBOXSTRICTRC_VAL(rcStrict))); 615 616 return rcStrict; 616 617 } … … 620 621 * Handler in ring-3? 621 622 */ 622 PIOMIOPORTRANGER3 pRangeR3 = iomIOPortGetRangeR3(pVM, Port);623 PIOMIOPORTRANGER3 pRangeR3 = iomIOPortGetRangeR3(pVM, uPort); 623 624 if (pRangeR3) 624 625 { … … 640 641 #endif 641 642 642 Log3(("IOMIOPortWriteStr: Port=%RTiop pGCPtrSrc=%p pcTransfer=%p:{%#x->%#x} cb=%d rc=VINF_SUCCESS\n",643 Port, pGCPtrSrc, pcTransfers, cTransfers, *pcTransfers, cb));643 Log3(("IOMIOPortWriteStr: uPort=%RTiop pvSrc=%p pcTransfer=%p:{%#x->%#x} cb=%d rc=VINF_SUCCESS\n", 644 uPort, pvSrc, pcTransfers, cTransfers, *pcTransfers, cb)); 644 645 IOM_UNLOCK_SHARED(pVM); 645 646 return VINF_SUCCESS; -
trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp
r56080 r56413 2339 2339 if (cTransfers > 1) 2340 2340 { 2341 /* If the device supports string transfers, ask it to do as 2342 * much as it wants. The rest is done with single-word transfers. */ 2343 const RTGCUINTREG cTransfersOrg = cTransfers; 2344 rcStrict = IOMIOPortReadString(pVM, pVCpu, uPort, &GCPtrDst, &cTransfers, cbTransfer); 2345 AssertRC(VBOXSTRICTRC_VAL(rcStrict)); Assert(cTransfers <= cTransfersOrg); 2346 pRegFrame->rdi = ((pRegFrame->rdi + (cTransfersOrg - cTransfers) * cbTransfer) & fAddrMask) 2347 | (pRegFrame->rdi & ~fAddrMask); 2348 } 2349 2341 /* 2342 * Work the string page by page, letting the device handle as much 2343 * as it likes via the string I/O interface. 2344 */ 2345 for (;;) 2346 { 2347 PGMPAGEMAPLOCK Lock; 2348 void *pvDst; 2349 rc2 = PGMPhysGCPtr2CCPtr(pVCpu, GCPtrDst, &pvDst, &Lock); 2350 if (RT_SUCCESS(rc2)) 2351 { 2352 uint32_t cMaxThisTime = (PAGE_SIZE - (GCPtrDst & PAGE_OFFSET_MASK)) / cbTransfer; 2353 if (cMaxThisTime > cTransfers) 2354 cMaxThisTime = cTransfers; 2355 if (!cMaxThisTime) 2356 break; 2357 uint32_t cThisTime = cMaxThisTime; 2358 2359 rcStrict = IOMIOPortReadString(pVM, pVCpu, uPort, pvDst, &cThisTime, cbTransfer); 2360 AssertRC(VBOXSTRICTRC_VAL(rcStrict)); 2361 Assert(cThisTime <= cMaxThisTime); /* cThisTime is now how many transfers we have left. */ 2362 2363 /* If not supported do IOMIOPortRead. */ 2364 /** @todo this code should move to IOMIOPortReadString! */ 2365 if ( cThisTime > 0 2366 && rcStrict == VINF_SUCCESS) 2367 { 2368 pvDst = (uint8_t *)pvDst + (cMaxThisTime - cThisTime) * cbTransfer; 2369 do 2370 { 2371 uint32_t u32Value = 0; 2372 rcStrict = IOMIOPortRead(pVM, pVCpu, uPort, &u32Value, cbTransfer); 2373 if (IOM_SUCCESS(rcStrict)) 2374 { 2375 switch (cbTransfer) 2376 { 2377 case 4: *(uint32_t *)pvDst = u32Value; pvDst = (uint8_t *)pvDst + 4; break; 2378 case 2: *(uint16_t *)pvDst = (uint16_t)u32Value; pvDst = (uint8_t *)pvDst + 2; break; 2379 case 1: *(uint8_t *)pvDst = (uint8_t )u32Value; pvDst = (uint8_t *)pvDst + 1; break; 2380 default: AssertFailedReturn(VERR_IOM_IOPORT_IPE_3); 2381 } 2382 cThisTime--; 2383 } 2384 } while ( cThisTime > 0 2385 && rcStrict == VINF_SUCCESS); 2386 } 2387 2388 PGMPhysReleasePageMappingLock(pVM, &Lock); 2389 2390 uint32_t const cActual = cMaxThisTime - cThisTime; 2391 uint32_t const cbActual = cActual * cbTransfer; 2392 cTransfers -= cActual; 2393 pRegFrame->rdi = ((pRegFrame->rdi + cbActual) & fAddrMask) 2394 | (pRegFrame->rdi & ~fAddrMask); 2395 GCPtrDst = (GCPtrDst + cbActual) & fAddrMask; 2396 2397 if ( cThisTime 2398 || !cTransfers 2399 || rcStrict != VINF_SUCCESS 2400 || (GCPtrDst & PAGE_OFFSET_MASK)) 2401 break; 2402 } 2403 else 2404 { 2405 Log(("IOMInterpretOUTSEx: PGMPhysGCPtr2CCPtr %#RGv -> %Rrc\n", GCPtrDst, rc2)); 2406 break; 2407 } 2408 } 2409 } 2410 2411 /* 2412 * Single transfer / unmapped memory fallback. 2413 */ 2350 2414 #ifdef IN_RC 2351 2415 MMGCRamRegisterTrapHandler(pVM); … … 2395 2459 * 2396 2460 * @param pVM The virtual machine. 2397 * @param pVCpu Pointer to the virtual CPU structure of the caller.2461 * @param pVCpu Pointer to the virtual CPU structure of the caller. 2398 2462 * @param pRegFrame Pointer to CPUMCTXCORE guest registers structure. 2399 2463 * @param uPort IO Port … … 2401 2465 * @param enmAddrMode The address mode. 2402 2466 * @param cbTransfer Size of transfer unit 2467 * 2468 * @remarks This API will probably be relaced by IEM before long, so no use in 2469 * optimizing+fixing stuff too much here. 2403 2470 */ 2404 2471 VMMDECL(VBOXSTRICTRC) IOMInterpretOUTSEx(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, … … 2458 2525 { 2459 2526 /* 2460 * If the device supports string transfers, ask it to do as2461 * much as it wants. The rest is done with single-word transfers.2527 * Work the string page by page, letting the device handle as much 2528 * as it likes via the string I/O interface. 2462 2529 */ 2463 const RTGCUINTREG cTransfersOrg = cTransfers; 2464 rcStrict = IOMIOPortWriteString(pVM, pVCpu, uPort, &GCPtrSrc, &cTransfers, cbTransfer); 2465 AssertRC(VBOXSTRICTRC_VAL(rcStrict)); Assert(cTransfers <= cTransfersOrg); 2466 pRegFrame->rsi = ((pRegFrame->rsi + (cTransfersOrg - cTransfers) * cbTransfer) & fAddrMask) 2467 | (pRegFrame->rsi & ~fAddrMask); 2468 } 2469 2530 for (;;) 2531 { 2532 PGMPAGEMAPLOCK Lock; 2533 void const *pvSrc; 2534 rc2 = PGMPhysGCPtr2CCPtrReadOnly(pVCpu, GCPtrSrc, &pvSrc, &Lock); 2535 if (RT_SUCCESS(rc2)) 2536 { 2537 uint32_t cMaxThisTime = (PAGE_SIZE - (GCPtrSrc & PAGE_OFFSET_MASK)) / cbTransfer; 2538 if (cMaxThisTime > cTransfers) 2539 cMaxThisTime = cTransfers; 2540 if (!cMaxThisTime) 2541 break; 2542 uint32_t cThisTime = cMaxThisTime; 2543 2544 rcStrict = IOMIOPortWriteString(pVM, pVCpu, uPort, pvSrc, &cThisTime, cbTransfer); 2545 AssertRC(VBOXSTRICTRC_VAL(rcStrict)); 2546 Assert(cThisTime <= cMaxThisTime); /* cThisTime is now how many transfers we have left. */ 2547 2548 /* If not supported do IOMIOPortWrite. */ 2549 /** @todo this code should move to IOMIOPortReadString! */ 2550 if ( cThisTime > 0 2551 && rcStrict == VINF_SUCCESS) 2552 { 2553 pvSrc = (uint8_t const *)pvSrc + (cMaxThisTime - cThisTime) * cbTransfer; 2554 do 2555 { 2556 uint32_t u32Value; 2557 switch (cbTransfer) 2558 { 2559 case 4: u32Value = *(uint32_t *)pvSrc; pvSrc = (uint8_t const *)pvSrc + 4; break; 2560 case 2: u32Value = *(uint16_t *)pvSrc; pvSrc = (uint8_t const *)pvSrc + 2; break; 2561 case 1: u32Value = *(uint8_t *)pvSrc; pvSrc = (uint8_t const *)pvSrc + 1; break; 2562 default: AssertFailedReturn(VERR_IOM_IOPORT_IPE_3); 2563 } 2564 rcStrict = IOMIOPortWrite(pVM, pVCpu, uPort, u32Value, cbTransfer); 2565 if (IOM_SUCCESS(rcStrict)) 2566 cThisTime--; 2567 } while ( cThisTime > 0 2568 && rcStrict == VINF_SUCCESS); 2569 } 2570 2571 PGMPhysReleasePageMappingLock(pVM, &Lock); 2572 2573 uint32_t const cActual = cMaxThisTime - cThisTime; 2574 uint32_t const cbActual = cActual * cbTransfer; 2575 cTransfers -= cActual; 2576 pRegFrame->rsi = ((pRegFrame->rsi + cbActual) & fAddrMask) 2577 | (pRegFrame->rsi & ~fAddrMask); 2578 GCPtrSrc = (GCPtrSrc + cbActual) & fAddrMask; 2579 2580 if ( cThisTime 2581 || !cTransfers 2582 || rcStrict != VINF_SUCCESS 2583 || (GCPtrSrc & PAGE_OFFSET_MASK)) 2584 break; 2585 } 2586 else 2587 { 2588 Log(("IOMInterpretOUTSEx: PGMPhysGCPtr2CCPtrReadOnly %#RGv -> %Rrc\n", GCPtrSrc, rc2)); 2589 break; 2590 } 2591 } 2592 } 2593 2594 /* 2595 * Single transfer / unmapped memory fallback. 2596 */ 2470 2597 #ifdef IN_RC 2471 2598 MMGCRamRegisterTrapHandler(pVM); -
trunk/src/VBox/VMM/VMMR3/IOM.cpp
r56287 r56413 132 132 static DECLCALLBACK(void) iomR3IOPortInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs); 133 133 static DECLCALLBACK(void) iomR3MMIOInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs); 134 static DECLCALLBACK(int) iomR3IOPortDummyIn(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);135 static DECLCALLBACK(int) iomR3IOPortDummyOut(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);136 static DECLCALLBACK(int) iomR3IOPortDummyInStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrDst, PRTGCUINTREG pcTransfer, unsigned cb);137 static DECLCALLBACK(int) iomR3IOPortDummyOutStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrSrc, PRTGCUINTREG pcTransfer, unsigned cb);134 static FNIOMIOPORTIN iomR3IOPortDummyIn; 135 static FNIOMIOPORTOUT iomR3IOPortDummyOut; 136 static FNIOMIOPORTINSTRING iomR3IOPortDummyInStr; 137 static FNIOMIOPORTOUTSTRING iomR3IOPortDummyOutStr; 138 138 139 139 #ifdef VBOX_WITH_STATISTICS … … 1201 1201 1202 1202 /** 1203 * Dummy Port I/O Handler for string IN operations. 1204 * 1205 * @returns VBox status code. 1206 * 1207 * @param pDevIns The device instance. 1208 * @param pvUser User argument. 1209 * @param Port Port number used for the string IN operation. 1210 * @param pGCPtrDst Pointer to the destination buffer (GC, incremented appropriately). 1211 * @param pcTransfer Pointer to the number of transfer units to read, on return remaining transfer units. 1212 * @param cb Size of the transfer unit (1, 2 or 4 bytes). 1213 */ 1214 static DECLCALLBACK(int) iomR3IOPortDummyInStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrDst, 1215 PRTGCUINTREG pcTransfer, unsigned cb) 1216 { 1217 NOREF(pDevIns); NOREF(pvUser); NOREF(Port); NOREF(pGCPtrDst); NOREF(pcTransfer); NOREF(cb); 1203 * @callback_method_impl{FNIOMIOPORTINSTRING, 1204 * Dummy Port I/O Handler for string IN operations.} 1205 */ 1206 static DECLCALLBACK(int) iomR3IOPortDummyInStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint8_t *pbDst, 1207 uint32_t *pcTransfer, unsigned cb) 1208 { 1209 NOREF(pDevIns); NOREF(pvUser); NOREF(Port); NOREF(pbDst); NOREF(pcTransfer); NOREF(cb); 1218 1210 return VINF_SUCCESS; 1219 1211 } … … 1239 1231 1240 1232 /** 1241 * Dummy Port I/O Handler for string OUT operations. 1242 * 1243 * @returns VBox status code. 1244 * 1245 * @param pDevIns The device instance. 1246 * @param pvUser User argument. 1247 * @param Port Port number used for the string OUT operation. 1248 * @param pGCPtrSrc Pointer to the source buffer (GC, incremented appropriately). 1249 * @param pcTransfer Pointer to the number of transfer units to write, on return remaining transfer units. 1250 * @param cb Size of the transfer unit (1, 2 or 4 bytes). 1251 */ 1252 static DECLCALLBACK(int) iomR3IOPortDummyOutStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrSrc, 1253 PRTGCUINTREG pcTransfer, unsigned cb) 1254 { 1255 NOREF(pDevIns); NOREF(pvUser); NOREF(Port); NOREF(pGCPtrSrc); NOREF(pcTransfer); NOREF(cb); 1233 * @callback_method_impl{FNIOMIOPORTOUTSTRING, 1234 * Dummy Port I/O Handler for string OUT operations.} 1235 */ 1236 static DECLCALLBACK(int) iomR3IOPortDummyOutStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint8_t const *pbSrc, 1237 uint32_t *pcTransfer, unsigned cb) 1238 { 1239 NOREF(pDevIns); NOREF(pvUser); NOREF(Port); NOREF(pbSrc); NOREF(pcTransfer); NOREF(cb); 1256 1240 return VINF_SUCCESS; 1257 1241 }
Note:
See TracChangeset
for help on using the changeset viewer.