|
@@ -1,7 +1,66 @@
|
1
|
|
-/* natsemi.c - gPXE driver for the NatSemi DP8381x series.
|
|
1
|
+/* natsemi.c - gPXE driver for the NatSemi DP8381x series. */
|
|
2
|
+
|
|
3
|
+/*
|
|
4
|
+
|
2
|
5
|
|
|
6
|
+ natsemi.c: An Etherboot driver for the NatSemi DP8381x series.
|
|
7
|
+
|
|
8
|
+ Copyright (C) 2001 Entity Cyber, Inc.
|
|
9
|
+
|
|
10
|
+ This development of this Etherboot driver was funded by
|
|
11
|
+
|
|
12
|
+ Sicom Systems: http://www.sicompos.com/
|
|
13
|
+
|
|
14
|
+ Author: Marty Connor (mdc@thinguin.org)
|
|
15
|
+ Adapted from a Linux driver which was written by Donald Becker
|
|
16
|
+
|
|
17
|
+ This software may be used and distributed according to the terms
|
|
18
|
+ of the GNU Public License (GPL), incorporated herein by reference.
|
|
19
|
+
|
|
20
|
+ Original Copyright Notice:
|
|
21
|
+
|
|
22
|
+ Written/copyright 1999-2001 by Donald Becker.
|
|
23
|
+
|
|
24
|
+ This software may be used and distributed according to the terms of
|
|
25
|
+ the GNU General Public License (GPL), incorporated herein by reference.
|
|
26
|
+ Drivers based on or derived from this code fall under the GPL and must
|
|
27
|
+ retain the authorship, copyright and license notice. This file is not
|
|
28
|
+ a complete program and may only be used when the entire operating
|
|
29
|
+ system is licensed under the GPL. License for under other terms may be
|
|
30
|
+ available. Contact the original author for details.
|
|
31
|
+
|
|
32
|
+ The original author may be reached as becker@scyld.com, or at
|
|
33
|
+ Scyld Computing Corporation
|
|
34
|
+ 410 Severn Ave., Suite 210
|
|
35
|
+ Annapolis MD 21403
|
|
36
|
+
|
|
37
|
+ Support information and updates available at
|
|
38
|
+ http://www.scyld.com/network/netsemi.html
|
|
39
|
+
|
|
40
|
+ References:
|
|
41
|
+
|
|
42
|
+ http://www.scyld.com/expert/100mbps.html
|
|
43
|
+ http://www.scyld.com/expert/NWay.html
|
|
44
|
+ Datasheet is available from:
|
|
45
|
+ http://www.national.com/pf/DP/DP83815.html
|
|
46
|
+
|
|
47
|
+*/
|
|
48
|
+
|
|
49
|
+/* Revision History */
|
3
|
50
|
|
|
51
|
+/*
|
|
52
|
+ 02 JUL 2007 Udayan Kumar 1.2 ported the driver from etherboot to gPXE API
|
|
53
|
+ Added a circular buffer for transmit and receive.
|
|
54
|
+ transmit routine will not wait for transmission to finish
|
|
55
|
+ poll routine deals with it.
|
|
56
|
+
|
|
57
|
+ 13 Dec 2003 timlegge 1.1 Enabled Multicast Support
|
|
58
|
+ 29 May 2001 mdc 1.0
|
|
59
|
+ Initial Release. Tested with Netgear FA311 and FA312 boards
|
4
|
60
|
*/
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
5
|
64
|
|
6
|
65
|
#include <stdint.h>
|
7
|
66
|
#include <stdlib.h>
|
|
@@ -21,6 +80,10 @@
|
21
|
80
|
|
22
|
81
|
#define TX_RING_SIZE 4
|
23
|
82
|
#define NUM_RX_DESC 4
|
|
83
|
+#define RX_BUF_SIZE 1536
|
|
84
|
+#define OWN 0x80000000
|
|
85
|
+#define DSIZE 0x00000FFF
|
|
86
|
+#define CRC_SIZE 4
|
24
|
87
|
|
25
|
88
|
struct natsemi_tx {
|
26
|
89
|
uint32_t link;
|
|
@@ -46,26 +109,13 @@ struct natsemi_nic {
|
46
|
109
|
* give the same.*/
|
47
|
110
|
struct io_buffer *iobuf[NUM_RX_DESC];
|
48
|
111
|
/*netdev_tx_complete needs pointer to the iobuf of the data so as to free
|
49
|
|
- it form the memory.*/
|
|
112
|
+ it from the memory.*/
|
50
|
113
|
struct io_buffer *tx_iobuf[TX_RING_SIZE];
|
51
|
114
|
struct spi_bit_basher spibit;
|
52
|
115
|
struct spi_device eeprom;
|
53
|
116
|
struct nvo_block nvo;
|
54
|
117
|
};
|
55
|
118
|
|
56
|
|
-/* Tuning Parameters */
|
57
|
|
-#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */
|
58
|
|
-#define RX_FIFO_THRESH 4 /* Rx buffer level before first PCI xfer. */
|
59
|
|
-#define RX_DMA_BURST 4 /* Maximum PCI burst, '4' is 256 bytes */
|
60
|
|
-#define TX_DMA_BURST 4 /* Calculate as 16<<val. */
|
61
|
|
-#define TX_IPG 3 /* This is the only valid value */
|
62
|
|
-//#define RX_BUF_LEN_IDX 0 /* */
|
63
|
|
-#define RX_BUF_LEN 8192 /*buffer size should be multiple of 32 */
|
64
|
|
-#define RX_BUF_PAD 4
|
65
|
|
-#define RX_BUF_SIZE 1536
|
66
|
|
-#define OWN 0x80000000
|
67
|
|
-#define DSIZE 0x00000FFF
|
68
|
|
-#define CRC_SIZE 4
|
69
|
119
|
|
70
|
120
|
/* NATSEMI: Offsets to the device registers.
|
71
|
121
|
Unlike software-only systems, device drivers interact with complex hardware.
|
|
@@ -153,8 +203,6 @@ enum desc_status_bits {
|
153
|
203
|
|
154
|
204
|
|
155
|
205
|
/* EEPROM access , values are devices specific*/
|
156
|
|
-//#define EE_M1 0x80 /* Mode select bit 1 */
|
157
|
|
-//#define EE_M0 0x40 /* Mode select bit 0 */
|
158
|
206
|
#define EE_CS 0x08 /* EEPROM chip select */
|
159
|
207
|
#define EE_SK 0x04 /* EEPROM shift clock */
|
160
|
208
|
#define EE_DI 0x01 /* Data in */
|
|
@@ -208,7 +256,7 @@ static struct bit_basher_operations nat_basher_ops = {
|
208
|
256
|
* detect that the card is not supporting VPD.
|
209
|
257
|
*/
|
210
|
258
|
static struct nvo_fragment nat_nvo_fragments[] = {
|
211
|
|
- { 0x0f, 0x40 },
|
|
259
|
+ { 0x0c, 0x40 },
|
212
|
260
|
{ 0, 0 }
|
213
|
261
|
};
|
214
|
262
|
|
|
@@ -218,8 +266,6 @@ static struct nvo_fragment nat_nvo_fragments[] = {
|
218
|
266
|
* @v NAT NATSEMI NIC
|
219
|
267
|
*/
|
220
|
268
|
void nat_init_eeprom ( struct natsemi_nic *nat ) {
|
221
|
|
- int ee9356;
|
222
|
|
- int vpd;
|
223
|
269
|
|
224
|
270
|
// Initialise three-wire bus
|
225
|
271
|
nat->spibit.basher.op = &nat_basher_ops;
|
|
@@ -227,18 +273,12 @@ static struct nvo_fragment nat_nvo_fragments[] = {
|
227
|
273
|
nat->spibit.endianness = SPI_BIT_LITTLE_ENDIAN;
|
228
|
274
|
init_spi_bit_basher ( &nat->spibit );
|
229
|
275
|
|
230
|
|
- DBG ( "EEPROM is an AT93C46\n" );
|
|
276
|
+ /*natsemi DP 83815 only supports at93c46 */
|
231
|
277
|
init_at93c46 ( &nat->eeprom, 16 );
|
232
|
278
|
nat->eeprom.bus = &nat->spibit.bus;
|
233
|
279
|
|
234
|
|
- // Initialise space for non-volatile options, if available
|
235
|
|
- //vpd = ( inw ( rtl->ioaddr + Config1 ) & VPDEnable );
|
236
|
|
- //if ( vpd ) {
|
237
|
|
- // DBG ( "EEPROM in use for VPD; cannot use for options\n" );
|
238
|
|
- //} else {
|
239
|
280
|
nat->nvo.nvs = &nat->eeprom.nvs;
|
240
|
281
|
nat->nvo.fragments = nat_nvo_fragments;
|
241
|
|
-// }
|
242
|
282
|
}
|
243
|
283
|
|
244
|
284
|
/**
|
|
@@ -280,7 +320,6 @@ static void nat_reset ( struct natsemi_nic *nat ) {
|
280
|
320
|
*/
|
281
|
321
|
static int nat_open ( struct net_device *netdev ) {
|
282
|
322
|
struct natsemi_nic *nat = netdev->priv;
|
283
|
|
- //struct io_buffer *iobuf;
|
284
|
323
|
int i;
|
285
|
324
|
uint32_t tx_config,rx_config;
|
286
|
325
|
|
|
@@ -296,13 +335,10 @@ static int nat_open ( struct net_device *netdev ) {
|
296
|
335
|
|
297
|
336
|
|
298
|
337
|
|
299
|
|
- /* Program the MAC address TODO enable this comment */
|
300
|
338
|
uint8_t last=0;
|
301
|
339
|
uint8_t last1=0;
|
302
|
340
|
for ( i = 0 ; i < ETH_ALEN ; i+=2 )
|
303
|
341
|
{
|
304
|
|
- // DBG("MAC address %d octet :%X %X\n",i,netdev->ll_addr[i],netdev->ll_addr[i+1]);
|
305
|
|
- // DBG("LAst = %d last1 = %d\n",last,last1);
|
306
|
342
|
outl(i,nat->ioaddr+RxFilterAddr);
|
307
|
343
|
last1=netdev->ll_addr[i]>>7;
|
308
|
344
|
netdev->ll_addr[i]=netdev->ll_addr[i]<<1|last;
|
|
@@ -310,9 +346,6 @@ static int nat_open ( struct net_device *netdev ) {
|
310
|
346
|
netdev->ll_addr[i+1]=(netdev->ll_addr[i+1]<<1)+last1;
|
311
|
347
|
|
312
|
348
|
outw ( netdev->ll_addr[i] + (netdev->ll_addr[i+1]<<8), nat->ioaddr +RxFilterData);
|
313
|
|
- //outw ( (fullbyte>>8)+(fullbyte<<8), nat->ioaddr +RxFilterData);
|
314
|
|
- // DBG("MAC address %d octet :%X %X\n",i,netdev->ll_addr[i],netdev->ll_addr[i+1]);
|
315
|
|
- // DBG("LAst = %d last1 = %d\n",last,last1);
|
316
|
349
|
}
|
317
|
350
|
|
318
|
351
|
|
|
@@ -417,7 +450,6 @@ static int nat_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
|
417
|
450
|
return -ENOBUFS;
|
418
|
451
|
}
|
419
|
452
|
|
420
|
|
- //DBG_HD(iobuf->data,iob_len(iobuf));
|
421
|
453
|
/* to be used in netdev_tx_complete*/
|
422
|
454
|
nat->tx_iobuf[nat->tx_cur]=iobuf;
|
423
|
455
|
|
|
@@ -432,7 +464,6 @@ static int nat_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
|
432
|
464
|
nat->tx[nat->tx_cur].cmdsts= (uint32_t) iob_len(iobuf)|OWN;
|
433
|
465
|
|
434
|
466
|
|
435
|
|
- //DBG_HD(bus_to_virt(nat->tx[nat->tx_cur].bufptr), iob_len(iobuf) );
|
436
|
467
|
nat->tx_cur=(nat->tx_cur+1) % TX_RING_SIZE;
|
437
|
468
|
|
438
|
469
|
/*start the transmitter */
|
|
@@ -459,7 +490,6 @@ static void nat_poll ( struct net_device *netdev, unsigned int rx_quota ) {
|
459
|
490
|
i=nat->tx_dirty;
|
460
|
491
|
while(i!=nat->tx_cur)
|
461
|
492
|
{
|
462
|
|
- //status=(uint32_t)bus_to_virt(nat->tx[nat->tx_dirty].cmdsts);
|
463
|
493
|
status=nat->tx[nat->tx_dirty].cmdsts;
|
464
|
494
|
DBG("value of tx_dirty = %d tx_cur=%d status=%X\n",
|
465
|
495
|
nat->tx_dirty,nat->tx_cur,status);
|
|
@@ -487,9 +517,7 @@ static void nat_poll ( struct net_device *netdev, unsigned int rx_quota ) {
|
487
|
517
|
}
|
488
|
518
|
|
489
|
519
|
|
490
|
|
- //rx_status=(unsigned int)bus_to_virt(nat->rx[nat->rx_cur].cmdsts);
|
491
|
520
|
rx_status=(unsigned int)nat->rx[nat->rx_cur].cmdsts;
|
492
|
|
- //DBG ("Receiver Status = %x\n",rx_status);
|
493
|
521
|
/* Handle received packets */
|
494
|
522
|
while (rx_quota && (rx_status & OWN))
|
495
|
523
|
{
|
|
@@ -510,16 +538,14 @@ static void nat_poll ( struct net_device *netdev, unsigned int rx_quota ) {
|
510
|
538
|
return;
|
511
|
539
|
memcpy(iob_put(rx_iob,rx_len),
|
512
|
540
|
bus_to_virt(nat->rx[nat->rx_cur].bufptr),rx_len);
|
513
|
|
- //DBG_HD(bus_to_virt(nat->rx[nat->rx_cur].bufptr),rx_len);
|
514
|
541
|
|
515
|
|
- DBG("received packet");
|
|
542
|
+ DBG("received packet\n");
|
516
|
543
|
/* add to the receive queue. */
|
517
|
544
|
netdev_rx(netdev,rx_iob);
|
518
|
545
|
rx_quota--;
|
519
|
546
|
}
|
520
|
547
|
nat->rx[nat->rx_cur].cmdsts = RX_BUF_SIZE;
|
521
|
548
|
nat->rx_cur=(nat->rx_cur+1) % NUM_RX_DESC;
|
522
|
|
- //rx_status=(unsigned int)bus_to_virt(nat->rx[nat->rx_cur].cmdsts);
|
523
|
549
|
rx_status=(unsigned int)nat->rx[nat->rx_cur].cmdsts;
|
524
|
550
|
}
|
525
|
551
|
|
|
@@ -568,9 +594,7 @@ static int nat_probe ( struct pci_device *pci,
|
568
|
594
|
nat_init_eeprom ( nat );
|
569
|
595
|
nvs_read ( &nat->eeprom.nvs, EE_MAC, netdev->ll_addr, ETH_ALEN );
|
570
|
596
|
uint8_t eetest[128];
|
571
|
|
- int i;
|
572
|
597
|
nvs_read ( &nat->eeprom.nvs, 0, eetest,128 );
|
573
|
|
- // DBG_HD(&eetest,128);
|
574
|
598
|
|
575
|
599
|
|
576
|
600
|
/* mdio routine of etherboot-5.4.0 natsemi driver has been removed and
|
|
@@ -633,10 +657,10 @@ static int nat_probe ( struct pci_device *pci,
|
633
|
657
|
static void nat_remove ( struct pci_device *pci ) {
|
634
|
658
|
struct net_device *netdev = pci_get_drvdata ( pci );
|
635
|
659
|
struct natsemi_nic *nat = netdev->priv;
|
636
|
|
-/* TODO
|
637
|
|
- if ( rtl->nvo.nvs )
|
638
|
|
- nvo_unregister ( &rtl->nvo );
|
639
|
|
- */
|
|
660
|
+
|
|
661
|
+ if ( nat->nvo.nvs )
|
|
662
|
+ nvo_unregister ( &nat->nvo );
|
|
663
|
+
|
640
|
664
|
unregister_netdev ( netdev );
|
641
|
665
|
nat_reset ( nat );
|
642
|
666
|
netdev_put ( netdev );
|