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. */
wait_for_cmd_done(int cmd_ioaddr)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
mdio_write(int phy_id,int location,int value)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 */
mdio_read(int phy_id,int location)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 */
do_eeprom_cmd(int cmd,int cmd_len)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
eepro100_irq(struct nic * nic __unused,irq_action_t action __unused)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
eepro100_transmit(struct nic * nic,const char * d,unsigned int t,unsigned int s,const char * p)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
speedo_rx_soft_reset(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
eepro100_poll(struct nic * nic,int retrieve)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 */
eepro100_disable(struct dev * dev __unused)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
eepro100_probe(struct dev * dev,struct pci_device * p)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... */
hd(void * where,int n)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