VirtualBox

Changeset 87109 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Dec 21, 2020 1:19:44 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
141975
Message:

Dev/E1000: (bugref:9850) Descriptor ring register fixes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/DevE1000.cpp

    r87071 r87109  
    14561456    { 0x02800, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, e1kRegReadDefault      , e1kRegWriteDefault      , "RDBAL"   , "Receive Descriptor Base Low" },
    14571457    { 0x02804, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, e1kRegReadDefault      , e1kRegWriteDefault      , "RDBAH"   , "Receive Descriptor Base High" },
    1458     { 0x02808, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, e1kRegReadDefault      , e1kRegWriteDefault      , "RDLEN"   , "Receive Descriptor Length" },
    1459     { 0x02810, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, e1kRegReadDefault      , e1kRegWriteDefault      , "RDH"     , "Receive Descriptor Head" },
    1460     { 0x02818, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, e1kRegReadDefault      , e1kRegWriteRDT          , "RDT"     , "Receive Descriptor Tail" },
     1458    { 0x02808, 0x00004, 0x000FFF80, 0x000FFF80, e1kRegReadDefault      , e1kRegWriteDefault      , "RDLEN"   , "Receive Descriptor Length" },
     1459    { 0x02810, 0x00004, 0x0000FFFF, 0x0000FFFF, e1kRegReadDefault      , e1kRegWriteDefault      , "RDH"     , "Receive Descriptor Head" },
     1460    { 0x02818, 0x00004, 0x0000FFFF, 0x0000FFFF, e1kRegReadDefault      , e1kRegWriteRDT          , "RDT"     , "Receive Descriptor Tail" },
    14611461    { 0x02820, 0x00004, 0x0000FFFF, 0x0000FFFF, e1kRegReadDefault      , e1kRegWriteRDTR         , "RDTR"    , "Receive Delay Timer" },
    14621462    { 0x02828, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, e1kRegReadUnimplemented, e1kRegWriteUnimplemented, "RXDCTL"  , "Receive Descriptor Control" },
     
    14711471    { 0x03800, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, e1kRegReadDefault      , e1kRegWriteDefault      , "TDBAL"   , "Transmit Descriptor Base Low" },
    14721472    { 0x03804, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, e1kRegReadDefault      , e1kRegWriteDefault      , "TDBAH"   , "Transmit Descriptor Base High" },
    1473     { 0x03808, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, e1kRegReadDefault      , e1kRegWriteDefault      , "TDLEN"   , "Transmit Descriptor Length" },
     1473    { 0x03808, 0x00004, 0x000FFF80, 0x000FFF80, e1kRegReadDefault      , e1kRegWriteDefault      , "TDLEN"   , "Transmit Descriptor Length" },
    14741474    { 0x03810, 0x00004, 0x0000FFFF, 0x0000FFFF, e1kRegReadDefault      , e1kRegWriteDefault      , "TDH"     , "Transmit Descriptor Head" },
    14751475    { 0x03818, 0x00004, 0x0000FFFF, 0x0000FFFF, e1kRegReadDefault      , e1kRegWriteTDT          , "TDT"     , "Transmit Descriptor Tail" },
     
    16651665# define e1kCsTxEnter(ps, rc) PDMDevHlpCritSectEnter(pDevIns, &ps->csTx, rc)
    16661666# define e1kCsTxLeave(ps) PDMDevHlpCritSectLeave(pDevIns, &ps->csTx)
     1667# define e1kCsTxIsOwner(ps) PDMDevHlpCritSectIsOwner(pDevIns, &ps->csTx)
    16671668#endif /* E1K_WITH_TX_CS */
    16681669
     1670
     1671#ifdef E1K_WITH_TXD_CACHE
     1672/*
     1673 * Transmit Descriptor Register Context
     1674 */
     1675struct E1kTxDContext
     1676{
     1677    uint32_t tdlen;
     1678    uint32_t tdh;
     1679    uint32_t tdt;
     1680};
     1681typedef struct E1kTxDContext E1KTXDC, *PE1KTXDC;
     1682
     1683DECLINLINE(bool) e1kUpdateTxDContext(PPDMDEVINS pDevIns, PE1KSTATE pThis, PE1KTXDC pContext)
     1684{
     1685    Assert(e1kCsTxIsOwner(pThis));
     1686    if (!e1kCsTxIsOwner(pThis))
     1687        return false;
     1688    pContext->tdlen = TDLEN;
     1689    pContext->tdh   = TDH;
     1690    pContext->tdt   = TDT;
     1691    uint32_t cTxRingSize = pContext->tdlen / sizeof(E1KTXDESC);
     1692#ifdef DEBUG
     1693    if (pContext->tdh >= cTxRingSize)
     1694    {
     1695        Log(("%s e1kUpdateTxDContext: will return false because TDH too big (%u >= %u)\n",
     1696             pThis->szPrf, pContext->tdh, cTxRingSize));
     1697        return VINF_SUCCESS;
     1698    }
     1699    if (pContext->tdt >= cTxRingSize)
     1700    {
     1701        Log(("%s e1kUpdateTxDContext: will return false because TDT too big (%u >= %u)\n",
     1702             pThis->szPrf, pContext->tdt, cTxRingSize));
     1703        return VINF_SUCCESS;
     1704    }
     1705#endif /* DEBUG */
     1706    return pContext->tdh < cTxRingSize && pContext->tdt < cTxRingSize;
     1707}
     1708#endif /* E1K_WITH_TXD_CACHE */
     1709#ifdef E1K_WITH_RXD_CACHE
     1710/*
     1711 * Receive Descriptor Register Context
     1712 */
     1713struct E1kRxDContext
     1714{
     1715    uint32_t rdlen;
     1716    uint32_t rdh;
     1717    uint32_t rdt;
     1718};
     1719typedef struct E1kRxDContext E1KRXDC, *PE1KRXDC;
     1720
     1721DECLINLINE(bool) e1kUpdateRxDContext(PPDMDEVINS pDevIns, PE1KSTATE pThis, PE1KRXDC pContext, const char *pcszCallee)
     1722{
     1723    Assert(e1kCsRxIsOwner(pThis));
     1724    if (!e1kCsRxIsOwner(pThis))
     1725        return false;
     1726    pContext->rdlen = RDLEN;
     1727    pContext->rdh   = RDH;
     1728    pContext->rdt   = RDT;
     1729    uint32_t cRxRingSize = pContext->rdlen / sizeof(E1KRXDESC);
     1730#ifdef DEBUG
     1731    if (pContext->rdh >= cRxRingSize)
     1732    {
     1733        Log(("%s e1kUpdateRxDContext: called from %s, will return false because RDH too big (%u >= %u)\n",
     1734             pThis->szPrf, pcszCallee, pContext->rdh, cRxRingSize));
     1735        return VINF_SUCCESS;
     1736    }
     1737    if (pContext->rdt >= cRxRingSize)
     1738    {
     1739        Log(("%s e1kUpdateRxDContext: called from %s, will return false because RDT too big (%u >= %u)\n",
     1740             pThis->szPrf, pcszCallee, pContext->rdt, cRxRingSize));
     1741        return VINF_SUCCESS;
     1742    }
     1743#else /* !DEBUG */
     1744    RT_NOREF(pcszCallee);
     1745#endif /* !DEBUG */
     1746    return pContext->rdh < cRxRingSize && pContext->rdt < cRxRingSize; // && (RCTL & RCTL_EN);
     1747}
     1748#endif /* E1K_WITH_RXD_CACHE */
    16691749
    16701750/**
     
    18591939 *
    18601940 * @returns the number of available descriptors in RX ring.
    1861  * @param   pThis       The device state structure.
     1941 * @param   pRxdc       The receive descriptor register context.
    18621942 * @thread  ???
    18631943 */
    1864 DECLINLINE(uint32_t) e1kGetRxLen(PE1KSTATE pThis)
     1944DECLINLINE(uint32_t) e1kGetRxLen(PE1KRXDC pRxdc)
    18651945{
    18661946    /**
     
    18681948     *  any moment.
    18691949     */
    1870     uint32_t rdt = RDT;
    1871     return (RDH > rdt ? RDLEN/sizeof(E1KRXDESC) : 0) + rdt - RDH;
     1950    uint32_t rdt = pRxdc->rdt;
     1951    return (pRxdc->rdh > rdt ? pRxdc->rdlen/sizeof(E1KRXDESC) : 0) + rdt - pRxdc->rdh;
    18721952}
    18731953
     
    18951975 * @thread  EMT, RX
    18961976 */
    1897 DECLINLINE(unsigned) e1kRxDPrefetch(PPDMDEVINS pDevIns, PE1KSTATE pThis)
    1898 {
     1977DECLINLINE(unsigned) e1kRxDPrefetch(PPDMDEVINS pDevIns, PE1KSTATE pThis, PE1KRXDC pRxdc)
     1978{
     1979    E1kLog3(("%s e1kRxDPrefetch: RDH=%x RDT=%x RDLEN=%x "
     1980                 "iRxDCurrent=%x nRxDFetched=%x\n",
     1981                 pThis->szPrf, pRxdc->rdh, pRxdc->rdt, pRxdc->rdlen, pThis->iRxDCurrent, pThis->nRxDFetched));
    18991982    /* We've already loaded pThis->nRxDFetched descriptors past RDH. */
    1900     unsigned nDescsAvailable    = e1kGetRxLen(pThis) - e1kRxDInCache(pThis);
     1983    unsigned nDescsAvailable    = e1kGetRxLen(pRxdc) - e1kRxDInCache(pThis);
    19011984    unsigned nDescsToFetch      = RT_MIN(nDescsAvailable, E1K_RXD_CACHE_SIZE - pThis->nRxDFetched);
    1902     unsigned nDescsTotal        = RDLEN / sizeof(E1KRXDESC);
     1985    unsigned nDescsTotal        = pRxdc->rdlen / sizeof(E1KRXDESC);
    19031986    Assert(nDescsTotal != 0);
    19041987    if (nDescsTotal == 0)
    19051988        return 0;
    1906     unsigned nFirstNotLoaded    = (RDH + e1kRxDInCache(pThis)) % nDescsTotal;
     1989    unsigned nFirstNotLoaded    = (pRxdc->rdh + e1kRxDInCache(pThis)) % nDescsTotal;
    19071990    unsigned nDescsInSingleRead = RT_MIN(nDescsToFetch, nDescsTotal - nFirstNotLoaded);
    19081991    E1kLog3(("%s e1kRxDPrefetch: nDescsAvailable=%u nDescsToFetch=%u "
     
    19252008    E1kLog3(("%s Fetched %u RX descriptors at %08x%08x(0x%x), RDLEN=%08x, RDH=%08x, RDT=%08x\n",
    19262009             pThis->szPrf, nDescsInSingleRead,
    1927              RDBAH, RDBAL + RDH * sizeof(E1KRXDESC),
    1928              nFirstNotLoaded, RDLEN, RDH, RDT));
     2010             RDBAH, RDBAL + pRxdc->rdh * sizeof(E1KRXDESC),
     2011             nFirstNotLoaded, pRxdc->rdlen, pRxdc->rdh, pRxdc->rdt));
    19292012    if (nDescsToFetch > nDescsInSingleRead)
    19302013    {
     
    21652248 * @param   pThis       The device state structure.
    21662249 */
    2167 DECLINLINE(void) e1kAdvanceRDH(PPDMDEVINS pDevIns, PE1KSTATE pThis)
     2250DECLINLINE(void) e1kAdvanceRDH(PPDMDEVINS pDevIns, PE1KSTATE pThis, PE1KRXDC pRxdc)
    21682251{
    21692252    Assert(e1kCsRxIsOwner(pThis));
    21702253    //e1kCsEnter(pThis, RT_SRC_POS);
    2171     if (++RDH * sizeof(E1KRXDESC) >= RDLEN)
    2172         RDH = 0;
     2254    if (++pRxdc->rdh * sizeof(E1KRXDESC) >= pRxdc->rdlen)
     2255        pRxdc->rdh = 0;
     2256    RDH = pRxdc->rdh; /* Sync the actual register and RXDC */
    21732257#ifdef E1K_WITH_RXD_CACHE
    21742258    /*
     
    21872271        E1kLog3(("%s e1kAdvanceRDH: Rx cache is empty, RDH=%x RDT=%x "
    21882272                 "iRxDCurrent=%x nRxDFetched=%x\n",
    2189                  pThis->szPrf, RDH, RDT, pThis->iRxDCurrent, pThis->nRxDFetched));
    2190         e1kRxDPrefetch(pDevIns, pThis);
     2273                 pThis->szPrf, pRxdc->rdh, pRxdc->rdt, pThis->iRxDCurrent, pThis->nRxDFetched));
     2274        e1kRxDPrefetch(pDevIns, pThis, pRxdc);
    21912275    }
    21922276#endif /* E1K_WITH_RXD_CACHE */
     
    21952279     * if we are low on receive buffers
    21962280     */
    2197     uint32_t uRQueueLen = RDH>RDT ? RDLEN/sizeof(E1KRXDESC)-RDH+RDT : RDT-RDH;
     2281    uint32_t uRQueueLen = pRxdc->rdh>pRxdc->rdt ? pRxdc->rdlen/sizeof(E1KRXDESC)-pRxdc->rdh+pRxdc->rdt : pRxdc->rdt-pRxdc->rdh;
    21982282    /*
    21992283     * The minimum threshold is controlled by RDMTS bits of RCTL:
     
    22032287     * 11 = reserved
    22042288     */
    2205     uint32_t uMinRQThreshold = RDLEN / sizeof(E1KRXDESC) / (2 << GET_BITS(RCTL, RDMTS));
     2289    uint32_t uMinRQThreshold = pRxdc->rdlen / sizeof(E1KRXDESC) / (2 << GET_BITS(RCTL, RDMTS));
    22062290    if (uRQueueLen <= uMinRQThreshold)
    22072291    {
    2208         E1kLogRel(("E1000: low on RX descriptors, RDH=%x RDT=%x len=%x threshold=%x\n", RDH, RDT, uRQueueLen, uMinRQThreshold));
     2292        E1kLogRel(("E1000: low on RX descriptors, RDH=%x RDT=%x len=%x threshold=%x\n", pRxdc->rdh, pRxdc->rdt, uRQueueLen, uMinRQThreshold));
    22092293        E1kLog2(("%s Low on RX descriptors, RDH=%x RDT=%x len=%x threshold=%x, raise an interrupt\n",
    2210                  pThis->szPrf, RDH, RDT, uRQueueLen, uMinRQThreshold));
     2294                 pThis->szPrf, pRxdc->rdh, pRxdc->rdt, uRQueueLen, uMinRQThreshold));
    22112295        E1K_INC_ISTAT_CNT(pThis->uStatIntRXDMT0);
    22122296        e1kRaiseInterrupt(pDevIns, pThis, VERR_SEM_BUSY, ICR_RXDMT0);
    22132297    }
    22142298    E1kLog2(("%s e1kAdvanceRDH: at exit RDH=%x RDT=%x len=%x\n",
    2215              pThis->szPrf, RDH, RDT, uRQueueLen));
     2299             pThis->szPrf, pRxdc->rdh, pRxdc->rdt, uRQueueLen));
    22162300    //e1kCsLeave(pThis);
    22172301}
     
    22342318 * @thread  RX
    22352319 */
    2236 DECLINLINE(E1KRXDESC *) e1kRxDGet(PPDMDEVINS pDevIns, PE1KSTATE pThis)
     2320DECLINLINE(E1KRXDESC *) e1kRxDGet(PPDMDEVINS pDevIns, PE1KSTATE pThis, PE1KRXDC pRxdc)
    22372321{
    22382322    Assert(e1kCsRxIsOwner(pThis));
     
    22422326    /* Cache is empty, reset it and check if we can fetch more. */
    22432327    pThis->iRxDCurrent = pThis->nRxDFetched = 0;
    2244     if (e1kRxDPrefetch(pDevIns, pThis))
     2328    if (e1kRxDPrefetch(pDevIns, pThis, pRxdc))
    22452329        return &pThis->aRxDescriptors[pThis->iRxDCurrent];
    22462330    /* Out of Rx descriptors. */
     
    22582342 * @thread  RX
    22592343 */
    2260 DECLINLINE(void) e1kRxDPut(PPDMDEVINS pDevIns, PE1KSTATE pThis, E1KRXDESC* pDesc)
     2344DECLINLINE(void) e1kRxDPut(PPDMDEVINS pDevIns, PE1KSTATE pThis, E1KRXDESC* pDesc, PE1KRXDC pRxdc)
    22612345{
    22622346    Assert(e1kCsRxIsOwner(pThis));
     
    22672351    // uint32_t rdh = RDH;
    22682352    // Assert(pThis->aRxDescAddr[pDesc - pThis->aRxDescriptors] == addr);
    2269     PDMDevHlpPCIPhysWrite(pDevIns, e1kDescAddr(RDBAH, RDBAL, RDH), pDesc, sizeof(E1KRXDESC));
     2353    PDMDevHlpPCIPhysWrite(pDevIns, e1kDescAddr(RDBAH, RDBAL, pRxdc->rdh), pDesc, sizeof(E1KRXDESC));
    22702354    /*
    22712355     * We need to print the descriptor before advancing RDH as it may fetch new
     
    22732357     */
    22742358    e1kPrintRDesc(pThis, pDesc);
    2275     e1kAdvanceRDH(pDevIns, pThis);
     2359    e1kAdvanceRDH(pDevIns, pThis, pRxdc);
    22762360}
    22772361
     
    24482532    uint8_t   rxPacket[E1K_MAX_RX_PKT_SIZE];
    24492533    uint8_t  *ptr = rxPacket;
     2534# ifdef E1K_WITH_RXD_CACHE
     2535    E1KRXDC   rxdc;
     2536# endif /* E1K_WITH_RXD_CACHE */
    24502537
    24512538    int rc = e1kCsRxEnter(pThis, VERR_SEM_BUSY);
    24522539    if (RT_UNLIKELY(rc != VINF_SUCCESS))
    24532540        return rc;
     2541# ifdef E1K_WITH_RXD_CACHE
     2542    if (RT_UNLIKELY(!e1kUpdateRxDContext(pDevIns, pThis, &rxdc, "e1kHandleRxPacket")))
     2543    {
     2544        e1kCsRxLeave(pThis);
     2545        E1kLog(("%s e1kHandleRxPacket: failed to update Rx context, returning VINF_SUCCESS\n",  pThis->szPrf));
     2546        return VINF_SUCCESS;
     2547    }
     2548# endif /* E1K_WITH_RXD_CACHE */
    24542549
    24552550    if (cb > 70) /* unqualified guess */
     
    25332628    while (cb > 0)
    25342629    {
    2535         E1KRXDESC *pDesc = e1kRxDGet(pDevIns, pThis);
     2630        E1KRXDESC *pDesc = e1kRxDGet(pDevIns, pThis, &rxdc);
    25362631
    25372632        if (pDesc == NULL)
     
    25392634            E1kLog(("%s Out of receive buffers, dropping the packet "
    25402635                    "(cb=%u, in_cache=%u, RDH=%x RDT=%x)\n",
    2541                     pThis->szPrf, cb, e1kRxDInCache(pThis), RDH, RDT));
     2636                    pThis->szPrf, cb, e1kRxDInCache(pThis), rxdc.rdh, rxdc.rdt));
    25422637            break;
    25432638        }
     
    25802675                if (RT_UNLIKELY(rc != VINF_SUCCESS))
    25812676                    return rc;
     2677# ifdef E1K_WITH_RXD_CACHE
     2678                if (RT_UNLIKELY(!e1kUpdateRxDContext(pDevIns, pThis, &rxdc, "e1kHandleRxPacket")))
     2679                {
     2680                    e1kCsRxLeave(pThis);
     2681                    E1kLog(("%s e1kHandleRxPacket: failed to update Rx context, returning VINF_SUCCESS\n",  pThis->szPrf));
     2682                    return VINF_SUCCESS;
     2683                }
     2684# endif /* E1K_WITH_RXD_CACHE */
    25822685                ptr += u16RxBufferSize;
    25832686                cb -= u16RxBufferSize;
     
    25922695                if (RT_UNLIKELY(rc != VINF_SUCCESS))
    25932696                    return rc;
     2697                if (RT_UNLIKELY(!e1kUpdateRxDContext(pDevIns, pThis, &rxdc, "e1kHandleRxPacket")))
     2698                {
     2699                    e1kCsRxLeave(pThis);
     2700                    E1kLog(("%s e1kHandleRxPacket: failed to update Rx context, returning VINF_SUCCESS\n",  pThis->szPrf));
     2701                    return VINF_SUCCESS;
     2702                }
    25942703                cb = 0;
    25952704# else /* !E1K_WITH_RXD_CACHE */
     
    26062715        /* Write back the descriptor. */
    26072716        pDesc->status.fDD = true;
    2608         e1kRxDPut(pDevIns, pThis, pDesc);
     2717        e1kRxDPut(pDevIns, pThis, pDesc, &rxdc);
    26092718# else /* !E1K_WITH_RXD_CACHE */
    26102719        else
     
    33173426        rc = e1kRegWriteDefault(pDevIns, pThis, offset, index, value);
    33183427#ifdef E1K_WITH_RXD_CACHE
     3428        E1KRXDC rxdc;
     3429        if (RT_UNLIKELY(!e1kUpdateRxDContext(pDevIns, pThis, &rxdc, "e1kRegWriteRDT")))
     3430        {
     3431            e1kCsRxLeave(pThis);
     3432            E1kLog(("%s e1kRegWriteRDT: failed to update Rx context, returning VINF_SUCCESS\n",  pThis->szPrf));
     3433            return VINF_SUCCESS;
     3434        }
    33193435        /*
    33203436         * We need to fetch descriptors now as RDT may go whole circle
     
    33373453         */
    33383454        if (e1kRxDIsCacheEmpty(pThis) && (RCTL & RCTL_EN))
    3339             e1kRxDPrefetch(pDevIns, pThis);
     3455            e1kRxDPrefetch(pDevIns, pThis, &rxdc);
    33403456#endif /* E1K_WITH_RXD_CACHE */
    33413457        e1kCsRxLeave(pThis);
     
    33763492}
    33773493
    3378 DECLINLINE(uint32_t) e1kGetTxLen(PE1KSTATE pThis)
     3494DECLINLINE(uint32_t) e1kGetTxLen(PE1KTXDC pTxdc)
    33793495{
    33803496    /**
     
    33823498     *  any moment.
    33833499     */
    3384     uint32_t tdt = TDT;
    3385     return (TDH>tdt ? TDLEN/sizeof(E1KTXDESC) : 0) + tdt - TDH;
     3500    uint32_t tdt = pTxdc->tdt;
     3501    return (pTxdc->tdh > tdt ? pTxdc->tdlen/sizeof(E1KTXDESC) : 0) + tdt - pTxdc->tdh;
    33863502}
    33873503
     
    39394055 * @thread  E1000_TX
    39404056 */
    3941 DECLINLINE(unsigned) e1kTxDLoadMore(PPDMDEVINS pDevIns, PE1KSTATE pThis)
     4057DECLINLINE(unsigned) e1kTxDLoadMore(PPDMDEVINS pDevIns, PE1KSTATE pThis, PE1KTXDC pTxdc)
    39424058{
    39434059    Assert(pThis->iTxDCurrent == 0);
    39444060    /* We've already loaded pThis->nTxDFetched descriptors past TDH. */
    3945     unsigned nDescsAvailable    = e1kGetTxLen(pThis) - pThis->nTxDFetched;
     4061    unsigned nDescsAvailable    = e1kGetTxLen(pTxdc) - pThis->nTxDFetched;
    39464062    /* The following two lines ensure that pThis->nTxDFetched never overflows. */
    39474063    AssertCompile(E1K_TXD_CACHE_SIZE < (256 * sizeof(pThis->nTxDFetched)));
    39484064    unsigned nDescsToFetch      = RT_MIN(nDescsAvailable, E1K_TXD_CACHE_SIZE - pThis->nTxDFetched);
    3949     unsigned nDescsTotal        = TDLEN / sizeof(E1KTXDESC);
     4065    unsigned nDescsTotal        = pTxdc->tdlen / sizeof(E1KTXDESC);
    39504066    Assert(nDescsTotal != 0);
    39514067    if (nDescsTotal == 0)
    39524068        return 0;
    3953     unsigned nFirstNotLoaded    = (TDH + pThis->nTxDFetched) % nDescsTotal;
     4069    unsigned nFirstNotLoaded    = (pTxdc->tdh + pThis->nTxDFetched) % nDescsTotal;
    39544070    unsigned nDescsInSingleRead = RT_MIN(nDescsToFetch, nDescsTotal - nFirstNotLoaded);
    39554071    E1kLog3(("%s e1kTxDLoadMore: nDescsAvailable=%u nDescsToFetch=%u nDescsTotal=%u nFirstNotLoaded=0x%x nDescsInSingleRead=%u\n",
     
    39644080    E1kLog3(("%s Fetched %u TX descriptors at %08x%08x(0x%x), TDLEN=%08x, TDH=%08x, TDT=%08x\n",
    39654081             pThis->szPrf, nDescsInSingleRead,
    3966              TDBAH, TDBAL + TDH * sizeof(E1KTXDESC),
    3967              nFirstNotLoaded, TDLEN, TDH, TDT));
     4082             TDBAH, TDBAL + pTxdc->tdh * sizeof(E1KTXDESC),
     4083             nFirstNotLoaded, pTxdc->tdlen, pTxdc->tdh, pTxdc->tdt));
    39684084    if (nDescsToFetch > nDescsInSingleRead)
    39694085    {
     
    39894105 * @thread  E1000_TX
    39904106 */
    3991 DECLINLINE(bool) e1kTxDLazyLoad(PPDMDEVINS pDevIns, PE1KSTATE pThis)
     4107DECLINLINE(bool) e1kTxDLazyLoad(PPDMDEVINS pDevIns, PE1KSTATE pThis, PE1KTXDC pTxdc)
    39924108{
    39934109    if (pThis->nTxDFetched == 0)
    3994         return e1kTxDLoadMore(pDevIns, pThis) != 0;
     4110        return e1kTxDLoadMore(pDevIns, pThis, pTxdc) != 0;
    39954111    return true;
    39964112}
     
    53345450}
    53355451
    5336 static int e1kXmitPacket(PPDMDEVINS pDevIns, PE1KSTATE pThis, bool fOnWorkerThread)
     5452static int e1kXmitPacket(PPDMDEVINS pDevIns, PE1KSTATE pThis, bool fOnWorkerThread, PE1KTXDC pTxdc)
    53375453{
    53385454    PE1KSTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PE1KSTATECC);
     
    53465462        E1KTXDESC *pDesc = &pThis->aTxDescriptors[pThis->iTxDCurrent];
    53475463        E1kLog3(("%s About to process new TX descriptor at %08x%08x, TDLEN=%08x, TDH=%08x, TDT=%08x\n",
    5348                  pThis->szPrf, TDBAH, TDBAL + TDH * sizeof(E1KTXDESC), TDLEN, TDH, TDT));
    5349         rc = e1kXmitDesc(pDevIns, pThis, pThisCC, pDesc, e1kDescAddr(TDBAH, TDBAL, TDH), fOnWorkerThread);
     5464                 pThis->szPrf, TDBAH, TDBAL + pTxdc->tdh * sizeof(E1KTXDESC), pTxdc->tdlen, pTxdc->tdh, pTxdc->tdt));
     5465        rc = e1kXmitDesc(pDevIns, pThis, pThisCC, pDesc, e1kDescAddr(TDBAH, TDBAL, pTxdc->tdh), fOnWorkerThread);
    53505466        if (RT_FAILURE(rc))
    53515467            break;
    5352         if (++TDH * sizeof(E1KTXDESC) >= TDLEN)
    5353             TDH = 0;
     5468        if (++pTxdc->tdh * sizeof(E1KTXDESC) >= pTxdc->tdlen)
     5469            pTxdc->tdh = 0;
     5470        TDH = pTxdc->tdh; /* Sync the actual register and TXDC */
    53545471        uint32_t uLowThreshold = GET_BITS(TXDCTL, LWTHRESH)*8;
    5355         if (uLowThreshold != 0 && e1kGetTxLen(pThis) <= uLowThreshold)
     5472        if (uLowThreshold != 0 && e1kGetTxLen(pTxdc) <= uLowThreshold)
    53565473        {
    53575474            E1kLog2(("%s Low on transmit descriptors, raise ICR.TXD_LOW, len=%x thresh=%x\n",
    5358                      pThis->szPrf, e1kGetTxLen(pThis), GET_BITS(TXDCTL, LWTHRESH)*8));
     5475                     pThis->szPrf, e1kGetTxLen(pTxdc), GET_BITS(TXDCTL, LWTHRESH)*8));
    53595476            e1kRaiseInterrupt(pDevIns, pThis, VERR_SEM_BUSY, ICR_TXD_LOW);
    53605477        }
     
    54485565#else /* E1K_WITH_TXD_CACHE */
    54495566
    5450 static void e1kDumpTxDCache(PPDMDEVINS pDevIns, PE1KSTATE pThis)
    5451 {
    5452     unsigned i, cDescs = TDLEN / sizeof(E1KTXDESC);
    5453     uint32_t tdh = TDH;
     5567static void e1kDumpTxDCache(PPDMDEVINS pDevIns, PE1KSTATE pThis, PE1KTXDC pTxdc)
     5568{
     5569    unsigned i, cDescs = pTxdc->tdlen / sizeof(E1KTXDESC);
     5570    uint32_t tdh = pTxdc->tdh;
    54545571    LogRel(("E1000: -- Transmit Descriptors (%d total) --\n", cDescs));
    54555572    for (i = 0; i < cDescs; ++i)
     
    54625579    }
    54635580    LogRel(("E1000: -- Transmit Descriptors in Cache (at %d (TDH %d)/ fetched %d / max %d) --\n",
    5464             pThis->iTxDCurrent, TDH, pThis->nTxDFetched, E1K_TXD_CACHE_SIZE));
     5581            pThis->iTxDCurrent, pTxdc->tdh, pThis->nTxDFetched, E1K_TXD_CACHE_SIZE));
    54655582    if (tdh > pThis->iTxDCurrent)
    54665583        tdh -= pThis->iTxDCurrent;
     
    55115628     */
    55125629    rc = e1kCsTxEnter(pThis, VERR_SEM_BUSY);
    5513     if (RT_LIKELY(rc == VINF_SUCCESS))
    5514     {
     5630    if (RT_LIKELY(rc == VINF_SUCCESS && (TCTL & TCTL_EN)))
     5631    {
     5632        E1KTXDC txdc;
     5633        bool fTxContextValid = e1kUpdateTxDContext(pDevIns, pThis, &txdc);
    55155634        STAM_PROFILE_ADV_START(&pThis->CTX_SUFF_Z(StatTransmit), a);
    55165635        /*
     
    55215640         */
    55225641        bool fIncomplete = false;
    5523         while (!pThis->fLocked && e1kTxDLazyLoad(pDevIns, pThis))
     5642        while (fTxContextValid && !pThis->fLocked && e1kTxDLazyLoad(pDevIns, pThis, &txdc))
    55245643        {
    55255644            while (e1kLocateTxPacket(pThis))
     
    55325651                    goto out;
    55335652                /* Copy the packet to allocated buffer and send it. */
    5534                 rc = e1kXmitPacket(pDevIns, pThis, fOnWorkerThread);
     5653                rc = e1kXmitPacket(pDevIns, pThis, fOnWorkerThread, &txdc);
    55355654                /* If we're out of bandwidth we'll come back later. */
    55365655                if (RT_FAILURE(rc))
     
    55515670                      u8Remain == E1K_TXD_CACHE_SIZE ? " full" : "",
    55525671                      pThis->nTxDFetched, pThis->iTxDCurrent,
    5553                       e1kGetTxLen(pThis)));
     5672                      e1kGetTxLen(&txdc)));
    55545673                if (!fTxDCacheDumped)
    55555674                {
    55565675                    fTxDCacheDumped = true;
    5557                     e1kDumpTxDCache(pDevIns, pThis);
     5676                    e1kDumpTxDCache(pDevIns, pThis, &txdc);
    55585677                }
    55595678                pThis->iTxDCurrent = pThis->nTxDFetched = 0;
     
    55745693                      "%d more are available\n",
    55755694                      pThis->szPrf, pThis->iTxDCurrent, u8Remain,
    5576                       e1kGetTxLen(pThis) - u8Remain));
     5695                      e1kGetTxLen(&txdc) - u8Remain));
    55775696
    55785697                /*
     
    55855704                pThis->iTxDCurrent = 0;
    55865705                pThis->nTxDFetched = u8Remain;
    5587                 e1kTxDLoadMore(pDevIns, pThis);
     5706                e1kTxDLoadMore(pDevIns, pThis, &txdc);
    55885707                fIncomplete = true;
    55895708            }
     
    56685787            pThis->szPrf, TDBAL, TDBAH, TDLEN, TDH, TDT));
    56695788
     5789    /* Compose a temporary TX context, breaking TX CS rule, for debugging purposes. */
     5790    /* If we decide to transmit, the TX critical section will be entered later in e1kXmitPending(). */
     5791    E1KTXDC txdc;
     5792    txdc.tdlen = TDLEN;
     5793    txdc.tdh   = TDH;
     5794    txdc.tdt   = TDT;
    56705795    /* Ignore TDT writes when the link is down. */
    5671     if (TDH != TDT && (STATUS & STATUS_LU))
    5672     {
    5673         Log5(("E1000: TDT write: TDH=%08x, TDT=%08x, %d descriptors to process\n", TDH, TDT, e1kGetTxLen(pThis)));
     5796    if (txdc.tdh != txdc.tdt && (STATUS & STATUS_LU))
     5797    {
     5798        Log5(("E1000: TDT write: TDH=%08x, TDT=%08x, %d descriptors to process\n", txdc.tdh, txdc.tdt, e1kGetTxLen(&txdc)));
    56745799        E1kLog(("%s e1kRegWriteTDT: %d descriptors to process\n",
    5675                  pThis->szPrf, e1kGetTxLen(pThis)));
     5800                 pThis->szPrf, e1kGetTxLen(&txdc)));
    56765801
    56775802        /* Transmit pending packets if possible, defer it if we cannot do it
     
    62596384            case 0x00: /* IOADDR */
    62606385                *pu32 = pThis->uSelectedReg;
    6261                 E1kLog2(("%s e1kIOPortIn: IOADDR(0), selecting register %#010x, val=%#010x\n", pThis->szPrf, pThis->uSelectedReg, *pu32));
     6386                Log9(("%s e1kIOPortIn: IOADDR(0), selecting register %#010x, val=%#010x\n", pThis->szPrf, pThis->uSelectedReg, *pu32));
    62626387                rc = VINF_SUCCESS;
    62636388                break;
     
    62706395                if (rc == VINF_IOM_R3_MMIO_READ)
    62716396                    rc = VINF_IOM_R3_IOPORT_READ;
    6272                 E1kLog2(("%s e1kIOPortIn: IODATA(4), reading from selected register %#010x, val=%#010x\n", pThis->szPrf, pThis->uSelectedReg, *pu32));
     6397                Log9(("%s e1kIOPortIn: IODATA(4), reading from selected register %#010x, val=%#010x\n", pThis->szPrf, pThis->uSelectedReg, *pu32));
    62736398                break;
    62746399
     
    63016426    RT_NOREF_PV(pvUser);
    63026427
    6303     E1kLog2(("%s e1kIOPortOut: offPort=%RTiop value=%08x\n", pThis->szPrf, offPort, u32));
     6428    Log9(("%s e1kIOPortOut: offPort=%RTiop value=%08x\n", pThis->szPrf, offPort, u32));
    63046429    if (RT_LIKELY(cb == 4))
    63056430    {
     
    63086433            case 0x00: /* IOADDR */
    63096434                pThis->uSelectedReg = u32;
    6310                 E1kLog2(("%s e1kIOPortOut: IOADDR(0), selected register %08x\n", pThis->szPrf, pThis->uSelectedReg));
     6435                Log9(("%s e1kIOPortOut: IOADDR(0), selected register %08x\n", pThis->szPrf, pThis->uSelectedReg));
    63116436                rc = VINF_SUCCESS;
    63126437                break;
    63136438
    63146439            case 0x04: /* IODATA */
    6315                 E1kLog2(("%s e1kIOPortOut: IODATA(4), writing to selected register %#010x, value=%#010x\n", pThis->szPrf, pThis->uSelectedReg, u32));
     6440                Log9(("%s e1kIOPortOut: IODATA(4), writing to selected register %#010x, value=%#010x\n", pThis->szPrf, pThis->uSelectedReg, u32));
    63166441                if (RT_LIKELY(!(pThis->uSelectedReg & 3)))
    63176442                {
     
    64436568    if (RT_UNLIKELY(e1kCsRxEnter(pThis, VERR_SEM_BUSY) != VINF_SUCCESS))
    64446569        return VERR_NET_NO_BUFFER_SPACE;
    6445 
    6446     if (RT_UNLIKELY(RDLEN == sizeof(E1KRXDESC)))
     6570    E1KRXDC rxdc;
     6571    if (RT_UNLIKELY(!e1kUpdateRxDContext(pDevIns, pThis, &rxdc, "e1kCanReceive")))
     6572    {
     6573        e1kCsRxLeave(pThis);
     6574        E1kLog(("%s e1kCanReceive: failed to update Rx context, returning VERR_NET_NO_BUFFER_SPACE\n",  pThis->szPrf));
     6575        return VERR_NET_NO_BUFFER_SPACE;
     6576    }
     6577
     6578    if (RT_UNLIKELY(rxdc.rdlen == sizeof(E1KRXDESC)))
    64476579    {
    64486580        E1KRXDESC desc;
    6449         PDMDevHlpPCIPhysRead(pDevIns, e1kDescAddr(RDBAH, RDBAL, RDH), &desc, sizeof(desc));
     6581        PDMDevHlpPCIPhysRead(pDevIns, e1kDescAddr(RDBAH, RDBAL, rxdc.rdh), &desc, sizeof(desc));
    64506582        if (desc.status.fDD)
    64516583            rc = VERR_NET_NO_BUFFER_SPACE;
    64526584    }
    6453     else if (e1kRxDIsCacheEmpty(pThis) && RDH == RDT)
     6585    else if (e1kRxDIsCacheEmpty(pThis) && rxdc.rdh == rxdc.rdt)
    64546586    {
    64556587        /* Cache is empty, so is the RX ring. */
     
    64586590    E1kLog2(("%s e1kCanReceive: at exit in_cache=%d RDH=%d RDT=%d RDLEN=%d"
    64596591             " u16RxBSize=%d rc=%Rrc\n", pThis->szPrf,
    6460              e1kRxDInCache(pThis), RDH, RDT, RDLEN, pThis->u16RxBSize, rc));
     6592             e1kRxDInCache(pThis), rxdc.rdh, rxdc.rdt, rxdc.rdlen, pThis->u16RxBSize, rc));
    64616593
    64626594    e1kCsRxLeave(pThis);
Note: See TracChangeset for help on using the changeset viewer.

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