//========================================================================
// Class Name	: NIC_DEVICE_OBJECT
// Purpose		: 
// Autor		: Richard Chuang
// Email		: 
// Description	: 
// Reference    : 
// Copyright    : Copyright (c) 2000-2007 Davicom Inc.  All rights reserved.
// -----------------------------------------------------------------------
// Version		: 3.0.0.1
// Update       : 2008-01-01
// Modified		: Richard Chung
// Description	: 
// -----------------------------------------------------------------------
// How to use: 
// 

#ifndef	__DAVICOM_DEVICE_H__
#define	__DAVICOM_DEVICE_H__

#include	<usb100.h>
#include	<usbdi.h>
#include	<usbtypes.h>


#include	"stdAfx.h"
#include	"exception.h"
#include	"mutex.h"
#include	"queue.h"
#include	"driver.h"

/*****************************************************************************************
 * [MDI-CONTROL-MODE]
 * Add: 所有Device/(of Drivers)都有處理MDI Control的問題, 2008.03.05 -Joseph
 *
 *****************************************************************************************/

#define AUTO_MDIX_MODE			0
#define MDI_MODE				1
#define MDIX_MODE				2
#define MDIX_CNTL_FORCE_MODE	15

extern LPWSTR ModNameT[];
	//= {
	//_T("-HP Auto-MDIX mode"), // 0 (20.5|20.4=x0b)
	//_T("-MDI mode"), // 1 (20.5|20.4=01b)
	//_T("-MDIX mode"), // 2 (20.5|20.4=11b)
	//};
extern LPWSTR ModeNameTbl[];
	//= {
	//_T("-HP Auto-MDIX mode \r\n"), // 0 (20.5|20.4=x0b)
	//_T("-MDI mode \r\n"), // 1 (20.5|20.4=01b)
	//_T("-MDIX mode \r\n"), // 2 (20.5|20.4=11b)
	//};

/*****************************************************************************************
 *
 * Add: 所有Device/(of Drivers)都有處理Link/Speed Control&Status的問題, 2008.03.05 -Joseph
 *
 *****************************************************************************************/

extern LPWSTR LinkNameTbl[]; /* Link Control Mode */
	//= {
	//_T("LINK AUTO"), // 0
	//_T("LINK 10M Half"), // 1
	//_T("LINK 10M Full"), // 2
	//_T("LINK 100M Half"), // 3
	//_T("LINK 100M Full"), // 4
	//_T("LINK LoopBack"), // 5
	//};

extern LPWSTR SpeedNameTbl[]; /* Link Speed Status */
	//= {
	//_T("SPEED NONE"), // 0
	//_T("SPEED 10M Half"), // 1
	//_T("SPEED 10M Full"), // 2
	//_T("SPEED 100M Half"), // 3
	//_T("SPEED 100M Full"), // 4
	//};

/* Link Control Mode */
typedef enum {
	LINKSPEED_AUTO = 0,				/* Auto Negotiation */
	LINKSPEED_HALF10BASE,			/* Half Duplex 10BASE */
	LINKSPEED_FULL10BASE,			/* Full Duplex 10BASE */
	LINKSPEED_HALF100BASE,			/* Half Duplex 100BASE */
	LINKSPEED_FULL100BASE,			/* Full Duplex 100BASE */
	LINKSPEED_LOOPBACK				/* Loopback */
} LinkSpeed;

/* Link Speed Status */
typedef enum {
	NETLINKSTATUS_NONE = 0,			/* not link*/
	NETLINKSTATUS_HALF10BASET,		/* 10BASE-T, Half Duplex */
	NETLINKSTATUS_FULL10BASET,		/* 10BASE-T, Full Duplex */
	NETLINKSTATUS_HALF100BASETX,	/* 100BASE-TX, Half Duplex */
	NETLINKSTATUS_FULL100BASETX		/* 100BASE-TX, Full Duplex */
} NetLinkStatus;

