1*1b8adde7SWilliam Kucharski /* 2*1b8adde7SWilliam Kucharski * eepro100.c -- This file implements the eepro100 driver for etherboot. 3*1b8adde7SWilliam Kucharski * 4*1b8adde7SWilliam Kucharski * 5*1b8adde7SWilliam Kucharski * Copyright (C) AW Computer Systems. 6*1b8adde7SWilliam Kucharski * written by R.E.Wolff -- R.E.Wolff@BitWizard.nl 7*1b8adde7SWilliam Kucharski * 8*1b8adde7SWilliam Kucharski * 9*1b8adde7SWilliam Kucharski * AW Computer Systems is contributing to the free software community 10*1b8adde7SWilliam Kucharski * by paying for this driver and then putting the result under GPL. 11*1b8adde7SWilliam Kucharski * 12*1b8adde7SWilliam Kucharski * If you need a Linux device driver, please contact BitWizard for a 13*1b8adde7SWilliam Kucharski * quote. 14*1b8adde7SWilliam Kucharski * 15*1b8adde7SWilliam Kucharski * 16*1b8adde7SWilliam Kucharski * This program is free software; you can redistribute it and/or 17*1b8adde7SWilliam Kucharski * modify it under the terms of the GNU General Public License as 18*1b8adde7SWilliam Kucharski * published by the Free Software Foundation; either version 2, or (at 19*1b8adde7SWilliam Kucharski * your option) any later version. 20*1b8adde7SWilliam Kucharski * 21*1b8adde7SWilliam Kucharski * This program is distributed in the hope that it will be useful, but 22*1b8adde7SWilliam Kucharski * WITHOUT ANY WARRANTY; without even the implied warranty of 23*1b8adde7SWilliam Kucharski * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24*1b8adde7SWilliam Kucharski * General Public License for more details. 25*1b8adde7SWilliam Kucharski * 26*1b8adde7SWilliam Kucharski * You should have received a copy of the GNU General Public License 27*1b8adde7SWilliam Kucharski * along with this program; if not, write to the Free Software 28*1b8adde7SWilliam Kucharski * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 29*1b8adde7SWilliam Kucharski * 30*1b8adde7SWilliam Kucharski * 31*1b8adde7SWilliam Kucharski * date version by what 32*1b8adde7SWilliam Kucharski * Written: May 29 1997 V0.10 REW Initial revision. 33*1b8adde7SWilliam Kucharski * changes: May 31 1997 V0.90 REW Works! 34*1b8adde7SWilliam Kucharski * Jun 1 1997 V0.91 REW Cleanup 35*1b8adde7SWilliam Kucharski * Jun 2 1997 V0.92 REW Add some code documentation 36*1b8adde7SWilliam Kucharski * Jul 25 1997 V1.00 REW Tested by AW to work in a PROM 37*1b8adde7SWilliam Kucharski * Cleanup for publication 38*1b8adde7SWilliam Kucharski * 39*1b8adde7SWilliam Kucharski * This is the etherboot intel etherexpress Pro/100B driver. 40*1b8adde7SWilliam Kucharski * 41*1b8adde7SWilliam Kucharski * It was written from scratch, with Donald Beckers eepro100.c kernel 42*1b8adde7SWilliam Kucharski * driver as a guideline. Mostly the 82557 related definitions and the 43*1b8adde7SWilliam Kucharski * lower level routines have been cut-and-pasted into this source. 44*1b8adde7SWilliam Kucharski * 45*1b8adde7SWilliam Kucharski * The driver was finished before Intel got the NDA out of the closet. 46*1b8adde7SWilliam Kucharski * I still don't have the docs. 47*1b8adde7SWilliam Kucharski * */ 48*1b8adde7SWilliam Kucharski 49*1b8adde7SWilliam Kucharski /* Philosophy of this driver. 50*1b8adde7SWilliam Kucharski * 51*1b8adde7SWilliam Kucharski * Probing: 52*1b8adde7SWilliam Kucharski * 53*1b8adde7SWilliam Kucharski * Using the pci.c functions of the Etherboot code, the 82557 chip is detected. 54*1b8adde7SWilliam Kucharski * It is verified that the BIOS initialized everything properly and if 55*1b8adde7SWilliam Kucharski * something is missing it is done now. 56*1b8adde7SWilliam Kucharski * 57*1b8adde7SWilliam Kucharski * 58*1b8adde7SWilliam Kucharski * Initialization: 59*1b8adde7SWilliam Kucharski * 60*1b8adde7SWilliam Kucharski * 61*1b8adde7SWilliam Kucharski * The chip is then initialized to "know" its ethernet address, and to 62*1b8adde7SWilliam Kucharski * start recieving packets. The Linux driver has a whole transmit and 63*1b8adde7SWilliam Kucharski * recieve ring of buffers. This is neat if you need high performance: 64*1b8adde7SWilliam Kucharski * you can write the buffers asynchronously to the chip reading the 65*1b8adde7SWilliam Kucharski * buffers and transmitting them over the network. Performance is NOT 66*1b8adde7SWilliam Kucharski * an issue here. We can boot a 400k kernel in about two 67*1b8adde7SWilliam Kucharski * seconds. (Theory: 0.4 seconds). Booting a system is going to take 68*1b8adde7SWilliam Kucharski * about half a minute anyway, so getting 10 times closer to the 69*1b8adde7SWilliam Kucharski * theoretical limit is going to make a difference of a few percent. 70*1b8adde7SWilliam Kucharski * 71*1b8adde7SWilliam Kucharski * 72*1b8adde7SWilliam Kucharski * Transmitting and recieving. 73*1b8adde7SWilliam Kucharski * 74*1b8adde7SWilliam Kucharski * We have only one transmit descriptor. It has two buffer descriptors: 75*1b8adde7SWilliam Kucharski * one for the header, and the other for the data. 76*1b8adde7SWilliam Kucharski * We have only one receive buffer. The chip is told to recieve packets, 77*1b8adde7SWilliam Kucharski * and suspend itself once it got one. The recieve (poll) routine simply 78*1b8adde7SWilliam Kucharski * looks at the recieve buffer to see if there is already a packet there. 79*1b8adde7SWilliam Kucharski * if there is, the buffer is copied, and the reciever is restarted. 80*1b8adde7SWilliam Kucharski * 81*1b8adde7SWilliam Kucharski * Caveats: 82*1b8adde7SWilliam Kucharski * 83*1b8adde7SWilliam Kucharski * The Etherboot framework moves the code to the 48k segment from 84*1b8adde7SWilliam Kucharski * 0x94000 to 0xa0000. There is just a little room between the end of 85*1b8adde7SWilliam Kucharski * this driver and the 0xa0000 address. If you compile in too many 86*1b8adde7SWilliam Kucharski * features, this will overflow. 87*1b8adde7SWilliam Kucharski * The number under "hex" in the output of size that scrolls by while 88*1b8adde7SWilliam Kucharski * compiling should be less than 8000. Maybe even the stack is up there, 89*1b8adde7SWilliam Kucharski * so that you need even more headroom. 90*1b8adde7SWilliam Kucharski */ 91*1b8adde7SWilliam Kucharski 92*1b8adde7SWilliam Kucharski /* The etherboot authors seem to dislike the argument ordering in 93*1b8adde7SWilliam Kucharski * outb macros that Linux uses. I disklike the confusion that this 94*1b8adde7SWilliam Kucharski * has caused even more.... This file uses the Linux argument ordering. */ 95*1b8adde7SWilliam Kucharski /* Sorry not us. It's inherited code from FreeBSD. [The authors] */ 96*1b8adde7SWilliam Kucharski 97*1b8adde7SWilliam Kucharski #include "etherboot.h" 98*1b8adde7SWilliam Kucharski #include "nic.h" 99*1b8adde7SWilliam Kucharski #include "pci.h" 100*1b8adde7SWilliam Kucharski #include "timer.h" 101*1b8adde7SWilliam Kucharski 102*1b8adde7SWilliam Kucharski static int ioaddr; 103*1b8adde7SWilliam Kucharski 104*1b8adde7SWilliam Kucharski typedef unsigned char u8; 105*1b8adde7SWilliam Kucharski typedef signed char s8; 106*1b8adde7SWilliam Kucharski typedef unsigned short u16; 107*1b8adde7SWilliam Kucharski typedef signed short s16; 108*1b8adde7SWilliam Kucharski typedef unsigned int u32; 109*1b8adde7SWilliam Kucharski typedef signed int s32; 110*1b8adde7SWilliam Kucharski 111*1b8adde7SWilliam Kucharski enum speedo_offsets { 112*1b8adde7SWilliam Kucharski SCBStatus = 0, SCBCmd = 2, /* Rx/Command Unit command and status. */ 113*1b8adde7SWilliam Kucharski SCBPointer = 4, /* General purpose pointer. */ 114*1b8adde7SWilliam Kucharski SCBPort = 8, /* Misc. commands and operands. */ 115*1b8adde7SWilliam Kucharski SCBflash = 12, SCBeeprom = 14, /* EEPROM and flash memory control. */ 116*1b8adde7SWilliam Kucharski SCBCtrlMDI = 16, /* MDI interface control. */ 117*1b8adde7SWilliam Kucharski SCBEarlyRx = 20, /* Early receive byte count. */ 118*1b8adde7SWilliam Kucharski }; 119*1b8adde7SWilliam Kucharski 120*1b8adde7SWilliam Kucharski enum SCBCmdBits { 121*1b8adde7SWilliam Kucharski SCBMaskCmdDone=0x8000, SCBMaskRxDone=0x4000, SCBMaskCmdIdle=0x2000, 122*1b8adde7SWilliam Kucharski SCBMaskRxSuspend=0x1000, SCBMaskEarlyRx=0x0800, SCBMaskFlowCtl=0x0400, 123*1b8adde7SWilliam Kucharski SCBTriggerIntr=0x0200, SCBMaskAll=0x0100, 124*1b8adde7SWilliam Kucharski /* The rest are Rx and Tx commands. */ 125*1b8adde7SWilliam Kucharski CUStart=0x0010, CUResume=0x0020, CUStatsAddr=0x0040, CUShowStats=0x0050, 126*1b8adde7SWilliam Kucharski CUCmdBase=0x0060, /* CU Base address (set to zero) . */ 127*1b8adde7SWilliam Kucharski CUDumpStats=0x0070, /* Dump then reset stats counters. */ 128*1b8adde7SWilliam Kucharski RxStart=0x0001, RxResume=0x0002, RxAbort=0x0004, RxAddrLoad=0x0006, 129*1b8adde7SWilliam Kucharski RxResumeNoResources=0x0007, 130*1b8adde7SWilliam Kucharski }; 131*1b8adde7SWilliam Kucharski 132*1b8adde7SWilliam Kucharski static int do_eeprom_cmd(int cmd, int cmd_len); 133*1b8adde7SWilliam Kucharski void hd(void *where, int n); 134*1b8adde7SWilliam Kucharski 135*1b8adde7SWilliam Kucharski /***********************************************************************/ 136*1b8adde7SWilliam Kucharski /* I82557 related defines */ 137*1b8adde7SWilliam Kucharski /***********************************************************************/ 138*1b8adde7SWilliam Kucharski 139*1b8adde7SWilliam Kucharski /* Serial EEPROM section. 140*1b8adde7SWilliam Kucharski A "bit" grungy, but we work our way through bit-by-bit :->. */ 141*1b8adde7SWilliam Kucharski /* EEPROM_Ctrl bits. */ 142*1b8adde7SWilliam Kucharski #define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */ 143*1b8adde7SWilliam Kucharski #define EE_CS 0x02 /* EEPROM chip select. */ 144*1b8adde7SWilliam Kucharski #define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */ 145*1b8adde7SWilliam Kucharski #define EE_DATA_READ 0x08 /* EEPROM chip data out. */ 146*1b8adde7SWilliam Kucharski #define EE_WRITE_0 0x4802 147*1b8adde7SWilliam Kucharski #define EE_WRITE_1 0x4806 148*1b8adde7SWilliam Kucharski #define EE_ENB (0x4800 | EE_CS) 149*1b8adde7SWilliam Kucharski 150*1b8adde7SWilliam Kucharski /* The EEPROM commands include the alway-set leading bit. */ 151*1b8adde7SWilliam Kucharski #define EE_READ_CMD 6 152*1b8adde7SWilliam Kucharski 153*1b8adde7SWilliam Kucharski /* The SCB accepts the following controls for the Tx and Rx units: */ 154*1b8adde7SWilliam Kucharski #define CU_START 0x0010 155*1b8adde7SWilliam Kucharski #define CU_RESUME 0x0020 156*1b8adde7SWilliam Kucharski #define CU_STATSADDR 0x0040 157*1b8adde7SWilliam Kucharski #define CU_SHOWSTATS 0x0050 /* Dump statistics counters. */ 158*1b8adde7SWilliam Kucharski #define CU_CMD_BASE 0x0060 /* Base address to add to add CU commands. */ 159*1b8adde7SWilliam Kucharski #define CU_DUMPSTATS 0x0070 /* Dump then reset stats counters. */ 160*1b8adde7SWilliam Kucharski 161*1b8adde7SWilliam Kucharski #define RX_START 0x0001 162*1b8adde7SWilliam Kucharski #define RX_RESUME 0x0002 163*1b8adde7SWilliam Kucharski #define RX_ABORT 0x0004 164*1b8adde7SWilliam Kucharski #define RX_ADDR_LOAD 0x0006 165*1b8adde7SWilliam Kucharski #define RX_RESUMENR 0x0007 166*1b8adde7SWilliam Kucharski #define INT_MASK 0x0100 167*1b8adde7SWilliam Kucharski #define DRVR_INT 0x0200 /* Driver generated interrupt. */ 168*1b8adde7SWilliam Kucharski 169*1b8adde7SWilliam Kucharski enum phy_chips { NonSuchPhy=0, I82553AB, I82553C, I82503, DP83840, S80C240, 170*1b8adde7SWilliam Kucharski S80C24, PhyUndefined, DP83840A=10, }; 171*1b8adde7SWilliam Kucharski 172*1b8adde7SWilliam Kucharski /* Commands that can be put in a command list entry. */ 173*1b8adde7SWilliam Kucharski enum commands { 174*1b8adde7SWilliam Kucharski CmdNOp = 0, 175*1b8adde7SWilliam Kucharski CmdIASetup = 1, 176*1b8adde7SWilliam Kucharski CmdConfigure = 2, 177*1b8adde7SWilliam Kucharski CmdMulticastList = 3, 178*1b8adde7SWilliam Kucharski CmdTx = 4, 179*1b8adde7SWilliam Kucharski CmdTDR = 5, 180*1b8adde7SWilliam Kucharski CmdDump = 6, 181*1b8adde7SWilliam Kucharski CmdDiagnose = 7, 182*1b8adde7SWilliam Kucharski 183*1b8adde7SWilliam Kucharski /* And some extra flags: */ 184*1b8adde7SWilliam Kucharski CmdSuspend = 0x4000, /* Suspend after completion. */ 185*1b8adde7SWilliam Kucharski CmdIntr = 0x2000, /* Interrupt after completion. */ 186*1b8adde7SWilliam Kucharski CmdTxFlex = 0x0008, /* Use "Flexible mode" for CmdTx command. */ 187*1b8adde7SWilliam Kucharski }; 188*1b8adde7SWilliam Kucharski 189*1b8adde7SWilliam Kucharski /* How to wait for the command unit to accept a command. 190*1b8adde7SWilliam Kucharski Typically this takes 0 ticks. */ 191*1b8adde7SWilliam Kucharski static inline void wait_for_cmd_done(int cmd_ioaddr) 192*1b8adde7SWilliam Kucharski { 193*1b8adde7SWilliam Kucharski int wait = 0; 194*1b8adde7SWilliam Kucharski int delayed_cmd; 195*1b8adde7SWilliam Kucharski 196*1b8adde7SWilliam Kucharski do 197*1b8adde7SWilliam Kucharski if (inb(cmd_ioaddr) == 0) return; 198*1b8adde7SWilliam Kucharski while(++wait <= 100); 199*1b8adde7SWilliam Kucharski delayed_cmd = inb(cmd_ioaddr); 200*1b8adde7SWilliam Kucharski do 201*1b8adde7SWilliam Kucharski if (inb(cmd_ioaddr) == 0) break; 202*1b8adde7SWilliam Kucharski while(++wait <= 10000); 203*1b8adde7SWilliam Kucharski printf("Command %2.2x was not immediately accepted, %d ticks!\n", 204*1b8adde7SWilliam Kucharski delayed_cmd, wait); 205*1b8adde7SWilliam Kucharski } 206*1b8adde7SWilliam Kucharski 207*1b8adde7SWilliam Kucharski /* Elements of the dump_statistics block. This block must be lword aligned. */ 208*1b8adde7SWilliam Kucharski static struct speedo_stats { 209*1b8adde7SWilliam Kucharski u32 tx_good_frames; 210*1b8adde7SWilliam Kucharski u32 tx_coll16_errs; 211*1b8adde7SWilliam Kucharski u32 tx_late_colls; 212*1b8adde7SWilliam Kucharski u32 tx_underruns; 213*1b8adde7SWilliam Kucharski u32 tx_lost_carrier; 214*1b8adde7SWilliam Kucharski u32 tx_deferred; 215*1b8adde7SWilliam Kucharski u32 tx_one_colls; 216*1b8adde7SWilliam Kucharski u32 tx_multi_colls; 217*1b8adde7SWilliam Kucharski u32 tx_total_colls; 218*1b8adde7SWilliam Kucharski u32 rx_good_frames; 219*1b8adde7SWilliam Kucharski u32 rx_crc_errs; 220*1b8adde7SWilliam Kucharski u32 rx_align_errs; 221*1b8adde7SWilliam Kucharski u32 rx_resource_errs; 222*1b8adde7SWilliam Kucharski u32 rx_overrun_errs; 223*1b8adde7SWilliam Kucharski u32 rx_colls_errs; 224*1b8adde7SWilliam Kucharski u32 rx_runt_errs; 225*1b8adde7SWilliam Kucharski u32 done_marker; 226*1b8adde7SWilliam Kucharski } lstats; 227*1b8adde7SWilliam Kucharski 228*1b8adde7SWilliam Kucharski /* A speedo3 TX buffer descriptor with two buffers... */ 229*1b8adde7SWilliam Kucharski static struct TxFD { 230*1b8adde7SWilliam Kucharski volatile s16 status; 231*1b8adde7SWilliam Kucharski s16 command; 232*1b8adde7SWilliam Kucharski u32 link; /* void * */ 233*1b8adde7SWilliam Kucharski u32 tx_desc_addr; /* (almost) Always points to the tx_buf_addr element. */ 234*1b8adde7SWilliam Kucharski s32 count; /* # of TBD (=2), Tx start thresh., etc. */ 235*1b8adde7SWilliam Kucharski /* This constitutes two "TBD" entries: hdr and data */ 236*1b8adde7SWilliam Kucharski u32 tx_buf_addr0; /* void *, header of frame to be transmitted. */ 237*1b8adde7SWilliam Kucharski s32 tx_buf_size0; /* Length of Tx hdr. */ 238*1b8adde7SWilliam Kucharski u32 tx_buf_addr1; /* void *, data to be transmitted. */ 239*1b8adde7SWilliam Kucharski s32 tx_buf_size1; /* Length of Tx data. */ 240*1b8adde7SWilliam Kucharski } txfd; 241*1b8adde7SWilliam Kucharski 242*1b8adde7SWilliam Kucharski struct RxFD { /* Receive frame descriptor. */ 243*1b8adde7SWilliam Kucharski volatile s16 status; 244*1b8adde7SWilliam Kucharski s16 command; 245*1b8adde7SWilliam Kucharski u32 link; /* struct RxFD * */ 246*1b8adde7SWilliam Kucharski u32 rx_buf_addr; /* void * */ 247*1b8adde7SWilliam Kucharski u16 count; 248*1b8adde7SWilliam Kucharski u16 size; 249*1b8adde7SWilliam Kucharski char packet[1518]; 250*1b8adde7SWilliam Kucharski }; 251*1b8adde7SWilliam Kucharski 252*1b8adde7SWilliam Kucharski static struct RxFD rxfd; 253*1b8adde7SWilliam Kucharski #define ACCESS(x) x. 254*1b8adde7SWilliam Kucharski 255*1b8adde7SWilliam Kucharski static int congenb = 0; /* Enable congestion control in the DP83840. */ 256*1b8adde7SWilliam Kucharski static int txfifo = 8; /* Tx FIFO threshold in 4 byte units, 0-15 */ 257*1b8adde7SWilliam Kucharski static int rxfifo = 8; /* Rx FIFO threshold, default 32 bytes. */ 258*1b8adde7SWilliam Kucharski static int txdmacount = 0; /* Tx DMA burst length, 0-127, default 0. */ 259*1b8adde7SWilliam Kucharski static int rxdmacount = 0; /* Rx DMA length, 0 means no preemption. */ 260*1b8adde7SWilliam Kucharski 261*1b8adde7SWilliam Kucharski /* I don't understand a byte in this structure. It was copied from the 262*1b8adde7SWilliam Kucharski * Linux kernel initialization for the eepro100. -- REW */ 263*1b8adde7SWilliam Kucharski static struct ConfCmd { 264*1b8adde7SWilliam Kucharski s16 status; 265*1b8adde7SWilliam Kucharski s16 command; 266*1b8adde7SWilliam Kucharski u32 link; 267*1b8adde7SWilliam Kucharski unsigned char data[22]; 268*1b8adde7SWilliam Kucharski } confcmd = { 269*1b8adde7SWilliam Kucharski 0, 0, 0, /* filled in later */ 270*1b8adde7SWilliam Kucharski {22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1, /* 1=Use MII 0=Use AUI */ 271*1b8adde7SWilliam Kucharski 0, 0x2E, 0, 0x60, 0, 272*1b8adde7SWilliam Kucharski 0xf2, 0x48, 0, 0x40, 0xf2, 0x80, /* 0x40=Force full-duplex */ 273*1b8adde7SWilliam Kucharski 0x3f, 0x05, } 274*1b8adde7SWilliam Kucharski }; 275*1b8adde7SWilliam Kucharski 276*1b8adde7SWilliam Kucharski /***********************************************************************/ 277*1b8adde7SWilliam Kucharski /* Locally used functions */ 278*1b8adde7SWilliam Kucharski /***********************************************************************/ 279*1b8adde7SWilliam Kucharski 280*1b8adde7SWilliam Kucharski /* Support function: mdio_write 281*1b8adde7SWilliam Kucharski * 282*1b8adde7SWilliam Kucharski * This probably writes to the "physical media interface chip". 283*1b8adde7SWilliam Kucharski * -- REW 284*1b8adde7SWilliam Kucharski */ 285*1b8adde7SWilliam Kucharski 286*1b8adde7SWilliam Kucharski static int mdio_write(int phy_id, int location, int value) 287*1b8adde7SWilliam Kucharski { 288*1b8adde7SWilliam Kucharski int val, boguscnt = 64*4; /* <64 usec. to complete, typ 27 ticks */ 289*1b8adde7SWilliam Kucharski 290*1b8adde7SWilliam Kucharski outl(0x04000000 | (location<<16) | (phy_id<<21) | value, 291*1b8adde7SWilliam Kucharski ioaddr + SCBCtrlMDI); 292*1b8adde7SWilliam Kucharski do { 293*1b8adde7SWilliam Kucharski udelay(16); 294*1b8adde7SWilliam Kucharski 295*1b8adde7SWilliam Kucharski val = inl(ioaddr + SCBCtrlMDI); 296*1b8adde7SWilliam Kucharski if (--boguscnt < 0) { 297*1b8adde7SWilliam Kucharski printf(" mdio_write() timed out with val = %X.\n", val); 298*1b8adde7SWilliam Kucharski break; 299*1b8adde7SWilliam Kucharski } 300*1b8adde7SWilliam Kucharski } while (! (val & 0x10000000)); 301*1b8adde7SWilliam Kucharski return val & 0xffff; 302*1b8adde7SWilliam Kucharski } 303*1b8adde7SWilliam Kucharski 304*1b8adde7SWilliam Kucharski /* Support function: mdio_read 305*1b8adde7SWilliam Kucharski * 306*1b8adde7SWilliam Kucharski * This probably reads a register in the "physical media interface chip". 307*1b8adde7SWilliam Kucharski * -- REW 308*1b8adde7SWilliam Kucharski */ 309*1b8adde7SWilliam Kucharski static int mdio_read(int phy_id, int location) 310*1b8adde7SWilliam Kucharski { 311*1b8adde7SWilliam Kucharski int val, boguscnt = 64*4; /* <64 usec. to complete, typ 27 ticks */ 312*1b8adde7SWilliam Kucharski outl(0x08000000 | (location<<16) | (phy_id<<21), ioaddr + SCBCtrlMDI); 313*1b8adde7SWilliam Kucharski do { 314*1b8adde7SWilliam Kucharski udelay(16); 315*1b8adde7SWilliam Kucharski 316*1b8adde7SWilliam Kucharski val = inl(ioaddr + SCBCtrlMDI); 317*1b8adde7SWilliam Kucharski 318*1b8adde7SWilliam Kucharski if (--boguscnt < 0) { 319*1b8adde7SWilliam Kucharski printf( " mdio_read() timed out with val = %X.\n", val); 320*1b8adde7SWilliam Kucharski break; 321*1b8adde7SWilliam Kucharski } 322*1b8adde7SWilliam Kucharski } while (! (val & 0x10000000)); 323*1b8adde7SWilliam Kucharski return val & 0xffff; 324*1b8adde7SWilliam Kucharski } 325*1b8adde7SWilliam Kucharski 326*1b8adde7SWilliam Kucharski /* The fixes for the code were kindly provided by Dragan Stancevic 327*1b8adde7SWilliam Kucharski <visitor@valinux.com> to strictly follow Intel specifications of EEPROM 328*1b8adde7SWilliam Kucharski access timing. 329*1b8adde7SWilliam Kucharski The publicly available sheet 64486302 (sec. 3.1) specifies 1us access 330*1b8adde7SWilliam Kucharski interval for serial EEPROM. However, it looks like that there is an 331*1b8adde7SWilliam Kucharski additional requirement dictating larger udelay's in the code below. 332*1b8adde7SWilliam Kucharski 2000/05/24 SAW */ 333*1b8adde7SWilliam Kucharski static int do_eeprom_cmd(int cmd, int cmd_len) 334*1b8adde7SWilliam Kucharski { 335*1b8adde7SWilliam Kucharski unsigned retval = 0; 336*1b8adde7SWilliam Kucharski long ee_addr = ioaddr + SCBeeprom; 337*1b8adde7SWilliam Kucharski 338*1b8adde7SWilliam Kucharski outw(EE_ENB, ee_addr); udelay(2); 339*1b8adde7SWilliam Kucharski outw(EE_ENB | EE_SHIFT_CLK, ee_addr); udelay(2); 340*1b8adde7SWilliam Kucharski 341*1b8adde7SWilliam Kucharski /* Shift the command bits out. */ 342*1b8adde7SWilliam Kucharski do { 343*1b8adde7SWilliam Kucharski short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0; 344*1b8adde7SWilliam Kucharski outw(dataval, ee_addr); udelay(2); 345*1b8adde7SWilliam Kucharski outw(dataval | EE_SHIFT_CLK, ee_addr); udelay(2); 346*1b8adde7SWilliam Kucharski retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0); 347*1b8adde7SWilliam Kucharski } while (--cmd_len >= 0); 348*1b8adde7SWilliam Kucharski outw(EE_ENB, ee_addr); udelay(2); 349*1b8adde7SWilliam Kucharski 350*1b8adde7SWilliam Kucharski /* Terminate the EEPROM access. */ 351*1b8adde7SWilliam Kucharski outw(EE_ENB & ~EE_CS, ee_addr); 352*1b8adde7SWilliam Kucharski return retval; 353*1b8adde7SWilliam Kucharski } 354*1b8adde7SWilliam Kucharski 355*1b8adde7SWilliam Kucharski #if 0 356*1b8adde7SWilliam Kucharski static inline void whereami (const char *str) 357*1b8adde7SWilliam Kucharski { 358*1b8adde7SWilliam Kucharski printf ("%s\n", str); 359*1b8adde7SWilliam Kucharski sleep (2); 360*1b8adde7SWilliam Kucharski } 361*1b8adde7SWilliam Kucharski #else 362*1b8adde7SWilliam Kucharski #define whereami(s) 363*1b8adde7SWilliam Kucharski #endif 364*1b8adde7SWilliam Kucharski 365*1b8adde7SWilliam Kucharski static void eepro100_irq(struct nic *nic __unused, irq_action_t action __unused) 366*1b8adde7SWilliam Kucharski { 367*1b8adde7SWilliam Kucharski switch ( action ) { 368*1b8adde7SWilliam Kucharski case DISABLE : 369*1b8adde7SWilliam Kucharski break; 370*1b8adde7SWilliam Kucharski case ENABLE : 371*1b8adde7SWilliam Kucharski break; 372*1b8adde7SWilliam Kucharski case FORCE : 373*1b8adde7SWilliam Kucharski break; 374*1b8adde7SWilliam Kucharski } 375*1b8adde7SWilliam Kucharski } 376*1b8adde7SWilliam Kucharski 377*1b8adde7SWilliam Kucharski /* function: eepro100_transmit 378*1b8adde7SWilliam Kucharski * This transmits a packet. 379*1b8adde7SWilliam Kucharski * 380*1b8adde7SWilliam Kucharski * Arguments: char d[6]: destination ethernet address. 381*1b8adde7SWilliam Kucharski * unsigned short t: ethernet protocol type. 382*1b8adde7SWilliam Kucharski * unsigned short s: size of the data-part of the packet. 383*1b8adde7SWilliam Kucharski * char *p: the data for the packet. 384*1b8adde7SWilliam Kucharski * returns: void. 385*1b8adde7SWilliam Kucharski */ 386*1b8adde7SWilliam Kucharski 387*1b8adde7SWilliam Kucharski static void eepro100_transmit(struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p) 388*1b8adde7SWilliam Kucharski { 389*1b8adde7SWilliam Kucharski struct eth_hdr { 390*1b8adde7SWilliam Kucharski unsigned char dst_addr[ETH_ALEN]; 391*1b8adde7SWilliam Kucharski unsigned char src_addr[ETH_ALEN]; 392*1b8adde7SWilliam Kucharski unsigned short type; 393*1b8adde7SWilliam Kucharski } hdr; 394*1b8adde7SWilliam Kucharski unsigned short status; 395*1b8adde7SWilliam Kucharski int s1, s2; 396*1b8adde7SWilliam Kucharski 397*1b8adde7SWilliam Kucharski status = inw(ioaddr + SCBStatus); 398*1b8adde7SWilliam Kucharski /* Acknowledge all of the current interrupt sources ASAP. */ 399*1b8adde7SWilliam Kucharski outw(status & 0xfc00, ioaddr + SCBStatus); 400*1b8adde7SWilliam Kucharski 401*1b8adde7SWilliam Kucharski #ifdef DEBUG 402*1b8adde7SWilliam Kucharski printf ("transmitting type %hX packet (%d bytes). status = %hX, cmd=%hX\n", 403*1b8adde7SWilliam Kucharski t, s, status, inw (ioaddr + SCBCmd)); 404*1b8adde7SWilliam Kucharski #endif 405*1b8adde7SWilliam Kucharski 406*1b8adde7SWilliam Kucharski memcpy (&hdr.dst_addr, d, ETH_ALEN); 407*1b8adde7SWilliam Kucharski memcpy (&hdr.src_addr, nic->node_addr, ETH_ALEN); 408*1b8adde7SWilliam Kucharski 409*1b8adde7SWilliam Kucharski hdr.type = htons (t); 410*1b8adde7SWilliam Kucharski 411*1b8adde7SWilliam Kucharski txfd.status = 0; 412*1b8adde7SWilliam Kucharski txfd.command = CmdSuspend | CmdTx | CmdTxFlex; 413*1b8adde7SWilliam Kucharski txfd.link = virt_to_bus (&txfd); 414*1b8adde7SWilliam Kucharski txfd.count = 0x02208000; 415*1b8adde7SWilliam Kucharski txfd.tx_desc_addr = virt_to_bus(&txfd.tx_buf_addr0); 416*1b8adde7SWilliam Kucharski 417*1b8adde7SWilliam Kucharski txfd.tx_buf_addr0 = virt_to_bus (&hdr); 418*1b8adde7SWilliam Kucharski txfd.tx_buf_size0 = sizeof (hdr); 419*1b8adde7SWilliam Kucharski 420*1b8adde7SWilliam Kucharski txfd.tx_buf_addr1 = virt_to_bus (p); 421*1b8adde7SWilliam Kucharski txfd.tx_buf_size1 = s; 422*1b8adde7SWilliam Kucharski 423*1b8adde7SWilliam Kucharski #ifdef DEBUG 424*1b8adde7SWilliam Kucharski printf ("txfd: \n"); 425*1b8adde7SWilliam Kucharski hd (&txfd, sizeof (txfd)); 426*1b8adde7SWilliam Kucharski #endif 427*1b8adde7SWilliam Kucharski 428*1b8adde7SWilliam Kucharski outl(virt_to_bus(&txfd), ioaddr + SCBPointer); 429*1b8adde7SWilliam Kucharski outw(INT_MASK | CU_START, ioaddr + SCBCmd); 430*1b8adde7SWilliam Kucharski wait_for_cmd_done(ioaddr + SCBCmd); 431*1b8adde7SWilliam Kucharski 432*1b8adde7SWilliam Kucharski s1 = inw (ioaddr + SCBStatus); 433*1b8adde7SWilliam Kucharski load_timer2(10*TICKS_PER_MS); /* timeout 10 ms for transmit */ 434*1b8adde7SWilliam Kucharski while (!txfd.status && timer2_running()) 435*1b8adde7SWilliam Kucharski /* Wait */; 436*1b8adde7SWilliam Kucharski s2 = inw (ioaddr + SCBStatus); 437*1b8adde7SWilliam Kucharski 438*1b8adde7SWilliam Kucharski #ifdef DEBUG 439*1b8adde7SWilliam Kucharski printf ("s1 = %hX, s2 = %hX.\n", s1, s2); 440*1b8adde7SWilliam Kucharski #endif 441*1b8adde7SWilliam Kucharski } 442*1b8adde7SWilliam Kucharski 443*1b8adde7SWilliam Kucharski /* 444*1b8adde7SWilliam Kucharski * Sometimes the receiver stops making progress. This routine knows how to 445*1b8adde7SWilliam Kucharski * get it going again, without losing packets or being otherwise nasty like 446*1b8adde7SWilliam Kucharski * a chip reset would be. Previously the driver had a whole sequence 447*1b8adde7SWilliam Kucharski * of if RxSuspended, if it's no buffers do one thing, if it's no resources, 448*1b8adde7SWilliam Kucharski * do another, etc. But those things don't really matter. Separate logic 449*1b8adde7SWilliam Kucharski * in the ISR provides for allocating buffers--the other half of operation 450*1b8adde7SWilliam Kucharski * is just making sure the receiver is active. speedo_rx_soft_reset does that. 451*1b8adde7SWilliam Kucharski * This problem with the old, more involved algorithm is shown up under 452*1b8adde7SWilliam Kucharski * ping floods on the order of 60K packets/second on a 100Mbps fdx network. 453*1b8adde7SWilliam Kucharski */ 454*1b8adde7SWilliam Kucharski static void 455*1b8adde7SWilliam Kucharski speedo_rx_soft_reset(void) 456*1b8adde7SWilliam Kucharski { 457*1b8adde7SWilliam Kucharski wait_for_cmd_done(ioaddr + SCBCmd); 458*1b8adde7SWilliam Kucharski /* 459*1b8adde7SWilliam Kucharski * Put the hardware into a known state. 460*1b8adde7SWilliam Kucharski */ 461*1b8adde7SWilliam Kucharski outb(RX_ABORT, ioaddr + SCBCmd); 462*1b8adde7SWilliam Kucharski 463*1b8adde7SWilliam Kucharski ACCESS(rxfd)rx_buf_addr = 0xffffffff; 464*1b8adde7SWilliam Kucharski 465*1b8adde7SWilliam Kucharski wait_for_cmd_done(ioaddr + SCBCmd); 466*1b8adde7SWilliam Kucharski 467*1b8adde7SWilliam Kucharski outb(RX_START, ioaddr + SCBCmd); 468*1b8adde7SWilliam Kucharski } 469*1b8adde7SWilliam Kucharski 470*1b8adde7SWilliam Kucharski /* function: eepro100_poll / eth_poll 471*1b8adde7SWilliam Kucharski * This recieves a packet from the network. 472*1b8adde7SWilliam Kucharski * 473*1b8adde7SWilliam Kucharski * Arguments: none 474*1b8adde7SWilliam Kucharski * 475*1b8adde7SWilliam Kucharski * returns: 1 if a packet was recieved. 476*1b8adde7SWilliam Kucharski * 0 if no pacet was recieved. 477*1b8adde7SWilliam Kucharski * side effects: 478*1b8adde7SWilliam Kucharski * returns the packet in the array nic->packet. 479*1b8adde7SWilliam Kucharski * returns the length of the packet in nic->packetlen. 480*1b8adde7SWilliam Kucharski */ 481*1b8adde7SWilliam Kucharski 482*1b8adde7SWilliam Kucharski static int eepro100_poll(struct nic *nic, int retrieve) 483*1b8adde7SWilliam Kucharski { 484*1b8adde7SWilliam Kucharski unsigned int status; 485*1b8adde7SWilliam Kucharski status = inw(ioaddr + SCBStatus); 486*1b8adde7SWilliam Kucharski 487*1b8adde7SWilliam Kucharski if (!ACCESS(rxfd)status) 488*1b8adde7SWilliam Kucharski return 0; 489*1b8adde7SWilliam Kucharski 490*1b8adde7SWilliam Kucharski /* There is a packet ready */ 491*1b8adde7SWilliam Kucharski if ( ! retrieve ) return 1; 492*1b8adde7SWilliam Kucharski 493*1b8adde7SWilliam Kucharski /* 494*1b8adde7SWilliam Kucharski * The chip may have suspended reception for various reasons. 495*1b8adde7SWilliam Kucharski * Check for that, and re-prime it should this be the case. 496*1b8adde7SWilliam Kucharski */ 497*1b8adde7SWilliam Kucharski switch ((status >> 2) & 0xf) { 498*1b8adde7SWilliam Kucharski case 0: /* Idle */ 499*1b8adde7SWilliam Kucharski break; 500*1b8adde7SWilliam Kucharski case 1: /* Suspended */ 501*1b8adde7SWilliam Kucharski case 2: /* No resources (RxFDs) */ 502*1b8adde7SWilliam Kucharski case 9: /* Suspended with no more RBDs */ 503*1b8adde7SWilliam Kucharski case 10: /* No resources due to no RBDs */ 504*1b8adde7SWilliam Kucharski case 12: /* Ready with no RBDs */ 505*1b8adde7SWilliam Kucharski speedo_rx_soft_reset(); 506*1b8adde7SWilliam Kucharski break; 507*1b8adde7SWilliam Kucharski case 3: case 5: case 6: case 7: case 8: 508*1b8adde7SWilliam Kucharski case 11: case 13: case 14: case 15: 509*1b8adde7SWilliam Kucharski /* these are all reserved values */ 510*1b8adde7SWilliam Kucharski break; 511*1b8adde7SWilliam Kucharski } 512*1b8adde7SWilliam Kucharski 513*1b8adde7SWilliam Kucharski /* Ok. We got a packet. Now restart the reciever.... */ 514*1b8adde7SWilliam Kucharski ACCESS(rxfd)status = 0; 515*1b8adde7SWilliam Kucharski ACCESS(rxfd)command = 0xc000; 516*1b8adde7SWilliam Kucharski outl(virt_to_bus(&(ACCESS(rxfd)status)), ioaddr + SCBPointer); 517*1b8adde7SWilliam Kucharski outw(INT_MASK | RX_START, ioaddr + SCBCmd); 518*1b8adde7SWilliam Kucharski wait_for_cmd_done(ioaddr + SCBCmd); 519*1b8adde7SWilliam Kucharski 520*1b8adde7SWilliam Kucharski #ifdef DEBUG 521*1b8adde7SWilliam Kucharski printf ("Got a packet: Len = %d.\n", ACCESS(rxfd)count & 0x3fff); 522*1b8adde7SWilliam Kucharski #endif 523*1b8adde7SWilliam Kucharski nic->packetlen = ACCESS(rxfd)count & 0x3fff; 524*1b8adde7SWilliam Kucharski memcpy (nic->packet, ACCESS(rxfd)packet, nic->packetlen); 525*1b8adde7SWilliam Kucharski #ifdef DEBUG 526*1b8adde7SWilliam Kucharski hd (nic->packet, 0x30); 527*1b8adde7SWilliam Kucharski #endif 528*1b8adde7SWilliam Kucharski return 1; 529*1b8adde7SWilliam Kucharski } 530*1b8adde7SWilliam Kucharski 531*1b8adde7SWilliam Kucharski /* function: eepro100_disable 532*1b8adde7SWilliam Kucharski * resets the card. This is used to allow Etherboot or Linux 533*1b8adde7SWilliam Kucharski * to probe the card again from a "virginal" state.... 534*1b8adde7SWilliam Kucharski * Arguments: none 535*1b8adde7SWilliam Kucharski * 536*1b8adde7SWilliam Kucharski * returns: void. 537*1b8adde7SWilliam Kucharski */ 538*1b8adde7SWilliam Kucharski static void eepro100_disable(struct dev *dev __unused) 539*1b8adde7SWilliam Kucharski { 540*1b8adde7SWilliam Kucharski /* from eepro100_reset */ 541*1b8adde7SWilliam Kucharski outl(0, ioaddr + SCBPort); 542*1b8adde7SWilliam Kucharski /* from eepro100_disable */ 543*1b8adde7SWilliam Kucharski /* See if this PartialReset solves the problem with interfering with 544*1b8adde7SWilliam Kucharski kernel operation after Etherboot hands over. - Ken 20001102 */ 545*1b8adde7SWilliam Kucharski outl(2, ioaddr + SCBPort); 546*1b8adde7SWilliam Kucharski 547*1b8adde7SWilliam Kucharski /* The following is from the Intel e100 driver. 548*1b8adde7SWilliam Kucharski * This hopefully solves the problem with hanging hard DOS images. */ 549*1b8adde7SWilliam Kucharski 550*1b8adde7SWilliam Kucharski /* wait for the reset to take effect */ 551*1b8adde7SWilliam Kucharski udelay(20); 552*1b8adde7SWilliam Kucharski 553*1b8adde7SWilliam Kucharski /* Mask off our interrupt line -- it is unmasked after reset */ 554*1b8adde7SWilliam Kucharski { 555*1b8adde7SWilliam Kucharski u16 intr_status; 556*1b8adde7SWilliam Kucharski /* Disable interrupts on our PCI board by setting the mask bit */ 557*1b8adde7SWilliam Kucharski outw(INT_MASK, ioaddr + SCBCmd); 558*1b8adde7SWilliam Kucharski intr_status = inw(ioaddr + SCBStatus); 559*1b8adde7SWilliam Kucharski /* ack and clear intrs */ 560*1b8adde7SWilliam Kucharski outw(intr_status, ioaddr + SCBStatus); 561*1b8adde7SWilliam Kucharski inw(ioaddr + SCBStatus); 562*1b8adde7SWilliam Kucharski } 563*1b8adde7SWilliam Kucharski } 564*1b8adde7SWilliam Kucharski 565*1b8adde7SWilliam Kucharski /* exported function: eepro100_probe / eth_probe 566*1b8adde7SWilliam Kucharski * initializes a card 567*1b8adde7SWilliam Kucharski * 568*1b8adde7SWilliam Kucharski * side effects: 569*1b8adde7SWilliam Kucharski * leaves the ioaddress of the 82557 chip in the variable ioaddr. 570*1b8adde7SWilliam Kucharski * leaves the 82557 initialized, and ready to recieve packets. 571*1b8adde7SWilliam Kucharski */ 572*1b8adde7SWilliam Kucharski 573*1b8adde7SWilliam Kucharski static int eepro100_probe(struct dev *dev, struct pci_device *p) 574*1b8adde7SWilliam Kucharski { 575*1b8adde7SWilliam Kucharski struct nic *nic = (struct nic *)dev; 576*1b8adde7SWilliam Kucharski unsigned short sum = 0; 577*1b8adde7SWilliam Kucharski int i; 578*1b8adde7SWilliam Kucharski int read_cmd, ee_size; 579*1b8adde7SWilliam Kucharski int options; 580*1b8adde7SWilliam Kucharski int rx_mode; 581*1b8adde7SWilliam Kucharski 582*1b8adde7SWilliam Kucharski /* we cache only the first few words of the EEPROM data 583*1b8adde7SWilliam Kucharski be careful not to access beyond this array */ 584*1b8adde7SWilliam Kucharski unsigned short eeprom[16]; 585*1b8adde7SWilliam Kucharski 586*1b8adde7SWilliam Kucharski if (p->ioaddr == 0) 587*1b8adde7SWilliam Kucharski return 0; 588*1b8adde7SWilliam Kucharski ioaddr = p->ioaddr & ~3; /* Mask the bit that says "this is an io addr" */ 589*1b8adde7SWilliam Kucharski nic->ioaddr = ioaddr; 590*1b8adde7SWilliam Kucharski 591*1b8adde7SWilliam Kucharski adjust_pci_device(p); 592*1b8adde7SWilliam Kucharski 593*1b8adde7SWilliam Kucharski /* Copy IRQ from PCI information */ 594*1b8adde7SWilliam Kucharski /* nic->irqno = pci->irq; */ 595*1b8adde7SWilliam Kucharski nic->irqno = 0; 596*1b8adde7SWilliam Kucharski 597*1b8adde7SWilliam Kucharski if ((do_eeprom_cmd(EE_READ_CMD << 24, 27) & 0xffe0000) 598*1b8adde7SWilliam Kucharski == 0xffe0000) { 599*1b8adde7SWilliam Kucharski ee_size = 0x100; 600*1b8adde7SWilliam Kucharski read_cmd = EE_READ_CMD << 24; 601*1b8adde7SWilliam Kucharski } else { 602*1b8adde7SWilliam Kucharski ee_size = 0x40; 603*1b8adde7SWilliam Kucharski read_cmd = EE_READ_CMD << 22; 604*1b8adde7SWilliam Kucharski } 605*1b8adde7SWilliam Kucharski 606*1b8adde7SWilliam Kucharski for (i = 0, sum = 0; i < ee_size; i++) { 607*1b8adde7SWilliam Kucharski unsigned short value = do_eeprom_cmd(read_cmd | (i << 16), 27); 608*1b8adde7SWilliam Kucharski if (i < (int)(sizeof(eeprom)/sizeof(eeprom[0]))) 609*1b8adde7SWilliam Kucharski eeprom[i] = value; 610*1b8adde7SWilliam Kucharski sum += value; 611*1b8adde7SWilliam Kucharski } 612*1b8adde7SWilliam Kucharski 613*1b8adde7SWilliam Kucharski for (i=0;i<ETH_ALEN;i++) { 614*1b8adde7SWilliam Kucharski nic->node_addr[i] = (eeprom[i/2] >> (8*(i&1))) & 0xff; 615*1b8adde7SWilliam Kucharski } 616*1b8adde7SWilliam Kucharski printf ("Ethernet addr: %!\n", nic->node_addr); 617*1b8adde7SWilliam Kucharski 618*1b8adde7SWilliam Kucharski if (sum != 0xBABA) 619*1b8adde7SWilliam Kucharski printf("eepro100: Invalid EEPROM checksum %#hX, " 620*1b8adde7SWilliam Kucharski "check settings before activating this device!\n", sum); 621*1b8adde7SWilliam Kucharski outl(0, ioaddr + SCBPort); 622*1b8adde7SWilliam Kucharski udelay (10000); 623*1b8adde7SWilliam Kucharski whereami ("Got eeprom."); 624*1b8adde7SWilliam Kucharski 625*1b8adde7SWilliam Kucharski /* Base = 0 */ 626*1b8adde7SWilliam Kucharski outl(0, ioaddr + SCBPointer); 627*1b8adde7SWilliam Kucharski outw(INT_MASK | RX_ADDR_LOAD, ioaddr + SCBCmd); 628*1b8adde7SWilliam Kucharski wait_for_cmd_done(ioaddr + SCBCmd); 629*1b8adde7SWilliam Kucharski whereami ("set rx base addr."); 630*1b8adde7SWilliam Kucharski 631*1b8adde7SWilliam Kucharski outl(virt_to_bus(&lstats), ioaddr + SCBPointer); 632*1b8adde7SWilliam Kucharski outw(INT_MASK | CU_STATSADDR, ioaddr + SCBCmd); 633*1b8adde7SWilliam Kucharski wait_for_cmd_done(ioaddr + SCBCmd); 634*1b8adde7SWilliam Kucharski whereami ("set stats addr."); 635*1b8adde7SWilliam Kucharski 636*1b8adde7SWilliam Kucharski /* INIT RX stuff. */ 637*1b8adde7SWilliam Kucharski ACCESS(rxfd)status = 0x0001; 638*1b8adde7SWilliam Kucharski ACCESS(rxfd)command = 0x0000; 639*1b8adde7SWilliam Kucharski ACCESS(rxfd)link = virt_to_bus(&(ACCESS(rxfd)status)); 640*1b8adde7SWilliam Kucharski ACCESS(rxfd)rx_buf_addr = virt_to_bus(&nic->packet); 641*1b8adde7SWilliam Kucharski ACCESS(rxfd)count = 0; 642*1b8adde7SWilliam Kucharski ACCESS(rxfd)size = 1528; 643*1b8adde7SWilliam Kucharski 644*1b8adde7SWilliam Kucharski outl(virt_to_bus(&(ACCESS(rxfd)status)), ioaddr + SCBPointer); 645*1b8adde7SWilliam Kucharski outw(INT_MASK | RX_START, ioaddr + SCBCmd); 646*1b8adde7SWilliam Kucharski wait_for_cmd_done(ioaddr + SCBCmd); 647*1b8adde7SWilliam Kucharski 648*1b8adde7SWilliam Kucharski whereami ("started RX process."); 649*1b8adde7SWilliam Kucharski 650*1b8adde7SWilliam Kucharski /* Start the reciever.... */ 651*1b8adde7SWilliam Kucharski ACCESS(rxfd)status = 0; 652*1b8adde7SWilliam Kucharski ACCESS(rxfd)command = 0xc000; 653*1b8adde7SWilliam Kucharski outl(virt_to_bus(&(ACCESS(rxfd)status)), ioaddr + SCBPointer); 654*1b8adde7SWilliam Kucharski outw(INT_MASK | RX_START, ioaddr + SCBCmd); 655*1b8adde7SWilliam Kucharski 656*1b8adde7SWilliam Kucharski /* INIT TX stuff. */ 657*1b8adde7SWilliam Kucharski 658*1b8adde7SWilliam Kucharski /* Base = 0 */ 659*1b8adde7SWilliam Kucharski outl(0, ioaddr + SCBPointer); 660*1b8adde7SWilliam Kucharski outw(INT_MASK | CU_CMD_BASE, ioaddr + SCBCmd); 661*1b8adde7SWilliam Kucharski wait_for_cmd_done(ioaddr + SCBCmd); 662*1b8adde7SWilliam Kucharski 663*1b8adde7SWilliam Kucharski whereami ("set TX base addr."); 664*1b8adde7SWilliam Kucharski 665*1b8adde7SWilliam Kucharski txfd.command = (CmdIASetup); 666*1b8adde7SWilliam Kucharski txfd.status = 0x0000; 667*1b8adde7SWilliam Kucharski txfd.link = virt_to_bus (&confcmd); 668*1b8adde7SWilliam Kucharski 669*1b8adde7SWilliam Kucharski { 670*1b8adde7SWilliam Kucharski char *t = (char *)&txfd.tx_desc_addr; 671*1b8adde7SWilliam Kucharski 672*1b8adde7SWilliam Kucharski for (i=0;i<ETH_ALEN;i++) 673*1b8adde7SWilliam Kucharski t[i] = nic->node_addr[i]; 674*1b8adde7SWilliam Kucharski } 675*1b8adde7SWilliam Kucharski 676*1b8adde7SWilliam Kucharski #ifdef DEBUG 677*1b8adde7SWilliam Kucharski printf ("Setup_eaddr:\n"); 678*1b8adde7SWilliam Kucharski hd (&txfd, 0x20); 679*1b8adde7SWilliam Kucharski #endif 680*1b8adde7SWilliam Kucharski /* options = 0x40; */ /* 10mbps half duplex... */ 681*1b8adde7SWilliam Kucharski options = 0x00; /* Autosense */ 682*1b8adde7SWilliam Kucharski 683*1b8adde7SWilliam Kucharski #ifdef PROMISC 684*1b8adde7SWilliam Kucharski rx_mode = 3; 685*1b8adde7SWilliam Kucharski #elif ALLMULTI 686*1b8adde7SWilliam Kucharski rx_mode = 1; 687*1b8adde7SWilliam Kucharski #else 688*1b8adde7SWilliam Kucharski rx_mode = 0; 689*1b8adde7SWilliam Kucharski #endif 690*1b8adde7SWilliam Kucharski 691*1b8adde7SWilliam Kucharski if ( ((eeprom[6]>>8) & 0x3f) == DP83840 692*1b8adde7SWilliam Kucharski || ((eeprom[6]>>8) & 0x3f) == DP83840A) { 693*1b8adde7SWilliam Kucharski int mdi_reg23 = mdio_read(eeprom[6] & 0x1f, 23) | 0x0422; 694*1b8adde7SWilliam Kucharski if (congenb) 695*1b8adde7SWilliam Kucharski mdi_reg23 |= 0x0100; 696*1b8adde7SWilliam Kucharski printf(" DP83840 specific setup, setting register 23 to %hX.\n", 697*1b8adde7SWilliam Kucharski mdi_reg23); 698*1b8adde7SWilliam Kucharski mdio_write(eeprom[6] & 0x1f, 23, mdi_reg23); 699*1b8adde7SWilliam Kucharski } 700*1b8adde7SWilliam Kucharski whereami ("Done DP8340 special setup."); 701*1b8adde7SWilliam Kucharski if (options != 0) { 702*1b8adde7SWilliam Kucharski mdio_write(eeprom[6] & 0x1f, 0, 703*1b8adde7SWilliam Kucharski ((options & 0x20) ? 0x2000 : 0) | /* 100mbps? */ 704*1b8adde7SWilliam Kucharski ((options & 0x10) ? 0x0100 : 0)); /* Full duplex? */ 705*1b8adde7SWilliam Kucharski whereami ("set mdio_register."); 706*1b8adde7SWilliam Kucharski } 707*1b8adde7SWilliam Kucharski 708*1b8adde7SWilliam Kucharski confcmd.command = CmdSuspend | CmdConfigure; 709*1b8adde7SWilliam Kucharski confcmd.status = 0x0000; 710*1b8adde7SWilliam Kucharski confcmd.link = virt_to_bus (&txfd); 711*1b8adde7SWilliam Kucharski confcmd.data[1] = (txfifo << 4) | rxfifo; 712*1b8adde7SWilliam Kucharski confcmd.data[4] = rxdmacount; 713*1b8adde7SWilliam Kucharski confcmd.data[5] = txdmacount + 0x80; 714*1b8adde7SWilliam Kucharski confcmd.data[15] = (rx_mode & 2) ? 0x49: 0x48; 715*1b8adde7SWilliam Kucharski confcmd.data[19] = (options & 0x10) ? 0xC0 : 0x80; 716*1b8adde7SWilliam Kucharski confcmd.data[21] = (rx_mode & 1) ? 0x0D: 0x05; 717*1b8adde7SWilliam Kucharski 718*1b8adde7SWilliam Kucharski outl(virt_to_bus(&txfd), ioaddr + SCBPointer); 719*1b8adde7SWilliam Kucharski outw(INT_MASK | CU_START, ioaddr + SCBCmd); 720*1b8adde7SWilliam Kucharski wait_for_cmd_done(ioaddr + SCBCmd); 721*1b8adde7SWilliam Kucharski 722*1b8adde7SWilliam Kucharski whereami ("started TX thingy (config, iasetup)."); 723*1b8adde7SWilliam Kucharski 724*1b8adde7SWilliam Kucharski load_timer2(10*TICKS_PER_MS); 725*1b8adde7SWilliam Kucharski while (!txfd.status && timer2_running()) 726*1b8adde7SWilliam Kucharski /* Wait */; 727*1b8adde7SWilliam Kucharski 728*1b8adde7SWilliam Kucharski /* Read the status register once to disgard stale data */ 729*1b8adde7SWilliam Kucharski mdio_read(eeprom[6] & 0x1f, 1); 730*1b8adde7SWilliam Kucharski /* Check to see if the network cable is plugged in. 731*1b8adde7SWilliam Kucharski * This allows for faster failure if there is nothing 732*1b8adde7SWilliam Kucharski * we can do. 733*1b8adde7SWilliam Kucharski */ 734*1b8adde7SWilliam Kucharski if (!(mdio_read(eeprom[6] & 0x1f, 1) & (1 << 2))) { 735*1b8adde7SWilliam Kucharski printf("Valid link not established\n"); 736*1b8adde7SWilliam Kucharski eepro100_disable(dev); 737*1b8adde7SWilliam Kucharski return 0; 738*1b8adde7SWilliam Kucharski } 739*1b8adde7SWilliam Kucharski 740*1b8adde7SWilliam Kucharski dev->disable = eepro100_disable; 741*1b8adde7SWilliam Kucharski nic->poll = eepro100_poll; 742*1b8adde7SWilliam Kucharski nic->transmit = eepro100_transmit; 743*1b8adde7SWilliam Kucharski nic->irq = eepro100_irq; 744*1b8adde7SWilliam Kucharski return 1; 745*1b8adde7SWilliam Kucharski } 746*1b8adde7SWilliam Kucharski 747*1b8adde7SWilliam Kucharski /*********************************************************************/ 748*1b8adde7SWilliam Kucharski 749*1b8adde7SWilliam Kucharski #ifdef DEBUG 750*1b8adde7SWilliam Kucharski 751*1b8adde7SWilliam Kucharski /* Hexdump a number of bytes from memory... */ 752*1b8adde7SWilliam Kucharski void hd (void *where, int n) 753*1b8adde7SWilliam Kucharski { 754*1b8adde7SWilliam Kucharski int i; 755*1b8adde7SWilliam Kucharski 756*1b8adde7SWilliam Kucharski while (n > 0) { 757*1b8adde7SWilliam Kucharski printf ("%X ", where); 758*1b8adde7SWilliam Kucharski for (i=0;i < ( (n>16)?16:n);i++) 759*1b8adde7SWilliam Kucharski printf (" %hhX", ((char *)where)[i]); 760*1b8adde7SWilliam Kucharski printf ("\n"); 761*1b8adde7SWilliam Kucharski n -= 16; 762*1b8adde7SWilliam Kucharski where += 16; 763*1b8adde7SWilliam Kucharski } 764*1b8adde7SWilliam Kucharski } 765*1b8adde7SWilliam Kucharski #endif 766*1b8adde7SWilliam Kucharski 767*1b8adde7SWilliam Kucharski static struct pci_id eepro100_nics[] = { 768*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x1029, "id1029", "Intel EtherExpressPro100 ID1029"), 769*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x1030, "id1030", "Intel EtherExpressPro100 ID1030"), 770*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x1031, "82801cam", "Intel 82801CAM (ICH3) Chipset Ethernet Controller"), 771*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x1032, "eepro100-1032", "Intel PRO/100 VE Network Connection"), 772*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x1033, "eepro100-1033", "Intel PRO/100 VM Network Connection"), 773*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x1034, "eepro100-1034", "Intel PRO/100 VM Network Connection"), 774*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x1035, "eepro100-1035", "Intel 82801CAM (ICH3) Chipset Ethernet Controller"), 775*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x1036, "eepro100-1036", "Intel 82801CAM (ICH3) Chipset Ethernet Controller"), 776*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x1037, "eepro100-1037", "Intel 82801CAM (ICH3) Chipset Ethernet Controller"), 777*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x1038, "id1038", "Intel PRO/100 VM Network Connection"), 778*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x1039, "82562et", "Intel PRO100 VE 82562ET"), 779*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x103a, "id103a", "Intel Corporation 82559 InBusiness 10/100"), 780*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x103b, "82562etb", "Intel PRO100 VE 82562ETB"), 781*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x103c, "eepro100-103c", "Intel PRO/100 VM Network Connection"), 782*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x103d, "eepro100-103d", "Intel PRO/100 VE Network Connection"), 783*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x103e, "eepro100-103e", "Intel PRO/100 VM Network Connection"), 784*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x1059, "82551qm", "Intel PRO/100 M Mobile Connection"), 785*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x1209, "82559er", "Intel EtherExpressPro100 82559ER"), 786*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x1227, "82865", "Intel 82865 EtherExpress PRO/100A"), 787*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x1228, "82556", "Intel 82556 EtherExpress PRO/100 Smart"), 788*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x1229, "eepro100", "Intel EtherExpressPro100"), 789*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x2449, "82562em", "Intel EtherExpressPro100 82562EM"), 790*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x2459, "82562-1", "Intel 82562 based Fast Ethernet Connection"), 791*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x245d, "82562-2", "Intel 82562 based Fast Ethernet Connection"), 792*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x1050, "82562ez", "Intel 82562EZ Network Connection"), 793*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x5200, "eepro100-5200", "Intel EtherExpress PRO/100 Intelligent Server"), 794*1b8adde7SWilliam Kucharski PCI_ROM(0x8086, 0x5201, "eepro100-5201", "Intel EtherExpress PRO/100 Intelligent Server"), 795*1b8adde7SWilliam Kucharski }; 796*1b8adde7SWilliam Kucharski 797*1b8adde7SWilliam Kucharski /* Cards with device ids 0x1030 to 0x103F, 0x2449, 0x2459 or 0x245D might need 798*1b8adde7SWilliam Kucharski * a workaround for hardware bug on 10 mbit half duplex (see linux driver eepro100.c) 799*1b8adde7SWilliam Kucharski * 2003/03/17 gbaum */ 800*1b8adde7SWilliam Kucharski 801*1b8adde7SWilliam Kucharski 802*1b8adde7SWilliam Kucharski struct pci_driver eepro100_driver = { 803*1b8adde7SWilliam Kucharski .type = NIC_DRIVER, 804*1b8adde7SWilliam Kucharski .name = "EEPRO100", 805*1b8adde7SWilliam Kucharski .probe = eepro100_probe, 806*1b8adde7SWilliam Kucharski .ids = eepro100_nics, 807*1b8adde7SWilliam Kucharski .id_count = sizeof(eepro100_nics)/sizeof(eepro100_nics[0]), 808*1b8adde7SWilliam Kucharski .class = 0 809*1b8adde7SWilliam Kucharski }; 810