e69a8f3f5108293813dfca164db7723075d5f121
[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         int NATSEMI_HW_TIMEOUT = 400;
470         for (i=0;i<NATSEMI_HW_TIMEOUT;i++) {
471
472                 int dspcfg,dspcfg_1;
473                 outw(1, nat->ioaddr + PGSEL);
474                 outw(PMDCSR_VAL, nat->ioaddr + PMDCSR);
475                 outw(TSTDAT_VAL, nat->ioaddr + TSTDAT);
476                 dspcfg = (srr <= SRR_DP83815_C)?
477                         DSPCFG_VAL : (DSPCFG_COEF | readw(nat->ioaddr + DSPCFG));
478                 outw(dspcfg, nat->ioaddr + DSPCFG);
479                 outw(SDCFG_VAL, nat->ioaddr + SDCFG);
480                 outw(0, nat->ioaddr + PGSEL);
481                 inl(nat->ioaddr + ChipConfig);
482                 udelay(10);
483
484                 outw(1, nat->ioaddr + PGSEL);
485                 dspcfg_1 = readw(nat->ioaddr + DSPCFG);
486                 outw(0, nat->ioaddr + PGSEL);
487                 if (dspcfg == dspcfg_1)
488                         break;
489         }
490
491                 if (i==NATSEMI_HW_TIMEOUT) {
492                         DBG ( "Natsemi: DSPCFG mismatch after retrying for"
493                               " %d usec.\n", i*10);
494                 } else {
495                         DBG ( "NATSEMI: DSPCFG accepted after %d usec.\n",
496                               i*10);
497                 }
498         /*
499          * Enable PHY Specific event based interrupts.  Link state change
500          * and Auto-Negotiation Completion are among the affected.
501          * Read the intr status to clear it (needed for wake events).
502          */
503         inw(nat->ioaddr + MIntrStatus);
504         //MICRIntEn = 0x2
505         outw(0x2, nat->ioaddr + MIntrCtrl);
506 }
507
508
509 /* 
510  * Patch up for fixing CRC errors.
511  * adapted from linux natsemi driver
512  *
513  */
514 static void do_cable_magic ( struct net_device *netdev ) {
515         struct natsemi_nic *nat = netdev->priv;
516         uint16_t data;
517         /*
518          * 100 MBit links with short cables can trip an issue with the chip.
519          * The problem manifests as lots of CRC errors and/or flickering
520          * activity LED while idle.  This process is based on instructions
521          * from engineers at National.
522          */
523         if (inl(nat->ioaddr + ChipConfig) & CfgSpeed100) {
524
525                 outw(1, nat->ioaddr + PGSEL);
526                 /*
527                  * coefficient visibility should already be enabled via
528                  * DSPCFG | 0x1000
529                  */
530                 data = inw(nat->ioaddr + TSTDAT) & 0xff;
531                 /*
532                  * the value must be negative, and within certain values
533                  * (these values all come from National)
534                  */
535                 if (!(data & 0x80) || ((data >= 0xd8) && (data <= 0xff))) {
536
537                         /* the bug has been triggered - fix the coefficient */
538                         outw(TSTDAT_FIXED, nat->ioaddr + TSTDAT);
539                         /* lock the value */
540                         data = inw(nat->ioaddr + DSPCFG);
541                         //np->dspcfg = data | DSPCFG_LOCK;
542                         outw(data | DSPCFG_LOCK , nat->ioaddr + DSPCFG);
543                 }
544                 outw(0, nat->ioaddr + PGSEL);
545         }
546
547 }
548
549 /*
550  * Open NIC
551  *
552  * @v netdev            Net device
553  * @ret rc              Return status code
554  */
555 static int nat_open ( struct net_device *netdev ) {
556         struct natsemi_nic *nat = netdev->priv;
557         int i;
558         uint32_t tx_config,rx_config;
559         
560         /* Disable PME:
561          * The PME bit is initialized from the EEPROM contents.
562          * PCI cards probably have PME disabled, but motherboard
563          * implementations may have PME set to enable WakeOnLan. 
564          * With PME set the chip will scan incoming packets but
565          * nothing will be written to memory. 
566          */
567         SavedClkRun = inl ( nat->ioaddr + ClkRun );
568         outl ( SavedClkRun & ~0x100, nat->ioaddr + ClkRun );
569
570         /* Setting up Mac address in the NIC
571          */
572         for ( i = 0 ; i < ETH_ALEN ; i+=2 ) {
573                 outl ( i,nat->ioaddr + RxFilterAddr );
574                 outw ( netdev->ll_addr[i] + ( netdev->ll_addr[i + 1] << 8 ),
575                        nat->ioaddr + RxFilterData );
576         }
577
578         /*Set up the Tx Ring
579          */
580         nat->tx_cur = 0;
581         nat->tx_dirty = 0;
582         for ( i = 0 ; i < TX_RING_SIZE ; i++ ) {
583                 nat->tx[i].link   = virt_to_bus ( ( i + 1 < TX_RING_SIZE ) ? &nat->tx[i + 1] : &nat->tx[0] );
584                 nat->tx[i].cmdsts = 0;
585                 nat->tx[i].bufptr = 0;
586         }
587
588         /* Set up RX ring
589          */
590         nat->rx_cur = 0;
591         for ( i = 0 ; i < NUM_RX_DESC ; i++ ) {
592                 nat->iobuf[i] = alloc_iob ( RX_BUF_SIZE );
593                 if ( !nat->iobuf[i] )
594                         goto memory_alloc_err;
595                 nat->rx[i].link   = virt_to_bus ( ( i + 1 < NUM_RX_DESC ) ? &nat->rx[i + 1] : &nat->rx[0] );
596                 nat->rx[i].cmdsts = RX_BUF_SIZE;
597                 nat->rx[i].bufptr = virt_to_bus ( nat->iobuf[i]->data );
598         }
599
600         /* load Receive Descriptor Register
601          */
602         outl ( virt_to_bus ( &nat->rx[0] ), nat->ioaddr + RxRingPtr );
603         DBG ( "Natsemi Rx descriptor loaded with: %X\n",
604                 (unsigned int) inl ( nat->ioaddr + RxRingPtr ) );               
605
606         /* setup Tx ring
607          */
608         outl ( virt_to_bus ( &nat->tx[0] ),nat->ioaddr + TxRingPtr );
609         DBG ( "Natsemi Tx descriptor loaded with: %X\n",
610                 (unsigned int)inl ( nat->ioaddr + TxRingPtr ) );
611
612         /* Enables RX
613          */
614         outl ( RxFilterEnable|AcceptBroadcast|AcceptAllMulticast|AcceptMyPhys,
615                  nat->ioaddr + RxFilterAddr );
616
617         /* Initialize other registers. 
618          * Configure the PCI bus bursts and FIFO thresholds. 
619          * Configure for standard, in-spec Ethernet. 
620          */
621         if ( inl ( nat->ioaddr + ChipConfig ) & 0x20000000 ) {  /* Full duplex */
622                 tx_config = 0xD0801002 | 0xC0000000;
623                 DBG ( "Full duplex\n" );
624                 rx_config = 0x10000020 | 0x10000000;
625         } else {
626                 tx_config = 0x10801002 & ~0xC0000000;
627                 DBG ( "Half duplex\n" );
628                 rx_config = 0x0020 & ~0x10000000;
629         }
630         outl ( tx_config, nat->ioaddr + TxConfig );
631         outl ( rx_config, nat->ioaddr + RxConfig );
632
633         /*start the receiver 
634          */
635         outl ( RxOn, nat->ioaddr + ChipCmd );
636         
637         /* lines 1586 linux-natsemi.c uses cable magic 
638          * testing this feature is required or not
639          */
640         do_cable_magic ( netdev ); 
641         init_phy_fixup ( netdev );
642         
643
644         /* mask the interrupts. note interrupt is not enabled here
645          */
646         return 0;
647                        
648 memory_alloc_err:
649
650         /* this block frees the previously allocated buffers
651          * if memory for all the buffers is not available
652          */
653         i = 0;
654         while ( nat->rx[i].cmdsts == RX_BUF_SIZE ) {
655                 free_iob ( nat->iobuf[i] );
656                 i++;
657         }
658         return -ENOMEM; 
659 }
660
661 /**
662  * Close NIC
663  *
664  * @v netdev            Net device
665  */
666 static void nat_close ( struct net_device *netdev ) {
667         struct natsemi_nic *nat = netdev->priv;
668         int i;
669
670         /* Reset the hardware to disable everything in one go
671          */
672         nat_reset ( nat );
673
674         /* Free RX ring
675          */
676         for ( i = 0; i < NUM_RX_DESC ; i++ ) {
677                 
678                 free_iob ( nat->iobuf[i] );
679         }
680 }
681
682 /** 
683  * Transmit packet
684  *
685  * @v netdev    Network device
686  * @v iobuf     I/O buffer
687  * @ret rc      Return status code
688  */
689 static int nat_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
690         struct natsemi_nic *nat = netdev->priv;
691
692         /* check for space in TX ring
693          */
694         if ( nat->tx[nat->tx_cur].cmdsts != 0 ) {
695                 DBG ( "TX overflow\n" );
696                 return -ENOBUFS;
697         }
698
699         /* to be used in netdev_tx_complete
700          */
701         nat->tx_iobuf[nat->tx_cur] = iobuf;
702
703         /* Pad and align packet has not been used because its not required here
704          * iob_pad ( iobuf, ETH_ZLEN ); can be used to achieve it
705          */
706
707         /* Add to TX ring
708          */
709         DBG ( "TX id %d at %lx + %x\n", nat->tx_cur,
710               virt_to_bus ( &iobuf->data ), iob_len ( iobuf ) );
711
712         nat->tx[nat->tx_cur].bufptr = virt_to_bus ( iobuf->data );
713         nat->tx[nat->tx_cur].cmdsts = iob_len ( iobuf ) | OWN;
714
715         /* increment the circular buffer pointer to the next buffer location
716          */
717         nat->tx_cur = ( nat->tx_cur + 1 ) % TX_RING_SIZE;
718
719         /*start the transmitter 
720          */
721         outl ( TxOn, nat->ioaddr + ChipCmd );
722
723         return 0;
724 }
725
726 /** 
727  * Poll for received packets
728  *
729  * @v netdev    Network device
730  * @v rx_quota  Maximum number of packets to receive
731  */
732 static void nat_poll ( struct net_device *netdev) {
733         struct natsemi_nic *nat = netdev->priv;
734         unsigned int status;
735         unsigned int rx_status;
736         unsigned int intr_status;
737         unsigned int rx_len;
738         struct io_buffer *rx_iob;
739         int i;
740         
741         /* read the interrupt register
742          */
743         intr_status = inl ( nat->ioaddr + IntrStatus );
744         if ( !intr_status )
745                 goto end;
746
747         /* check the status of packets given to card for transmission
748          */     
749         DBG ( "Intr status %X\n",intr_status );
750
751         i = nat->tx_dirty;
752         while ( i!= nat->tx_cur ) {
753                 status = nat->tx[nat->tx_dirty].cmdsts;
754                 DBG ( "value of tx_dirty = %d tx_cur=%d status=%X\n",
755                         nat->tx_dirty,nat->tx_cur,status );
756                 
757                 /* check if current packet has been transmitted or not
758                  */
759                 if ( status & OWN ) 
760                         break;
761
762                 /* Check if any errors in transmission
763                  */
764                 if (! ( status & DescPktOK ) ) {
765                         DBG ( "Error in sending Packet status:%X\n",
766                                         (unsigned int) status );
767                         netdev_tx_complete_err ( netdev,nat->tx_iobuf[nat->tx_dirty],-EINVAL );
768                 } else {
769                         DBG ( "Success in transmitting Packet\n" );
770                         netdev_tx_complete ( netdev,nat->tx_iobuf[nat->tx_dirty] );
771                 }
772
773                 /* setting cmdsts zero, indicating that it can be reused 
774                  */
775                 nat->tx[nat->tx_dirty].cmdsts = 0;
776                 nat->tx_dirty = ( nat->tx_dirty + 1 ) % TX_RING_SIZE;
777                 i = ( i + 1 ) % TX_RING_SIZE;
778         }
779         
780         /* Handle received packets 
781          */
782         rx_status = (unsigned int) nat->rx[nat->rx_cur].cmdsts; 
783         while ( ( rx_status & OWN ) ) {
784                 rx_len = ( rx_status & DSIZE ) - CRC_SIZE;
785
786                 /*check for the corrupt packet 
787                  */
788                 if ( ( rx_status & ( DescMore|DescPktOK|RxTooLong ) ) != DescPktOK) {
789                          DBG ( "natsemi_poll: Corrupted packet received, "
790                                         "buffer status = %X ^ %X \n",rx_status,
791                                         (unsigned int) nat->rx[nat->rx_cur].cmdsts );
792                          netdev_rx_err ( netdev,NULL,-EINVAL );
793                 } else  {
794                         rx_iob = alloc_iob ( rx_len );
795
796                         if ( !rx_iob ) 
797                                 /* leave packet for next call to poll
798                                  */
799                                 goto end;
800                         memcpy ( iob_put ( rx_iob,rx_len ),
801                                         nat->iobuf[nat->rx_cur]->data,rx_len );
802                         DBG ( "received packet\n" );
803
804                         /* add to the receive queue. 
805                          */
806                         netdev_rx ( netdev,rx_iob );
807                 }
808                 nat->rx[nat->rx_cur].cmdsts = RX_BUF_SIZE;
809                 nat->rx_cur = ( nat->rx_cur + 1 ) % NUM_RX_DESC;
810                 rx_status = nat->rx[nat->rx_cur].cmdsts; 
811         }
812 end:
813
814         /* re-enable the potentially idle receive state machine 
815          */
816         outl ( RxOn, nat->ioaddr + ChipCmd );   
817 }                               
818
819 /**
820  * Enable/disable interrupts
821  *
822  * @v netdev    Network device
823  * @v enable    Interrupts should be enabled
824  */
825 static void nat_irq ( struct net_device *netdev, int enable ) {
826         struct natsemi_nic *nat = netdev->priv;
827
828         outl ( ( enable ? ( RxOk|RxErr|TxOk|TxErr ) :0 ),
829                 nat->ioaddr + IntrMask); 
830         outl ( ( enable ? 1:0 ),nat->ioaddr + IntrEnable );
831 }
832
833
834
835
836
837 /** natsemi net device operations */
838 static struct net_device_operations nat_operations = {
839         .open           = nat_open,
840         .close          = nat_close,
841         .transmit       = nat_transmit,
842         .poll           = nat_poll,
843         .irq            = nat_irq,
844 };
845
846 /*
847  * Probe PCI device
848  *
849  * @v pci       PCI device
850  * @v id        PCI ID
851  * @ret rc      Return status code
852  */
853 static int nat_probe ( struct pci_device *pci,
854                        const struct pci_device_id *id __unused ) {
855         struct net_device *netdev;
856         struct natsemi_nic *nat = NULL;
857         int rc;
858         int i;
859         uint8_t ll_addr_encoded[MAX_LL_ADDR_LEN];
860         uint8_t last = 0;
861         uint8_t last1 = 0;
862         uint8_t prev_bytes[2];
863
864         /* Allocate net device 
865          */
866         netdev = alloc_etherdev ( sizeof ( *nat ) );
867         if ( ! netdev ) 
868                 return -ENOMEM;
869         netdev_init ( netdev,&nat_operations );
870         nat = netdev->priv;
871         pci_set_drvdata ( pci, netdev );
872         netdev->dev = &pci->dev;
873         memset ( nat, 0, sizeof ( *nat ) );
874         nat->ioaddr = pci->ioaddr;
875
876         /* Fix up PCI device
877          */
878         adjust_pci_device ( pci );
879
880         /* Reset the NIC, set up EEPROM access and read MAC address
881          */
882         nat_reset ( nat );
883         nat_init_eeprom ( nat );
884         nvs_read ( &nat->eeprom.nvs, EE_MAC-1, prev_bytes, 1 );
885         nvs_read ( &nat->eeprom.nvs, EE_MAC, ll_addr_encoded, ETH_ALEN );
886
887         /* decoding the MAC address read from NVS 
888          * and save it in netdev->ll_addr
889          */
890         last = prev_bytes[1] >> 7;
891         for ( i = 0 ; i < ETH_ALEN ; i++ ) {
892                 last1 = ll_addr_encoded[i] >> 7;
893                 netdev->ll_addr[i] = ll_addr_encoded[i] << 1 | last;
894                 last = last1;
895         }
896
897         /* Register network device
898          */
899         if ( ( rc = register_netdev ( netdev ) ) != 0 )
900                 goto err_register_netdev;
901
902         return 0;
903
904 err_register_netdev:
905
906         /* Disable NIC
907          */
908         nat_reset ( nat );
909
910         /* Free net device
911          */
912         netdev_put ( netdev );
913         return rc;
914 }
915
916 /**
917  * Remove PCI device
918  *
919  * @v pci       PCI device
920  */
921 static void nat_remove ( struct pci_device *pci ) {
922         struct net_device *netdev = pci_get_drvdata ( pci );
923         struct natsemi_nic *nat = netdev->priv;
924  
925         if ( nat->nvo.nvs )
926                 nvo_unregister ( &nat->nvo );
927                 
928         unregister_netdev ( netdev );
929         nat_reset ( nat );
930         netdev_put ( netdev );
931 }
932
933 static struct pci_device_id natsemi_nics[] = {
934         PCI_ROM(0x100b, 0x0020, "dp83815", "DP83815"),
935 };
936
937 struct pci_driver natsemi_driver __pci_driver = {
938         .ids = natsemi_nics,
939         .id_count = ( sizeof ( natsemi_nics ) / sizeof ( natsemi_nics[0] ) ),
940         .probe = nat_probe,
941         .remove = nat_remove,
942 };