2009-03-04 22:02:13 +01:00
|
|
|
/*
|
|
|
|
* 3c90x.c -- This file implements the 3c90x driver for etherboot. Written
|
|
|
|
* by Greg Beeley, Greg.Beeley@LightSys.org. Modified by Steve Smith,
|
|
|
|
* Steve.Smith@Juno.Com. Alignment bug fix Neil Newell (nn@icenoir.net).
|
|
|
|
*
|
2010-04-19 21:16:01 +02:00
|
|
|
* Port from etherboot to iPXE API, implementation of tx/rx ring support
|
2009-03-04 22:02:13 +01:00
|
|
|
* by Thomas Miletich, thomas.miletich@gmail.com
|
|
|
|
* Thanks to Marty Connor and Stefan Hajnoczi for their help and feedback.
|
|
|
|
*
|
|
|
|
* This program Copyright (C) 1999 LightSys Technology Services, Inc.
|
|
|
|
* Portions Copyright (C) 1999 Steve Smith
|
|
|
|
*
|
|
|
|
* This program may be re-distributed in source or binary form, modified,
|
|
|
|
* sold, or copied for any purpose, provided that the above copyright message
|
|
|
|
* and this text are included with all source copies or derivative works, and
|
|
|
|
* provided that the above copyright message and this text are included in the
|
|
|
|
* documentation of any binary-only distributions. This program is distributed
|
|
|
|
* WITHOUT ANY WARRANTY, without even the warranty of FITNESS FOR A PARTICULAR
|
|
|
|
* PURPOSE or MERCHANTABILITY. Please read the associated documentation
|
|
|
|
* "3c90x.txt" before compiling and using this driver.
|
|
|
|
*
|
|
|
|
* --------
|
|
|
|
*
|
|
|
|
* Program written with the assistance of the 3com documentation for
|
|
|
|
* the 3c905B-TX card, as well as with some assistance from the 3c59x
|
|
|
|
* driver Donald Becker wrote for the Linux kernel, and with some assistance
|
|
|
|
* from the remainder of the Etherboot distribution.
|
|
|
|
*
|
|
|
|
* REVISION HISTORY:
|
|
|
|
*
|
|
|
|
* v0.10 1-26-1998 GRB Initial implementation.
|
|
|
|
* v0.90 1-27-1998 GRB System works.
|
|
|
|
* v1.00pre1 2-11-1998 GRB Got prom boot issue fixed.
|
|
|
|
* v2.0 9-24-1999 SCS Modified for 3c905 (from 3c905b code)
|
|
|
|
* Re-wrote poll and transmit for
|
|
|
|
* better error recovery and heavy
|
|
|
|
* network traffic operation
|
|
|
|
* v2.01 5-26-2003 NN Fixed driver alignment issue which
|
|
|
|
* caused system lockups if driver structures
|
|
|
|
* not 8-byte aligned.
|
|
|
|
* v2.02 11-28-2007 GSt Got polling working again by replacing
|
|
|
|
* "for(i=0;i<40000;i++);" with "mdelay(1);"
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* indent options: indent -kr -i8 3c90x.c
|
|
|
|
*/
|
|
|
|
|
2009-05-01 16:41:06 +02:00
|
|
|
FILE_LICENCE ( BSD2 );
|
|
|
|
|
2009-03-04 22:02:13 +01:00
|
|
|
#ifndef __3C90X_H_
|
|
|
|
#define __3C90X_H_
|
|
|
|
|
|
|
|
static struct net_device_operations a3c90x_operations;
|
|
|
|
|
|
|
|
#define XCVR_MAGIC (0x5A00)
|
|
|
|
|
|
|
|
/* 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 {
|
|
|
|
winNone = 0xff,
|
|
|
|
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, /* */
|
|
|
|
};
|
|
|
|
|
2011-02-01 23:10:18 +01:00
|
|
|
enum GlobalResetParams {
|
|
|
|
globalResetAll = 0,
|
|
|
|
globalResetMaskNetwork = (1<<2),
|
|
|
|
globalResetMaskAll = 0x1ff,
|
|
|
|
};
|
|
|
|
|
2009-03-04 22:02:13 +01:00
|
|
|
enum FrameStartHeader {
|
|
|
|
fshTxIndicate = 0x8000,
|
|
|
|
fshDnComplete = 0x10000,
|
2013-08-19 13:16:27 +02:00
|
|
|
fshRndupDefeat = 0x10000000,
|
2009-03-04 22:02:13 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
enum UpDownDesc {
|
|
|
|
upLastFrag = (1 << 31),
|
|
|
|
downLastFrag = (1 << 31),
|
|
|
|
};
|
|
|
|
|
|
|
|
enum UpPktStatus {
|
|
|
|
upComplete = (1 << 15),
|
|
|
|
upError = (1 << 14),
|
|
|
|
};
|
|
|
|
|
|
|
|
enum Stalls {
|
|
|
|
upStall = 0x00,
|
|
|
|
upUnStall = 0x01,
|
|
|
|
|
|
|
|
dnStall = 0x02,
|
|
|
|
dnUnStall = 0x03,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum Resources {
|
|
|
|
resRxRing = 0x00,
|
|
|
|
resTxRing = 0x02,
|
|
|
|
resRxIOBuf = 0x04
|
|
|
|
};
|
|
|
|
|
|
|
|
enum eeprom {
|
|
|
|
eepromBusy = (1 << 15),
|
|
|
|
eepromRead = ((0x02) << 6),
|
|
|
|
eepromRead_556 = 0x230,
|
|
|
|
eepromHwAddrOffset = 0x0a,
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Bit 4 is only used in revison B and upwards */
|
|
|
|
enum linktype {
|
|
|
|
link10BaseT = 0x00,
|
|
|
|
linkAUI = 0x01,
|
|
|
|
link10Base2 = 0x03,
|
|
|
|
link100BaseFX = 0x05,
|
|
|
|
linkMII = 0x06,
|
|
|
|
linkAutoneg = 0x08,
|
|
|
|
linkExternalMII = 0x09,
|
|
|
|
};
|
|
|
|
|
|
|
|
/* 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)
|
|
|
|
|
|
|
|
/* Buffer sizes */
|
|
|
|
#define TX_RING_SIZE 8
|
|
|
|
#define RX_RING_SIZE 8
|
|
|
|
#define TX_RING_ALIGN 16
|
|
|
|
#define RX_RING_ALIGN 16
|
|
|
|
#define RX_BUF_SIZE 1536
|
|
|
|
|
|
|
|
/* Timeouts for eeprom and command completion */
|
|
|
|
/* Timeout 1 second, to be save */
|
|
|
|
#define EEPROM_TIMEOUT 1 * 1000 * 1000
|
|
|
|
|
|
|
|
/* TX descriptor */
|
|
|
|
struct TXD {
|
|
|
|
volatile unsigned int DnNextPtr;
|
|
|
|
volatile unsigned int FrameStartHeader;
|
|
|
|
volatile unsigned int DataAddr;
|
|
|
|
volatile unsigned int DataLength;
|
|
|
|
} __attribute__ ((aligned(8))); /* 64-bit aligned for bus mastering */
|
|
|
|
|
|
|
|
/* RX descriptor */
|
|
|
|
struct RXD {
|
|
|
|
volatile unsigned int UpNextPtr;
|
|
|
|
volatile unsigned int UpPktStatus;
|
|
|
|
volatile unsigned int DataAddr;
|
|
|
|
volatile unsigned int DataLength;
|
|
|
|
} __attribute__ ((aligned(8))); /* 64-bit aligned for bus mastering */
|
|
|
|
|
|
|
|
/* Private NIC dats */
|
|
|
|
struct INF_3C90X {
|
|
|
|
unsigned int is3c556;
|
|
|
|
unsigned char isBrev;
|
|
|
|
unsigned char CurrentWindow;
|
|
|
|
unsigned int IOAddr;
|
|
|
|
unsigned short eeprom[0x21];
|
|
|
|
unsigned int tx_cur; /* current entry in tx_ring */
|
|
|
|
unsigned int tx_cnt; /* current number of used tx descriptors */
|
|
|
|
unsigned int tx_tail; /* entry of last finished packet */
|
|
|
|
unsigned int rx_cur;
|
|
|
|
struct TXD *tx_ring;
|
|
|
|
struct RXD *rx_ring;
|
|
|
|
struct io_buffer *tx_iobuf[TX_RING_SIZE];
|
|
|
|
struct io_buffer *rx_iobuf[RX_RING_SIZE];
|
|
|
|
struct nvs_device nvs;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|