Home | History | Annotate | Download | only in net
      1 /*
      2  * 3c90x.c -- This file implements the 3c90x driver for etherboot.  Written
      3  * by Greg Beeley, Greg.Beeley (at) LightSys.org.  Modified by Steve Smith,
      4  * Steve.Smith (at) Juno.Com. Alignment bug fix Neil Newell (nn (at) icenoir.net).
      5  *
      6  * Port from etherboot to gPXE API, implementation of tx/rx ring support
      7  * by Thomas Miletich, thomas.miletich (at) gmail.com
      8  * Thanks to Marty Connor and Stefan Hajnoczi for their help and feedback.
      9  *
     10  * This program Copyright (C) 1999 LightSys Technology Services, Inc.
     11  * Portions Copyright (C) 1999 Steve Smith
     12  *
     13  * This program may be re-distributed in source or binary form, modified,
     14  * sold, or copied for any purpose, provided that the above copyright message
     15  * and this text are included with all source copies or derivative works, and
     16  * provided that the above copyright message and this text are included in the
     17  * documentation of any binary-only distributions.  This program is distributed
     18  * WITHOUT ANY WARRANTY, without even the warranty of FITNESS FOR A PARTICULAR
     19  * PURPOSE or MERCHANTABILITY.  Please read the associated documentation
     20  * "3c90x.txt" before compiling and using this driver.
     21  *
     22  * --------
     23  *
     24  * Program written with the assistance of the 3com documentation for
     25  * the 3c905B-TX card, as well as with some assistance from the 3c59x
     26  * driver Donald Becker wrote for the Linux kernel, and with some assistance
     27  * from the remainder of the Etherboot distribution.
     28  *
     29  * REVISION HISTORY:
     30  *
     31  * v0.10	1-26-1998	GRB	Initial implementation.
     32  * v0.90	1-27-1998	GRB	System works.
     33  * v1.00pre1	2-11-1998	GRB	Got prom boot issue fixed.
     34  * v2.0		9-24-1999	SCS	Modified for 3c905 (from 3c905b code)
     35  *					Re-wrote poll and transmit for
     36  *					better error recovery and heavy
     37  *					network traffic operation
     38  * v2.01    5-26-2003 NN Fixed driver alignment issue which
     39  *                  caused system lockups if driver structures
     40  *                  not 8-byte aligned.
     41  * v2.02   11-28-2007 GSt Got polling working again by replacing
     42  * 			"for(i=0;i<40000;i++);" with "mdelay(1);"
     43  *
     44  *
     45  * indent options: indent -kr -i8 3c90x.c
     46  */
     47 
     48 FILE_LICENCE ( BSD2 );
     49 
     50 #ifndef __3C90X_H_
     51 #define __3C90X_H_
     52 
     53 static struct net_device_operations a3c90x_operations;
     54 
     55 #define	XCVR_MAGIC	(0x5A00)
     56 
     57 /* Register definitions for the 3c905 */
     58 enum Registers {
     59 	regPowerMgmtCtrl_w = 0x7c,	/* 905B Revision Only                 */
     60 	regUpMaxBurst_w = 0x7a,	/* 905B Revision Only                 */
     61 	regDnMaxBurst_w = 0x78,	/* 905B Revision Only                 */
     62 	regDebugControl_w = 0x74,	/* 905B Revision Only                 */
     63 	regDebugData_l = 0x70,	/* 905B Revision Only                 */
     64 	regRealTimeCnt_l = 0x40,	/* Universal                          */
     65 	regUpBurstThresh_b = 0x3e,	/* 905B Revision Only                 */
     66 	regUpPoll_b = 0x3d,	/* 905B Revision Only                 */
     67 	regUpPriorityThresh_b = 0x3c,	/* 905B Revision Only                 */
     68 	regUpListPtr_l = 0x38,	/* Universal                          */
     69 	regCountdown_w = 0x36,	/* Universal                          */
     70 	regFreeTimer_w = 0x34,	/* Universal                          */
     71 	regUpPktStatus_l = 0x30,	/* Universal with Exception, pg 130   */
     72 	regTxFreeThresh_b = 0x2f,	/* 90X Revision Only                  */
     73 	regDnPoll_b = 0x2d,	/* 905B Revision Only                 */
     74 	regDnPriorityThresh_b = 0x2c,	/* 905B Revision Only                 */
     75 	regDnBurstThresh_b = 0x2a,	/* 905B Revision Only                 */
     76 	regDnListPtr_l = 0x24,	/* Universal with Exception, pg 107   */
     77 	regDmaCtrl_l = 0x20,	/* Universal with Exception, pg 106   */
     78 	/*                                    */
     79 	regIntStatusAuto_w = 0x1e,	/* 905B Revision Only                 */
     80 	regTxStatus_b = 0x1b,	/* Universal with Exception, pg 113   */
     81 	regTimer_b = 0x1a,	/* Universal                          */
     82 	regTxPktId_b = 0x18,	/* 905B Revision Only                 */
     83 	regCommandIntStatus_w = 0x0e,	/* Universal (Command Variations)     */
     84 };
     85 
     86 /* following are windowed registers */
     87 enum Registers7 {
     88 	regPowerMgmtEvent_7_w = 0x0c,	/* 905B Revision Only                 */
     89 	regVlanEtherType_7_w = 0x04,	/* 905B Revision Only                 */
     90 	regVlanMask_7_w = 0x00,	/* 905B Revision Only                 */
     91 };
     92 
     93 enum Registers6 {
     94 	regBytesXmittedOk_6_w = 0x0c,	/* Universal                          */
     95 	regBytesRcvdOk_6_w = 0x0a,	/* Universal                          */
     96 	regUpperFramesOk_6_b = 0x09,	/* Universal                          */
     97 	regFramesDeferred_6_b = 0x08,	/* Universal                          */
     98 	regFramesRecdOk_6_b = 0x07,	/* Universal with Exceptions, pg 142  */
     99 	regFramesXmittedOk_6_b = 0x06,	/* Universal                          */
    100 	regRxOverruns_6_b = 0x05,	/* Universal                          */
    101 	regLateCollisions_6_b = 0x04,	/* Universal                          */
    102 	regSingleCollisions_6_b = 0x03,	/* Universal                          */
    103 	regMultipleCollisions_6_b = 0x02,	/* Universal                          */
    104 	regSqeErrors_6_b = 0x01,	/* Universal                          */
    105 	regCarrierLost_6_b = 0x00,	/* Universal                          */
    106 };
    107 
    108 enum Registers5 {
    109 	regIndicationEnable_5_w = 0x0c,	/* Universal                          */
    110 	regInterruptEnable_5_w = 0x0a,	/* Universal                          */
    111 	regTxReclaimThresh_5_b = 0x09,	/* 905B Revision Only                 */
    112 	regRxFilter_5_b = 0x08,	/* Universal                          */
    113 	regRxEarlyThresh_5_w = 0x06,	/* Universal                          */
    114 	regTxStartThresh_5_w = 0x00,	/* Universal                          */
    115 };
    116 
    117 enum Registers4 {
    118 	regUpperBytesOk_4_b = 0x0d,	/* Universal                          */
    119 	regBadSSD_4_b = 0x0c,	/* Universal                          */
    120 	regMediaStatus_4_w = 0x0a,	/* Universal with Exceptions, pg 201  */
    121 	regPhysicalMgmt_4_w = 0x08,	/* Universal                          */
    122 	regNetworkDiagnostic_4_w = 0x06,	/* Universal with Exceptions, pg 203  */
    123 	regFifoDiagnostic_4_w = 0x04,	/* Universal with Exceptions, pg 196  */
    124 	regVcoDiagnostic_4_w = 0x02,	/* Undocumented?                      */
    125 };
    126 
    127 enum Registers3 {
    128 	regTxFree_3_w = 0x0c,	/* Universal                          */
    129 	regRxFree_3_w = 0x0a,	/* Universal with Exceptions, pg 125  */
    130 	regResetMediaOptions_3_w = 0x08,	/* Media Options on B Revision,       */
    131 	/* Reset Options on Non-B Revision    */
    132 	regMacControl_3_w = 0x06,	/* Universal with Exceptions, pg 199  */
    133 	regMaxPktSize_3_w = 0x04,	/* 905B Revision Only                 */
    134 	regInternalConfig_3_l = 0x00,	/* Universal, different bit           */
    135 	/* definitions, pg 59                 */
    136 };
    137 
    138 enum Registers2 {
    139 	regResetOptions_2_w = 0x0c,	/* 905B Revision Only                 */
    140 	regStationMask_2_3w = 0x06,	/* Universal with Exceptions, pg 127  */
    141 	regStationAddress_2_3w = 0x00,	/* Universal with Exceptions, pg 127  */
    142 };
    143 
    144 enum Registers1 {
    145 	regRxStatus_1_w = 0x0a,	/* 90X Revision Only, Pg 126          */
    146 };
    147 
    148 enum Registers0 {
    149 	regEepromData_0_w = 0x0c,	/* Universal                          */
    150 	regEepromCommand_0_w = 0x0a,	/* Universal                          */
    151 	regBiosRomData_0_b = 0x08,	/* 905B Revision Only                 */
    152 	regBiosRomAddr_0_l = 0x04,	/* 905B Revision Only                 */
    153 };
    154 
    155 
    156 /* The names for the eight register windows */
    157 enum Windows {
    158 	winNone = 0xff,
    159 	winPowerVlan7 = 0x07,
    160 	winStatistics6 = 0x06,
    161 	winTxRxControl5 = 0x05,
    162 	winDiagnostics4 = 0x04,
    163 	winTxRxOptions3 = 0x03,
    164 	winAddressing2 = 0x02,
    165 	winUnused1 = 0x01,
    166 	winEepromBios0 = 0x00,
    167 };
    168 
    169 
    170 /* Command definitions for the 3c90X */
    171 enum Commands {
    172 	cmdGlobalReset = 0x00,	/* Universal with Exceptions, pg 151 */
    173 	cmdSelectRegisterWindow = 0x01,	/* Universal                         */
    174 	cmdEnableDcConverter = 0x02,	/*                                   */
    175 	cmdRxDisable = 0x03,	/*                                   */
    176 	cmdRxEnable = 0x04,	/* Universal                         */
    177 	cmdRxReset = 0x05,	/* Universal                         */
    178 	cmdStallCtl = 0x06,	/* Universal                         */
    179 	cmdTxEnable = 0x09,	/* Universal                         */
    180 	cmdTxDisable = 0x0A,	/*                                   */
    181 	cmdTxReset = 0x0B,	/* Universal                         */
    182 	cmdRequestInterrupt = 0x0C,	/*                                   */
    183 	cmdAcknowledgeInterrupt = 0x0D,	/* Universal                         */
    184 	cmdSetInterruptEnable = 0x0E,	/* Universal                         */
    185 	cmdSetIndicationEnable = 0x0F,	/* Universal                         */
    186 	cmdSetRxFilter = 0x10,	/* Universal                         */
    187 	cmdSetRxEarlyThresh = 0x11,	/*                                   */
    188 	cmdSetTxStartThresh = 0x13,	/*                                   */
    189 	cmdStatisticsEnable = 0x15,	/*                                   */
    190 	cmdStatisticsDisable = 0x16,	/*                                   */
    191 	cmdDisableDcConverter = 0x17,	/*                                   */
    192 	cmdSetTxReclaimThresh = 0x18,	/*                                   */
    193 	cmdSetHashFilterBit = 0x19,	/*                                   */
    194 };
    195 
    196 enum FrameStartHeader {
    197 	fshTxIndicate = 0x8000,
    198 	fshDnComplete = 0x10000,
    199 };
    200 
    201 enum UpDownDesc {
    202 	upLastFrag = (1 << 31),
    203 	downLastFrag = (1 << 31),
    204 };
    205 
    206 enum UpPktStatus {
    207 	upComplete = (1 << 15),
    208 	upError = (1 << 14),
    209 };
    210 
    211 enum Stalls {
    212 	upStall = 0x00,
    213 	upUnStall = 0x01,
    214 
    215 	dnStall = 0x02,
    216 	dnUnStall = 0x03,
    217 };
    218 
    219 enum Resources {
    220 	resRxRing = 0x00,
    221 	resTxRing = 0x02,
    222 	resRxIOBuf = 0x04
    223 };
    224 
    225 enum eeprom {
    226 	eepromBusy = (1 << 15),
    227 	eepromRead = ((0x02) << 6),
    228 	eepromRead_556 = 0x230,
    229 	eepromHwAddrOffset = 0x0a,
    230 };
    231 
    232 /* Bit 4 is only used in revison B and upwards */
    233 enum linktype {
    234 	link10BaseT = 0x00,
    235 	linkAUI = 0x01,
    236 	link10Base2 = 0x03,
    237 	link100BaseFX = 0x05,
    238 	linkMII = 0x06,
    239 	linkAutoneg = 0x08,
    240 	linkExternalMII = 0x09,
    241 };
    242 
    243 /* Values for int status register bitmask */
    244 #define	INT_INTERRUPTLATCH	(1<<0)
    245 #define INT_HOSTERROR		(1<<1)
    246 #define INT_TXCOMPLETE		(1<<2)
    247 #define INT_RXCOMPLETE		(1<<4)
    248 #define INT_RXEARLY		(1<<5)
    249 #define INT_INTREQUESTED	(1<<6)
    250 #define INT_UPDATESTATS		(1<<7)
    251 #define INT_LINKEVENT		(1<<8)
    252 #define INT_DNCOMPLETE		(1<<9)
    253 #define INT_UPCOMPLETE		(1<<10)
    254 #define INT_CMDINPROGRESS	(1<<12)
    255 #define INT_WINDOWNUMBER	(7<<13)
    256 
    257 /* Buffer sizes */
    258 #define TX_RING_SIZE 8
    259 #define RX_RING_SIZE 8
    260 #define TX_RING_ALIGN 16
    261 #define RX_RING_ALIGN 16
    262 #define RX_BUF_SIZE 1536
    263 
    264 /* Timeouts for eeprom and command completion */
    265 /* Timeout 1 second, to be save */
    266 #define EEPROM_TIMEOUT		1 * 1000 * 1000
    267 
    268 /* TX descriptor */
    269 struct TXD {
    270 	volatile unsigned int DnNextPtr;
    271 	volatile unsigned int FrameStartHeader;
    272 	volatile unsigned int DataAddr;
    273 	volatile unsigned int DataLength;
    274 } __attribute__ ((aligned(8)));	/* 64-bit aligned for bus mastering */
    275 
    276 /* RX descriptor */
    277 struct RXD {
    278 	volatile unsigned int UpNextPtr;
    279 	volatile unsigned int UpPktStatus;
    280 	volatile unsigned int DataAddr;
    281 	volatile unsigned int DataLength;
    282 } __attribute__ ((aligned(8)));	/* 64-bit aligned for bus mastering */
    283 
    284 /* Private NIC dats */
    285 struct INF_3C90X {
    286 	unsigned int is3c556;
    287 	unsigned char isBrev;
    288 	unsigned char CurrentWindow;
    289 	unsigned int IOAddr;
    290 	unsigned short eeprom[0x21];
    291 	unsigned int tx_cur;	/* current entry in tx_ring */
    292 	unsigned int tx_cnt;	/* current number of used tx descriptors */
    293 	unsigned int tx_tail;	/* entry of last finished packet */
    294 	unsigned int rx_cur;
    295 	struct TXD *tx_ring;
    296 	struct RXD *rx_ring;
    297 	struct io_buffer *tx_iobuf[TX_RING_SIZE];
    298 	struct io_buffer *rx_iobuf[RX_RING_SIZE];
    299 	struct nvs_device nvs;
    300 };
    301 
    302 #endif
    303