/*
// [ISA-TYPE]
typedef	enum {
	DM9_NCR = 0,
	DM9_NSR,
	DM9_TXCR,
	DM9_TXSR1,
	DM9_TXSR2,
	DM9_RXCR,
	DM9_RXSR,
	DM9_ROCR,  // 0x07
	DM9_BACKTH,
	DM9_PAUSETH,
	DM9_FCR,	
	DM9_EPCNTL,	// 0x0B 
	DM9_EPADDR, // C
	DM9_EPLOW,  // D
	DM9_EPHIGH, // E
	DM9_WCR,
	
	DM9_PAR0 = 0x10,
	DM9_PAR1,
	DM9_PAR2,
	DM9_PAR3,
	DM9_PAR4,
	DM9_PAR5,

	DM9_MAR0 = 0x16,
	DM9_MAR1,
	DM9_MAR2,
	DM9_MAR3,
	DM9_MAR4,
	DM9_MAR5,
	DM9_MAR6,
	DM9_MAR7,
		
	DM9_GPCR = 0x1E,
	DM9_GPR,

	DM9_TRAL = 0x22,
	DM9_TRAH = 0x23,
	
	DM9_VIDL = 0x28,
	DM9_VIDH,
	DM9_PIDL,
	DM9_PIDH,
	
	DM9_CHIPREV = 0x2C,
	DM9_PBCR = 0x38, 
	DM9_INT_PC = 0x39,
	DM9_MONITOR2=	0x41,	

	DM9_SCR		=0x52,
	DM9_VLANCR 	=0x53,
	DM9_PIndex	=0x60,
	DM9_PCTRL	=0x61,
	DM9_PRATE	=0x66,
	DM9_PBW		=0x67,
	DM9_PPRI	=0x6D,
	DM9_VLAN_TAGL=0x6E,
	
	DM9_MRCMDX = 0xF0,
	DM9_MRCMD = 0xF2,

	DM9_MDRAL = 0xF4,
	DM9_MDRAH,

	DM9_MWCMDX = 0xF6,
	DM9_MWCMD = 0xF8,

	DM9_MDWAL = 0xFA,
	DM9_MDWAH = 0xFB,
	
	DM9_TXLENL = 0xFC,
	DM9_TXLENH,

	DM9_ISR = 0xFE,
	DM9_IMR
		
} DM9000_REGISTER_TYPE;
*/

/********************************************************************************
 *
 * Constant Parameters
 *
 ********************************************************************************/

#define	PEL_SFT	0

/*
 * Network Control Register(NCR)
 */
#define bRST		(0x1<<PEL_SFT)
#define bLBK0		(0x2<<PEL_SFT)
#define bLBK1		(0x4<<PEL_SFT)
#define bFDX		(0x8<<PEL_SFT)
#define bFCOL		(0x10<<PEL_SFT)
#define bWAKEEN		(0x40<<PEL_SFT)
#define	bLB_NORMAL	(0)
#define bLB_INTERNAL	(bLBK0)
#define	bLB_EXTERNAL	(bLBK1)

/*
 * Network Status Register (NSR)
 */
#define bRXOV		(0x2<<PEL_SFT)
#define bTX1END		(0x4<<PEL_SFT)
#define bTX2END		(0x8<<PEL_SFT)
#define bWAKEST		(0x20<<PEL_SFT)
#define bNSRLINKST	(0x40<<PEL_SFT)
#define bSPEED		(0x80<<PEL_SFT)


#define	MIIADDR_SPSTAT		(17)
#define MIIADDR_SCFG		(20)

