xref: /titanic_51/usr/src/grub/grub-0.97/netboot/eepro100.c (revision 1b8adde7ba7d5e04395c141c5400dc2cffd7d809)
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