summaryrefslogtreecommitdiff
path: root/src/VBox/Devices/Network/DevPCNet.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2014-03-26 19:21:20 +0000
committer <>2014-05-08 15:03:54 +0000
commitfb123f93f9f5ce42c8e5785d2f8e0edaf951740e (patch)
treec2103d76aec5f1f10892cd1d3a38e24f665ae5db /src/VBox/Devices/Network/DevPCNet.cpp
parent58ed4748338f9466599adfc8a9171280ed99e23f (diff)
downloadVirtualBox-master.tar.gz
Imported from /home/lorry/working-area/delta_VirtualBox/VirtualBox-4.3.10.tar.bz2.HEADVirtualBox-4.3.10master
Diffstat (limited to 'src/VBox/Devices/Network/DevPCNet.cpp')
-rw-r--r--src/VBox/Devices/Network/DevPCNet.cpp1404
1 files changed, 568 insertions, 836 deletions
diff --git a/src/VBox/Devices/Network/DevPCNet.cpp b/src/VBox/Devices/Network/DevPCNet.cpp
index 0f0f2bfa..481267ee 100644
--- a/src/VBox/Devices/Network/DevPCNet.cpp
+++ b/src/VBox/Devices/Network/DevPCNet.cpp
@@ -10,7 +10,7 @@
*/
/*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2006-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -54,7 +54,7 @@
#include <VBox/vmm/pdmdev.h>
#include <VBox/vmm/pdmnetifs.h>
#include <VBox/vmm/pgm.h>
-#include <VBox/DevPCNet.h>
+#include <VBox/version.h>
#include <iprt/asm.h>
#include <iprt/assert.h>
#include <iprt/critsect.h>
@@ -69,6 +69,10 @@
#include "VBoxDD.h"
+
+/*******************************************************************************
+* Defined Constants And Macros *
+*******************************************************************************/
/* Enable this to catch writes to the ring descriptors instead of using excessive polling */
/* #define PCNET_NO_POLLING */
@@ -94,15 +98,151 @@
#define MII_MAX_REG 32
#define CSR_MAX_REG 128
-/* Maximum number of times we report a link down to the guest (failure to send frame) */
+/** Maximum number of times we report a link down to the guest (failure to send frame) */
#define PCNET_MAX_LINKDOWN_REPORTED 3
-/* Maximum frame size we handle */
+/** Maximum frame size we handle */
#define MAX_FRAME 1536
+#define PCNETSTATE_2_DEVINS(pPCNet) ((pPCNet)->CTX_SUFF(pDevIns))
+#define PCIDEV_2_PCNETSTATE(pPciDev) RT_FROM_MEMBER((pPciDev), PCNETSTATE, PciDev)
+#define PCNET_INST_NR (PCNETSTATE_2_DEVINS(pThis)->iInstance)
+
+/** @name Bus configuration registers
+ * @{ */
+#define BCR_MSRDA 0
+#define BCR_MSWRA 1
+#define BCR_MC 2
+#define BCR_RESERVED3 3
+#define BCR_LNKST 4
+#define BCR_LED1 5
+#define BCR_LED2 6
+#define BCR_LED3 7
+#define BCR_RESERVED8 8
+#define BCR_FDC 9
+/* 10 - 15 = reserved */
+#define BCR_IOBASEL 16 /* Reserved */
+#define BCR_IOBASEU 16 /* Reserved */
+#define BCR_BSBC 18
+#define BCR_EECAS 19
+#define BCR_SWS 20
+#define BCR_INTCON 21 /* Reserved */
+#define BCR_PLAT 22
+#define BCR_PCISVID 23
+#define BCR_PCISID 24
+#define BCR_SRAMSIZ 25
+#define BCR_SRAMB 26
+#define BCR_SRAMIC 27
+#define BCR_EBADDRL 28
+#define BCR_EBADDRU 29
+#define BCR_EBD 30
+#define BCR_STVAL 31
+#define BCR_MIICAS 32
+#define BCR_MIIADDR 33
+#define BCR_MIIMDR 34
+#define BCR_PCIVID 35
+#define BCR_PMC_A 36
+#define BCR_DATA0 37
+#define BCR_DATA1 38
+#define BCR_DATA2 39
+#define BCR_DATA3 40
+#define BCR_DATA4 41
+#define BCR_DATA5 42
+#define BCR_DATA6 43
+#define BCR_DATA7 44
+#define BCR_PMR1 45
+#define BCR_PMR2 46
+#define BCR_PMR3 47
+/** @} */
+
+/** @name Bus configuration sub register accessors.
+ * @{ */
+#define BCR_DWIO(S) !!((S)->aBCR[BCR_BSBC] & 0x0080)
+#define BCR_SSIZE32(S) !!((S)->aBCR[BCR_SWS ] & 0x0100)
+#define BCR_SWSTYLE(S) ((S)->aBCR[BCR_SWS ] & 0x00FF)
+/** @} */
+
+/** @name CSR subregister accessors.
+ * @{ */
+#define CSR_INIT(S) !!((S)->aCSR[0] & 0x0001) /**< Init assertion */
+#define CSR_STRT(S) !!((S)->aCSR[0] & 0x0002) /**< Start assertion */
+#define CSR_STOP(S) !!((S)->aCSR[0] & 0x0004) /**< Stop assertion */
+#define CSR_TDMD(S) !!((S)->aCSR[0] & 0x0008) /**< Transmit demand. (perform xmit poll now (readable, settable, not clearable) */
+#define CSR_TXON(S) !!((S)->aCSR[0] & 0x0010) /**< Transmit on (readonly) */
+#define CSR_RXON(S) !!((S)->aCSR[0] & 0x0020) /**< Receive On */
+#define CSR_INEA(S) !!((S)->aCSR[0] & 0x0040) /**< Interrupt Enable */
+#define CSR_LAPPEN(S) !!((S)->aCSR[3] & 0x0020) /**< Look Ahead Packet Processing Enable */
+#define CSR_DXSUFLO(S) !!((S)->aCSR[3] & 0x0040) /**< Disable Transmit Stop on Underflow error */
+#define CSR_ASTRP_RCV(S) !!((S)->aCSR[4] & 0x0400) /**< Auto Strip Receive */
+#define CSR_DPOLL(S) !!((S)->aCSR[4] & 0x1000) /**< Disable Transmit Polling */
+#define CSR_SPND(S) !!((S)->aCSR[5] & 0x0001) /**< Suspend */
+#define CSR_LTINTEN(S) !!((S)->aCSR[5] & 0x4000) /**< Last Transmit Interrupt Enable */
+#define CSR_TOKINTD(S) !!((S)->aCSR[5] & 0x8000) /**< Transmit OK Interrupt Disable */
+
+#define CSR_STINT !!((S)->aCSR[7] & 0x0800) /**< Software Timer Interrupt */
+#define CSR_STINTE !!((S)->aCSR[7] & 0x0400) /**< Software Timer Interrupt Enable */
+
+#define CSR_DRX(S) !!((S)->aCSR[15] & 0x0001) /**< Disable Receiver */
+#define CSR_DTX(S) !!((S)->aCSR[15] & 0x0002) /**< Disable Transmit */
+#define CSR_LOOP(S) !!((S)->aCSR[15] & 0x0004) /**< Loopback Enable */
+#define CSR_DRCVPA(S) !!((S)->aCSR[15] & 0x2000) /**< Disable Receive Physical Address */
+#define CSR_DRCVBC(S) !!((S)->aCSR[15] & 0x4000) /**< Disable Receive Broadcast */
+#define CSR_PROM(S) !!((S)->aCSR[15] & 0x8000) /**< Promiscuous Mode */
+/** @} */
+
+#if !defined(RT_ARCH_X86) && !defined(RT_ARCH_AMD64)
+# error fix macros (and more in this file) for big-endian machines
+#endif
+
+/** @name CSR register accessors.
+ * @{ */
+#define CSR_IADR(S) (*(uint32_t*)((S)->aCSR + 1)) /**< Initialization Block Address */
+#define CSR_CRBA(S) (*(uint32_t*)((S)->aCSR + 18)) /**< Current Receive Buffer Address */
+#define CSR_CXBA(S) (*(uint32_t*)((S)->aCSR + 20)) /**< Current Transmit Buffer Address */
+#define CSR_NRBA(S) (*(uint32_t*)((S)->aCSR + 22)) /**< Next Receive Buffer Address */
+#define CSR_BADR(S) (*(uint32_t*)((S)->aCSR + 24)) /**< Base Address of Receive Ring */
+#define CSR_NRDA(S) (*(uint32_t*)((S)->aCSR + 26)) /**< Next Receive Descriptor Address */
+#define CSR_CRDA(S) (*(uint32_t*)((S)->aCSR + 28)) /**< Current Receive Descriptor Address */
+#define CSR_BADX(S) (*(uint32_t*)((S)->aCSR + 30)) /**< Base Address of Transmit Descriptor */
+#define CSR_NXDA(S) (*(uint32_t*)((S)->aCSR + 32)) /**< Next Transmit Descriptor Address */
+#define CSR_CXDA(S) (*(uint32_t*)((S)->aCSR + 34)) /**< Current Transmit Descriptor Address */
+#define CSR_NNRD(S) (*(uint32_t*)((S)->aCSR + 36)) /**< Next Next Receive Descriptor Address */
+#define CSR_NNXD(S) (*(uint32_t*)((S)->aCSR + 38)) /**< Next Next Transmit Descriptor Address */
+#define CSR_CRBC(S) ((S)->aCSR[40]) /**< Current Receive Byte Count */
+#define CSR_CRST(S) ((S)->aCSR[41]) /**< Current Receive Status */
+#define CSR_CXBC(S) ((S)->aCSR[42]) /**< Current Transmit Byte Count */
+#define CSR_CXST(S) ((S)->aCSR[43]) /**< Current transmit status */
+#define CSR_NRBC(S) ((S)->aCSR[44]) /**< Next Receive Byte Count */
+#define CSR_NRST(S) ((S)->aCSR[45]) /**< Next Receive Status */
+#define CSR_POLL(S) ((S)->aCSR[46]) /**< Transmit Poll Time Counter */
+#define CSR_PINT(S) ((S)->aCSR[47]) /**< Transmit Polling Interval */
+#define CSR_PXDA(S) (*(uint32_t*)((S)->aCSR + 60)) /**< Previous Transmit Descriptor Address*/
+#define CSR_PXBC(S) ((S)->aCSR[62]) /**< Previous Transmit Byte Count */
+#define CSR_PXST(S) ((S)->aCSR[63]) /**< Previous Transmit Status */
+#define CSR_NXBA(S) (*(uint32_t*)((S)->aCSR + 64)) /**< Next Transmit Buffer Address */
+#define CSR_NXBC(S) ((S)->aCSR[66]) /**< Next Transmit Byte Count */
+#define CSR_NXST(S) ((S)->aCSR[67]) /**< Next Transmit Status */
+#define CSR_RCVRC(S) ((S)->aCSR[72]) /**< Receive Descriptor Ring Counter */
+#define CSR_XMTRC(S) ((S)->aCSR[74]) /**< Transmit Descriptor Ring Counter */
+#define CSR_RCVRL(S) ((S)->aCSR[76]) /**< Receive Descriptor Ring Length */
+#define CSR_XMTRL(S) ((S)->aCSR[78]) /**< Transmit Descriptor Ring Length */
+#define CSR_MISSC(S) ((S)->aCSR[112]) /**< Missed Frame Count */
+/** @} */
+
+/** @name Version for the PCnet/FAST III 79C973 card
+ * @{ */
+#define CSR_VERSION_LOW_79C973 0x5003 /* the lower two bits must be 11b for AMD */
+#define CSR_VERSION_LOW_79C970A 0x1003 /* the lower two bits must be 11b for AMD */
+#define CSR_VERSION_HIGH 0x0262
+/** @} */
+
+/** Calculates the full physical address. */
+#define PHYSADDR(S,A) ((A) | (S)->GCUpperPhys)
-typedef struct PCNetState_st PCNetState;
+/*******************************************************************************
+* Structures and Typedefs *
+*******************************************************************************/
/**
* PCNET state.
*
@@ -112,7 +252,7 @@ typedef struct PCNetState_st PCNetState;
* @implements PDMINETWORKCONFIG
* @implements PDMILEDPORTS
*/
-struct PCNetState_st
+typedef struct PCNETSTATE
{
PCIDEVICE PciDev;
@@ -132,8 +272,6 @@ struct PCNetState_st
PDMINETWORKDOWN INetworkDown;
/** LUN\#0: The network config port interface. */
PDMINETWORKCONFIG INetworkConfig;
- /** The shared memory used for the private interface - R3. */
- R3PTRTYPE(PPCNETGUESTSHAREDMEMORY) pSharedMMIOR3;
/** Software Interrupt timer - R3. */
PTMTIMERR3 pTimerSoftIntR3;
#ifndef PCNET_NO_POLLING
@@ -152,8 +290,6 @@ struct PCNetState_st
R0PTRTYPE(PPDMQUEUE) pXmitQueueR0;
/** Pointer to the connector of the attached network driver - R0. */
PPDMINETWORKUPR0 pDrvR0;
- /** The shared memory used for the private interface - R0. */
- R0PTRTYPE(PPCNETGUESTSHAREDMEMORY) pSharedMMIOR0;
/** Software Interrupt timer - R0. */
PTMTIMERR0 pTimerSoftIntR0;
#ifndef PCNET_NO_POLLING
@@ -169,8 +305,6 @@ struct PCNetState_st
RCPTRTYPE(PPDMQUEUE) pXmitQueueRC;
/** Pointer to the connector of the attached network driver - RC. */
PPDMINETWORKUPRC pDrvRC;
- /** The shared memory used for the private interface - RC. */
- RCPTRTYPE(PPCNETGUESTSHAREDMEMORY) pSharedMMIORC;
/** Software Interrupt timer - RC. */
PTMTIMERRC pTimerSoftIntRC;
#ifndef PCNET_NO_POLLING
@@ -178,10 +312,8 @@ struct PCNetState_st
PTMTIMERRC pTimerPollRC;
#endif
-//#if HC_ARCH_BITS == 64
+ /** Alignment padding. */
uint32_t Alignment1;
-//#endif
-
/** Register Address Pointer */
uint32_t u32RAP;
/** Internal interrupt service */
@@ -201,7 +333,6 @@ struct PCNetState_st
* guest to clear any of these bits (by writing a ONE) before a bit was
* seen by the guest. */
uint16_t u16CSR0LastSeenByGuest;
- uint16_t Alignment2[HC_ARCH_BITS == 32 ? 2 : 2];
/** Last time we polled the queues */
uint64_t u64LastPoll;
@@ -210,8 +341,8 @@ struct PCNetState_st
/** The recv buffer. */
uint8_t abRecvBuf[4096];
- /** Unused / padding. */
- uint32_t u32Unused;
+ /** Alignment padding. */
+ uint32_t Alignment2;
/** Size of a RX/TX descriptor (8 or 16 bytes according to SWSTYLE */
int iLog2DescSize;
@@ -232,7 +363,7 @@ struct PCNetState_st
/** The configured MAC address. */
RTMAC MacConfigured;
/** Alignment padding. */
- uint8_t Alignment4[HC_ARCH_BITS == 64 ? 2 : 2];
+ uint8_t Alignment3[2];
/** The LED. */
PDMLED Led;
@@ -249,7 +380,8 @@ struct PCNetState_st
bool volatile fMaybeOutOfSpace;
/** True if we signal the guest that RX packets are missing. */
bool fSignalRxMiss;
- uint8_t Alignment5[HC_ARCH_BITS == 64 ? 2 : 6];
+ /** Alignment padding. */
+ uint8_t Alignment4[HC_ARCH_BITS == 64 ? 2 : 6];
#ifdef PCNET_NO_POLLING
RTGCPHYS32 TDRAPhysOld;
@@ -264,14 +396,19 @@ struct PCNetState_st
/** Error counter for bad receive descriptors. */
uint32_t uCntBadRMD;
-
- /** True if host and guest admitted to use the private interface. */
- bool fPrivIfEnabled;
+ /* True if raw context is enabled. */
bool fGCEnabled;
+ /* True if R0 context is enabled. */
bool fR0Enabled;
+ /* True: Emulate Am79C973. False: Emulate 79C970A. */
bool fAm79C973;
+ /* Link speed to be reported through CSR68. */
+ bool fSharedRegion;
+ /* Alignment padding. */
uint32_t u32LinkSpeed;
+ /* MS to wait before we enable the link. */
uint32_t cMsLinkUpDelay;
+ /* Alignment padding. */
uint32_t Alignment6;
STAMCOUNTER StatReceiveBytes;
@@ -327,129 +464,10 @@ struct PCNetState_st
STAMCOUNTER StatRingWriteOutsideRC;
# endif
#endif /* VBOX_WITH_STATISTICS */
-};
-//AssertCompileMemberAlignment(PCNetState, StatReceiveBytes, 8);
-
-#define PCNETSTATE_2_DEVINS(pPCNet) ((pPCNet)->CTX_SUFF(pDevIns))
-#define PCIDEV_2_PCNETSTATE(pPciDev) ((PCNetState *)(pPciDev))
-#define PCNET_INST_NR (PCNETSTATE_2_DEVINS(pThis)->iInstance)
-
-/* BUS CONFIGURATION REGISTERS */
-#define BCR_MSRDA 0
-#define BCR_MSWRA 1
-#define BCR_MC 2
-#define BCR_RESERVED3 3
-#define BCR_LNKST 4
-#define BCR_LED1 5
-#define BCR_LED2 6
-#define BCR_LED3 7
-#define BCR_RESERVED8 8
-#define BCR_FDC 9
-/* 10 - 15 = reserved */
-#define BCR_IOBASEL 16 /* Reserved */
-#define BCR_IOBASEU 16 /* Reserved */
-#define BCR_BSBC 18
-#define BCR_EECAS 19
-#define BCR_SWS 20
-#define BCR_INTCON 21 /* Reserved */
-#define BCR_PLAT 22
-#define BCR_PCISVID 23
-#define BCR_PCISID 24
-#define BCR_SRAMSIZ 25
-#define BCR_SRAMB 26
-#define BCR_SRAMIC 27
-#define BCR_EBADDRL 28
-#define BCR_EBADDRU 29
-#define BCR_EBD 30
-#define BCR_STVAL 31
-#define BCR_MIICAS 32
-#define BCR_MIIADDR 33
-#define BCR_MIIMDR 34
-#define BCR_PCIVID 35
-#define BCR_PMC_A 36
-#define BCR_DATA0 37
-#define BCR_DATA1 38
-#define BCR_DATA2 39
-#define BCR_DATA3 40
-#define BCR_DATA4 41
-#define BCR_DATA5 42
-#define BCR_DATA6 43
-#define BCR_DATA7 44
-#define BCR_PMR1 45
-#define BCR_PMR2 46
-#define BCR_PMR3 47
-
-#define BCR_DWIO(S) !!((S)->aBCR[BCR_BSBC] & 0x0080)
-#define BCR_SSIZE32(S) !!((S)->aBCR[BCR_SWS ] & 0x0100)
-#define BCR_SWSTYLE(S) ((S)->aBCR[BCR_SWS ] & 0x00FF)
-
-#define CSR_INIT(S) !!((S)->aCSR[0] & 0x0001) /**< Init assertion */
-#define CSR_STRT(S) !!((S)->aCSR[0] & 0x0002) /**< Start assertion */
-#define CSR_STOP(S) !!((S)->aCSR[0] & 0x0004) /**< Stop assertion */
-#define CSR_TDMD(S) !!((S)->aCSR[0] & 0x0008) /**< Transmit demand. (perform xmit poll now (readable, settable, not clearable) */
-#define CSR_TXON(S) !!((S)->aCSR[0] & 0x0010) /**< Transmit on (readonly) */
-#define CSR_RXON(S) !!((S)->aCSR[0] & 0x0020) /**< Receive On */
-#define CSR_INEA(S) !!((S)->aCSR[0] & 0x0040) /**< Interrupt Enable */
-#define CSR_LAPPEN(S) !!((S)->aCSR[3] & 0x0020) /**< Look Ahead Packet Processing Enable */
-#define CSR_DXSUFLO(S) !!((S)->aCSR[3] & 0x0040) /**< Disable Transmit Stop on Underflow error */
-#define CSR_ASTRP_RCV(S) !!((S)->aCSR[4] & 0x0400) /**< Auto Strip Receive */
-#define CSR_DPOLL(S) !!((S)->aCSR[4] & 0x1000) /**< Disable Transmit Polling */
-#define CSR_SPND(S) !!((S)->aCSR[5] & 0x0001) /**< Suspend */
-#define CSR_LTINTEN(S) !!((S)->aCSR[5] & 0x4000) /**< Last Transmit Interrupt Enable */
-#define CSR_TOKINTD(S) !!((S)->aCSR[5] & 0x8000) /**< Transmit OK Interrupt Disable */
-
-#define CSR_STINT !!((S)->aCSR[7] & 0x0800) /**< Software Timer Interrupt */
-#define CSR_STINTE !!((S)->aCSR[7] & 0x0400) /**< Software Timer Interrupt Enable */
-
-#define CSR_DRX(S) !!((S)->aCSR[15] & 0x0001) /**< Disable Receiver */
-#define CSR_DTX(S) !!((S)->aCSR[15] & 0x0002) /**< Disable Transmit */
-#define CSR_LOOP(S) !!((S)->aCSR[15] & 0x0004) /**< Loopback Enable */
-#define CSR_DRCVPA(S) !!((S)->aCSR[15] & 0x2000) /**< Disable Receive Physical Address */
-#define CSR_DRCVBC(S) !!((S)->aCSR[15] & 0x4000) /**< Disable Receive Broadcast */
-#define CSR_PROM(S) !!((S)->aCSR[15] & 0x8000) /**< Promiscuous Mode */
-
-#if !defined(RT_ARCH_X86) && !defined(RT_ARCH_AMD64)
-#error fix macros (and more in this file) for big-endian machines
-#endif
-
-#define CSR_IADR(S) (*(uint32_t*)((S)->aCSR + 1)) /**< Initialization Block Address */
-#define CSR_CRBA(S) (*(uint32_t*)((S)->aCSR + 18)) /**< Current Receive Buffer Address */
-#define CSR_CXBA(S) (*(uint32_t*)((S)->aCSR + 20)) /**< Current Transmit Buffer Address */
-#define CSR_NRBA(S) (*(uint32_t*)((S)->aCSR + 22)) /**< Next Receive Buffer Address */
-#define CSR_BADR(S) (*(uint32_t*)((S)->aCSR + 24)) /**< Base Address of Receive Ring */
-#define CSR_NRDA(S) (*(uint32_t*)((S)->aCSR + 26)) /**< Next Receive Descriptor Address */
-#define CSR_CRDA(S) (*(uint32_t*)((S)->aCSR + 28)) /**< Current Receive Descriptor Address */
-#define CSR_BADX(S) (*(uint32_t*)((S)->aCSR + 30)) /**< Base Address of Transmit Descriptor */
-#define CSR_NXDA(S) (*(uint32_t*)((S)->aCSR + 32)) /**< Next Transmit Descriptor Address */
-#define CSR_CXDA(S) (*(uint32_t*)((S)->aCSR + 34)) /**< Current Transmit Descriptor Address */
-#define CSR_NNRD(S) (*(uint32_t*)((S)->aCSR + 36)) /**< Next Next Receive Descriptor Address */
-#define CSR_NNXD(S) (*(uint32_t*)((S)->aCSR + 38)) /**< Next Next Transmit Descriptor Address */
-#define CSR_CRBC(S) ((S)->aCSR[40]) /**< Current Receive Byte Count */
-#define CSR_CRST(S) ((S)->aCSR[41]) /**< Current Receive Status */
-#define CSR_CXBC(S) ((S)->aCSR[42]) /**< Current Transmit Byte Count */
-#define CSR_CXST(S) ((S)->aCSR[43]) /**< Current transmit status */
-#define CSR_NRBC(S) ((S)->aCSR[44]) /**< Next Receive Byte Count */
-#define CSR_NRST(S) ((S)->aCSR[45]) /**< Next Receive Status */
-#define CSR_POLL(S) ((S)->aCSR[46]) /**< Transmit Poll Time Counter */
-#define CSR_PINT(S) ((S)->aCSR[47]) /**< Transmit Polling Interval */
-#define CSR_PXDA(S) (*(uint32_t*)((S)->aCSR + 60)) /**< Previous Transmit Descriptor Address*/
-#define CSR_PXBC(S) ((S)->aCSR[62]) /**< Previous Transmit Byte Count */
-#define CSR_PXST(S) ((S)->aCSR[63]) /**< Previous Transmit Status */
-#define CSR_NXBA(S) (*(uint32_t*)((S)->aCSR + 64)) /**< Next Transmit Buffer Address */
-#define CSR_NXBC(S) ((S)->aCSR[66]) /**< Next Transmit Byte Count */
-#define CSR_NXST(S) ((S)->aCSR[67]) /**< Next Transmit Status */
-#define CSR_RCVRC(S) ((S)->aCSR[72]) /**< Receive Descriptor Ring Counter */
-#define CSR_XMTRC(S) ((S)->aCSR[74]) /**< Transmit Descriptor Ring Counter */
-#define CSR_RCVRL(S) ((S)->aCSR[76]) /**< Receive Descriptor Ring Length */
-#define CSR_XMTRL(S) ((S)->aCSR[78]) /**< Transmit Descriptor Ring Length */
-#define CSR_MISSC(S) ((S)->aCSR[112]) /**< Missed Frame Count */
-
-#define PHYSADDR(S,A) ((A) | (S)->GCUpperPhys)
-
-/* Version for the PCnet/FAST III 79C973 card */
-#define CSR_VERSION_LOW_79C973 0x5003 /* the lower two bits must be 11b for AMD */
-#define CSR_VERSION_LOW_79C970A 0x1003 /* the lower two bits must be 11b for AMD */
-#define CSR_VERSION_HIGH 0x0262
+} PCNETSTATE;
+//AssertCompileMemberAlignment(PCNETSTATE, StatReceiveBytes, 8);
+/** Pointer to a PC-Net state structure. */
+typedef PCNETSTATE *PPCNETSTATE;
/** @todo All structs: big endian? */
@@ -612,8 +630,8 @@ AssertCompileSize(RMD, 16);
(R)->rmd2.rcc, (R)->rmd2.rpc, (R)->rmd2.mcnt, \
(R)->rmd2.zeros))
-static void pcnetPollTimerStart(PCNetState *pThis);
-static int pcnetXmitPending(PCNetState *pThis, bool fOnWorkerThread);
+static void pcnetPollTimerStart(PPCNETSTATE pThis);
+static int pcnetXmitPending(PPCNETSTATE pThis, bool fOnWorkerThread);
@@ -622,7 +640,7 @@ static int pcnetXmitPending(PCNetState *pThis, bool fOnWorkerThread);
* @returns true if the link is up.
* @returns false if the link is down.
*/
-DECLINLINE(bool) pcnetIsLinkUp(PCNetState *pThis)
+DECLINLINE(bool) pcnetIsLinkUp(PPCNETSTATE pThis)
{
return pThis->pDrvR3 && !pThis->fLinkTempDown && pThis->fLinkUp;
}
@@ -636,23 +654,12 @@ DECLINLINE(bool) pcnetIsLinkUp(PCNetState *pThis)
* @param fRetIfNotOwn return immediately after reading the own flag if we don't own the descriptor
* @return true if we own the descriptor, false otherwise
*/
-DECLINLINE(bool) pcnetTmdLoad(PCNetState *pThis, TMD *tmd, RTGCPHYS32 addr, bool fRetIfNotOwn)
+DECLINLINE(bool) pcnetTmdLoad(PPCNETSTATE pThis, TMD *tmd, RTGCPHYS32 addr, bool fRetIfNotOwn)
{
PPDMDEVINS pDevIns = PCNETSTATE_2_DEVINS(pThis);
uint8_t ownbyte;
- if (pThis->fPrivIfEnabled)
- {
- /* RX/TX descriptors shared between host and guest => direct copy */
- uint8_t *pv = (uint8_t*)pThis->CTX_SUFF(pSharedMMIO)
- + (addr - pThis->GCTDRA)
- + pThis->CTX_SUFF(pSharedMMIO)->V.V1.offTxDescriptors;
- if (!(pv[7] & 0x80) && fRetIfNotOwn)
- return false;
- memcpy(tmd, pv, 16);
- return true;
- }
- else if (RT_UNLIKELY(BCR_SWSTYLE(pThis) == 0))
+ if (RT_UNLIKELY(BCR_SWSTYLE(pThis) == 0))
{
uint16_t xda[4];
@@ -699,20 +706,11 @@ DECLINLINE(bool) pcnetTmdLoad(PCNetState *pThis, TMD *tmd, RTGCPHYS32 addr, bool
* Store transmit message descriptor and hand it over to the host (the VM guest).
* Make sure that all data are transmitted before we clear the own flag.
*/
-DECLINLINE(void) pcnetTmdStorePassHost(PCNetState *pThis, TMD *tmd, RTGCPHYS32 addr)
+DECLINLINE(void) pcnetTmdStorePassHost(PPCNETSTATE pThis, TMD *tmd, RTGCPHYS32 addr)
{
STAM_PROFILE_ADV_START(&pThis->CTX_SUFF_Z(StatTmdStore), a);
PPDMDEVINS pDevIns = PCNETSTATE_2_DEVINS(pThis);
- if (pThis->fPrivIfEnabled)
- {
- /* RX/TX descriptors shared between host and guest => direct copy */
- uint8_t *pv = (uint8_t*)pThis->CTX_SUFF(pSharedMMIO)
- + (addr - pThis->GCTDRA)
- + pThis->CTX_SUFF(pSharedMMIO)->V.V1.offTxDescriptors;
- memcpy(pv, tmd, 16);
- pv[7] &= ~0x80;
- }
- else if (RT_UNLIKELY(BCR_SWSTYLE(pThis) == 0))
+ if (RT_UNLIKELY(BCR_SWSTYLE(pThis) == 0))
{
uint16_t xda[4];
xda[0] = ((uint32_t *)tmd)[0] & 0xffff;
@@ -720,16 +718,16 @@ DECLINLINE(void) pcnetTmdStorePassHost(PCNetState *pThis, TMD *tmd, RTGCPHYS32 a
xda[2] = ((uint32_t *)tmd)[1] & 0xffff;
xda[3] = ((uint32_t *)tmd)[2] >> 16;
xda[1] |= 0x8000;
- PDMDevHlpPhysWrite(pDevIns, addr, (void*)&xda[0], sizeof(xda));
+ PDMDevHlpPCIPhysWrite(pDevIns, addr, (void*)&xda[0], sizeof(xda));
xda[1] &= ~0x8000;
- PDMDevHlpPhysWrite(pDevIns, addr+3, (uint8_t*)xda + 3, 1);
+ PDMDevHlpPCIPhysWrite(pDevIns, addr+3, (uint8_t*)xda + 3, 1);
}
else if (RT_LIKELY(BCR_SWSTYLE(pThis) != 3))
{
((uint32_t*)tmd)[1] |= 0x80000000;
- PDMDevHlpPhysWrite(pDevIns, addr, (void*)tmd, 16);
+ PDMDevHlpPCIPhysWrite(pDevIns, addr, (void*)tmd, 16);
((uint32_t*)tmd)[1] &= ~0x80000000;
- PDMDevHlpPhysWrite(pDevIns, addr+7, (uint8_t*)tmd + 7, 1);
+ PDMDevHlpPCIPhysWrite(pDevIns, addr+7, (uint8_t*)tmd + 7, 1);
}
else
{
@@ -739,9 +737,9 @@ DECLINLINE(void) pcnetTmdStorePassHost(PCNetState *pThis, TMD *tmd, RTGCPHYS32 a
xda[2] = ((uint32_t *)tmd)[0];
xda[3] = ((uint32_t *)tmd)[3];
xda[1] |= 0x80000000;
- PDMDevHlpPhysWrite(pDevIns, addr, (void*)&xda[0], sizeof(xda));
+ PDMDevHlpPCIPhysWrite(pDevIns, addr, (void*)&xda[0], sizeof(xda));
xda[1] &= ~0x80000000;
- PDMDevHlpPhysWrite(pDevIns, addr+7, (uint8_t*)xda + 7, 1);
+ PDMDevHlpPCIPhysWrite(pDevIns, addr+7, (uint8_t*)xda + 7, 1);
}
STAM_PROFILE_ADV_STOP(&pThis->CTX_SUFF_Z(StatTmdStore), a);
}
@@ -755,23 +753,12 @@ DECLINLINE(void) pcnetTmdStorePassHost(PCNetState *pThis, TMD *tmd, RTGCPHYS32 a
* @param fRetIfNotOwn return immediately after reading the own flag if we don't own the descriptor
* @return true if we own the descriptor, false otherwise
*/
-DECLINLINE(int) pcnetRmdLoad(PCNetState *pThis, RMD *rmd, RTGCPHYS32 addr, bool fRetIfNotOwn)
+DECLINLINE(int) pcnetRmdLoad(PPCNETSTATE pThis, RMD *rmd, RTGCPHYS32 addr, bool fRetIfNotOwn)
{
PPDMDEVINS pDevIns = PCNETSTATE_2_DEVINS(pThis);
uint8_t ownbyte;
- if (pThis->fPrivIfEnabled)
- {
- /* RX/TX descriptors shared between host and guest => direct copy */
- uint8_t *pb = (uint8_t*)pThis->CTX_SUFF(pSharedMMIO)
- + (addr - pThis->GCRDRA)
- + pThis->CTX_SUFF(pSharedMMIO)->V.V1.offRxDescriptors;
- if (!(pb[7] & 0x80) && fRetIfNotOwn)
- return false;
- memcpy(rmd, pb, 16);
- return true;
- }
- else if (RT_UNLIKELY(BCR_SWSTYLE(pThis) == 0))
+ if (RT_UNLIKELY(BCR_SWSTYLE(pThis) == 0))
{
uint16_t rda[4];
PDMDevHlpPhysRead(pDevIns, addr+3, &ownbyte, 1);
@@ -818,19 +805,10 @@ DECLINLINE(int) pcnetRmdLoad(PCNetState *pThis, RMD *rmd, RTGCPHYS32 addr, bool
* Store receive message descriptor and hand it over to the host (the VM guest).
* Make sure that all data are transmitted before we clear the own flag.
*/
-DECLINLINE(void) pcnetRmdStorePassHost(PCNetState *pThis, RMD *rmd, RTGCPHYS32 addr)
+DECLINLINE(void) pcnetRmdStorePassHost(PPCNETSTATE pThis, RMD *rmd, RTGCPHYS32 addr)
{
PPDMDEVINS pDevIns = PCNETSTATE_2_DEVINS(pThis);
- if (pThis->fPrivIfEnabled)
- {
- /* RX/TX descriptors shared between host and guest => direct copy */
- uint8_t *pv = (uint8_t*)pThis->CTX_SUFF(pSharedMMIO)
- + (addr - pThis->GCRDRA)
- + pThis->CTX_SUFF(pSharedMMIO)->V.V1.offRxDescriptors;
- memcpy(pv, rmd, 16);
- pv[7] &= ~0x80;
- }
- else if (RT_UNLIKELY(BCR_SWSTYLE(pThis) == 0))
+ if (RT_UNLIKELY(BCR_SWSTYLE(pThis) == 0))
{
uint16_t rda[4];
rda[0] = ((uint32_t *)rmd)[0] & 0xffff;
@@ -838,16 +816,16 @@ DECLINLINE(void) pcnetRmdStorePassHost(PCNetState *pThis, RMD *rmd, RTGCPHYS32 a
rda[2] = ((uint32_t *)rmd)[1] & 0xffff;
rda[3] = ((uint32_t *)rmd)[2] & 0xffff;
rda[1] |= 0x8000;
- PDMDevHlpPhysWrite(pDevIns, addr, (void*)&rda[0], sizeof(rda));
+ PDMDevHlpPCIPhysWrite(pDevIns, addr, (void*)&rda[0], sizeof(rda));
rda[1] &= ~0x8000;
- PDMDevHlpPhysWrite(pDevIns, addr+3, (uint8_t*)rda + 3, 1);
+ PDMDevHlpPCIPhysWrite(pDevIns, addr+3, (uint8_t*)rda + 3, 1);
}
else if (RT_LIKELY(BCR_SWSTYLE(pThis) != 3))
{
((uint32_t*)rmd)[1] |= 0x80000000;
- PDMDevHlpPhysWrite(pDevIns, addr, (void*)rmd, 16);
+ PDMDevHlpPCIPhysWrite(pDevIns, addr, (void*)rmd, 16);
((uint32_t*)rmd)[1] &= ~0x80000000;
- PDMDevHlpPhysWrite(pDevIns, addr+7, (uint8_t*)rmd + 7, 1);
+ PDMDevHlpPCIPhysWrite(pDevIns, addr+7, (uint8_t*)rmd + 7, 1);
}
else
{
@@ -857,32 +835,28 @@ DECLINLINE(void) pcnetRmdStorePassHost(PCNetState *pThis, RMD *rmd, RTGCPHYS32 a
rda[2] = ((uint32_t *)rmd)[0];
rda[3] = ((uint32_t *)rmd)[3];
rda[1] |= 0x80000000;
- PDMDevHlpPhysWrite(pDevIns, addr, (void*)&rda[0], sizeof(rda));
+ PDMDevHlpPCIPhysWrite(pDevIns, addr, (void*)&rda[0], sizeof(rda));
rda[1] &= ~0x80000000;
- PDMDevHlpPhysWrite(pDevIns, addr+7, (uint8_t*)rda + 7, 1);
+ PDMDevHlpPCIPhysWrite(pDevIns, addr+7, (uint8_t*)rda + 7, 1);
}
}
#ifdef IN_RING3
/**
- * Read+Write a TX/RX descriptor to prevent PDMDevHlpPhysWrite() allocating
+ * Read+Write a TX/RX descriptor to prevent PDMDevHlpPCIPhysWrite() allocating
* pages later when we shouldn't schedule to EMT. Temporarily hack.
*/
-static void pcnetDescTouch(PCNetState *pThis, RTGCPHYS32 addr)
+static void pcnetDescTouch(PPCNETSTATE pThis, RTGCPHYS32 addr)
{
PPDMDEVINS pDevIns = PCNETSTATE_2_DEVINS(pThis);
-
- if (!pThis->fPrivIfEnabled)
- {
- uint8_t aBuf[16];
- size_t cbDesc;
- if (RT_UNLIKELY(BCR_SWSTYLE(pThis) == 0))
- cbDesc = 8;
- else
- cbDesc = 16;
- PDMDevHlpPhysRead(pDevIns, addr, aBuf, cbDesc);
- PDMDevHlpPhysWrite(pDevIns, addr, aBuf, cbDesc);
- }
+ uint8_t aBuf[16];
+ size_t cbDesc;
+ if (RT_UNLIKELY(BCR_SWSTYLE(pThis) == 0))
+ cbDesc = 8;
+ else
+ cbDesc = 16;
+ PDMDevHlpPhysRead(pDevIns, addr, aBuf, cbDesc);
+ PDMDevHlpPCIPhysWrite(pDevIns, addr, aBuf, cbDesc);
}
#endif /* IN_RING3 */
@@ -924,52 +898,6 @@ struct ether_header /** @todo Use RTNETETHERHDR */
} while (0)
-#ifdef IN_RING3
-/**
- * Initialize the shared memory for the private guest interface.
- *
- * @note Changing this layout will break SSM for guests using the private guest interface!
- */
-static void pcnetInitSharedMemory(PCNetState *pThis)
-{
- /* Clear the entire block for pcnetReset usage. */
- memset(pThis->pSharedMMIOR3, 0, PCNET_GUEST_SHARED_MEMORY_SIZE);
-
- pThis->pSharedMMIOR3->u32Version = PCNET_GUEST_INTERFACE_VERSION;
- uint32_t off = 2048; /* Leave some space for more fields within the header */
-
- /*
- * The Descriptor arrays.
- */
- pThis->pSharedMMIOR3->V.V1.offTxDescriptors = off;
- off = RT_ALIGN(off + PCNET_GUEST_TX_DESCRIPTOR_SIZE * PCNET_GUEST_MAX_TX_DESCRIPTORS, 32);
-
- pThis->pSharedMMIOR3->V.V1.offRxDescriptors = off;
- off = RT_ALIGN(off + PCNET_GUEST_RX_DESCRIPTOR_SIZE * PCNET_GUEST_MAX_RX_DESCRIPTORS, 32);
-
- /* Make sure all the descriptors are mapped into HMA space (and later ring-0). The 8192
- bytes limit is hardcoded in the PDMDevHlpMMHyperMapMMIO2 call down in pcnetConstruct. */
- AssertRelease(off <= 8192);
-
- /*
- * The buffer arrays.
- */
-#if 0
- /* Don't allocate TX buffers since Windows guests cannot use it */
- pThis->pSharedMMIOR3->V.V1.offTxBuffers = off;
- off = RT_ALIGN(off + PCNET_GUEST_NIC_BUFFER_SIZE * PCNET_GUEST_MAX_TX_DESCRIPTORS, 32);
-#endif
-
- pThis->pSharedMMIOR3->V.V1.offRxBuffers = off;
- pThis->pSharedMMIOR3->fFlags = PCNET_GUEST_FLAGS_ADMIT_HOST;
- off = RT_ALIGN(off + PCNET_GUEST_NIC_BUFFER_SIZE * PCNET_GUEST_MAX_RX_DESCRIPTORS, 32);
- AssertRelease(off <= PCNET_GUEST_SHARED_MEMORY_SIZE);
-
- /* Update the header with the final size. */
- pThis->pSharedMMIOR3->cbUsed = off;
-}
-#endif /* IN_RING3 */
-
#define MULTICAST_FILTER_LEN 8
DECLINLINE(uint32_t) lnc_mchash(const uint8_t *ether_addr)
@@ -1065,7 +993,7 @@ static const uint32_t crctab[256] =
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
};
-DECLINLINE(int) padr_match(PCNetState *pThis, const uint8_t *buf, size_t size)
+DECLINLINE(int) padr_match(PPCNETSTATE pThis, const uint8_t *buf, size_t size)
{
struct ether_header *hdr = (struct ether_header *)buf;
int result;
@@ -1092,7 +1020,7 @@ DECLINLINE(int) padr_match(PCNetState *pThis, const uint8_t *buf, size_t size)
return result;
}
-DECLINLINE(int) padr_bcast(PCNetState *pThis, const uint8_t *buf, size_t size)
+DECLINLINE(int) padr_bcast(PPCNETSTATE pThis, const uint8_t *buf, size_t size)
{
static uint8_t aBCAST[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
struct ether_header *hdr = (struct ether_header *)buf;
@@ -1103,7 +1031,7 @@ DECLINLINE(int) padr_bcast(PCNetState *pThis, const uint8_t *buf, size_t size)
return result;
}
-static int ladr_match(PCNetState *pThis, const uint8_t *buf, size_t size)
+static int ladr_match(PPCNETSTATE pThis, const uint8_t *buf, size_t size)
{
struct ether_header *hdr = (struct ether_header *)buf;
if (RT_UNLIKELY(hdr->ether_dhost[0] & 0x01) && ((uint64_t *)&pThis->aCSR[8])[0] != 0LL)
@@ -1133,7 +1061,7 @@ static int ladr_match(PCNetState *pThis, const uint8_t *buf, size_t size)
/**
* Get the receive descriptor ring address with a given index.
*/
-DECLINLINE(RTGCPHYS32) pcnetRdraAddr(PCNetState *pThis, int idx)
+DECLINLINE(RTGCPHYS32) pcnetRdraAddr(PPCNETSTATE pThis, int idx)
{
return pThis->GCRDRA + ((CSR_RCVRL(pThis) - idx) << pThis->iLog2DescSize);
}
@@ -1141,7 +1069,7 @@ DECLINLINE(RTGCPHYS32) pcnetRdraAddr(PCNetState *pThis, int idx)
/**
* Get the transmit descriptor ring address with a given index.
*/
-DECLINLINE(RTGCPHYS32) pcnetTdraAddr(PCNetState *pThis, int idx)
+DECLINLINE(RTGCPHYS32) pcnetTdraAddr(PPCNETSTATE pThis, int idx)
{
return pThis->GCTDRA + ((CSR_XMTRL(pThis) - idx) << pThis->iLog2DescSize);
}
@@ -1158,11 +1086,11 @@ RT_C_DECLS_END
#undef htons
#define htons(x) ( (((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8) )
-static void pcnetPollRxTx(PCNetState *pThis);
-static void pcnetPollTimer(PCNetState *pThis);
-static void pcnetUpdateIrq(PCNetState *pThis);
-static uint32_t pcnetBCRReadU16(PCNetState *pThis, uint32_t u32RAP);
-static int pcnetBCRWriteU16(PCNetState *pThis, uint32_t u32RAP, uint32_t val);
+static void pcnetPollRxTx(PPCNETSTATE pThis);
+static void pcnetPollTimer(PPCNETSTATE pThis);
+static void pcnetUpdateIrq(PPCNETSTATE pThis);
+static uint32_t pcnetBCRReadU16(PPCNETSTATE pThis, uint32_t u32RAP);
+static int pcnetBCRWriteU16(PPCNETSTATE pThis, uint32_t u32RAP, uint32_t val);
#ifdef PCNET_NO_POLLING
@@ -1182,7 +1110,7 @@ static int pcnetBCRWriteU16(PCNetState *pThis, uint32_t u32RAP, uint32_t va
DECLEXPORT(int) pcnetHandleRingWrite(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame,
RTGCPTR pvFault, RTGCPHYS GCPhysFault, void *pvUser)
{
- PCNetState *pThis = (PCNetState *)pvUser;
+ PPCNETSTATE pThis = (PPCNETSTATE)pvUser;
Log(("#%d pcnetHandleRingWriteGC: write to %#010x\n", PCNET_INST_NR, GCPhysFault));
@@ -1243,7 +1171,7 @@ static DECLCALLBACK(int) pcnetHandleRingWrite(PVM pVM, RTGCPHYS GCPhys, void *pv
size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser)
{
PPDMDEVINS pDevIns = (PPDMDEVINS)pvUser;
- PCNetState *pThis = PDMINS_2_DATA(pDevIns, PCNetState *);
+ PPCNETSTATE pThis = PDMINS_2_DATA(pDevIns, PPCNETSTATE);
Log(("#%d pcnetHandleRingWrite: write to %#010x\n", PCNET_INST_NR, GCPhys));
#ifdef VBOX_WITH_STATISTICS
@@ -1278,7 +1206,7 @@ static DECLCALLBACK(int) pcnetHandleRingWrite(PVM pVM, RTGCPHYS GCPhys, void *pv
# endif /* !IN_RING3 */
#endif /* PCNET_NO_POLLING */
-static void pcnetSoftReset(PCNetState *pThis)
+static void pcnetSoftReset(PPCNETSTATE pThis)
{
Log(("#%d pcnetSoftReset:\n", PCNET_INST_NR));
@@ -1323,7 +1251,7 @@ static void pcnetSoftReset(PCNetState *pThis)
* - csr4 (only written by pcnetSoftReset(), pcnetStop() or by the guest driver)
* - csr5 (only written by pcnetSoftReset(), pcnetStop or by the driver guest)
*/
-static void pcnetUpdateIrq(PCNetState *pThis)
+static void pcnetUpdateIrq(PPCNETSTATE pThis)
{
register int iISR = 0;
register uint16_t csr0 = pThis->aCSR[0];
@@ -1409,23 +1337,9 @@ static void pcnetUpdateIrq(PCNetState *pThis)
STAM_PROFILE_ADV_STOP(&pThis->StatInterrupt, a);
}
-/**
- * Enable/disable the private guest interface.
- */
-static void pcnetEnablePrivateIf(PCNetState *pThis)
-{
- bool fPrivIfEnabled = pThis->pSharedMMIOR3
- && !!(pThis->CTX_SUFF(pSharedMMIO)->fFlags & PCNET_GUEST_FLAGS_ADMIT_GUEST);
- if (fPrivIfEnabled != pThis->fPrivIfEnabled)
- {
- pThis->fPrivIfEnabled = fPrivIfEnabled;
- LogRel(("PCNet#%d: %s private interface\n", PCNET_INST_NR, fPrivIfEnabled ? "Enabling" : "Disabling"));
- }
-}
-
#ifdef IN_RING3
#ifdef PCNET_NO_POLLING
-static void pcnetUpdateRingHandlers(PCNetState *pThis)
+static void pcnetUpdateRingHandlers(PPCNETSTATE pThis)
{
PPDMDEVINS pDevIns = PCNETSTATE_2_DEVINS(pThis);
int rc;
@@ -1513,7 +1427,7 @@ static void pcnetUpdateRingHandlers(PCNetState *pThis)
}
#endif /* PCNET_NO_POLLING */
-static void pcnetInit(PCNetState *pThis)
+static void pcnetInit(PPCNETSTATE pThis)
{
PPDMDEVINS pDevIns = PCNETSTATE_2_DEVINS(pThis);
Log(("#%d pcnetInit: init_addr=%#010x\n", PCNET_INST_NR, PHYSADDR(pThis, CSR_IADR(pThis))));
@@ -1538,8 +1452,6 @@ static void pcnetInit(PCNetState *pThis)
pThis->GCTDRA = PHYSADDR(pThis, initblk.tdra); \
} while (0)
- pcnetEnablePrivateIf(pThis);
-
if (BCR_SSIZE32(pThis))
{
struct INITBLK32 initblk;
@@ -1618,14 +1530,13 @@ static void pcnetInit(PCNetState *pThis)
/**
* Start RX/TX operation.
*/
-static void pcnetStart(PCNetState *pThis)
+static void pcnetStart(PPCNETSTATE pThis)
{
Log(("#%d pcnetStart:\n", PCNET_INST_NR));
if (!CSR_DTX(pThis))
pThis->aCSR[0] |= 0x0010; /* set TXON */
if (!CSR_DRX(pThis))
pThis->aCSR[0] |= 0x0020; /* set RXON */
- pcnetEnablePrivateIf(pThis);
pThis->aCSR[0] &= ~0x0004; /* clear STOP bit */
pThis->aCSR[0] |= 0x0002; /* STRT */
pcnetPollTimerStart(pThis); /* start timer if it was stopped */
@@ -1634,21 +1545,20 @@ static void pcnetStart(PCNetState *pThis)
/**
* Stop RX/TX operation.
*/
-static void pcnetStop(PCNetState *pThis)
+static void pcnetStop(PPCNETSTATE pThis)
{
Log(("#%d pcnetStop:\n", PCNET_INST_NR));
pThis->aCSR[0] &= ~0x7feb;
pThis->aCSR[0] |= 0x0014;
pThis->aCSR[4] &= ~0x02c2;
pThis->aCSR[5] &= ~0x0011;
- pcnetEnablePrivateIf(pThis);
pcnetPollTimer(pThis);
}
#ifdef IN_RING3
static DECLCALLBACK(void) pcnetWakeupReceive(PPDMDEVINS pDevIns)
{
- PCNetState *pThis = PDMINS_2_DATA(pDevIns, PCNetState *);
+ PPCNETSTATE pThis = PDMINS_2_DATA(pDevIns, PPCNETSTATE);
STAM_COUNTER_INC(&pThis->StatRxOverflowWakeup);
if (pThis->hEventOutOfRxSpace != NIL_RTSEMEVENT)
RTSemEventSignal(pThis->hEventOutOfRxSpace);
@@ -1669,7 +1579,7 @@ static DECLCALLBACK(bool) pcnetCanRxQueueConsumer(PPDMDEVINS pDevIns, PPDMQUEUEI
* definition.
* @param fSkipCurrent if true, don't scan the current RDTE.
*/
-static void pcnetRdtePoll(PCNetState *pThis, bool fSkipCurrent=false)
+static void pcnetRdtePoll(PPCNETSTATE pThis, bool fSkipCurrent=false)
{
STAM_PROFILE_ADV_START(&pThis->CTX_SUFF_Z(StatRdtePoll), a);
/* assume lack of a next receive descriptor */
@@ -1777,7 +1687,7 @@ static void pcnetRdtePoll(PCNetState *pThis, bool fSkipCurrent=false)
* Poll Transmit Descriptor Table Entry
* @return true if transmit descriptors available
*/
-static int pcnetTdtePoll(PCNetState *pThis, TMD *tmd)
+static int pcnetTdtePoll(PPCNETSTATE pThis, TMD *tmd)
{
STAM_PROFILE_ADV_START(&pThis->CTX_SUFF_Z(StatTdtePoll), a);
if (RT_LIKELY(pThis->GCTDRA))
@@ -1825,7 +1735,7 @@ static int pcnetTdtePoll(PCNetState *pThis, TMD *tmd)
* Poll Transmit Descriptor Table Entry
* @return true if transmit descriptors available
*/
-static int pcnetCalcPacketLen(PCNetState *pThis, unsigned cb)
+static int pcnetCalcPacketLen(PPCNETSTATE pThis, unsigned cb)
{
TMD tmd;
unsigned cbPacket = cb;
@@ -1873,7 +1783,7 @@ static int pcnetCalcPacketLen(PCNetState *pThis, unsigned cb)
/**
* Write data into guest receive buffers.
*/
-static void pcnetReceiveNoSync(PCNetState *pThis, const uint8_t *buf, size_t cbToRecv, bool fAddFCS)
+static void pcnetReceiveNoSync(PPCNETSTATE pThis, const uint8_t *buf, size_t cbToRecv, bool fAddFCS)
{
PPDMDEVINS pDevIns = PCNETSTATE_2_DEVINS(pThis);
int is_padr = 0, is_bcast = 0, is_ladr = 0;
@@ -1913,8 +1823,7 @@ static void pcnetReceiveNoSync(PCNetState *pThis, const uint8_t *buf, size_t cbT
{
/* Not owned by controller. This should not be possible as
* we already called pcnetCanReceive(). */
- LogRel(("PCNet#%d: no buffer: RCVRC=%d\n",
- PCNET_INST_NR, CSR_RCVRC(pThis)));
+ LogRel(("PCNet#%d: no buffer: RCVRC=%d\n", PCNET_INST_NR, CSR_RCVRC(pThis)));
/* Dump the status of all RX descriptors */
const unsigned cb = 1 << pThis->iLog2DescSize;
RTGCPHYS32 GCPhys = pThis->GCRDRA;
@@ -1980,7 +1889,7 @@ static void pcnetReceiveNoSync(PCNetState *pThis, const uint8_t *buf, size_t cbT
* - we don't cache any register state beyond this point
*/
PDMCritSectLeave(&pThis->CritSect);
- PDMDevHlpPhysWrite(pDevIns, rbadr, src, cbBuf);
+ PDMDevHlpPCIPhysWrite(pDevIns, rbadr, src, cbBuf);
int rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY);
AssertReleaseRC(rc);
@@ -2027,7 +1936,7 @@ static void pcnetReceiveNoSync(PCNetState *pThis, const uint8_t *buf, size_t cbT
* with EMT when the write is to an unallocated page or has an access
* handler associated with it. See above for additional comments. */
PDMCritSectLeave(&pThis->CritSect);
- PDMDevHlpPhysWrite(pDevIns, rbadr2, src, cbBuf);
+ PDMDevHlpPCIPhysWrite(pDevIns, rbadr2, src, cbBuf);
rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY);
AssertReleaseRC(rc);
@@ -2102,7 +2011,7 @@ static void pcnetReceiveNoSync(PCNetState *pThis, const uint8_t *buf, size_t cbT
*/
static DECLCALLBACK(bool) pcnetXmitQueueConsumer(PPDMDEVINS pDevIns, PPDMQUEUEITEMCORE pItem)
{
- PCNetState *pThis = PDMINS_2_DATA(pDevIns, PCNetState *);
+ PPCNETSTATE pThis = PDMINS_2_DATA(pDevIns, PPCNETSTATE);
NOREF(pItem);
/*
@@ -2125,7 +2034,7 @@ static DECLCALLBACK(bool) pcnetXmitQueueConsumer(PPDMDEVINS pDevIns, PPDMQUEUEIT
* @param ppSgBuf Where to return the SG buffer descriptor on success.
* Always set.
*/
-DECLINLINE(int) pcnetXmitAllocBuf(PCNetState *pThis, size_t cbMin, bool fLoopback,
+DECLINLINE(int) pcnetXmitAllocBuf(PPCNETSTATE pThis, size_t cbMin, bool fLoopback,
PPDMSCATTERGATHER pSgLoop, PPPDMSCATTERGATHER ppSgBuf)
{
int rc;
@@ -2170,7 +2079,7 @@ DECLINLINE(int) pcnetXmitAllocBuf(PCNetState *pThis, size_t cbMin, bool fLoopbac
* @param fLoopback Set if we're in loopback mode.
* @param pSgBuf The SG to free. Can be NULL.
*/
-DECLINLINE(void) pcnetXmitFreeBuf(PCNetState *pThis, bool fLoopback, PPDMSCATTERGATHER pSgBuf)
+DECLINLINE(void) pcnetXmitFreeBuf(PPCNETSTATE pThis, bool fLoopback, PPDMSCATTERGATHER pSgBuf)
{
if (pSgBuf)
{
@@ -2198,7 +2107,7 @@ DECLINLINE(void) pcnetXmitFreeBuf(PCNetState *pThis, bool fLoopback, PPDMSCATTER
* @param fOnWorkerThread Set if we're being called on a work thread. Clear
* if an EMT.
*/
-DECLINLINE(int) pcnetXmitSendBuf(PCNetState *pThis, bool fLoopback, PPDMSCATTERGATHER pSgBuf, bool fOnWorkerThread)
+DECLINLINE(int) pcnetXmitSendBuf(PPCNETSTATE pThis, bool fLoopback, PPDMSCATTERGATHER pSgBuf, bool fOnWorkerThread)
{
int rc;
STAM_REL_COUNTER_ADD(&pThis->StatTransmitBytes, pSgBuf->cbUsed);
@@ -2243,7 +2152,7 @@ DECLINLINE(int) pcnetXmitSendBuf(PCNetState *pThis, bool fLoopback, PPDMSCATTERG
* pcnetXmitRead1st worker that handles the unlikely + slower segmented code
* path.
*/
-static void pcnetXmitRead1stSlow(PCNetState *pThis, RTGCPHYS32 GCPhysFrame, unsigned cbFrame,
+static void pcnetXmitRead1stSlow(PPCNETSTATE pThis, RTGCPHYS32 GCPhysFrame, unsigned cbFrame,
PPDMSCATTERGATHER pSgBuf)
{
AssertFailed(); /* This path is not supposed to be taken atm */
@@ -2266,7 +2175,7 @@ static void pcnetXmitRead1stSlow(PCNetState *pThis, RTGCPHYS32 GCPhysFrame, unsi
* pcnetXmitSgReadMore worker that handles the unlikely + slower segmented code
* path.
*/
-static void pcnetXmitReadMoreSlow(PCNetState *pThis, RTGCPHYS32 GCPhysFrame, unsigned cbFrame,
+static void pcnetXmitReadMoreSlow(PPCNETSTATE pThis, RTGCPHYS32 GCPhysFrame, unsigned cbFrame,
PPDMSCATTERGATHER pSgBuf)
{
AssertFailed(); /* This path is not supposed to be taken atm */
@@ -2317,7 +2226,7 @@ static void pcnetXmitReadMoreSlow(PCNetState *pThis, RTGCPHYS32 GCPhysFrame, uns
/**
* Reads the first part of a frame into the scatter gather buffer.
*/
-DECLINLINE(void) pcnetXmitRead1st(PCNetState *pThis, RTGCPHYS32 GCPhysFrame, const unsigned cbFrame,
+DECLINLINE(void) pcnetXmitRead1st(PPCNETSTATE pThis, RTGCPHYS32 GCPhysFrame, const unsigned cbFrame,
PPDMSCATTERGATHER pSgBuf)
{
Assert(PDMCritSectIsOwner(&pThis->CritSect));
@@ -2335,7 +2244,7 @@ DECLINLINE(void) pcnetXmitRead1st(PCNetState *pThis, RTGCPHYS32 GCPhysFrame, con
/**
* Reads more into the current frame.
*/
-DECLINLINE(void) pcnetXmitReadMore(PCNetState *pThis, RTGCPHYS32 GCPhysFrame, const unsigned cbFrame,
+DECLINLINE(void) pcnetXmitReadMore(PPCNETSTATE pThis, RTGCPHYS32 GCPhysFrame, const unsigned cbFrame,
PPDMSCATTERGATHER pSgBuf)
{
size_t off = pSgBuf->cbUsed;
@@ -2355,7 +2264,7 @@ DECLINLINE(void) pcnetXmitReadMore(PCNetState *pThis, RTGCPHYS32 GCPhysFrame, co
/**
* Fails a TMD with a link down error.
*/
-static void pcnetXmitFailTMDLinkDown(PCNetState *pThis, TMD *pTmd)
+static void pcnetXmitFailTMDLinkDown(PPCNETSTATE pThis, TMD *pTmd)
{
/* make carrier error - hope this is correct. */
pThis->cLinkDownReported++;
@@ -2369,7 +2278,7 @@ static void pcnetXmitFailTMDLinkDown(PCNetState *pThis, TMD *pTmd)
/**
* Fails a TMD with a generic error.
*/
-static void pcnetXmitFailTMDGeneric(PCNetState *pThis, TMD *pTmd)
+static void pcnetXmitFailTMDGeneric(PPCNETSTATE pThis, TMD *pTmd)
{
/* make carrier error - hope this is correct. */
pTmd->tmd2.lcar = pTmd->tmd1.err = 1;
@@ -2383,7 +2292,7 @@ static void pcnetXmitFailTMDGeneric(PCNetState *pThis, TMD *pTmd)
/**
* Try to transmit frames
*/
-static void pcnetTransmit(PCNetState *pThis)
+static void pcnetTransmit(PPCNETSTATE pThis)
{
if (RT_UNLIKELY(!CSR_TXON(pThis)))
{
@@ -2430,7 +2339,7 @@ static void pcnetTransmit(PCNetState *pThis)
*
* @threads TX or EMT.
*/
-static int pcnetAsyncTransmit(PCNetState *pThis, bool fOnWorkerThread)
+static int pcnetAsyncTransmit(PPCNETSTATE pThis, bool fOnWorkerThread)
{
Assert(PDMCritSectIsOwner(&pThis->CritSect));
@@ -2700,7 +2609,7 @@ static int pcnetAsyncTransmit(PCNetState *pThis, bool fOnWorkerThread)
* @param pThis The PCNet instance data.
* @param fOnWorkerThread Whether we're on a worker thread or on an EMT.
*/
-static int pcnetXmitPending(PCNetState *pThis, bool fOnWorkerThread)
+static int pcnetXmitPending(PPCNETSTATE pThis, bool fOnWorkerThread)
{
int rc = VINF_SUCCESS;
@@ -2741,7 +2650,7 @@ static int pcnetXmitPending(PCNetState *pThis, bool fOnWorkerThread)
/**
* Poll for changes in RX and TX descriptor rings.
*/
-static void pcnetPollRxTx(PCNetState *pThis)
+static void pcnetPollRxTx(PPCNETSTATE pThis)
{
if (CSR_RXON(pThis))
{
@@ -2765,7 +2674,7 @@ static void pcnetPollRxTx(PCNetState *pThis)
* Poll timer interval is fixed to 500Hz. Don't stop it.
* @thread EMT, TAP.
*/
-static void pcnetPollTimerStart(PCNetState *pThis)
+static void pcnetPollTimerStart(PPCNETSTATE pThis)
{
TMTimerSetMillies(pThis->CTX_SUFF(pTimerPoll), 2);
}
@@ -2775,7 +2684,7 @@ static void pcnetPollTimerStart(PCNetState *pThis)
* Update the poller timer.
* @thread EMT.
*/
-static void pcnetPollTimer(PCNetState *pThis)
+static void pcnetPollTimer(PPCNETSTATE pThis)
{
STAM_PROFILE_ADV_START(&pThis->StatPollTimer, a);
@@ -2836,7 +2745,7 @@ static void pcnetPollTimer(PCNetState *pThis)
}
-static int pcnetCSRWriteU16(PCNetState *pThis, uint32_t u32RAP, uint32_t val)
+static int pcnetCSRWriteU16(PPCNETSTATE pThis, uint32_t u32RAP, uint32_t val)
{
int rc = VINF_SUCCESS;
#ifdef PCNET_DEBUG_CSR
@@ -3048,7 +2957,7 @@ static uint32_t pcnetLinkSpd(uint32_t speed)
return (exp << 13) | speed;
}
-static uint32_t pcnetCSRReadU16(PCNetState *pThis, uint32_t u32RAP)
+static uint32_t pcnetCSRReadU16(PPCNETSTATE pThis, uint32_t u32RAP)
{
uint32_t val;
switch (u32RAP)
@@ -3081,7 +2990,7 @@ static uint32_t pcnetCSRReadU16(PCNetState *pThis, uint32_t u32RAP)
return val;
}
-static int pcnetBCRWriteU16(PCNetState *pThis, uint32_t u32RAP, uint32_t val)
+static int pcnetBCRWriteU16(PPCNETSTATE pThis, uint32_t u32RAP, uint32_t val)
{
int rc = VINF_SUCCESS;
u32RAP &= 0x7f;
@@ -3153,7 +3062,7 @@ static int pcnetBCRWriteU16(PCNetState *pThis, uint32_t u32RAP, uint32_t val)
return rc;
}
-static uint32_t pcnetMIIReadU16(PCNetState *pThis, uint32_t miiaddr)
+static uint32_t pcnetMIIReadU16(PPCNETSTATE pThis, uint32_t miiaddr)
{
uint32_t val;
bool autoneg, duplex, fast;
@@ -3267,7 +3176,7 @@ static uint32_t pcnetMIIReadU16(PCNetState *pThis, uint32_t miiaddr)
return val;
}
-static uint32_t pcnetBCRReadU16(PCNetState *pThis, uint32_t u32RAP)
+static uint32_t pcnetBCRReadU16(PPCNETSTATE pThis, uint32_t u32RAP)
{
uint32_t val;
u32RAP &= 0x7f;
@@ -3309,7 +3218,7 @@ static uint32_t pcnetBCRReadU16(PCNetState *pThis, uint32_t u32RAP)
}
#ifdef IN_RING3 /* move down */
-static void pcnetHardReset(PCNetState *pThis)
+static void pcnetR3HardReset(PPCNETSTATE pThis)
{
int i;
uint16_t checksum;
@@ -3353,7 +3262,10 @@ static void pcnetHardReset(PCNetState *pThis)
}
#endif /* IN_RING3 */
-static void pcnetAPROMWriteU8(PCNetState *pThis, uint32_t addr, uint32_t val)
+
+/* -=-=-=-=-=- APROM I/O Port access -=-=-=-=-=- */
+
+static void pcnetAPROMWriteU8(PPCNETSTATE pThis, uint32_t addr, uint32_t val)
{
addr &= 0x0f;
val &= 0xff;
@@ -3363,14 +3275,74 @@ static void pcnetAPROMWriteU8(PCNetState *pThis, uint32_t addr, uint32_t val)
pThis->aPROM[addr] = val;
}
-static uint32_t pcnetAPROMReadU8(PCNetState *pThis, uint32_t addr)
+static uint32_t pcnetAPROMReadU8(PPCNETSTATE pThis, uint32_t addr)
{
uint32_t val = pThis->aPROM[addr &= 0x0f];
Log(("#%d pcnetAPROMReadU8: addr=%#010x val=%#04x\n", PCNET_INST_NR, addr, val));
return val;
}
-static int pcnetIoportWriteU8(PCNetState *pThis, uint32_t addr, uint32_t val)
+/**
+ * @callback_method_impl{FNIOMIOPORTIN, APROM}
+ */
+PDMBOTHCBDECL(int) pcnetIOPortAPromRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
+{
+ PPCNETSTATE pThis = PDMINS_2_DATA(pDevIns, PPCNETSTATE);
+ int rc = VINF_SUCCESS;
+ STAM_PROFILE_ADV_START(&pThis->StatAPROMRead, a);
+ Assert(PDMCritSectIsOwner(&pThis->CritSect));
+
+
+ /* FreeBSD is accessing in dwords. */
+ if (cb == 1)
+ *pu32 = pcnetAPROMReadU8(pThis, Port);
+ else if (cb == 2 && !BCR_DWIO(pThis))
+ *pu32 = pcnetAPROMReadU8(pThis, Port)
+ | (pcnetAPROMReadU8(pThis, Port + 1) << 8);
+ else if (cb == 4 && BCR_DWIO(pThis))
+ *pu32 = pcnetAPROMReadU8(pThis, Port)
+ | (pcnetAPROMReadU8(pThis, Port + 1) << 8)
+ | (pcnetAPROMReadU8(pThis, Port + 2) << 16)
+ | (pcnetAPROMReadU8(pThis, Port + 3) << 24);
+ else
+ {
+ Log(("#%d pcnetIOPortAPromRead: Port=%RTiop cb=%d BCR_DWIO !!\n", PCNET_INST_NR, Port, cb));
+ rc = VERR_IOM_IOPORT_UNUSED;
+ }
+
+ STAM_PROFILE_ADV_STOP(&pThis->StatAPROMRead, a);
+ LogFlow(("#%d pcnetIOPortAPromRead: Port=%RTiop *pu32=%#RX32 cb=%d rc=%Rrc\n", PCNET_INST_NR, Port, *pu32, cb, rc));
+ return rc;
+}
+
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT, APROM}
+ */
+PDMBOTHCBDECL(int) pcnetIOPortAPromWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
+{
+ PPCNETSTATE pThis = PDMINS_2_DATA(pDevIns, PPCNETSTATE);
+ int rc = VINF_SUCCESS;
+ Assert(PDMCritSectIsOwner(&pThis->CritSect));
+
+ if (cb == 1)
+ {
+ STAM_PROFILE_ADV_START(&pThis->StatAPROMWrite, a);
+ pcnetAPROMWriteU8(pThis, Port, u32);
+ STAM_PROFILE_ADV_STOP(&pThis->StatAPROMWrite, a);
+ }
+ else
+ rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "Port=%#x cb=%d u32=%#x\n", Port, cb, u32);
+
+ LogFlow(("#%d pcnetIOPortAPromWrite: Port=%RTiop u32=%#RX32 cb=%d rc=%Rrc\n", PCNET_INST_NR, Port, u32, cb, rc));
+ return rc;
+}
+
+
+/* -=-=-=-=-=- I/O Port access -=-=-=-=-=- */
+
+
+static int pcnetIoportWriteU8(PPCNETSTATE pThis, uint32_t addr, uint32_t val)
{
int rc = VINF_SUCCESS;
@@ -3392,7 +3364,7 @@ static int pcnetIoportWriteU8(PCNetState *pThis, uint32_t addr, uint32_t val)
return rc;
}
-static uint32_t pcnetIoportReadU8(PCNetState *pThis, uint32_t addr, int *pRC)
+static uint32_t pcnetIoportReadU8(PPCNETSTATE pThis, uint32_t addr, int *pRC)
{
uint32_t val = ~0U;
@@ -3419,7 +3391,7 @@ static uint32_t pcnetIoportReadU8(PCNetState *pThis, uint32_t addr, int *pRC)
return val;
}
-static int pcnetIoportWriteU16(PCNetState *pThis, uint32_t addr, uint32_t val)
+static int pcnetIoportWriteU16(PPCNETSTATE pThis, uint32_t addr, uint32_t val)
{
int rc = VINF_SUCCESS;
@@ -3450,7 +3422,7 @@ static int pcnetIoportWriteU16(PCNetState *pThis, uint32_t addr, uint32_t val)
return rc;
}
-static uint32_t pcnetIoportReadU16(PCNetState *pThis, uint32_t addr, int *pRC)
+static uint32_t pcnetIoportReadU16(PPCNETSTATE pThis, uint32_t addr, int *pRC)
{
uint32_t val = ~0U;
@@ -3494,7 +3466,7 @@ skip_update_irq:
return val;
}
-static int pcnetIoportWriteU32(PCNetState *pThis, uint32_t addr, uint32_t val)
+static int pcnetIoportWriteU32(PPCNETSTATE pThis, uint32_t addr, uint32_t val)
{
int rc = VINF_SUCCESS;
@@ -3533,7 +3505,7 @@ static int pcnetIoportWriteU32(PCNetState *pThis, uint32_t addr, uint32_t val)
return rc;
}
-static uint32_t pcnetIoportReadU32(PCNetState *pThis, uint32_t addr, int *pRC)
+static uint32_t pcnetIoportReadU32(PPCNETSTATE pThis, uint32_t addr, int *pRC)
{
uint32_t val = ~0U;
@@ -3576,7 +3548,64 @@ skip_update_irq:
return val;
}
-static void pcnetMMIOWriteU8(PCNetState *pThis, RTGCPHYS addr, uint32_t val)
+
+/**
+ * @callback_method_impl{FNIOMIOPORTIN}
+ */
+PDMBOTHCBDECL(int) pcnetIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
+{
+ PPCNETSTATE pThis = PDMINS_2_DATA(pDevIns, PPCNETSTATE);
+ int rc = VINF_SUCCESS;
+ STAM_PROFILE_ADV_START(&pThis->CTX_SUFF_Z(StatIORead), a);
+ Assert(PDMCritSectIsOwner(&pThis->CritSect));
+
+ switch (cb)
+ {
+ case 1: *pu32 = pcnetIoportReadU8(pThis, Port, &rc); break;
+ case 2: *pu32 = pcnetIoportReadU16(pThis, Port, &rc); break;
+ case 4: *pu32 = pcnetIoportReadU32(pThis, Port, &rc); break;
+ default:
+ rc = PDMDevHlpDBGFStop(pThis->CTX_SUFF(pDevIns), RT_SRC_POS,
+ "pcnetIOPortRead: unsupported op size: offset=%#10x cb=%u\n",
+ Port, cb);
+ }
+
+ Log2(("#%d pcnetIOPortRead: Port=%RTiop *pu32=%#RX32 cb=%d rc=%Rrc\n", PCNET_INST_NR, Port, *pu32, cb, rc));
+ STAM_PROFILE_ADV_STOP(&pThis->CTX_SUFF_Z(StatIORead), a);
+ return rc;
+}
+
+
+/**
+ * @callback_method_impl{FNIOMIOPORTOUT}
+ */
+PDMBOTHCBDECL(int) pcnetIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
+{
+ PPCNETSTATE pThis = PDMINS_2_DATA(pDevIns, PPCNETSTATE);
+ int rc = VINF_SUCCESS;
+ STAM_PROFILE_ADV_START(&pThis->CTX_SUFF_Z(StatIOWrite), a);
+ Assert(PDMCritSectIsOwner(&pThis->CritSect));
+
+ switch (cb)
+ {
+ case 1: rc = pcnetIoportWriteU8(pThis, Port, u32); break;
+ case 2: rc = pcnetIoportWriteU16(pThis, Port, u32); break;
+ case 4: rc = pcnetIoportWriteU32(pThis, Port, u32); break;
+ default:
+ rc = PDMDevHlpDBGFStop(pThis->CTX_SUFF(pDevIns), RT_SRC_POS,
+ "pcnetIOPortWrite: unsupported op size: offset=%#10x cb=%u\n",
+ Port, cb);
+ }
+
+ Log2(("#%d pcnetIOPortWrite: Port=%RTiop u32=%#RX32 cb=%d rc=%Rrc\n", PCNET_INST_NR, Port, u32, cb, rc));
+ STAM_PROFILE_ADV_STOP(&pThis->CTX_SUFF_Z(StatIOWrite), a);
+ return rc;
+}
+
+
+/* -=-=-=-=-=- MMIO -=-=-=-=-=- */
+
+static void pcnetMMIOWriteU8(PPCNETSTATE pThis, RTGCPHYS addr, uint32_t val)
{
#ifdef PCNET_DEBUG_IO
Log2(("#%d pcnetMMIOWriteU8: addr=%#010x val=%#04x\n", PCNET_INST_NR, addr, val));
@@ -3585,7 +3614,7 @@ static void pcnetMMIOWriteU8(PCNetState *pThis, RTGCPHYS addr, uint32_t val)
pcnetAPROMWriteU8(pThis, addr, val);
}
-static uint32_t pcnetMMIOReadU8(PCNetState *pThis, RTGCPHYS addr)
+static uint32_t pcnetMMIOReadU8(PPCNETSTATE pThis, RTGCPHYS addr)
{
uint32_t val = ~0U;
if (!(addr & 0x10))
@@ -3596,7 +3625,7 @@ static uint32_t pcnetMMIOReadU8(PCNetState *pThis, RTGCPHYS addr)
return val;
}
-static void pcnetMMIOWriteU16(PCNetState *pThis, RTGCPHYS addr, uint32_t val)
+static void pcnetMMIOWriteU16(PPCNETSTATE pThis, RTGCPHYS addr, uint32_t val)
{
#ifdef PCNET_DEBUG_IO
Log2(("#%d pcnetMMIOWriteU16: addr=%#010x val=%#06x\n", PCNET_INST_NR, addr, val));
@@ -3610,7 +3639,7 @@ static void pcnetMMIOWriteU16(PCNetState *pThis, RTGCPHYS addr, uint32_t val)
}
}
-static uint32_t pcnetMMIOReadU16(PCNetState *pThis, RTGCPHYS addr)
+static uint32_t pcnetMMIOReadU16(PPCNETSTATE pThis, RTGCPHYS addr)
{
uint32_t val = ~0U;
int rc;
@@ -3629,7 +3658,7 @@ static uint32_t pcnetMMIOReadU16(PCNetState *pThis, RTGCPHYS addr)
return val;
}
-static void pcnetMMIOWriteU32(PCNetState *pThis, RTGCPHYS addr, uint32_t val)
+static void pcnetMMIOWriteU32(PPCNETSTATE pThis, RTGCPHYS addr, uint32_t val)
{
#ifdef PCNET_DEBUG_IO
Log2(("#%d pcnetMMIOWriteU32: addr=%#010x val=%#010x\n", PCNET_INST_NR, addr, val));
@@ -3645,7 +3674,7 @@ static void pcnetMMIOWriteU32(PCNetState *pThis, RTGCPHYS addr, uint32_t val)
}
}
-static uint32_t pcnetMMIOReadU32(PCNetState *pThis, RTGCPHYS addr)
+static uint32_t pcnetMMIOReadU32(PPCNETSTATE pThis, RTGCPHYS addr)
{
uint32_t val;
int rc;
@@ -3670,216 +3699,29 @@ static uint32_t pcnetMMIOReadU32(PCNetState *pThis, RTGCPHYS addr)
/**
- * Port I/O Handler for IN operations.
- *
- * @returns VBox status code.
- *
- * @param pDevIns The device instance.
- * @param pvUser User argument.
- * @param Port Port number used for the IN operation.
- * @param pu32 Where to store the result.
- * @param cb Number of bytes read.
- */
-PDMBOTHCBDECL(int) pcnetIOPortAPromRead(PPDMDEVINS pDevIns, void *pvUser,
- RTIOPORT Port, uint32_t *pu32, unsigned cb)
-{
- PCNetState *pThis = PDMINS_2_DATA(pDevIns, PCNetState *);
- int rc;
-
- STAM_PROFILE_ADV_START(&pThis->StatAPROMRead, a);
- rc = PDMCritSectEnter(&pThis->CritSect, VINF_IOM_R3_IOPORT_WRITE);
- if (rc == VINF_SUCCESS)
- {
-
- /* FreeBSD is accessing in dwords. */
- if (cb == 1)
- *pu32 = pcnetAPROMReadU8(pThis, Port);
- else if (cb == 2 && !BCR_DWIO(pThis))
- *pu32 = pcnetAPROMReadU8(pThis, Port)
- | (pcnetAPROMReadU8(pThis, Port + 1) << 8);
- else if (cb == 4 && BCR_DWIO(pThis))
- *pu32 = pcnetAPROMReadU8(pThis, Port)
- | (pcnetAPROMReadU8(pThis, Port + 1) << 8)
- | (pcnetAPROMReadU8(pThis, Port + 2) << 16)
- | (pcnetAPROMReadU8(pThis, Port + 3) << 24);
- else
- {
- Log(("#%d pcnetIOPortAPromRead: Port=%RTiop cb=%d BCR_DWIO !!\n", PCNET_INST_NR, Port, cb));
- rc = VERR_IOM_IOPORT_UNUSED;
- }
- PDMCritSectLeave(&pThis->CritSect);
- }
- STAM_PROFILE_ADV_STOP(&pThis->StatAPROMRead, a);
- LogFlow(("#%d pcnetIOPortAPromRead: Port=%RTiop *pu32=%#RX32 cb=%d rc=%Rrc\n", PCNET_INST_NR, Port, *pu32, cb, rc));
- return rc;
-}
-
-
-/**
- * Port I/O Handler for OUT operations.
- *
- * @returns VBox status code.
- *
- * @param pDevIns The device instance.
- * @param pvUser User argument.
- * @param Port Port number used for the IN operation.
- * @param u32 The value to output.
- * @param cb The value size in bytes.
- */
-PDMBOTHCBDECL(int) pcnetIOPortAPromWrite(PPDMDEVINS pDevIns, void *pvUser,
- RTIOPORT Port, uint32_t u32, unsigned cb)
-{
- PCNetState *pThis = PDMINS_2_DATA(pDevIns, PCNetState *);
- int rc;
-
- if (cb == 1)
- {
- STAM_PROFILE_ADV_START(&pThis->StatAPROMWrite, a);
- rc = PDMCritSectEnter(&pThis->CritSect, VINF_IOM_R3_IOPORT_WRITE);
- if (RT_LIKELY(rc == VINF_SUCCESS))
- {
- pcnetAPROMWriteU8(pThis, Port, u32);
- PDMCritSectLeave(&pThis->CritSect);
- }
- STAM_PROFILE_ADV_STOP(&pThis->StatAPROMWrite, a);
- }
- else
- {
- AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
- rc = VINF_SUCCESS;
- }
- LogFlow(("#%d pcnetIOPortAPromWrite: Port=%RTiop u32=%#RX32 cb=%d rc=%Rrc\n", PCNET_INST_NR, Port, u32, cb, rc));
-#ifdef LOG_ENABLED
- if (rc == VINF_IOM_R3_IOPORT_WRITE)
- LogFlow(("#%d => HC\n", PCNET_INST_NR));
-#endif
- return rc;
-}
-
-
-/**
- * Port I/O Handler for IN operations.
- *
- * @returns VBox status code.
- *
- * @param pDevIns The device instance.
- * @param pvUser User argument.
- * @param Port Port number used for the IN operation.
- * @param pu32 Where to store the result.
- * @param cb Number of bytes read.
+ * @callback_method_impl{FNIOMMMIOREAD}
*/
-PDMBOTHCBDECL(int) pcnetIOPortRead(PPDMDEVINS pDevIns, void *pvUser,
- RTIOPORT Port, uint32_t *pu32, unsigned cb)
+PDMBOTHCBDECL(int) pcnetMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
{
- PCNetState *pThis = PDMINS_2_DATA(pDevIns, PCNetState *);
- int rc = VINF_SUCCESS;
-
- STAM_PROFILE_ADV_START(&pThis->CTX_SUFF_Z(StatIORead), a);
- rc = PDMCritSectEnter(&pThis->CritSect, VINF_IOM_R3_IOPORT_READ);
- if (RT_LIKELY(rc == VINF_SUCCESS))
- {
- switch (cb)
- {
- case 1: *pu32 = pcnetIoportReadU8(pThis, Port, &rc); break;
- case 2: *pu32 = pcnetIoportReadU16(pThis, Port, &rc); break;
- case 4: *pu32 = pcnetIoportReadU32(pThis, Port, &rc); break;
- default:
- rc = PDMDevHlpDBGFStop(pThis->CTX_SUFF(pDevIns), RT_SRC_POS,
- "pcnetIOPortRead: unsupported op size: offset=%#10x cb=%u\n",
- Port, cb);
- }
- PDMCritSectLeave(&pThis->CritSect);
- }
- STAM_PROFILE_ADV_STOP(&pThis->CTX_SUFF_Z(StatIORead), a);
- Log2(("#%d pcnetIOPortRead: Port=%RTiop *pu32=%#RX32 cb=%d rc=%Rrc\n", PCNET_INST_NR, Port, *pu32, cb, rc));
-#ifdef LOG_ENABLED
- if (rc == VINF_IOM_R3_IOPORT_READ)
- LogFlow(("#%d pcnetIOPortRead/critsect failed in GC => HC\n", PCNET_INST_NR));
-#endif
- return rc;
-}
-
-
-/**
- * Port I/O Handler for OUT operations.
- *
- * @returns VBox status code.
- *
- * @param pDevIns The device instance.
- * @param pvUser User argument.
- * @param Port Port number used for the IN operation.
- * @param u32 The value to output.
- * @param cb The value size in bytes.
- */
-PDMBOTHCBDECL(int) pcnetIOPortWrite(PPDMDEVINS pDevIns, void *pvUser,
- RTIOPORT Port, uint32_t u32, unsigned cb)
-{
- PCNetState *pThis = PDMINS_2_DATA(pDevIns, PCNetState *);
- int rc = VINF_SUCCESS;
-
- STAM_PROFILE_ADV_START(&pThis->CTX_SUFF_Z(StatIOWrite), a);
- rc = PDMCritSectEnter(&pThis->CritSect, VINF_IOM_R3_IOPORT_WRITE);
- if (RT_LIKELY(rc == VINF_SUCCESS))
- {
- switch (cb)
- {
- case 1: rc = pcnetIoportWriteU8(pThis, Port, u32); break;
- case 2: rc = pcnetIoportWriteU16(pThis, Port, u32); break;
- case 4: rc = pcnetIoportWriteU32(pThis, Port, u32); break;
- default:
- rc = PDMDevHlpDBGFStop(pThis->CTX_SUFF(pDevIns), RT_SRC_POS,
- "pcnetIOPortWrite: unsupported op size: offset=%#10x cb=%u\n",
- Port, cb);
- }
- PDMCritSectLeave(&pThis->CritSect);
- }
- STAM_PROFILE_ADV_STOP(&pThis->CTX_SUFF_Z(StatIOWrite), a);
- Log2(("#%d pcnetIOPortWrite: Port=%RTiop u32=%#RX32 cb=%d rc=%Rrc\n", PCNET_INST_NR, Port, u32, cb, rc));
-#ifdef LOG_ENABLED
- if (rc == VINF_IOM_R3_IOPORT_WRITE)
- LogFlow(("#%d pcnetIOPortWrite/critsect failed in GC => HC\n", PCNET_INST_NR));
-#endif
- return rc;
-}
-
-
-/**
- * Memory mapped I/O Handler for read operations.
- *
- * @returns VBox status code.
- *
- * @param pDevIns The device instance.
- * @param pvUser User argument.
- * @param GCPhysAddr Physical address (in GC) where the read starts.
- * @param pv Where to store the result.
- * @param cb Number of bytes read.
- */
-PDMBOTHCBDECL(int) pcnetMMIORead(PPDMDEVINS pDevIns, void *pvUser,
- RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
-{
- PCNetState *pThis = (PCNetState *)pvUser;
+ PPCNETSTATE pThis = (PPCNETSTATE)pvUser;
int rc = VINF_SUCCESS;
+ Assert(PDMCritSectIsOwner(&pThis->CritSect));
/*
- * We have to check the range, because we're page aligning the MMIO stuff presently.
+ * We have to check the range, because we're page aligning the MMIO.
*/
if (GCPhysAddr - pThis->MMIOBase < PCNET_PNPMMIO_SIZE)
{
STAM_PROFILE_ADV_START(&pThis->CTX_SUFF_Z(StatMMIORead), a);
- rc = PDMCritSectEnter(&pThis->CritSect, VINF_IOM_R3_MMIO_READ);
- if (RT_LIKELY(rc == VINF_SUCCESS))
+ switch (cb)
{
- switch (cb)
- {
- case 1: *(uint8_t *)pv = pcnetMMIOReadU8 (pThis, GCPhysAddr); break;
- case 2: *(uint16_t *)pv = pcnetMMIOReadU16(pThis, GCPhysAddr); break;
- case 4: *(uint32_t *)pv = pcnetMMIOReadU32(pThis, GCPhysAddr); break;
- default:
- rc = PDMDevHlpDBGFStop(pThis->CTX_SUFF(pDevIns), RT_SRC_POS,
- "pcnetMMIORead: unsupported op size: address=%RGp cb=%u\n",
- GCPhysAddr, cb);
- }
- PDMCritSectLeave(&pThis->CritSect);
+ case 1: *(uint8_t *)pv = pcnetMMIOReadU8 (pThis, GCPhysAddr); break;
+ case 2: *(uint16_t *)pv = pcnetMMIOReadU16(pThis, GCPhysAddr); break;
+ case 4: *(uint32_t *)pv = pcnetMMIOReadU32(pThis, GCPhysAddr); break;
+ default:
+ rc = PDMDevHlpDBGFStop(pThis->CTX_SUFF(pDevIns), RT_SRC_POS,
+ "pcnetMMIORead: unsupported op size: address=%RGp cb=%u\n",
+ GCPhysAddr, cb);
}
STAM_PROFILE_ADV_STOP(&pThis->CTX_SUFF_Z(StatMMIORead), a);
}
@@ -3888,30 +3730,18 @@ PDMBOTHCBDECL(int) pcnetMMIORead(PPDMDEVINS pDevIns, void *pvUser,
LogFlow(("#%d pcnetMMIORead: pvUser=%p:{%.*Rhxs} cb=%d GCPhysAddr=%RGp rc=%Rrc\n",
PCNET_INST_NR, pv, cb, pv, cb, GCPhysAddr, rc));
-#ifdef LOG_ENABLED
- if (rc == VINF_IOM_R3_MMIO_READ)
- LogFlow(("#%d => HC\n", PCNET_INST_NR));
-#endif
return rc;
}
/**
- * Port I/O Handler for write operations.
- *
- * @returns VBox status code.
- *
- * @param pDevIns The device instance.
- * @param pvUser User argument.
- * @param GCPhysAddr Physical address (in GC) where the read starts.
- * @param pv Where to fetch the result.
- * @param cb Number of bytes to write.
+ * @callback_method_impl{FNIOMMMIOWRITE}
*/
-PDMBOTHCBDECL(int) pcnetMMIOWrite(PPDMDEVINS pDevIns, void *pvUser,
- RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
+PDMBOTHCBDECL(int) pcnetMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
{
- PCNetState *pThis = (PCNetState *)pvUser;
+ PPCNETSTATE pThis = (PPCNETSTATE)pvUser;
int rc = VINF_SUCCESS;
+ Assert(PDMCritSectIsOwner(&pThis->CritSect));
/*
* We have to check the range, because we're page aligning the MMIO stuff presently.
@@ -3919,46 +3749,35 @@ PDMBOTHCBDECL(int) pcnetMMIOWrite(PPDMDEVINS pDevIns, void *pvUser,
if (GCPhysAddr - pThis->MMIOBase < PCNET_PNPMMIO_SIZE)
{
STAM_PROFILE_ADV_START(&pThis->CTX_SUFF_Z(StatMMIOWrite), a);
- rc = PDMCritSectEnter(&pThis->CritSect, VINF_IOM_R3_MMIO_WRITE);
- if (RT_LIKELY(rc == VINF_SUCCESS))
+ switch (cb)
{
- switch (cb)
- {
- case 1: pcnetMMIOWriteU8 (pThis, GCPhysAddr, *(uint8_t *)pv); break;
- case 2: pcnetMMIOWriteU16(pThis, GCPhysAddr, *(uint16_t *)pv); break;
- case 4: pcnetMMIOWriteU32(pThis, GCPhysAddr, *(uint32_t *)pv); break;
- default:
- rc = PDMDevHlpDBGFStop(pThis->CTX_SUFF(pDevIns), RT_SRC_POS,
- "pcnetMMIOWrite: unsupported op size: address=%RGp cb=%u\n",
- GCPhysAddr, cb);
- }
- PDMCritSectLeave(&pThis->CritSect);
+ case 1: pcnetMMIOWriteU8 (pThis, GCPhysAddr, *(uint8_t *)pv); break;
+ case 2: pcnetMMIOWriteU16(pThis, GCPhysAddr, *(uint16_t *)pv); break;
+ case 4: pcnetMMIOWriteU32(pThis, GCPhysAddr, *(uint32_t *)pv); break;
+ default:
+ rc = PDMDevHlpDBGFStop(pThis->CTX_SUFF(pDevIns), RT_SRC_POS,
+ "pcnetMMIOWrite: unsupported op size: address=%RGp cb=%u\n",
+ GCPhysAddr, cb);
}
- // else rc == VINF_IOM_R3_MMIO_WRITE => handle in ring3
STAM_PROFILE_ADV_STOP(&pThis->CTX_SUFF_Z(StatMMIOWrite), a);
}
LogFlow(("#%d pcnetMMIOWrite: pvUser=%p:{%.*Rhxs} cb=%d GCPhysAddr=%RGp rc=%Rrc\n",
PCNET_INST_NR, pv, cb, pv, cb, GCPhysAddr, rc));
-#ifdef LOG_ENABLED
- if (rc == VINF_IOM_R3_MMIO_WRITE)
- LogFlow(("#%d => HC\n", PCNET_INST_NR));
-#endif
return rc;
}
#ifdef IN_RING3
+
+/* -=-=-=-=-=- Timer Callbacks -=-=-=-=-=- */
+
/**
- * Device timer callback function.
- *
- * @param pDevIns Device instance of the device which registered the timer.
- * @param pTimer The timer handle.
- * @thread EMT
+ * @callback_method_impl{FNTMTIMERDEV, Poll timer}
*/
static DECLCALLBACK(void) pcnetTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
{
- PCNetState *pThis = (PCNetState *)pvUser;
+ PPCNETSTATE pThis = (PPCNETSTATE)pvUser;
Assert(PDMCritSectIsOwner(&pThis->CritSect));
STAM_PROFILE_ADV_START(&pThis->StatTimer, a);
@@ -3968,15 +3787,12 @@ static DECLCALLBACK(void) pcnetTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *
/**
- * Software interrupt timer callback function.
- *
- * @param pDevIns Device instance of the device which registered the timer.
- * @param pTimer The timer handle.
- * @thread EMT
+ * @callback_method_impl{FNTMTIMERDEV,
+ * Software interrupt timer callback function.}
*/
static DECLCALLBACK(void) pcnetTimerSoftInt(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
{
- PCNetState *pThis = (PCNetState *)pvUser;
+ PPCNETSTATE pThis = (PPCNETSTATE)pvUser;
Assert(PDMCritSectIsOwner(&pThis->CritSect));
pThis->aCSR[7] |= 0x0800; /* STINT */
@@ -3986,18 +3802,15 @@ static DECLCALLBACK(void) pcnetTimerSoftInt(PPDMDEVINS pDevIns, PTMTIMER pTimer,
/**
- * Restore timer callback.
+ * @callback_method_impl{FNTMTIMERDEV, Restore timer callback}
*
* This is only called when we restore a saved state and temporarily
* disconnected the network link to inform the guest that network connections
* should be considered lost.
- *
- * @param pDevIns Device instance of the device which registered the timer.
- * @param pTimer The timer handle.
*/
static DECLCALLBACK(void) pcnetTimerRestore(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
{
- PCNetState *pThis = PDMINS_2_DATA(pDevIns, PCNetState *);
+ PPCNETSTATE pThis = PDMINS_2_DATA(pDevIns, PPCNETSTATE);
int rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY);
AssertReleaseRC(rc);
@@ -4024,17 +3837,11 @@ static DECLCALLBACK(void) pcnetTimerRestore(PPDMDEVINS pDevIns, PTMTIMER pTimer,
PDMCritSectLeave(&pThis->CritSect);
}
+
+/* -=-=-=-=-=- PCI Device Callbacks -=-=-=-=-=- */
+
/**
- * Callback function for mapping an PCI I/O region.
- *
- * @return VBox status code.
- * @param pPciDev Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
- * @param iRegion The region number.
- * @param GCPhysAddress Physical address of the region. If iType is PCI_ADDRESS_SPACE_IO, this is an
- * I/O port, else it's a physical address.
- * This address is *NOT* relative to pci_mem_base like earlier!
- * @param cb Region size.
- * @param enmType One of the PCI_ADDRESS_SPACE_* values.
+ * @callback_method_impl{FNPCIIOREGIONMAP, For the PC-NET I/O Ports.}
*/
static DECLCALLBACK(int) pcnetIOPortMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion,
RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)
@@ -4042,7 +3849,7 @@ static DECLCALLBACK(int) pcnetIOPortMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRe
int rc;
PPDMDEVINS pDevIns = pPciDev->pDevIns;
RTIOPORT Port = (RTIOPORT)GCPhysAddress;
- PCNetState *pThis = PCIDEV_2_PCNETSTATE(pPciDev);
+ PPCNETSTATE pThis = PCIDEV_2_PCNETSTATE(pPciDev);
Assert(enmType == PCI_ADDRESS_SPACE_IO);
Assert(cb >= 0x20);
@@ -4085,27 +3892,18 @@ static DECLCALLBACK(int) pcnetIOPortMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRe
/**
- * Callback function for mapping the MMIO region.
- *
- * @return VBox status code.
- * @param pPciDev Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
- * @param iRegion The region number.
- * @param GCPhysAddress Physical address of the region. If iType is PCI_ADDRESS_SPACE_IO, this is an
- * I/O port, else it's a physical address.
- * This address is *NOT* relative to pci_mem_base like earlier!
- * @param cb Region size.
- * @param enmType One of the PCI_ADDRESS_SPACE_* values.
+ * @callback_method_impl{FNPCIIOREGIONMAP, For the PC-Net MMIO region.}
*/
static DECLCALLBACK(int) pcnetMMIOMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion,
RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)
{
- PCNetState *pThis = PCIDEV_2_PCNETSTATE(pPciDev);
+ PPCNETSTATE pThis = PCIDEV_2_PCNETSTATE(pPciDev);
int rc;
Assert(enmType == PCI_ADDRESS_SPACE_MEM);
Assert(cb >= PCNET_PNPMMIO_SIZE);
- /* We use the assigned size here, because we currently only support page aligned MMIO ranges. */
+ /* We use the assigned size here, because we only support page aligned MMIO ranges. */
rc = PDMDevHlpMMIORegister(pPciDev->pDevIns, GCPhysAddress, cb, pThis,
IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU,
pcnetMMIOWrite, pcnetMMIORead, "PCNet");
@@ -4116,39 +3914,14 @@ static DECLCALLBACK(int) pcnetMMIOMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegi
}
-/**
- * Callback function for mapping the MMIO region.
- *
- * @return VBox status code.
- * @param pPciDev Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
- * @param iRegion The region number.
- * @param GCPhysAddress Physical address of the region. If iType is PCI_ADDRESS_SPACE_IO, this is an
- * I/O port, else it's a physical address.
- * This address is *NOT* relative to pci_mem_base like earlier!
- * @param cb Region size.
- * @param enmType One of the PCI_ADDRESS_SPACE_* values.
- */
-static DECLCALLBACK(int) pcnetMMIOSharedMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion,
- RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)
-{
- if (GCPhysAddress != NIL_RTGCPHYS)
- return PDMDevHlpMMIO2Map(pPciDev->pDevIns, iRegion, GCPhysAddress);
-
- /* nothing to clean up */
- return VINF_SUCCESS;
-}
-
+/* -=-=-=-=-=- Debug Info Handler -=-=-=-=-=- */
/**
- * PCNET status info callback.
- *
- * @param pDevIns The device instance.
- * @param pHlp The output helpers.
- * @param pszArgs The arguments.
+ * @callback_method_impl{FNDBGFHANDLERDEV}
*/
static DECLCALLBACK(void) pcnetInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
{
- PCNetState *pThis = PDMINS_2_DATA(pDevIns, PCNetState *);
+ PPCNETSTATE pThis = PDMINS_2_DATA(pDevIns, PPCNETSTATE);
bool fRcvRing = false;
bool fXmtRing = false;
@@ -4366,6 +4139,8 @@ static DECLCALLBACK(void) pcnetInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, cons
}
+/* -=-=-=-=-=- Helper(s) -=-=-=-=-=- */
+
/**
* Takes down the link temporarily if it's current status is up.
*
@@ -4377,7 +4152,7 @@ static DECLCALLBACK(void) pcnetInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, cons
*
* @param pThis The PCNet instance data.
*/
-static void pcnetTempLinkDown(PCNetState *pThis)
+static void pcnetTempLinkDown(PPCNETSTATE pThis)
{
if (pThis->fLinkUp)
{
@@ -4391,13 +4166,15 @@ static void pcnetTempLinkDown(PCNetState *pThis)
}
+/* -=-=-=-=-=- Saved State -=-=-=-=-=- */
+
/**
* Saves the configuration.
*
* @param pThis The PCNet instance data.
* @param pSSM The saved state handle.
*/
-static void pcnetSaveConfig(PCNetState *pThis, PSSMHANDLE pSSM)
+static void pcnetSaveConfig(PPCNETSTATE pThis, PSSMHANDLE pSSM)
{
SSMR3PutMem(pSSM, &pThis->MacConfigured, sizeof(pThis->MacConfigured));
SSMR3PutBool(pSSM, pThis->fAm79C973); /* >= If version 0.8 */
@@ -4406,31 +4183,23 @@ static void pcnetSaveConfig(PCNetState *pThis, PSSMHANDLE pSSM)
/**
- * Live Save, pass 0.
- *
- * @returns VBox status code.
- * @param pDevIns The device instance.
- * @param pSSM The saved state handle.
- * @param uPass The pass number.
+ * @callback_method_impl{FNSSMDEVLIVEEXEC, Pass 0 only.}
*/
static DECLCALLBACK(int) pcnetLiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
{
- PCNetState *pThis = PDMINS_2_DATA(pDevIns, PCNetState *);
+ PPCNETSTATE pThis = PDMINS_2_DATA(pDevIns, PPCNETSTATE);
pcnetSaveConfig(pThis, pSSM);
return VINF_SSM_DONT_CALL_AGAIN;
}
/**
- * Serializes the receive thread, it may be working inside the critsect.
- *
- * @returns VBox status code.
- * @param pDevIns The device instance.
- * @param pSSM The saved state handle.
+ * @callback_method_impl{FNSSMDEVSAVEPREP,
+ * Serializes the receive thread, it may be working inside the critsect.}
*/
static DECLCALLBACK(int) pcnetSavePrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
{
- PCNetState *pThis = PDMINS_2_DATA(pDevIns, PCNetState *);
+ PPCNETSTATE pThis = PDMINS_2_DATA(pDevIns, PPCNETSTATE);
int rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY);
AssertRC(rc);
@@ -4441,21 +4210,17 @@ static DECLCALLBACK(int) pcnetSavePrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
/**
- * Saves a state of the PC-Net II device.
- *
- * @returns VBox status code.
- * @param pDevIns The device instance.
- * @param pSSM The saved state handle.
+ * @callback_method_impl{FNSSMDEVSAVEEXEC}
*/
static DECLCALLBACK(int) pcnetSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
{
- PCNetState *pThis = PDMINS_2_DATA(pDevIns, PCNetState *);
+ PPCNETSTATE pThis = PDMINS_2_DATA(pDevIns, PPCNETSTATE);
SSMR3PutBool(pSSM, pThis->fLinkUp);
SSMR3PutU32(pSSM, pThis->u32RAP);
SSMR3PutS32(pSSM, pThis->iISR);
SSMR3PutU32(pSSM, pThis->u32Lnkst);
- SSMR3PutBool(pSSM, pThis->fPrivIfEnabled); /* >= If version 0.9 */
+ SSMR3PutBool(pSSM, false/* was ffPrivIfEnabled */); /* >= If version 0.9 */
SSMR3PutBool(pSSM, pThis->fSignalRxMiss); /* >= If version 0.10 */
SSMR3PutGCPhys32(pSSM, pThis->GCRDRA);
SSMR3PutGCPhys32(pSSM, pThis->GCTDRA);
@@ -4480,36 +4245,41 @@ static DECLCALLBACK(int) pcnetSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
/**
- * Serializes the receive thread, it may be working inside the critsect.
- *
- * @returns VBox status code.
- * @param pDevIns The device instance.
- * @param pSSM The saved state handle.
+ * @callback_method_impl{FNSSMDEVLOADPREP},
+ * Serializes the receive thread, it may be working inside the critsect.}
*/
static DECLCALLBACK(int) pcnetLoadPrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
{
- PCNetState *pThis = PDMINS_2_DATA(pDevIns, PCNetState *);
+ PPCNETSTATE pThis = PDMINS_2_DATA(pDevIns, PPCNETSTATE);
int rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY);
AssertRC(rc);
+
+ uint32_t uVer = SSMR3HandleVersion(pSSM);
+ if ( uVer < VBOX_FULL_VERSION_MAKE(4, 3, 6)
+ || ( uVer >= VBOX_FULL_VERSION_MAKE(4, 3, 51)
+ && uVer < VBOX_FULL_VERSION_MAKE(4, 3, 53)))
+ {
+ /* older saved states contain the shared memory region which was never used for ages. */
+ void *pvSharedMMIOR3;
+ rc = PDMDevHlpMMIO2Register(pDevIns, 2, _512K, 0, (void **)&pvSharedMMIOR3, "PCNetSh");
+ if (RT_FAILURE(rc))
+ rc = PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
+ N_("Failed to allocate the dummy shmem region for the PCNet device"));
+ pThis->fSharedRegion = true;
+ }
PDMCritSectLeave(&pThis->CritSect);
- return VINF_SUCCESS;
+ return rc;
}
/**
- * Loads a saved PC-Net II device state.
- *
- * @returns VBox status code.
- * @param pDevIns The device instance.
- * @param pSSM The handle to the saved state.
- * @param uVersion The data unit version number.
- * @param uPass The data pass.
+ * @callback_method_impl{FNSSMDEVLOADEXEC}
*/
static DECLCALLBACK(int) pcnetLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
{
- PCNetState *pThis = PDMINS_2_DATA(pDevIns, PCNetState *);
+ PPCNETSTATE pThis = PDMINS_2_DATA(pDevIns, PPCNETSTATE);
if ( SSM_VERSION_MAJOR_CHANGED(uVersion, PCNET_SAVEDSTATE_VERSION)
|| SSM_VERSION_MINOR(uVersion) < 7)
@@ -4525,9 +4295,14 @@ static DECLCALLBACK(int) pcnetLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint
if ( SSM_VERSION_MAJOR(uVersion) > 0
|| SSM_VERSION_MINOR(uVersion) >= 9)
{
- SSMR3GetBool(pSSM, &pThis->fPrivIfEnabled);
- if (pThis->fPrivIfEnabled)
- LogRel(("PCNet#%d: Enabling private interface\n", PCNET_INST_NR));
+ bool fPrivIfEnabled = false;
+ SSMR3GetBool(pSSM, &fPrivIfEnabled);
+ if (fPrivIfEnabled)
+ {
+ /* no longer implemented */
+ LogRel(("PCNet#%d: Cannot enabling private interface!\n", PCNET_INST_NR));
+ return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
+ }
}
if ( SSM_VERSION_MAJOR(uVersion) > 0
|| SSM_VERSION_MINOR(uVersion) >= 10)
@@ -4602,31 +4377,34 @@ static DECLCALLBACK(int) pcnetLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint
return VINF_SUCCESS;
}
-
/**
- * @interface_method_impl{PDMIBASE,pfnQueryInterface}
+ * @callback_method_impl{FNSSMDEVLOADDONE}
*/
-static DECLCALLBACK(void *) pcnetQueryInterface(struct PDMIBASE *pInterface, const char *pszIID)
+static DECLCALLBACK(int) pcnetLoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
{
- PCNetState *pThis = RT_FROM_MEMBER(pInterface, PCNetState, IBase);
- Assert(&pThis->IBase == pInterface);
- PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
- PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKDOWN, &pThis->INetworkDown);
- PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKCONFIG, &pThis->INetworkConfig);
- PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pThis->ILeds);
- return NULL;
+ PPCNETSTATE pThis = PDMINS_2_DATA(pDevIns, PPCNETSTATE);
+ int rc = VINF_SUCCESS;
+ if (pThis->fSharedRegion)
+ {
+ /* drop this dummy region */
+ rc = PDMDevHlpMMIO2Deregister(pDevIns, 2);
+ pThis->fSharedRegion = false;
+ }
+ return rc;
}
-
+/* -=-=-=-=-=- PCNETSTATE::INetworkDown -=-=-=-=-=- */
/**
* Check if the device/driver can receive data now.
- * This must be called before the pfnRecieve() method is called.
+ *
+ * Worker for pcnetNetworkDown_WaitReceiveAvail(). This must be called before
+ * the pfnRecieve() method is called.
*
* @returns VBox status code.
- * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pThis The PC-Net instance data.
*/
-static int pcnetCanReceive(PCNetState *pThis)
+static int pcnetCanReceive(PPCNETSTATE pThis)
{
int rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY);
AssertReleaseRC(rc);
@@ -4658,7 +4436,7 @@ static int pcnetCanReceive(PCNetState *pThis)
*/
static DECLCALLBACK(int) pcnetNetworkDown_WaitReceiveAvail(PPDMINETWORKDOWN pInterface, RTMSINTERVAL cMillies)
{
- PCNetState *pThis = RT_FROM_MEMBER(pInterface, PCNetState, INetworkDown);
+ PPCNETSTATE pThis = RT_FROM_MEMBER(pInterface, PCNETSTATE, INetworkDown);
int rc = pcnetCanReceive(pThis);
if (RT_SUCCESS(rc))
@@ -4700,7 +4478,7 @@ static DECLCALLBACK(int) pcnetNetworkDown_WaitReceiveAvail(PPDMINETWORKDOWN pInt
*/
static DECLCALLBACK(int) pcnetNetworkDown_Receive(PPDMINETWORKDOWN pInterface, const void *pvBuf, size_t cb)
{
- PCNetState *pThis = RT_FROM_MEMBER(pInterface, PCNetState, INetworkDown);
+ PPCNETSTATE pThis = RT_FROM_MEMBER(pInterface, PCNETSTATE, INetworkDown);
int rc;
STAM_PROFILE_ADV_START(&pThis->StatReceive, a);
@@ -4754,38 +4532,30 @@ static DECLCALLBACK(int) pcnetNetworkDown_Receive(PPDMINETWORKDOWN pInterface, c
*/
static DECLCALLBACK(void) pcnetNetworkDown_XmitPending(PPDMINETWORKDOWN pInterface)
{
- PCNetState *pThis = RT_FROM_MEMBER(pInterface, PCNetState, INetworkDown);
+ PPCNETSTATE pThis = RT_FROM_MEMBER(pInterface, PCNETSTATE, INetworkDown);
pcnetXmitPending(pThis, true /*fOnWorkerThread*/);
}
+/* -=-=-=-=-=- PCNETSTATE::INetworkConfig -=-=-=-=-=- */
/**
- * Gets the current Media Access Control (MAC) address.
- *
- * @returns VBox status code.
- * @param pInterface Pointer to the interface structure containing the called function pointer.
- * @param pMac Where to store the MAC address.
- * @thread EMT
+ * @interface_method_impl{PDMINETWORKCONFIG,pfnGetMac}
*/
static DECLCALLBACK(int) pcnetGetMac(PPDMINETWORKCONFIG pInterface, PRTMAC pMac)
{
- PCNetState *pThis = RT_FROM_MEMBER(pInterface, PCNetState, INetworkConfig);
+ PPCNETSTATE pThis = RT_FROM_MEMBER(pInterface, PCNETSTATE, INetworkConfig);
memcpy(pMac, pThis->aPROM, sizeof(*pMac));
return VINF_SUCCESS;
}
/**
- * Gets the new link state.
- *
- * @returns The current link state.
- * @param pInterface Pointer to the interface structure containing the called function pointer.
- * @thread EMT
+ * @interface_method_impl{PDMINETWORKCONFIG,pfnGetLinkState}
*/
static DECLCALLBACK(PDMNETWORKLINKSTATE) pcnetGetLinkState(PPDMINETWORKCONFIG pInterface)
{
- PCNetState *pThis = RT_FROM_MEMBER(pInterface, PCNetState, INetworkConfig);
+ PPCNETSTATE pThis = RT_FROM_MEMBER(pInterface, PCNETSTATE, INetworkConfig);
if (pThis->fLinkUp && !pThis->fLinkTempDown)
return PDMNETWORKLINKSTATE_UP;
if (!pThis->fLinkUp)
@@ -4798,24 +4568,26 @@ static DECLCALLBACK(PDMNETWORKLINKSTATE) pcnetGetLinkState(PPDMINETWORKCONFIG pI
/**
- * Sets the new link state.
- *
- * @returns VBox status code.
- * @param pInterface Pointer to the interface structure containing the called function pointer.
- * @param enmState The new link state
- * @thread EMT
+ * @interface_method_impl{PDMINETWORKCONFIG,pfnSetLinkState}
*/
static DECLCALLBACK(int) pcnetSetLinkState(PPDMINETWORKCONFIG pInterface, PDMNETWORKLINKSTATE enmState)
{
- PCNetState *pThis = RT_FROM_MEMBER(pInterface, PCNetState, INetworkConfig);
+ PPCNETSTATE pThis = RT_FROM_MEMBER(pInterface, PCNETSTATE, INetworkConfig);
bool fLinkUp;
- if ( enmState != PDMNETWORKLINKSTATE_DOWN
- && enmState != PDMNETWORKLINKSTATE_UP)
+
+ AssertMsgReturn(enmState > PDMNETWORKLINKSTATE_INVALID && enmState <= PDMNETWORKLINKSTATE_DOWN_RESUME,
+ ("Invalid link state: enmState=%d\n", enmState), VERR_INVALID_PARAMETER);
+
+ if (enmState == PDMNETWORKLINKSTATE_DOWN_RESUME)
{
- AssertMsgFailed(("Invalid parameter enmState=%d\n", enmState));
- return VERR_INVALID_PARAMETER;
+ pcnetTempLinkDown(pThis);
+ /*
+ * Note that we do not notify the driver about the link state change because
+ * the change is only temporary and can be disregarded from the driver's
+ * point of view (see @bugref{7057}).
+ */
+ return VINF_SUCCESS;
}
-
/* has the state changed? */
fLinkUp = enmState == PDMNETWORKLINKSTATE_UP;
if (pThis->fLinkUp != fLinkUp)
@@ -4823,7 +4595,7 @@ static DECLCALLBACK(int) pcnetSetLinkState(PPDMINETWORKCONFIG pInterface, PDMNET
pThis->fLinkUp = fLinkUp;
if (fLinkUp)
{
- /* connect with a delay of 5 seconds */
+ /* Connect with a configured delay. */
pThis->fLinkTempDown = true;
pThis->cLinkDownReported = 0;
pThis->aCSR[0] |= RT_BIT(15) | RT_BIT(13); /* ERR | CERR (this is probably wrong) */
@@ -4846,17 +4618,14 @@ static DECLCALLBACK(int) pcnetSetLinkState(PPDMINETWORKCONFIG pInterface, PDMNET
}
+/* -=-=-=-=-=- PCNETSTATE::ILeds (LUN#0) -=-=-=-=-=- */
+
/**
- * Gets the pointer to the status LED of a unit.
- *
- * @returns VBox status code.
- * @param pInterface Pointer to the interface structure containing the called function pointer.
- * @param iLUN The unit which status LED we desire.
- * @param ppLed Where to store the LED pointer.
+ * @interface_method_impl{PDMILEDPORTS,pfnQueryStatusLed}
*/
static DECLCALLBACK(int) pcnetQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
{
- PCNetState *pThis = (PCNetState *)( (uintptr_t)pInterface - RT_OFFSETOF(PCNetState, ILeds) );
+ PPCNETSTATE pThis = RT_FROM_MEMBER(pInterface, PCNETSTATE, ILeds);
if (iLUN == 0)
{
*ppLed = &pThis->Led;
@@ -4866,8 +4635,27 @@ static DECLCALLBACK(int) pcnetQueryStatusLed(PPDMILEDPORTS pInterface, unsigned
}
+/* -=-=-=-=-=- PCNETSTATE::IBase (LUN#0) -=-=-=-=-=- */
+
+/**
+ * @interface_method_impl{PDMIBASE,pfnQueryInterface}
+ */
+static DECLCALLBACK(void *) pcnetQueryInterface(struct PDMIBASE *pInterface, const char *pszIID)
+{
+ PPCNETSTATE pThis = RT_FROM_MEMBER(pInterface, PCNETSTATE, IBase);
+ Assert(&pThis->IBase == pInterface);
+ PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
+ PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKDOWN, &pThis->INetworkDown);
+ PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKCONFIG, &pThis->INetworkConfig);
+ PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pThis->ILeds);
+ return NULL;
+}
+
+
+/* -=-=-=-=-=- PDMDEVREG -=-=-=-=-=- */
+
/**
- * @copydoc FNPDMDEVPOWEROFF
+ * @interface_method_impl{PDMDEVREG,pfnPowerOff}
*/
static DECLCALLBACK(void) pcnetPowerOff(PPDMDEVINS pDevIns)
{
@@ -4877,17 +4665,13 @@ static DECLCALLBACK(void) pcnetPowerOff(PPDMDEVINS pDevIns)
/**
- * Detach notification.
+ * @interface_method_impl{PDMDEVREG,pfnDetach}
*
* One port on the network card has been disconnected from the network.
- *
- * @param pDevIns The device instance.
- * @param iLUN The logical unit which is being detached.
- * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
*/
static DECLCALLBACK(void) pcnetDetach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
{
- PCNetState *pThis = PDMINS_2_DATA(pDevIns, PCNetState *);
+ PPCNETSTATE pThis = PDMINS_2_DATA(pDevIns, PPCNETSTATE);
Log(("#%d pcnetDetach:\n", PCNET_INST_NR));
AssertLogRelReturnVoid(iLUN == 0);
@@ -4911,20 +4695,12 @@ static DECLCALLBACK(void) pcnetDetach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_
/**
- * Attach the Network attachment.
- *
+ * @interface_method_impl{PDMDEVREG,pfnAttach}
* One port on the network card has been connected to a network.
- *
- * @returns VBox status code.
- * @param pDevIns The device instance.
- * @param iLUN The logical unit which is being attached.
- * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
- *
- * @remarks This code path is not used during construction.
*/
static DECLCALLBACK(int) pcnetAttach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
{
- PCNetState *pThis = PDMINS_2_DATA(pDevIns, PCNetState *);
+ PPCNETSTATE pThis = PDMINS_2_DATA(pDevIns, PPCNETSTATE);
LogFlow(("#%d pcnetAttach:\n", PCNET_INST_NR));
AssertLogRelReturn(iLUN == 0, VERR_PDM_NO_SUCH_LUN);
@@ -4976,7 +4752,7 @@ static DECLCALLBACK(int) pcnetAttach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t
/**
- * @copydoc FNPDMDEVSUSPEND
+ * @interface_method_impl{PDMDEVREG,pfnSuspend}
*/
static DECLCALLBACK(void) pcnetSuspend(PPDMDEVINS pDevIns)
{
@@ -4986,36 +4762,32 @@ static DECLCALLBACK(void) pcnetSuspend(PPDMDEVINS pDevIns)
/**
- * @copydoc FNPDMDEVRESET
+ * @interface_method_impl{PDMDEVREG,pfnReset}
*/
static DECLCALLBACK(void) pcnetReset(PPDMDEVINS pDevIns)
{
- PCNetState *pThis = PDMINS_2_DATA(pDevIns, PCNetState *);
+ PPCNETSTATE pThis = PDMINS_2_DATA(pDevIns, PPCNETSTATE);
if (pThis->fLinkTempDown)
{
pThis->cLinkDownReported = 0x10000;
TMTimerStop(pThis->pTimerRestore);
pcnetTimerRestore(pDevIns, pThis->pTimerRestore, pThis);
}
- if (pThis->pSharedMMIOR3)
- pcnetInitSharedMemory(pThis);
/** @todo How to flush the queues? */
- pcnetHardReset(pThis);
+ pcnetR3HardReset(pThis);
}
/**
- * @copydoc FNPDMDEVRELOCATE
+ * @interface_method_impl{PDMDEVREG,pfnRelocate}
*/
static DECLCALLBACK(void) pcnetRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
{
- PCNetState *pThis = PDMINS_2_DATA(pDevIns, PCNetState *);
+ PPCNETSTATE pThis = PDMINS_2_DATA(pDevIns, PPCNETSTATE);
pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
pThis->pXmitQueueRC = PDMQueueRCPtr(pThis->pXmitQueueR3);
pThis->pCanRxQueueRC = PDMQueueRCPtr(pThis->pCanRxQueueR3);
- if (pThis->pSharedMMIOR3)
- pThis->pSharedMMIORC += offDelta;
#ifdef PCNET_NO_POLLING
pThis->pfnEMInterpretInstructionRC += offDelta;
#else
@@ -5027,17 +4799,11 @@ static DECLCALLBACK(void) pcnetRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
/**
- * Destruct a device instance.
- *
- * Most VM resources are freed by the VM. This callback is provided so that any non-VM
- * resources can be freed correctly.
- *
- * @returns VBox status.
- * @param pDevIns The device instance data.
+ * @interface_method_impl{PDMDEVREG,pfnDestruct}
*/
static DECLCALLBACK(int) pcnetDestruct(PPDMDEVINS pDevIns)
{
- PCNetState *pThis = PDMINS_2_DATA(pDevIns, PCNetState *);
+ PPCNETSTATE pThis = PDMINS_2_DATA(pDevIns, PPCNETSTATE);
PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
if (PDMCritSectIsInitialized(&pThis->CritSect))
@@ -5056,7 +4822,7 @@ static DECLCALLBACK(int) pcnetDestruct(PPDMDEVINS pDevIns)
*/
static DECLCALLBACK(int) pcnetConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
{
- PCNetState *pThis = PDMINS_2_DATA(pDevIns, PCNetState *);
+ PPCNETSTATE pThis = PDMINS_2_DATA(pDevIns, PPCNETSTATE);
PPDMIBASE pBase;
char szTmp[128];
int rc;
@@ -5182,63 +4948,29 @@ static DECLCALLBACK(int) pcnetConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGM
pThis->PciDev.config[0x3f] = 0xff;
/*
+ * We use own critical section (historical reasons).
+ */
+ rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, RT_SRC_POS, "PCNet#%u", iInstance);
+ AssertRCReturn(rc, rc);
+ rc = PDMDevHlpSetDeviceCritSect(pDevIns, &pThis->CritSect);
+ AssertRCReturn(rc, rc);
+
+ rc = RTSemEventCreate(&pThis->hEventOutOfRxSpace);
+ AssertRCReturn(rc, rc);
+
+ /*
* Register the PCI device, its I/O regions, the timer and the saved state item.
*/
rc = PDMDevHlpPCIRegister(pDevIns, &pThis->PciDev);
if (RT_FAILURE(rc))
return rc;
- rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, PCNET_IOPORT_SIZE,
- PCI_ADDRESS_SPACE_IO, pcnetIOPortMap);
+ rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, PCNET_IOPORT_SIZE, PCI_ADDRESS_SPACE_IO, pcnetIOPortMap);
if (RT_FAILURE(rc))
return rc;
- rc = PDMDevHlpPCIIORegionRegister(pDevIns, 1, PCNET_PNPMMIO_SIZE,
- PCI_ADDRESS_SPACE_MEM, pcnetMMIOMap);
- if (RT_FAILURE(rc))
- return rc;
-
- bool fPrivIfEnabled;
- rc = CFGMR3QueryBool(pCfg, "PrivIfEnabled", &fPrivIfEnabled);
- if (rc == VERR_CFGM_VALUE_NOT_FOUND)
- fPrivIfEnabled = true;
- else if (RT_FAILURE(rc))
- return PDMDEV_SET_ERROR(pDevIns, rc,
- N_("Configuration error: Failed to get the \"PrivIfEnabled\" value"));
-
- if (fPrivIfEnabled)
- {
- /*
- * Initialize shared memory between host and guest for descriptors and RX buffers. Most guests
- * should not care if there is an additional PCI resource but just in case we made this configurable.
- */
- rc = PDMDevHlpMMIO2Register(pDevIns, 2, PCNET_GUEST_SHARED_MEMORY_SIZE, 0, (void **)&pThis->pSharedMMIOR3, "PCNetShMem");
- if (RT_FAILURE(rc))
- return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
- N_("Failed to allocate %u bytes of memory for the PCNet device"), PCNET_GUEST_SHARED_MEMORY_SIZE);
- rc = PDMDevHlpMMHyperMapMMIO2(pDevIns, 2, 0, 8192, "PCNetShMem", &pThis->pSharedMMIORC);
- if (RT_FAILURE(rc))
- return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
- N_("Failed to map 8192 bytes of memory for the PCNet device into the hyper memory"));
- pThis->pSharedMMIOR0 = (uintptr_t)pThis->pSharedMMIOR3; /** @todo @bugref{1865}: Map MMIO2 into ring-0. */
-
- pcnetInitSharedMemory(pThis);
- rc = PDMDevHlpPCIIORegionRegister(pDevIns, 2, PCNET_GUEST_SHARED_MEMORY_SIZE,
- PCI_ADDRESS_SPACE_MEM, pcnetMMIOSharedMap);
- if (RT_FAILURE(rc))
- return rc;
- }
-
- /*
- * Initialize critical section.
- * This must be done before register the critsect with the timer code, and also before
- * attaching drivers or anything else that may call us back.
- */
- rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, RT_SRC_POS, "PCNet#%u", iInstance);
+ rc = PDMDevHlpPCIIORegionRegister(pDevIns, 1, PCNET_PNPMMIO_SIZE, PCI_ADDRESS_SPACE_MEM, pcnetMMIOMap);
if (RT_FAILURE(rc))
return rc;
- rc = RTSemEventCreate(&pThis->hEventOutOfRxSpace);
- AssertRC(rc);
-
#ifdef PCNET_NO_POLLING
/*
* Resolve the R0 and RC handlers.
@@ -5275,7 +5007,7 @@ static DECLCALLBACK(int) pcnetConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGM
rc = PDMDevHlpSSMRegisterEx(pDevIns, PCNET_SAVEDSTATE_VERSION, sizeof(*pThis), NULL,
NULL, pcnetLiveExec, NULL,
pcnetSavePrep, pcnetSaveExec, NULL,
- pcnetLoadPrep, pcnetLoadExec, NULL);
+ pcnetLoadPrep, pcnetLoadExec, pcnetLoadDone);
if (RT_FAILURE(rc))
return rc;
@@ -5352,7 +5084,13 @@ static DECLCALLBACK(int) pcnetConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGM
/*
* Reset the device state. (Do after attaching.)
*/
- pcnetHardReset(pThis);
+ pcnetR3HardReset(pThis);
+
+ PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatReceiveBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Amount of data received", "/Public/Net/PCNet%u/BytesReceived", iInstance);
+ PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatTransmitBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Amount of data transmitted", "/Public/Net/PCNet%u/BytesTransmitted", iInstance);
+
+ PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatReceiveBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Amount of data received", "/Devices/PCNet%d/ReceiveBytes", iInstance);
+ PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatTransmitBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Amount of data transmitted", "/Devices/PCNet%d/TransmitBytes", iInstance);
#ifdef VBOX_WITH_STATISTICS
PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatMMIOReadRZ, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling MMIO reads in RZ", "/Devices/PCNet%d/MMIO/ReadRZ", iInstance);
@@ -5369,16 +5107,10 @@ static DECLCALLBACK(int) pcnetConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGM
PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatReceive, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling receive", "/Devices/PCNet%d/Receive", iInstance);
PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatRxOverflow, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_OCCURENCE, "Profiling RX overflows", "/Devices/PCNet%d/RxOverflow", iInstance);
PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatRxOverflowWakeup, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_OCCURENCE, "Nr of RX overflow wakeups", "/Devices/PCNet%d/RxOverflowWakeup", iInstance);
-#endif
- PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatReceiveBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Amount of data received", "/Devices/PCNet%d/ReceiveBytes", iInstance);
-#ifdef VBOX_WITH_STATISTICS
PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatTransmitCase1, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Single descriptor transmit", "/Devices/PCNet%d/Transmit/Case1", iInstance);
PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatTransmitCase2, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Multi descriptor transmit", "/Devices/PCNet%d/Transmit/Case2", iInstance);
PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatTransmitRZ, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling transmits in RZ", "/Devices/PCNet%d/Transmit/TotalRZ", iInstance);
PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatTransmitR3, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling transmits in R3", "/Devices/PCNet%d/Transmit/TotalR3", iInstance);
-#endif
- PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatTransmitBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Amount of data transmitted", "/Devices/PCNet%d/TransmitBytes", iInstance);
-#ifdef VBOX_WITH_STATISTICS
PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatTransmitSendRZ, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling PCNet send transmit in RZ","/Devices/PCNet%d/Transmit/SendRZ", iInstance);
PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatTransmitSendR3, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling PCNet send transmit in R3","/Devices/PCNet%d/Transmit/SendR3", iInstance);
PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatTxLenCalcRZ, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling PCNet TX len calc in RZ", "/Devices/PCNet%d/Transmit/LenCalcRZ", iInstance);
@@ -5418,7 +5150,7 @@ static DECLCALLBACK(int) pcnetConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGM
PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatRingWriteOutsideR0, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Nr of monitored writes outside ring","/Devices/PCNet%d/Ring/R0/Outside", iInstance);
PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatRingWriteOutsideRC, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Nr of monitored writes outside ring","/Devices/PCNet%d/Ring/RC/Outside", iInstance);
# endif /* PCNET_NO_POLLING */
-#endif
+#endif /* VBOX_WITH_STATISTICS */
return VINF_SUCCESS;
}
@@ -5454,14 +5186,14 @@ const PDMDEVREG g_DevicePCNet =
/* cMaxInstances */
~0U,
/* cbInstance */
- sizeof(PCNetState),
+ sizeof(PCNETSTATE),
/* pfnConstruct */
pcnetConstruct,
/* pfnDestruct */
pcnetDestruct,
/* pfnRelocate */
pcnetRelocate,
- /* pfnIOCtl */
+ /* pfnMemSetup */
NULL,
/* pfnPowerOn */
NULL,