Changeset 56406 in vbox for trunk/src/VBox/Devices/Storage
- Timestamp:
- Jun 13, 2015 7:31:54 PM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 101007
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevATA.cpp
r56405 r56406 4869 4869 } 4870 4870 4871 static int ataDataWrite(PATACONTROLLER pCtl, uint32_t addr, uint32_t cbSize, const uint8_t *pbBuf) 4872 { 4873 ATADevState *s = &pCtl->aIfs[pCtl->iSelectedIf]; 4874 4875 if (s->iIOBufferPIODataStart < s->iIOBufferPIODataEnd) 4876 { 4877 Assert(s->uTxDir == PDMBLOCKTXDIR_TO_DEVICE); 4878 uint8_t *pbDst = s->CTX_SUFF(pbIOBuffer) + s->iIOBufferPIODataStart; 4871 4872 /** 4873 * Port I/O Handler for primary port range OUT operations. 4874 * @see FNIOMIOPORTOUT for details. 4875 */ 4876 PDMBOTHCBDECL(int) ataIOPortWrite1Data(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 4877 { 4878 uint32_t i = (uint32_t)(uintptr_t)pvUser; 4879 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *); 4880 PATACONTROLLER pCtl = &pThis->aCts[i]; 4881 4882 Assert(i < 2); 4883 Assert(Port == pCtl->IOPortBase1); 4884 Assert(cb == 2 || cb == 4); /* Writes to the data port may be 16-bit or 32-bit. */ 4885 4886 int rc = PDMCritSectEnter(&pCtl->lock, VINF_IOM_R3_IOPORT_WRITE); 4887 if (rc == VINF_SUCCESS) 4888 { 4889 ATADevState *s = &pCtl->aIfs[pCtl->iSelectedIf]; 4890 4891 if (s->iIOBufferPIODataStart < s->iIOBufferPIODataEnd) 4892 { 4893 Assert(s->uTxDir == PDMBLOCKTXDIR_TO_DEVICE); 4894 uint8_t *pbDst = s->CTX_SUFF(pbIOBuffer) + s->iIOBufferPIODataStart; 4895 uint8_t const *pbSrc = (uint8_t const *)&u32; 4879 4896 4880 4897 #ifdef IN_RC 4881 /* Raw-mode: The ataHCPIOTransfer following the last transfer unit 4882 requires I/O thread signalling, we must go to ring-3 for that. */ 4883 if (s->iIOBufferPIODataStart + cbSize < s->iIOBufferPIODataEnd) 4884 ataCopyPioData124(s, pbDst, pbBuf, cbSize); 4898 /* Raw-mode: The ataHCPIOTransfer following the last transfer unit 4899 requires I/O thread signalling, we must go to ring-3 for that. */ 4900 if (s->iIOBufferPIODataStart + cb < s->iIOBufferPIODataEnd) 4901 ataCopyPioData124(s, pbDst, pbSrc, cb); 4902 else 4903 return VINF_IOM_R3_IOPORT_WRITE; 4904 4905 #elif defined(IN_RING0) 4906 /* Ring-0: We can do I/O thread signalling here, however for paranoid reasons 4907 triggered by a special case in ataHCPIOTransferFinish, we take extra care here. */ 4908 if (s->iIOBufferPIODataStart + cb < s->iIOBufferPIODataEnd) 4909 ataCopyPioData124(s, pbDst, pbSrc, cb); 4910 else if (s->uTxDir == PDMBLOCKTXDIR_TO_DEVICE) /* paranoia */ 4911 { 4912 ataCopyPioData124(s, pbDst, pbSrc, cb); 4913 ataHCPIOTransferFinish(pCtl, s); 4914 } 4915 else 4916 { 4917 Log(("%s: Unexpected\n",__FUNCTION__)); 4918 return VINF_IOM_R3_IOPORT_WRITE; 4919 } 4920 4921 #else /* IN_RING 3*/ 4922 ataCopyPioData124(s, pbDst, pbSrc, cb); 4923 if (s->iIOBufferPIODataStart >= s->iIOBufferPIODataEnd) 4924 ataHCPIOTransferFinish(pCtl, s); 4925 #endif /* IN_RING 3*/ 4926 } 4885 4927 else 4886 return VINF_IOM_R3_IOPORT_WRITE; 4928 Log2(("%s: DUMMY data\n", __FUNCTION__)); 4929 4930 Log3(("%s: addr=%#x val=%.*Rhxs\n", __FUNCTION__, Port, cb, &u32)); 4931 PDMCritSectLeave(&pCtl->lock); 4932 } 4933 else 4934 Log3(("%s: addr=%#x -> %d\n", __FUNCTION__, Port, rc)); 4935 return rc; 4936 } 4937 4938 4939 /** 4940 * Port I/O Handler for primary port range IN operations. 4941 * @see FNIOMIOPORTIN for details. 4942 */ 4943 PDMBOTHCBDECL(int) ataIOPortRead1Data(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) 4944 { 4945 uint32_t i = (uint32_t)(uintptr_t)pvUser; 4946 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *); 4947 PATACONTROLLER pCtl = &pThis->aCts[i]; 4948 4949 Assert(i < 2); 4950 Assert(Port == pCtl->IOPortBase1); 4951 4952 /* Reads from the data register may be 16-bit or 32-bit. Byte accesses are 4953 upgraded to word. */ 4954 Assert(cb == 1 || cb == 2 || cb == 4); 4955 uint32_t cbActual = cb != 1 ? cb : 2; 4956 *pu32 = 0; 4957 4958 int rc = PDMCritSectEnter(&pCtl->lock, VINF_IOM_R3_IOPORT_READ); 4959 if (rc == VINF_SUCCESS) 4960 { 4961 ATADevState *s = &pCtl->aIfs[pCtl->iSelectedIf]; 4962 4963 if (s->iIOBufferPIODataStart < s->iIOBufferPIODataEnd) 4964 { 4965 Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE); 4966 uint8_t const *pbSrc = s->CTX_SUFF(pbIOBuffer) + s->iIOBufferPIODataStart; 4967 uint8_t *pbDst = (uint8_t *)pu32; 4968 4969 #ifdef IN_RC 4970 /* All but the last transfer unit is simple enough for RC, but 4971 * sending a request to the async IO thread is too complicated. */ 4972 if (s->iIOBufferPIODataStart + cbActual < s->iIOBufferPIODataEnd) 4973 ataCopyPioData124(s, pbDst, pbSrc, cbActual); 4974 else 4975 return VINF_IOM_R3_IOPORT_READ; 4887 4976 4888 4977 #elif defined(IN_RING0) 4889 /* Ring-0: We can do I/O thread signalling here, however for paranoid reasons 4890 triggered by a special case in ataHCPIOTransferFinish, we take extra care here. */ 4891 if (s->iIOBufferPIODataStart + cbSize < s->iIOBufferPIODataEnd) 4892 ataCopyPioData124(s, pbDst, pbBuf, cbSize); 4893 else if (s->uTxDir == PDMBLOCKTXDIR_TO_DEVICE) /* paranoia */ 4894 { 4895 ataCopyPioData124(s, pbDst, pbBuf, cbSize); 4896 ataHCPIOTransferFinish(pCtl, s); 4978 /* Ring-0: We can do I/O thread signalling here. However there is one 4979 case in ataHCPIOTransfer that does a LogRel and would (but not from 4980 here) call directly into the driver code. We detect that odd case 4981 here cand return to ring-3 to handle it. */ 4982 if (s->iIOBufferPIODataStart + cbActual < s->iIOBufferPIODataEnd) 4983 ataCopyPioData124(s, pbDst, pbSrc, cbActual); 4984 else if ( s->cbTotalTransfer == 0 4985 || s->iSourceSink != ATAFN_SS_NULL 4986 || s->iIOBufferCur <= s->iIOBufferEnd) 4987 { 4988 ataCopyPioData124(s, pbDst, pbSrc, cbActual); 4989 ataHCPIOTransferFinish(pCtl, s); 4990 } 4991 else 4992 { 4993 Log(("%s: Unexpected\n",__FUNCTION__)); 4994 return VINF_IOM_R3_IOPORT_READ; 4995 } 4996 4997 #else /* IN_RING3 */ 4998 ataCopyPioData124(s, pbDst, pbSrc, cbActual); 4999 if (s->iIOBufferPIODataStart >= s->iIOBufferPIODataEnd) 5000 ataHCPIOTransferFinish(pCtl, s); 5001 #endif /* IN_RING3 */ 5002 5003 /* Just to be on the safe side (caller takes care of this, really). */ 5004 if (cb == 1) 5005 *pu32 &= 0xff; 4897 5006 } 4898 5007 else 4899 5008 { 4900 Log(("%s: Unexpected\n",__FUNCTION__)); 4901 return VINF_IOM_R3_IOPORT_WRITE; 4902 } 4903 4904 #else /* IN_RING 3*/ 4905 ataCopyPioData124(s, pbDst, pbBuf, cbSize); 5009 Log2(("%s: DUMMY data\n", __FUNCTION__)); 5010 memset(pu32, 0xff, cb); 5011 } 5012 Log3(("%s: addr=%#x val=%.*Rhxs\n", __FUNCTION__, Port, cb, pu32)); 5013 5014 PDMCritSectLeave(&pCtl->lock); 5015 } 5016 else 5017 Log3(("%s: addr=%#x -> %d\n", __FUNCTION__, Port, rc)); 5018 5019 return rc; 5020 } 5021 5022 #ifndef IN_RING0 /** @todo do this in ring-0 as well - after IEM specific interface rewrite! */ 5023 5024 /** 5025 * Port I/O Handler for primary port range IN string operations. 5026 * @see FNIOMIOPORTINSTRING for details. 5027 */ 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; 5032 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *); 5033 PATACONTROLLER pCtl = &pThis->aCts[i]; 5034 int rc = VINF_SUCCESS; 5035 5036 Assert(i < 2); 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 { 5054 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 4906 5085 if (s->iIOBufferPIODataStart >= s->iIOBufferPIODataEnd) 4907 5086 ataHCPIOTransferFinish(pCtl, s); 4908 #endif /* IN_RING 3*/ 4909 } 4910 else 4911 Log2(("%s: DUMMY data\n", __FUNCTION__)); 4912 Log3(("%s: addr=%#x val=%.*Rhxs\n", __FUNCTION__, addr, cbSize, pbBuf)); 4913 return VINF_SUCCESS; 4914 } 4915 4916 static int ataDataRead(PATACONTROLLER pCtl, uint32_t addr, uint32_t cbSize, uint8_t *pbBuf) 4917 { 4918 ATADevState *s = &pCtl->aIfs[pCtl->iSelectedIf]; 4919 4920 if (s->iIOBufferPIODataStart < s->iIOBufferPIODataEnd) 4921 { 4922 Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE); 4923 uint8_t const *pbSrc = s->CTX_SUFF(pbIOBuffer) + s->iIOBufferPIODataStart; 4924 4925 #ifdef IN_RC 4926 /* All but the last transfer unit is simple enough for RC, but 4927 * sending a request to the async IO thread is too complicated. */ 4928 if (s->iIOBufferPIODataStart + cbSize < s->iIOBufferPIODataEnd) 4929 ataCopyPioData124(s, pbBuf, pbSrc, cbSize); 4930 else 4931 return VINF_IOM_R3_IOPORT_READ; 4932 4933 #elif defined(IN_RING0) 4934 /* Ring-0: We can do I/O thread signalling here. However there is one 4935 case in ataHCPIOTransfer that does a LogRel and would (but not from 4936 here) call directly into the driver code. We detect that odd case 4937 here cand return to ring-3 to handle it. */ 4938 if (s->iIOBufferPIODataStart + cbSize < s->iIOBufferPIODataEnd) 4939 ataCopyPioData124(s, pbBuf, pbSrc, cbSize); 4940 else if ( s->cbTotalTransfer == 0 4941 || s->iSourceSink != ATAFN_SS_NULL 4942 || s->iIOBufferCur <= s->iIOBufferEnd) 4943 { 4944 ataCopyPioData124(s, pbBuf, pbSrc, cbSize); 4945 ataHCPIOTransferFinish(pCtl, s); 4946 } 4947 else 4948 { 4949 Log(("%s: Unexpected\n",__FUNCTION__)); 4950 return VINF_IOM_R3_IOPORT_READ; 4951 } 4952 4953 #else /* IN_RING3 */ 4954 ataCopyPioData124(s, pbBuf, pbSrc, cbSize); 5087 # endif /* IN_RING3 */ 5088 PDMCritSectLeave(&pCtl->lock); 5089 } 5090 return rc; 5091 } 5092 5093 5094 /** 5095 * Port I/O Handler for primary port range OUT string operations. 5096 * @see FNIOMIOPORTOUTSTRING for details. 5097 */ 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; 5102 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *); 5103 PATACONTROLLER pCtl = &pThis->aCts[i]; 5104 int rc; 5105 5106 Assert(i < 2); 5107 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 { 5123 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 4955 5154 if (s->iIOBufferPIODataStart >= s->iIOBufferPIODataEnd) 4956 5155 ataHCPIOTransferFinish(pCtl, s); 4957 #endif /* IN_RING3 */ 4958 } 4959 else 4960 { 4961 Log2(("%s: DUMMY data\n", __FUNCTION__)); 4962 memset(pbBuf, '\xff', cbSize); 4963 } 4964 Log3(("%s: addr=%#x val=%.*Rhxs\n", __FUNCTION__, addr, cbSize, pbBuf)); 4965 return VINF_SUCCESS; 4966 } 5156 # endif /* IN_RING3 */ 5157 PDMCritSectLeave(&pCtl->lock); 5158 } 5159 return rc; 5160 } 5161 5162 #endif /* !IN_RING0 */ 5163 4967 5164 4968 5165 #ifdef IN_RING3 … … 5984 6181 /* -=-=-=-=-=- Wrappers -=-=-=-=-=- */ 5985 6182 5986 /**5987 * Port I/O Handler for primary port range OUT operations.5988 * @see FNIOMIOPORTOUT for details.5989 */5990 PDMBOTHCBDECL(int) ataIOPortWrite1Data(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)5991 {5992 uint32_t i = (uint32_t)(uintptr_t)pvUser;5993 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *);5994 PATACONTROLLER pCtl = &pThis->aCts[i];5995 5996 Assert(i < 2);5997 Assert(Port == pCtl->IOPortBase1);5998 5999 int rc = PDMCritSectEnter(&pCtl->lock, VINF_IOM_R3_IOPORT_WRITE);6000 if (rc == VINF_SUCCESS)6001 {6002 /* Writes to the data port may be 16-bit or 32-bit. */6003 Assert(cb == 2 || cb == 4);6004 rc = ataDataWrite(pCtl, Port, cb, (const uint8_t *)&u32);6005 6006 PDMCritSectLeave(&pCtl->lock);6007 }6008 return rc;6009 }6010 6011 6012 /**6013 * Port I/O Handler for primary port range IN operations.6014 * @see FNIOMIOPORTIN for details.6015 */6016 PDMBOTHCBDECL(int) ataIOPortRead1Data(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)6017 {6018 uint32_t i = (uint32_t)(uintptr_t)pvUser;6019 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *);6020 PATACONTROLLER pCtl = &pThis->aCts[i];6021 6022 Assert(i < 2);6023 Assert(Port == pCtl->IOPortBase1);6024 6025 int rc = PDMCritSectEnter(&pCtl->lock, VINF_IOM_R3_IOPORT_READ);6026 if (rc == VINF_SUCCESS)6027 {6028 /* Reads from the data register may be 16-bit or 32-bit. */6029 Assert(cb == 1 || cb == 2 || cb == 4);6030 rc = ataDataRead(pCtl, Port, cb == 1 ? 2 : cb, (uint8_t *)pu32);6031 if (cb <= 2)6032 *pu32 &= 0xffff >> (16 - cb * 8);6033 6034 PDMCritSectLeave(&pCtl->lock);6035 }6036 6037 return rc;6038 }6039 6040 #ifndef IN_RING0 /** @todo do this in ring-0 as well - after IEM specific interface rewrite! */6041 6042 /**6043 * Port I/O Handler for primary port range IN string operations.6044 * @see FNIOMIOPORTINSTRING for details.6045 */6046 PDMBOTHCBDECL(int) ataIOPortReadStr1Data(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrDst,6047 PRTGCUINTREG pcTransfer, unsigned cb)6048 {6049 uint32_t i = (uint32_t)(uintptr_t)pvUser;6050 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *);6051 PATACONTROLLER pCtl = &pThis->aCts[i];6052 int rc = VINF_SUCCESS;6053 6054 Assert(i < 2);6055 Assert(Port == pCtl->IOPortBase1);6056 6057 rc = PDMCritSectEnter(&pCtl->lock, VINF_IOM_R3_IOPORT_READ);6058 if (rc == VINF_SUCCESS)6059 {6060 ATADevState *s = &pCtl->aIfs[pCtl->iSelectedIf];6061 uint32_t cTransAvailable;6062 uint32_t cTransfer = *pcTransfer;6063 uint32_t cbTransfer;6064 RTGCPTR GCDst = *pGCPtrDst;6065 Assert(cb == 2 || cb == 4);6066 6067 cTransAvailable = (s->iIOBufferPIODataEnd - s->iIOBufferPIODataStart) / cb;6068 # ifndef IN_RING36069 /* Deal with the unlikely case where no data (or not enough for the read length operation) is available; go back to ring 3. */6070 if (!cTransAvailable)6071 {6072 PDMCritSectLeave(&pCtl->lock);6073 return VINF_IOM_R3_IOPORT_READ;6074 }6075 /* The last transfer unit cannot be handled in GC, as it involves thread communication. */6076 cTransAvailable--;6077 # endif /* !IN_RING3 */6078 /* Do not handle the dummy transfer stuff here, leave it to the single-word transfers.6079 * They are not performance-critical and generally shouldn't occur at all. */6080 if (cTransAvailable > cTransfer)6081 cTransAvailable = cTransfer;6082 cbTransfer = cTransAvailable * cb;6083 6084 rc = PGMPhysSimpleDirtyWriteGCPtr(PDMDevHlpGetVMCPU(pDevIns), GCDst, s->CTX_SUFF(pbIOBuffer) + s->iIOBufferPIODataStart, cbTransfer);6085 # ifndef IN_RING36086 /* Paranoia. */6087 if (RT_FAILURE(rc))6088 {6089 PDMCritSectLeave(&pCtl->lock);6090 AssertFailed();6091 return VINF_IOM_R3_IOPORT_READ;6092 }6093 # else6094 Assert(rc == VINF_SUCCESS);6095 # endif6096 6097 if (cbTransfer)6098 Log3(("%s: addr=%#x val=%.*Rhxs\n", __FUNCTION__, Port, cbTransfer, s->CTX_SUFF(pbIOBuffer) + s->iIOBufferPIODataStart));6099 s->iIOBufferPIODataStart += cbTransfer;6100 *pGCPtrDst = (RTGCPTR)((RTGCUINTPTR)GCDst + cbTransfer);6101 *pcTransfer = cTransfer - cTransAvailable;6102 # ifdef IN_RING36103 if (s->iIOBufferPIODataStart >= s->iIOBufferPIODataEnd)6104 ataHCPIOTransferFinish(pCtl, s);6105 # endif /* IN_RING3 */6106 PDMCritSectLeave(&pCtl->lock);6107 }6108 return rc;6109 }6110 6111 6112 /**6113 * Port I/O Handler for primary port range OUT string operations.6114 * @see FNIOMIOPORTOUTSTRING for details.6115 */6116 PDMBOTHCBDECL(int) ataIOPortWriteStr1Data(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrSrc,6117 PRTGCUINTREG pcTransfer, unsigned cb)6118 {6119 uint32_t i = (uint32_t)(uintptr_t)pvUser;6120 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *);6121 PATACONTROLLER pCtl = &pThis->aCts[i];6122 int rc;6123 6124 Assert(i < 2);6125 Assert(Port == pCtl->IOPortBase1);6126 6127 rc = PDMCritSectEnter(&pCtl->lock, VINF_IOM_R3_IOPORT_WRITE);6128 if (rc == VINF_SUCCESS)6129 {6130 ATADevState *s = &pCtl->aIfs[pCtl->iSelectedIf];6131 uint32_t cTransfer = *pcTransfer;6132 uint32_t cbTransfer;6133 RTGCPTR GCSrc = *pGCPtrSrc;6134 Assert(cb == 2 || cb == 4);6135 6136 uint32_t cTransAvailable = (s->iIOBufferPIODataEnd - s->iIOBufferPIODataStart) / cb;6137 # ifndef IN_RING36138 /* Deal with the unlikely case where no data (or not enough for the read length operation) is available; go back to ring 3. */6139 if (!cTransAvailable)6140 {6141 PDMCritSectLeave(&pCtl->lock);6142 return VINF_IOM_R3_IOPORT_WRITE;6143 }6144 /* The last transfer unit cannot be handled in GC, as it involves thread communication. */6145 cTransAvailable--;6146 # endif /* !IN_RING3 */6147 /* Do not handle the dummy transfer stuff here, leave it to the single-word transfers.6148 * They are not performance-critical and generally shouldn't occur at all. */6149 if (cTransAvailable > cTransfer)6150 cTransAvailable = cTransfer;6151 cbTransfer = cTransAvailable * cb;6152 6153 rc = PGMPhysSimpleReadGCPtr(PDMDevHlpGetVMCPU(pDevIns), s->CTX_SUFF(pbIOBuffer) + s->iIOBufferPIODataStart, GCSrc, cbTransfer);6154 # ifndef IN_RING36155 /* Paranoia. */6156 if (RT_FAILURE(rc))6157 {6158 PDMCritSectLeave(&pCtl->lock);6159 AssertFailed();6160 return VINF_IOM_R3_IOPORT_WRITE;6161 }6162 # else6163 Assert(rc == VINF_SUCCESS);6164 # endif6165 6166 if (cbTransfer)6167 Log3(("%s: addr=%#x val=%.*Rhxs\n", __FUNCTION__, Port, cbTransfer, s->CTX_SUFF(pbIOBuffer) + s->iIOBufferPIODataStart));6168 s->iIOBufferPIODataStart += cbTransfer;6169 *pGCPtrSrc = (RTGCPTR)((RTGCUINTPTR)GCSrc + cbTransfer);6170 *pcTransfer = cTransfer - cTransAvailable;6171 # ifdef IN_RING36172 if (s->iIOBufferPIODataStart >= s->iIOBufferPIODataEnd)6173 ataHCPIOTransferFinish(pCtl, s);6174 # endif /* IN_RING3 */6175 PDMCritSectLeave(&pCtl->lock);6176 }6177 return rc;6178 }6179 6180 #endif /* !IN_RING0 */6181 6183 6182 6184 /**
Note:
See TracChangeset
for help on using the changeset viewer.