/* Basic Mode Control Register (BMCR) */
#define	bMII_BMCR_RESET		(0x8000)		/* Reset */
#define	bMII_BMCR_LOOPBACK	(0x4000)		/* loopback */
#define	bMII_BMCR_SPEED		(0x2000)		/* Speed select */
#define	bMII_BMCR_AUTO		(0x1000)		/* Auto-negotiation enable */
#define	bMII_BMCR_POWERDOWN	(0x0800)		/* Power Down */
#define	bMII_BMCR_ISOLATE	(0x0400)		/* Isolate */
#define	bMII_BMCR_RESTART	(0x0200)		/* Restart auto-negotiation */
#define	bMII_BMCR_DUPLEX	(0x0100)		/* Duplex mode */
#define	bMII_BMCR_COLLISION	(0x0080)		/* Collision test */



//==============================================================================
//#define DAVICOM_NIC_DEVICE_VERSION		_T("3.0.0.2")		// Major.Minor.Release.Built
//#define DAVICOM_NIC_DEVICE_RELEASE		_T("2008/01/17")	// YYYY/MM/DD
//==============================================================================


typedef	enum _DEVICE_IO_MODE_
{
	BYTE_MODE=1,
	WORD_MODE=2,
	DWORD_MODE=4,
} DEVICE_IO_MODE;

typedef	enum _NIC_HW_STATUS_TYPE_
{
	NIC_HW_OK,
	NIC_HW_TX_IDLE,
	NIC_HW_TX_BUSY,
} NIC_HW_STATUS_TYPE;

#ifdef	IMPL_STATISTICS
#define	REPORT(evt,val)	if((val)) DeviceReportStatistics(evt,val)
#else
#define	REPORT(evt,val)
#endif

#ifdef	IMPL_RESET
#define	CHECK_SHUTDOWN()	if(m_fShutdown) break
#else
#define	CHECK_SHUTDOWN()
#endif

/********************************************************************************
 *
 * EEPROM 93C46 Parameters
 *
 ********************************************************************************/
#define	BITS_PER_BYTE	8

#define EEPROM_93C46_BITS				1024
#define EEPROM_93C46_SIZE				(EEPROM_93C46_BITS/BITS_PER_BYTE)
#define EEPROM_93C46_MAX_CYCLES			25
#define	EEPROM_93C46_ADDRESS_BITS		6
#define	EEPROM_93C46_DATA_BITS			16
#define EEPROM_93C46_DELAY				20
typedef	unsigned short EEPROM_93C46_DATA_TYPE;

/********************************************************************************
 *
 * EEPROM Parameters
 *
 ********************************************************************************/

#define	EEPROM_SIZE			EEPROM_93C46_SIZE
#define	EEPROM_MAX_CYCLES	EEPROM_93C46_MAX_CYCLES
#define	EEPROM_DELAY		EEPROM_93C46_DELAY
#define	EEPROM_ADDRESS_BITS EEPROM_93C46_ADDRESS_BITS
#define	EEPROM_DATA_BITS 	EEPROM_93C46_DATA_BITS
#define	EEPROM_DATA_TYPE	EEPROM_93C46_DATA_TYPE

/********************************************************************************
 *
 * PHY Parameters
 *
 ********************************************************************************/

#define MII_INTERNAL_PHY_ADDR		1
#define	MII_PHY_ADDR_LEN	5
#define	MII_REG_ADDR_LEN	5
#define	MII_DELAY			20
#define	MII_PREAMBLES		32

#define MII_OFFSET_BMCR		0x00
#define MII_OFFSET_BMSR		0x01
#define MII_OFFSET_OUI_M	0x02
#define MII_OFFSET_OUI_L	0x03
#define MII_OFFSET_ANAR		0x04
#define MII_OFFSET_ALPAR	0x05

/********************************************************************************
 *
 * Configuration definitions
 *
 ********************************************************************************/

#define CONNECTION_NONE             0x00000000
#define CONNECTION_AUTO             0x00000001
#define CONNECTION_10_HALF          0x00000002
#define CONNECTION_10_FULL          0x00000003
#define CONNECTION_100_HALF         0x00000004
#define CONNECTION_100_FULL         0x00000005
#define CONNECTION_1M8_HPNA         0x00000100
#define CONNECTION_10M8_HPNA        0x00000200

