Changeset 27844 in vbox for trunk/src/VBox/Devices/Network/DevPCNet.cpp
- Timestamp:
- Mar 30, 2010 9:02:49 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DevPCNet.cpp
r27825 r27844 50 50 * THE SOFTWARE. 51 51 */ 52 #define VBOX_WITH_TX_THREAD_IN_NET_DEVICES 1 //debug, bird, remove 52 53 53 54 /******************************************************************************* … … 158 159 uint64_t u64LastPoll; 159 160 160 /** Size of current send frame */ 161 uint32_t cbSendFrame; 162 #if HC_ARCH_BITS == 64 163 uint32_t Alignment3; 164 #endif 165 /** Buffer address of current send frame */ 166 R3PTRTYPE(uint8_t *) pvSendFrame; 167 /** The xmit buffer. */ 168 uint8_t abSendBuf[4096]; 161 /** The loopback transmit buffer (avoid stack allocations). */ 162 uint8_t abLoopBuf[4096]; 169 163 /** The recv buffer. */ 170 164 uint8_t abRecvBuf[4096]; 171 165 172 /** Pending send packet counter. */173 uint32_t cPendingSends;166 /** Unused / padding. */ 167 uint32_t u32Unused; 174 168 175 169 /** Size of a RX/TX descriptor (8 or 16 bytes according to SWSTYLE */ … … 201 195 PTMTIMERR3 pTimerRestore; 202 196 /** Pointer to the connector of the attached network driver. */ 203 R3PTRTYPE(PPDMINETWORKUP) pDrv;197 R3PTRTYPE(PPDMINETWORKUP) pDrvR3; 204 198 /** Pointer to the attached network driver. */ 205 199 R3PTRTYPE(PPDMIBASE) pDrvBase; … … 233 227 R3PTRTYPE(PPDMILEDCONNECTORS) pLedsConnector; 234 228 229 #ifdef VBOX_WITH_TX_THREAD_IN_NET_DEVICES 235 230 /** Async send thread */ 236 231 RTSEMEVENT hSendEventSem; 237 232 /** The Async send thread. */ 238 233 PPDMTHREAD pSendThread; 234 #endif 239 235 240 236 /** Access critical section. */ … … 292 288 STAMPROFILEADV StatReceive; 293 289 STAMPROFILEADV StatTransmit; 294 STAMPROFILEADV StatTransmitSend; 290 STAMCOUNTER StatTransmitCase1; 291 STAMCOUNTER StatTransmitCase2; 292 STAMPROFILE StatTransmitSend; 295 293 STAMPROFILEADV StatTdtePollGC; 296 294 STAMPROFILEADV StatTdtePollHC; … … 617 615 DECLINLINE(bool) pcnetIsLinkUp(PCNetState *pThis) 618 616 { 619 return pThis->pDrv && !pThis->fLinkTempDown && pThis->fLinkUp;617 return pThis->pDrvR3 && !pThis->fLinkTempDown && pThis->fLinkUp; 620 618 } 621 619 … … 1598 1596 pThis->fSignalRxMiss = (cbRxBuffers == 0 || cbRxBuffers >= 32*_1K); 1599 1597 1600 if (pThis->pDrv )1601 pThis->pDrv ->pfnSetPromiscuousMode(pThis->pDrv, CSR_PROM(pThis));1598 if (pThis->pDrvR3) 1599 pThis->pDrvR3->pfnSetPromiscuousMode(pThis->pDrvR3, CSR_PROM(pThis)); 1602 1600 1603 1601 CSR_RCVRC(pThis) = CSR_RCVRL(pThis); … … 2063 2061 2064 2062 /* Clear counter .*/ 2065 ASMAtomicAndU32(&pThis->cPendingSends, 0); 2063 #ifndef VBOX_WITH_TX_THREAD_IN_NET_DEVICES 2064 int rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY); 2065 AssertReleaseRC(rc); 2066 2067 pcnetAsyncTransmit(pThis, false /*fOnWorkerThread*/); 2068 2069 PDMCritSectLeave(&pThis->CritSect); 2070 #else 2066 2071 int rc = RTSemEventSignal(pThis->hSendEventSem); 2067 2072 AssertRC(rc); 2073 #endif 2068 2074 return true; 2069 2075 } … … 2071 2077 2072 2078 /** 2073 * Scraps the top frame. 2074 * This is done as a precaution against mess left over by on 2075 */ 2076 DECLINLINE(void) pcnetXmitScrapFrame(PCNetState *pThis) 2077 { 2078 pThis->pvSendFrame = NULL; 2079 pThis->cbSendFrame = 0; 2080 } 2081 2082 2083 /** 2084 * Reads the first part of a frame 2085 */ 2086 DECLINLINE(void) pcnetXmitRead1st(PCNetState *pThis, RTGCPHYS32 GCPhysFrame, const unsigned cbFrame) 2079 * Allocates a scatter/gather buffer for a transfer. 2080 * 2081 * @returns See PPDMINETWORKUP::pfnAllocBuf. 2082 * @param pThis The device instance. 2083 * @param cbMin The minimum buffer size. 2084 * @param fLoopback Set if we're in loopback mode. 2085 * @param pSgLoop Pointer to stack storage for the loopback SG. 2086 * @param ppSgBuf Where to return the SG buffer descriptor on success. 2087 * Always set. 2088 */ 2089 DECLINLINE(int) pcnetXmitAllocBuf(PCNetState *pThis, size_t cbMin, bool fLoopback, 2090 PPDMSCATTERGATHER pSgLoop, PPPDMSCATTERGATHER ppSgBuf) 2091 { 2092 int rc; 2093 2094 if (RT_UNLIKELY(fLoopback)) /* hope that loopback mode is rare */ 2095 { 2096 pSgLoop->fFlags = PDMSCATTERGATHER_FLAGS_MAGIC | PDMSCATTERGATHER_FLAGS_OWNER_1; 2097 pSgLoop->cbUsed = 0; 2098 pSgLoop->cbAvailable = sizeof(pThis->abLoopBuf); 2099 pSgLoop->pvAllocator = pThis; 2100 pSgLoop->pvUser = NULL; 2101 pSgLoop->cSegs = 1; 2102 pSgLoop->aSegs[0].cbSeg = sizeof(pThis->abLoopBuf); 2103 pSgLoop->aSegs[0].pvSeg = pThis->abLoopBuf; 2104 *ppSgBuf = pSgLoop; 2105 rc = VINF_SUCCESS; 2106 } 2107 else 2108 { 2109 PPDMINETWORKUP pDrv = pThis->pDrvR3; 2110 if (RT_LIKELY(pDrv)) 2111 { 2112 rc = pDrv->pfnAllocBuf(pDrv, cbMin, ppSgBuf); 2113 AssertMsg(rc == VINF_SUCCESS || rc == VERR_TRY_AGAIN || rc == VERR_NET_DOWN || rc == VERR_NO_MEMORY, ("%Rrc\n", rc)); 2114 if (RT_FAILURE(rc)) 2115 *ppSgBuf = NULL; 2116 } 2117 else 2118 { 2119 rc = VERR_NET_DOWN; 2120 *ppSgBuf = NULL; 2121 } 2122 } 2123 return rc; 2124 } 2125 2126 2127 /** 2128 * Frees an unsent buffer. 2129 * 2130 * @param pThis The device instance. 2131 * @param fLoopback Set if we're in loopback mode. 2132 * @param pSgBuf The SG to free. Can be NULL. 2133 */ 2134 DECLINLINE(void) pcnetXmitFreeBuf(PCNetState *pThis, bool fLoopback, PPDMSCATTERGATHER pSgBuf) 2135 { 2136 if (pSgBuf) 2137 { 2138 if (RT_UNLIKELY(fLoopback)) 2139 pSgBuf->pvAllocator = NULL; 2140 else 2141 { 2142 PPDMINETWORKUP pDrv = pThis->pDrvR3; 2143 if (RT_LIKELY(pDrv)) 2144 pDrv->pfnFreeBuf(pDrv, pSgBuf); 2145 } 2146 } 2147 } 2148 2149 2150 /** 2151 * Sends the scatter/gather buffer. 2152 * 2153 * Wrapper around PDMINETWORKUP::pfnSendBuf, so check it out for the fine print. 2154 * 2155 * @returns See PDMINETWORKUP::pfnSendBuf. 2156 * @param pThis The device instance. 2157 * @param fLoopback Set if we're in loopback mode. 2158 * @param pSgBuf The SG to send. 2159 * @param fOnWorkerThread Set if we're being called on a work thread. Clear 2160 * if an EMT. 2161 */ 2162 DECLINLINE(int) pcnetXmitSendBuf(PCNetState *pThis, bool fLoopback, PPDMSCATTERGATHER pSgBuf, bool fOnWorkerThread) 2163 { 2164 int rc; 2165 STAM_REL_COUNTER_ADD(&pThis->StatTransmitBytes, pSgBuf->cbUsed); 2166 if (RT_UNLIKELY(fLoopback)) /* hope that loopback mode is rare */ 2167 { 2168 Assert(pSgBuf->pvAllocator == (void *)pThis); 2169 pThis->Led.Asserted.s.fReading = pThis->Led.Actual.s.fReading = 1; 2170 if (HOST_IS_OWNER(CSR_CRST(pThis))) 2171 pcnetRdtePoll(pThis); 2172 2173 pcnetReceiveNoSync(pThis, pThis->abLoopBuf, pSgBuf->cbUsed); 2174 pThis->Led.Actual.s.fReading = 0; 2175 rc = VINF_SUCCESS; 2176 } 2177 else 2178 { 2179 /** @todo We used to leave the critsect here, not sure if that's necessary any 2180 * longer. If we could avoid that we could cache a bit more info in 2181 * the loop and make it part of the driver<->device contract, saving 2182 * critsect mess down in DrvIntNet. */ 2183 STAM_PROFILE_START(&pThis->StatTransmitSend, a); 2184 if (pSgBuf->cbUsed > 70) /* unqualified guess */ 2185 pThis->Led.Asserted.s.fWriting = pThis->Led.Actual.s.fWriting = 1; 2186 2187 PPDMINETWORKUP pDrv = pThis->pDrvR3; 2188 if (RT_LIKELY(pDrv)) 2189 { 2190 rc = pDrv->pfnSendBuf(pDrv, pSgBuf, fOnWorkerThread); 2191 AssertMsg(rc == VINF_SUCCESS || rc == VERR_NET_DOWN || rc == VERR_NET_NO_BUFFER_SPACE, ("%Rrc\n", rc)); 2192 } 2193 else 2194 rc = VERR_NET_DOWN; 2195 2196 pThis->Led.Actual.s.fWriting = 0; 2197 STAM_PROFILE_STOP(&pThis->StatTransmitSend, a); 2198 } 2199 return rc; 2200 } 2201 2202 2203 /** 2204 * pcnetXmitRead1st worker that handles the unlikely + slower segmented code 2205 * path. 2206 */ 2207 static void pcnetXmitRead1stSlow(PCNetState *pThis, RTGCPHYS32 GCPhysFrame, unsigned cbFrame, 2208 PPDMSCATTERGATHER pSgBuf) 2209 { 2210 AssertFailed(); /* This path is not suppost to be taken atm */ 2211 2212 pSgBuf->cbUsed = cbFrame; 2213 for (uint32_t iSeg = 0; ; iSeg++) 2214 { 2215 Assert(iSeg < pSgBuf->cSegs); 2216 size_t cbRead = RT_MIN(cbFrame, pSgBuf->aSegs[iSeg].cbSeg); 2217 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhysFrame, pSgBuf->aSegs[iSeg].pvSeg, cbRead); 2218 cbFrame -= cbRead; 2219 if (!cbFrame) 2220 return; 2221 GCPhysFrame += cbRead; 2222 } 2223 } 2224 2225 2226 /** 2227 * pcnetXmitSgReadMore worker that handles the unlikely + slower segmented code 2228 * path. 2229 */ 2230 static void pcnetXmitReadMoreSlow(PCNetState *pThis, RTGCPHYS32 GCPhysFrame, unsigned cbFrame, 2231 PPDMSCATTERGATHER pSgBuf) 2232 { 2233 AssertFailed(); /* This path is not suppost to be taken atm */ 2234 2235 /* Find the segment which we'll put the next byte into. */ 2236 size_t off = pSgBuf->cbUsed; 2237 size_t offSeg = 0; 2238 uint32_t iSeg = 0; 2239 while (offSeg + pSgBuf->aSegs[iSeg].cbSeg <= off) 2240 { 2241 offSeg += pSgBuf->aSegs[iSeg].cbSeg; 2242 iSeg++; 2243 Assert(iSeg < pSgBuf->cSegs); 2244 } 2245 2246 /* Commit before we start copying so we can decrement cbFrame. */ 2247 pSgBuf->cbUsed = off + cbFrame; 2248 2249 /* Deal with the first segment if we at an offset into it. */ 2250 if (off != offSeg) 2251 { 2252 size_t offIntoSeg = off - offSeg; 2253 size_t cbRead = RT_MIN(pSgBuf->aSegs[iSeg].cbSeg - offIntoSeg, cbFrame); 2254 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhysFrame, 2255 (uint8_t *)pSgBuf->aSegs[iSeg].pvSeg + offIntoSeg, cbRead); 2256 cbFrame -= cbRead; 2257 if (!cbFrame) 2258 return; 2259 GCPhysFrame += cbRead; 2260 iSeg++; 2261 } 2262 2263 /* For the remainder, we've got whole segments. */ 2264 for (;; iSeg++) 2265 { 2266 Assert(iSeg < pSgBuf->cSegs); 2267 2268 size_t cbRead = RT_MIN(pSgBuf->aSegs[iSeg].cbSeg, cbFrame); 2269 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhysFrame, pSgBuf->aSegs[iSeg].pvSeg, cbRead); 2270 cbFrame -= cbRead; 2271 if (!cbFrame) 2272 return; 2273 GCPhysFrame += cbFrame; 2274 } 2275 } 2276 2277 2278 /** 2279 * Reads the first part of a frame into the scatter gather buffer. 2280 */ 2281 DECLINLINE(void) pcnetXmitRead1st(PCNetState *pThis, RTGCPHYS32 GCPhysFrame, const unsigned cbFrame, 2282 PPDMSCATTERGATHER pSgBuf) 2087 2283 { 2088 2284 Assert(PDMCritSectIsOwner(&pThis->CritSect)); 2089 Assert(cbFrame < sizeof(pThis->abSendBuf)); 2090 2091 pThis->pvSendFrame = pThis->abSendBuf; 2092 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhysFrame, pThis->pvSendFrame, cbFrame); 2093 pThis->cbSendFrame = cbFrame; 2094 } 2095 2285 Assert(pSgBuf->cbAvailable >= cbFrame); 2286 2287 if (RT_LIKELY(pSgBuf->aSegs[0].cbSeg >= cbFrame)) /* justification: all drivers returns a single segment atm. */ 2288 { 2289 pSgBuf->cbUsed = cbFrame; 2290 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhysFrame, pSgBuf->aSegs[0].pvSeg, cbFrame); 2291 } 2292 else 2293 pcnetXmitRead1stSlow(pThis, GCPhysFrame, cbFrame, pSgBuf); 2294 } 2096 2295 2097 2296 /** 2098 2297 * Reads more into the current frame. 2099 2298 */ 2100 DECLINLINE(void) pcnetXmitReadMore(PCNetState *pThis, RTGCPHYS32 GCPhysFrame, const unsigned cbFrame) 2101 { 2102 Assert(pThis->cbSendFrame + cbFrame <= MAX_FRAME); 2103 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhysFrame, pThis->pvSendFrame + pThis->cbSendFrame, cbFrame); 2104 pThis->cbSendFrame += cbFrame; 2105 } 2106 2107 2108 /** 2109 * Completes the current frame. 2110 * If we've reached the maxium number of frames, they will be flushed. 2111 */ 2112 DECLINLINE(int) pcnetXmitCompleteFrame(PCNetState *pThis) 2113 { 2114 /* Don't hold the critical section while transmitting data. */ 2115 /** @note also avoids deadlocks with NAT as it can call us right back. */ 2116 PDMCritSectLeave(&pThis->CritSect); 2117 2118 STAM_PROFILE_ADV_START(&pThis->StatTransmitSend, a); 2119 if (pThis->cbSendFrame > 70) /* unqualified guess */ 2120 pThis->Led.Asserted.s.fWriting = pThis->Led.Actual.s.fWriting = 1; 2121 2122 pThis->pDrv->pfnSendDeprecated(pThis->pDrv, pThis->pvSendFrame, pThis->cbSendFrame); 2123 STAM_REL_COUNTER_ADD(&pThis->StatTransmitBytes, pThis->cbSendFrame); 2124 pThis->Led.Actual.s.fWriting = 0; 2125 STAM_PROFILE_ADV_STOP(&pThis->StatTransmitSend, a); 2126 2127 return PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY); 2299 DECLINLINE(void) pcnetXmitReadMore(PCNetState *pThis, RTGCPHYS32 GCPhysFrame, const unsigned cbFrame, 2300 PPDMSCATTERGATHER pSgBuf) 2301 { 2302 size_t off = pSgBuf->cbUsed; 2303 Assert(pSgBuf->cbAvailable >= cbFrame + off); 2304 2305 if (RT_LIKELY(pSgBuf->aSegs[0].cbSeg >= cbFrame + off)) 2306 { 2307 pSgBuf->cbUsed = cbFrame + off; 2308 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhysFrame, 2309 (uint8_t *)pSgBuf->aSegs[0].pvSeg + off, cbFrame); 2310 } 2311 else 2312 pcnetXmitReadMoreSlow(pThis, GCPhysFrame, cbFrame, pSgBuf); 2128 2313 } 2129 2314 … … 2158 2343 2159 2344 /** 2160 * Transmit a loopback frame.2161 */2162 DECLINLINE(void) pcnetXmitLoopbackFrame(PCNetState *pThis)2163 {2164 pThis->Led.Asserted.s.fReading = pThis->Led.Actual.s.fReading = 1;2165 if (HOST_IS_OWNER(CSR_CRST(pThis)))2166 pcnetRdtePoll(pThis);2167 2168 Assert(pThis->pvSendFrame);2169 pcnetReceiveNoSync(pThis, (const uint8_t *)pThis->pvSendFrame, pThis->cbSendFrame);2170 pcnetXmitScrapFrame(pThis);2171 pThis->Led.Actual.s.fReading = 0;2172 }2173 2174 /**2175 2345 * Flushes queued frames. 2176 2346 */ … … 2213 2383 pcnetXmitFlushFrames(pThis); 2214 2384 #else 2215 # if 12216 2385 PPDMQUEUEITEMCORE pItem = PDMQueueAlloc(pThis->CTX_SUFF(pXmitQueue)); 2217 2386 if (RT_UNLIKELY(pItem)) 2218 2387 PDMQueueInsert(pThis->CTX_SUFF(pXmitQueue), pItem); 2219 # else2220 if (ASMAtomicIncU32(&pThis->cPendingSends) < 16)2221 {2222 PPDMQUEUEITEMCORE pItem = PDMQueueAlloc(pThis->CTX_SUFF(pXmitQueue));2223 if (RT_UNLIKELY(pItem))2224 PDMQueueInsert(pThis->CTX_SUFF(pXmitQueue), pItem);2225 }2226 else2227 PDMQueueFlush(pThis->CTX_SUFF(pXmitQueue));2228 # endif2229 2388 #endif 2230 2389 } … … 2233 2392 2234 2393 /** 2235 * Try to transmit frames2236 * /2237 static int pcnetAsyncTransmit(PCNetState *pThis) 2238 { 2239 unsigned cFlushIrq = 0; 2240 2394 * Actually try transmit frames. 2395 * 2396 * @threads TX or EMT. 2397 */ 2398 static int pcnetAsyncTransmit(PCNetState *pThis, bool fOnWorkerThread) 2399 { 2241 2400 Assert(PDMCritSectIsOwner(&pThis->CritSect)); 2242 2401 2402 /* 2403 * Just cleard transmit demand if the transmitter is off. 2404 */ 2243 2405 if (RT_UNLIKELY(!CSR_TXON(pThis))) 2244 2406 { … … 2250 2412 * Iterate the transmit descriptors. 2251 2413 */ 2414 int rc; 2415 unsigned cFlushIrq = 0; 2252 2416 STAM_PROFILE_ADV_START(&pThis->StatTransmit, a); 2253 2417 do … … 2270 2434 PRINT_TMD(&tmd); 2271 2435 #endif 2272 pcnetXmitScrapFrame(pThis); 2436 bool const fLoopback = CSR_LOOP(pThis); 2437 PDMSCATTERGATHER SgLoop; 2438 PPDMSCATTERGATHER pSgBuf; 2273 2439 2274 2440 /* … … 2278 2444 { 2279 2445 const unsigned cb = 4096 - tmd.tmd1.bcnt; 2280 Log(("#%d pcnetTransmit: stp&enp: cb=%d xmtrc=%#x\n", PCNET_INST_NR, cb, CSR_XMTRC(pThis))); 2281 2282 if (RT_LIKELY(pcnetIsLinkUp(pThis) || CSR_LOOP(pThis))) 2446 Log(("#%d pcnetAsyncTransmit: stp&enp: cb=%d xmtrc=%#x\n", PCNET_INST_NR, cb, CSR_XMTRC(pThis))); 2447 STAM_COUNTER_INC(&pThis->StatTransmitCase1); 2448 2449 if (RT_LIKELY(pcnetIsLinkUp(pThis) || fLoopback)) 2283 2450 { 2284 2451 /* From the manual: ``A zero length buffer is acceptable as … … 2288 2455 if (RT_LIKELY(cb <= MAX_FRAME)) 2289 2456 { 2290 pcnetXmitRead1st(pThis, PHYSADDR(pThis, tmd.tmd0.tbadr), cb); 2291 if (CSR_LOOP(pThis)) 2292 pcnetXmitLoopbackFrame(pThis); 2293 else 2457 rc = pcnetXmitAllocBuf(pThis, cb, fLoopback, &SgLoop, &pSgBuf); 2458 if (RT_SUCCESS(rc)) 2294 2459 { 2295 int rc = pcnetXmitCompleteFrame(pThis);2296 AssertRCReturn(rc, rc);2460 pcnetXmitRead1st(pThis, PHYSADDR(pThis, tmd.tmd0.tbadr), cb, pSgBuf); 2461 rc = pcnetXmitSendBuf(pThis, fLoopback, pSgBuf, fOnWorkerThread); 2297 2462 } 2463 else if (rc == VERR_TRY_AGAIN) 2464 { 2465 STAM_PROFILE_ADV_STOP(&pThis->StatTransmit, a); 2466 return VINF_SUCCESS; 2467 } 2468 if (RT_FAILURE(rc)) 2469 pcnetXmitFailTMDLinkDown(pThis, &tmd); 2298 2470 } 2299 2471 else if (cb == 4096) … … 2337 2509 else if (tmd.tmd1.stp) 2338 2510 { 2511 STAM_COUNTER_INC(&pThis->StatTransmitCase2); 2512 2339 2513 /* 2340 2514 * Read TMDs until end-of-packet or tdte poll fails (underflow). 2515 * 2516 * We allocate a maximum sized buffer here since we do not wish to 2517 * waste time finding out how much space we actually need even if 2518 * we could reliably do that on SMP guests. 2341 2519 */ 2342 bool fDropFrame = false;2343 2520 unsigned cb = 4096 - tmd.tmd1.bcnt; 2344 pcnetXmitRead1st(pThis, PHYSADDR(pThis, tmd.tmd0.tbadr), cb); 2521 rc = pcnetXmitAllocBuf(pThis, RT_MAX(MAX_FRAME, cb), fLoopback, &SgLoop, &pSgBuf); 2522 if (rc == VERR_TRY_AGAIN) 2523 { 2524 STAM_PROFILE_ADV_STOP(&pThis->StatTransmit, a); 2525 return VINF_SUCCESS; 2526 } 2527 2528 bool fDropFrame = RT_FAILURE(rc); 2529 if (!fDropFrame) 2530 pcnetXmitRead1st(pThis, PHYSADDR(pThis, tmd.tmd0.tbadr), cb, pSgBuf); 2531 2345 2532 for (;;) 2346 2533 { … … 2349 2536 */ 2350 2537 #ifdef LOG_ENABLED 2351 const uint32_t iStart = CSR_XMTRC(pThis);2538 const uint32_t iStart = CSR_XMTRC(pThis); 2352 2539 #endif 2353 2540 const uint32_t GCPhysPrevTmd = PHYSADDR(pThis, CSR_CXDA(pThis)); … … 2368 2555 pThis->aCSR[0] &= ~0x0010; /* clear TXON */ 2369 2556 pcnetTmdStorePassHost(pThis, &tmd, GCPhysPrevTmd); 2370 AssertMsgFailed(("pcnetTransmit: Underflow!!!\n")); 2557 AssertMsgFailed(("pcnetAsyncTransmit: Underflow!!!\n")); 2558 pcnetXmitFreeBuf(pThis, fLoopback, pSgBuf); 2371 2559 break; 2372 2560 } … … 2376 2564 2377 2565 /* 2378 * The next t dm.2566 * The next tmd. 2379 2567 */ 2380 2568 #ifdef VBOX_WITH_STATISTICS … … 2383 2571 pcnetTmdLoad(pThis, &tmd, PHYSADDR(pThis, CSR_CXDA(pThis)), false); 2384 2572 cb = 4096 - tmd.tmd1.bcnt; 2385 if ( pThis->cbSendFrame + cb < MAX_FRAME2386 && !fDropFrame)2387 pcnetXmitReadMore(pThis, PHYSADDR(pThis, tmd.tmd0.tbadr), cb );2573 if ( !fDropFrame 2574 && pSgBuf->cbUsed + cb <= MAX_FRAME) /** @todo this used to be ... + cb < MAX_FRAME. */ 2575 pcnetXmitReadMore(pThis, PHYSADDR(pThis, tmd.tmd0.tbadr), cb, pSgBuf); 2388 2576 else 2389 2577 { 2390 AssertMsg(fDropFrame, ("pcnetTransmit: Frame is too big!!! %d bytes\n", 2391 pThis->cbSendFrame + cb)); 2578 AssertMsg(fDropFrame, ("pcnetAsyncTransmit: Frame is too big!!! %d bytes\n", pSgBuf->cbUsed + cb)); 2392 2579 fDropFrame = true; 2393 2580 } 2581 2582 /* 2583 * Done already? 2584 */ 2394 2585 if (tmd.tmd1.enp) 2395 2586 { 2396 Log(("#%d pcnet Transmit: stp: cb=%d xmtrc=%#x-%#x\n", PCNET_INST_NR,2397 pThis->cbSendFrame, iStart, CSR_XMTRC(pThis)));2398 if ( pcnetIsLinkUp(pThis) && !fDropFrame)2587 Log(("#%d pcnetAsyncTransmit: stp: cb=%d xmtrc=%#x-%#x\n", PCNET_INST_NR, 2588 pSgBuf ? pSgBuf->cbUsed : 0, iStart, CSR_XMTRC(pThis))); 2589 if (!fDropFrame && (pcnetIsLinkUp(pThis) || fLoopback)) 2399 2590 { 2400 int rc = pcnetXmitCompleteFrame(pThis);2401 AssertRCReturn(rc,rc);2591 rc = pcnetXmitSendBuf(pThis, fLoopback, pSgBuf, fOnWorkerThread); 2592 fDropFrame = RT_FAILURE(rc); 2402 2593 } 2403 else if (CSR_LOOP(pThis) && !fDropFrame)2404 pcnetXmitLoopbackFrame(pThis);2405 2594 else 2406 { 2407 if (!fDropFrame) 2408 pcnetXmitFailTMDLinkDown(pThis, &tmd); 2409 pcnetXmitScrapFrame(pThis); 2410 } 2595 pcnetXmitFreeBuf(pThis, fLoopback, pSgBuf); 2596 if (fDropFrame) 2597 pcnetXmitFailTMDLinkDown(pThis, &tmd); 2411 2598 2412 2599 /* Write back the TMD, pass it to the host */ … … 2420 2607 break; 2421 2608 } 2422 } 2609 } /* the loop */ 2423 2610 } 2424 2611 else … … 2429 2616 */ 2430 2617 /** @todo according to the specs we're supposed to clear the own bit and move on to the next one. */ 2431 Log(("#%d pcnet Transmit: guest is giving us shit!\n", PCNET_INST_NR));2618 Log(("#%d pcnetAsyncTransmit: guest is giving us shit!\n", PCNET_INST_NR)); 2432 2619 break; 2433 2620 } … … 2461 2648 } 2462 2649 2650 #ifdef VBOX_WITH_TX_THREAD_IN_NET_DEVICES 2463 2651 2464 2652 /** … … 2510 2698 if (pThread->enmState == PDMTHREADSTATE_RUNNING) 2511 2699 { 2512 rc = pcnetAsyncTransmit(pThis );2700 rc = pcnetAsyncTransmit(pThis, true /*fOnWorkerThread*/); 2513 2701 AssertReleaseRC(rc); 2514 2702 } … … 2535 2723 } 2536 2724 2725 # endif /* VBOX_WITH_TX_THREAD_IN_NET_DEVICES*/ 2537 2726 #endif /* IN_RING3 */ 2538 2727 … … 2745 2934 } 2746 2935 case 15: /* Mode */ 2747 if ((pThis->aCSR[15] & 0x8000) != (uint16_t)(val & 0x8000) && pThis->pDrv )2936 if ((pThis->aCSR[15] & 0x8000) != (uint16_t)(val & 0x8000) && pThis->pDrvR3) 2748 2937 { 2749 2938 Log(("#%d: promiscuous mode changed to %d\n", PCNET_INST_NR, !!(val & 0x8000))); … … 2752 2941 #else 2753 2942 /* check for promiscuous mode change */ 2754 if (pThis->pDrv )2755 pThis->pDrv ->pfnSetPromiscuousMode(pThis->pDrv, !!(val & 0x8000));2943 if (pThis->pDrvR3) 2944 pThis->pDrvR3->pfnSetPromiscuousMode(pThis->pDrvR3, !!(val & 0x8000)); 2756 2945 #endif 2757 2946 } … … 3078 3267 val = pThis->aBCR[u32RAP] & ~0x8000; 3079 3268 /* Clear LNKSTE if we're not connected or if we've just loaded a VM state. */ 3080 if (!pThis->pDrv || pThis->fLinkTempDown || !pThis->fLinkUp)3269 if (!pThis->pDrvR3 || pThis->fLinkTempDown || !pThis->fLinkUp) 3081 3270 { 3082 3271 if (u32RAP == 4) … … 4382 4571 4383 4572 /* update promiscuous mode. */ 4384 if (pThis->pDrv )4385 pThis->pDrv ->pfnSetPromiscuousMode(pThis->pDrv, CSR_PROM(pThis));4573 if (pThis->pDrvR3) 4574 pThis->pDrvR3->pfnSetPromiscuousMode(pThis->pDrvR3, CSR_PROM(pThis)); 4386 4575 4387 4576 #ifdef PCNET_NO_POLLING … … 4632 4821 } 4633 4822 Assert(!PDMCritSectIsOwner(&pThis->CritSect)); 4634 if (pThis->pDrv )4635 pThis->pDrv ->pfnNotifyLinkChanged(pThis->pDrv, enmState);4823 if (pThis->pDrvR3) 4824 pThis->pDrvR3->pfnNotifyLinkChanged(pThis->pDrvR3, enmState); 4636 4825 } 4637 4826 return VINF_SUCCESS; … … 4696 4885 */ 4697 4886 pThis->pDrvBase = NULL; 4698 pThis->pDrv = NULL;4887 pThis->pDrvR3 = NULL; 4699 4888 4700 4889 PDMCritSectLeave(&pThis->CritSect); … … 4739 4928 #endif 4740 4929 } 4741 pThis->pDrv = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMINETWORKUP);4742 AssertMsgStmt(pThis->pDrv , ("Failed to obtain the PDMINETWORKUP interface!\n"),4930 pThis->pDrvR3 = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMINETWORKUP); 4931 AssertMsgStmt(pThis->pDrvR3, ("Failed to obtain the PDMINETWORKUP interface!\n"), 4743 4932 rc = VERR_PDM_MISSING_INTERFACE_BELOW); 4744 4933 } … … 4861 5050 Assert(RT_ELEMENTS(pThis->aBCR) == BCR_MAX_RAP); 4862 5051 Assert(RT_ELEMENTS(pThis->aMII) == MII_MAX_REG); 4863 Assert(sizeof(pThis->ab SendBuf) == RT_ALIGN_Z(sizeof(pThis->abSendBuf), 16));5052 Assert(sizeof(pThis->abLoopBuf) == RT_ALIGN_Z(sizeof(pThis->abLoopBuf), 16)); 4864 5053 4865 5054 /* … … 5116 5305 #endif 5117 5306 } 5118 pThis->pDrv = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMINETWORKUP);5119 AssertMsgReturn(pThis->pDrv , ("Failed to obtain the PDMINETWORKUP interface!\n"),5307 pThis->pDrvR3 = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMINETWORKUP); 5308 AssertMsgReturn(pThis->pDrvR3, ("Failed to obtain the PDMINETWORKUP interface!\n"), 5120 5309 VERR_PDM_MISSING_INTERFACE_BELOW); 5121 5310 } … … 5130 5319 pcnetHardReset(pThis); 5131 5320 5321 #ifdef VBOX_WITH_TX_THREAD_IN_NET_DEVICES 5132 5322 /* Create send queue for the async send thread. */ 5133 5323 rc = RTSemEventCreate(&pThis->hSendEventSem); … … 5137 5327 rc = PDMDevHlpThreadCreate(pDevIns, &pThis->pSendThread, pThis, pcnetAsyncSendThread, pcnetAsyncSendThreadWakeUp, 0, RTTHREADTYPE_IO, "PCNET_TX"); 5138 5328 AssertRCReturn(rc, rc); 5329 #endif 5139 5330 5140 5331 #ifdef VBOX_WITH_STATISTICS … … 5156 5347 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatReceiveBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Amount of data received", "/Devices/PCNet%d/ReceiveBytes", iInstance); 5157 5348 #ifdef VBOX_WITH_STATISTICS 5349 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatTransmitCase1, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Single descriptor transmit", "/Devices/PCNet%d/Transmit/Case1", iInstance); 5350 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatTransmitCase2, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Multi descriptor transmit", "/Devices/PCNet%d/Transmit/Case2", iInstance); 5158 5351 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatTransmit, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling transmits in HC", "/Devices/PCNet%d/Transmit/Total", iInstance); 5159 5352 #endif
Note:
See TracChangeset
for help on using the changeset viewer.