- Timestamp:
- Aug 31, 2021 8:11:28 AM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DevPCNet.cpp
r90447 r91022 1596 1596 Log(("#%d pcnetR3Init: init_addr=%#010x\n", PCNET_INST_NR, PHYSADDR(pThis, CSR_IADR(pThis)))); 1597 1597 1598 /* If intialization was invoked with PCI bus mastering disabled, it's not going to 1599 * go very well. Better report an error. 1600 */ 1601 if (PCNET_IS_PCI(pThis)) 1602 { 1603 PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0]; 1604 uint8_t uCmd = PDMPciDevGetByte(pPciDev, 0x04); 1605 1606 if (!(uCmd & 4)) 1607 { 1608 pThis->aCSR[0] |= 0x0801; /* Set the MERR bit instead of IDON. */ 1609 LogRel(("PCnet#%d: Warning: Initialization failed due to disabled PCI bus mastering.\n", PCNET_INST_NR)); 1610 return; 1611 } 1612 } 1613 1598 1614 /** @todo Documentation says that RCVRL and XMTRL are stored as two's complement! 1599 1615 * Software is allowed to write these registers directly. */ … … 2954 2970 #ifdef IN_RING3 2955 2971 if (!CSR_INIT(pThis) && (val & 1)) 2956 pcnetR3Init(pDevIns, pThis, pThisCC); 2972 { 2973 bool fDelayInit = false; 2974 2975 /* Many PCnet drivers disable PCI bus mastering before setting the INIT bit and 2976 * then immediately enable it back again. This is done to work around a silicon 2977 * bug that could cause a PCI bus hang under some circumstances. The bug only 2978 * existed in the early PCI chips (Am79C970 PCnet-PCI) but many drivers apply the 2979 * workaround to all PCnet PCI models. Drivers written by AMD generally do this 2980 * (DOS, Windows, OS/2). PCnet drivers in Windows 2000 and XP are new enough to 2981 * not apply the workaround to our emulated PCnet-PCI II (Am79C970A) and 2982 * PCnet-FAST III (Am79C973). 2983 * 2984 * The AMDPCnet32 drivers for NeXTSTEP/OpenStep (notably OS 4.2) cpompletely fail 2985 * unless we delay the initialization until after bus mastering is re-enabled. 2986 */ 2987 if (PCNET_IS_PCI(pThis)) 2988 { 2989 PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0]; 2990 uint8_t uCmd = PDMPciDevGetByte(pPciDev, 0x04); 2991 2992 /* Recognize situation with PCI bus mastering disabled and setting 2993 * INIT bit without also setting STRT. 2994 */ 2995 if (!(uCmd & 4) && !(val & 2)) 2996 fDelayInit = true; 2997 } 2998 2999 if (!fDelayInit) 3000 pcnetR3Init(pDevIns, pThis, pThisCC); 3001 else 3002 { 3003 LogRel(("PCnet#%d: Delaying INIT due to disabled PCI bus mastering\n", PCNET_INST_NR)); 3004 pThis->aCSR[0] |= 0x0001; /* Set INIT and MERR bits. */ 3005 pThis->aCSR[6] = 1; /* Set a flag in read-only CSR6. */ 3006 } 3007 } 2957 3008 #endif 2958 3009 … … 3141 3192 } 3142 3193 3143 static uint32_t pcnetCSRReadU16(PPDMDEVINS pDevIns, PPCNETSTATE pThis, uint32_t u32RAP)3194 static VBOXSTRICTRC pcnetCSRReadU16(PPDMDEVINS pDevIns, PPCNETSTATE pThis, PPCNETSTATECC pThisCC, uint32_t u32RAP, uint32_t *pu32) 3144 3195 { 3145 3196 uint32_t val; … … 3147 3198 { 3148 3199 case 0: 3200 /* Check if delayed initialization needs to run. */ 3201 if (RT_UNLIKELY(pThis->aCSR[6] == 1)) 3202 { 3203 #ifndef IN_RING3 3204 return VINF_IOM_R3_IOPORT_READ; 3205 #else 3206 /* This is the second half of delayed initialization required 3207 * to work around guest drivers that temporarily disable PCI bus 3208 * mastering around setting the INIT bit in CSR0. 3209 * See pcnetCSRWriteU16() for details. 3210 */ 3211 pcnetR3Init(pDevIns, pThis, pThisCC); 3212 Assert(pThis->aCSR[6] != 1); 3213 #endif 3214 } 3149 3215 pcnetUpdateIrq(pDevIns, pThis); 3150 3216 val = pThis->aCSR[0]; … … 3153 3219 break; 3154 3220 case 16: 3155 return pcnetCSRReadU16(pDevIns, pThis, 1);3221 return pcnetCSRReadU16(pDevIns, pThis, pThisCC, 1, pu32); 3156 3222 case 17: 3157 return pcnetCSRReadU16(pDevIns, pThis, 2);3223 return pcnetCSRReadU16(pDevIns, pThis, pThisCC, 2, pu32); 3158 3224 case 58: 3159 return pcnetBCRReadU16(pThis, BCR_SWS); 3225 *pu32 = pcnetBCRReadU16(pThis, BCR_SWS); 3226 return VINF_SUCCESS; 3160 3227 case 68: /* Custom register to pass link speed to driver */ 3161 return pcnetLinkSpd(pThis->u32LinkSpeed); 3228 *pu32 = pcnetLinkSpd(pThis->u32LinkSpeed); 3229 return VINF_SUCCESS; 3162 3230 case 88: 3163 3231 val = pThis->aCSR[89]; … … 3168 3236 val = pThis->aCSR[u32RAP]; 3169 3237 } 3238 *pu32 = val; 3170 3239 Log8(("#%d pcnetCSRReadU16: rap=%d val=%#06x\n", PCNET_INST_NR, u32RAP, val)); 3171 return val;3240 return VINF_SUCCESS; 3172 3241 } 3173 3242 … … 3616 3685 } 3617 3686 3618 static uint32_t pcnetIoPortReadU8(PPDMDEVINS pDevIns, PPCNETSTATE pThis, uint32_t addr)3619 { 3620 uint32_tval = UINT32_MAX;3687 static VBOXSTRICTRC pcnetIoPortReadU8(PPDMDEVINS pDevIns, PPCNETSTATE pThis, uint32_t addr, uint32_t *val) 3688 { 3689 *val = UINT32_MAX; 3621 3690 3622 3691 if (RT_LIKELY(!BCR_DWIO(pThis))) … … 3626 3695 case 0x04: /* RESET */ 3627 3696 pcnetSoftReset(pThis); 3628 val = 0;3697 *val = 0; 3629 3698 break; 3630 3699 } 3631 3700 } 3632 3701 else 3633 Log(("#%d pcnetIoPortReadU8: addr=%#010x val=%#06x BCR_DWIO !!\n", PCNET_INST_NR, addr, val & 0xff));3702 Log(("#%d pcnetIoPortReadU8: addr=%#010x val=%#06x BCR_DWIO !!\n", PCNET_INST_NR, addr, *val & 0xff)); 3634 3703 3635 3704 pcnetUpdateIrq(pDevIns, pThis); 3636 3705 3637 Log6(("#%d pcnetIoPortReadU8: addr=%#010x val=%#06x\n", PCNET_INST_NR, addr, val & 0xff));3638 return val;3706 Log6(("#%d pcnetIoPortReadU8: addr=%#010x val=%#06x\n", PCNET_INST_NR, addr, *val & 0xff)); 3707 return VINF_SUCCESS; 3639 3708 } 3640 3709 … … 3667 3736 } 3668 3737 3669 static uint32_t pcnetIoPortReadU16(PPDMDEVINS pDevIns, PPCNETSTATE pThis, PPCNETSTATECC pThisCC, uint32_t addr) 3670 { 3671 uint32_t val = ~0U; 3738 static VBOXSTRICTRC pcnetIoPortReadU16(PPDMDEVINS pDevIns, PPCNETSTATE pThis, PPCNETSTATECC pThisCC, uint32_t addr, uint32_t *val) 3739 { 3740 VBOXSTRICTRC rc = VINF_SUCCESS; 3741 3742 *val = ~0U; 3672 3743 3673 3744 if (RT_LIKELY(!BCR_DWIO(pThis))) … … 3681 3752 pcnetPollTimer(pDevIns, pThis, pThisCC); 3682 3753 3683 val = pcnetCSRReadU16(pDevIns, pThis, pThis->u32RAP);3754 rc = pcnetCSRReadU16(pDevIns, pThis, pThisCC, pThis->u32RAP, val); 3684 3755 if (pThis->u32RAP == 0) // pcnetUpdateIrq() already called by pcnetCSRReadU16() 3685 3756 goto skip_update_irq; 3686 3757 break; 3687 3758 case 0x02: /* RAP */ 3688 val = pThis->u32RAP;3759 *val = pThis->u32RAP; 3689 3760 goto skip_update_irq; 3690 3761 case 0x04: /* RESET */ 3691 3762 pcnetSoftReset(pThis); 3692 val = 0;3763 *val = 0; 3693 3764 break; 3694 3765 case 0x06: /* BDP */ 3695 val = pcnetBCRReadU16(pThis, pThis->u32RAP);3766 *val = pcnetBCRReadU16(pThis, pThis->u32RAP); 3696 3767 break; 3697 3768 } 3698 3769 } 3699 3770 else 3700 Log(("#%d pcnetIoPortReadU16: addr=%#010x val=%#06x BCR_DWIO !!\n", PCNET_INST_NR, addr, val & 0xffff));3771 Log(("#%d pcnetIoPortReadU16: addr=%#010x val=%#06x BCR_DWIO !!\n", PCNET_INST_NR, addr, *val & 0xffff)); 3701 3772 3702 3773 pcnetUpdateIrq(pDevIns, pThis); 3703 3774 3704 3775 skip_update_irq: 3705 Log6(("#%d pcnetIoPortReadU16: addr=%#010x val=%#06x\n", PCNET_INST_NR, addr, val & 0xffff));3706 return val;3776 Log6(("#%d pcnetIoPortReadU16: addr=%#010x val=%#06x\n", PCNET_INST_NR, addr, *val & 0xffff)); 3777 return rc; 3707 3778 } 3708 3779 … … 3741 3812 } 3742 3813 3743 static uint32_t pcnetIoPortReadU32(PPDMDEVINS pDevIns, PPCNETSTATE pThis, PPCNETSTATECC pThisCC, uint32_t addr) 3744 { 3745 uint32_t val = ~0U; 3814 static VBOXSTRICTRC pcnetIoPortReadU32(PPDMDEVINS pDevIns, PPCNETSTATE pThis, PPCNETSTATECC pThisCC, uint32_t addr, uint32_t *val) 3815 { 3816 VBOXSTRICTRC rc = VINF_SUCCESS; 3817 3818 *val = ~0U; 3746 3819 3747 3820 if (RT_LIKELY(BCR_DWIO(pThis))) … … 3755 3828 pcnetPollTimer(pDevIns, pThis, pThisCC); 3756 3829 3757 val = pcnetCSRReadU16(pDevIns, pThis, pThis->u32RAP);3830 rc = pcnetCSRReadU16(pDevIns, pThis, pThisCC, pThis->u32RAP, val); 3758 3831 if (pThis->u32RAP == 0) // pcnetUpdateIrq() already called by pcnetCSRReadU16() 3759 3832 goto skip_update_irq; 3760 3833 break; 3761 3834 case 0x04: /* RAP */ 3762 val = pThis->u32RAP;3835 *val = pThis->u32RAP; 3763 3836 goto skip_update_irq; 3764 3837 case 0x08: /* RESET */ 3765 3838 pcnetSoftReset(pThis); 3766 val = 0;3839 *val = 0; 3767 3840 break; 3768 3841 case 0x0c: /* BDP */ 3769 val = pcnetBCRReadU16(pThis, pThis->u32RAP);3842 *val = pcnetBCRReadU16(pThis, pThis->u32RAP); 3770 3843 break; 3771 3844 } 3772 3845 } 3773 3846 else 3774 Log(("#%d pcnetIoPortReadU32: addr=%#010x val=%#010x !BCR_DWIO !!\n", PCNET_INST_NR, addr, val));3847 Log(("#%d pcnetIoPortReadU32: addr=%#010x val=%#010x !BCR_DWIO !!\n", PCNET_INST_NR, addr, *val)); 3775 3848 pcnetUpdateIrq(pDevIns, pThis); 3776 3849 3777 3850 skip_update_irq: 3778 Log6(("#%d pcnetIoPortReadU32: addr=%#010x val=%#010x\n", PCNET_INST_NR, addr, val));3779 return val;3851 Log6(("#%d pcnetIoPortReadU32: addr=%#010x val=%#010x\n", PCNET_INST_NR, addr, *val)); 3852 return rc; 3780 3853 } 3781 3854 … … 3788 3861 PPCNETSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PPCNETSTATE); 3789 3862 PPCNETSTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PPCNETSTATECC); 3790 VBOXSTRICTRC rc = VINF_SUCCESS;3863 VBOXSTRICTRC rc; 3791 3864 STAM_PROFILE_ADV_START(&pThis->CTX_SUFF_Z(StatIORead), a); 3792 3865 Assert(PDMDevHlpCritSectIsOwner(pDevIns, &pThis->CritSect)); … … 3795 3868 switch (cb) 3796 3869 { 3797 case 1: *pu32 = pcnetIoPortReadU8(pDevIns, pThis, offPort); break;3798 case 2: *pu32 = pcnetIoPortReadU16(pDevIns, pThis, pThisCC, offPort); break;3799 case 4: *pu32 = pcnetIoPortReadU32(pDevIns, pThis, pThisCC, offPort); break;3870 case 1: rc = pcnetIoPortReadU8(pDevIns, pThis, offPort, pu32); break; 3871 case 2: rc = pcnetIoPortReadU16(pDevIns, pThis, pThisCC, offPort, pu32); break; 3872 case 4: rc = pcnetIoPortReadU32(pDevIns, pThis, pThisCC, offPort, pu32); break; 3800 3873 default: 3801 3874 rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "pcnetIoPortRead: unsupported op size: offset=%#10x cb=%u\n", offPort, cb); … … 3846 3919 } 3847 3920 3848 static uint32_t pcnetR3MmioReadU8(PPCNETSTATE pThis, RTGCPHYS addr)3849 { 3850 uint32_t val = ~0U;3921 static VBOXSTRICTRC pcnetR3MmioReadU8(PPCNETSTATE pThis, RTGCPHYS addr, uint8_t *val) 3922 { 3923 *val = 0xff; 3851 3924 if (!(addr & 0x10)) 3852 val = pcnetAPROMReadU8(pThis, addr);3853 Log6(("#%d pcnetR3MmioReadU8: addr=%#010x val=%#04x\n", PCNET_INST_NR, addr, val & 0xff));3854 return val;3925 *val = pcnetAPROMReadU8(pThis, addr); 3926 Log6(("#%d pcnetR3MmioReadU8: addr=%#010x val=%#04x\n", PCNET_INST_NR, addr, *val)); 3927 return VINF_SUCCESS; 3855 3928 } 3856 3929 … … 3874 3947 } 3875 3948 3876 static uint32_t pcnetR3MmioReadU16(PPDMDEVINS pDevIns, PPCNETSTATE pThis, PPCNETSTATECC pThisCC, RTGCPHYS addr) 3877 { 3878 uint32_t val = ~0U; 3949 static VBOXSTRICTRC pcnetR3MmioReadU16(PPDMDEVINS pDevIns, PPCNETSTATE pThis, PPCNETSTATECC pThisCC, RTGCPHYS addr, uint16_t *val) 3950 { 3951 VBOXSTRICTRC rcStrict; 3952 uint32_t val32 = ~0U; 3879 3953 3880 3954 if (addr & 0x10) 3881 val = pcnetIoPortReadU16(pDevIns, pThis, pThisCC, addr & 0x0f); 3955 { 3956 rcStrict = pcnetIoPortReadU16(pDevIns, pThis, pThisCC, addr & 0x0f, &val32); 3957 if (rcStrict == VINF_IOM_R3_IOPORT_READ) 3958 rcStrict = VINF_IOM_R3_MMIO_READ; 3959 } 3882 3960 else 3883 3961 { 3884 val = pcnetAPROMReadU8(pThis, addr+1); 3885 val <<= 8; 3886 val |= pcnetAPROMReadU8(pThis, addr); 3887 } 3888 Log6(("#%d pcnetR3MmioReadU16: addr=%#010x val = %#06x\n", PCNET_INST_NR, addr, val & 0xffff)); 3889 return val; 3962 val32 = pcnetAPROMReadU8(pThis, addr+1); 3963 val32 <<= 8; 3964 val32 |= pcnetAPROMReadU8(pThis, addr); 3965 rcStrict = VINF_SUCCESS; 3966 } 3967 *val = (uint16_t)val32; 3968 Log6(("#%d pcnetR3MmioReadU16: addr=%#010x val = %#06x\n", PCNET_INST_NR, addr, *val)); 3969 return rcStrict; 3890 3970 } 3891 3971 … … 3911 3991 } 3912 3992 3913 static uint32_t pcnetR3MmioReadU32(PPDMDEVINS pDevIns, PPCNETSTATE pThis, PPCNETSTATECC pThisCC, RTGCPHYS addr)3914 { 3915 uint32_t val;3993 static VBOXSTRICTRC pcnetR3MmioReadU32(PPDMDEVINS pDevIns, PPCNETSTATE pThis, PPCNETSTATECC pThisCC, RTGCPHYS addr, uint32_t *val) 3994 { 3995 VBOXSTRICTRC rcStrict; 3916 3996 3917 3997 if (addr & 0x10) 3918 val = pcnetIoPortReadU32(pDevIns, pThis, pThisCC, addr & 0x0f); 3998 { 3999 rcStrict = pcnetIoPortReadU32(pDevIns, pThis, pThisCC, addr & 0x0f, val); 4000 if (rcStrict == VINF_IOM_R3_IOPORT_READ) 4001 rcStrict = VINF_IOM_R3_MMIO_READ; 4002 } 3919 4003 else 3920 4004 { 3921 val = pcnetAPROMReadU8(pThis, addr+3); 3922 val <<= 8; 3923 val |= pcnetAPROMReadU8(pThis, addr+2); 3924 val <<= 8; 3925 val |= pcnetAPROMReadU8(pThis, addr+1); 3926 val <<= 8; 3927 val |= pcnetAPROMReadU8(pThis, addr ); 3928 } 3929 Log6(("#%d pcnetR3MmioReadU32: addr=%#010x val=%#010x\n", PCNET_INST_NR, addr, val)); 3930 return val; 4005 uint32_t val32; 4006 4007 val32 = pcnetAPROMReadU8(pThis, addr+3); 4008 val32 <<= 8; 4009 val32 |= pcnetAPROMReadU8(pThis, addr+2); 4010 val32 <<= 8; 4011 val32 |= pcnetAPROMReadU8(pThis, addr+1); 4012 val32 <<= 8; 4013 val32 |= pcnetAPROMReadU8(pThis, addr ); 4014 *val = val32; 4015 rcStrict = VINF_SUCCESS; 4016 } 4017 Log6(("#%d pcnetR3MmioReadU32: addr=%#010x val=%#010x\n", PCNET_INST_NR, addr, *val)); 4018 return rcStrict; 3931 4019 } 3932 4020 … … 3951 4039 switch (cb) 3952 4040 { 3953 case 1: *(uint8_t *)pv = pcnetR3MmioReadU8 (pThis, off); break;3954 case 2: *(uint16_t *)pv = pcnetR3MmioReadU16(pDevIns, pThis, pThisCC, off); break;3955 case 4: *(uint32_t *)pv = pcnetR3MmioReadU32(pDevIns, pThis, pThisCC, off); break;4041 case 1: rc = pcnetR3MmioReadU8 (pThis, off, (uint8_t *)pv); break; 4042 case 2: rc = pcnetR3MmioReadU16(pDevIns, pThis, pThisCC, off, (uint16_t *)pv); break; 4043 case 4: rc = pcnetR3MmioReadU32(pDevIns, pThis, pThisCC, off, (uint32_t *)pv); break; 3956 4044 default: 3957 4045 rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "pcnetR3MmioRead: unsupported op size: address=%RGp cb=%u\n", off, cb); … … 5244 5332 PDMPciDevSetByte(pPciDev, 0x06, 0x80); /* status */ 5245 5333 PDMPciDevSetByte(pPciDev, 0x07, 0x02); 5246 PDMPciDevSetByte(pPciDev, 0x08, pThis->uDevType == DEV_AM79C973 ? 0x40 : 0x1 0); /* revision */5334 PDMPciDevSetByte(pPciDev, 0x08, pThis->uDevType == DEV_AM79C973 ? 0x40 : 0x16); /* revision */ 5247 5335 PDMPciDevSetByte(pPciDev, 0x09, 0x00); 5248 5336 PDMPciDevSetByte(pPciDev, 0x0a, 0x00); /* ethernet network controller */
Note:
See TracChangeset
for help on using the changeset viewer.