added silicon revision number
[people/holger/gpxe.git] / src / drivers / net / natsemi.c
1 /* natsemi.c - gPXE driver for the NatSemi DP8381x series. */
2
3 /*
4
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 */
50
51 /*
52   02 JUL 2007 Udayan Kumar       1.2 ported the driver from etherboot to gPXE API.
53                                      Fully rewritten,adapting the old driver.
54                                      Added a circular buffer for transmit and receive.
55                                      transmit routine will not wait for transmission to finish.
56                                      poll routine deals with it.
57
58   13 Dec 2003 timlegge           1.1 Enabled Multicast Support
59   29 May 2001  mdc               1.0
60      Initial Release.            Tested with Netgear FA311 and FA312 boards
61 */
62  
63
64
65
66 #include <stdint.h>
67 #include <pic8259.h>
68 #include <stdlib.h>
69 #include <stdio.h>
70 #include <io.h>
71 #include <errno.h>
72 #include <timer.h>
73 #include <byteswap.h>
74 #include <gpxe/pci.h>
75 #include <gpxe/if_ether.h>
76 #include <gpxe/ethernet.h>
77 #include <gpxe/iobuf.h>
78 #include <gpxe/netdevice.h>
79 #include <gpxe/spi_bit.h>
80 #include <gpxe/threewire.h>
81 #include <gpxe/nvo.h>
82 #include <mii.h>
83
84 #define TX_RING_SIZE 4
85 #define NUM_RX_DESC  4
86 #define RX_BUF_SIZE 1536
87 #define OWN       0x80000000
88 #define DSIZE     0x00000FFF
89 #define CRC_SIZE  4
90
91 struct natsemi_tx {
92         uint32_t link;
93         uint32_t cmdsts;
94         uint32_t bufptr;
95 };
96
97 struct natsemi_rx {
98         uint32_t link;
99         uint32_t cmdsts;
100         uint32_t bufptr;
101 };
102
103 struct natsemi_nic {
104         unsigned short ioaddr;
105         unsigned short tx_cur;
106         unsigned short tx_dirty;
107         unsigned short rx_cur;
108         struct natsemi_tx tx[TX_RING_SIZE];
109         struct natsemi_rx rx[NUM_RX_DESC];
110
111         /* need to add iobuf as we cannot free iobuf->data in close without this 
112          * alternatively substracting sizeof(head) and sizeof(list_head) can also 
113          * give the same.
114          */
115         struct io_buffer *iobuf[NUM_RX_DESC];
116
117         /* netdev_tx_complete needs pointer to the iobuf of the data so as to free 
118          * it from the memory.
119          */
120         struct io_buffer *tx_iobuf[TX_RING_SIZE];
121         struct spi_bit_basher spibit;
122         struct spi_device eeprom;
123         struct nvo_block nvo;
124 };
125
126
127 /*
128  * Support for fibre connections on Am79C874:
129  * This phy needs a special setup when connected to a fibre cable.
130  * http://www.amd.com/files/connectivitysolutions/networking/archivednetworking/22235.pdf
131  */
132 #define PHYID_AM79C874  0x0022561b
133
134 enum {
135         MII_MCTRL       = 0x15,         /* mode control register */
136         MII_FX_SEL      = 0x0001,       /* 100BASE-FX (fiber) */
137         MII_EN_SCRM     = 0x0004,       /* enable scrambler (tp) */
138 };
139
140
141
142 /* values we might find in the silicon revision register */
143 #define SRR_DP83815_C   0x0302
144 #define SRR_DP83815_D   0x0403
145 #define SRR_DP83816_A4  0x0504
146 #define SRR_DP83816_A5  0x0505
147
148 /* NATSEMI: Offsets to the device registers.
149  * Unlike software-only systems, device drivers interact with complex hardware.
150  * It's not useful to define symbolic names for every register bit in the
151  * device.
152  */
153 enum register_offsets {
154     ChipCmd      = 0x00, 
155     ChipConfig   = 0x04, 
156     EECtrl       = 0x08, 
157     PCIBusCfg    = 0x0C,
158     IntrStatus   = 0x10, 
159     IntrMask     = 0x14, 
160     IntrEnable   = 0x18,
161     TxRingPtr    = 0x20, 
162     TxConfig     = 0x24,
163     RxRingPtr    = 0x30,
164     RxConfig     = 0x34, 
165     ClkRun       = 0x3C,
166     WOLCmd       = 0x40, 
167     PauseCmd     = 0x44,
168     RxFilterAddr = 0x48, 
169     RxFilterData = 0x4C,
170     BootRomAddr  = 0x50, 
171     BootRomData  = 0x54, 
172     SiliconRev   = 0x58, 
173     StatsCtrl    = 0x5C,
174     StatsData    = 0x60, 
175     RxPktErrs    = 0x60, 
176     RxMissed     = 0x68, 
177     RxCRCErrs    = 0x64,
178     PCIPM        = 0x44,
179     PhyStatus    = 0xC0, 
180     MIntrCtrl    = 0xC4, 
181     MIntrStatus  = 0xC8,
182
183     /* These are from the spec, around page 78... on a separate table. 
184      */
185     PGSEL        = 0xCC, 
186     PMDCSR       = 0xE4, 
187     TSTDAT       = 0xFC, 
188     DSPCFG       = 0xF4, 
189     SDCFG        = 0x8C,
190     BasicControl = 0x80,        
191     BasicStatus  = 0x84
192             
193 };
194
195 /* the values for the 'magic' registers above (PGSEL=1) */
196 #define PMDCSR_VAL      0x189c  /* enable preferred adaptation circuitry */
197 #define TSTDAT_VAL      0x0
198 #define DSPCFG_VAL      0x5040
199 #define SDCFG_VAL       0x008c  /* set voltage thresholds for Signal Detect */
200 #define DSPCFG_LOCK     0x20    /* coefficient lock bit in DSPCFG */
201 #define DSPCFG_COEF     0x1000  /* see coefficient (in TSTDAT) bit in DSPCFG */
202 #define TSTDAT_FIXED    0xe8    /* magic number for bad coefficients */
203
204 /* Bit in ChipCmd.
205  */
206 enum ChipCmdBits {
207     ChipReset = 0x100, 
208     RxReset   = 0x20, 
209     TxReset   = 0x10, 
210     RxOff     = 0x08, 
211     RxOn      = 0x04,
212     TxOff     = 0x02, 
213     TxOn      = 0x01
214 };
215
216 enum ChipConfig_bits {
217         CfgPhyDis               = 0x200,
218         CfgPhyRst               = 0x400,
219         CfgExtPhy               = 0x1000,
220         CfgAnegEnable           = 0x2000,
221         CfgAneg100              = 0x4000,
222         CfgAnegFull             = 0x8000,
223         CfgAnegDone             = 0x8000000,
224         CfgFullDuplex           = 0x20000000,
225         CfgSpeed100             = 0x40000000,
226         CfgLink                 = 0x80000000,
227 };
228
229
230 /* Bits in the RxMode register.
231  */
232 enum rx_mode_bits {
233     AcceptErr          = 0x20,
234     AcceptRunt         = 0x10,
235     AcceptBroadcast    = 0xC0000000,
236     AcceptMulticast    = 0x00200000, 
237     AcceptAllMulticast = 0x20000000,
238     AcceptAllPhys      = 0x10000000, 
239     AcceptMyPhys       = 0x08000000,
240     RxFilterEnable     = 0x80000000
241 };
242
243 /* Bits in network_desc.status
244  */
245 enum desc_status_bits {
246     DescOwn   = 0x80000000, 
247     DescMore  = 0x40000000, 
248     DescIntr  = 0x20000000,
249     DescNoCRC = 0x10000000,
250     DescPktOK = 0x08000000, 
251     RxTooLong = 0x00400000
252 };
253
254 /*Bits in Interrupt Mask register
255  */
256 enum Intr_mask_register_bits {
257     RxOk       = 0x001,
258     RxErr      = 0x004,
259     TxOk       = 0x040,
260     TxErr      = 0x100 
261 };      
262
263 /*  EEPROM access , values are devices specific
264  */
265 #define EE_CS           0x08    /* EEPROM chip select */
266 #define EE_SK           0x04    /* EEPROM shift clock */
267 #define EE_DI           0x01    /* Data in */
268 #define EE_DO           0x02    /* Data out */
269
270 /* Offsets within EEPROM (these are word offsets)
271  */
272 #define EE_MAC 7
273 #define EE_REG  EECtrl
274 static uint32_t SavedClkRun;    
275
276 static const uint8_t nat_ee_bits[] = {
277         [SPI_BIT_SCLK]  = EE_SK,
278         [SPI_BIT_MOSI]  = EE_DI,
279         [SPI_BIT_MISO]  = EE_DO,
280         [SPI_BIT_SS(0)] = EE_CS,
281 };
282
283 static int nat_spi_read_bit ( struct bit_basher *basher,
284                               unsigned int bit_id ) {
285         struct natsemi_nic *nat = container_of ( basher, struct natsemi_nic,
286                                                  spibit.basher );
287         uint8_t mask = nat_ee_bits[bit_id];
288         uint8_t eereg;
289
290         eereg = inb ( nat->ioaddr + EE_REG );
291         return ( eereg & mask );
292 }
293
294 static void nat_spi_write_bit ( struct bit_basher *basher,
295                                 unsigned int bit_id, unsigned long data ) {
296         struct natsemi_nic *nat = container_of ( basher, struct natsemi_nic,
297                                                  spibit.basher );
298         uint8_t mask = nat_ee_bits[bit_id];
299         uint8_t eereg;
300
301         eereg = inb ( nat->ioaddr + EE_REG );
302         eereg &= ~mask;
303         eereg |= ( data & mask );
304         outb ( eereg, nat->ioaddr + EE_REG );
305 }
306
307 static struct bit_basher_operations nat_basher_ops = {
308         .read = nat_spi_read_bit,
309         .write = nat_spi_write_bit,
310 };
311
312 /* It looks that this portion of EEPROM can be used for 
313  * non-volatile stored options. Data sheet does not talk about this region.
314  * Currently it is not working. But with some efforts it can.
315  */
316 static struct nvo_fragment nat_nvo_fragments[] = {
317         { 0x0c, 0x68 },
318         { 0, 0 }
319 };
320
321 /*
322  * Set up for EEPROM access
323  *
324  * @v NAT               NATSEMI NIC
325  */
326  void nat_init_eeprom ( struct natsemi_nic *nat ) {
327
328         /* Initialise three-wire bus 
329          */
330         nat->spibit.basher.op = &nat_basher_ops;
331         nat->spibit.bus.mode = SPI_MODE_THREEWIRE;
332         nat->spibit.endianness = SPI_BIT_LITTLE_ENDIAN;
333         init_spi_bit_basher ( &nat->spibit );
334
335         /*natsemi DP 83815 only supports at93c46
336          */
337         init_at93c46 ( &nat->eeprom, 16 );
338         nat->eeprom.bus = &nat->spibit.bus;
339
340         nat->nvo.nvs = &nat->eeprom.nvs;
341         nat->nvo.fragments = nat_nvo_fragments;
342 }
343
344 /*
345  * Reset NIC
346  *
347  * @v           NATSEMI NIC
348  *
349  * Issues a hardware reset and waits for the reset to complete.
350  */
351 static void nat_reset ( struct natsemi_nic *nat ) {
352
353         int i;
354
355         /* Reset chip
356          */
357         outl ( ChipReset, nat->ioaddr + ChipCmd );
358         mdelay ( 10 );
359         nat->tx_dirty = 0;
360         nat->tx_cur = 0;
361         for ( i = 0 ; i < TX_RING_SIZE ; i++ ) {
362                 nat->tx[i].link = 0;
363                 nat->tx[i].cmdsts = 0;
364                 nat->tx[i].bufptr = 0;
365         }
366         nat->rx_cur = 0;
367         outl ( virt_to_bus( &nat->tx[0] ),nat->ioaddr + TxRingPtr );
368         outl ( virt_to_bus( &nat->rx[0] ),nat->ioaddr + RxRingPtr );
369
370         outl ( TxOff|RxOff, nat->ioaddr + ChipCmd );
371
372         /* Restore PME enable bit
373          */
374         outl ( SavedClkRun, nat->ioaddr + ClkRun );
375 }
376
377
378 static int mdio_read(struct net_device *netdev, int reg) {
379         struct natsemi_nic *nat = netdev->priv;
380
381         /* The 83815 series has two ports:
382          * - an internal transceiver
383          * - an external mii bus
384          */
385                 return inw(nat->ioaddr+BasicControl+(reg<<2));
386 }
387
388 static void mdio_write(struct net_device *netdev, int reg, u16 data) {
389         struct natsemi_nic *nat = netdev->priv;
390
391         /* The 83815 series has an internal transceiver; handle separately */
392                 writew(data, nat->ioaddr+BasicControl+(reg<<2));
393 }
394
395 static void init_phy_fixup(struct net_device *netdev) {
396         struct natsemi_nic *nat = netdev->priv;
397         int i;
398         u32 cfg;
399         u16 tmp;
400         uint16_t advertising;
401         int mii;
402
403         /* restore stuff lost when power was out */
404         tmp = mdio_read(netdev, MII_BMCR);
405         advertising= mdio_read(netdev, MII_ADVERTISE);
406 //      if (np->autoneg == AUTONEG_ENABLE) {
407                 /* renegotiate if something changed */
408                 if ((tmp & BMCR_ANENABLE) == 0
409                  || advertising != mdio_read(netdev, MII_ADVERTISE))
410                 {
411                         /* turn on autonegotiation and force negotiation */
412                         tmp |= (BMCR_ANENABLE | BMCR_ANRESTART);
413                         mdio_write(netdev, MII_ADVERTISE, advertising);
414                 }
415 //      } else {
416                 /* turn off auto negotiation, set speed and duplexity */
417 //              tmp &= ~(BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX);
418 //              if (np->speed == SPEED_100)
419 ///                     tmp |= BMCR_SPEED100;
420 //              if (np->duplex == DUPLEX_FULL)
421 //                      tmp |= BMCR_FULLDPLX;
422                 /*
423                  * Note: there is no good way to inform the link partner
424                  * that our capabilities changed. The user has to unplug
425                  * and replug the network cable after some changes, e.g.
426                  * after switching from 10HD, autoneg off to 100 HD,
427                  * autoneg off.
428                  */
429 //      }
430         mdio_write(netdev, MII_BMCR, tmp);
431         inl(nat->ioaddr + ChipConfig);
432         udelay(1);
433
434         /* find out what phy this is */
435         mii = (mdio_read(netdev, MII_PHYSID1) << 16)
436                                 + mdio_read(netdev, MII_PHYSID2);
437
438         /* handle external phys here */
439         switch (mii) {
440         case PHYID_AM79C874:
441                 /* phy specific configuration for fibre/tp operation */
442                 tmp = mdio_read(netdev, MII_MCTRL);
443                 tmp &= ~(MII_FX_SEL | MII_EN_SCRM);
444                 //if (dev->if_port == PORT_FIBRE)
445                 //      tmp |= MII_FX_SEL;
446                 //else
447                         tmp |= MII_EN_SCRM;
448                 mdio_write(netdev, MII_MCTRL, tmp);
449                 break;
450         default:
451                 break;
452         }
453         cfg = inl(nat->ioaddr + ChipConfig);
454         if (cfg & CfgExtPhy)
455                 return;
456
457         /* On page 78 of the spec, they recommend some settings for "optimum
458            performance" to be done in sequence.  These settings optimize some
459            of the 100Mbit autodetection circuitry.  They say we only want to
460            do this for rev C of the chip, but engineers at NSC (Bradley
461            Kennedy) recommends always setting them.  If you don't, you get
462            errors on some autonegotiations that make the device unusable.
463
464            It seems that the DSP needs a few usec to reinitialize after
465            the start of the phy. Just retry writing these values until they
466            stick.
467         */
468         uint32_t srr = inl(nat->ioaddr + SiliconRev);
469         DBG ( "Natsemi : silicon revision %#04x.\n",(unsigned int)srr);
470         int NATSEMI_HW_TIMEOUT = 400;
471         for (i=0;i<NATSEMI_HW_TIMEOUT;i++) {
472
473                 int dspcfg,dspcfg_1;
474                 outw(1, nat->ioaddr + PGSEL);
475                 outw(PMDCSR_VAL, nat->ioaddr + PMDCSR);
476                 outw(TSTDAT_VAL, nat->ioaddr + TSTDAT);
477                 dspcfg = (srr <= SRR_DP83815_C)?
478                         DSPCFG_VAL : (DSPCFG_COEF | readw(nat->ioaddr + DSPCFG));
479                 outw(dspcfg, nat->ioaddr + DSPCFG);
480                 outw(SDCFG_VAL, nat->ioaddr + SDCFG);
481                 outw(0, nat->ioaddr + PGSEL);
482                 inl(nat->ioaddr + ChipConfig);
483                 udelay(10);
484
485                 outw(1, nat->ioaddr + PGSEL);
486                 dspcfg_1 = readw(nat->ioaddr + DSPCFG);
487                 outw(0, nat->ioaddr + PGSEL);
488                 if (dspcfg == dspcfg_1)
489                         break;
490         }
491
492                 if (i==NATSEMI_HW_TIMEOUT) {
493                         DBG ( "Natsemi: DSPCFG mismatch after retrying for"
494                               " %d usec.\n", i*10);
495                 } else {
496                         DBG ( "NATSEMI: DSPCFG accepted after %d usec.\n",
497                               i*10);
498                 }
499         /*
500          * Enable PHY Specific event based interrupts.  Link state change
501          * and Auto-Negotiation Completion are among the affected.
502          * Read the intr status to clear it (needed for wake events).
503          */
504         inw(nat->ioaddr + MIntrStatus);
505         //MICRIntEn = 0x2
506         outw(0x2, nat->ioaddr + MIntrCtrl);
507 }
508
509
510 /* 
511  * Patch up for fixing CRC errors.
512  * adapted from linux natsemi driver
513  *
514  */
515 static void do_cable_magic ( struct net_device *netdev ) {
516         struct natsemi_nic *nat = netdev->priv;
517         uint16_t data;
518         /*
519          * 100 MBit links with short cables can trip an issue with the chip.
520          * The problem manifests as lots of CRC errors and/or flickering
521          * activity LED while idle.  This process is based on instructions
522          * from engineers at National.
523          */
524         if (inl(nat->ioaddr + ChipConfig) & CfgSpeed100) {
525
526                 outw(1, nat->ioaddr + PGSEL);
527                 /*
528                  * coefficient visibility should already be enabled via
529                  * DSPCFG | 0x1000
530                  */
531                 data = inw(nat->ioaddr + TSTDAT) & 0xff;
532                 /*
533                  * the value must be negative, and within certain values
534                  * (these values all come from National)
535                  */
536                 if (!(data & 0x80) || ((data >= 0xd8) && (data <= 0xff))) {
537
538                         /* the bug has been triggered - fix the coefficient */
539                         outw(TSTDAT_FIXED, nat->ioaddr + TSTDAT);
540                         /* lock the value */
541                         data = inw(nat->ioaddr + DSPCFG);
542                         //np->dspcfg = data | DSPCFG_LOCK;
543                         outw(data | DSPCFG_LOCK , nat->ioaddr + DSPCFG);
544                 }
545                 outw(0, nat->ioaddr + PGSEL);
546         }
547
548 }
549
550 /*
551  * Open NIC
552  *
553  * @v netdev            Net device
554  * @ret rc              Return status code
555  */
556 static int nat_open ( struct net_device *netdev ) {
557         struct natsemi_nic *nat = netdev->priv;
558         int i;
559         uint32_t tx_config,rx_config;
560         
561         /* Disable PME:
562          * The PME bit is initialized from the EEPROM contents.
563          * PCI cards probably have PME disabled, but motherboard
564          * implementations may have PME set to enable WakeOnLan. 
565          * With PME set the chip will scan incoming packets but
566          * nothing will be written to memory. 
567          */
568         SavedClkRun = inl ( nat->ioaddr + ClkRun );
569         outl ( SavedClkRun & ~0x100, nat->ioaddr + ClkRun );
570
571         /* Setting up Mac address in the NIC
572          */
573         for ( i = 0 ; i < ETH_ALEN ; i+=2 ) {
574                 outl ( i,nat->ioaddr + RxFilterAddr );
575                 outw ( netdev->ll_addr[i] + ( netdev->ll_addr[i + 1] << 8 ),
576                        nat->ioaddr + RxFilterData );
577         }
578
579         /*Set up the Tx Ring
580          */
581         nat->tx_cur = 0;
582         nat->tx_dirty = 0;
583         for ( i = 0 ; i < TX_RING_SIZE ; i++ ) {
584                 nat->tx[i].link   = virt_to_bus ( ( i + 1 < TX_RING_SIZE ) ? &nat->tx[i + 1] : &nat->tx[0] );
585                 nat->tx[i].cmdsts = 0;
586                 nat->tx[i].bufptr = 0;
587         }
588
589         /* Set up RX ring
590          */
591         nat->rx_cur = 0;
592         for ( i = 0 ; i < NUM_RX_DESC ; i++ ) {
593                 nat->iobuf[i] = alloc_iob ( RX_BUF_SIZE );
594                 if ( !nat->iobuf[i] )
595                         goto memory_alloc_err;
596                 nat->rx[i].link   = virt_to_bus ( ( i + 1 < NUM_RX_DESC ) ? &nat->rx[i + 1] : &nat->rx[0] );
597                 nat->rx[i].cmdsts = RX_BUF_SIZE;
598                 nat->rx[i].bufptr = virt_to_bus ( nat->iobuf[i]->data );
599         }
600
601         /* load Receive Descriptor Register
602          */
603         outl ( virt_to_bus ( &nat->rx[0] ), nat->ioaddr + RxRingPtr );
604         DBG ( "Natsemi Rx descriptor loaded with: %X\n",
605                 (unsigned int) inl ( nat->ioaddr + RxRingPtr ) );               
606
607         /* setup Tx ring
608          */
609         outl ( virt_to_bus ( &nat->tx[0] ),nat->ioaddr + TxRingPtr );
610         DBG ( "Natsemi Tx descriptor loaded with: %X\n",
611                 (unsigned int)inl ( nat->ioaddr + TxRingPtr ) );
612
613         /* Enables RX
614          */
615         outl ( RxFilterEnable|AcceptBroadcast|AcceptAllMulticast|AcceptMyPhys,
616                  nat->ioaddr + RxFilterAddr );
617
618         /* Initialize other registers. 
619          * Configure the PCI bus bursts and FIFO thresholds. 
620          * Configure for standard, in-spec Ethernet. 
621          */
622         if ( inl ( nat->ioaddr + ChipConfig ) & 0x20000000 ) {  /* Full duplex */
623                 tx_config = 0xD0801002 | 0xC0000000;
624                 DBG ( "Full duplex\n" );
625                 rx_config = 0x10000020 | 0x10000000;
626         } else {
627                 tx_config = 0x10801002 & ~0xC0000000;
628                 DBG ( "Half duplex\n" );
629                 rx_config = 0x0020 & ~0x10000000;
630         }
631         outl ( tx_config, nat->ioaddr + TxConfig );
632         outl ( rx_config, nat->ioaddr + RxConfig );
633
634         /*start the receiver 
635          */
636         outl ( RxOn, nat->ioaddr + ChipCmd );
637         
638         /* lines 1586 linux-natsemi.c uses cable magic 
639          * testing this feature is required or not
640          */
641         do_cable_magic ( netdev ); 
642         init_phy_fixup ( netdev );
643         
644
645         /* mask the interrupts. note interrupt is not enabled here
646          */
647         return 0;
648                        
649 memory_alloc_err:
650
651         /* this block frees the previously allocated buffers
652          * if memory for all the buffers is not available
653          */
654         i = 0;
655         while ( nat->rx[i].cmdsts == RX_BUF_SIZE ) {
656                 free_iob ( nat->iobuf[i] );
657                 i++;
658         }
659         return -ENOMEM; 
660 }
661
662 /**
663  * Close NIC
664  *
665  * @v netdev            Net device
666  */
667 static void nat_close ( struct net_device *netdev ) {
668         struct natsemi_nic *nat = netdev->priv;
669         int i;
670
671         /* Reset the hardware to disable everything in one go
672          */
673         nat_reset ( nat );
674
675         /* Free RX ring
676          */
677         for ( i = 0; i < NUM_RX_DESC ; i++ ) {
678                 
679                 free_iob ( nat->iobuf[i] );
680         }
681 }
682
683 /** 
684  * Transmit packet
685  *
686  * @v netdev    Network device
687  * @v iobuf     I/O buffer
688  * @ret rc      Return status code
689  */
690 static int nat_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
691         struct natsemi_nic *nat = netdev->priv;
692
693         /* check for space in TX ring
694          */
695         if ( nat->tx[nat->tx_cur].cmdsts != 0 ) {
696                 DBG ( "TX overflow\n" );
697                 return -ENOBUFS;
698         }
699
700         /* to be used in netdev_tx_complete
701          */
702         nat->tx_iobuf[nat->tx_cur] = iobuf;
703
704         /* Pad and align packet has not been used because its not required here
705          * iob_pad ( iobuf, ETH_ZLEN ); can be used to achieve it
706          */
707
708         /* Add to TX ring
709          */
710         DBG ( "TX id %d at %lx + %x\n", nat->tx_cur,
711               virt_to_bus ( &iobuf->data ), iob_len ( iobuf ) );
712
713         nat->tx[nat->tx_cur].bufptr = virt_to_bus ( iobuf->data );
714         nat->tx[nat->tx_cur].cmdsts = iob_len ( iobuf ) | OWN;
715
716         /* increment the circular buffer pointer to the next buffer location
717          */
718         nat->tx_cur = ( nat->tx_cur + 1 ) % TX_RING_SIZE;
719
720         /*start the transmitter 
721          */
722         outl ( TxOn, nat->ioaddr + ChipCmd );
723
724         return 0;
725 }
726
727 /** 
728  * Poll for received packets
729  *
730  * @v netdev    Network device
731  * @v rx_quota  Maximum number of packets to receive
732  */
733 static void nat_poll ( struct net_device *netdev) {
734         struct natsemi_nic *nat = netdev->priv;
735         unsigned int status;
736         unsigned int rx_status;
737         unsigned int intr_status;
738         unsigned int rx_len;
739         struct io_buffer *rx_iob;
740         int i;
741         
742         /* read the interrupt register
743          */
744         intr_status = inl ( nat->ioaddr + IntrStatus );
745         if ( !intr_status )
746                 goto end;
747
748         /* check the status of packets given to card for transmission
749          */     
750         DBG ( "Intr status %X\n",intr_status );
751
752         i = nat->tx_dirty;
753         while ( i!= nat->tx_cur ) {
754                 status = nat->tx[nat->tx_dirty].cmdsts;
755                 DBG ( "value of tx_dirty = %d tx_cur=%d status=%X\n",
756                         nat->tx_dirty,nat->tx_cur,status );
757                 
758                 /* check if current packet has been transmitted or not
759                  */
760                 if ( status & OWN ) 
761                         break;
762
763                 /* Check if any errors in transmission
764                  */
765                 if (! ( status & DescPktOK ) ) {
766                         DBG ( "Error in sending Packet status:%X\n",
767                                         (unsigned int) status );
768                         netdev_tx_complete_err ( netdev,nat->tx_iobuf[nat->tx_dirty],-EINVAL );
769                 } else {
770                         DBG ( "Success in transmitting Packet\n" );
771                         netdev_tx_complete ( netdev,nat->tx_iobuf[nat->tx_dirty] );
772                 }
773
774                 /* setting cmdsts zero, indicating that it can be reused 
775                  */
776                 nat->tx[nat->tx_dirty].cmdsts = 0;
777                 nat->tx_dirty = ( nat->tx_dirty + 1 ) % TX_RING_SIZE;
778                 i = ( i + 1 ) % TX_RING_SIZE;
779         }
780         
781         /* Handle received packets 
782          */
783         rx_status = (unsigned int) nat->rx[nat->rx_cur].cmdsts; 
784         while ( ( rx_status & OWN ) ) {
785                 rx_len = ( rx_status & DSIZE ) - CRC_SIZE;
786
787                 /*check for the corrupt packet 
788                  */
789                 if ( ( rx_status & ( DescMore|DescPktOK|RxTooLong ) ) != DescPktOK) {
790                          DBG ( "natsemi_poll: Corrupted packet received, "
791                                         "buffer status = %X \n",
792                                         (unsigned int) nat->rx[nat->rx_cur].cmdsts );
793                          netdev_rx_err ( netdev,NULL,-EINVAL );
794                 } else  {
795                         rx_iob = alloc_iob ( rx_len );
796
797                         if ( !rx_iob ) 
798                                 /* leave packet for next call to poll
799                                  */
800                                 goto end;
801                         memcpy ( iob_put ( rx_iob,rx_len ),
802                                         nat->iobuf[nat->rx_cur]->data,rx_len );
803                         DBG ( "received packet\n" );
804
805                         /* add to the receive queue. 
806                          */
807                         netdev_rx ( netdev,rx_iob );
808                 }
809                 nat->rx[nat->rx_cur].cmdsts = RX_BUF_SIZE;
810                 nat->rx_cur = ( nat->rx_cur + 1 ) % NUM_RX_DESC;
811                 rx_status = nat->rx[nat->rx_cur].cmdsts; 
812         }
813 end:
814
815         /* re-enable the potentially idle receive state machine 
816          */
817         outl ( RxOn, nat->ioaddr + ChipCmd );   
818 }                               
819
820 /**
821  * Enable/disable interrupts
822  *
823  * @v netdev    Network device
824  * @v enable    Interrupts should be enabled
825  */
826 static void nat_irq ( struct net_device *netdev, int enable ) {
827         struct natsemi_nic *nat = netdev->priv;
828
829         outl ( ( enable ? ( RxOk|RxErr|TxOk|TxErr ) :0 ),
830                 nat->ioaddr + IntrMask); 
831         outl ( ( enable ? 1:0 ),nat->ioaddr + IntrEnable );
832 }
833
834
835
836
837
838 /** natsemi net device operations */
839 static struct net_device_operations nat_operations = {
840         .open           = nat_open,
841         .close          = nat_close,
842         .transmit       = nat_transmit,
843         .poll           = nat_poll,
844         .irq            = nat_irq,
845 };
846
847 /*
848  * Probe PCI device
849  *
850  * @v pci       PCI device
851  * @v id        PCI ID
852  * @ret rc      Return status code
853  */
854 static int nat_probe ( struct pci_device *pci,
855                        const struct pci_device_id *id __unused ) {
856         struct net_device *netdev;
857         struct natsemi_nic *nat = NULL;
858         int rc;
859         int i;
860         uint8_t ll_addr_encoded[MAX_LL_ADDR_LEN];
861         uint8_t last = 0;
862         uint8_t last1 = 0;
863         uint8_t prev_bytes[2];
864
865         /* Allocate net device 
866          */
867         netdev = alloc_etherdev ( sizeof ( *nat ) );
868         if ( ! netdev ) 
869                 return -ENOMEM;
870         netdev_init ( netdev,&nat_operations );
871         nat = netdev->priv;
872         pci_set_drvdata ( pci, netdev );
873         netdev->dev = &pci->dev;
874         memset ( nat, 0, sizeof ( *nat ) );
875         nat->ioaddr = pci->ioaddr;
876
877         /* Fix up PCI device
878          */
879         adjust_pci_device ( pci );
880
881         /* Reset the NIC, set up EEPROM access and read MAC address
882          */
883         nat_reset ( nat );
884         nat_init_eeprom ( nat );
885         nvs_read ( &nat->eeprom.nvs, EE_MAC-1, prev_bytes, 1 );
886         nvs_read ( &nat->eeprom.nvs, EE_MAC, ll_addr_encoded, ETH_ALEN );
887
888         /* decoding the MAC address read from NVS 
889          * and save it in netdev->ll_addr
890          */
891         last = prev_bytes[1] >> 7;
892         for ( i = 0 ; i < ETH_ALEN ; i++ ) {
893                 last1 = ll_addr_encoded[i] >> 7;
894                 netdev->ll_addr[i] = ll_addr_encoded[i] << 1 | last;
895                 last = last1;
896         }
897
898         /* Register network device
899          */
900         if ( ( rc = register_netdev ( netdev ) ) != 0 )
901                 goto err_register_netdev;
902
903         return 0;
904
905 err_register_netdev:
906
907         /* Disable NIC
908          */
909         nat_reset ( nat );
910
911         /* Free net device
912          */
913         netdev_put ( netdev );
914         return rc;
915 }
916
917 /**
918  * Remove PCI device
919  *
920  * @v pci       PCI device
921  */
922 static void nat_remove ( struct pci_device *pci ) {
923         struct net_device *netdev = pci_get_drvdata ( pci );
924         struct natsemi_nic *nat = netdev->priv;
925  
926         if ( nat->nvo.nvs )
927                 nvo_unregister ( &nat->nvo );
928                 
929         unregister_netdev ( netdev );
930         nat_reset ( nat );
931         netdev_put ( netdev );
932 }
933
934 static struct pci_device_id natsemi_nics[] = {
935         PCI_ROM(0x100b, 0x0020, "dp83815", "DP83815"),
936 };
937
938 struct pci_driver natsemi_driver __pci_driver = {
939         .ids = natsemi_nics,
940         .id_count = ( sizeof ( natsemi_nics ) / sizeof ( natsemi_nics[0] ) ),
941         .probe = nat_probe,
942         .remove = nat_remove,
943 };