17.6.36
by Colin Watson
* New upstream snapshot. |
1 |
/*
|
2 |
* 3c595.c -- 3COM 3C595 Fast Etherlink III PCI driver for etherboot
|
|
3 |
*
|
|
4 |
* Copyright (C) 2000 Shusuke Nisiyama <shu@athena.qe.eng.hokudai.ac.jp>
|
|
5 |
* All rights reserved.
|
|
6 |
* Mar. 14, 2000
|
|
7 |
*
|
|
8 |
* This software may be used, modified, copied, distributed, and sold, in
|
|
9 |
* both source and binary form provided that the above copyright and these
|
|
10 |
* terms are retained. Under no circumstances are the authors responsible for
|
|
11 |
* the proper functioning of this software, nor do the authors assume any
|
|
12 |
* responsibility for damages incurred with its use.
|
|
13 |
*
|
|
14 |
* This code is based on Martin Renters' etherboot-4.4.3 3c509.c and
|
|
15 |
* Herb Peyerl's FreeBSD 3.4-RELEASE if_vx.c driver.
|
|
16 |
*
|
|
17 |
* Copyright (C) 1993-1994, David Greenman, Martin Renters.
|
|
18 |
* Copyright (C) 1993-1995, Andres Vega Garcia.
|
|
19 |
* Copyright (C) 1995, Serge Babkin.
|
|
20 |
*
|
|
21 |
* Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca>
|
|
22 |
*
|
|
23 |
* timlegge 08-24-2003 Add Multicast Support
|
|
24 |
*/
|
|
25 |
||
26 |
FILE_LICENCE ( BSD2 ); |
|
27 |
||
28 |
/* #define EDEBUG */
|
|
29 |
||
30 |
#include "etherboot.h" |
|
31 |
#include "nic.h" |
|
32 |
#include <gpxe/pci.h> |
|
33 |
#include <gpxe/ethernet.h> |
|
34 |
#include "3c595.h" |
|
35 |
||
36 |
static struct nic_operations t595_operations; |
|
37 |
||
38 |
static unsigned short eth_nic_base; |
|
39 |
static unsigned short vx_connector, vx_connectors; |
|
40 |
||
41 |
static struct connector_entry { |
|
42 |
int bit; |
|
43 |
char *name; |
|
44 |
} conn_tab[VX_CONNECTORS] = { |
|
45 |
#define CONNECTOR_UTP 0
|
|
46 |
{ 0x08, "utp"}, |
|
47 |
#define CONNECTOR_AUI 1
|
|
48 |
{ 0x20, "aui"}, |
|
49 |
/* dummy */
|
|
50 |
{ 0, "???"}, |
|
51 |
#define CONNECTOR_BNC 3
|
|
52 |
{ 0x10, "bnc"}, |
|
53 |
#define CONNECTOR_TX 4
|
|
54 |
{ 0x02, "tx"}, |
|
55 |
#define CONNECTOR_FX 5
|
|
56 |
{ 0x04, "fx"}, |
|
57 |
#define CONNECTOR_MII 6
|
|
58 |
{ 0x40, "mii"}, |
|
59 |
{ 0, "???"} |
|
60 |
};
|
|
61 |
||
62 |
static void vxgetlink(void); |
|
63 |
static void vxsetlink(void); |
|
64 |
||
65 |
/**************************************************************************
|
|
66 |
ETH_RESET - Reset adapter
|
|
67 |
***************************************************************************/
|
|
68 |
static void t595_reset(struct nic *nic) |
|
69 |
{
|
|
70 |
int i; |
|
71 |
||
72 |
/***********************************************************
|
|
73 |
Reset 3Com 595 card
|
|
74 |
*************************************************************/
|
|
75 |
||
76 |
/* stop card */
|
|
77 |
outw(RX_DISABLE, BASE + VX_COMMAND); |
|
78 |
outw(RX_DISCARD_TOP_PACK, BASE + VX_COMMAND); |
|
79 |
VX_BUSY_WAIT; |
|
80 |
outw(TX_DISABLE, BASE + VX_COMMAND); |
|
81 |
outw(STOP_TRANSCEIVER, BASE + VX_COMMAND); |
|
82 |
udelay(8000); |
|
83 |
outw(RX_RESET, BASE + VX_COMMAND); |
|
84 |
VX_BUSY_WAIT; |
|
85 |
outw(TX_RESET, BASE + VX_COMMAND); |
|
86 |
VX_BUSY_WAIT; |
|
87 |
outw(C_INTR_LATCH, BASE + VX_COMMAND); |
|
88 |
outw(SET_RD_0_MASK, BASE + VX_COMMAND); |
|
89 |
outw(SET_INTR_MASK, BASE + VX_COMMAND); |
|
90 |
outw(SET_RX_FILTER, BASE + VX_COMMAND); |
|
91 |
||
92 |
/*
|
|
93 |
* initialize card
|
|
94 |
*/
|
|
95 |
VX_BUSY_WAIT; |
|
96 |
||
97 |
GO_WINDOW(0); |
|
98 |
||
99 |
/* Disable the card */
|
|
100 |
/* outw(0, BASE + VX_W0_CONFIG_CTRL); */
|
|
101 |
||
102 |
/* Configure IRQ to none */
|
|
103 |
/* outw(SET_IRQ(0), BASE + VX_W0_RESOURCE_CFG); */
|
|
104 |
||
105 |
/* Enable the card */
|
|
106 |
/* outw(ENABLE_DRQ_IRQ, BASE + VX_W0_CONFIG_CTRL); */
|
|
107 |
||
108 |
GO_WINDOW(2); |
|
109 |
||
110 |
/* Reload the ether_addr. */
|
|
111 |
for (i = 0; i < ETH_ALEN; i++) |
|
112 |
outb(nic->node_addr[i], BASE + VX_W2_ADDR_0 + i); |
|
113 |
||
114 |
outw(RX_RESET, BASE + VX_COMMAND); |
|
115 |
VX_BUSY_WAIT; |
|
116 |
outw(TX_RESET, BASE + VX_COMMAND); |
|
117 |
VX_BUSY_WAIT; |
|
118 |
||
119 |
/* Window 1 is operating window */
|
|
120 |
GO_WINDOW(1); |
|
121 |
for (i = 0; i < 31; i++) |
|
122 |
inb(BASE + VX_W1_TX_STATUS); |
|
123 |
||
124 |
outw(SET_RD_0_MASK | S_CARD_FAILURE | S_RX_COMPLETE | |
|
125 |
S_TX_COMPLETE | S_TX_AVAIL, BASE + VX_COMMAND); |
|
126 |
outw(SET_INTR_MASK | S_CARD_FAILURE | S_RX_COMPLETE | |
|
127 |
S_TX_COMPLETE | S_TX_AVAIL, BASE + VX_COMMAND); |
|
128 |
||
129 |
/*
|
|
130 |
* Attempt to get rid of any stray interrupts that occured during
|
|
131 |
* configuration. On the i386 this isn't possible because one may
|
|
132 |
* already be queued. However, a single stray interrupt is
|
|
133 |
* unimportant.
|
|
134 |
*/
|
|
135 |
||
136 |
outw(ACK_INTR | 0xff, BASE + VX_COMMAND); |
|
137 |
||
138 |
outw(SET_RX_FILTER | FIL_INDIVIDUAL | |
|
139 |
FIL_BRDCST|FIL_MULTICAST, BASE + VX_COMMAND); |
|
140 |
||
141 |
vxsetlink(); |
|
142 |
/*{
|
|
143 |
int i,j;
|
|
144 |
i = CONNECTOR_TX;
|
|
145 |
GO_WINDOW(3);
|
|
146 |
j = inl(BASE + VX_W3_INTERNAL_CFG) & ~INTERNAL_CONNECTOR_MASK;
|
|
147 |
outl(BASE + VX_W3_INTERNAL_CFG, j | (i <<INTERNAL_CONNECTOR_BITS));
|
|
148 |
GO_WINDOW(4);
|
|
149 |
outw(LINKBEAT_ENABLE, BASE + VX_W4_MEDIA_TYPE);
|
|
150 |
GO_WINDOW(1);
|
|
151 |
}*/
|
|
152 |
||
153 |
/* start tranciever and receiver */
|
|
154 |
outw(RX_ENABLE, BASE + VX_COMMAND); |
|
155 |
outw(TX_ENABLE, BASE + VX_COMMAND); |
|
156 |
||
157 |
}
|
|
158 |
||
159 |
/**************************************************************************
|
|
160 |
ETH_TRANSMIT - Transmit a frame
|
|
161 |
***************************************************************************/
|
|
162 |
static char padmap[] = { |
|
163 |
0, 3, 2, 1}; |
|
164 |
||
165 |
static void t595_transmit( |
|
166 |
struct nic *nic, |
|
167 |
const char *d, /* Destination */ |
|
168 |
unsigned int t, /* Type */ |
|
169 |
unsigned int s, /* size */ |
|
170 |
const char *p) /* Packet */ |
|
171 |
{
|
|
172 |
register int len; |
|
173 |
int pad; |
|
174 |
int status; |
|
175 |
||
176 |
#ifdef EDEBUG
|
|
177 |
printf("{l=%d,t=%hX}",s+ETH_HLEN,t); |
|
178 |
#endif
|
|
179 |
||
180 |
/* swap bytes of type */
|
|
181 |
t= htons(t); |
|
182 |
||
183 |
len=s+ETH_HLEN; /* actual length of packet */ |
|
184 |
pad = padmap[len & 3]; |
|
185 |
||
186 |
/*
|
|
187 |
* The 3c595 automatically pads short packets to minimum ethernet length,
|
|
188 |
* but we drop packets that are too large. Perhaps we should truncate
|
|
189 |
* them instead?
|
|
190 |
*/
|
|
191 |
if (len + pad > ETH_FRAME_LEN) { |
|
192 |
return; |
|
193 |
}
|
|
194 |
||
195 |
/* drop acknowledgements */
|
|
196 |
while(( status=inb(BASE + VX_W1_TX_STATUS) )& TXS_COMPLETE ) { |
|
197 |
if(status & (TXS_UNDERRUN|TXS_MAX_COLLISION|TXS_STATUS_OVERFLOW)) { |
|
198 |
outw(TX_RESET, BASE + VX_COMMAND); |
|
199 |
outw(TX_ENABLE, BASE + VX_COMMAND); |
|
200 |
}
|
|
201 |
||
202 |
outb(0x0, BASE + VX_W1_TX_STATUS); |
|
203 |
}
|
|
204 |
||
205 |
while (inw(BASE + VX_W1_FREE_TX) < len + pad + 4) { |
|
206 |
/* no room in FIFO */
|
|
207 |
}
|
|
208 |
||
209 |
outw(len, BASE + VX_W1_TX_PIO_WR_1); |
|
210 |
outw(0x0, BASE + VX_W1_TX_PIO_WR_1); /* Second dword meaningless */ |
|
211 |
||
212 |
/* write packet */
|
|
213 |
outsw(BASE + VX_W1_TX_PIO_WR_1, d, ETH_ALEN/2); |
|
214 |
outsw(BASE + VX_W1_TX_PIO_WR_1, nic->node_addr, ETH_ALEN/2); |
|
215 |
outw(t, BASE + VX_W1_TX_PIO_WR_1); |
|
216 |
outsw(BASE + VX_W1_TX_PIO_WR_1, p, s / 2); |
|
217 |
if (s & 1) |
|
218 |
outb(*(p+s - 1), BASE + VX_W1_TX_PIO_WR_1); |
|
219 |
||
220 |
while (pad--) |
|
221 |
outb(0, BASE + VX_W1_TX_PIO_WR_1); /* Padding */ |
|
222 |
||
223 |
/* wait for Tx complete */
|
|
224 |
while((inw(BASE + VX_STATUS) & S_COMMAND_IN_PROGRESS) != 0) |
|
225 |
;
|
|
226 |
}
|
|
227 |
||
228 |
/**************************************************************************
|
|
229 |
ETH_POLL - Wait for a frame
|
|
230 |
***************************************************************************/
|
|
231 |
static int t595_poll(struct nic *nic, int retrieve) |
|
232 |
{
|
|
233 |
/* common variables */
|
|
234 |
/* variables for 3C595 */
|
|
235 |
short status, cst; |
|
236 |
register short rx_fifo; |
|
237 |
||
238 |
cst=inw(BASE + VX_STATUS); |
|
239 |
||
240 |
#ifdef EDEBUG
|
|
241 |
if(cst & 0x1FFF) |
|
242 |
printf("-%hX-",cst); |
|
243 |
#endif
|
|
244 |
||
245 |
if( (cst & S_RX_COMPLETE)==0 ) { |
|
246 |
/* acknowledge everything */
|
|
247 |
outw(ACK_INTR | cst, BASE + VX_COMMAND); |
|
248 |
outw(C_INTR_LATCH, BASE + VX_COMMAND); |
|
249 |
||
250 |
return 0; |
|
251 |
}
|
|
252 |
||
253 |
status = inw(BASE + VX_W1_RX_STATUS); |
|
254 |
#ifdef EDEBUG
|
|
255 |
printf("*%hX*",status); |
|
256 |
#endif
|
|
257 |
||
258 |
if (status & ERR_RX) { |
|
259 |
outw(RX_DISCARD_TOP_PACK, BASE + VX_COMMAND); |
|
260 |
return 0; |
|
261 |
}
|
|
262 |
||
263 |
rx_fifo = status & RX_BYTES_MASK; |
|
264 |
if (rx_fifo==0) |
|
265 |
return 0; |
|
266 |
||
267 |
if ( ! retrieve ) return 1; |
|
268 |
||
269 |
/* read packet */
|
|
270 |
#ifdef EDEBUG
|
|
271 |
printf("[l=%d",rx_fifo); |
|
272 |
#endif
|
|
273 |
insw(BASE + VX_W1_RX_PIO_RD_1, nic->packet, rx_fifo / 2); |
|
274 |
if(rx_fifo & 1) |
|
275 |
nic->packet[rx_fifo-1]=inb(BASE + VX_W1_RX_PIO_RD_1); |
|
276 |
nic->packetlen=rx_fifo; |
|
277 |
||
278 |
while(1) { |
|
279 |
status = inw(BASE + VX_W1_RX_STATUS); |
|
280 |
#ifdef EDEBUG
|
|
281 |
printf("*%hX*",status); |
|
282 |
#endif
|
|
283 |
rx_fifo = status & RX_BYTES_MASK; |
|
284 |
||
285 |
if(rx_fifo>0) { |
|
286 |
insw(BASE + VX_W1_RX_PIO_RD_1, nic->packet+nic->packetlen, rx_fifo / 2); |
|
287 |
if(rx_fifo & 1) |
|
288 |
nic->packet[nic->packetlen+rx_fifo-1]=inb(BASE + VX_W1_RX_PIO_RD_1); |
|
289 |
nic->packetlen+=rx_fifo; |
|
290 |
#ifdef EDEBUG
|
|
291 |
printf("+%d",rx_fifo); |
|
292 |
#endif
|
|
293 |
}
|
|
294 |
if(( status & RX_INCOMPLETE )==0) { |
|
295 |
#ifdef EDEBUG
|
|
296 |
printf("=%d",nic->packetlen); |
|
297 |
#endif
|
|
298 |
break; |
|
299 |
}
|
|
300 |
udelay(1000); |
|
301 |
}
|
|
302 |
||
303 |
/* acknowledge reception of packet */
|
|
304 |
outw(RX_DISCARD_TOP_PACK, BASE + VX_COMMAND); |
|
305 |
while (inw(BASE + VX_STATUS) & S_COMMAND_IN_PROGRESS); |
|
306 |
#ifdef EDEBUG
|
|
307 |
{
|
|
308 |
unsigned short type = 0; /* used by EDEBUG */ |
|
309 |
type = (nic->packet[12]<<8) | nic->packet[13]; |
|
310 |
if(nic->packet[0]+nic->packet[1]+nic->packet[2]+nic->packet[3]+nic->packet[4]+ |
|
311 |
nic->packet[5] == 0xFF*ETH_ALEN) |
|
312 |
printf(",t=%hX,b]",type); |
|
313 |
else
|
|
314 |
printf(",t=%hX]",type); |
|
315 |
}
|
|
316 |
#endif
|
|
317 |
return 1; |
|
318 |
}
|
|
319 |
||
320 |
||
321 |
/*************************************************************************
|
|
322 |
3Com 595 - specific routines
|
|
323 |
**************************************************************************/
|
|
324 |
||
325 |
static int |
|
326 |
eeprom_rdy() |
|
327 |
{
|
|
328 |
int i; |
|
329 |
||
330 |
for (i = 0; is_eeprom_busy(BASE) && i < MAX_EEPROMBUSY; i++) |
|
331 |
udelay(1000); |
|
332 |
if (i >= MAX_EEPROMBUSY) { |
|
333 |
/* printf("3c595: eeprom failed to come ready.\n"); */
|
|
334 |
printf("3c595: eeprom is busy.\n"); /* memory in EPROM is tight */ |
|
335 |
return (0); |
|
336 |
}
|
|
337 |
return (1); |
|
338 |
}
|
|
339 |
||
340 |
/*
|
|
341 |
* get_e: gets a 16 bits word from the EEPROM. we must have set the window
|
|
342 |
* before
|
|
343 |
*/
|
|
344 |
static int |
|
345 |
get_e(offset) |
|
346 |
int offset; |
|
347 |
{
|
|
348 |
if (!eeprom_rdy()) |
|
349 |
return (0xffff); |
|
350 |
outw(EEPROM_CMD_RD | offset, BASE + VX_W0_EEPROM_COMMAND); |
|
351 |
if (!eeprom_rdy()) |
|
352 |
return (0xffff); |
|
353 |
return (inw(BASE + VX_W0_EEPROM_DATA)); |
|
354 |
}
|
|
355 |
||
356 |
static void |
|
357 |
vxgetlink(void) |
|
358 |
{
|
|
359 |
int n, k; |
|
360 |
||
361 |
GO_WINDOW(3); |
|
362 |
vx_connectors = inw(BASE + VX_W3_RESET_OPT) & 0x7f; |
|
363 |
for (n = 0, k = 0; k < VX_CONNECTORS; k++) { |
|
364 |
if (vx_connectors & conn_tab[k].bit) { |
|
365 |
if (n > 0) { |
|
366 |
printf("/"); |
|
367 |
}
|
|
368 |
printf("%s", conn_tab[k].name ); |
|
369 |
n++; |
|
370 |
}
|
|
371 |
}
|
|
372 |
if (vx_connectors == 0) { |
|
373 |
printf("no connectors!"); |
|
374 |
return; |
|
375 |
}
|
|
376 |
GO_WINDOW(3); |
|
377 |
vx_connector = (inl(BASE + VX_W3_INTERNAL_CFG) |
|
378 |
& INTERNAL_CONNECTOR_MASK) |
|
379 |
>> INTERNAL_CONNECTOR_BITS; |
|
380 |
if (vx_connector & 0x10) { |
|
381 |
vx_connector &= 0x0f; |
|
382 |
printf("[*%s*]", conn_tab[vx_connector].name); |
|
383 |
printf(": disable 'auto select' with DOS util!"); |
|
384 |
} else { |
|
385 |
printf("[*%s*]", conn_tab[vx_connector].name); |
|
386 |
}
|
|
387 |
}
|
|
388 |
||
389 |
static void |
|
390 |
vxsetlink(void) |
|
391 |
{
|
|
392 |
int i, j; |
|
393 |
char *reason, *warning; |
|
394 |
static char prev_conn = -1; |
|
395 |
||
396 |
if (prev_conn == -1) { |
|
397 |
prev_conn = vx_connector; |
|
398 |
}
|
|
399 |
||
400 |
i = vx_connector; /* default in EEPROM */ |
|
401 |
reason = "default"; |
|
402 |
warning = 0; |
|
403 |
||
404 |
if ((vx_connectors & conn_tab[vx_connector].bit) == 0) { |
|
405 |
warning = "strange connector type in EEPROM."; |
|
406 |
reason = "forced"; |
|
407 |
i = CONNECTOR_UTP; |
|
408 |
}
|
|
409 |
||
410 |
if (warning != 0) { |
|
411 |
printf("warning: %s\n", warning); |
|
412 |
}
|
|
413 |
printf("selected %s. (%s)\n", conn_tab[i].name, reason); |
|
414 |
||
415 |
/* Set the selected connector. */
|
|
416 |
GO_WINDOW(3); |
|
417 |
j = inl(BASE + VX_W3_INTERNAL_CFG) & ~INTERNAL_CONNECTOR_MASK; |
|
418 |
outl(j | (i <<INTERNAL_CONNECTOR_BITS), BASE + VX_W3_INTERNAL_CFG); |
|
419 |
||
420 |
/* First, disable all. */
|
|
421 |
outw(STOP_TRANSCEIVER, BASE + VX_COMMAND); |
|
422 |
udelay(8000); |
|
423 |
GO_WINDOW(4); |
|
424 |
outw(0, BASE + VX_W4_MEDIA_TYPE); |
|
425 |
||
426 |
/* Second, enable the selected one. */
|
|
427 |
switch(i) { |
|
428 |
case CONNECTOR_UTP: |
|
429 |
GO_WINDOW(4); |
|
430 |
outw(ENABLE_UTP, BASE + VX_W4_MEDIA_TYPE); |
|
431 |
break; |
|
432 |
case CONNECTOR_BNC: |
|
433 |
outw(START_TRANSCEIVER,BASE + VX_COMMAND); |
|
434 |
udelay(8000); |
|
435 |
break; |
|
436 |
case CONNECTOR_TX: |
|
437 |
case CONNECTOR_FX: |
|
438 |
GO_WINDOW(4); |
|
439 |
outw(LINKBEAT_ENABLE, BASE + VX_W4_MEDIA_TYPE); |
|
440 |
break; |
|
441 |
default: /* AUI and MII fall here */ |
|
442 |
break; |
|
443 |
}
|
|
444 |
GO_WINDOW(1); |
|
445 |
}
|
|
446 |
||
447 |
static void t595_disable ( struct nic *nic ) { |
|
448 |
||
449 |
t595_reset(nic); |
|
450 |
||
451 |
outw(STOP_TRANSCEIVER, BASE + VX_COMMAND); |
|
452 |
udelay(8000); |
|
453 |
GO_WINDOW(4); |
|
454 |
outw(0, BASE + VX_W4_MEDIA_TYPE); |
|
455 |
GO_WINDOW(1); |
|
456 |
}
|
|
457 |
||
458 |
static void t595_irq(struct nic *nic __unused, irq_action_t action __unused) |
|
459 |
{
|
|
460 |
switch ( action ) { |
|
461 |
case DISABLE : |
|
462 |
break; |
|
463 |
case ENABLE : |
|
464 |
break; |
|
465 |
case FORCE : |
|
466 |
break; |
|
467 |
}
|
|
468 |
}
|
|
469 |
||
470 |
/**************************************************************************
|
|
471 |
ETH_PROBE - Look for an adapter
|
|
472 |
***************************************************************************/
|
|
473 |
static int t595_probe ( struct nic *nic, struct pci_device *pci ) { |
|
474 |
||
475 |
int i; |
|
476 |
unsigned short *p; |
|
477 |
||
478 |
if (pci->ioaddr == 0) |
|
479 |
return 0; |
|
480 |
eth_nic_base = pci->ioaddr; |
|
481 |
||
482 |
nic->irqno = 0; |
|
483 |
nic->ioaddr = pci->ioaddr; |
|
484 |
||
485 |
GO_WINDOW(0); |
|
486 |
outw(GLOBAL_RESET, BASE + VX_COMMAND); |
|
487 |
VX_BUSY_WAIT; |
|
488 |
||
489 |
vxgetlink(); |
|
490 |
||
491 |
/*
|
|
492 |
printf("\nEEPROM:");
|
|
493 |
for (i = 0; i < (EEPROMSIZE/2); i++) {
|
|
494 |
printf("%hX:", get_e(i));
|
|
495 |
}
|
|
496 |
printf("\n");
|
|
497 |
*/
|
|
498 |
/*
|
|
499 |
* Read the station address from the eeprom
|
|
500 |
*/
|
|
501 |
p = (unsigned short *) nic->node_addr; |
|
502 |
for (i = 0; i < 3; i++) { |
|
503 |
GO_WINDOW(0); |
|
504 |
p[i] = htons(get_e(EEPROM_OEM_ADDR_0 + i)); |
|
505 |
GO_WINDOW(2); |
|
506 |
outw(ntohs(p[i]), BASE + VX_W2_ADDR_0 + (i * 2)); |
|
507 |
}
|
|
508 |
||
509 |
DBG ( "Ethernet address: %s\n", eth_ntoa (nic->node_addr) ); |
|
510 |
||
511 |
t595_reset(nic); |
|
512 |
nic->nic_op = &t595_operations; |
|
513 |
return 1; |
|
514 |
||
515 |
}
|
|
516 |
||
517 |
static struct nic_operations t595_operations = { |
|
518 |
.connect = dummy_connect, |
|
519 |
.poll = t595_poll, |
|
520 |
.transmit = t595_transmit, |
|
521 |
.irq = t595_irq, |
|
522 |
||
523 |
};
|
|
524 |
||
525 |
static struct pci_device_id t595_nics[] = { |
|
526 |
PCI_ROM(0x10b7, 0x5900, "3c590", "3Com590", 0), /* Vortex 10Mbps */ |
|
527 |
PCI_ROM(0x10b7, 0x5950, "3c595", "3Com595", 0), /* Vortex 100baseTx */ |
|
528 |
PCI_ROM(0x10b7, 0x5951, "3c595-1", "3Com595", 0), /* Vortex 100baseT4 */ |
|
529 |
PCI_ROM(0x10b7, 0x5952, "3c595-2", "3Com595", 0), /* Vortex 100base-MII */ |
|
530 |
PCI_ROM(0x10b7, 0x9000, "3c900-tpo", "3Com900-TPO", 0), /* 10 Base TPO */ |
|
531 |
PCI_ROM(0x10b7, 0x9001, "3c900-t4", "3Com900-Combo", 0), /* 10/100 T4 */ |
|
532 |
PCI_ROM(0x10b7, 0x9004, "3c900b-tpo", "3Com900B-TPO", 0), /* 10 Base TPO */ |
|
533 |
PCI_ROM(0x10b7, 0x9005, "3c900b-combo", "3Com900B-Combo", 0), /* 10 Base Combo */ |
|
534 |
PCI_ROM(0x10b7, 0x9006, "3c900b-tpb2", "3Com900B-2/T", 0), /* 10 Base TP and Base2 */ |
|
535 |
PCI_ROM(0x10b7, 0x900a, "3c900b-fl", "3Com900B-FL", 0), /* 10 Base F */ |
|
536 |
PCI_ROM(0x10b7, 0x9800, "3c980-cyclone-1", "3Com980-Cyclone", 0), /* Cyclone */ |
|
537 |
PCI_ROM(0x10b7, 0x9805, "3c9805-1", "3Com9805", 0), /* Dual Port Server Cyclone */ |
|
538 |
PCI_ROM(0x10b7, 0x7646, "3csoho100-tx-1", "3CSOHO100-TX", 0), /* Hurricane */ |
|
539 |
PCI_ROM(0x10b7, 0x4500, "3c450-1", "3Com450 HomePNA Tornado", 0), |
|
540 |
};
|
|
541 |
||
542 |
PCI_DRIVER ( t595_driver, t595_nics, PCI_NO_CLASS ); |
|
543 |
||
544 |
DRIVER ( "3C595", nic_driver, pci_driver, t595_driver, |
|
545 |
t595_probe, t595_disable ); |
|
546 |
||
547 |
/*
|
|
548 |
* Local variables:
|
|
549 |
* c-basic-offset: 8
|
|
550 |
* c-indent-level: 8
|
|
551 |
* tab-width: 8
|
|
552 |
* End:
|
|
553 |
*/
|