Pārlūkot izejas kodu

Split 3c509.c into 3c509.9 and 3c529.c, with shared code in 3c5x9.c.

Probe mechanisms now use standard EISA and MCA bus methods, with 3c509.c
defining a custom ISA bus to handle the 3c509 contention resolution logic.
tags/v0.9.3
Michael Brown 19 gadus atpakaļ
vecāks
revīzija
4c0d5a0b71
4 mainītis faili ar 683 papildinājumiem un 622 dzēšanām
  1. 212
    619
      src/drivers/net/3c509.c
  2. 9
    3
      src/drivers/net/3c509.h
  3. 49
    0
      src/drivers/net/3c529.c
  4. 413
    0
      src/drivers/net/3c5x9.c

+ 212
- 619
src/drivers/net/3c509.c Parādīt failu

@@ -1,355 +1,92 @@
1
-/**************************************************************************
2
-ETHERBOOT -  BOOTP/TFTP Bootstrap Program
3
-
4
-Author: Martin Renters.
5
-  Date: Mar 22 1995
6
-
7
- This code is based heavily on David Greenman's if_ed.c driver and
8
-  Andres Vega Garcia's if_ep.c driver.
9
-
10
- Copyright (C) 1993-1994, David Greenman, Martin Renters.
11
- Copyright (C) 1993-1995, Andres Vega Garcia.
12
- Copyright (C) 1995, Serge Babkin.
13
-  This software may be used, modified, copied, distributed, and sold, in
14
-  both source and binary form provided that the above copyright and these
15
-  terms are retained. Under no circumstances are the authors responsible for
16
-  the proper functioning of this software, nor do the authors assume any
17
-  responsibility for damages incurred with its use.
18
-
19
-3c509 support added by Serge Babkin (babkin@hq.icb.chel.su)
20
-
21
-$Id$
22
-
23
-***************************************************************************/
24
-
25
-/* #define EDEBUG */
1
+/*
2
+ * Split out into 3c509.c and 3c5x9.c, to make it possible to build a
3
+ * 3c529 module without including ISA, ISAPnP and EISA code.
4
+ *
5
+ */
26 6
 
27
-#include "etherboot.h"
28
-#include "nic.h"
7
+#include "eisa.h"
29 8
 #include "isa.h"
9
+#include "dev.h"
10
+#include "io.h"
30 11
 #include "timer.h"
12
+#include "string.h"
13
+#include "etherboot.h"
31 14
 #include "3c509.h"
32 15
 
33
-static unsigned short	eth_nic_base;
34
-static enum { none, bnc, utp } connector = none;	/* for 3C509 */
35
-
36
-#ifdef	INCLUDE_3C529
37 16
 /*
38
- * This table and several other pieces of the MCA support
39
- * code were shamelessly borrowed from the Linux kernel source.
17
+ * 3c509 cards have their own method of contention resolution; this
18
+ * effectively defines another bus type.
40 19
  *
41
- * MCA support added by Adam Fritzler (mid@auk.cx)
20
+ */
21
+
22
+/*
23
+ * A physical t509 device
42 24
  *
43 25
  */
44
-struct el3_mca_adapters_struct {
45
-        const char *name;
46
-        int id;
47
-};
48
-static struct el3_mca_adapters_struct el3_mca_adapters[] = {
49
-        { "3Com 3c529 EtherLink III (10base2)", 0x627c },
50
-        { "3Com 3c529 EtherLink III (10baseT)", 0x627d },
51
-        { "3Com 3c529 EtherLink III (test mode)", 0x62db },
52
-        { "3Com 3c529 EtherLink III (TP or coax)", 0x62f6 },
53
-        { "3Com 3c529 EtherLink III (TP)", 0x62f7 },
54
-        { NULL, 0 },
26
+struct t509_device {
27
+	char *magic; /* must be first */
28
+	struct dev *dev;
29
+	uint16_t id_port;
30
+	uint16_t ioaddr;
31
+	unsigned char current_tag;
55 32
 };
56
-#endif
57
-
58
-/**************************************************************************
59
-ETH_RESET - Reset adapter
60
-***************************************************************************/
61
-static void t509_reset(struct nic *nic)
62
-{
63
-	int i;
64
-
65
-	/***********************************************************
66
-			Reset 3Com 509 card
67
-	*************************************************************/
68
-
69
-	/* stop card */
70
-	outw(RX_DISABLE, BASE + EP_COMMAND);
71
-	outw(RX_DISCARD_TOP_PACK, BASE + EP_COMMAND);
72
-	while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS)
73
-		;
74
-	outw(TX_DISABLE, BASE + EP_COMMAND);
75
-	outw(STOP_TRANSCEIVER, BASE + EP_COMMAND);
76
-	udelay(1000);
77
-	outw(RX_RESET, BASE + EP_COMMAND);
78
-	outw(TX_RESET, BASE + EP_COMMAND);
79
-	outw(C_INTR_LATCH, BASE + EP_COMMAND);
80
-	outw(SET_RD_0_MASK, BASE + EP_COMMAND);
81
-	outw(SET_INTR_MASK, BASE + EP_COMMAND);
82
-	outw(SET_RX_FILTER, BASE + EP_COMMAND);
83
-
84
-	/*
85
-	* initialize card
86
-	*/
87
-	while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS)
88
-		;
89
-
90
-	GO_WINDOW(0);
91
-
92
-	/* Disable the card */
93
-	outw(0, BASE + EP_W0_CONFIG_CTRL);
94
-
95
-	/* Configure IRQ to none */
96
-	outw(SET_IRQ(0), BASE + EP_W0_RESOURCE_CFG);
97
-
98
-	/* Enable the card */
99
-	outw(ENABLE_DRQ_IRQ, BASE + EP_W0_CONFIG_CTRL);
100
-
101
-	GO_WINDOW(2);
102
-
103
-	/* Reload the ether_addr. */
104
-	for (i = 0; i < ETH_ALEN; i++)
105
-		outb(nic->node_addr[i], BASE + EP_W2_ADDR_0 + i);
106
-
107
-	outw(RX_RESET, BASE + EP_COMMAND);
108
-	outw(TX_RESET, BASE + EP_COMMAND);
109
-
110
-	/* Window 1 is operating window */
111
-	GO_WINDOW(1);
112
-	for (i = 0; i < 31; i++)
113
-		inb(BASE + EP_W1_TX_STATUS);
114
-
115
-	/* get rid of stray intr's */
116
-	outw(ACK_INTR | 0xff, BASE + EP_COMMAND);
117
-
118
-	outw(SET_RD_0_MASK | S_5_INTS, BASE + EP_COMMAND);
119
-
120
-	outw(SET_INTR_MASK, BASE + EP_COMMAND);
121
-
122
-	outw(SET_RX_FILTER | FIL_GROUP | FIL_INDIVIDUAL | FIL_BRDCST, BASE + EP_COMMAND);
123
-
124
-	/* configure BNC */
125
-	if (connector == bnc) {
126
-		outw(START_TRANSCEIVER, BASE + EP_COMMAND);
127
-		udelay(1000);
128
-	}
129
-	/* configure UTP */
130
-	else if (connector == utp) {
131
-		GO_WINDOW(4);
132
-		outw(ENABLE_UTP, BASE + EP_W4_MEDIA_TYPE);
133
-		sleep(2);	/* Give time for media to negotiate */
134
-		GO_WINDOW(1);
135
-	}
136
-
137
-	/* start transceiver and receiver */
138
-	outw(RX_ENABLE, BASE + EP_COMMAND);
139
-	outw(TX_ENABLE, BASE + EP_COMMAND);
140 33
 
141
-	/* set early threshold for minimal packet length */
142
-	outw(SET_RX_EARLY_THRESH | ETH_ZLEN, BASE + EP_COMMAND);
143
-	outw(SET_TX_START_THRESH | 16, BASE + EP_COMMAND);
144
-}
145
-
146
-/**************************************************************************
147
-ETH_TRANSMIT - Transmit a frame
148
-***************************************************************************/
149
-static char padmap[] = {
150
-	0, 3, 2, 1};
151
-
152
-static void t509_transmit(
153
-struct nic *nic,
154
-const char *d,			/* Destination */
155
-unsigned int t,			/* Type */
156
-unsigned int s,			/* size */
157
-const char *p)			/* Packet */
158
-{
159
-	register unsigned int len;
160
-	int pad;
161
-	int status;
162
-
163
-#ifdef	EDEBUG
164
-	printf("{l=%d,t=%hX}",s+ETH_HLEN,t);
165
-#endif
166
-
167
-	/* swap bytes of type */
168
-	t= htons(t);
169
-
170
-	len=s+ETH_HLEN; /* actual length of packet */
171
-	pad = padmap[len & 3];
172
-
173
-	/*
174
-	* The 3c509 automatically pads short packets to minimum ethernet length,
175
-	* but we drop packets that are too large. Perhaps we should truncate
176
-	* them instead?
177
-	*/
178
-	if (len + pad > ETH_FRAME_LEN) {
179
-		return;
180
-	}
181
-
182
-	/* drop acknowledgements */
183
-	while ((status=inb(BASE + EP_W1_TX_STATUS)) & TXS_COMPLETE ) {
184
-		if (status & (TXS_UNDERRUN|TXS_MAX_COLLISION|TXS_STATUS_OVERFLOW)) {
185
-			outw(TX_RESET, BASE + EP_COMMAND);
186
-			outw(TX_ENABLE, BASE + EP_COMMAND);
187
-		}
188
-		outb(0x0, BASE + EP_W1_TX_STATUS);
189
-	}
190
-
191
-	while (inw(BASE + EP_W1_FREE_TX) < (unsigned short)len + pad + 4)
192
-		; /* no room in FIFO */
193
-
194
-	outw(len, BASE + EP_W1_TX_PIO_WR_1);
195
-	outw(0x0, BASE + EP_W1_TX_PIO_WR_1);	/* Second dword meaningless */
196
-
197
-	/* write packet */
198
-	outsw(BASE + EP_W1_TX_PIO_WR_1, d, ETH_ALEN/2);
199
-	outsw(BASE + EP_W1_TX_PIO_WR_1, nic->node_addr, ETH_ALEN/2);
200
-	outw(t, BASE + EP_W1_TX_PIO_WR_1);
201
-	outsw(BASE + EP_W1_TX_PIO_WR_1, p, s / 2);
202
-	if (s & 1)
203
-		outb(*(p+s - 1), BASE + EP_W1_TX_PIO_WR_1);
204
-
205
-	while (pad--)
206
-		outb(0, BASE + EP_W1_TX_PIO_WR_1);	/* Padding */
207
-
208
-	/* wait for Tx complete */
209
-	while((inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS) != 0)
210
-		;
211
-}
212
-
213
-/**************************************************************************
214
-ETH_POLL - Wait for a frame
215
-***************************************************************************/
216
-static int t509_poll(struct nic *nic, int retrieve)
217
-{
218
-	/* common variables */
219
-	/* variables for 3C509 */
220
-	short status, cst;
221
-	register short rx_fifo;
222
-
223
-	cst=inw(BASE + EP_STATUS);
224
-
225
-#ifdef	EDEBUG
226
-	if(cst & 0x1FFF)
227
-		printf("-%hX-",cst);
228
-#endif
229
-
230
-	if( (cst & S_RX_COMPLETE)==0 ) {
231
-		/* acknowledge  everything */
232
-		outw(ACK_INTR| (cst & S_5_INTS), BASE + EP_COMMAND);
233
-		outw(C_INTR_LATCH, BASE + EP_COMMAND);
234
-
235
-		return 0;
236
-	}
237
-
238
-	status = inw(BASE + EP_W1_RX_STATUS);
239
-#ifdef	EDEBUG
240
-	printf("*%hX*",status);
241
-#endif
242
-
243
-	if (status & ERR_RX) {
244
-		outw(RX_DISCARD_TOP_PACK, BASE + EP_COMMAND);
245
-		return 0;
246
-	}
34
+/*
35
+ * A t509 driver
36
+ *
37
+ */
38
+struct t509_driver {
39
+	char *name;
40
+};
247 41
 
248
-	rx_fifo = status & RX_BYTES_MASK;
249
-	if (rx_fifo==0)
250
-		return 0;
42
+/*
43
+ * Ensure that there is sufficient space in the shared dev_bus
44
+ * structure for a struct pci_device.
45
+ *
46
+ */
47
+DEV_BUS( struct t509_device, t509_dev );
48
+static char t509_magic[0]; /* guaranteed unique symbol */
251 49
 
252
-	if ( ! retrieve ) return 1;
253
-
254
-		/* read packet */
255
-#ifdef	EDEBUG
256
-	printf("[l=%d",rx_fifo);
257
-#endif
258
-	insw(BASE + EP_W1_RX_PIO_RD_1, nic->packet, rx_fifo / 2);
259
-	if(rx_fifo & 1)
260
-		nic->packet[rx_fifo-1]=inb(BASE + EP_W1_RX_PIO_RD_1);
261
-	nic->packetlen=rx_fifo;
262
-
263
-	while(1) {
264
-		status = inw(BASE + EP_W1_RX_STATUS);
265
-#ifdef	EDEBUG
266
-		printf("*%hX*",status);
267
-#endif
268
-		rx_fifo = status & RX_BYTES_MASK;
269
-		if(rx_fifo>0) {
270
-			insw(BASE + EP_W1_RX_PIO_RD_1, nic->packet+nic->packetlen, rx_fifo / 2);
271
-			if(rx_fifo & 1)
272
-				nic->packet[nic->packetlen+rx_fifo-1]=inb(BASE + EP_W1_RX_PIO_RD_1);
273
-			nic->packetlen+=rx_fifo;
274
-#ifdef	EDEBUG
275
-			printf("+%d",rx_fifo);
276
-#endif
277
-		}
278
-		if(( status & RX_INCOMPLETE )==0) {
279
-#ifdef	EDEBUG
280
-			printf("=%d",nic->packetlen);
281
-#endif
282
-			break;
50
+/*
51
+ * Find a port that can be used for contention select
52
+ *
53
+ * Called only once, so inlined for efficiency.
54
+ *
55
+ */
56
+static inline int find_id_port ( struct t509_device *t509 ) {
57
+	for ( t509->id_port = EP_ID_PORT_START ;
58
+	      t509->id_port < EP_ID_PORT_END ;
59
+	      t509->id_port += EP_ID_PORT_INC ) {
60
+		outb ( 0x00, t509->id_port );
61
+		outb ( 0xff, t509->id_port );
62
+		if ( inb ( t509->id_port ) & 0x01 ) {
63
+			/* Found a suitable port */
64
+			return 1;
283 65
 		}
284
-		udelay(1000);	/* if incomplete wait 1 ms */
285 66
 	}
286
-	/* acknowledge reception of packet */
287
-	outw(RX_DISCARD_TOP_PACK, BASE + EP_COMMAND);
288
-	while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS)
289
-		;
290
-#ifdef	EDEBUG
291
-{
292
-	unsigned short type = 0;	/* used by EDEBUG */
293
-	type = (nic->packet[12]<<8) | nic->packet[13];
294
-	if(nic->packet[0]+nic->packet[1]+nic->packet[2]+nic->packet[3]+nic->packet[4]+
295
-	    nic->packet[5] == 0xFF*ETH_ALEN)
296
-		printf(",t=%hX,b]",type);
297
-	else
298
-		printf(",t=%hX]",type);
299
-}
300
-#endif
301
-	return (1);
302
-}
303
-
304
-/*************************************************************************
305
-	3Com 509 - specific routines
306
-**************************************************************************/
307
-
308
-static int
309
-eeprom_rdy(void)
310
-{
311
-	int i;
312
-
313
-	for (i = 0; is_eeprom_busy(IS_BASE) && i < MAX_EEPROMBUSY; i++);
314
-	if (i >= MAX_EEPROMBUSY) {
315
-		/* printf("3c509: eeprom failed to come ready.\n"); */
316
-		/* memory in EPROM is tight */
317
-		/* printf("3c509: eeprom busy.\n"); */
318
-		return (0);
319
-	}
320
-	return (1);
67
+	/* No id port available */
68
+	return 0;
321 69
 }
322 70
 
323 71
 /*
324
- * get_e: gets a 16 bits word from the EEPROM. we must have set the window
325
- * before
72
+ * Send ID sequence to the ID port
73
+ *
74
+ * Called only once, so inlined for efficiency.
75
+ *
326 76
  */
327
-static int
328
-get_e(int offset)
329
-{
330
-	if (!eeprom_rdy())
331
-		return (0xffff);
332
-	outw(EEPROM_CMD_RD | offset, IS_BASE + EP_W0_EEPROM_COMMAND);
333
-	if (!eeprom_rdy())
334
-		return (0xffff);
335
-	return (inw(IS_BASE + EP_W0_EEPROM_DATA));
77
+static inline void send_id_sequence ( struct t509_device *t509 ) {
78
+	unsigned short lrs_state, i;
79
+
80
+	outb ( 0x00, t509->id_port );
81
+        outb ( 0x00, t509->id_port );
82
+	lrs_state = 0xff;
83
+        for ( i = 0; i < 255; i++ ) {
84
+                outb ( lrs_state, t509->id_port );
85
+                lrs_state <<= 1;
86
+                lrs_state = lrs_state & 0x100 ? lrs_state ^ 0xcf : lrs_state;
87
+        }
336 88
 }
337 89
 
338
-static int
339
-send_ID_sequence(int port)
340
-{
341
-	int cx, al;
342
-
343
-	for (al = 0xff, cx = 0; cx < 255; cx++) {
344
-		outb(al, port);
345
-		al <<= 1;
346
-		if (al & 0x100)
347
-			al ^= 0xcf;
348
-	}
349
-	return (1);
350
-}
351
-
352
-
353 90
 /*
354 91
  * We get eeprom data from the id_port given an offset into the eeprom.
355 92
  * Basically; after the ID_sequence is sent to all of the cards; they enter
@@ -362,314 +99,170 @@ send_ID_sequence(int port)
362 99
  * the AX register which is conveniently returned to us by inb().  Hence; we
363 100
  * read 16 times getting one bit of data with each read.
364 101
  */
365
-static int
366
-get_eeprom_data(int id_port, int offset)
367
-{
102
+static uint16_t id_read_eeprom ( struct t509_device *t509, int offset ) {
368 103
 	int i, data = 0;
369
-	outb(0x80 + offset, id_port);
104
+
105
+	outb ( 0x80 + offset, t509->id_port );
370 106
 	/* Do we really need this wait? Won't be noticeable anyway */
371 107
 	udelay(10000);
372
-	for (i = 0; i < 16; i++)
373
-		data = (data << 1) | (inw(id_port) & 1);
374
-	return (data);
375
-}
376
-
377
-static void __t509_disable(void)
378
-{
379
-	outb(0xc0, EP_ID_PORT);
380
-}
381 108
 
382
-static void t509_disable ( struct nic *nic ) {
383
-	/* reset and disable merge */
384
-	t509_reset(nic);
385
-	__t509_disable();
386
-}
387
-
388
-static void t509_irq(struct nic *nic __unused, irq_action_t action __unused)
389
-{
390
-  switch ( action ) {
391
-  case DISABLE :
392
-    break;
393
-  case ENABLE :
394
-    break;
395
-  case FORCE :
396
-    break;
397
-  }
109
+	for ( i = 0; i < 16; i++ ) {
110
+		data = ( data << 1 ) | ( inw ( t509->id_port ) & 1 );
111
+	}
112
+	return data;
398 113
 }
399 114
 
400
-/**************************************************************************
401
-ETH_PROBE - Look for an adapter
402
-***************************************************************************/
403
-#ifdef	INCLUDE_3C529
404
-static int t529_probe(struct dev *dev, unsigned short *probe_addrs __unused)
405
-#else
406
-static int t509_probe(struct dev *dev, unsigned short *probe_addrs __unused)
407
-#endif
408
-{
409
-	struct nic *nic = (struct nic *)dev;
410
-	/* common variables */
115
+/*
116
+ * Find the next t509 device
117
+ *
118
+ * Called only once, so inlined for efficiency.
119
+ *
120
+ */
121
+static inline int fill_t509_device ( struct t509_device *t509 ) {
411 122
 	int i;
412
-	int failcount;
413
-
414
-#ifdef	INCLUDE_3C529
415
-	struct el3_mca_adapters_struct *mcafound = NULL;
416
-	int mca_pos4 = 0, mca_pos5 = 0, mca_irq = 0;
417
-#endif
418
-
419
-	__t509_disable();		/* in case board was active */
420
-
421
-	for (failcount = 0; failcount < 100; failcount++) {
422
-		int data, j, io_base, id_port;
423
-		unsigned short k;
424
-		int ep_current_tag;
425
-		short *p;
426
-#ifdef	INCLUDE_3C529
427
-		int curboard;
428
-#endif
429
-
430
-		id_port = EP_ID_PORT;
431
-		ep_current_tag = EP_LAST_TAG + 1;
432
-
433
-	/*********************************************************
434
-			Search for 3Com 509 card
435
-	***********************************************************/
436
-#ifdef	INCLUDE_3C529
437
-		/*
438
-		 * XXX: We should really check to make sure we have an MCA
439
-		 * bus controller before going ahead with this...
440
-		 *
441
-		 * For now, we avoid any hassle by making it a compile
442
-		 * time option.
443
-		 *
444
-		 */
445
-		/* printf("\nWarning: Assuming presence of MCA bus\n"); */
446
-
447
-                /* Make sure motherboard setup is off */
448
-                outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG);
449
-
450
-		/* Cycle through slots */
451
-		for(curboard=0; curboard<MCA_MAX_SLOT_NR; curboard++) {
452
-			int boardid;
453
-			int curcard;
454
-
455
-			outb_p(0x8|(curboard&0xf), MCA_ADAPTER_SETUP_REG);
456
-
457
-			boardid = inb_p(MCA_POS_REG(0));
458
-			boardid += inb_p(MCA_POS_REG(1)) << 8;
459
-
460
-			curcard = 0;
461
-			while (el3_mca_adapters[curcard].name) {
462
-				if (el3_mca_adapters[curcard].id == boardid) {
463
-					mcafound = &el3_mca_adapters[curcard];
464
-
465
-					mca_pos4 = inb_p(MCA_POS_REG(4));
466
-					mca_pos5 = inb_p(MCA_POS_REG(5));
467
-
468
-					goto donewithdetect;
469
-				}
470
-				else
471
-					curcard++;
472
-			}
123
+	uint16_t iobase;
473 124
 
125
+	/* 
126
+	 * If this is the start of the scan, find an id_port and clear
127
+	 * all tag registers.  Otherwise, tell already-found NICs not
128
+	 * to respond.
129
+	 *
130
+	 */
131
+	if ( t509->current_tag == 0 ) {
132
+		if ( ! find_id_port ( t509 ) ) {
133
+			DBG ( "No ID port available for contention select\n" );
134
+			return 0;
474 135
 		}
475
-	donewithdetect:
476
-		/* Kill all setup modes */
477
-		outb_p(0, MCA_ADAPTER_SETUP_REG);
478
-
479
-		if (mcafound) {
480
-			eth_nic_base = ((short)((mca_pos4&0xfc)|0x02)) << 8;
481
-			mca_irq = mca_pos5 & 0x0f;
482
-			ep_current_tag--;
483
-		}
484
-		else
485
-			/*printf("MCA Card not found\n")*/;
486
-#endif
487
-	/* Look for the EISA boards, leave them activated */
488
-	/* search for the first card, ignore all others */
489
-	for(j = 1; j < 16; j++) {
490
-		io_base = (j * EP_EISA_START) | EP_EISA_W0;
491
-		if (inw(io_base + EP_W0_MFG_ID) != MFG_ID)
492
-			continue;
493
-
494
-		/* we must have found 0x1f if the board is EISA configurated */
495
-		if ((inw(io_base + EP_W0_ADDRESS_CFG) & 0x1f) != 0x1f)
496
-			continue;
497
-
498
-		/* Reset and Enable the card */
499
-		outb(W0_P4_CMD_RESET_ADAPTER, io_base + EP_W0_CONFIG_CTRL);
500
-		udelay(1000); /* Must wait 800 µs, be conservative */
501
-		outb(W0_P4_CMD_ENABLE_ADAPTER, io_base + EP_W0_CONFIG_CTRL);
502
-
503
-		/*
504
-		 * Once activated, all the registers are mapped in the range
505
-		 * x000 - x00F, where x is the slot number.
506
-		 */
507
-		eth_nic_base = j * EP_EISA_START;
508
-		break;
136
+		outb ( 0xd0, t509->id_port );
137
+	} else {
138
+		outb ( 0xd8, t509->id_port ) ;
509 139
 	}
510
-	ep_current_tag--;
511
-
512
-	/* Look for the ISA boards. Init and leave them actived */
513
-	/* search for the first card, ignore all others */
514
-	outb(0xc0, id_port);	/* Global reset */
515
-	udelay(1000);		/* wait 1 ms */
516
-	for (i = 0; i < EP_MAX_BOARDS; i++) {
517
-		outb(0, id_port);
518
-		outb(0, id_port);
519
-		send_ID_sequence(id_port);
520
-
521
-		data = get_eeprom_data(id_port, EEPROM_MFG_ID);
522
-		if (data != MFG_ID)
523
-			break;
524
-
525
-		/* resolve contention using the Ethernet address */
526
-		for (j = 0; j < 3; j++)
527
-			data = get_eeprom_data(id_port, j);
528
-
529
-		eth_nic_base =
530
-		    (get_eeprom_data(id_port, EEPROM_ADDR_CFG) & 0x1f) * 0x10 + 0x200;
531
-		outb(ep_current_tag, id_port);	/* tags board */
532
-		outb(ACTIVATE_ADAPTER_TO_CONFIG, id_port);
533
-		ep_current_tag--;
534
-		break;
140
+
141
+	/* Send the ID sequence */
142
+	send_id_sequence ( t509 );
143
+
144
+	/* Check the manufacturer ID */
145
+	if ( id_read_eeprom ( t509, EEPROM_MFG_ID ) != MFG_ID ) {
146
+		/* No more t509 devices */
147
+		return 0;
535 148
 	}
536 149
 
537
-	if (i >= EP_MAX_BOARDS)
538
-		goto no3c509;
539
-
540
-	/*
541
-	* The iobase was found and MFG_ID was 0x6d50. PROD_ID should be
542
-	* 0x9[0-f]50
543
-	*/
544
-	GO_WINDOW(0);
545
-	k = get_e(EEPROM_PROD_ID);
546
-#ifdef	INCLUDE_3C529
547
-	/*
548
-	 * On MCA, the PROD_ID matches the MCA card ID (POS0+POS1)
549
-	 */
550
-	if (mcafound) {
551
-		if (mcafound->id != k) {
552
-			printf("MCA: PROD_ID in EEPROM does not match MCA card ID! (%hX != %hX)\n", k, mcafound->id);
553
-			goto no3c509;
554
-		}
555
-	} else { /* for ISA/EISA */
556
-		if ((k & 0xf0ff) != (PROD_ID & 0xf0ff))
557
-			goto no3c509;
150
+	/* Do contention select by reading the MAC address */
151
+	for ( i = 0 ; i < 3 ; i++ ) {
152
+		id_read_eeprom ( t509, i );
558 153
 	}
559
-#else
560
-	if ((k & 0xf0ff) != (PROD_ID & 0xf0ff))
561
-		goto no3c509;
562
-#endif
563
-
564
-#ifdef	INCLUDE_3C529
565
-	if (mcafound) {
566
-		printf("%s board found on MCA at %#hx IRQ %d -",
567
-		       mcafound->name, eth_nic_base, mca_irq);
568
-	} else {
569
-#endif
570
-		if(eth_nic_base >= EP_EISA_START)
571
-			printf("3C5x9 board on EISA at %#hx - ",eth_nic_base);
572
-		else
573
-			printf("3C5x9 board on ISA at %#hx - ",eth_nic_base);
574
-#ifdef	INCLUDE_3C529
154
+
155
+	/* By now, only one device will be left active.  Get its I/O
156
+	 * address, tag and activate the adaptor.  Tagging will
157
+	 * prevent it taking part in the next scan, enabling us to see
158
+	 * the next device.
159
+	 */
160
+	iobase = id_read_eeprom ( t509, EEPROM_ADDR_CFG );
161
+	t509->ioaddr = 0x200 + ( ( iobase & 0x1f ) << 4 );
162
+	outb ( ++t509->current_tag, t509->id_port ); /* tag */
163
+	outb ( ( 0xe0 | iobase ), t509->id_port ); /* activate */
164
+
165
+	return 1;
166
+}
167
+
168
+/*
169
+ * Obtain a struct t509_device * from a struct dev *
170
+ *
171
+ * If dev has not previously been used for a PCI device scan, blank
172
+ * out struct t509_device
173
+ */
174
+static struct t509_device * t509_device ( struct dev *dev ) {
175
+	struct t509_device *t509 = dev->bus;
176
+
177
+	if ( t509->magic != t509_magic ) {
178
+		memset ( t509, 0, sizeof ( *t509 ) );
179
+		t509->magic = t509_magic;
575 180
 	}
576
-#endif
577
-
578
-	/* test for presence of connectors */
579
-	i = inw(IS_BASE + EP_W0_CONFIG_CTRL);
580
-	j = (inw(IS_BASE + EP_W0_ADDRESS_CFG) >> 14) & 0x3;
581
-
582
-	switch(j) {
583
-		case 0:
584
-			if (i & IS_UTP) {
585
-				printf("10baseT\n");
586
-				connector = utp;
587
-				}
588
-			else {
589
-				printf("10baseT not present\n");
590
-				goto no3c509;
591
-				}
592
-			break;
593
-		case 1:
594
-			if (i & IS_AUI)
595
-				printf("10base5\n");
596
-			else {
597
-				printf("10base5 not present\n");
598
-				goto no3c509;
599
-				}
600
-			break;
601
-		case 3:
602
-			if (i & IS_BNC) {
603
-				printf("10base2\n");
604
-				connector = bnc;
605
-				}
606
-			else {
607
-				printf("10base2 not present\n");
608
-				goto no3c509;
609
-				}
610
-			break;
611
-		default:
612
-			printf("unknown connector\n");
613
-			goto no3c509;
614
-		}
615
-	/*
616
-	* Read the station address from the eeprom
617
-	*/
618
-	p = (unsigned short *) nic->node_addr;
619
-	for (i = 0; i < ETH_ALEN / 2; i++) {
620
-		GO_WINDOW(0);
621
-		p[i] = htons(get_e(i));
622
-		GO_WINDOW(2);
623
-		outw(ntohs(p[i]), BASE + EP_W2_ADDR_0 + (i * 2));
181
+	t509->dev = dev;
182
+	return t509;
183
+}
184
+
185
+/*
186
+ * Find a t509 device matching the specified driver.  ("Matching the
187
+ * specified driver" is, in this case, a no-op, but we want to
188
+ * preserve the common bus API).
189
+ *
190
+ */
191
+static int find_t509_device ( struct t509_device *t509,
192
+				 struct t509_driver *driver ) {
193
+	/* Find the next t509 device */
194
+	if ( ! fill_t509_device ( t509 ) )
195
+		return 0;
196
+	
197
+	/* Fill in dev structure, if present */
198
+	if ( t509->dev ) {
199
+		t509->dev->name = driver->name;
200
+		t509->dev->devid.bus_type = ISA_BUS_TYPE;
201
+		t509->dev->devid.vendor_id = MFG_ID;
202
+		t509->dev->devid.device_id = PROD_ID;
624 203
 	}
625
-	printf("Ethernet address: %!\n", nic->node_addr);
626
-	t509_reset(nic);
627
-
628
-	nic->irqno    = 0;
629
-	nic->ioaddr   = eth_nic_base;
630
-static struct nic_operations t509_operations;
631
-static struct nic_operations t509_operations = {
632
-	.connect	= dummy_connect,
633
-	.poll		= t509_poll,
634
-	.transmit	= t509_transmit,
635
-	.irq		= t509_irq,
636
-	.disable	= t509_disable,
637
-};
638
-	nic->nic_op	= &t509_operations;
639 204
 
640
-	/* Based on PnP ISA map */
641
-	dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
642
-	dev->devid.device_id = htons(0x80f7);
643 205
 	return 1;
644
-no3c509:
645
-	continue;
646
-	/* printf("(probe fail)"); */
647
-	}
648
-	return 0;
649 206
 }
650 207
 
651
-#ifdef INCLUDE_3C509
652
-static struct isa_driver t509_driver __isa_driver = {
653
-	.type    = NIC_DRIVER,
654
-	.name    = "3C509",
655
-	.probe   = t509_probe,
656
-	.ioaddrs = 0,
657
-};
658
-ISA_ROM("3c509","3c509, ISA/EISA");
659
-#endif
660
-
661
-#ifdef INCLUDE_3C529
662
-static struct isa_driver t529_driver __isa_driver = {
663
-	.type    = NIC_DRIVER,
664
-	.name    = "3C529",
665
-	.probe   = t529_probe,
666
-	.ioaddrs = 0,
208
+/*
209
+ * The ISA probe function
210
+ *
211
+ */
212
+static struct t509_driver el3_t509_driver = { "3c509 (ISA)" };
213
+
214
+static int el3_t509_probe ( struct dev *dev ) {
215
+	struct nic *nic = nic_device ( dev );
216
+	struct t509_device *t509 = t509_device ( dev );
217
+	
218
+	if ( ! find_t509_device ( t509, &el3_t509_driver ) )
219
+		return 0;
220
+	
221
+	nic->ioaddr = t509->ioaddr;
222
+	nic->irqno = 0;
223
+	printf ( "3C5x9 board on ISA at %#hx - ", nic->ioaddr );
224
+
225
+	/* Hand off to generic t5x9 probe routine */
226
+	return t5x9_probe ( nic, ISA_PROD_ID ( PROD_ID ), ISA_PROD_ID_MASK );
227
+}
228
+
229
+BOOT_DRIVER ( "3c509", el3_t509_probe );
230
+
231
+/*
232
+ * The 3c509 driver also supports EISA cards
233
+ *
234
+ */
235
+static struct eisa_id el3_eisa_adapters[] = {
236
+	{ "3Com 3c509 EtherLink III (EISA)", MFG_ID, PROD_ID },
667 237
 };
668
-ISA_ROM("3c529","3c529 == MCA 3c509");
669
-#endif
238
+
239
+static struct eisa_driver el3_eisa_driver =
240
+	EISA_DRIVER ( "3c509 (EISA)", el3_eisa_adapters );
241
+
242
+static int el3_eisa_probe ( struct dev *dev ) {
243
+	struct nic *nic = nic_device ( dev );
244
+	struct eisa_device *eisa = eisa_device ( dev );
245
+	
246
+	if ( ! find_eisa_device ( eisa, &el3_eisa_driver ) )
247
+		return 0;
248
+	
249
+	enable_eisa_device ( eisa );
250
+	nic->ioaddr = eisa->ioaddr;
251
+	nic->irqno = 0;
252
+	printf ( "3C5x9 board on EISA at %#hx - ", nic->ioaddr );
253
+
254
+	/* Hand off to generic t5x9 probe routine */
255
+	return t5x9_probe ( nic, ISA_PROD_ID ( PROD_ID ), ISA_PROD_ID_MASK );
256
+}
257
+
258
+BOOT_DRIVER ( "3c509 (EISA)", el3_eisa_probe );
670 259
 
671 260
 /*
672
- * Local variables:
673
- *  c-basic-offset: 8
674
- * End:
261
+ * We currently build both ISA and EISA support into a single ROM
262
+ * image, though there's no reason why this couldn't be split to
263
+ * reduce code size; just split this .c file into two in the obvious
264
+ * place.
265
+ *
675 266
  */
267
+ISA_ROM ( "3c509","3c509, ISA/EISA" );
268
+

+ 9
- 3
src/drivers/net/3c509.h Parādīt failu

@@ -49,9 +49,9 @@
49 49
 #define MAX_EEPROMBUSY	1000
50 50
 #define EP_LAST_TAG	0xd7
51 51
 #define EP_MAX_BOARDS	16
52
-#ifndef	EP_ID_PORT
53
-#define EP_ID_PORT	0x100
54
-#endif
52
+#define EP_ID_PORT_START 0x110
53
+#define EP_ID_PORT_INC 0x10
54
+#define EP_ID_PORT_END 0x200
55 55
 
56 56
 /*
57 57
  * Commands to read/write EEPROM trough EEPROM command register (Window 0,
@@ -374,6 +374,12 @@
374 374
 
375 375
 #define RX_BYTES_MASK			(unsigned short) (0x07ff)
376 376
 
377
+/*
378
+ * Function shared between 3c509.c and 3c529.c
379
+ */
380
+extern int t5x9_probe ( struct nic *nic,
381
+			uint16_t prod_id_check, uint16_t prod_id_mask );
382
+
377 383
 
378 384
 /*
379 385
  * Local variables:

+ 49
- 0
src/drivers/net/3c529.c Parādīt failu

@@ -0,0 +1,49 @@
1
+/*
2
+ * Split out from 3c509.c to make build process more sane
3
+ *
4
+ */
5
+
6
+#include "etherboot.h"
7
+#include "mca.h"
8
+#include "isa.h"
9
+#include "nic.h"
10
+#include "3c509.h"
11
+
12
+/*
13
+ * This table and several other pieces of the MCA support
14
+ * code were shamelessly borrowed from the Linux kernel source.
15
+ *
16
+ * MCA support added by Adam Fritzler (mid@auk.cx)
17
+ *
18
+ */
19
+static struct mca_id el3_mca_adapters[] = {
20
+        { "3Com 3c529 EtherLink III (10base2)", 0x627c },
21
+        { "3Com 3c529 EtherLink III (10baseT)", 0x627d },
22
+        { "3Com 3c529 EtherLink III (test mode)", 0x62db },
23
+        { "3Com 3c529 EtherLink III (TP or coax)", 0x62f6 },
24
+        { "3Com 3c529 EtherLink III (TP)", 0x62f7 },
25
+};
26
+
27
+static struct mca_driver t529_driver
28
+	= MCA_DRIVER ( "3c529", el3_mca_adapters );
29
+
30
+ISA_ROM( "3c529", "3c529 == MCA 3c509" );
31
+
32
+static int t529_probe ( struct dev *dev ) {
33
+	struct nic *nic = nic_device ( dev );
34
+	struct mca_device *mca = mca_device ( dev );
35
+
36
+	if ( ! find_mca_device ( mca, &t529_driver ) )
37
+		return 0;
38
+
39
+	/* Retrieve NIC parameters from MCA device parameters */
40
+	nic->ioaddr = ( ( mca->pos[4] & 0xfc ) | 0x02 ) << 8;
41
+	nic->irqno = mca->pos[5] & 0x0f;
42
+	printf ( "%s board found on MCA at %#hx IRQ %d -",
43
+		 dev->name, nic->ioaddr, nic->irqno );
44
+
45
+	/* Hand off to generic t5x9 probe routine */
46
+	return t5x9_probe ( nic, MCA_ID ( mca ), 0xffff );
47
+}
48
+
49
+BOOT_DRIVER ( "3c529", t529_probe );

+ 413
- 0
src/drivers/net/3c5x9.c Parādīt failu

@@ -0,0 +1,413 @@
1
+/**************************************************************************
2
+ETHERBOOT -  BOOTP/TFTP Bootstrap Program
3
+
4
+Author: Martin Renters.
5
+  Date: Mar 22 1995
6
+
7
+ This code is based heavily on David Greenman's if_ed.c driver and
8
+  Andres Vega Garcia's if_ep.c driver.
9
+
10
+ Copyright (C) 1993-1994, David Greenman, Martin Renters.
11
+ Copyright (C) 1993-1995, Andres Vega Garcia.
12
+ Copyright (C) 1995, Serge Babkin.
13
+  This software may be used, modified, copied, distributed, and sold, in
14
+  both source and binary form provided that the above copyright and these
15
+  terms are retained. Under no circumstances are the authors responsible for
16
+  the proper functioning of this software, nor do the authors assume any
17
+  responsibility for damages incurred with its use.
18
+
19
+3c509 support added by Serge Babkin (babkin@hq.icb.chel.su)
20
+
21
+$Id$
22
+
23
+***************************************************************************/
24
+
25
+/* #define EDEBUG */
26
+
27
+#include "etherboot.h"
28
+#include "nic.h"
29
+#include "isa.h"
30
+#include "timer.h"
31
+#include "3c509.h"
32
+
33
+static enum { none, bnc, utp } connector = none;	/* for 3C509 */
34
+
35
+/**************************************************************************
36
+ETH_RESET - Reset adapter
37
+***************************************************************************/
38
+static void t509_disable ( struct nic *nic ) {
39
+	/* stop card */
40
+	outw(RX_DISABLE, nic->ioaddr + EP_COMMAND);
41
+	outw(RX_DISCARD_TOP_PACK, nic->ioaddr + EP_COMMAND);
42
+	while (inw(nic->ioaddr + EP_STATUS) & S_COMMAND_IN_PROGRESS)
43
+		;
44
+	outw(TX_DISABLE, nic->ioaddr + EP_COMMAND);
45
+	outw(STOP_TRANSCEIVER, nic->ioaddr + EP_COMMAND);
46
+	udelay(1000);
47
+	outw(RX_RESET, nic->ioaddr + EP_COMMAND);
48
+	outw(TX_RESET, nic->ioaddr + EP_COMMAND);
49
+	outw(C_INTR_LATCH, nic->ioaddr + EP_COMMAND);
50
+	outw(SET_RD_0_MASK, nic->ioaddr + EP_COMMAND);
51
+	outw(SET_INTR_MASK, nic->ioaddr + EP_COMMAND);
52
+	outw(SET_RX_FILTER, nic->ioaddr + EP_COMMAND);
53
+
54
+	/*
55
+	 * wait for reset to complete
56
+	 */
57
+	while (inw(nic->ioaddr + EP_STATUS) & S_COMMAND_IN_PROGRESS)
58
+		;
59
+
60
+	GO_WINDOW(nic->ioaddr,0);
61
+
62
+	/* Disable the card */
63
+	outw(0, nic->ioaddr + EP_W0_CONFIG_CTRL);
64
+
65
+	/* Configure IRQ to none */
66
+	outw(SET_IRQ(0), nic->ioaddr + EP_W0_RESOURCE_CFG);
67
+}
68
+
69
+static void t509_enable ( struct nic *nic ) {
70
+	int i;
71
+
72
+	/* Enable the card */
73
+	GO_WINDOW(nic->ioaddr,0);
74
+	outw(ENABLE_DRQ_IRQ, nic->ioaddr + EP_W0_CONFIG_CTRL);
75
+
76
+	GO_WINDOW(nic->ioaddr,2);
77
+
78
+	/* Reload the ether_addr. */
79
+	for (i = 0; i < ETH_ALEN; i++)
80
+		outb(nic->node_addr[i], nic->ioaddr + EP_W2_ADDR_0 + i);
81
+
82
+	outw(RX_RESET, nic->ioaddr + EP_COMMAND);
83
+	outw(TX_RESET, nic->ioaddr + EP_COMMAND);
84
+
85
+	/* Window 1 is operating window */
86
+	GO_WINDOW(nic->ioaddr,1);
87
+	for (i = 0; i < 31; i++)
88
+		inb(nic->ioaddr + EP_W1_TX_STATUS);
89
+
90
+	/* get rid of stray intr's */
91
+	outw(ACK_INTR | 0xff, nic->ioaddr + EP_COMMAND);
92
+
93
+	outw(SET_RD_0_MASK | S_5_INTS, nic->ioaddr + EP_COMMAND);
94
+
95
+	outw(SET_INTR_MASK, nic->ioaddr + EP_COMMAND);
96
+
97
+	outw(SET_RX_FILTER | FIL_GROUP | FIL_INDIVIDUAL | FIL_BRDCST,
98
+	     nic->ioaddr + EP_COMMAND);
99
+
100
+	/* configure BNC */
101
+	if (connector == bnc) {
102
+		outw(START_TRANSCEIVER, nic->ioaddr + EP_COMMAND);
103
+		udelay(1000);
104
+	}
105
+	/* configure UTP */
106
+	else if (connector == utp) {
107
+		GO_WINDOW(nic->ioaddr,4);
108
+		outw(ENABLE_UTP, nic->ioaddr + EP_W4_MEDIA_TYPE);
109
+		sleep(2);	/* Give time for media to negotiate */
110
+		GO_WINDOW(nic->ioaddr,1);
111
+	}
112
+
113
+	/* start transceiver and receiver */
114
+	outw(RX_ENABLE, nic->ioaddr + EP_COMMAND);
115
+	outw(TX_ENABLE, nic->ioaddr + EP_COMMAND);
116
+
117
+	/* set early threshold for minimal packet length */
118
+	outw(SET_RX_EARLY_THRESH | ETH_ZLEN, nic->ioaddr + EP_COMMAND);
119
+	outw(SET_TX_START_THRESH | 16, nic->ioaddr + EP_COMMAND);
120
+}
121
+
122
+static void t509_reset ( struct nic *nic ) {
123
+	t509_disable ( nic );
124
+	t509_enable ( nic );
125
+}    
126
+
127
+/**************************************************************************
128
+ETH_TRANSMIT - Transmit a frame
129
+***************************************************************************/
130
+static char padmap[] = {
131
+	0, 3, 2, 1};
132
+
133
+static void t509_transmit(
134
+struct nic *nic,
135
+const char *d,			/* Destination */
136
+unsigned int t,			/* Type */
137
+unsigned int s,			/* size */
138
+const char *p)			/* Packet */
139
+{
140
+	register unsigned int len;
141
+	int pad;
142
+	int status;
143
+
144
+#ifdef	EDEBUG
145
+	printf("{l=%d,t=%hX}",s+ETH_HLEN,t);
146
+#endif
147
+
148
+	/* swap bytes of type */
149
+	t= htons(t);
150
+
151
+	len=s+ETH_HLEN; /* actual length of packet */
152
+	pad = padmap[len & 3];
153
+
154
+	/*
155
+	* The 3c509 automatically pads short packets to minimum ethernet length,
156
+	* but we drop packets that are too large. Perhaps we should truncate
157
+	* them instead?
158
+	*/
159
+	if (len + pad > ETH_FRAME_LEN) {
160
+		return;
161
+	}
162
+
163
+	/* drop acknowledgements */
164
+	while ((status=inb(nic->ioaddr + EP_W1_TX_STATUS)) & TXS_COMPLETE ) {
165
+		if (status & (TXS_UNDERRUN|TXS_MAX_COLLISION|TXS_STATUS_OVERFLOW)) {
166
+			outw(TX_RESET, nic->ioaddr + EP_COMMAND);
167
+			outw(TX_ENABLE, nic->ioaddr + EP_COMMAND);
168
+		}
169
+		outb(0x0, nic->ioaddr + EP_W1_TX_STATUS);
170
+	}
171
+
172
+	while (inw(nic->ioaddr + EP_W1_FREE_TX) < (unsigned short)len + pad + 4)
173
+		; /* no room in FIFO */
174
+
175
+	outw(len, nic->ioaddr + EP_W1_TX_PIO_WR_1);
176
+	outw(0x0, nic->ioaddr + EP_W1_TX_PIO_WR_1);	/* Second dword meaningless */
177
+
178
+	/* write packet */
179
+	outsw(nic->ioaddr + EP_W1_TX_PIO_WR_1, d, ETH_ALEN/2);
180
+	outsw(nic->ioaddr + EP_W1_TX_PIO_WR_1, nic->node_addr, ETH_ALEN/2);
181
+	outw(t, nic->ioaddr + EP_W1_TX_PIO_WR_1);
182
+	outsw(nic->ioaddr + EP_W1_TX_PIO_WR_1, p, s / 2);
183
+	if (s & 1)
184
+		outb(*(p+s - 1), nic->ioaddr + EP_W1_TX_PIO_WR_1);
185
+
186
+	while (pad--)
187
+		outb(0, nic->ioaddr + EP_W1_TX_PIO_WR_1);	/* Padding */
188
+
189
+	/* wait for Tx complete */
190
+	while((inw(nic->ioaddr + EP_STATUS) & S_COMMAND_IN_PROGRESS) != 0)
191
+		;
192
+}
193
+
194
+/**************************************************************************
195
+ETH_POLL - Wait for a frame
196
+***************************************************************************/
197
+static int t509_poll(struct nic *nic, int retrieve)
198
+{
199
+	/* common variables */
200
+	/* variables for 3C509 */
201
+	short status, cst;
202
+	register short rx_fifo;
203
+
204
+	cst=inw(nic->ioaddr + EP_STATUS);
205
+
206
+#ifdef	EDEBUG
207
+	if(cst & 0x1FFF)
208
+		printf("-%hX-",cst);
209
+#endif
210
+
211
+	if( (cst & S_RX_COMPLETE)==0 ) {
212
+		/* acknowledge  everything */
213
+		outw(ACK_INTR| (cst & S_5_INTS), nic->ioaddr + EP_COMMAND);
214
+		outw(C_INTR_LATCH, nic->ioaddr + EP_COMMAND);
215
+
216
+		return 0;
217
+	}
218
+
219
+	status = inw(nic->ioaddr + EP_W1_RX_STATUS);
220
+#ifdef	EDEBUG
221
+	printf("*%hX*",status);
222
+#endif
223
+
224
+	if (status & ERR_RX) {
225
+		outw(RX_DISCARD_TOP_PACK, nic->ioaddr + EP_COMMAND);
226
+		return 0;
227
+	}
228
+
229
+	rx_fifo = status & RX_BYTES_MASK;
230
+	if (rx_fifo==0)
231
+		return 0;
232
+
233
+	if ( ! retrieve ) return 1;
234
+
235
+		/* read packet */
236
+#ifdef	EDEBUG
237
+	printf("[l=%d",rx_fifo);
238
+#endif
239
+	insw(nic->ioaddr + EP_W1_RX_PIO_RD_1, nic->packet, rx_fifo / 2);
240
+	if(rx_fifo & 1)
241
+		nic->packet[rx_fifo-1]=inb(nic->ioaddr + EP_W1_RX_PIO_RD_1);
242
+	nic->packetlen=rx_fifo;
243
+
244
+	while(1) {
245
+		status = inw(nic->ioaddr + EP_W1_RX_STATUS);
246
+#ifdef	EDEBUG
247
+		printf("*%hX*",status);
248
+#endif
249
+		rx_fifo = status & RX_BYTES_MASK;
250
+		if(rx_fifo>0) {
251
+			insw(nic->ioaddr + EP_W1_RX_PIO_RD_1, nic->packet+nic->packetlen, rx_fifo / 2);
252
+			if(rx_fifo & 1)
253
+				nic->packet[nic->packetlen+rx_fifo-1]=inb(nic->ioaddr + EP_W1_RX_PIO_RD_1);
254
+			nic->packetlen+=rx_fifo;
255
+#ifdef	EDEBUG
256
+			printf("+%d",rx_fifo);
257
+#endif
258
+		}
259
+		if(( status & RX_INCOMPLETE )==0) {
260
+#ifdef	EDEBUG
261
+			printf("=%d",nic->packetlen);
262
+#endif
263
+			break;
264
+		}
265
+		udelay(1000);	/* if incomplete wait 1 ms */
266
+	}
267
+	/* acknowledge reception of packet */
268
+	outw(RX_DISCARD_TOP_PACK, nic->ioaddr + EP_COMMAND);
269
+	while (inw(nic->ioaddr + EP_STATUS) & S_COMMAND_IN_PROGRESS)
270
+		;
271
+#ifdef	EDEBUG
272
+{
273
+	unsigned short type = 0;	/* used by EDEBUG */
274
+	type = (nic->packet[12]<<8) | nic->packet[13];
275
+	if(nic->packet[0]+nic->packet[1]+nic->packet[2]+nic->packet[3]+nic->packet[4]+
276
+	    nic->packet[5] == 0xFF*ETH_ALEN)
277
+		printf(",t=%hX,b]",type);
278
+	else
279
+		printf(",t=%hX]",type);
280
+}
281
+#endif
282
+	return (1);
283
+}
284
+
285
+/**************************************************************************
286
+ETH_IRQ - interrupt handling
287
+***************************************************************************/
288
+static void t509_irq(struct nic *nic __unused, irq_action_t action __unused)
289
+{
290
+  switch ( action ) {
291
+  case DISABLE :
292
+    break;
293
+  case ENABLE :
294
+    break;
295
+  case FORCE :
296
+    break;
297
+  }
298
+}
299
+
300
+/*************************************************************************
301
+	3Com 509 - specific routines
302
+**************************************************************************/
303
+
304
+static int eeprom_rdy ( uint16_t ioaddr ) {
305
+	int i;
306
+
307
+	for (i = 0; is_eeprom_busy(ioaddr) && i < MAX_EEPROMBUSY; i++);
308
+	if (i >= MAX_EEPROMBUSY) {
309
+		/* printf("3c509: eeprom failed to come ready.\n"); */
310
+		/* memory in EPROM is tight */
311
+		/* printf("3c509: eeprom busy.\n"); */
312
+		return (0);
313
+	}
314
+	return (1);
315
+}
316
+
317
+/*
318
+ * get_e: gets a 16 bits word from the EEPROM.
319
+ */
320
+static int get_e ( uint16_t ioaddr, int offset ) {
321
+	GO_WINDOW(ioaddr,0);
322
+	if (!eeprom_rdy(ioaddr))
323
+		return (0xffff);
324
+	outw(EEPROM_CMD_RD | offset, ioaddr + EP_W0_EEPROM_COMMAND);
325
+	if (!eeprom_rdy(ioaddr))
326
+		return (0xffff);
327
+	return (inw(ioaddr + EP_W0_EEPROM_DATA));
328
+}
329
+
330
+struct nic_operations t509_operations = {
331
+	.connect	= dummy_connect,
332
+	.poll		= t509_poll,
333
+	.transmit	= t509_transmit,
334
+	.irq		= t509_irq,
335
+	.disable	= t509_disable,
336
+};
337
+
338
+/**************************************************************************
339
+ETH_PROBE - Look for an adapter
340
+***************************************************************************/
341
+int t5x9_probe ( struct nic *nic,
342
+		 uint16_t prod_id_check, uint16_t prod_id_mask ) {
343
+	uint16_t prod_id;
344
+	int i,j;
345
+	unsigned short *p;
346
+	
347
+	/* Check product ID */
348
+	prod_id = get_e ( nic->ioaddr, EEPROM_PROD_ID );
349
+	if ( ( prod_id & prod_id_mask ) != prod_id_check ) {
350
+		printf ( "EEPROM Product ID is incorrect (%hx & %hx != %hx)\n",
351
+			 prod_id, prod_id_mask, prod_id_check );
352
+		return 0;
353
+	}
354
+
355
+	/* test for presence of connectors */
356
+	GO_WINDOW(nic->ioaddr,0);
357
+	i = inw(nic->ioaddr + EP_W0_CONFIG_CTRL);
358
+	j = (inw(nic->ioaddr + EP_W0_ADDRESS_CFG) >> 14) & 0x3;
359
+
360
+	switch(j) {
361
+	case 0:
362
+		if (i & IS_UTP) {
363
+			printf("10baseT\n");
364
+			connector = utp;
365
+		} else {
366
+			printf("10baseT not present\n");
367
+			return 0;
368
+		}
369
+		break;
370
+	case 1:
371
+		if (i & IS_AUI) {
372
+			printf("10base5\n");
373
+		} else {
374
+			printf("10base5 not present\n");
375
+			return 0;
376
+		}
377
+		break;
378
+	case 3:
379
+		if (i & IS_BNC) {
380
+			printf("10base2\n");
381
+			connector = bnc;
382
+		} else {
383
+			printf("10base2 not present\n");
384
+			return 0;
385
+		}
386
+		break;
387
+	default:
388
+		printf("unknown connector\n");
389
+		return 0;
390
+	}
391
+
392
+	/*
393
+	* Read the station address from the eeprom
394
+	*/
395
+	p = (unsigned short *) nic->node_addr;
396
+	for (i = 0; i < ETH_ALEN / 2; i++) {
397
+		p[i] = htons(get_e(nic->ioaddr,i));
398
+		GO_WINDOW(nic->ioaddr,2);
399
+		outw(ntohs(p[i]), nic->ioaddr + EP_W2_ADDR_0 + (i * 2));
400
+	}
401
+	printf("Ethernet address: %!\n", nic->node_addr);
402
+	t509_reset(nic);
403
+
404
+	nic->nic_op = &t509_operations;
405
+	return 1;
406
+
407
+}
408
+
409
+/*
410
+ * Local variables:
411
+ *  c-basic-offset: 8
412
+ * End:
413
+ */

Notiek ielāde…
Atcelt
Saglabāt