interrupt in natsemi
[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                                  Added a circular buffer for transmit and receive.
54                                  transmit routine will not wait for transmission to finish
55                                  poll routine deals with it.
56
57   13 Dec 2003 timlegge          1.1 Enabled Multicast Support
58   29 May 2001  mdc              1.0
59      Initial Release.           Tested with Netgear FA311 and FA312 boards
60 */
61  
62
63
64
65 #include <stdint.h>
66 #include <stdlib.h>
67 #include <stdio.h>
68 #include <io.h>
69 #include <errno.h>
70 #include <timer.h>
71 #include <byteswap.h>
72 #include <gpxe/pci.h>
73 #include <gpxe/if_ether.h>
74 #include <gpxe/ethernet.h>
75 #include <gpxe/iobuf.h>
76 #include <gpxe/netdevice.h>
77 #include <gpxe/spi_bit.h>
78 #include <gpxe/threewire.h>
79 #include <gpxe/nvo.h>
80
81 #define TX_RING_SIZE 4
82 #define NUM_RX_DESC  4
83 #define RX_BUF_SIZE 1536
84 #define OWN       0x80000000
85 #define DSIZE     0x00000FFF
86 #define CRC_SIZE  4
87
88 struct natsemi_tx {
89         uint32_t link;
90         uint32_t cmdsts;
91         uint32_t bufptr;
92 };
93
94 struct natsemi_rx {
95         uint32_t link;
96         uint32_t cmdsts;
97         uint32_t bufptr;
98 };
99
100 struct natsemi_nic {
101         unsigned short ioaddr;
102         unsigned short tx_cur;
103         unsigned short tx_dirty;
104         unsigned short rx_cur;
105         struct natsemi_tx tx[TX_RING_SIZE];
106         struct natsemi_rx rx[NUM_RX_DESC];
107         /* need to add iobuf as we cannot free iobuf->data in close without this 
108          * alternatively substracting sizeof(head) and sizeof(list_head) can also 
109          * give the same.*/
110         struct io_buffer *iobuf[NUM_RX_DESC];
111         /*netdev_tx_complete needs pointer to the iobuf of the data so as to free 
112           it from the memory.*/
113         struct io_buffer *tx_iobuf[TX_RING_SIZE];
114         struct spi_bit_basher spibit;
115         struct spi_device eeprom;
116         struct nvo_block nvo;
117 };
118
119
120 /* NATSEMI: Offsets to the device registers.
121    Unlike software-only systems, device drivers interact with complex hardware.
122    It's not useful to define symbolic names for every register bit in the
123    device.
124 */
125 enum register_offsets {
126     ChipCmd      = 0x00, 
127     ChipConfig   = 0x04, 
128     EECtrl       = 0x08, 
129     PCIBusCfg    = 0x0C,
130     IntrStatus   = 0x10, 
131     IntrMask     = 0x14, 
132     IntrEnable   = 0x18,
133     TxRingPtr    = 0x20, 
134     TxConfig     = 0x24,
135     RxRingPtr    = 0x30,
136     RxConfig     = 0x34, 
137     ClkRun       = 0x3C,
138     WOLCmd       = 0x40, 
139     PauseCmd     = 0x44,
140     RxFilterAddr = 0x48, 
141     RxFilterData = 0x4C,
142     BootRomAddr  = 0x50, 
143     BootRomData  = 0x54, 
144     SiliconRev   = 0x58, 
145     StatsCtrl    = 0x5C,
146     StatsData    = 0x60, 
147     RxPktErrs    = 0x60, 
148     RxMissed     = 0x68, 
149     RxCRCErrs    = 0x64,
150     PCIPM        = 0x44,
151     PhyStatus    = 0xC0, 
152     MIntrCtrl    = 0xC4, 
153     MIntrStatus  = 0xC8,
154
155     /* These are from the spec, around page 78... on a separate table. */
156     PGSEL        = 0xCC, 
157     PMDCSR       = 0xE4, 
158     TSTDAT       = 0xFC, 
159     DSPCFG       = 0xF4, 
160     SDCFG        = 0x8C,
161     BasicControl = 0x80,        
162     BasicStatus  = 0x84
163             
164 };
165
166
167
168
169 /* Bit in ChipCmd. */
170 enum ChipCmdBits {
171     ChipReset = 0x100, 
172     RxReset   = 0x20, 
173     TxReset   = 0x10, 
174     RxOff     = 0x08, 
175     RxOn      = 0x04,
176     TxOff     = 0x02, 
177     TxOn      = 0x01
178 };
179
180
181 /* Bits in the RxMode register. */
182 enum rx_mode_bits {
183     AcceptErr          = 0x20,
184     AcceptRunt         = 0x10,
185     AcceptBroadcast    = 0xC0000000,
186     AcceptMulticast    = 0x00200000, 
187     AcceptAllMulticast = 0x20000000,
188     AcceptAllPhys      = 0x10000000, 
189     AcceptMyPhys       = 0x08000000,
190     RxFilterEnable     = 0x80000000
191 };
192
193 /* Bits in network_desc.status */
194 enum desc_status_bits {
195     DescOwn   = 0x80000000, 
196     DescMore  = 0x40000000, 
197     DescIntr  = 0x20000000,
198     DescNoCRC = 0x10000000,
199     DescPktOK = 0x08000000, 
200     RxTooLong = 0x00400000
201 };
202
203 /*Bits in Interrupt Mask register */
204
205 enum Intr_mask_register_bits {
206     RxOk       = 0x001,
207     RxErr      = 0x004,
208     TxOk       = 0x040,
209     TxErr      = 0x100 
210 };      
211
212
213 /*  EEPROM access , values are devices specific*/
214 #define EE_CS           0x08    /* EEPROM chip select */
215 #define EE_SK           0x04    /* EEPROM shift clock */
216 #define EE_DI           0x01    /* Data in */
217 #define EE_DO           0x02    /* Data out */
218
219 /* Offsets within EEPROM (these are word offsets) */
220 #define EE_MAC 7
221 #define EE_REG  EECtrl
222 static uint32_t SavedClkRun;    
223
224
225 static const uint8_t nat_ee_bits[] = {
226         [SPI_BIT_SCLK]  = EE_SK,
227         [SPI_BIT_MOSI]  = EE_DI,
228         [SPI_BIT_MISO]  = EE_DO,
229         [SPI_BIT_SS(0)] = EE_CS,
230 };
231
232 static int nat_spi_read_bit ( struct bit_basher *basher,
233                               unsigned int bit_id ) {
234         struct natsemi_nic *nat = container_of ( basher, struct natsemi_nic,
235                                                  spibit.basher );
236         uint8_t mask = nat_ee_bits[bit_id];
237         uint8_t eereg;
238
239         eereg = inb ( nat->ioaddr + EE_REG);
240         return ( eereg & mask );
241 }
242
243 static void nat_spi_write_bit ( struct bit_basher *basher,
244                                 unsigned int bit_id, unsigned long data ) {
245         struct natsemi_nic *nat = container_of ( basher, struct natsemi_nic,
246                                                  spibit.basher );
247         uint8_t mask = nat_ee_bits[bit_id];
248         uint8_t eereg;
249
250         eereg = inb ( nat->ioaddr + EE_REG );
251         eereg &= ~mask;
252         eereg |= ( data & mask );
253         outb ( eereg, nat->ioaddr + EE_REG);
254 }
255
256 static struct bit_basher_operations nat_basher_ops = {
257         .read = nat_spi_read_bit,
258         .write = nat_spi_write_bit,
259 };
260 /** Portion of EEPROM available for non-volatile stored options
261  *
262  * We use offset 0x40 (i.e. address 0x20), length 0x40.  This block is
263  * marked as VPD in the rtl8139 datasheets, so we use it only if we
264  * detect that the card is not supporting VPD.
265  */
266 static struct nvo_fragment nat_nvo_fragments[] = {
267         { 0x0c, 0x40 },
268         { 0, 0 }
269 };
270
271 /**
272  * Set up for EEPROM access
273  *
274  * @v NAT               NATSEMI NIC
275  */
276  void nat_init_eeprom ( struct natsemi_nic *nat ) {
277
278         // Initialise three-wire bus 
279         nat->spibit.basher.op = &nat_basher_ops;
280         nat->spibit.bus.mode = SPI_MODE_THREEWIRE;
281         nat->spibit.endianness = SPI_BIT_LITTLE_ENDIAN;
282         init_spi_bit_basher ( &nat->spibit );
283
284         /*natsemi DP 83815 only supports at93c46 */
285         init_at93c46 ( &nat->eeprom, 16 );
286         nat->eeprom.bus = &nat->spibit.bus;
287
288                 nat->nvo.nvs = &nat->eeprom.nvs;
289                 nat->nvo.fragments = nat_nvo_fragments;
290 }
291
292 /**
293  * Reset NIC
294  *
295  * @v           NATSEMI NIC
296  *
297  * Issues a hardware reset and waits for the reset to complete.
298  */
299 static void nat_reset ( struct natsemi_nic *nat ) {
300
301         int i;
302         /* Reset chip */
303         outl ( ChipReset, nat->ioaddr + ChipCmd );
304         mdelay ( 10 );
305         nat->tx_dirty=0;
306         nat->tx_cur=0;
307         for(i=0;i<TX_RING_SIZE;i++)
308         {
309                 nat->tx[i].link=0;
310                 nat->tx[i].cmdsts=0;
311                 nat->tx[i].bufptr=0;
312         }
313         nat->rx_cur = 0;
314         outl(virt_to_bus(&nat->tx[0]),nat->ioaddr+TxRingPtr);
315         outl(virt_to_bus(&nat->rx[0]), nat->ioaddr + RxRingPtr);
316
317         outl(TxOff|RxOff, nat->ioaddr + ChipCmd);
318
319         /* Restore PME enable bit */
320         outl(SavedClkRun, nat->ioaddr + ClkRun);
321 }
322
323 /**
324  * Open NIC
325  *
326  * @v netdev            Net device
327  * @ret rc              Return status code
328  */
329 static int nat_open ( struct net_device *netdev ) {
330         struct natsemi_nic *nat = netdev->priv;
331         int i;
332         uint32_t tx_config,rx_config;
333         
334         /* Disable PME:
335         * The PME bit is initialized from the EEPROM contents.
336         * PCI cards probably have PME disabled, but motherboard
337         * implementations may have PME set to enable WakeOnLan. 
338         * With PME set the chip will scan incoming packets but
339         * nothing will be written to memory. */
340         SavedClkRun = inl(nat->ioaddr + ClkRun);
341         outl(SavedClkRun & ~0x100, nat->ioaddr + ClkRun);
342
343                 
344
345
346          uint8_t last=0;
347          uint8_t last1=0;
348          for ( i = 0 ; i < ETH_ALEN ; i+=2 )
349          {
350                 outl(i,nat->ioaddr+RxFilterAddr);
351                 last1=netdev->ll_addr[i]>>7;
352                 netdev->ll_addr[i]=netdev->ll_addr[i]<<1|last;
353                 last=(netdev->ll_addr[i+1]>>7);
354                 netdev->ll_addr[i+1]=(netdev->ll_addr[i+1]<<1)+last1;
355
356                 outw ( netdev->ll_addr[i] + (netdev->ll_addr[i+1]<<8), nat->ioaddr +RxFilterData);
357         }
358        
359
360
361         /*Set up the Tx Ring */
362         nat->tx_cur=0;
363         nat->tx_dirty=0;
364         for (i=0;i<TX_RING_SIZE;i++)
365         {
366                 nat->tx[i].link   = virt_to_bus((i+1 < TX_RING_SIZE) ? &nat->tx[i+1] : &nat->tx[0]);
367                 nat->tx[i].cmdsts = 0;
368                 nat->tx[i].bufptr = 0;
369         }
370
371
372
373
374
375         /* Set up RX ring */
376         nat->rx_cur=0;
377         for (i=0;i<NUM_RX_DESC;i++)
378         {
379
380                 nat->iobuf[i] = alloc_iob ( RX_BUF_SIZE );
381                 if (!nat->iobuf[i])
382                        return -ENOMEM;  
383                 nat->rx[i].link   = virt_to_bus((i+1 < NUM_RX_DESC) ? &nat->rx[i+1] : &nat->rx[0]);
384                 nat->rx[i].cmdsts = (uint32_t) RX_BUF_SIZE;
385                 nat->rx[i].bufptr = virt_to_bus(nat->iobuf[i]->data);
386         }
387
388
389          /* load Receive Descriptor Register */
390         outl(virt_to_bus(&nat->rx[0]), nat->ioaddr + RxRingPtr);
391         DBG("Natsemi Rx descriptor loaded with: %X\n",(unsigned int)inl(nat->ioaddr+RxRingPtr));                
392
393         /* setup Tx ring */
394         outl(virt_to_bus(&nat->tx[0]),nat->ioaddr+TxRingPtr);
395         DBG("Natsemi Tx descriptor loaded with: %X\n",(unsigned int)inl(nat->ioaddr+TxRingPtr));
396
397         /* Enables RX */
398         outl(RxFilterEnable|AcceptBroadcast|AcceptAllMulticast|AcceptMyPhys, nat->ioaddr+RxFilterAddr);
399
400         /* Initialize other registers. */
401         /* Configure the PCI bus bursts and FIFO thresholds. */
402         /* Configure for standard, in-spec Ethernet. */
403         if (inl(nat->ioaddr + ChipConfig) & 0x20000000) {       /* Full duplex */
404                 tx_config = 0xD0801002;
405                 rx_config = 0x10000020;
406         } else {
407                 tx_config = 0x10801002;
408                 rx_config = 0x0020;
409         }
410         outl(tx_config, nat->ioaddr + TxConfig);
411         outl(rx_config, nat->ioaddr + RxConfig);
412
413
414
415         /*start the receiver  */
416         outl(RxOn, nat->ioaddr + ChipCmd);
417
418         /*enable interrupts*/
419         outl((RxOk|RxErr|TxOk|TxErr),nat->ioaddr + IntrMask); 
420         outl(1,nat->ioaddr +IntrEnable);
421
422
423
424
425         return 0;
426 }
427
428 /**
429  * Close NIC
430  *
431  * @v netdev            Net device
432  */
433 static void nat_close ( struct net_device *netdev ) {
434         struct natsemi_nic *nat = netdev->priv;
435         int i;
436
437
438         /* Reset the hardware to disable everything in one go */
439         nat_reset ( nat );
440
441         /* Free RX ring */
442         for (i=0;i<NUM_RX_DESC;i++)
443         {
444                 
445                 free_iob( nat->iobuf[i] );
446         }
447         /* disable interrupts */
448         outl(0,nat->ioaddr + IntrMask) ;
449 }
450
451 /** 
452  * Transmit packet
453  *
454  * @v netdev    Network device
455  * @v iobuf     I/O buffer
456  * @ret rc      Return status code
457  */
458 static int nat_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
459         struct natsemi_nic *nat = netdev->priv;
460
461        /* check for space in TX ring */
462
463         if (nat->tx[nat->tx_cur].cmdsts !=0)
464         {
465                 printf ( "TX overflow\n" );
466                 return -ENOBUFS;
467         }
468
469         /* to be used in netdev_tx_complete*/
470         nat->tx_iobuf[nat->tx_cur]=iobuf;
471
472         /* Pad and align packet */
473         iob_pad ( iobuf, ETH_ZLEN );
474
475         /* Add to TX ring */
476         DBG ( "TX id %d at %lx+%x\n", nat->tx_cur,
477               virt_to_bus ( &iobuf->data ), iob_len ( iobuf ) );
478
479         nat->tx[nat->tx_cur].bufptr = virt_to_bus(iobuf->data);
480         nat->tx[nat->tx_cur].cmdsts= (uint32_t) iob_len(iobuf)|OWN;
481
482
483         nat->tx_cur=(nat->tx_cur+1) % TX_RING_SIZE;
484
485         /*start the transmitter  */
486         outl(TxOn, nat->ioaddr + ChipCmd);
487
488         return 0;
489 }
490
491 /** 
492  * Poll for received packets
493  *
494  * @v netdev    Network device
495  * @v rx_quota  Maximum number of packets to receive
496  */
497 static void nat_poll ( struct net_device *netdev, unsigned int rx_quota ) {
498         struct natsemi_nic *nat = netdev->priv;
499         unsigned int status;
500         unsigned int rx_status;
501         unsigned int intr_status;
502         unsigned int rx_len;
503         struct io_buffer *rx_iob;
504         int i;
505         
506         outl(1,nat->ioaddr +IntrEnable);
507         /* read the interrupt register */
508         intr_status=inl(nat->ioaddr+IntrStatus);
509         if(!intr_status)
510         goto end;
511
512         /* check the status of packets given to card for transmission */        
513         DBG("Intr status %X\n",intr_status);
514
515
516         i=nat->tx_dirty;
517         while(i!=nat->tx_cur)
518         {
519                 status=nat->tx[nat->tx_dirty].cmdsts;
520                 DBG("value of tx_dirty = %d tx_cur=%d status=%X\n",
521                         nat->tx_dirty,nat->tx_cur,status);
522                 
523                 /* check if current packet has been transmitted or not */
524                 if(status & OWN) 
525                         break;
526                 /* Check if any errors in transmission */
527                 if (! (status & DescPktOK))
528                 {
529                         printf("Error in sending Packet status:%X\n",
530                                         (unsigned int)status);
531                 }
532                 else
533                 {
534                         DBG("Success in transmitting Packet with data\n");
535                 //      DBG_HD(&nat->tx[nat->tx_dirty].bufptr,130);
536                 }
537                 netdev_tx_complete(netdev,nat->tx_iobuf[nat->tx_dirty]);
538                 /* setting cmdsts zero, indicating that it can be reused */
539                 nat->tx[nat->tx_dirty].cmdsts=0;
540                 nat->tx_dirty=(nat->tx_dirty +1) % TX_RING_SIZE;
541                 i=(i+1) % TX_RING_SIZE;
542
543         }
544                         
545         
546         rx_status=(unsigned int)nat->rx[nat->rx_cur].cmdsts; 
547         /* Handle received packets */
548         while (rx_quota && (rx_status & OWN))
549         {
550                 rx_len= (rx_status & DSIZE) - CRC_SIZE;
551
552                 /*check for the corrupt packet */
553                 if((rx_status & (DescMore|DescPktOK|RxTooLong)) != DescPktOK)
554                 {
555                          printf("natsemi_poll: Corrupted packet received, "
556                                         "buffer status = %X ^ %X \n",rx_status,
557                                         (unsigned int) nat->rx[nat->rx_cur].cmdsts);
558                 }
559                 else
560                 {
561                         rx_iob = alloc_iob(rx_len);
562                         if(!rx_iob) 
563                                 /* leave packet for next call to poll*/
564                                 goto end;
565                         memcpy(iob_put(rx_iob,rx_len),
566                                         bus_to_virt(nat->rx[nat->rx_cur].bufptr),rx_len);
567
568                         DBG("received packet\n");
569                         /* add to the receive queue. */
570                         netdev_rx(netdev,rx_iob);
571                         rx_quota--;
572                 }
573                 nat->rx[nat->rx_cur].cmdsts = RX_BUF_SIZE;
574                 nat->rx_cur=(nat->rx_cur+1) % NUM_RX_DESC;
575                 rx_status=(unsigned int)nat->rx[nat->rx_cur].cmdsts; 
576         }
577
578 end:
579
580          /* re-enable the potentially idle receive state machine */
581         outl(RxOn, nat->ioaddr + ChipCmd);      
582         outl(1,nat->ioaddr +IntrEnable);
583 }                               
584
585
586
587
588
589
590 /**
591  * Probe PCI device
592  *
593  * @v pci       PCI device
594  * @v id        PCI ID
595  * @ret rc      Return status code
596  */
597 static int nat_probe ( struct pci_device *pci,
598                        const struct pci_device_id *id __unused ) {
599         struct net_device *netdev;
600         struct natsemi_nic *nat = NULL;
601         int registered_netdev = 0;
602         int rc;
603         uint32_t advertising;
604
605         /* Fix up PCI device */
606         adjust_pci_device ( pci );
607
608         /* Allocate net device */
609         netdev = alloc_etherdev ( sizeof ( *nat ) );
610         if ( ! netdev ) {
611                 rc = -ENOMEM;
612                 goto err;
613         }
614         nat = netdev->priv;
615         pci_set_drvdata ( pci, netdev );
616         netdev->dev = &pci->dev;
617         memset ( nat, 0, sizeof ( *nat ) );
618         nat->ioaddr = pci->ioaddr;
619
620         /* Reset the NIC, set up EEPROM access and read MAC address */
621         nat_reset ( nat );
622         nat_init_eeprom ( nat );
623         nvs_read ( &nat->eeprom.nvs, EE_MAC, netdev->ll_addr, ETH_ALEN );
624         uint8_t  eetest[128];   
625         nvs_read ( &nat->eeprom.nvs, 0, eetest,128 );
626         
627
628         /* mdio routine of etherboot-5.4.0 natsemi driver has been removed and 
629          * statement to read from MII transceiver control section is used directly
630          */
631
632         advertising = inl(nat->ioaddr + 0x80 + (4<<2)) & 0xffff; 
633         {
634                 uint32_t chip_config = inl(nat->ioaddr + ChipConfig);
635                 DBG("%s: Transceiver default autoneg. %s 10 %s %s duplex.\n",
636                 pci->driver_name,
637                 chip_config & 0x2000 ? "enabled, advertise" : "disabled, force",
638                 chip_config & 0x4000 ? "0" : "",
639                 chip_config & 0x8000 ? "full" : "half");
640         }
641         DBG("%s: Transceiver status %hX advertising %hX\n",pci->driver_name, (int)inl(nat->ioaddr + 0x84),(unsigned int) advertising);
642
643
644
645
646
647         /* Point to NIC specific routines */
648         netdev->open     = nat_open;
649         netdev->close    = nat_close;
650         netdev->transmit = nat_transmit;
651         netdev->poll     = nat_poll;
652
653         /* Register network device */
654         if ( ( rc = register_netdev ( netdev ) ) != 0 )
655                 goto err;
656         registered_netdev = 1;
657
658         /* Register non-volatile storagei
659          * uncomment lines below in final version*/
660         
661          if ( nat->nvo.nvs ) {
662                 if ( ( rc = nvo_register ( &nat->nvo ) ) != 0 )
663                         goto err;
664         }
665         
666
667         return 0;
668
669  err:
670         /* Disable NIC */
671         if ( nat )
672                 nat_reset ( nat );
673         if ( registered_netdev )
674                 unregister_netdev ( netdev );
675         /* Free net device */
676         netdev_put ( netdev );
677         return rc;
678 }
679
680 /**
681  * Remove PCI device
682  *
683  * @v pci       PCI device
684  */
685 static void nat_remove ( struct pci_device *pci ) {
686         struct net_device *netdev = pci_get_drvdata ( pci );
687         struct natsemi_nic *nat = netdev->priv;
688  
689         if ( nat->nvo.nvs )
690                 nvo_unregister ( &nat->nvo );
691                 
692         unregister_netdev ( netdev );
693         nat_reset ( nat );
694         netdev_put ( netdev );
695 }
696
697 static struct pci_device_id natsemi_nics[] = {
698         PCI_ROM(0x100b, 0x0020, "dp83815", "DP83815"),
699
700 };
701
702 struct pci_driver natsemi_driver __pci_driver = {
703         .ids = natsemi_nics,
704         .id_count = ( sizeof ( natsemi_nics ) / sizeof ( natsemi_nics[0] ) ),
705         .probe = nat_probe,
706         .remove = nat_remove,
707 };