1 /* natsemi.c - gPXE driver for the NatSemi DP8381x series. */
6 natsemi.c: An Etherboot driver for the NatSemi DP8381x series.
8 Copyright (C) 2001 Entity Cyber, Inc.
10 This development of this Etherboot driver was funded by
12 Sicom Systems: http://www.sicompos.com/
14 Author: Marty Connor (mdc@thinguin.org)
15 Adapted from a Linux driver which was written by Donald Becker
17 This software may be used and distributed according to the terms
18 of the GNU Public License (GPL), incorporated herein by reference.
20 Original Copyright Notice:
22 Written/copyright 1999-2001 by Donald Becker.
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.
32 The original author may be reached as becker@scyld.com, or at
33 Scyld Computing Corporation
34 410 Severn Ave., Suite 210
37 Support information and updates available at
38 http://www.scyld.com/network/netsemi.html
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
49 /* Revision History */
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.
57 13 Dec 2003 timlegge 1.1 Enabled Multicast Support
59 Initial Release. Tested with Netgear FA311 and FA312 boards
74 #include <gpxe/if_ether.h>
75 #include <gpxe/ethernet.h>
76 #include <gpxe/iobuf.h>
77 #include <gpxe/netdevice.h>
78 #include <gpxe/spi_bit.h>
79 #include <gpxe/threewire.h>
82 #define TX_RING_SIZE 4
84 #define RX_BUF_SIZE 1536
85 #define OWN 0x80000000
86 #define DSIZE 0x00000FFF
102 unsigned short ioaddr
;
103 unsigned short tx_cur
;
104 unsigned short tx_dirty
;
105 unsigned short rx_cur
;
106 struct natsemi_tx tx
[TX_RING_SIZE
];
107 struct natsemi_rx rx
[NUM_RX_DESC
];
108 /* need to add iobuf as we cannot free iobuf->data in close without this
109 * alternatively substracting sizeof(head) and sizeof(list_head) can also
111 struct io_buffer
*iobuf
[NUM_RX_DESC
];
112 /*netdev_tx_complete needs pointer to the iobuf of the data so as to free
113 it from the memory.*/
114 struct io_buffer
*tx_iobuf
[TX_RING_SIZE
];
115 struct spi_bit_basher spibit
;
116 struct spi_device eeprom
;
117 struct nvo_block nvo
;
121 /* NATSEMI: Offsets to the device registers.
122 Unlike software-only systems, device drivers interact with complex hardware.
123 It's not useful to define symbolic names for every register bit in the
126 enum register_offsets
{
156 /* These are from the spec, around page 78... on a separate table. */
170 /* Bit in ChipCmd. */
182 /* Bits in the RxMode register. */
186 AcceptBroadcast
= 0xC0000000,
187 AcceptMulticast
= 0x00200000,
188 AcceptAllMulticast
= 0x20000000,
189 AcceptAllPhys
= 0x10000000,
190 AcceptMyPhys
= 0x08000000,
191 RxFilterEnable
= 0x80000000
194 /* Bits in network_desc.status */
195 enum desc_status_bits
{
196 DescOwn
= 0x80000000,
197 DescMore
= 0x40000000,
198 DescIntr
= 0x20000000,
199 DescNoCRC
= 0x10000000,
200 DescPktOK
= 0x08000000,
201 RxTooLong
= 0x00400000
204 /*Bits in Interrupt Mask register */
206 enum Intr_mask_register_bits
{
214 /* EEPROM access , values are devices specific*/
215 #define EE_CS 0x08 /* EEPROM chip select */
216 #define EE_SK 0x04 /* EEPROM shift clock */
217 #define EE_DI 0x01 /* Data in */
218 #define EE_DO 0x02 /* Data out */
220 /* Offsets within EEPROM (these are word offsets) */
222 #define EE_REG EECtrl
223 static uint32_t SavedClkRun
;
226 static const uint8_t nat_ee_bits
[] = {
227 [SPI_BIT_SCLK
] = EE_SK
,
228 [SPI_BIT_MOSI
] = EE_DI
,
229 [SPI_BIT_MISO
] = EE_DO
,
230 [SPI_BIT_SS(0)] = EE_CS
,
233 static int nat_spi_read_bit ( struct bit_basher
*basher
,
234 unsigned int bit_id
) {
235 struct natsemi_nic
*nat
= container_of ( basher
, struct natsemi_nic
,
237 uint8_t mask
= nat_ee_bits
[bit_id
];
240 eereg
= inb ( nat
->ioaddr
+ EE_REG
);
241 return ( eereg
& mask
);
244 static void nat_spi_write_bit ( struct bit_basher
*basher
,
245 unsigned int bit_id
, unsigned long data
) {
246 struct natsemi_nic
*nat
= container_of ( basher
, struct natsemi_nic
,
248 uint8_t mask
= nat_ee_bits
[bit_id
];
251 eereg
= inb ( nat
->ioaddr
+ EE_REG
);
253 eereg
|= ( data
& mask
);
254 outb ( eereg
, nat
->ioaddr
+ EE_REG
);
257 static struct bit_basher_operations nat_basher_ops
= {
258 .read
= nat_spi_read_bit
,
259 .write
= nat_spi_write_bit
,
261 /** Portion of EEPROM available for non-volatile stored options
263 * We use offset 0x40 (i.e. address 0x20), length 0x40. This block is
264 * marked as VPD in the rtl8139 datasheets, so we use it only if we
265 * detect that the card is not supporting VPD.
267 static struct nvo_fragment nat_nvo_fragments
[] = {
273 * Set up for EEPROM access
277 void nat_init_eeprom ( struct natsemi_nic
*nat
) {
279 // Initialise three-wire bus
280 nat
->spibit
.basher
.op
= &nat_basher_ops
;
281 nat
->spibit
.bus
.mode
= SPI_MODE_THREEWIRE
;
282 nat
->spibit
.endianness
= SPI_BIT_LITTLE_ENDIAN
;
283 init_spi_bit_basher ( &nat
->spibit
);
285 /*natsemi DP 83815 only supports at93c46 */
286 init_at93c46 ( &nat
->eeprom
, 16 );
287 nat
->eeprom
.bus
= &nat
->spibit
.bus
;
289 nat
->nvo
.nvs
= &nat
->eeprom
.nvs
;
290 nat
->nvo
.fragments
= nat_nvo_fragments
;
298 * Issues a hardware reset and waits for the reset to complete.
300 static void nat_reset ( struct natsemi_nic
*nat
) {
304 outl ( ChipReset
, nat
->ioaddr
+ ChipCmd
);
308 for(i
=0;i
<TX_RING_SIZE
;i
++)
315 outl(virt_to_bus(&nat
->tx
[0]),nat
->ioaddr
+TxRingPtr
);
316 outl(virt_to_bus(&nat
->rx
[0]), nat
->ioaddr
+ RxRingPtr
);
318 outl(TxOff
|RxOff
, nat
->ioaddr
+ ChipCmd
);
320 /* Restore PME enable bit */
321 outl(SavedClkRun
, nat
->ioaddr
+ ClkRun
);
327 * @v netdev Net device
328 * @ret rc Return status code
330 static int nat_open ( struct net_device
*netdev
) {
331 struct natsemi_nic
*nat
= netdev
->priv
;
333 uint32_t tx_config
,rx_config
;
336 * The PME bit is initialized from the EEPROM contents.
337 * PCI cards probably have PME disabled, but motherboard
338 * implementations may have PME set to enable WakeOnLan.
339 * With PME set the chip will scan incoming packets but
340 * nothing will be written to memory. */
341 SavedClkRun
= inl(nat
->ioaddr
+ ClkRun
);
342 outl(SavedClkRun
& ~0x100, nat
->ioaddr
+ ClkRun
);
349 for ( i
= 0 ; i
< ETH_ALEN
; i
+=2 )
351 outl(i
,nat
->ioaddr
+RxFilterAddr
);
352 last1
=netdev
->ll_addr
[i
]>>7;
353 netdev
->ll_addr
[i
]=netdev
->ll_addr
[i
]<<1|last
;
354 last
=(netdev
->ll_addr
[i
+1]>>7);
355 netdev
->ll_addr
[i
+1]=(netdev
->ll_addr
[i
+1]<<1)+last1
;
357 outw ( netdev
->ll_addr
[i
] + (netdev
->ll_addr
[i
+1]<<8), nat
->ioaddr
+RxFilterData
);
362 /*Set up the Tx Ring */
365 for (i
=0;i
<TX_RING_SIZE
;i
++)
367 nat
->tx
[i
].link
= virt_to_bus((i
+1 < TX_RING_SIZE
) ? &nat
->tx
[i
+1] : &nat
->tx
[0]);
368 nat
->tx
[i
].cmdsts
= 0;
369 nat
->tx
[i
].bufptr
= 0;
378 for (i
=0;i
<NUM_RX_DESC
;i
++)
381 nat
->iobuf
[i
] = alloc_iob ( RX_BUF_SIZE
);
384 nat
->rx
[i
].link
= virt_to_bus((i
+1 < NUM_RX_DESC
) ? &nat
->rx
[i
+1] : &nat
->rx
[0]);
385 nat
->rx
[i
].cmdsts
= (uint32_t) RX_BUF_SIZE
;
386 nat
->rx
[i
].bufptr
= virt_to_bus(nat
->iobuf
[i
]->data
);
390 /* load Receive Descriptor Register */
391 outl(virt_to_bus(&nat
->rx
[0]), nat
->ioaddr
+ RxRingPtr
);
392 DBG("Natsemi Rx descriptor loaded with: %X\n",(unsigned int)inl(nat
->ioaddr
+RxRingPtr
));
395 outl(virt_to_bus(&nat
->tx
[0]),nat
->ioaddr
+TxRingPtr
);
396 DBG("Natsemi Tx descriptor loaded with: %X\n",(unsigned int)inl(nat
->ioaddr
+TxRingPtr
));
399 outl(RxFilterEnable
|AcceptBroadcast
|AcceptAllMulticast
|AcceptMyPhys
, nat
->ioaddr
+RxFilterAddr
);
401 /* Initialize other registers. */
402 /* Configure the PCI bus bursts and FIFO thresholds. */
403 /* Configure for standard, in-spec Ethernet. */
404 if (inl(nat
->ioaddr
+ ChipConfig
) & 0x20000000) { /* Full duplex */
405 tx_config
= 0xD0801002;
406 rx_config
= 0x10000020;
408 tx_config
= 0x10801002;
411 outl(tx_config
, nat
->ioaddr
+ TxConfig
);
412 outl(rx_config
, nat
->ioaddr
+ RxConfig
);
416 /*start the receiver */
417 outl(RxOn
, nat
->ioaddr
+ ChipCmd
);
419 /*enable interrupts*/
420 outl((RxOk
|RxErr
|TxOk
|TxErr
),nat
->ioaddr
+ IntrMask
);
421 outl(1,nat
->ioaddr
+IntrEnable
);
432 * @v netdev Net device
434 static void nat_close ( struct net_device
*netdev
) {
435 struct natsemi_nic
*nat
= netdev
->priv
;
439 /* Reset the hardware to disable everything in one go */
443 for (i
=0;i
<NUM_RX_DESC
;i
++)
446 free_iob( nat
->iobuf
[i
] );
448 /* disable interrupts */
449 outl(0,nat
->ioaddr
+ IntrMask
) ;
455 * @v netdev Network device
456 * @v iobuf I/O buffer
457 * @ret rc Return status code
459 static int nat_transmit ( struct net_device
*netdev
, struct io_buffer
*iobuf
) {
460 struct natsemi_nic
*nat
= netdev
->priv
;
462 /* check for space in TX ring */
464 if (nat
->tx
[nat
->tx_cur
].cmdsts
!=0)
466 printf ( "TX overflow\n" );
470 /* to be used in netdev_tx_complete*/
471 nat
->tx_iobuf
[nat
->tx_cur
]=iobuf
;
473 /* Pad and align packet */
474 iob_pad ( iobuf
, ETH_ZLEN
);
477 DBG ( "TX id %d at %lx+%x\n", nat
->tx_cur
,
478 virt_to_bus ( &iobuf
->data
), iob_len ( iobuf
) );
480 nat
->tx
[nat
->tx_cur
].bufptr
= virt_to_bus(iobuf
->data
);
481 nat
->tx
[nat
->tx_cur
].cmdsts
= (uint32_t) iob_len(iobuf
)|OWN
;
484 nat
->tx_cur
=(nat
->tx_cur
+1) % TX_RING_SIZE
;
486 /*start the transmitter */
487 outl(TxOn
, nat
->ioaddr
+ ChipCmd
);
493 * Poll for received packets
495 * @v netdev Network device
496 * @v rx_quota Maximum number of packets to receive
498 static void nat_poll ( struct net_device
*netdev
, unsigned int rx_quota
) {
499 struct natsemi_nic
*nat
= netdev
->priv
;
501 unsigned int rx_status
;
502 unsigned int intr_status
;
504 struct io_buffer
*rx_iob
;
507 //outl(1,nat->ioaddr +IntrEnable);
508 /* read the interrupt register */
509 intr_status
=inl(nat
->ioaddr
+IntrStatus
);
513 /* check the status of packets given to card for transmission */
514 DBG("Intr status %X\n",intr_status
);
518 while(i
!=nat
->tx_cur
)
520 status
=nat
->tx
[nat
->tx_dirty
].cmdsts
;
521 DBG("value of tx_dirty = %d tx_cur=%d status=%X\n",
522 nat
->tx_dirty
,nat
->tx_cur
,status
);
524 /* check if current packet has been transmitted or not */
527 /* Check if any errors in transmission */
528 if (! (status
& DescPktOK
))
530 printf("Error in sending Packet status:%X\n",
531 (unsigned int)status
);
535 DBG("Success in transmitting Packet with data\n");
536 // DBG_HD(&nat->tx[nat->tx_dirty].bufptr,130);
538 netdev_tx_complete(netdev
,nat
->tx_iobuf
[nat
->tx_dirty
]);
539 /* setting cmdsts zero, indicating that it can be reused */
540 nat
->tx
[nat
->tx_dirty
].cmdsts
=0;
541 nat
->tx_dirty
=(nat
->tx_dirty
+1) % TX_RING_SIZE
;
542 i
=(i
+1) % TX_RING_SIZE
;
547 rx_status
=(unsigned int)nat
->rx
[nat
->rx_cur
].cmdsts
;
548 /* Handle received packets */
549 while (rx_quota
&& (rx_status
& OWN
))
551 rx_len
= (rx_status
& DSIZE
) - CRC_SIZE
;
553 /*check for the corrupt packet */
554 if((rx_status
& (DescMore
|DescPktOK
|RxTooLong
)) != DescPktOK
)
556 printf("natsemi_poll: Corrupted packet received, "
557 "buffer status = %X ^ %X \n",rx_status
,
558 (unsigned int) nat
->rx
[nat
->rx_cur
].cmdsts
);
562 rx_iob
= alloc_iob(rx_len
);
564 /* leave packet for next call to poll*/
566 memcpy(iob_put(rx_iob
,rx_len
),
567 bus_to_virt(nat
->rx
[nat
->rx_cur
].bufptr
),rx_len
);
569 DBG("received packet\n");
570 /* add to the receive queue. */
571 netdev_rx(netdev
,rx_iob
);
574 nat
->rx
[nat
->rx_cur
].cmdsts
= RX_BUF_SIZE
;
575 nat
->rx_cur
=(nat
->rx_cur
+1) % NUM_RX_DESC
;
576 rx_status
=(unsigned int)nat
->rx
[nat
->rx_cur
].cmdsts
;
581 /* re-enable the potentially idle receive state machine */
582 outl(RxOn
, nat
->ioaddr
+ ChipCmd
);
583 // outl(1,nat->ioaddr +IntrEnable);
596 * @ret rc Return status code
598 static int nat_probe ( struct pci_device
*pci
,
599 const struct pci_device_id
*id __unused
) {
600 struct net_device
*netdev
;
601 struct natsemi_nic
*nat
= NULL
;
602 int registered_netdev
= 0;
604 uint32_t advertising
;
606 /* Fix up PCI device */
607 adjust_pci_device ( pci
);
609 /* Allocate net device */
610 netdev
= alloc_etherdev ( sizeof ( *nat
) );
616 pci_set_drvdata ( pci
, netdev
);
617 netdev
->dev
= &pci
->dev
;
618 memset ( nat
, 0, sizeof ( *nat
) );
619 nat
->ioaddr
= pci
->ioaddr
;
621 /* getting the IRQ vector */
622 unsigned long vector_phys
= IRQ_INT ( pci
->irq
) * 4;
623 DBG_HDA ( vector_phys
, phys_to_virt ( vector_phys
), 4 );
624 DBG_HD ( phys_to_virt ( 0xfaea5 ), 64 );
625 DBG (" PIC state %X\n", irq_enabled(pci
->irq
));
626 DBG (" IRQ Number %X\n",pci
->irq
);
630 /* Reset the NIC, set up EEPROM access and read MAC address */
632 nat_init_eeprom ( nat
);
633 nvs_read ( &nat
->eeprom
.nvs
, EE_MAC
, netdev
->ll_addr
, ETH_ALEN
);
635 nvs_read ( &nat
->eeprom
.nvs
, 0, eetest
,128 );
638 /* mdio routine of etherboot-5.4.0 natsemi driver has been removed and
639 * statement to read from MII transceiver control section is used directly
642 advertising
= inl(nat
->ioaddr
+ 0x80 + (4<<2)) & 0xffff;
644 uint32_t chip_config
= inl(nat
->ioaddr
+ ChipConfig
);
645 DBG("%s: Transceiver default autoneg. %s 10 %s %s duplex.\n",
647 chip_config
& 0x2000 ? "enabled, advertise" : "disabled, force",
648 chip_config
& 0x4000 ? "0" : "",
649 chip_config
& 0x8000 ? "full" : "half");
651 DBG("%s: Transceiver status %hX advertising %hX\n",pci
->driver_name
, (int)inl(nat
->ioaddr
+ 0x84),(unsigned int) advertising
);
657 /* Point to NIC specific routines */
658 netdev
->open
= nat_open
;
659 netdev
->close
= nat_close
;
660 netdev
->transmit
= nat_transmit
;
661 netdev
->poll
= nat_poll
;
663 /* Register network device */
664 if ( ( rc
= register_netdev ( netdev
) ) != 0 )
666 registered_netdev
= 1;
668 /* Register non-volatile storagei
669 * uncomment lines below in final version*/
671 if ( nat
->nvo
.nvs
) {
672 if ( ( rc
= nvo_register ( &nat
->nvo
) ) != 0 )
683 if ( registered_netdev
)
684 unregister_netdev ( netdev
);
685 /* Free net device */
686 netdev_put ( netdev
);
695 static void nat_remove ( struct pci_device
*pci
) {
696 struct net_device
*netdev
= pci_get_drvdata ( pci
);
697 struct natsemi_nic
*nat
= netdev
->priv
;
700 nvo_unregister ( &nat
->nvo
);
702 unregister_netdev ( netdev
);
704 netdev_put ( netdev
);
707 static struct pci_device_id natsemi_nics
[] = {
708 PCI_ROM(0x100b, 0x0020, "dp83815", "DP83815"),
712 struct pci_driver natsemi_driver __pci_driver
= {
714 .id_count
= ( sizeof ( natsemi_nics
) / sizeof ( natsemi_nics
[0] ) ),
716 .remove
= nat_remove
,