43b7f2df94111f95600771da9ceb1305a903da6d
[people/sha0/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
83 #define TX_RING_SIZE 4
84 #define NUM_RX_DESC  4
85 #define RX_BUF_SIZE 1536
86 #define OWN       0x80000000
87 #define DSIZE     0x00000FFF
88 #define CRC_SIZE  4
89
90 struct natsemi_tx {
91         uint32_t link;
92         uint32_t cmdsts;
93         uint32_t bufptr;
94 };
95
96 struct natsemi_rx {
97         uint32_t link;
98         uint32_t cmdsts;
99         uint32_t bufptr;
100 };
101
102 struct natsemi_nic {
103         unsigned short ioaddr;
104         unsigned short tx_cur;
105         unsigned short tx_dirty;
106         unsigned short rx_cur;
107         struct natsemi_tx tx[TX_RING_SIZE];
108         struct natsemi_rx rx[NUM_RX_DESC];
109
110         /* need to add iobuf as we cannot free iobuf->data in close without this 
111          * alternatively substracting sizeof(head) and sizeof(list_head) can also 
112          * give the same.
113          */
114         struct io_buffer *iobuf[NUM_RX_DESC];
115
116         /* netdev_tx_complete needs pointer to the iobuf of the data so as to free 
117          * it from the memory.
118          */
119         struct io_buffer *tx_iobuf[TX_RING_SIZE];
120         struct spi_bit_basher spibit;
121         struct spi_device eeprom;
122         struct nvo_block nvo;
123 };
124
125 /* NATSEMI: Offsets to the device registers.
126  * Unlike software-only systems, device drivers interact with complex hardware.
127  * It's not useful to define symbolic names for every register bit in the
128  * device.
129  */
130 enum register_offsets {
131     ChipCmd      = 0x00, 
132     ChipConfig   = 0x04, 
133     EECtrl       = 0x08, 
134     PCIBusCfg    = 0x0C,
135     IntrStatus   = 0x10, 
136     IntrMask     = 0x14, 
137     IntrEnable   = 0x18,
138     TxRingPtr    = 0x20, 
139     TxConfig     = 0x24,
140     RxRingPtr    = 0x30,
141     RxConfig     = 0x34, 
142     ClkRun       = 0x3C,
143     WOLCmd       = 0x40, 
144     PauseCmd     = 0x44,
145     RxFilterAddr = 0x48, 
146     RxFilterData = 0x4C,
147     BootRomAddr  = 0x50, 
148     BootRomData  = 0x54, 
149     SiliconRev   = 0x58, 
150     StatsCtrl    = 0x5C,
151     StatsData    = 0x60, 
152     RxPktErrs    = 0x60, 
153     RxMissed     = 0x68, 
154     RxCRCErrs    = 0x64,
155     PCIPM        = 0x44,
156     PhyStatus    = 0xC0, 
157     MIntrCtrl    = 0xC4, 
158     MIntrStatus  = 0xC8,
159
160     /* These are from the spec, around page 78... on a separate table. 
161      */
162     PGSEL        = 0xCC, 
163     PMDCSR       = 0xE4, 
164     TSTDAT       = 0xFC, 
165     DSPCFG       = 0xF4, 
166     SDCFG        = 0x8C,
167     BasicControl = 0x80,        
168     BasicStatus  = 0x84
169             
170 };
171
172 /* the values for the 'magic' registers above (PGSEL=1) */
173 #define PMDCSR_VAL      0x189c  /* enable preferred adaptation circuitry */
174 #define TSTDAT_VAL      0x0
175 #define DSPCFG_VAL      0x5040
176 #define SDCFG_VAL       0x008c  /* set voltage thresholds for Signal Detect */
177 #define DSPCFG_LOCK     0x20    /* coefficient lock bit in DSPCFG */
178 #define DSPCFG_COEF     0x1000  /* see coefficient (in TSTDAT) bit in DSPCFG */
179 #define TSTDAT_FIXED    0xe8    /* magic number for bad coefficients */
180
181 /* Bit in ChipCmd.
182  */
183 enum ChipCmdBits {
184     ChipReset = 0x100, 
185     RxReset   = 0x20, 
186     TxReset   = 0x10, 
187     RxOff     = 0x08, 
188     RxOn      = 0x04,
189     TxOff     = 0x02, 
190     TxOn      = 0x01
191 };
192
193 enum ChipConfig_bits {
194         CfgPhyDis               = 0x200,
195         CfgPhyRst               = 0x400,
196         CfgExtPhy               = 0x1000,
197         CfgAnegEnable           = 0x2000,
198         CfgAneg100              = 0x4000,
199         CfgAnegFull             = 0x8000,
200         CfgAnegDone             = 0x8000000,
201         CfgFullDuplex           = 0x20000000,
202         CfgSpeed100             = 0x40000000,
203         CfgLink                 = 0x80000000,
204 };
205
206
207 /* Bits in the RxMode register.
208  */
209 enum rx_mode_bits {
210     AcceptErr          = 0x20,
211     AcceptRunt         = 0x10,
212     AcceptBroadcast    = 0xC0000000,
213     AcceptMulticast    = 0x00200000, 
214     AcceptAllMulticast = 0x20000000,
215     AcceptAllPhys      = 0x10000000, 
216     AcceptMyPhys       = 0x08000000,
217     RxFilterEnable     = 0x80000000
218 };
219
220 /* Bits in network_desc.status
221  */
222 enum desc_status_bits {
223     DescOwn   = 0x80000000, 
224     DescMore  = 0x40000000, 
225     DescIntr  = 0x20000000,
226     DescNoCRC = 0x10000000,
227     DescPktOK = 0x08000000, 
228     RxTooLong = 0x00400000
229 };
230
231 /*Bits in Interrupt Mask register
232  */
233 enum Intr_mask_register_bits {
234     RxOk       = 0x001,
235     RxErr      = 0x004,
236     TxOk       = 0x040,
237     TxErr      = 0x100 
238 };      
239
240 /*  EEPROM access , values are devices specific
241  */
242 #define EE_CS           0x08    /* EEPROM chip select */
243 #define EE_SK           0x04    /* EEPROM shift clock */
244 #define EE_DI           0x01    /* Data in */
245 #define EE_DO           0x02    /* Data out */
246
247 /* Offsets within EEPROM (these are word offsets)
248  */
249 #define EE_MAC 7
250 #define EE_REG  EECtrl
251 static uint32_t SavedClkRun;    
252
253 static const uint8_t nat_ee_bits[] = {
254         [SPI_BIT_SCLK]  = EE_SK,
255         [SPI_BIT_MOSI]  = EE_DI,
256         [SPI_BIT_MISO]  = EE_DO,
257         [SPI_BIT_SS(0)] = EE_CS,
258 };
259
260 static int nat_spi_read_bit ( struct bit_basher *basher,
261                               unsigned int bit_id ) {
262         struct natsemi_nic *nat = container_of ( basher, struct natsemi_nic,
263                                                  spibit.basher );
264         uint8_t mask = nat_ee_bits[bit_id];
265         uint8_t eereg;
266
267         eereg = inb ( nat->ioaddr + EE_REG );
268         return ( eereg & mask );
269 }
270
271 static void nat_spi_write_bit ( struct bit_basher *basher,
272                                 unsigned int bit_id, unsigned long data ) {
273         struct natsemi_nic *nat = container_of ( basher, struct natsemi_nic,
274                                                  spibit.basher );
275         uint8_t mask = nat_ee_bits[bit_id];
276         uint8_t eereg;
277
278         eereg = inb ( nat->ioaddr + EE_REG );
279         eereg &= ~mask;
280         eereg |= ( data & mask );
281         outb ( eereg, nat->ioaddr + EE_REG );
282 }
283
284 static struct bit_basher_operations nat_basher_ops = {
285         .read = nat_spi_read_bit,
286         .write = nat_spi_write_bit,
287 };
288
289 /* It looks that this portion of EEPROM can be used for 
290  * non-volatile stored options. Data sheet does not talk about this region.
291  * Currently it is not working. But with some efforts it can.
292  */
293 static struct nvo_fragment nat_nvo_fragments[] = {
294         { 0x0c, 0x68 },
295         { 0, 0 }
296 };
297
298 /*
299  * Set up for EEPROM access
300  *
301  * @v NAT               NATSEMI NIC
302  */
303  void nat_init_eeprom ( struct natsemi_nic *nat ) {
304
305         /* Initialise three-wire bus 
306          */
307         nat->spibit.basher.op = &nat_basher_ops;
308         nat->spibit.bus.mode = SPI_MODE_THREEWIRE;
309         nat->spibit.endianness = SPI_BIT_LITTLE_ENDIAN;
310         init_spi_bit_basher ( &nat->spibit );
311
312         /*natsemi DP 83815 only supports at93c46
313          */
314         init_at93c46 ( &nat->eeprom, 16 );
315         nat->eeprom.bus = &nat->spibit.bus;
316
317         nat->nvo.nvs = &nat->eeprom.nvs;
318         nat->nvo.fragments = nat_nvo_fragments;
319 }
320
321 /*
322  * Reset NIC
323  *
324  * @v           NATSEMI NIC
325  *
326  * Issues a hardware reset and waits for the reset to complete.
327  */
328 static void nat_reset ( struct natsemi_nic *nat ) {
329
330         int i;
331
332         /* Reset chip
333          */
334         outl ( ChipReset, nat->ioaddr + ChipCmd );
335         mdelay ( 10 );
336         nat->tx_dirty = 0;
337         nat->tx_cur = 0;
338         for ( i = 0 ; i < TX_RING_SIZE ; i++ ) {
339                 nat->tx[i].link = 0;
340                 nat->tx[i].cmdsts = 0;
341                 nat->tx[i].bufptr = 0;
342         }
343         nat->rx_cur = 0;
344         outl ( virt_to_bus( &nat->tx[0] ),nat->ioaddr + TxRingPtr );
345         outl ( virt_to_bus( &nat->rx[0] ),nat->ioaddr + RxRingPtr );
346
347         outl ( TxOff|RxOff, nat->ioaddr + ChipCmd );
348
349         /* Restore PME enable bit
350          */
351         outl ( SavedClkRun, nat->ioaddr + ClkRun );
352 }
353
354 static void do_cable_magic ( struct net_device *netdev ) {
355         struct natsemi_nic *nat = netdev->priv;
356         uint16_t data;
357         /*
358          * 100 MBit links with short cables can trip an issue with the chip.
359          * The problem manifests as lots of CRC errors and/or flickering
360          * activity LED while idle.  This process is based on instructions
361          * from engineers at National.
362          */
363         if (inl(nat->ioaddr + ChipConfig) & CfgSpeed100) {
364
365                 outw(1, nat->ioaddr + PGSEL);
366                 /*
367                  * coefficient visibility should already be enabled via
368                  * DSPCFG | 0x1000
369                  */
370                 data = inw(nat->ioaddr + TSTDAT) & 0xff;
371                 /*
372                  * the value must be negative, and within certain values
373                  * (these values all come from National)
374                  */
375                 if (!(data & 0x80) || ((data >= 0xd8) && (data <= 0xff))) {
376
377                         /* the bug has been triggered - fix the coefficient */
378                         outw(TSTDAT_FIXED, nat->ioaddr + TSTDAT);
379                         /* lock the value */
380                         data = inw(nat->ioaddr + DSPCFG);
381                         //np->dspcfg = data | DSPCFG_LOCK;
382                         outw(data | DSPCFG_LOCK , nat->ioaddr + DSPCFG);
383                 }
384                 outw(0, nat->ioaddr + PGSEL);
385         }
386
387 }
388
389 /*
390  * Open NIC
391  *
392  * @v netdev            Net device
393  * @ret rc              Return status code
394  */
395 static int nat_open ( struct net_device *netdev ) {
396         struct natsemi_nic *nat = netdev->priv;
397         int i;
398         uint32_t tx_config,rx_config;
399         
400         /* Disable PME:
401          * The PME bit is initialized from the EEPROM contents.
402          * PCI cards probably have PME disabled, but motherboard
403          * implementations may have PME set to enable WakeOnLan. 
404          * With PME set the chip will scan incoming packets but
405          * nothing will be written to memory. 
406          */
407         SavedClkRun = inl ( nat->ioaddr + ClkRun );
408         outl ( SavedClkRun & ~0x100, nat->ioaddr + ClkRun );
409
410         /* Setting up Mac address in the NIC
411          */
412         for ( i = 0 ; i < ETH_ALEN ; i+=2 ) {
413                 outl ( i,nat->ioaddr + RxFilterAddr );
414                 outw ( netdev->ll_addr[i] + ( netdev->ll_addr[i + 1] << 8 ),
415                        nat->ioaddr + RxFilterData );
416         }
417
418         /*Set up the Tx Ring
419          */
420         nat->tx_cur = 0;
421         nat->tx_dirty = 0;
422         for ( i = 0 ; i < TX_RING_SIZE ; i++ ) {
423                 nat->tx[i].link   = virt_to_bus ( ( i + 1 < TX_RING_SIZE ) ? &nat->tx[i + 1] : &nat->tx[0] );
424                 nat->tx[i].cmdsts = 0;
425                 nat->tx[i].bufptr = 0;
426         }
427
428         /* Set up RX ring
429          */
430         nat->rx_cur = 0;
431         for ( i = 0 ; i < NUM_RX_DESC ; i++ ) {
432                 nat->iobuf[i] = alloc_iob ( RX_BUF_SIZE );
433                 if ( !nat->iobuf[i] )
434                         goto memory_alloc_err;
435                 nat->rx[i].link   = virt_to_bus ( ( i + 1 < NUM_RX_DESC ) ? &nat->rx[i + 1] : &nat->rx[0] );
436                 nat->rx[i].cmdsts = RX_BUF_SIZE;
437                 nat->rx[i].bufptr = virt_to_bus ( nat->iobuf[i]->data );
438         }
439
440         /* load Receive Descriptor Register
441          */
442         outl ( virt_to_bus ( &nat->rx[0] ), nat->ioaddr + RxRingPtr );
443         DBG ( "Natsemi Rx descriptor loaded with: %X\n",
444                 (unsigned int) inl ( nat->ioaddr + RxRingPtr ) );               
445
446         /* setup Tx ring
447          */
448         outl ( virt_to_bus ( &nat->tx[0] ),nat->ioaddr + TxRingPtr );
449         DBG ( "Natsemi Tx descriptor loaded with: %X\n",
450                 (unsigned int)inl ( nat->ioaddr + TxRingPtr ) );
451
452         /* Enables RX
453          */
454         outl ( RxFilterEnable|AcceptBroadcast|AcceptAllMulticast|AcceptMyPhys,
455                  nat->ioaddr + RxFilterAddr );
456
457         /* Initialize other registers. 
458          * Configure the PCI bus bursts and FIFO thresholds. 
459          * Configure for standard, in-spec Ethernet. 
460          */
461         if ( inl ( nat->ioaddr + ChipConfig ) & 0x20000000 ) {  /* Full duplex */
462                 tx_config = 0xD0801002 | 0xC0000000;
463                 DBG ( "Full duplex\n" );
464                 rx_config = 0x10000020 | 0x10000000;
465         } else {
466                 tx_config = 0x10801002 & ~0xC0000000;
467                 DBG ( "Half duplex\n" );
468                 rx_config = 0x0020 & ~0x10000000;
469         }
470         outl ( tx_config, nat->ioaddr + TxConfig );
471         outl ( rx_config, nat->ioaddr + RxConfig );
472
473         /*start the receiver 
474          */
475         outl ( RxOn, nat->ioaddr + ChipCmd );
476         
477         /* lines 1586 linux-natsemi.c uses cable magic 
478          * testing this feature is required or not
479          */
480         do_cable_magic ( netdev ); 
481         
482
483         /* mask the interrupts. note interrupt is not enabled here
484          */
485         return 0;
486                        
487 memory_alloc_err:
488
489         /* this block frees the previously allocated buffers
490          * if memory for all the buffers is not available
491          */
492         i = 0;
493         while ( nat->rx[i].cmdsts == RX_BUF_SIZE ) {
494                 free_iob ( nat->iobuf[i] );
495                 i++;
496         }
497         return -ENOMEM; 
498 }
499
500 /**
501  * Close NIC
502  *
503  * @v netdev            Net device
504  */
505 static void nat_close ( struct net_device *netdev ) {
506         struct natsemi_nic *nat = netdev->priv;
507         int i;
508
509         /* Reset the hardware to disable everything in one go
510          */
511         nat_reset ( nat );
512
513         /* Free RX ring
514          */
515         for ( i = 0; i < NUM_RX_DESC ; i++ ) {
516                 
517                 free_iob ( nat->iobuf[i] );
518         }
519 }
520
521 /** 
522  * Transmit packet
523  *
524  * @v netdev    Network device
525  * @v iobuf     I/O buffer
526  * @ret rc      Return status code
527  */
528 static int nat_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
529         struct natsemi_nic *nat = netdev->priv;
530
531         /* check for space in TX ring
532          */
533         if ( nat->tx[nat->tx_cur].cmdsts != 0 ) {
534                 DBG ( "TX overflow\n" );
535                 return -ENOBUFS;
536         }
537
538         /* to be used in netdev_tx_complete
539          */
540         nat->tx_iobuf[nat->tx_cur] = iobuf;
541
542         /* Pad and align packet has not been used because its not required here
543          * iob_pad ( iobuf, ETH_ZLEN ); can be used to achieve it
544          */
545
546         /* Add to TX ring
547          */
548         DBG ( "TX id %d at %lx + %x\n", nat->tx_cur,
549               virt_to_bus ( &iobuf->data ), iob_len ( iobuf ) );
550
551         nat->tx[nat->tx_cur].bufptr = virt_to_bus ( iobuf->data );
552         nat->tx[nat->tx_cur].cmdsts = iob_len ( iobuf ) | OWN;
553
554         /* increment the circular buffer pointer to the next buffer location
555          */
556         nat->tx_cur = ( nat->tx_cur + 1 ) % TX_RING_SIZE;
557
558         /*start the transmitter 
559          */
560         outl ( TxOn, nat->ioaddr + ChipCmd );
561
562         return 0;
563 }
564
565 /** 
566  * Poll for received packets
567  *
568  * @v netdev    Network device
569  * @v rx_quota  Maximum number of packets to receive
570  */
571 static void nat_poll ( struct net_device *netdev) {
572         struct natsemi_nic *nat = netdev->priv;
573         unsigned int status;
574         unsigned int rx_status;
575         unsigned int intr_status;
576         unsigned int rx_len;
577         struct io_buffer *rx_iob;
578         int i;
579         
580         /* read the interrupt register
581          */
582         intr_status = inl ( nat->ioaddr + IntrStatus );
583         if ( !intr_status )
584                 goto end;
585
586         /* check the status of packets given to card for transmission
587          */     
588         DBG ( "Intr status %X\n",intr_status );
589
590         i = nat->tx_dirty;
591         while ( i!= nat->tx_cur ) {
592                 status = nat->tx[nat->tx_dirty].cmdsts;
593                 DBG ( "value of tx_dirty = %d tx_cur=%d status=%X\n",
594                         nat->tx_dirty,nat->tx_cur,status );
595                 
596                 /* check if current packet has been transmitted or not
597                  */
598                 if ( status & OWN ) 
599                         break;
600
601                 /* Check if any errors in transmission
602                  */
603                 if (! ( status & DescPktOK ) ) {
604                         DBG ( "Error in sending Packet status:%X\n",
605                                         (unsigned int) status );
606                         netdev_tx_complete_err ( netdev,nat->tx_iobuf[nat->tx_dirty],-EINVAL );
607                 } else {
608                         DBG ( "Success in transmitting Packet\n" );
609                         netdev_tx_complete ( netdev,nat->tx_iobuf[nat->tx_dirty] );
610                 }
611
612                 /* setting cmdsts zero, indicating that it can be reused 
613                  */
614                 nat->tx[nat->tx_dirty].cmdsts = 0;
615                 nat->tx_dirty = ( nat->tx_dirty + 1 ) % TX_RING_SIZE;
616                 i = ( i + 1 ) % TX_RING_SIZE;
617         }
618         
619         /* Handle received packets 
620          */
621         rx_status = (unsigned int) nat->rx[nat->rx_cur].cmdsts; 
622         while ( ( rx_status & OWN ) ) {
623                 rx_len = ( rx_status & DSIZE ) - CRC_SIZE;
624
625                 /*check for the corrupt packet 
626                  */
627                 if ( ( rx_status & ( DescMore|DescPktOK|RxTooLong ) ) != DescPktOK) {
628                          DBG ( "natsemi_poll: Corrupted packet received, "
629                                         "buffer status = %X ^ %X \n",rx_status,
630                                         (unsigned int) nat->rx[nat->rx_cur].cmdsts );
631                          netdev_rx_err ( netdev,NULL,-EINVAL );
632                 } else  {
633                         rx_iob = alloc_iob ( rx_len );
634
635                         if ( !rx_iob ) 
636                                 /* leave packet for next call to poll
637                                  */
638                                 goto end;
639                         memcpy ( iob_put ( rx_iob,rx_len ),
640                                         nat->iobuf[nat->rx_cur]->data,rx_len );
641                         DBG ( "received packet\n" );
642
643                         /* add to the receive queue. 
644                          */
645                         netdev_rx ( netdev,rx_iob );
646                 }
647                 nat->rx[nat->rx_cur].cmdsts = RX_BUF_SIZE;
648                 nat->rx_cur = ( nat->rx_cur + 1 ) % NUM_RX_DESC;
649                 rx_status = nat->rx[nat->rx_cur].cmdsts; 
650         }
651 end:
652
653         /* re-enable the potentially idle receive state machine 
654          */
655         outl ( RxOn, nat->ioaddr + ChipCmd );   
656 }                               
657
658 /**
659  * Enable/disable interrupts
660  *
661  * @v netdev    Network device
662  * @v enable    Interrupts should be enabled
663  */
664 static void nat_irq ( struct net_device *netdev, int enable ) {
665         struct natsemi_nic *nat = netdev->priv;
666
667         outl ( ( enable ? ( RxOk|RxErr|TxOk|TxErr ) :0 ),
668                 nat->ioaddr + IntrMask); 
669         outl ( ( enable ? 1:0 ),nat->ioaddr + IntrEnable );
670 }
671
672
673
674
675
676 /** natsemi net device operations */
677 static struct net_device_operations nat_operations = {
678         .open           = nat_open,
679         .close          = nat_close,
680         .transmit       = nat_transmit,
681         .poll           = nat_poll,
682         .irq            = nat_irq,
683 };
684
685 /*
686  * Probe PCI device
687  *
688  * @v pci       PCI device
689  * @v id        PCI ID
690  * @ret rc      Return status code
691  */
692 static int nat_probe ( struct pci_device *pci,
693                        const struct pci_device_id *id __unused ) {
694         struct net_device *netdev;
695         struct natsemi_nic *nat = NULL;
696         int rc;
697         int i;
698         uint8_t ll_addr_encoded[MAX_LL_ADDR_LEN];
699         uint8_t last = 0;
700         uint8_t last1 = 0;
701         uint8_t prev_bytes[2];
702
703         /* Allocate net device 
704          */
705         netdev = alloc_etherdev ( sizeof ( *nat ) );
706         if ( ! netdev ) 
707                 return -ENOMEM;
708         netdev_init ( netdev,&nat_operations );
709         nat = netdev->priv;
710         pci_set_drvdata ( pci, netdev );
711         netdev->dev = &pci->dev;
712         memset ( nat, 0, sizeof ( *nat ) );
713         nat->ioaddr = pci->ioaddr;
714
715         /* Fix up PCI device
716          */
717         adjust_pci_device ( pci );
718
719         /* Reset the NIC, set up EEPROM access and read MAC address
720          */
721         nat_reset ( nat );
722         nat_init_eeprom ( nat );
723         nvs_read ( &nat->eeprom.nvs, EE_MAC-1, prev_bytes, 1 );
724         nvs_read ( &nat->eeprom.nvs, EE_MAC, ll_addr_encoded, ETH_ALEN );
725
726         /* decoding the MAC address read from NVS 
727          * and save it in netdev->ll_addr
728          */
729         last = prev_bytes[1] >> 7;
730         for ( i = 0 ; i < ETH_ALEN ; i++ ) {
731                 last1 = ll_addr_encoded[i] >> 7;
732                 netdev->ll_addr[i] = ll_addr_encoded[i] << 1 | last;
733                 last = last1;
734         }
735
736         /* Register network device
737          */
738         if ( ( rc = register_netdev ( netdev ) ) != 0 )
739                 goto err_register_netdev;
740
741         return 0;
742
743 err_register_netdev:
744
745         /* Disable NIC
746          */
747         nat_reset ( nat );
748
749         /* Free net device
750          */
751         netdev_put ( netdev );
752         return rc;
753 }
754
755 /**
756  * Remove PCI device
757  *
758  * @v pci       PCI device
759  */
760 static void nat_remove ( struct pci_device *pci ) {
761         struct net_device *netdev = pci_get_drvdata ( pci );
762         struct natsemi_nic *nat = netdev->priv;
763  
764         if ( nat->nvo.nvs )
765                 nvo_unregister ( &nat->nvo );
766                 
767         unregister_netdev ( netdev );
768         nat_reset ( nat );
769         netdev_put ( netdev );
770 }
771
772 static struct pci_device_id natsemi_nics[] = {
773         PCI_ROM(0x100b, 0x0020, "dp83815", "DP83815"),
774 };
775
776 struct pci_driver natsemi_driver __pci_driver = {
777         .ids = natsemi_nics,
778         .id_count = ( sizeof ( natsemi_nics ) / sizeof ( natsemi_nics[0] ) ),
779         .probe = nat_probe,
780         .remove = nat_remove,
781 };