extern "C" void DeviceTimerTrunkRoutine(LPVOID,LPVOID,LPVOID,LPVOID);

/******************************************************************************
 *
 * . about the DeviceOnSetupFilter
 *
 *	Basically, filter modification is one memoryless task. The driver needs not
 *	to remember the last state of filter. It simply sets the filter to meet
 *	the request.
 *	The driver object will call DeviceOnSetupFilter at the late stage of
 *	InitialHardware for filter reset. The device object need call this
 *	function at DeviceReset routine if the reset action will impact the filter.
 *	The driver will later call this routine when NDIS submits set request.
 *
 *	Argument zero means reset the filter, the routine should set the NIC in
 *	unicast mode only and clear the multicast list and counts.
 *
 *****************************************************************************/
class	NIC_DEVICE_OBJECT
{
public:
	//==========================================================================
	// Constructor/Destrcutor
	//==========================================================================
	NIC_DEVICE_OBJECT(NIC_DRIVER_OBJECT* pUpper,PVOID pVoid);
	~NIC_DEVICE_OBJECT();

	//==========================================================================
	// Member functions
	//==========================================================================


public:

	void	DeviceReportStatistics(U32,U32);
#if LEGAL_PATENT
	U32		DeviceCalculateCRC32(PU8 ptrBuffer, int nLength);
#endif
	U32		DeviceCalculateCRC32(PU8 ptrBuffer, int nLength, BOOL bReservse=TRUE);

	//--------------------------------------------------------------------------
	// device initialize and ...
	//--------------------------------------------------------------------------
	//(+)2007-11-02 Richard Chung 
//	virtual void	InitialConfigurations(NDIS_HANDLE hConfig);	// add by Richard Chung
	virtual void	InitialConfigurations(NDIS_HANDLE hWrapperConfiguration);	// add by Richard Chung
	virtual void	RegisterConfigurations();	// add by Richard Chung

	
	//(-)2007-11-02 Richard Chung 

	//--------------------------------------------------------------------------
	// device attributes or characteristics
	//--------------------------------------------------------------------------
	virtual LPCTSTR		GetDriverVersion(void)=0;		// abstract function
	virtual LPCTSTR		GetReleaseDate(void)=0;


protected:
	//(+)2007-10-31 Richard Chung 
	//virtual	U32		DevicePCIID(void)=0;			// abstract function
	virtual	DWORD		GetDriverChipID(void)=0;		// Get ChipID from Driver(abstract function)
	virtual	DWORD		GetChipID(void)=0;				// Get ChipID from Register(abstract function)

	//(-)2007-10-31 Richard Chung 
public:
	//(+)2007-11-05 Richard Chung 
	//virtual	PU8		DeviceMacAddress(PU8);
	//virtual	U16		DeviceVendorID(void);
	//virtual	U16		DeviceProductID(void);
	//virtual	BOOL	GetMacAddress(PU8 pbMacAddress);
	virtual	PU8	GetMacAddress(PU8 pbMacAddress);
	virtual	WORD	GetVendorID(void);
	virtual	WORD	GetProductID(void);
	//(-)2007-11-05 Richard Chung 


	virtual	void	DeviceRegisterAdapter(void);
	virtual	BOOL	DeviceQueryInformation(
		OUT NDIS_STATUS		*Status,
		IN NDIS_OID		Oid,
		IN PVOID		InfoBuffer, 
		IN ULONG		InfoBufferLength, 
		OUT PULONG		BytesWritten,
		OUT PULONG		BytesNeeded);//{ return FALSE; }
	virtual	BOOL	DeviceSetInformation(
		OUT NDIS_STATUS		*Status,
		IN NDIS_OID		Oid,
		IN PVOID		InfoBuffer, 
		IN ULONG		InfoBufferLength, 
		OUT PULONG		BytesRead,
		OUT PULONG		BytesNeeded);//{ return FALSE; }

