VirtualBox

Changeset 56406 in vbox for trunk/src/VBox/Devices/Storage


Ignore:
Timestamp:
Jun 13, 2015 7:31:54 PM (10 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
101007
Message:

DevATA: Merged ataIOPortRead1Data/ataIOPortWrite1Data with ataDataRead/Write.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/DevATA.cpp

    r56405 r56406  
    48694869}
    48704870
    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 */
     4876PDMBOTHCBDECL(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;
    48794896
    48804897#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        }
    48854927        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 */
     4943PDMBOTHCBDECL(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;
    48874976
    48884977#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;
    48975006        }
    48985007        else
    48995008        {
    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 */
     5028PDMBOTHCBDECL(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
    49065085        if (s->iIOBufferPIODataStart >= s->iIOBufferPIODataEnd)
    49075086            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 */
     5098PDMBOTHCBDECL(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
    49555154        if (s->iIOBufferPIODataStart >= s->iIOBufferPIODataEnd)
    49565155            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
    49675164
    49685165#ifdef IN_RING3
     
    59846181/* -=-=-=-=-=- Wrappers  -=-=-=-=-=- */
    59856182
    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_RING3
    6069         /* 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_RING3
    6086         /* Paranoia. */
    6087         if (RT_FAILURE(rc))
    6088         {
    6089             PDMCritSectLeave(&pCtl->lock);
    6090             AssertFailed();
    6091             return VINF_IOM_R3_IOPORT_READ;
    6092         }
    6093 # else
    6094         Assert(rc == VINF_SUCCESS);
    6095 # endif
    6096 
    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_RING3
    6103         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_RING3
    6138         /* 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_RING3
    6155         /* Paranoia. */
    6156         if (RT_FAILURE(rc))
    6157         {
    6158             PDMCritSectLeave(&pCtl->lock);
    6159             AssertFailed();
    6160             return VINF_IOM_R3_IOPORT_WRITE;
    6161         }
    6162 # else
    6163         Assert(rc == VINF_SUCCESS);
    6164 # endif
    6165 
    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_RING3
    6172         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 */
    61816183
    61826184/**
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette