Changeset 87109 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Dec 21, 2020 1:19:44 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 141975
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DevE1000.cpp
r87071 r87109 1456 1456 { 0x02800, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, e1kRegReadDefault , e1kRegWriteDefault , "RDBAL" , "Receive Descriptor Base Low" }, 1457 1457 { 0x02804, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, e1kRegReadDefault , e1kRegWriteDefault , "RDBAH" , "Receive Descriptor Base High" }, 1458 { 0x02808, 0x00004, 0x FFFFFFFF, 0xFFFFFFFF, e1kRegReadDefault , e1kRegWriteDefault , "RDLEN" , "Receive Descriptor Length" },1459 { 0x02810, 0x00004, 0x FFFFFFFF, 0xFFFFFFFF, e1kRegReadDefault , e1kRegWriteDefault , "RDH" , "Receive Descriptor Head" },1460 { 0x02818, 0x00004, 0x FFFFFFFF, 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" }, 1461 1461 { 0x02820, 0x00004, 0x0000FFFF, 0x0000FFFF, e1kRegReadDefault , e1kRegWriteRDTR , "RDTR" , "Receive Delay Timer" }, 1462 1462 { 0x02828, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, e1kRegReadUnimplemented, e1kRegWriteUnimplemented, "RXDCTL" , "Receive Descriptor Control" }, … … 1471 1471 { 0x03800, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, e1kRegReadDefault , e1kRegWriteDefault , "TDBAL" , "Transmit Descriptor Base Low" }, 1472 1472 { 0x03804, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, e1kRegReadDefault , e1kRegWriteDefault , "TDBAH" , "Transmit Descriptor Base High" }, 1473 { 0x03808, 0x00004, 0x FFFFFFFF, 0xFFFFFFFF, e1kRegReadDefault , e1kRegWriteDefault , "TDLEN" , "Transmit Descriptor Length" },1473 { 0x03808, 0x00004, 0x000FFF80, 0x000FFF80, e1kRegReadDefault , e1kRegWriteDefault , "TDLEN" , "Transmit Descriptor Length" }, 1474 1474 { 0x03810, 0x00004, 0x0000FFFF, 0x0000FFFF, e1kRegReadDefault , e1kRegWriteDefault , "TDH" , "Transmit Descriptor Head" }, 1475 1475 { 0x03818, 0x00004, 0x0000FFFF, 0x0000FFFF, e1kRegReadDefault , e1kRegWriteTDT , "TDT" , "Transmit Descriptor Tail" }, … … 1665 1665 # define e1kCsTxEnter(ps, rc) PDMDevHlpCritSectEnter(pDevIns, &ps->csTx, rc) 1666 1666 # define e1kCsTxLeave(ps) PDMDevHlpCritSectLeave(pDevIns, &ps->csTx) 1667 # define e1kCsTxIsOwner(ps) PDMDevHlpCritSectIsOwner(pDevIns, &ps->csTx) 1667 1668 #endif /* E1K_WITH_TX_CS */ 1668 1669 1670 1671 #ifdef E1K_WITH_TXD_CACHE 1672 /* 1673 * Transmit Descriptor Register Context 1674 */ 1675 struct E1kTxDContext 1676 { 1677 uint32_t tdlen; 1678 uint32_t tdh; 1679 uint32_t tdt; 1680 }; 1681 typedef struct E1kTxDContext E1KTXDC, *PE1KTXDC; 1682 1683 DECLINLINE(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 */ 1713 struct E1kRxDContext 1714 { 1715 uint32_t rdlen; 1716 uint32_t rdh; 1717 uint32_t rdt; 1718 }; 1719 typedef struct E1kRxDContext E1KRXDC, *PE1KRXDC; 1720 1721 DECLINLINE(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 */ 1669 1749 1670 1750 /** … … 1859 1939 * 1860 1940 * @returns the number of available descriptors in RX ring. 1861 * @param p This The device state structure.1941 * @param pRxdc The receive descriptor register context. 1862 1942 * @thread ??? 1863 1943 */ 1864 DECLINLINE(uint32_t) e1kGetRxLen(PE1K STATE pThis)1944 DECLINLINE(uint32_t) e1kGetRxLen(PE1KRXDC pRxdc) 1865 1945 { 1866 1946 /** … … 1868 1948 * any moment. 1869 1949 */ 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; 1872 1952 } 1873 1953 … … 1895 1975 * @thread EMT, RX 1896 1976 */ 1897 DECLINLINE(unsigned) e1kRxDPrefetch(PPDMDEVINS pDevIns, PE1KSTATE pThis) 1898 { 1977 DECLINLINE(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)); 1899 1982 /* We've already loaded pThis->nRxDFetched descriptors past RDH. */ 1900 unsigned nDescsAvailable = e1kGetRxLen(p This) - e1kRxDInCache(pThis);1983 unsigned nDescsAvailable = e1kGetRxLen(pRxdc) - e1kRxDInCache(pThis); 1901 1984 unsigned nDescsToFetch = RT_MIN(nDescsAvailable, E1K_RXD_CACHE_SIZE - pThis->nRxDFetched); 1902 unsigned nDescsTotal = RDLEN/ sizeof(E1KRXDESC);1985 unsigned nDescsTotal = pRxdc->rdlen / sizeof(E1KRXDESC); 1903 1986 Assert(nDescsTotal != 0); 1904 1987 if (nDescsTotal == 0) 1905 1988 return 0; 1906 unsigned nFirstNotLoaded = ( RDH+ e1kRxDInCache(pThis)) % nDescsTotal;1989 unsigned nFirstNotLoaded = (pRxdc->rdh + e1kRxDInCache(pThis)) % nDescsTotal; 1907 1990 unsigned nDescsInSingleRead = RT_MIN(nDescsToFetch, nDescsTotal - nFirstNotLoaded); 1908 1991 E1kLog3(("%s e1kRxDPrefetch: nDescsAvailable=%u nDescsToFetch=%u " … … 1925 2008 E1kLog3(("%s Fetched %u RX descriptors at %08x%08x(0x%x), RDLEN=%08x, RDH=%08x, RDT=%08x\n", 1926 2009 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)); 1929 2012 if (nDescsToFetch > nDescsInSingleRead) 1930 2013 { … … 2165 2248 * @param pThis The device state structure. 2166 2249 */ 2167 DECLINLINE(void) e1kAdvanceRDH(PPDMDEVINS pDevIns, PE1KSTATE pThis )2250 DECLINLINE(void) e1kAdvanceRDH(PPDMDEVINS pDevIns, PE1KSTATE pThis, PE1KRXDC pRxdc) 2168 2251 { 2169 2252 Assert(e1kCsRxIsOwner(pThis)); 2170 2253 //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 */ 2173 2257 #ifdef E1K_WITH_RXD_CACHE 2174 2258 /* … … 2187 2271 E1kLog3(("%s e1kAdvanceRDH: Rx cache is empty, RDH=%x RDT=%x " 2188 2272 "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); 2191 2275 } 2192 2276 #endif /* E1K_WITH_RXD_CACHE */ … … 2195 2279 * if we are low on receive buffers 2196 2280 */ 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; 2198 2282 /* 2199 2283 * The minimum threshold is controlled by RDMTS bits of RCTL: … … 2203 2287 * 11 = reserved 2204 2288 */ 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)); 2206 2290 if (uRQueueLen <= uMinRQThreshold) 2207 2291 { 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)); 2209 2293 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)); 2211 2295 E1K_INC_ISTAT_CNT(pThis->uStatIntRXDMT0); 2212 2296 e1kRaiseInterrupt(pDevIns, pThis, VERR_SEM_BUSY, ICR_RXDMT0); 2213 2297 } 2214 2298 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)); 2216 2300 //e1kCsLeave(pThis); 2217 2301 } … … 2234 2318 * @thread RX 2235 2319 */ 2236 DECLINLINE(E1KRXDESC *) e1kRxDGet(PPDMDEVINS pDevIns, PE1KSTATE pThis )2320 DECLINLINE(E1KRXDESC *) e1kRxDGet(PPDMDEVINS pDevIns, PE1KSTATE pThis, PE1KRXDC pRxdc) 2237 2321 { 2238 2322 Assert(e1kCsRxIsOwner(pThis)); … … 2242 2326 /* Cache is empty, reset it and check if we can fetch more. */ 2243 2327 pThis->iRxDCurrent = pThis->nRxDFetched = 0; 2244 if (e1kRxDPrefetch(pDevIns, pThis ))2328 if (e1kRxDPrefetch(pDevIns, pThis, pRxdc)) 2245 2329 return &pThis->aRxDescriptors[pThis->iRxDCurrent]; 2246 2330 /* Out of Rx descriptors. */ … … 2258 2342 * @thread RX 2259 2343 */ 2260 DECLINLINE(void) e1kRxDPut(PPDMDEVINS pDevIns, PE1KSTATE pThis, E1KRXDESC* pDesc )2344 DECLINLINE(void) e1kRxDPut(PPDMDEVINS pDevIns, PE1KSTATE pThis, E1KRXDESC* pDesc, PE1KRXDC pRxdc) 2261 2345 { 2262 2346 Assert(e1kCsRxIsOwner(pThis)); … … 2267 2351 // uint32_t rdh = RDH; 2268 2352 // 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)); 2270 2354 /* 2271 2355 * We need to print the descriptor before advancing RDH as it may fetch new … … 2273 2357 */ 2274 2358 e1kPrintRDesc(pThis, pDesc); 2275 e1kAdvanceRDH(pDevIns, pThis );2359 e1kAdvanceRDH(pDevIns, pThis, pRxdc); 2276 2360 } 2277 2361 … … 2448 2532 uint8_t rxPacket[E1K_MAX_RX_PKT_SIZE]; 2449 2533 uint8_t *ptr = rxPacket; 2534 # ifdef E1K_WITH_RXD_CACHE 2535 E1KRXDC rxdc; 2536 # endif /* E1K_WITH_RXD_CACHE */ 2450 2537 2451 2538 int rc = e1kCsRxEnter(pThis, VERR_SEM_BUSY); 2452 2539 if (RT_UNLIKELY(rc != VINF_SUCCESS)) 2453 2540 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 */ 2454 2549 2455 2550 if (cb > 70) /* unqualified guess */ … … 2533 2628 while (cb > 0) 2534 2629 { 2535 E1KRXDESC *pDesc = e1kRxDGet(pDevIns, pThis );2630 E1KRXDESC *pDesc = e1kRxDGet(pDevIns, pThis, &rxdc); 2536 2631 2537 2632 if (pDesc == NULL) … … 2539 2634 E1kLog(("%s Out of receive buffers, dropping the packet " 2540 2635 "(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)); 2542 2637 break; 2543 2638 } … … 2580 2675 if (RT_UNLIKELY(rc != VINF_SUCCESS)) 2581 2676 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 */ 2582 2685 ptr += u16RxBufferSize; 2583 2686 cb -= u16RxBufferSize; … … 2592 2695 if (RT_UNLIKELY(rc != VINF_SUCCESS)) 2593 2696 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 } 2594 2703 cb = 0; 2595 2704 # else /* !E1K_WITH_RXD_CACHE */ … … 2606 2715 /* Write back the descriptor. */ 2607 2716 pDesc->status.fDD = true; 2608 e1kRxDPut(pDevIns, pThis, pDesc );2717 e1kRxDPut(pDevIns, pThis, pDesc, &rxdc); 2609 2718 # else /* !E1K_WITH_RXD_CACHE */ 2610 2719 else … … 3317 3426 rc = e1kRegWriteDefault(pDevIns, pThis, offset, index, value); 3318 3427 #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 } 3319 3435 /* 3320 3436 * We need to fetch descriptors now as RDT may go whole circle … … 3337 3453 */ 3338 3454 if (e1kRxDIsCacheEmpty(pThis) && (RCTL & RCTL_EN)) 3339 e1kRxDPrefetch(pDevIns, pThis );3455 e1kRxDPrefetch(pDevIns, pThis, &rxdc); 3340 3456 #endif /* E1K_WITH_RXD_CACHE */ 3341 3457 e1kCsRxLeave(pThis); … … 3376 3492 } 3377 3493 3378 DECLINLINE(uint32_t) e1kGetTxLen(PE1K STATE pThis)3494 DECLINLINE(uint32_t) e1kGetTxLen(PE1KTXDC pTxdc) 3379 3495 { 3380 3496 /** … … 3382 3498 * any moment. 3383 3499 */ 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; 3386 3502 } 3387 3503 … … 3939 4055 * @thread E1000_TX 3940 4056 */ 3941 DECLINLINE(unsigned) e1kTxDLoadMore(PPDMDEVINS pDevIns, PE1KSTATE pThis )4057 DECLINLINE(unsigned) e1kTxDLoadMore(PPDMDEVINS pDevIns, PE1KSTATE pThis, PE1KTXDC pTxdc) 3942 4058 { 3943 4059 Assert(pThis->iTxDCurrent == 0); 3944 4060 /* We've already loaded pThis->nTxDFetched descriptors past TDH. */ 3945 unsigned nDescsAvailable = e1kGetTxLen(pT his) - pThis->nTxDFetched;4061 unsigned nDescsAvailable = e1kGetTxLen(pTxdc) - pThis->nTxDFetched; 3946 4062 /* The following two lines ensure that pThis->nTxDFetched never overflows. */ 3947 4063 AssertCompile(E1K_TXD_CACHE_SIZE < (256 * sizeof(pThis->nTxDFetched))); 3948 4064 unsigned nDescsToFetch = RT_MIN(nDescsAvailable, E1K_TXD_CACHE_SIZE - pThis->nTxDFetched); 3949 unsigned nDescsTotal = TDLEN/ sizeof(E1KTXDESC);4065 unsigned nDescsTotal = pTxdc->tdlen / sizeof(E1KTXDESC); 3950 4066 Assert(nDescsTotal != 0); 3951 4067 if (nDescsTotal == 0) 3952 4068 return 0; 3953 unsigned nFirstNotLoaded = ( TDH+ pThis->nTxDFetched) % nDescsTotal;4069 unsigned nFirstNotLoaded = (pTxdc->tdh + pThis->nTxDFetched) % nDescsTotal; 3954 4070 unsigned nDescsInSingleRead = RT_MIN(nDescsToFetch, nDescsTotal - nFirstNotLoaded); 3955 4071 E1kLog3(("%s e1kTxDLoadMore: nDescsAvailable=%u nDescsToFetch=%u nDescsTotal=%u nFirstNotLoaded=0x%x nDescsInSingleRead=%u\n", … … 3964 4080 E1kLog3(("%s Fetched %u TX descriptors at %08x%08x(0x%x), TDLEN=%08x, TDH=%08x, TDT=%08x\n", 3965 4081 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)); 3968 4084 if (nDescsToFetch > nDescsInSingleRead) 3969 4085 { … … 3989 4105 * @thread E1000_TX 3990 4106 */ 3991 DECLINLINE(bool) e1kTxDLazyLoad(PPDMDEVINS pDevIns, PE1KSTATE pThis )4107 DECLINLINE(bool) e1kTxDLazyLoad(PPDMDEVINS pDevIns, PE1KSTATE pThis, PE1KTXDC pTxdc) 3992 4108 { 3993 4109 if (pThis->nTxDFetched == 0) 3994 return e1kTxDLoadMore(pDevIns, pThis ) != 0;4110 return e1kTxDLoadMore(pDevIns, pThis, pTxdc) != 0; 3995 4111 return true; 3996 4112 } … … 5334 5450 } 5335 5451 5336 static int e1kXmitPacket(PPDMDEVINS pDevIns, PE1KSTATE pThis, bool fOnWorkerThread )5452 static int e1kXmitPacket(PPDMDEVINS pDevIns, PE1KSTATE pThis, bool fOnWorkerThread, PE1KTXDC pTxdc) 5337 5453 { 5338 5454 PE1KSTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PE1KSTATECC); … … 5346 5462 E1KTXDESC *pDesc = &pThis->aTxDescriptors[pThis->iTxDCurrent]; 5347 5463 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); 5350 5466 if (RT_FAILURE(rc)) 5351 5467 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 */ 5354 5471 uint32_t uLowThreshold = GET_BITS(TXDCTL, LWTHRESH)*8; 5355 if (uLowThreshold != 0 && e1kGetTxLen(pT his) <= uLowThreshold)5472 if (uLowThreshold != 0 && e1kGetTxLen(pTxdc) <= uLowThreshold) 5356 5473 { 5357 5474 E1kLog2(("%s Low on transmit descriptors, raise ICR.TXD_LOW, len=%x thresh=%x\n", 5358 pThis->szPrf, e1kGetTxLen(pT his), GET_BITS(TXDCTL, LWTHRESH)*8));5475 pThis->szPrf, e1kGetTxLen(pTxdc), GET_BITS(TXDCTL, LWTHRESH)*8)); 5359 5476 e1kRaiseInterrupt(pDevIns, pThis, VERR_SEM_BUSY, ICR_TXD_LOW); 5360 5477 } … … 5448 5565 #else /* E1K_WITH_TXD_CACHE */ 5449 5566 5450 static void e1kDumpTxDCache(PPDMDEVINS pDevIns, PE1KSTATE pThis )5451 { 5452 unsigned i, cDescs = TDLEN/ sizeof(E1KTXDESC);5453 uint32_t tdh = TDH;5567 static void e1kDumpTxDCache(PPDMDEVINS pDevIns, PE1KSTATE pThis, PE1KTXDC pTxdc) 5568 { 5569 unsigned i, cDescs = pTxdc->tdlen / sizeof(E1KTXDESC); 5570 uint32_t tdh = pTxdc->tdh; 5454 5571 LogRel(("E1000: -- Transmit Descriptors (%d total) --\n", cDescs)); 5455 5572 for (i = 0; i < cDescs; ++i) … … 5462 5579 } 5463 5580 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)); 5465 5582 if (tdh > pThis->iTxDCurrent) 5466 5583 tdh -= pThis->iTxDCurrent; … … 5511 5628 */ 5512 5629 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); 5515 5634 STAM_PROFILE_ADV_START(&pThis->CTX_SUFF_Z(StatTransmit), a); 5516 5635 /* … … 5521 5640 */ 5522 5641 bool fIncomplete = false; 5523 while ( !pThis->fLocked && e1kTxDLazyLoad(pDevIns, pThis))5642 while (fTxContextValid && !pThis->fLocked && e1kTxDLazyLoad(pDevIns, pThis, &txdc)) 5524 5643 { 5525 5644 while (e1kLocateTxPacket(pThis)) … … 5532 5651 goto out; 5533 5652 /* Copy the packet to allocated buffer and send it. */ 5534 rc = e1kXmitPacket(pDevIns, pThis, fOnWorkerThread );5653 rc = e1kXmitPacket(pDevIns, pThis, fOnWorkerThread, &txdc); 5535 5654 /* If we're out of bandwidth we'll come back later. */ 5536 5655 if (RT_FAILURE(rc)) … … 5551 5670 u8Remain == E1K_TXD_CACHE_SIZE ? " full" : "", 5552 5671 pThis->nTxDFetched, pThis->iTxDCurrent, 5553 e1kGetTxLen( pThis)));5672 e1kGetTxLen(&txdc))); 5554 5673 if (!fTxDCacheDumped) 5555 5674 { 5556 5675 fTxDCacheDumped = true; 5557 e1kDumpTxDCache(pDevIns, pThis );5676 e1kDumpTxDCache(pDevIns, pThis, &txdc); 5558 5677 } 5559 5678 pThis->iTxDCurrent = pThis->nTxDFetched = 0; … … 5574 5693 "%d more are available\n", 5575 5694 pThis->szPrf, pThis->iTxDCurrent, u8Remain, 5576 e1kGetTxLen( pThis) - u8Remain));5695 e1kGetTxLen(&txdc) - u8Remain)); 5577 5696 5578 5697 /* … … 5585 5704 pThis->iTxDCurrent = 0; 5586 5705 pThis->nTxDFetched = u8Remain; 5587 e1kTxDLoadMore(pDevIns, pThis );5706 e1kTxDLoadMore(pDevIns, pThis, &txdc); 5588 5707 fIncomplete = true; 5589 5708 } … … 5668 5787 pThis->szPrf, TDBAL, TDBAH, TDLEN, TDH, TDT)); 5669 5788 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; 5670 5795 /* 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))); 5674 5799 E1kLog(("%s e1kRegWriteTDT: %d descriptors to process\n", 5675 pThis->szPrf, e1kGetTxLen( pThis)));5800 pThis->szPrf, e1kGetTxLen(&txdc))); 5676 5801 5677 5802 /* Transmit pending packets if possible, defer it if we cannot do it … … 6259 6384 case 0x00: /* IOADDR */ 6260 6385 *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)); 6262 6387 rc = VINF_SUCCESS; 6263 6388 break; … … 6270 6395 if (rc == VINF_IOM_R3_MMIO_READ) 6271 6396 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)); 6273 6398 break; 6274 6399 … … 6301 6426 RT_NOREF_PV(pvUser); 6302 6427 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)); 6304 6429 if (RT_LIKELY(cb == 4)) 6305 6430 { … … 6308 6433 case 0x00: /* IOADDR */ 6309 6434 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)); 6311 6436 rc = VINF_SUCCESS; 6312 6437 break; 6313 6438 6314 6439 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)); 6316 6441 if (RT_LIKELY(!(pThis->uSelectedReg & 3))) 6317 6442 { … … 6443 6568 if (RT_UNLIKELY(e1kCsRxEnter(pThis, VERR_SEM_BUSY) != VINF_SUCCESS)) 6444 6569 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))) 6447 6579 { 6448 6580 E1KRXDESC desc; 6449 PDMDevHlpPCIPhysRead(pDevIns, e1kDescAddr(RDBAH, RDBAL, RDH), &desc, sizeof(desc));6581 PDMDevHlpPCIPhysRead(pDevIns, e1kDescAddr(RDBAH, RDBAL, rxdc.rdh), &desc, sizeof(desc)); 6450 6582 if (desc.status.fDD) 6451 6583 rc = VERR_NET_NO_BUFFER_SPACE; 6452 6584 } 6453 else if (e1kRxDIsCacheEmpty(pThis) && RDH == RDT)6585 else if (e1kRxDIsCacheEmpty(pThis) && rxdc.rdh == rxdc.rdt) 6454 6586 { 6455 6587 /* Cache is empty, so is the RX ring. */ … … 6458 6590 E1kLog2(("%s e1kCanReceive: at exit in_cache=%d RDH=%d RDT=%d RDLEN=%d" 6459 6591 " 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)); 6461 6593 6462 6594 e1kCsRxLeave(pThis);
Note:
See TracChangeset
for help on using the changeset viewer.