1*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 2*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 2002 3*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 5*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * See file CREDITS for list of people who contributed to this 6*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * project. 7*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 8*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * This program is free software; you can redistribute it and/or 9*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * modify it under the terms of the GNU General Public License as 10*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * published by the Free Software Foundation; either version 2 of 11*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * the License, or (at your option) any later version. 12*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 13*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * This program is distributed in the hope that it will be useful, 14*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * but WITHOUT ANY WARRANTY; without even the implied warranty of 15*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * GNU General Public License for more details. 17*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * 18*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * You should have received a copy of the GNU General Public License 19*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * along with this program; if not, write to the Free Software 20*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * MA 02111-1307 USA 22*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 23*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 24*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <common.h> 25*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <malloc.h> 26*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <net.h> 27*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <asm/io.h> 28*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <pci.h> 29*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <miiphy.h> 30*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 31*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #undef DEBUG 32*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 33*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_CMD_NET) \ 34*2439e4bfSJean-Christophe PLAGNIOL-VILLARD && defined(CONFIG_NET_MULTI) && defined(CONFIG_EEPRO100) 35*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 36*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Ethernet chip registers. 37*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 38*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCBStatus 0 /* Rx/Command Unit Status *Word* */ 39*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCBIntAckByte 1 /* Rx/Command Unit STAT/ACK byte */ 40*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCBCmd 2 /* Rx/Command Unit Command *Word* */ 41*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCBIntrCtlByte 3 /* Rx/Command Unit Intr.Control Byte */ 42*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCBPointer 4 /* General purpose pointer. */ 43*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCBPort 8 /* Misc. commands and operands. */ 44*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCBflash 12 /* Flash memory control. */ 45*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCBeeprom 14 /* EEPROM memory control. */ 46*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCBCtrlMDI 16 /* MDI interface control. */ 47*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCBEarlyRx 20 /* Early receive byte count. */ 48*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCBGenControl 28 /* 82559 General Control Register */ 49*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCBGenStatus 29 /* 82559 General Status register */ 50*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 51*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 82559 SCB status word defnitions 52*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 53*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCB_STATUS_CX 0x8000 /* CU finished command (transmit) */ 54*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCB_STATUS_FR 0x4000 /* frame received */ 55*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCB_STATUS_CNA 0x2000 /* CU left active state */ 56*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCB_STATUS_RNR 0x1000 /* receiver left ready state */ 57*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCB_STATUS_MDI 0x0800 /* MDI read/write cycle done */ 58*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCB_STATUS_SWI 0x0400 /* software generated interrupt */ 59*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCB_STATUS_FCP 0x0100 /* flow control pause interrupt */ 60*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 61*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCB_INTACK_MASK 0xFD00 /* all the above */ 62*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 63*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCB_INTACK_TX (SCB_STATUS_CX | SCB_STATUS_CNA) 64*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCB_INTACK_RX (SCB_STATUS_FR | SCB_STATUS_RNR) 65*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 66*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* System control block commands 67*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 68*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* CU Commands */ 69*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CU_NOP 0x0000 70*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CU_START 0x0010 71*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CU_RESUME 0x0020 72*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CU_STATSADDR 0x0040 /* Load Dump Statistics ctrs addr */ 73*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CU_SHOWSTATS 0x0050 /* Dump statistics counters. */ 74*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CU_ADDR_LOAD 0x0060 /* Base address to add to CU commands */ 75*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CU_DUMPSTATS 0x0070 /* Dump then reset stats counters. */ 76*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 77*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* RUC Commands */ 78*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RUC_NOP 0x0000 79*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RUC_START 0x0001 80*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RUC_RESUME 0x0002 81*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RUC_ABORT 0x0004 82*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RUC_ADDR_LOAD 0x0006 /* (seems not to clear on acceptance) */ 83*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RUC_RESUMENR 0x0007 84*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 85*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CU_CMD_MASK 0x00f0 86*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RU_CMD_MASK 0x0007 87*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 88*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCB_M 0x0100 /* 0 = enable interrupt, 1 = disable */ 89*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCB_SWI 0x0200 /* 1 - cause device to interrupt */ 90*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 91*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CU_STATUS_MASK 0x00C0 92*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RU_STATUS_MASK 0x003C 93*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 94*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RU_STATUS_IDLE (0<<2) 95*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RU_STATUS_SUS (1<<2) 96*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RU_STATUS_NORES (2<<2) 97*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RU_STATUS_READY (4<<2) 98*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RU_STATUS_NO_RBDS_SUS ((1<<2)|(8<<2)) 99*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RU_STATUS_NO_RBDS_NORES ((2<<2)|(8<<2)) 100*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RU_STATUS_NO_RBDS_READY ((4<<2)|(8<<2)) 101*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 102*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 82559 Port interface commands. 103*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 104*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define I82559_RESET 0x00000000 /* Software reset */ 105*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define I82559_SELFTEST 0x00000001 /* 82559 Selftest command */ 106*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define I82559_SELECTIVE_RESET 0x00000002 107*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define I82559_DUMP 0x00000003 108*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define I82559_DUMP_WAKEUP 0x00000007 109*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 110*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 82559 Eeprom interface. 111*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 112*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */ 113*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_CS 0x02 /* EEPROM chip select. */ 114*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */ 115*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_WRITE_0 0x01 116*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_WRITE_1 0x05 117*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_DATA_READ 0x08 /* EEPROM chip data out. */ 118*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_ENB (0x4800 | EE_CS) 119*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_CMD_BITS 3 120*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_DATA_BITS 16 121*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 122*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* The EEPROM commands include the alway-set leading bit. 123*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 124*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_EWENB_CMD (4 << addr_len) 125*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_WRITE_CMD (5 << addr_len) 126*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_READ_CMD (6 << addr_len) 127*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_ERASE_CMD (7 << addr_len) 128*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 129*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Receive frame descriptors. 130*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 131*2439e4bfSJean-Christophe PLAGNIOL-VILLARD struct RxFD { 132*2439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u16 status; 133*2439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u16 control; 134*2439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u32 link; /* struct RxFD * */ 135*2439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u32 rx_buf_addr; /* void * */ 136*2439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u32 count; 137*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 138*2439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u8 data[PKTSIZE_ALIGN]; 139*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 140*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 141*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_STATUS_C 0x8000 /* completion of received frame */ 142*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_STATUS_OK 0x2000 /* frame received with no errors */ 143*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 144*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_CONTROL_EL 0x8000 /* 1=last RFD in RFA */ 145*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_CONTROL_S 0x4000 /* 1=suspend RU after receiving frame */ 146*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_CONTROL_H 0x0010 /* 1=RFD is a header RFD */ 147*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_CONTROL_SF 0x0008 /* 0=simplified, 1=flexible mode */ 148*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 149*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_COUNT_MASK 0x3fff 150*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_COUNT_F 0x4000 151*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_COUNT_EOF 0x8000 152*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 153*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_RX_CRC 0x0800 /* crc error */ 154*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_RX_ALIGNMENT 0x0400 /* alignment error */ 155*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_RX_RESOURCE 0x0200 /* out of space, no resources */ 156*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_RX_DMA_OVER 0x0100 /* DMA overrun */ 157*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_RX_SHORT 0x0080 /* short frame error */ 158*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_RX_LENGTH 0x0020 159*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_RX_ERROR 0x0010 /* receive error */ 160*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_RX_NO_ADR_MATCH 0x0004 /* no address match */ 161*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_RX_IA_MATCH 0x0002 /* individual address does not match */ 162*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_RX_TCO 0x0001 /* TCO indication */ 163*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 164*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Transmit frame descriptors 165*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 166*2439e4bfSJean-Christophe PLAGNIOL-VILLARD struct TxFD { /* Transmit frame descriptor set. */ 167*2439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u16 status; 168*2439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u16 command; 169*2439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u32 link; /* void * */ 170*2439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u32 tx_desc_addr; /* Always points to the tx_buf_addr element. */ 171*2439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile s32 count; 172*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 173*2439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u32 tx_buf_addr0; /* void *, frame to be transmitted. */ 174*2439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile s32 tx_buf_size0; /* Length of Tx frame. */ 175*2439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u32 tx_buf_addr1; /* void *, frame to be transmitted. */ 176*2439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile s32 tx_buf_size1; /* Length of Tx frame. */ 177*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 178*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 179*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TxCB_CMD_TRANSMIT 0x0004 /* transmit command */ 180*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TxCB_CMD_SF 0x0008 /* 0=simplified, 1=flexible mode */ 181*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TxCB_CMD_NC 0x0010 /* 0=CRC insert by controller */ 182*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TxCB_CMD_I 0x2000 /* generate interrupt on completion */ 183*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TxCB_CMD_S 0x4000 /* suspend on completion */ 184*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TxCB_CMD_EL 0x8000 /* last command block in CBL */ 185*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 186*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TxCB_COUNT_MASK 0x3fff 187*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TxCB_COUNT_EOF 0x8000 188*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 189*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* The Speedo3 Rx and Tx frame/buffer descriptors. 190*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 191*2439e4bfSJean-Christophe PLAGNIOL-VILLARD struct descriptor { /* A generic descriptor. */ 192*2439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u16 status; 193*2439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u16 command; 194*2439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u32 link; /* struct descriptor * */ 195*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 196*2439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned char params[0]; 197*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 198*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 199*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CFG_CMD_EL 0x8000 200*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CFG_CMD_SUSPEND 0x4000 201*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CFG_CMD_INT 0x2000 202*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CFG_CMD_IAS 0x0001 /* individual address setup */ 203*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CFG_CMD_CONFIGURE 0x0002 /* configure */ 204*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 205*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CFG_STATUS_C 0x8000 206*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CFG_STATUS_OK 0x2000 207*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 208*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Misc. 209*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 210*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define NUM_RX_DESC PKTBUFSRX 211*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define NUM_TX_DESC 1 /* Number of TX descriptors */ 212*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 213*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TOUT_LOOP 1000000 214*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 215*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define ETH_ALEN 6 216*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 217*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static struct RxFD rx_ring[NUM_RX_DESC]; /* RX descriptor ring */ 218*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static struct TxFD tx_ring[NUM_TX_DESC]; /* TX descriptor ring */ 219*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int rx_next; /* RX descriptor ring pointer */ 220*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int tx_next; /* TX descriptor ring pointer */ 221*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int tx_threshold; 222*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 223*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 224*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * The parameters for a CmdConfigure operation. 225*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * There are so many options that it would be difficult to document 226*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * each bit. We mostly use the default or recommended settings. 227*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 228*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static const char i82557_config_cmd[] = { 229*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 22, 0x08, 0, 0, 0, 0, 0x32, 0x03, 1, /* 1=Use MII 0=Use AUI */ 230*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 0, 0x2E, 0, 0x60, 0, 231*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 0xf2, 0x48, 0, 0x40, 0xf2, 0x80, /* 0x40=Force full-duplex */ 232*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 0x3f, 0x05, 233*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 234*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static const char i82558_config_cmd[] = { 235*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 22, 0x08, 0, 1, 0, 0, 0x22, 0x03, 1, /* 1=Use MII 0=Use AUI */ 236*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 0, 0x2E, 0, 0x60, 0x08, 0x88, 237*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 0x68, 0, 0x40, 0xf2, 0x84, /* Disable FC */ 238*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 0x31, 0x05, 239*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 240*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 241*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void init_rx_ring (struct eth_device *dev); 242*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void purge_tx_ring (struct eth_device *dev); 243*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 244*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void read_hw_addr (struct eth_device *dev, bd_t * bis); 245*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 246*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int eepro100_init (struct eth_device *dev, bd_t * bis); 247*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int eepro100_send (struct eth_device *dev, volatile void *packet, 248*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int length); 249*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int eepro100_recv (struct eth_device *dev); 250*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void eepro100_halt (struct eth_device *dev); 251*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 252*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_E500) || defined(CONFIG_DB64360) || defined(CONFIG_DB64460) 253*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define bus_to_phys(a) (a) 254*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define phys_to_bus(a) (a) 255*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else 256*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, a) 257*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) 258*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 259*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 260*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline int INW (struct eth_device *dev, u_long addr) 261*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 262*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return le16_to_cpu (*(volatile u16 *) (addr + dev->iobase)); 263*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 264*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 265*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline void OUTW (struct eth_device *dev, int command, u_long addr) 266*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 267*2439e4bfSJean-Christophe PLAGNIOL-VILLARD *(volatile u16 *) ((addr + dev->iobase)) = cpu_to_le16 (command); 268*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 269*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 270*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline void OUTL (struct eth_device *dev, int command, u_long addr) 271*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 272*2439e4bfSJean-Christophe PLAGNIOL-VILLARD *(volatile u32 *) ((addr + dev->iobase)) = cpu_to_le32 (command); 273*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 274*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 275*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) 276*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline int INL (struct eth_device *dev, u_long addr) 277*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 278*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return le32_to_cpu (*(volatile u32 *) (addr + dev->iobase)); 279*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 280*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 281*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int get_phyreg (struct eth_device *dev, unsigned char addr, 282*2439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned char reg, unsigned short *value) 283*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 284*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int cmd; 285*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int timeout = 50; 286*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 287*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* read requested data */ 288*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cmd = (2 << 26) | ((addr & 0x1f) << 21) | ((reg & 0x1f) << 16); 289*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, cmd, SCBCtrlMDI); 290*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 291*2439e4bfSJean-Christophe PLAGNIOL-VILLARD do { 292*2439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1000); 293*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cmd = INL (dev, SCBCtrlMDI); 294*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } while (!(cmd & (1 << 28)) && (--timeout)); 295*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 296*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (timeout == 0) 297*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return -1; 298*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 299*2439e4bfSJean-Christophe PLAGNIOL-VILLARD *value = (unsigned short) (cmd & 0xffff); 300*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 301*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 302*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 303*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 304*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int set_phyreg (struct eth_device *dev, unsigned char addr, 305*2439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned char reg, unsigned short value) 306*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 307*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int cmd; 308*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int timeout = 50; 309*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 310*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* write requested data */ 311*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cmd = (1 << 26) | ((addr & 0x1f) << 21) | ((reg & 0x1f) << 16); 312*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, cmd | value, SCBCtrlMDI); 313*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 314*2439e4bfSJean-Christophe PLAGNIOL-VILLARD while (!(INL (dev, SCBCtrlMDI) & (1 << 28)) && (--timeout)) 315*2439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1000); 316*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 317*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (timeout == 0) 318*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return -1; 319*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 320*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 321*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 322*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 323*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Check if given phyaddr is valid, i.e. there is a PHY connected. 324*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * Do this by checking model value field from ID2 register. 325*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 326*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static struct eth_device* verify_phyaddr (char *devname, unsigned char addr) 327*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 328*2439e4bfSJean-Christophe PLAGNIOL-VILLARD struct eth_device *dev; 329*2439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned short value; 330*2439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned char model; 331*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 332*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev = eth_get_dev_by_name(devname); 333*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (dev == NULL) { 334*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("%s: no such device\n", devname); 335*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return NULL; 336*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 337*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 338*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* read id2 register */ 339*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (get_phyreg(dev, addr, PHY_PHYIDR2, &value) != 0) { 340*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("%s: mii read timeout!\n", devname); 341*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return NULL; 342*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 343*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 344*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* get model */ 345*2439e4bfSJean-Christophe PLAGNIOL-VILLARD model = (unsigned char)((value >> 4) & 0x003f); 346*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 347*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (model == 0) { 348*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("%s: no PHY at address %d\n", devname, addr); 349*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return NULL; 350*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 351*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 352*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return dev; 353*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 354*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 355*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int eepro100_miiphy_read (char *devname, unsigned char addr, 356*2439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned char reg, unsigned short *value) 357*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 358*2439e4bfSJean-Christophe PLAGNIOL-VILLARD struct eth_device *dev; 359*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 360*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev = verify_phyaddr(devname, addr); 361*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (dev == NULL) 362*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return -1; 363*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 364*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (get_phyreg(dev, addr, reg, value) != 0) { 365*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("%s: mii read timeout!\n", devname); 366*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return -1; 367*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 368*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 369*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 370*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 371*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 372*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int eepro100_miiphy_write (char *devname, unsigned char addr, 373*2439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned char reg, unsigned short value) 374*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 375*2439e4bfSJean-Christophe PLAGNIOL-VILLARD struct eth_device *dev; 376*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 377*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev = verify_phyaddr(devname, addr); 378*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (dev == NULL) 379*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return -1; 380*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 381*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (set_phyreg(dev, addr, reg, value) != 0) { 382*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("%s: mii write timeout!\n", devname); 383*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return -1; 384*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 385*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 386*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 387*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 388*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 389*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 390*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 391*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Wait for the chip get the command. 392*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 393*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int wait_for_eepro100 (struct eth_device *dev) 394*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 395*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int i; 396*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 397*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; INW (dev, SCBCmd) & (CU_CMD_MASK | RU_CMD_MASK); i++) { 398*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (i >= TOUT_LOOP) { 399*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 400*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 401*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 402*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 403*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return 1; 404*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 405*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 406*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static struct pci_device_id supported[] = { 407*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82557}, 408*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559}, 409*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559ER}, 410*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {} 411*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 412*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 413*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int eepro100_initialize (bd_t * bis) 414*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 415*2439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_dev_t devno; 416*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int card_number = 0; 417*2439e4bfSJean-Christophe PLAGNIOL-VILLARD struct eth_device *dev; 418*2439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 iobase, status; 419*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int idx = 0; 420*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 421*2439e4bfSJean-Christophe PLAGNIOL-VILLARD while (1) { 422*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Find PCI device 423*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 424*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((devno = pci_find_devices (supported, idx++)) < 0) { 425*2439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 426*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 427*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 428*2439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_read_config_dword (devno, PCI_BASE_ADDRESS_0, &iobase); 429*2439e4bfSJean-Christophe PLAGNIOL-VILLARD iobase &= ~0xf; 430*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 431*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 432*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("eepro100: Intel i82559 PCI EtherExpressPro @0x%x\n", 433*2439e4bfSJean-Christophe PLAGNIOL-VILLARD iobase); 434*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 435*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 436*2439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_write_config_dword (devno, 437*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PCI_COMMAND, 438*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); 439*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 440*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Check if I/O accesses and Bus Mastering are enabled. 441*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 442*2439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_read_config_dword (devno, PCI_COMMAND, &status); 443*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!(status & PCI_COMMAND_MEMORY)) { 444*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("Error: Can not enable MEM access.\n"); 445*2439e4bfSJean-Christophe PLAGNIOL-VILLARD continue; 446*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 447*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 448*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!(status & PCI_COMMAND_MASTER)) { 449*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("Error: Can not enable Bus Mastering.\n"); 450*2439e4bfSJean-Christophe PLAGNIOL-VILLARD continue; 451*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 452*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 453*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev = (struct eth_device *) malloc (sizeof *dev); 454*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 455*2439e4bfSJean-Christophe PLAGNIOL-VILLARD sprintf (dev->name, "i82559#%d", card_number); 456*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->priv = (void *) devno; /* this have to come before bus_to_phys() */ 457*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->iobase = bus_to_phys (iobase); 458*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->init = eepro100_init; 459*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->halt = eepro100_halt; 460*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->send = eepro100_send; 461*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->recv = eepro100_recv; 462*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 463*2439e4bfSJean-Christophe PLAGNIOL-VILLARD eth_register (dev); 464*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 465*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if defined (CONFIG_MII) || defined(CONFIG_CMD_MII) 466*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* register mii command access routines */ 467*2439e4bfSJean-Christophe PLAGNIOL-VILLARD miiphy_register(dev->name, 468*2439e4bfSJean-Christophe PLAGNIOL-VILLARD eepro100_miiphy_read, eepro100_miiphy_write); 469*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 470*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 471*2439e4bfSJean-Christophe PLAGNIOL-VILLARD card_number++; 472*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 473*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set the latency timer for value. 474*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 475*2439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_write_config_byte (devno, PCI_LATENCY_TIMER, 0x20); 476*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 477*2439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (10 * 1000); 478*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 479*2439e4bfSJean-Christophe PLAGNIOL-VILLARD read_hw_addr (dev, bis); 480*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 481*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 482*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return card_number; 483*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 484*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 485*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 486*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int eepro100_init (struct eth_device *dev, bd_t * bis) 487*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 488*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int i, status = 0; 489*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int tx_cur; 490*2439e4bfSJean-Christophe PLAGNIOL-VILLARD struct descriptor *ias_cmd, *cfg_cmd; 491*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 492*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Reset the ethernet controller 493*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 494*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, I82559_SELECTIVE_RESET, SCBPort); 495*2439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (20); 496*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 497*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, I82559_RESET, SCBPort); 498*2439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (20); 499*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 500*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!wait_for_eepro100 (dev)) { 501*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("Error: Can not reset ethernet controller.\n"); 502*2439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 503*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 504*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, 0, SCBPointer); 505*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, SCB_M | RUC_ADDR_LOAD, SCBCmd); 506*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 507*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!wait_for_eepro100 (dev)) { 508*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("Error: Can not reset ethernet controller.\n"); 509*2439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 510*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 511*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, 0, SCBPointer); 512*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, SCB_M | CU_ADDR_LOAD, SCBCmd); 513*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 514*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Initialize Rx and Tx rings. 515*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 516*2439e4bfSJean-Christophe PLAGNIOL-VILLARD init_rx_ring (dev); 517*2439e4bfSJean-Christophe PLAGNIOL-VILLARD purge_tx_ring (dev); 518*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 519*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Tell the adapter where the RX ring is located. 520*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 521*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!wait_for_eepro100 (dev)) { 522*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("Error: Can not reset ethernet controller.\n"); 523*2439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 524*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 525*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 526*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, phys_to_bus ((u32) & rx_ring[rx_next]), SCBPointer); 527*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, SCB_M | RUC_START, SCBCmd); 528*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 529*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Send the Configure frame */ 530*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_cur = tx_next; 531*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_next = ((tx_next + 1) % NUM_TX_DESC); 532*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 533*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cfg_cmd = (struct descriptor *) &tx_ring[tx_cur]; 534*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cfg_cmd->command = cpu_to_le16 ((CFG_CMD_SUSPEND | CFG_CMD_CONFIGURE)); 535*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cfg_cmd->status = 0; 536*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cfg_cmd->link = cpu_to_le32 (phys_to_bus ((u32) & tx_ring[tx_next])); 537*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 538*2439e4bfSJean-Christophe PLAGNIOL-VILLARD memcpy (cfg_cmd->params, i82558_config_cmd, 539*2439e4bfSJean-Christophe PLAGNIOL-VILLARD sizeof (i82558_config_cmd)); 540*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 541*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!wait_for_eepro100 (dev)) { 542*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("Error---CFG_CMD_CONFIGURE: Can not reset ethernet controller.\n"); 543*2439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 544*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 545*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 546*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, phys_to_bus ((u32) & tx_ring[tx_cur]), SCBPointer); 547*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, SCB_M | CU_START, SCBCmd); 548*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 549*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; 550*2439e4bfSJean-Christophe PLAGNIOL-VILLARD !(le16_to_cpu (tx_ring[tx_cur].status) & CFG_STATUS_C); 551*2439e4bfSJean-Christophe PLAGNIOL-VILLARD i++) { 552*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (i >= TOUT_LOOP) { 553*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("%s: Tx error buffer not ready\n", dev->name); 554*2439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 555*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 556*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 557*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 558*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!(le16_to_cpu (tx_ring[tx_cur].status) & CFG_STATUS_OK)) { 559*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("TX error status = 0x%08X\n", 560*2439e4bfSJean-Christophe PLAGNIOL-VILLARD le16_to_cpu (tx_ring[tx_cur].status)); 561*2439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 562*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 563*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 564*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Send the Individual Address Setup frame 565*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 566*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_cur = tx_next; 567*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_next = ((tx_next + 1) % NUM_TX_DESC); 568*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 569*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ias_cmd = (struct descriptor *) &tx_ring[tx_cur]; 570*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ias_cmd->command = cpu_to_le16 ((CFG_CMD_SUSPEND | CFG_CMD_IAS)); 571*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ias_cmd->status = 0; 572*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ias_cmd->link = cpu_to_le32 (phys_to_bus ((u32) & tx_ring[tx_next])); 573*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 574*2439e4bfSJean-Christophe PLAGNIOL-VILLARD memcpy (ias_cmd->params, dev->enetaddr, 6); 575*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 576*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Tell the adapter where the TX ring is located. 577*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 578*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!wait_for_eepro100 (dev)) { 579*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("Error: Can not reset ethernet controller.\n"); 580*2439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 581*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 582*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 583*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, phys_to_bus ((u32) & tx_ring[tx_cur]), SCBPointer); 584*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, SCB_M | CU_START, SCBCmd); 585*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 586*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; !(le16_to_cpu (tx_ring[tx_cur].status) & CFG_STATUS_C); 587*2439e4bfSJean-Christophe PLAGNIOL-VILLARD i++) { 588*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (i >= TOUT_LOOP) { 589*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("%s: Tx error buffer not ready\n", 590*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->name); 591*2439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 592*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 593*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 594*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 595*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!(le16_to_cpu (tx_ring[tx_cur].status) & CFG_STATUS_OK)) { 596*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("TX error status = 0x%08X\n", 597*2439e4bfSJean-Christophe PLAGNIOL-VILLARD le16_to_cpu (tx_ring[tx_cur].status)); 598*2439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 599*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 600*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 601*2439e4bfSJean-Christophe PLAGNIOL-VILLARD status = 1; 602*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 603*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Done: 604*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return status; 605*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 606*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 607*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int eepro100_send (struct eth_device *dev, volatile void *packet, int length) 608*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 609*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int i, status = -1; 610*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int tx_cur; 611*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 612*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (length <= 0) { 613*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("%s: bad packet size: %d\n", dev->name, length); 614*2439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 615*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 616*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 617*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_cur = tx_next; 618*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_next = (tx_next + 1) % NUM_TX_DESC; 619*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 620*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[tx_cur].command = cpu_to_le16 ( TxCB_CMD_TRANSMIT | 621*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TxCB_CMD_SF | 622*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TxCB_CMD_S | 623*2439e4bfSJean-Christophe PLAGNIOL-VILLARD TxCB_CMD_EL ); 624*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[tx_cur].status = 0; 625*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[tx_cur].count = cpu_to_le32 (tx_threshold); 626*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[tx_cur].link = 627*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cpu_to_le32 (phys_to_bus ((u32) & tx_ring[tx_next])); 628*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[tx_cur].tx_desc_addr = 629*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cpu_to_le32 (phys_to_bus ((u32) & tx_ring[tx_cur].tx_buf_addr0)); 630*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[tx_cur].tx_buf_addr0 = 631*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cpu_to_le32 (phys_to_bus ((u_long) packet)); 632*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[tx_cur].tx_buf_size0 = cpu_to_le32 (length); 633*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 634*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!wait_for_eepro100 (dev)) { 635*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("%s: Tx error ethernet controller not ready.\n", 636*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->name); 637*2439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 638*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 639*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 640*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Send the packet. 641*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 642*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, phys_to_bus ((u32) & tx_ring[tx_cur]), SCBPointer); 643*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, SCB_M | CU_START, SCBCmd); 644*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 645*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; !(le16_to_cpu (tx_ring[tx_cur].status) & CFG_STATUS_C); 646*2439e4bfSJean-Christophe PLAGNIOL-VILLARD i++) { 647*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (i >= TOUT_LOOP) { 648*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("%s: Tx error buffer not ready\n", dev->name); 649*2439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 650*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 651*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 652*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 653*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!(le16_to_cpu (tx_ring[tx_cur].status) & CFG_STATUS_OK)) { 654*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("TX error status = 0x%08X\n", 655*2439e4bfSJean-Christophe PLAGNIOL-VILLARD le16_to_cpu (tx_ring[tx_cur].status)); 656*2439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 657*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 658*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 659*2439e4bfSJean-Christophe PLAGNIOL-VILLARD status = length; 660*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 661*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Done: 662*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return status; 663*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 664*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 665*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int eepro100_recv (struct eth_device *dev) 666*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 667*2439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 status, stat; 668*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int rx_prev, length = 0; 669*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 670*2439e4bfSJean-Christophe PLAGNIOL-VILLARD stat = INW (dev, SCBStatus); 671*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, stat & SCB_STATUS_RNR, SCBStatus); 672*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 673*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (;;) { 674*2439e4bfSJean-Christophe PLAGNIOL-VILLARD status = le16_to_cpu (rx_ring[rx_next].status); 675*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 676*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!(status & RFD_STATUS_C)) { 677*2439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 678*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 679*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 680*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Valid frame status. 681*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 682*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((status & RFD_STATUS_OK)) { 683*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* A valid frame received. 684*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 685*2439e4bfSJean-Christophe PLAGNIOL-VILLARD length = le32_to_cpu (rx_ring[rx_next].count) & 0x3fff; 686*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 687*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Pass the packet up to the protocol 688*2439e4bfSJean-Christophe PLAGNIOL-VILLARD * layers. 689*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 690*2439e4bfSJean-Christophe PLAGNIOL-VILLARD NetReceive (rx_ring[rx_next].data, length); 691*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 692*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* There was an error. 693*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 694*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("RX error status = 0x%08X\n", status); 695*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 696*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 697*2439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_ring[rx_next].control = cpu_to_le16 (RFD_CONTROL_S); 698*2439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_ring[rx_next].status = 0; 699*2439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_ring[rx_next].count = cpu_to_le32 (PKTSIZE_ALIGN << 16); 700*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 701*2439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_prev = (rx_next + NUM_RX_DESC - 1) % NUM_RX_DESC; 702*2439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_ring[rx_prev].control = 0; 703*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 704*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Update entry information. 705*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 706*2439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_next = (rx_next + 1) % NUM_RX_DESC; 707*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 708*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 709*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (stat & SCB_STATUS_RNR) { 710*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 711*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("%s: Receiver is not ready, restart it !\n", dev->name); 712*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 713*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Reinitialize Rx ring. 714*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 715*2439e4bfSJean-Christophe PLAGNIOL-VILLARD init_rx_ring (dev); 716*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 717*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!wait_for_eepro100 (dev)) { 718*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("Error: Can not restart ethernet controller.\n"); 719*2439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 720*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 721*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 722*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, phys_to_bus ((u32) & rx_ring[rx_next]), SCBPointer); 723*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, SCB_M | RUC_START, SCBCmd); 724*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 725*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 726*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Done: 727*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return length; 728*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 729*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 730*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void eepro100_halt (struct eth_device *dev) 731*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 732*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Reset the ethernet controller 733*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 734*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, I82559_SELECTIVE_RESET, SCBPort); 735*2439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (20); 736*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 737*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, I82559_RESET, SCBPort); 738*2439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (20); 739*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 740*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!wait_for_eepro100 (dev)) { 741*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("Error: Can not reset ethernet controller.\n"); 742*2439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 743*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 744*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, 0, SCBPointer); 745*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, SCB_M | RUC_ADDR_LOAD, SCBCmd); 746*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 747*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!wait_for_eepro100 (dev)) { 748*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("Error: Can not reset ethernet controller.\n"); 749*2439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 750*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 751*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, 0, SCBPointer); 752*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, SCB_M | CU_ADDR_LOAD, SCBCmd); 753*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 754*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Done: 755*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return; 756*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 757*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 758*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* SROM Read. 759*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 760*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int read_eeprom (struct eth_device *dev, int location, int addr_len) 761*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 762*2439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned short retval = 0; 763*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int read_cmd = location | EE_READ_CMD; 764*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int i; 765*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 766*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, EE_ENB & ~EE_CS, SCBeeprom); 767*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, EE_ENB, SCBeeprom); 768*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 769*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Shift the read command bits out. */ 770*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 12; i >= 0; i--) { 771*2439e4bfSJean-Christophe PLAGNIOL-VILLARD short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; 772*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 773*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, EE_ENB | dataval, SCBeeprom); 774*2439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (1); 775*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom); 776*2439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (1); 777*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 778*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, EE_ENB, SCBeeprom); 779*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 780*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 15; i >= 0; i--) { 781*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, EE_ENB | EE_SHIFT_CLK, SCBeeprom); 782*2439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (1); 783*2439e4bfSJean-Christophe PLAGNIOL-VILLARD retval = (retval << 1) | 784*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ((INW (dev, SCBeeprom) & EE_DATA_READ) ? 1 : 0); 785*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, EE_ENB, SCBeeprom); 786*2439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (1); 787*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 788*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 789*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Terminate the EEPROM access. */ 790*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, EE_ENB & ~EE_CS, SCBeeprom); 791*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return retval; 792*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 793*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 794*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_EEPRO100_SROM_WRITE 795*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int eepro100_write_eeprom (struct eth_device* dev, int location, int addr_len, unsigned short data) 796*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 797*2439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned short dataval; 798*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int enable_cmd = 0x3f | EE_EWENB_CMD; 799*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int write_cmd = location | EE_WRITE_CMD; 800*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int i; 801*2439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long datalong, tmplong; 802*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 803*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom); 804*2439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1); 805*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB, SCBeeprom); 806*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 807*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Shift the enable command bits out. */ 808*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = (addr_len+EE_CMD_BITS-1); i >= 0; i--) 809*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 810*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dataval = (enable_cmd & (1 << i)) ? EE_DATA_WRITE : 0; 811*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB | dataval, SCBeeprom); 812*2439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1); 813*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom); 814*2439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1); 815*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 816*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 817*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB, SCBeeprom); 818*2439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1); 819*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom); 820*2439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1); 821*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB, SCBeeprom); 822*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 823*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 824*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Shift the write command bits out. */ 825*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = (addr_len+EE_CMD_BITS-1); i >= 0; i--) 826*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 827*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dataval = (write_cmd & (1 << i)) ? EE_DATA_WRITE : 0; 828*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB | dataval, SCBeeprom); 829*2439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1); 830*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom); 831*2439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1); 832*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 833*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 834*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Write the data */ 835*2439e4bfSJean-Christophe PLAGNIOL-VILLARD datalong= (unsigned long) ((((data) & 0x00ff) << 8) | ( (data) >> 8)); 836*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 837*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i< EE_DATA_BITS; i++) 838*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 839*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Extract and move data bit to bit DI */ 840*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dataval = ((datalong & 0x8000)>>13) ? EE_DATA_WRITE : 0; 841*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 842*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB | dataval, SCBeeprom); 843*2439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1); 844*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom); 845*2439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1); 846*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB | dataval, SCBeeprom); 847*2439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1); 848*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 849*2439e4bfSJean-Christophe PLAGNIOL-VILLARD datalong = datalong << 1; /* Adjust significant data bit*/ 850*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 851*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 852*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Finish up command (toggle CS) */ 853*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom); 854*2439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1); /* delay for more than 250 ns */ 855*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB, SCBeeprom); 856*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 857*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Wait for programming ready (D0 = 1) */ 858*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tmplong = 10; 859*2439e4bfSJean-Christophe PLAGNIOL-VILLARD do 860*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 861*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dataval = INW(dev, SCBeeprom); 862*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (dataval & EE_DATA_READ) 863*2439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 864*2439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(10000); 865*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 866*2439e4bfSJean-Christophe PLAGNIOL-VILLARD while (-- tmplong); 867*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 868*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (tmplong == 0) 869*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 870*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("Write i82559 eeprom timed out (100 ms waiting for data ready.\n"); 871*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return -1; 872*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 873*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 874*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Terminate the EEPROM access. */ 875*2439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom); 876*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 877*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 878*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 879*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 880*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 881*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void init_rx_ring (struct eth_device *dev) 882*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 883*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int i; 884*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 885*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < NUM_RX_DESC; i++) { 886*2439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_ring[i].status = 0; 887*2439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_ring[i].control = 888*2439e4bfSJean-Christophe PLAGNIOL-VILLARD (i == NUM_RX_DESC - 1) ? cpu_to_le16 (RFD_CONTROL_S) : 0; 889*2439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_ring[i].link = 890*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cpu_to_le32 (phys_to_bus 891*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ((u32) & rx_ring[(i + 1) % NUM_RX_DESC])); 892*2439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_ring[i].rx_buf_addr = 0xffffffff; 893*2439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_ring[i].count = cpu_to_le32 (PKTSIZE_ALIGN << 16); 894*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 895*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 896*2439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_next = 0; 897*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 898*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 899*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void purge_tx_ring (struct eth_device *dev) 900*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 901*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int i; 902*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 903*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_next = 0; 904*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_threshold = 0x01208000; 905*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 906*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < NUM_TX_DESC; i++) { 907*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[i].status = 0; 908*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[i].command = 0; 909*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[i].link = 0; 910*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[i].tx_desc_addr = 0; 911*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[i].count = 0; 912*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 913*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[i].tx_buf_addr0 = 0; 914*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[i].tx_buf_size0 = 0; 915*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[i].tx_buf_addr1 = 0; 916*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[i].tx_buf_size1 = 0; 917*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 918*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 919*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 920*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void read_hw_addr (struct eth_device *dev, bd_t * bis) 921*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 922*2439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 eeprom[0x40]; 923*2439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 sum = 0; 924*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int i, j; 925*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int addr_len = read_eeprom (dev, 0, 6) == 0xffff ? 8 : 6; 926*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 927*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (j = 0, i = 0; i < 0x40; i++) { 928*2439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 value = read_eeprom (dev, i, addr_len); 929*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 930*2439e4bfSJean-Christophe PLAGNIOL-VILLARD eeprom[i] = value; 931*2439e4bfSJean-Christophe PLAGNIOL-VILLARD sum += value; 932*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (i < 3) { 933*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->enetaddr[j++] = value; 934*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->enetaddr[j++] = value >> 8; 935*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 936*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 937*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 938*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (sum != 0xBABA) { 939*2439e4bfSJean-Christophe PLAGNIOL-VILLARD memset (dev->enetaddr, 0, ETH_ALEN); 940*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 941*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("%s: Invalid EEPROM checksum %#4.4x, " 942*2439e4bfSJean-Christophe PLAGNIOL-VILLARD "check settings before activating this device!\n", 943*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->name, sum); 944*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 945*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 946*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 947*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 948*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 949