xbox-kernel/private/ntos/net/nicx.h
2020-09-30 17:17:25 +02:00

257 lines
11 KiB
C++

// ---------------------------------------------------------------------------------------
// nicx.h
//
// Copyright (C) Microsoft Corporation
// ---------------------------------------------------------------------------------------
#ifndef _NICX_H_
#define _NICX_H_
// ---------------------------------------------------------------------------------------
// Definitions
// ---------------------------------------------------------------------------------------
struct NICSTATS
{
ULONG isrCount;
ULONG dpcCount;
ULONG txGoodFrames;
ULONG rxGoodFrames;
ULONG txUnderflowErrors;
ULONG txLateCollisions;
ULONG txLostCarriers;
ULONG txDefers;
ULONG txExcessiveDefers;
ULONG txRetryErrors;
ULONG rxMinSizeErrors;
ULONG rxFramingErrors;
ULONG rxOverFlowErrors;
ULONG rxCrcErrors;
ULONG rxLengthErrors;
ULONG rxMaxFrameErrors;
ULONG rxLateCollisions;
ULONG rxRunts;
ULONG rxExtraByteErrors;
ULONG rxMissedFrames;
ULONG rxEndOfFrameErrors;
};
#define NIC_VENDORID 0x10DE // nVidia Vendor ID
#define NIC_DEVICEID 0x01C3 // nVidia Device ID
#define RXDESC_OWN BIT(31) // 0 - host owns; 1 - controller owns
#define RXDESC_ERR BIT(30) // receive error
#define RXDESC_FRAM BIT(29) // framing error
#define RXDESC_OFOL BIT(28) // overflow error
#define RXDESC_CRC BIT(27) // CRC error
#define RXDESC_LFER BIT(26) // length field error
#define RXDESC_MAX BIT(25) // received frame larger than max size
#define RXDESC_LCOL BIT(24) // late collision
#define RXDESC_RUNT BIT(23) // runt packet received
#define RXDESC_PAM BIT(22) // physical address match
#define RXDESC_MAM BIT(21) // multicast address match
#define RXDESC_BAM BIT(20) // broadcast address match
#define RXDESC_EXTRA BIT(18) // received frame length has an extra byte
#define RXDESC_MISS BIT(17) // missed data reception
#define RXDESC_REND BIT(16) // end of receive frame
#define TXDESC_OWN BIT(31) // 0 - host owns; 1 - controller owns
#define TXDESC_ERR BIT(30) // transmit error
#define TXDESC_UFLO BIT(29) // underflow error
#define TXDESC_LCOL BIT(28) // late collision
#define TXDESC_LCAR BIT(27) // loss of carrier
#define TXDESC_DEF BIT(26) // deferred
#define TXDESC_EXDEF BIT(25) // excessive deferral
#define TXDESC_INTEN BIT(24) // interrupt override
#define TXDESC_RTRY BIT(19) // retry error (23-20: retry count)
#define TXDESC_TEND BIT(16) // end of transmit frame
struct XmitDesc
{
DWORD _dwPhyAddr; // physical address of xmit buffer
DWORD _dwFlagsCount; // HIWORD - control/status bits; LOWORD - byte count minus 1
};
struct RecvDesc
{
DWORD _dwPhyAddr; // physical address of recv buffer
DWORD _dwFlagsCount; // HIWORD - control/status bits; LOWORD - byte count
};
#define NIC_FRAME_SIZE (PAGE_SIZE/2)
#define NIC_FRAME_ALIGNMENT 2
// ---------------------------------------------------------------------------------------
// CXnNic
// ---------------------------------------------------------------------------------------
class NOVTABLE CXnNic : public CXnBase
{
// Definitions -----------------------------------------------------------------------
struct XNADDRXBDM
{
BYTE bSizeOfStruct; // sizeof(XNADDR)
BYTE bFlags; // XNET_XNADDR_* flags below
BYTE abEnet[6]; // Ethernet MAC address
IN_ADDR ina; // IP address (zero if not static/DHCP)
IN_ADDR inaOnline; // Online IP address (zero if not online)
WORD wPortOnline; // Online port (zero if not online)
BYTE abIdOnline[20]; // Online identifier (zero if not online)
};
// External --------------------------------------------------------------------------
public:
HAL_DECLARE_NEW_DELETE(CXnNic)
BOOL NicXmitReady();
void NicXmit(CPacket * ppkt);
VIRTUAL void NicTimer();
#if defined(XNET_FEATURE_XBDM_CLIENT) || defined(XNET_FEATURE_XBDM_SERVER)
DWORD NicGetOtherXnAddr(XNADDR * pxna);
#endif
protected:
NTSTATUS NicInit(XNetInitParams * pxnip);
INLINE INT NicConfig(const XNetConfigParams * pxncp) { return(0); }
void NicStart();
void NicFlush();
void NicStop();
void NicTerm();
VIRTUAL void EnetRecv(CPacket * ppkt, UINT uiType) VPURE;
VIRTUAL void EnetPush() VPURE;
// Internal --------------------------------------------------------------------------
private:
INLINE XmitDesc * PxdNext(XmitDesc * pxd) { return(pxd == _pxdLast ? _pxdFirst : (pxd + 1)); }
INLINE RecvDesc * PrdNext(RecvDesc * prd) { return(prd == _prdLast ? _prdFirst : (prd + 1)); }
INLINE DWORD_PTR PhyAddr(void * pv) { return((DWORD_PTR)pv + _dwPhyOff); }
INLINE void * VirAddr(DWORD_PTR dw) { return((void *)(dw - _dwPhyOff)); }
void NicStartXmitRecv();
void NicStopXmitRecv();
static BOOLEAN NicIsr(PKINTERRUPT, PVOID pvContext);
BOOLEAN NicProcessIsr();
static void NicDpc(PKDPC dpc, void * pvContext, void * pvArg1, void * pvArg2);
void NicProcessDpc();
void NicMiiInterrupt(DWORD dwMintr, BOOL fInit);
void NicRecvInterrupt();
void NicXmitInterrupt();
static void HalShutdownNotification(HAL_SHUTDOWN_REGISTRATION * pHalShutdownReg);
class CXbdmClient
{
public:
INLINE CXnNic * GetXnNic();
virtual void XmitComplete(void * pvPkt);
virtual void EnetRecv(UINT uiFlags, void * pv, UINT cb, UINT uiType);
virtual void EnetPush();
virtual DWORD GetXnAddr(XNADDRXBDM * pxnaXbdm);
};
class CXbdmServer
{
public:
// This magic cookie on the XBDM server CXnNic protects the client from connecting
// to an incompatible version. We only change it when this interface changes in
// a non-backward compatible way.
#define XBDM_SERVER_COOKIE 'XBD6'
CXbdmServer() { _dwCookie = XBDM_SERVER_COOKIE; }
BOOL IsValidServer() { return(_dwCookie == XBDM_SERVER_COOKIE); }
INLINE CXnNic * GetXnNic();
virtual void NicStop();
virtual NTSTATUS InitClient(UINT cfgRecvQ, UINT cfgXmitQ, CEnetAddr * pea, BOOL * pfLinkIsUp);
virtual void AttachClient(CXbdmClient * pXbdmClient);
virtual void DetachClient();
virtual DWORD GetXnAddr(XNADDRXBDM * pxnaXbdm);
virtual void Xmit(void * pvPkt, void * pv, UINT cb);
virtual BOOL XmitReady();
DWORD _dwCookie;
};
class CXbdmPacket : public CPacket
{
public:
void * _pvPkt; // Client's packet pointer
};
#ifdef XNET_FEATURE_STATS
#define STATINC(n) StatInc(offsetof(NICSTATS, n))
#define STATINC_(x,n) if (x) STATINC(n)
void StatInit();
void StatTerm();
void StatInc(UINT iStat);
void StatTimer(CTimer * pt);
#else
#define STATINC(n)
#define STATINC_(x,n)
INLINE void StatInit() {};
INLINE void StatTerm() {};
#endif
// Data ------------------------------------------------------------------------------
public:
CEnetAddr _ea; // Ethernet address
private:
KDPC _dpc; // DPC object
ULONG _ulIntrVector; // interrupt vector
KIRQL _irqlIntr; // interrupt IRQ level
DWORD _dwRxPollFreq; // Rx polling frequency
DWORD _dwLinkState; // last known link state (from PhyGetLinkState)
BOOL _fXmitFull; // TRUE if _cxdBusy >= _cxdPool
DWORD_PTR _dwPhyOff; // virtual to physical offset
LONG _cxdBusy; // count of busy transmit descriptors
LONG _cxdPool; // number of transmit descriptors (minus 1)
XmitDesc * _pxdFirst; // first transmit descriptor
XmitDesc * _pxdLast; // last transmit descriptor
XmitDesc * _pxdBusy; // first busy transmit descriptor
XmitDesc * _pxdFree; // first free transmit descriptor
CPacketQueue _pqXmit; // queue of packets being transmitted
LONG _crdPool; // number of receive descriptors available
RecvDesc * _prdFirst; // first receive descriptor
RecvDesc * _prdLast; // last receive descriptor
RecvDesc * _prdPtr; // current receive descriptor
HAL_SHUTDOWN_REGISTRATION _HalShutdownReg; // registration for system shutdown
#ifdef XNET_FEATURE_XBDM_CLIENT
CXbdmServer * _pXbdmServer; // Non-NULL when XBDM is running in this process
CXbdmClient _XbdmClient; // The object we give to the XBDM server
#endif
#ifdef XNET_FEATURE_XBDM_SERVER
CXbdmClient * _pXbdmClient; // Non-NULL when the title stack is attached
CXbdmServer _XbdmServer; // The object we give to the XBDM client
CEnetAddr _eaClient; // Ethernet address of title stack
CPacketQueue _pqClient; // Packet queue of client packets
CXbdmPacket * _ppktXbdm; // Vector of CXbdmPacket structures
#endif
#ifdef XNET_FEATURE_STATS
NICSTATS _NicStats; // statistics
NICSTATS _NicStatsLast; // statistics at last report
CTimer _timerStats; // statistics timer
#endif
private:
static KINTERRUPT s_InterruptObject;
};
#endif // _NICX_H_