📄 3c90x.c
字号:
#include "includes.h"
#include "pci.h"
#include "ether.h"
#include "nic.h"
#define XCVR_MAGIC (0x5A00)
/** any single transmission fails after 16 collisions or other errors
** this is the number of times to retry the transmission -- this should
** be plenty
**/
#define XMIT_RETRIES 250
#undef virt_to_bus
#define virt_to_bus(x) (FP_OFF(x) + FP_SEG(x) * 16)
/*** Register definitions for the 3c905 ***/
enum Registers
{
regPowerMgmtCtrl_w = 0x7c, /** 905B Revision Only **/
regUpMaxBurst_w = 0x7a, /** 905B Revision Only **/
regDnMaxBurst_w = 0x78, /** 905B Revision Only **/
regDebugControl_w = 0x74, /** 905B Revision Only **/
regDebugData_l = 0x70, /** 905B Revision Only **/
regRealTimeCnt_l = 0x40, /** Universal **/
regUpBurstThresh_b = 0x3e, /** 905B Revision Only **/
regUpPoll_b = 0x3d, /** 905B Revision Only **/
regUpPriorityThresh_b = 0x3c, /** 905B Revision Only **/
regUpListPtr_l = 0x38, /** Universal **/
regCountdown_w = 0x36, /** Universal **/
regFreeTimer_w = 0x34, /** Universal **/
regUpPktStatus_l = 0x30, /** Universal with Exception, pg 130 **/
regTxFreeThresh_b = 0x2f, /** 90X Revision Only **/
regDnPoll_b = 0x2d, /** 905B Revision Only **/
regDnPriorityThresh_b = 0x2c, /** 905B Revision Only **/
regDnBurstThresh_b = 0x2a, /** 905B Revision Only **/
regDnListPtr_l = 0x24, /** Universal with Exception, pg 107 **/
regDmaCtrl_l = 0x20, /** Universal with Exception, pg 106 **/
/** **/
regIntStatusAuto_w = 0x1e, /** 905B Revision Only **/
regTxStatus_b = 0x1b, /** Universal with Exception, pg 113 **/
regTimer_b = 0x1a, /** Universal **/
regTxPktId_b = 0x18, /** 905B Revision Only **/
regCommandIntStatus_w = 0x0e, /** Universal (Command Variations) **/
};
/** following are windowed registers **/
enum Registers7
{
regPowerMgmtEvent_7_w = 0x0c, /** 905B Revision Only **/
regVlanEtherType_7_w = 0x04, /** 905B Revision Only **/
regVlanMask_7_w = 0x00, /** 905B Revision Only **/
};
enum Registers6
{
regBytesXmittedOk_6_w = 0x0c, /** Universal **/
regBytesRcvdOk_6_w = 0x0a, /** Universal **/
regUpperFramesOk_6_b = 0x09, /** Universal **/
regFramesDeferred_6_b = 0x08, /** Universal **/
regFramesRecdOk_6_b = 0x07, /** Universal with Exceptions, pg 142 **/
regFramesXmittedOk_6_b = 0x06, /** Universal **/
regRxOverruns_6_b = 0x05, /** Universal **/
regLateCollisions_6_b = 0x04, /** Universal **/
regSingleCollisions_6_b = 0x03, /** Universal **/
regMultipleCollisions_6_b = 0x02, /** Universal **/
regSqeErrors_6_b = 0x01, /** Universal **/
regCarrierLost_6_b = 0x00, /** Universal **/
};
enum Registers5
{
regIndicationEnable_5_w = 0x0c, /** Universal **/
regInterruptEnable_5_w = 0x0a, /** Universal **/
regTxReclaimThresh_5_b = 0x09, /** 905B Revision Only **/
regRxFilter_5_b = 0x08, /** Universal **/
regRxEarlyThresh_5_w = 0x06, /** Universal **/
regTxStartThresh_5_w = 0x00, /** Universal **/
};
enum Registers4
{
regUpperBytesOk_4_b = 0x0d, /** Universal **/
regBadSSD_4_b = 0x0c, /** Universal **/
regMediaStatus_4_w = 0x0a, /** Universal with Exceptions, pg 201 **/
regPhysicalMgmt_4_w = 0x08, /** Universal **/
regNetworkDiagnostic_4_w = 0x06, /** Universal with Exceptions, pg 203 **/
regFifoDiagnostic_4_w = 0x04, /** Universal with Exceptions, pg 196 **/
regVcoDiagnostic_4_w = 0x02, /** Undocumented? **/
};
enum Registers3
{
regTxFree_3_w = 0x0c, /** Universal **/
regRxFree_3_w = 0x0a, /** Universal with Exceptions, pg 125 **/
regResetMediaOptions_3_w = 0x08, /** Media Options on B Revision, **/
/** Reset Options on Non-B Revision **/
regMacControl_3_w = 0x06, /** Universal with Exceptions, pg 199 **/
regMaxPktSize_3_w = 0x04, /** 905B Revision Only **/
regInternalConfig_3_l = 0x00, /** Universal, different bit **/
/** definitions, pg 59 **/
};
enum Registers2
{
regResetOptions_2_w = 0x0c, /** 905B Revision Only **/
regStationMask_2_3w = 0x06, /** Universal with Exceptions, pg 127 **/
regStationAddress_2_3w = 0x00, /** Universal with Exceptions, pg 127 **/
};
enum Registers1
{
regRxStatus_1_w = 0x0a, /** 90X Revision Only, Pg 126 **/
};
enum Registers0
{
regEepromData_0_w = 0x0c, /** Universal **/
regEepromCommand_0_w = 0x0a, /** Universal **/
regBiosRomData_0_b = 0x08, /** 905B Revision Only **/
regBiosRomAddr_0_l = 0x04, /** 905B Revision Only **/
};
/*** The names for the eight register windows ***/
enum Windows
{
winPowerVlan7 = 0x07,
winStatistics6 = 0x06,
winTxRxControl5 = 0x05,
winDiagnostics4 = 0x04,
winTxRxOptions3 = 0x03,
winAddressing2 = 0x02,
winUnused1 = 0x01,
winEepromBios0 = 0x00,
};
/*** Command definitions for the 3c90X ***/
enum Commands
{
cmdGlobalReset = 0x00, /** Universal with Exceptions, pg 151 **/
cmdSelectRegisterWindow = 0x01, /** Universal **/
cmdEnableDcConverter = 0x02, /** **/
cmdRxDisable = 0x03, /** **/
cmdRxEnable = 0x04, /** Universal **/
cmdRxReset = 0x05, /** Universal **/
cmdStallCtl = 0x06, /** Universal **/
cmdTxEnable = 0x09, /** Universal **/
cmdTxDisable = 0x0A, /** **/
cmdTxReset = 0x0B, /** Universal **/
cmdRequestInterrupt = 0x0C, /** **/
cmdAcknowledgeInterrupt = 0x0D, /** Universal **/
cmdSetInterruptEnable = 0x0E, /** Universal **/
cmdSetIndicationEnable = 0x0F, /** Universal **/
cmdSetRxFilter = 0x10, /** Universal **/
cmdSetRxEarlyThresh = 0x11, /** **/
cmdSetTxStartThresh = 0x13, /** **/
cmdStatisticsEnable = 0x15, /** **/
cmdStatisticsDisable = 0x16, /** **/
cmdDisableDcConverter = 0x17, /** **/
cmdSetTxReclaimThresh = 0x18, /** **/
cmdSetHashFilterBit = 0x19, /** **/
};
/*** Values for int status register bitmask **/
#define INT_INTERRUPTLATCH (1<<0)
#define INT_HOSTERROR (1<<1)
#define INT_TXCOMPLETE (1<<2)
#define INT_RXCOMPLETE (1<<4)
#define INT_RXEARLY (1<<5)
#define INT_INTREQUESTED (1<<6)
#define INT_UPDATESTATS (1<<7)
#define INT_LINKEVENT (1<<8)
#define INT_DNCOMPLETE (1<<9)
#define INT_UPCOMPLETE (1<<10)
#define INT_CMDINPROGRESS (1<<12)
#define INT_WINDOWNUMBER (7<<13)
/*** TX descriptor ***/
typedef struct
{
unsigned long DnNextPtr;
unsigned long FrameStartHeader;
unsigned long HdrAddr;
unsigned long HdrLength;
unsigned long DataAddr;
unsigned long DataLength;
}
TXD;
/*** RX descriptor ***/
typedef struct
{
unsigned long UpNextPtr;
unsigned long UpPktStatus;
unsigned long DataAddr;
unsigned long DataLength;
}
RXD;
/*** Global variables ***/
static struct
{
unsigned char isBrev;
unsigned char CurrentWindow;
unsigned long IOAddr;
unsigned char HWAddr[ETH_ALEN];
TXD TransmitDPD;
RXD ReceiveUPD;
}
INF_3C90X;
/*** a3c90x_internal_IssueCommand: sends a command to the 3c90x card
***/
static int
a3c90x_internal_IssueCommand(unsigned short ioaddr, int cmd, int param)
{
unsigned long val;
/** Build the cmd. **/
val = cmd;
val <<= 11;
val |= param;
/** Send the cmd to the cmd register **/
NETCARD_OUTW(val, ioaddr + regCommandIntStatus_w);
/** Wait for the cmd to complete, if necessary **/
while (NETCARD_INW(ioaddr + regCommandIntStatus_w) & INT_CMDINPROGRESS);
return 0;
}
/*** a3c90x_internal_SetWindow: selects a register window set.
***/
static int
a3c90x_internal_SetWindow(unsigned short ioaddr, int window)
{
/** Window already as set? **/
if (INF_3C90X.CurrentWindow == window) return 0;
/** Issue the window command. **/
a3c90x_internal_IssueCommand(ioaddr, cmdSelectRegisterWindow, window);
INF_3C90X.CurrentWindow = window;
return 0;
}
/*** a3c90x_internal_ReadEeprom - read data from the serial eeprom.
***/
static unsigned short
a3c90x_internal_ReadEeprom(unsigned short ioaddr, int address)
{
unsigned short val;
/** Select correct window **/
a3c90x_internal_SetWindow(INF_3C90X.IOAddr, winEepromBios0);
/** Make sure the eeprom isn't busy **/
while((1<<15) & NETCARD_INW(ioaddr + regEepromCommand_0_w));
/** Read the value. **/
NETCARD_OUTW(address + ((0x02)<<6), ioaddr + regEepromCommand_0_w);
while((1<<15) & NETCARD_INW(ioaddr + regEepromCommand_0_w));
val = NETCARD_INW(ioaddr + regEepromData_0_w);
return val;
}
/*** a3c90x_internal_WriteEepromWord - write a physical word of
*** data to the onboard serial eeprom (not the BIOS prom, but the
*** nvram in the card that stores, among other things, the MAC
*** address).
***/
static int
a3c90x_internal_WriteEepromWord(unsigned short ioaddr, int address, unsigned short value)
{
/** Select register window **/
a3c90x_internal_SetWindow(ioaddr, winEepromBios0);
/** Verify Eeprom not busy **/
while((1<<15) & NETCARD_INW(ioaddr + regEepromCommand_0_w));
/** Issue WriteEnable, and wait for completion. **/
NETCARD_OUTW(0x30, ioaddr + regEepromCommand_0_w);
while((1<<15) & NETCARD_INW(ioaddr + regEepromCommand_0_w));
/** Issue EraseRegister, and wait for completion. **/
NETCARD_OUTW(address + ((0x03)<<6), ioaddr + regEepromCommand_0_w);
while((1<<15) & NETCARD_INW(ioaddr + regEepromCommand_0_w));
/** Send the new data to the eeprom, and wait for completion. **/
NETCARD_OUTW(value, ioaddr + regEepromData_0_w);
NETCARD_OUTW(0x30, ioaddr + regEepromCommand_0_w);
while((1<<15) & NETCARD_INW(ioaddr + regEepromCommand_0_w));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -