~ubuntu-branches/ubuntu/trusty/grub2/trusty

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
 */