	//(+)2007-11-01 Richard Chung 
protected:
//public:
	//virtual	PCONFIG_PARAMETER	DeviceConfigureParameters(void)=0; // abstract function
	virtual	PCONFIG_PARAMETER	GetConfigureParameters(void)=0; // abstract function
	virtual	void	InitialDefaultSettings(void);
	virtual	void	InitialEepromFieldPosition()=0;	//DeviceSetEepromFormat(void)=0; // abstract function
	//(-)2007-11-01 Richard Chung 



	//--------------------------------------------------------------------------
	// device control routines
	//--------------------------------------------------------------------------

public:
	virtual void	DeviceStart(void)=0;					// abstract function
	virtual int		DeviceOnSetupFilter(U32 dw)=0;			// abstract function
	virtual	void	DeviceHalt(void)=0;						// abstract function

	//(+)2007-11-01 Richard Chung 
protected:
//public:
	//virtual void	EDeviceValidateConfigurations(void)=0;	// abstract function
	virtual void	ValidateConfigurations(void)=0;	// abstract function
	virtual	void	InitialHardware(int)=0;				// abstract function
	//(+)2008-01-17 Richard Chung
	virtual void	InitialChip(void)=0;	
	virtual WORD	LinkState_Get_BMSR(int i)= 0;	
	virtual WORD	LinkState_Get_DSCSR(LPWSTR head, int i)= 0;
	virtual WORD	LinkState_Get_DSCSR_EX(LPWSTR head, LPWSTR regname, int i)= 0;
	virtual WORD	LinkState_Get_SCFG(LPWSTR head, int i)= 0;
	//(-)2008-01-17 Richard Chung	
	virtual	void	DeviceRetriveConfigurations(NDIS_HANDLE hConfig);
	virtual	void	RegisterIoSpace(void);
	virtual	void	RegisterInterrupt(void); //EDeviceRegisterInterrupt(void);
	//(-)2007-11-01 Richard Chung 


	//--------------------------------------------------------------------------
	// device access routines
	//--------------------------------------------------------------------------
protected:
	virtual DWORD	DeviceReadPort(DWORD dwPort)=0;				// abstract function
	virtual DWORD	DeviceWritePort(DWORD dwPort,DWORD dwValue)=0;	// abstract function
	virtual	WORD	DeviceReadEeprom(DWORD dwAddress)=0;		// abstract function
	virtual	WORD	DeviceWriteEeprom(DWORD dwAddress,WORD wValue)=0; // abstract function
	virtual WORD	DeviceReadPhy(DWORD dwPhyRegister,DWORD dwOffset)=0;		// abstract function
	virtual WORD	DeviceWritePhy(DWORD dwPhyRegister,DWORD dwOffset,WORD wValue)=0; // abstract function

	virtual	void	LoadEeprom(void); //EDeviceLoadEeprom(void);

	//virtual void	InitialLinkProg(int n)=0;

	//(+)2007-11-05 Richard Chung
	// Device link state routines
	virtual WORD	GetLinkState()=0;
	virtual void	PrintMessageCtrl(WORD wLinkState)= 0;
	virtual BOOL	LinkState_LinkUp(int i)= 0;
	virtual int		LnkStat_GetLinkStatus(void)= 0;
	//(-)2007-11-05 Richard Chung


public:

	WORD DeviceCheckLink(void); //  // Device-Check-For-Link() ;Public for inheritance

	virtual int		DeviceSend(PCQUEUE_GEN_HEADER)=0;		// abstract function
	virtual BOOL	DeviceCheckForHang(void);
	virtual	U32		DeviceHardwareStatus(void);
	virtual	void	DeviceReset(void)=0;					// abstract function
	virtual	void	DeviceResetPHYceiver(void)=0;			// abstract function

