Changeset 85113 in vbox for trunk/src/VBox/Devices/Network/DevPCNet.cpp
- Timestamp:
- Jul 8, 2020 4:33:03 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DevPCNet.cpp
r82968 r85113 621 621 uint32_t trc:4; /**< transmit retry count */ 622 622 uint32_t res:12; /**< reserved */ 623 uint32_t tdr:10; /**< ???*/623 uint32_t tdr:10; /**< time domain reflectometry */ 624 624 uint32_t rtry:1; /**< retry error */ 625 625 uint32_t lcar:1; /**< loss of carrier */ … … 762 762 763 763 /** 764 * Load transmit message descriptor 765 * Make sure we read the own flag first. 764 * Load transmit message descriptor (TMD) if we own it. 765 * Makes sure we read the OWN bit first, which requires issuing two reads if 766 * the OWN bit is laid out in the second (D)WORD in memory. 766 767 * 767 768 * @param pDevIns The device instance. 768 769 * @param pThis adapter private data 769 770 * @param addr physical address of the descriptor 770 * @param fRetIfNotOwn return immediately after reading the own flag if we don't own the descriptor771 771 * @return true if we own the descriptor, false otherwise 772 772 */ 773 DECLINLINE(bool) pcnetTmdLoad(PPDMDEVINS pDevIns, PPCNETSTATE pThis, TMD *tmd, RTGCPHYS32 addr, bool fRetIfNotOwn) 774 { 775 uint8_t ownbyte; 776 773 DECLINLINE(bool) pcnetTmdTryLoad(PPDMDEVINS pDevIns, PPCNETSTATE pThis, TMD *tmd, RTGCPHYS32 addr) 774 { 775 /* Convert the in-memory format to the internal layout which corresponds to SWSTYLE=2. 776 * Do not touch tmd if the OWN bit is not set (i.e. we don't own the descriptor). 777 */ 777 778 if (RT_UNLIKELY(BCR_SWSTYLE(pThis) == 0)) 778 779 { 780 uint16_t xda[4]; /* Corresponds to memory layout, last word unused. */ 781 782 /* For SWSTYLE=0, the OWN bit is in the second WORD we need and must be read before the first WORD. */ 783 PDMDevHlpPhysRead(pDevIns, addr + sizeof(uint16_t), (void*)&xda[1], 2 * sizeof(uint16_t)); 784 if (!(xda[1] & RT_BIT(15))) 785 return false; 786 PDMDevHlpPhysRead(pDevIns, addr, (void*)&xda[0], sizeof(uint16_t)); 787 ((uint32_t *)tmd)[0] = (uint32_t)xda[0] | ((uint32_t)(xda[1] & 0x00ff) << 16); /* TMD0, buffer address. */ 788 ((uint32_t *)tmd)[1] = (uint32_t)xda[2] | ((uint32_t)(xda[1] & 0xff00) << 16); /* TMD1, buffer size and control bits. */ 789 ((uint32_t *)tmd)[2] = 0; /* TMD2, status bits, set on error but not read. */ 790 ((uint32_t *)tmd)[3] = 0; /* TMD3, user data, never accessed. */ 791 } 792 else if (RT_LIKELY(BCR_SWSTYLE(pThis) != 3)) 793 { 794 /* For SWSTYLE=2, the OWN bit is in the second DWORD we need and must be read first. */ 795 uint32_t xda[2]; 796 PDMDevHlpPhysRead(pDevIns, addr + sizeof(uint32_t), (void*)&xda[1], sizeof(uint32_t)); 797 if (!(xda[1] & RT_BIT(31))) 798 return false; 799 PDMDevHlpPhysRead(pDevIns, addr, (void*)&xda[0], sizeof(uint32_t)); 800 ((uint32_t *)tmd)[0] = xda[0]; /* TMD0, buffer address. */ 801 ((uint32_t *)tmd)[1] = xda[1]; /* TMD1, buffer size and control bits. */ 802 ((uint32_t *)tmd)[2] = 0; /* TMD2, status bits, set on error but not read. */ 803 ((uint32_t *)tmd)[3] = 0; /* TMD3, user data, never accessed. */ 804 } 805 else 806 { 807 /* For SWSTYLE=3, the OWN bit is in the first DWORD we need, therefore a single read suffices. */ 808 uint32_t xda[2]; 809 PDMDevHlpPhysRead(pDevIns, addr + sizeof(uint32_t), (void*)&xda, sizeof(xda)); 810 if (!(xda[0] & RT_BIT(31))) 811 return false; 812 ((uint32_t *)tmd)[0] = xda[1]; /* TMD0, buffer address. */ 813 ((uint32_t *)tmd)[1] = xda[0]; /* TMD1, buffer size and control bits. */ 814 ((uint32_t *)tmd)[2] = 0; /* TMD2, status bits, set on error but not read. */ 815 ((uint32_t *)tmd)[3] = 0; /* TMD3, user data, never accessed. */ 816 } 817 818 return !!tmd->tmd1.own; 819 } 820 821 /** 822 * Loads an entire transmit message descriptor. Used for logging/debugging. 823 * 824 * @param pDevIns The device instance. 825 * @param pThis Adapter private data 826 * @param addr Physical address of the descriptor 827 */ 828 DECLINLINE(void) pcnetTmdLoadAll(PPDMDEVINS pDevIns, PPCNETSTATE pThis, TMD *tmd, RTGCPHYS32 addr) 829 { 830 /* Convert the in-memory format to the internal layout which corresponds to SWSTYLE=2. */ 831 if (RT_UNLIKELY(BCR_SWSTYLE(pThis) == 0)) 832 { 779 833 uint16_t xda[4]; 780 834 781 PDMDevHlpPhysRead(pDevIns, addr+3, &ownbyte, 1); 782 if (!(ownbyte & 0x80) && fRetIfNotOwn) 783 return false; 784 PDMDevHlpPhysRead(pDevIns, addr, (void*)&xda[0], sizeof(xda)); 785 ((uint32_t *)tmd)[0] = (uint32_t)xda[0] | ((uint32_t)(xda[1] & 0x00ff) << 16); 786 ((uint32_t *)tmd)[1] = (uint32_t)xda[2] | ((uint32_t)(xda[1] & 0xff00) << 16); 787 ((uint32_t *)tmd)[2] = (uint32_t)xda[3] << 16; 788 ((uint32_t *)tmd)[3] = 0; 835 /* For SWSTYLE=0, we have to do a bit of work. */ 836 PDMDevHlpPhysRead(pDevIns, addr, (void*)&xda, sizeof(xda)); 837 ((uint32_t *)tmd)[0] = (uint32_t)xda[0] | ((uint32_t)(xda[1] & 0x00ff) << 16); /* TMD0, buffer address. */ 838 ((uint32_t *)tmd)[1] = (uint32_t)xda[2] | ((uint32_t)(xda[1] & 0xff00) << 16); /* TMD1, buffer size and control bits. */ 839 ((uint32_t *)tmd)[2] = (uint32_t)xda[3] << 16; /* TMD2, status bits. */ 840 ((uint32_t *)tmd)[3] = 0; /* TMD3, user data, not present for SWSTYLE=1. */ 789 841 } 790 842 else if (RT_LIKELY(BCR_SWSTYLE(pThis) != 3)) 791 843 { 792 PDMDevHlpPhysRead(pDevIns, addr+7, &ownbyte, 1); 793 if (!(ownbyte & 0x80) && fRetIfNotOwn) 794 return false; 795 PDMDevHlpPhysRead(pDevIns, addr, (void*)tmd, 16); 844 /* For SWSTYLE=2, simply read the TMD as is. */ 845 PDMDevHlpPhysRead(pDevIns, addr, (void*)tmd, sizeof(*tmd)); 796 846 } 797 847 else 798 848 { 849 /* For SWSTYLE=3, swap the first and third DWORD around. */ 799 850 uint32_t xda[4]; 800 PDMDevHlpPhysRead(pDevIns, addr+7, &ownbyte, 1); 801 if (!(ownbyte & 0x80) && fRetIfNotOwn) 802 return false; 803 PDMDevHlpPhysRead(pDevIns, addr, (void*)&xda[0], sizeof(xda)); 804 ((uint32_t *)tmd)[0] = xda[2]; 805 ((uint32_t *)tmd)[1] = xda[1]; 806 ((uint32_t *)tmd)[2] = xda[0]; 807 ((uint32_t *)tmd)[3] = xda[3]; 808 } 809 /* Double check the own bit; guest drivers might be buggy and lock prefixes in the recompiler are ignored by other threads. */ 810 #ifdef DEBUG 811 if (tmd->tmd1.own == 1 && !(ownbyte & 0x80)) 812 Log(("pcnetTmdLoad: own bit flipped while reading!!\n")); 813 #endif 814 if (!(ownbyte & 0x80)) 815 tmd->tmd1.own = 0; 816 817 return !!tmd->tmd1.own; 851 PDMDevHlpPhysRead(pDevIns, addr, (void*)&xda, sizeof(xda)); 852 ((uint32_t *)tmd)[0] = xda[2]; /* TMD0, buffer address. */ 853 ((uint32_t *)tmd)[1] = xda[1]; /* TMD1, buffer size and control bits. */ 854 ((uint32_t *)tmd)[2] = xda[0]; /* TMD2, status bits. */ 855 ((uint32_t *)tmd)[3] = xda[3]; /* TMD3, user data. */ 856 } 818 857 } 819 858 820 859 /** 821 860 * Store transmit message descriptor and hand it over to the host (the VM guest). 822 * Make sure th at all data are transmitted before we clear the own flag.861 * Make sure the cleared OWN bit gets written last. 823 862 */ 824 863 DECLINLINE(void) pcnetTmdStorePassHost(PPDMDEVINS pDevIns, PPCNETSTATE pThis, TMD *tmd, RTGCPHYS32 addr) … … 827 866 if (RT_UNLIKELY(BCR_SWSTYLE(pThis) == 0)) 828 867 { 829 uint16_t xda[4]; 830 xda[0] = ((uint32_t *)tmd)[0] & 0xffff; 868 uint16_t xda[4]; /* Corresponds to memory layout, only two words used. */ 869 870 /* For SWSTYLE=0, write the status word first, then the word containing the OWN bit. */ 831 871 xda[1] = ((((uint32_t *)tmd)[0] >> 16) & 0xff) | ((((uint32_t *)tmd)[1]>>16) & 0xff00); 832 xda[ 2] = ((uint32_t *)tmd)[1] & 0xffff;872 xda[1] &= ~RT_BIT(15); 833 873 xda[3] = ((uint32_t *)tmd)[2] >> 16; 834 xda[1] |= 0x8000; 835 pcnetPhysWrite(pDevIns, pThis, addr, (void*)&xda[0], sizeof(xda)); 836 xda[1] &= ~0x8000; 837 pcnetPhysWrite(pDevIns, pThis, addr+3, (uint8_t*)xda + 3, 1); 874 /** @todo: The WORD containing status bits may not need to be written unless the ERR bit is set. */ 875 pcnetPhysWrite(pDevIns, pThis, addr + 3 * sizeof(uint16_t), (void*)&xda[3], sizeof(uint16_t)); 876 pcnetPhysWrite(pDevIns, pThis, addr + 1 * sizeof(uint16_t), (void*)&xda[1], sizeof(uint16_t)); 838 877 } 839 878 else if (RT_LIKELY(BCR_SWSTYLE(pThis) != 3)) 840 879 { 841 ((uint32_t*)tmd)[1] |= 0x80000000; 842 pcnetPhysWrite(pDevIns, pThis, addr, (void*)tmd, 12); 843 ((uint32_t*)tmd)[1] &= ~0x80000000; 844 pcnetPhysWrite(pDevIns, pThis, addr+7, (uint8_t*)tmd + 7, 1); 880 /* For SWSTYLE=0, write TMD2 first, then TMD1. */ 881 /** @todo: The DWORD containing status bits may not need to be written unless the ERR bit is set. */ 882 pcnetPhysWrite(pDevIns, pThis, addr + 2 * sizeof(uint32_t), (uint32_t*)tmd + 2, sizeof(uint32_t)); 883 ((uint32_t*)tmd)[1] &= ~RT_BIT(31); 884 pcnetPhysWrite(pDevIns, pThis, addr + 1 * sizeof(uint32_t), (uint32_t*)tmd + 1, sizeof(uint32_t)); 845 885 } 846 886 else 847 887 { 848 uint32_t xda[3]; 888 uint32_t xda[2]; 889 890 /* For SWSTYLE=3, two DWORDs can be written in one go because the OWN bit is last. */ 849 891 xda[0] = ((uint32_t *)tmd)[2]; 850 892 xda[1] = ((uint32_t *)tmd)[1]; 851 xda[2] = ((uint32_t *)tmd)[0]; 852 xda[1] |= 0x80000000; 853 pcnetPhysWrite(pDevIns, pThis, addr, (void*)&xda[0], sizeof(xda)); 854 xda[1] &= ~0x80000000; 855 pcnetPhysWrite(pDevIns, pThis, addr+7, (uint8_t*)xda + 7, 1); 893 xda[1] &= ~RT_BIT(31); 894 pcnetPhysWrite(pDevIns, pThis, addr, (void*)&xda, sizeof(xda)); 856 895 } 857 896 STAM_PROFILE_ADV_STOP(&pThis->CTX_SUFF_Z(StatTmdStore), a); … … 1800 1839 RTGCPHYS32 cxda = pcnetTdraAddr(pThis, CSR_XMTRC(pThis)); 1801 1840 1802 if (!pcnetTmd Load(pDevIns, pThis, tmd, PHYSADDR(pThis, cxda), true))1841 if (!pcnetTmdTryLoad(pDevIns, pThis, tmd, PHYSADDR(pThis, cxda))) 1803 1842 { 1804 1843 STAM_PROFILE_ADV_STOP(&pThis->CTX_SUFF_Z(StatTdtePoll), a); … … 1862 1901 RTGCPHYS32 addrDesc = pcnetTdraAddr(pThis, iDesc); 1863 1902 1864 if (!pcnetTmd Load(pDevIns, pThis, &tmd, PHYSADDR(pThis, addrDesc), true))1903 if (!pcnetTmdTryLoad(pDevIns, pThis, &tmd, PHYSADDR(pThis, addrDesc))) 1865 1904 { 1866 1905 STAM_PROFILE_ADV_STOP(&pThis->CTX_SUFF_Z(StatTxLenCalc), a); … … 2293 2332 static void pcnetXmitRead1stSlow(PPDMDEVINS pDevIns, RTGCPHYS32 GCPhysFrame, unsigned cbFrame, PPDMSCATTERGATHER pSgBuf) 2294 2333 { 2295 AssertFailed(); /* This path is not supposed to be taken atm */2296 2297 2334 pSgBuf->cbUsed = cbFrame; 2298 2335 for (uint32_t iSeg = 0; ; iSeg++) 2299 2336 { 2300 Assert(iSeg < pSgBuf->cSegs); 2337 if (iSeg >= pSgBuf->cSegs) 2338 { 2339 AssertFailed(); 2340 LogRelMax(10, ("PCnet: pcnetXmitRead1stSlow: segment overflow -> ignoring\n")); 2341 return; 2342 } 2343 2301 2344 uint32_t cbRead = (uint32_t)RT_MIN(cbFrame, pSgBuf->aSegs[iSeg].cbSeg); 2302 2345 PDMDevHlpPhysRead(pDevIns, GCPhysFrame, pSgBuf->aSegs[iSeg].pvSeg, cbRead); … … 2315 2358 static void pcnetXmitReadMoreSlow(PPDMDEVINS pDevIns, RTGCPHYS32 GCPhysFrame, unsigned cbFrame, PPDMSCATTERGATHER pSgBuf) 2316 2359 { 2317 AssertFailed(); /* This path is not supposed to be taken atm */2318 2319 2360 /* Find the segment which we'll put the next byte into. */ 2320 2361 size_t off = pSgBuf->cbUsed; … … 2325 2366 offSeg += pSgBuf->aSegs[iSeg].cbSeg; 2326 2367 iSeg++; 2327 Assert(iSeg < pSgBuf->cSegs); 2368 if (iSeg >= pSgBuf->cSegs) 2369 { 2370 AssertFailed(); 2371 LogRelMax(10, ("PCnet: pcnetXmitReadMoreSlow: segment overflow #1 -> ignoring\n")); 2372 return; 2373 } 2328 2374 } 2329 2375 … … 2348 2394 for (;; iSeg++) 2349 2395 { 2350 Assert(iSeg < pSgBuf->cSegs); 2396 if (iSeg >= pSgBuf->cSegs) 2397 { 2398 AssertFailed(); 2399 LogRelMax(10, ("PCnet: pcnetXmitReadMoreSlow: segment overflow #2 -> ignoring\n")); 2400 return; 2401 } 2351 2402 2352 2403 uint32_t cbRead = (uint32_t)RT_MIN(pSgBuf->aSegs[iSeg].cbSeg, cbFrame); … … 2634 2685 CSR_XMTRC(pThis)--; 2635 2686 2636 TMD dummy;2637 if (!pcnetTdtePoll(pDevIns, pThis, & dummy))2687 TMD tmdNext; 2688 if (!pcnetTdtePoll(pDevIns, pThis, &tmdNext)) 2638 2689 { 2639 2690 /* … … 2656 2707 2657 2708 /* 2658 * The next tmd .2709 * The next tmd is already loaded. 2659 2710 */ 2660 2711 #ifdef VBOX_WITH_STATISTICS 2661 2712 cBuffers++; 2662 2713 #endif 2663 pcnetTmdLoad(pDevIns, pThis, &tmd, PHYSADDR(pThis, CSR_CXDA(pThis)), false);2714 tmd = tmdNext; 2664 2715 cb = 4096 - tmd.tmd1.bcnt; 2665 2716 if ( !fDropFrame 2666 && pSgBuf->cbUsed + cb <= MAX_FRAME) /** @todo this used to be ... + cb < MAX_FRAME. */2717 && pSgBuf->cbUsed + cb <= pSgBuf->cbAvailable) 2667 2718 pcnetXmitReadMore(pDevIns, PHYSADDR(pThis, tmd.tmd0.tbadr), cb, pSgBuf); 2668 2719 else … … 2858 2909 { 2859 2910 TMD tmd; 2860 pcnetTmdLoad (pDevIns, pThis, &tmd, PHYSADDR(pThis, CSR_CXDA(pThis)), false);2911 pcnetTmdLoadAll(pDevIns, pThis, &tmd, PHYSADDR(pThis, CSR_CXDA(pThis))); 2861 2912 Log10(("#%d pcnetPollTimer: TMDLOAD %#010x\n", PCNET_INST_NR, PHYSADDR(pThis, CSR_CXDA(pThis)))); 2862 2913 PRINT_TMD(&tmd); … … 4310 4361 { 4311 4362 TMD tmd; 4312 pcnetTmdLoad (pDevIns, pThis, &tmd, PHYSADDR(pThis, GCPhys), false);4363 pcnetTmdLoadAll(pDevIns, pThis, &tmd, PHYSADDR(pThis, GCPhys)); 4313 4364 pHlp->pfnPrintf(pHlp, 4314 4365 "%04x %RX32:%c%c TBADR=%08RX32 BCNT=%03x OWN=%d "
Note:
See TracChangeset
for help on using the changeset viewer.