d2097abb0fe88bdb77724fd583c071748348096f
[people/xl0/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         //      DBG ( " Address of iobuf [%d] = %x and iobuf->data = %x \n", i, 
600         //              nat->iobuf[i],nat->iobuf[i]->data);
601         }
602
603         /* load Receive Descriptor Register
604          */
605         outl ( virt_to_bus ( &nat->rx[0] ), nat->ioaddr + RxRingPtr );
606         DBG ( "Natsemi Rx descriptor loaded with: %X\n",
607                 (unsigned int) inl ( nat->ioaddr + RxRingPtr ) );               
608
609         /* setup Tx ring
610          */
611         outl ( virt_to_bus ( &nat->tx[0] ),nat->ioaddr + TxRingPtr );
612         DBG ( "Natsemi Tx descriptor loaded with: %X\n",
613                 (unsigned int)inl ( nat->ioaddr + TxRingPtr ) );
614
615         /* Enables RX
616          */
617         outl ( RxFilterEnable|AcceptBroadcast|AcceptAllMulticast|AcceptMyPhys,
618                  nat->ioaddr + RxFilterAddr );
619
620         /* Initialize other registers. 
621          * Configure the PCI bus bursts and FIFO thresholds. 
622          * Configure for standard, in-spec Ethernet. 
623          */
624         if ( inl ( nat->ioaddr + ChipConfig ) & 0x20000000 ) {  /* Full duplex */
625                 tx_config = 0xD0801002 | 0xC0000000;
626                 DBG ( "Full duplex\n" );
627                 rx_config = 0x10000020 | 0x10000000;
628         } else {
629                 tx_config = 0x10801002 & ~0xC0000000;
630                 DBG ( "Half duplex\n" );
631                 rx_config = 0x0020 & ~0x10000000;
632         }
633         outl ( tx_config, nat->ioaddr + TxConfig );
634         outl ( rx_config, nat->ioaddr + RxConfig );
635
636         DBG ( "Tx config register = %x Rx config register =  %x\n", 
637                (unsigned int) inl ( nat->ioaddr + TxConfig),
638                (unsigned int) inl ( nat->ioaddr + RxConfig) );
639         /*start the receiver 
640          */
641         outl ( RxOn, nat->ioaddr + ChipCmd );
642         
643         /* lines 1586 linux-natsemi.c uses cable magic 
644          * testing this feature is required or not
645          */
646         do_cable_magic ( netdev ); 
647         init_phy_fixup ( netdev );
648         
649         
650
651         /* mask the interrupts. note interrupt is not enabled here
652          */
653         return 0;
654                        
655 memory_alloc_err:
656
657         /* this block frees the previously allocated buffers
658          * if memory for all the buffers is not available
659          */
660         i = 0;
661         while ( nat->rx[i].cmdsts == RX_BUF_SIZE ) {
662                 free_iob ( nat->iobuf[i] );
663                 i++;
664         }
665         return -ENOMEM; 
666 }
667
668 /**
669  * Close NIC
670  *
671  * @v netdev            Net device
672  */
673 static void nat_close ( struct net_device *netdev ) {
674         struct natsemi_nic *nat = netdev->priv;
675         int i;
676
677         /* Reset the hardware to disable everything in one go
678          */
679         nat_reset ( nat );
680
681         /* Free RX ring
682          */
683         for ( i = 0; i < NUM_RX_DESC ; i++ ) {
684                 
685                 free_iob ( nat->iobuf[i] );
686         }
687 }
688
689 /** 
690  * Transmit packet
691  *
692  * @v netdev    Network device
693  * @v iobuf     I/O buffer
694  * @ret rc      Return status code
695  */
696 static int nat_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
697         struct natsemi_nic *nat = netdev->priv;
698
699         /* check for space in TX ring
700          */
701         if ( nat->tx[nat->tx_cur].cmdsts != 0 ) {
702                 DBG ( "TX overflow\n" );
703                 return -ENOBUFS;
704         }
705
706         /* to be used in netdev_tx_complete
707          */
708         nat->tx_iobuf[nat->tx_cur] = iobuf;
709
710         /* Pad and align packet has not been used because its not required here
711          * iob_pad ( iobuf, ETH_ZLEN ); can be used to achieve it
712          */
713
714         /* Add to TX ring
715          */
716         DBG ( "TX id %d at %lx + %x\n", nat->tx_cur,
717               virt_to_bus ( &iobuf->data ), iob_len ( iobuf ) );
718
719         nat->tx[nat->tx_cur].bufptr = virt_to_bus ( iobuf->data );
720         nat->tx[nat->tx_cur].cmdsts = iob_len ( iobuf ) | OWN;
721
722         /* increment the circular buffer pointer to the next buffer location
723          */
724         nat->tx_cur = ( nat->tx_cur + 1 ) % TX_RING_SIZE;
725
726         /*start the transmitter 
727          */
728         outl ( TxOn, nat->ioaddr + ChipCmd );
729
730         return 0;
731 }
732
733 /** 
734  * Poll for received packets
735  *
736  * @v netdev    Network device
737  * @v rx_quota  Maximum number of packets to receive
738  */
739 static void nat_poll ( struct net_device *netdev) {
740         struct natsemi_nic *nat = netdev->priv;
741         unsigned int status;
742         unsigned int rx_status;
743         unsigned int intr_status;
744         unsigned int rx_len;
745         struct io_buffer *rx_iob;
746         int i;
747         
748         /* read the interrupt register
749          */
750         intr_status = inl ( nat->ioaddr + IntrStatus );
751         if ( !intr_status )
752                 goto end;
753
754         /* check the status of packets given to card for transmission
755          */     
756         DBG ( "Intr status %X\n",intr_status );
757
758         i = nat->tx_dirty;
759         while ( i!= nat->tx_cur ) {
760                 status = nat->tx[nat->tx_dirty].cmdsts;
761                 DBG ( "value of tx_dirty = %d tx_cur=%d status=%X\n",
762                         nat->tx_dirty,nat->tx_cur,status );
763                 
764                 /* check if current packet has been transmitted or not
765                  */
766                 if ( status & OWN ) 
767                         break;
768
769                 /* Check if any errors in transmission
770                  */
771                 if (! ( status & DescPktOK ) ) {
772                         DBG ( "Error in sending Packet status:%X\n",
773                                         (unsigned int) status );
774                         netdev_tx_complete_err ( netdev,nat->tx_iobuf[nat->tx_dirty],-EINVAL );
775                 } else {
776                         DBG ( "Success in transmitting Packet\n" );
777                         netdev_tx_complete ( netdev,nat->tx_iobuf[nat->tx_dirty] );
778                 }
779
780                 /* setting cmdsts zero, indicating that it can be reused 
781                  */
782                 nat->tx[nat->tx_dirty].cmdsts = 0;
783                 nat->tx_dirty = ( nat->tx_dirty + 1 ) % TX_RING_SIZE;
784                 i = ( i + 1 ) % TX_RING_SIZE;
785         }
786         
787         /* Handle received packets 
788          */
789         rx_status = (unsigned int) nat->rx[nat->rx_cur].cmdsts; 
790         while ( ( rx_status & OWN ) ) {
791                 rx_len = ( rx_status & DSIZE ) - CRC_SIZE;
792                 DBG ( " Status of received packet = %X , Lenght of Packet = %X\n",
793                         rx_status,rx_len );
794
795                 /*check for the corrupt packet 
796                  */
797                 if ( ( rx_status & ( DescMore|DescPktOK|RxTooLong ) ) != DescPktOK) {
798                         DBG ( "natsemi_poll: Corrupted packet received, "
799                                 "buffer status = %X \n",
800                                 (unsigned int) nat->rx[nat->rx_cur].cmdsts );
801                         //DBG_HD ( nat->iobuf[nat->rx_cur]->data,rx_len);
802                         netdev_rx_err ( netdev,NULL,-EINVAL );
803                 } else  {
804                         rx_iob = alloc_iob ( rx_len );
805
806                         if ( !rx_iob ) 
807                                 /* leave packet for next call to poll
808                                  */
809                                 goto end;
810                         memcpy ( iob_put ( rx_iob,rx_len ),
811                                         nat->iobuf[nat->rx_cur]->data,rx_len );
812                         DBG ( "received packet\n" );
813                         //DBG_HD ( nat->iobuf[nat->rx_cur]->data,30);
814
815                         /* add to the receive queue. 
816                          */
817                         netdev_rx ( netdev,rx_iob );
818                 }
819                 nat->rx[nat->rx_cur].cmdsts = RX_BUF_SIZE;
820                 nat->rx_cur = ( nat->rx_cur + 1 ) % NUM_RX_DESC;
821                 rx_status = nat->rx[nat->rx_cur].cmdsts; 
822         }
823 end:
824
825         /* re-enable the potentially idle receive state machine 
826          */
827         outl ( RxOn, nat->ioaddr + ChipCmd );   
828 }                               
829
830 /**
831  * Enable/disable interrupts
832  *
833  * @v netdev    Network device
834  * @v enable    Interrupts should be enabled
835  */
836 static void nat_irq ( struct net_device *netdev, int enable ) {
837         struct natsemi_nic *nat = netdev->priv;
838
839         outl ( ( enable ? ( RxOk|RxErr|TxOk|TxErr ) :0 ),
840                 nat->ioaddr + IntrMask); 
841         outl ( ( enable ? 1:0 ),nat->ioaddr + IntrEnable );
842 }
843
844
845
846
847
848 /** natsemi net device operations */
849 static struct net_device_operations nat_operations = {
850         .open           = nat_open,
851         .close          = nat_close,
852         .transmit       = nat_transmit,
853         .poll           = nat_poll,
854         .irq            = nat_irq,
855 };
856
857 /*
858  * Probe PCI device
859  *
860  * @v pci       PCI device
861  * @v id        PCI ID
862  * @ret rc      Return status code
863  */
864 static int nat_probe ( struct pci_device *pci,
865                        const struct pci_device_id *id __unused ) {
866         struct net_device *netdev;
867         struct natsemi_nic *nat = NULL;
868         int rc;
869         int i;
870         uint8_t ll_addr_encoded[MAX_LL_ADDR_LEN];
871         uint8_t last = 0;
872         uint8_t last1 = 0;
873         uint8_t prev_bytes[2];
874
875         /* Allocate net device 
876          */
877         netdev = alloc_etherdev ( sizeof ( *nat ) );
878         if ( ! netdev ) 
879                 return -ENOMEM;
880         netdev_init ( netdev,&nat_operations );
881         nat = netdev->priv;
882         pci_set_drvdata ( pci, netdev );
883         netdev->dev = &pci->dev;
884         memset ( nat, 0, sizeof ( *nat ) );
885         nat->ioaddr = pci->ioaddr;
886
887         /* Fix up PCI device
888          */
889         adjust_pci_device ( pci );
890
891         /* Reset the NIC, set up EEPROM access and read MAC address
892          */
893         nat_reset ( nat );
894         nat_init_eeprom ( nat );
895         nvs_read ( &nat->eeprom.nvs, EE_MAC-1, prev_bytes, 1 );
896         nvs_read ( &nat->eeprom.nvs, EE_MAC, ll_addr_encoded, ETH_ALEN );
897
898         /* decoding the MAC address read from NVS 
899          * and save it in netdev->ll_addr
900          */
901         last = prev_bytes[1] >> 7;
902         for ( i = 0 ; i < ETH_ALEN ; i++ ) {
903                 last1 = ll_addr_encoded[i] >> 7;
904                 netdev->ll_addr[i] = ll_addr_encoded[i] << 1 | last;
905                 last = last1;
906         }
907
908         /* Register network device
909          */
910         if ( ( rc = register_netdev ( netdev ) ) != 0 )
911                 goto err_register_netdev;
912
913         return 0;
914
915 err_register_netdev:
916
917         /* Disable NIC
918          */
919         nat_reset ( nat );
920
921         /* Free net device
922          */
923         netdev_put ( netdev );
924         return rc;
925 }
926
927 /**
928  * Remove PCI device
929  *
930  * @v pci       PCI device
931  */
932 static void nat_remove ( struct pci_device *pci ) {
933         struct net_device *netdev = pci_get_drvdata ( pci );
934         struct natsemi_nic *nat = netdev->priv;
935  
936         if ( nat->nvo.nvs )
937                 nvo_unregister ( &nat->nvo );
938                 
939         unregister_netdev ( netdev );
940         nat_reset ( nat );
941         netdev_put ( netdev );
942 }
943
944 static struct pci_device_id natsemi_nics[] = {
945         PCI_ROM(0x100b, 0x0020, "dp83815", "DP83815"),
946 };
947
948 struct pci_driver natsemi_driver __pci_driver = {
949         .ids = natsemi_nics,
950         .id_count = ( sizeof ( natsemi_nics ) / sizeof ( natsemi_nics[0] ) ),
951         .probe = nat_probe,
952         .remove = nat_remove,
953 };