	virtual	void	DbgDUMP_REGs(TCHAR *CFN)=0;					// abstract function [JJ-20080118]
	
	virtual	void DeviceEnableInterrupt(void)=0;				// abstract function
	virtual	void DeviceDisableInterrupt(void)=0;			// abstract function
	virtual	void DeviceEnableReceive(void)=0;				// abstract function
	virtual	void DeviceDisableReceive(void)=0;				// abstract function
	virtual	void DeviceEnableTransmit(void);
	virtual	void DeviceDisableTransmit(void);
	virtual	U32 DeviceGetInterruptStatus(void)=0;			// abstract function
	virtual	U32 DeviceSetInterruptStatus(U32)=0;			// abstract function
	virtual	U32	DeviceGetReceiveStatus(void)=0;				// abstract function
	virtual	void DeviceInterruptEventHandler(DWORD dwValue)=0; // abstract function


	virtual void DeviceIndication(U32 dwIndication);
	virtual	void DeviceSendCompleted(PCQUEUE_GEN_HEADER pObject);
	virtual	void DeviceReceiveIndication(int nCurr,PVOID pVoid,int nLength);


	BOOL	DevicePolling(
		U32	uPort,
		U32	uMask,
		U32	uExpected,
		U32	uInterval=20,	/* uInterval in micro-second */
		U32	uRetries=WAIT_FOREVER);

	// Device timer routine
	virtual	void	DeviceOnTimer(void);
	virtual void	DeviceInitializeTimer(void);
	virtual void	DeviceCancelTimer(void);
	virtual void	DeviceSetTimer(U32 milliseconds);

#ifdef	IMPL_DEVICE_ISR
	virtual	void	DeviceIsr(U32)=0; // abstract function
#endif                
	//(+)2007-10-23 Richard Chung
//	virtual int		DeviceQueryTxResources(void)=0;
	virtual BOOL	DeviceQueryTxResources(void);


	//(-)2007-10-23 Richard Chung

	/* USB CHANGED */
	virtual void InitialUsbParameters(USB_HANDLE pHandle,LPCUSB_FUNCS lpFunctions,LPCUSB_INTERFACE lpInterface);//EDeviceSetUsbParameters

protected:
	void SetConnectionStatus(bool bConnected);


protected:

private:
	BOOL AssignDummyMacAddress();

	//==========================================================================
	// Data Member
	//==========================================================================
public:

	class NIC_DRIVER_OBJECT*	m_pUpper;
	
	BOOL		m_fTxEnabled;

	CQueue	m_TQStandby;
	CQueue	m_TQWaiting;
	
	CMutex	m_mutexRxValidate;
	CMutex	m_mutexTxValidate;
	
	U32		m_szConfigures[CID_SIZE];
	DWORD	m_dwEepromFiledPosition[EID_SIZE];		// EEPROM Format position
	U32		m_szCurrentSettings[SID_SIZE];
	U32		m_szStatistics[TID_SIZE];
	U32		m_szLastStatistics[TID_SIZE];
	U8		m_szMulticastList[MAX_MULTICAST_LIST][ETH_ADDRESS_LENGTH];
	int		m_nMulticasts;
	int		m_nResetCounts;
public:

#ifdef	IMPL_RESET
	BOOL	m_fShutdown;
#endif
		
	NDIS_MINIPORT_INTERRUPT	m_InterruptHandle;
	
	CMutex	m_mutexTimer;
	NDIS_MINIPORT_TIMER	m_timerObject;

	CMutex	m_mutexEEPROM;
	U8		m_btEeprom[EEPROM_SIZE];

protected:
	//int 		m_nOldLinkState;
	WORD	m_wLinkState;
	BOOL	m_CHIPMsgCtrl;
	int		m_Counter;
	int		m_Counter_Fail;
	int		m_Counter_Mix;

};

#endif // __DAVICOM_DEVICE_H__