Merge branch 'master' of git://github.com/illumos/illumos-gate
[unleashed.git] / usr / src / grub / grub-0.97 / netboot / natsemi.c
blob9e2e22f4ef83f778b482e0ee3d89596e124a5e9d
1 /* -*- Mode:C; c-basic-offset:4; -*- */
3 /*
4 natsemi.c: An Etherboot driver for the NatSemi DP8381x series.
6 Copyright (C) 2001 Entity Cyber, Inc.
8 This development of this Etherboot driver was funded by
10 Sicom Systems: http://www.sicompos.com/
12 Author: Marty Connor (mdc@thinguin.org)
13 Adapted from a Linux driver which was written by Donald Becker
15 This software may be used and distributed according to the terms
16 of the GNU Public License (GPL), incorporated herein by reference.
18 Original Copyright Notice:
20 Written/copyright 1999-2001 by Donald Becker.
22 This software may be used and distributed according to the terms of
23 the GNU General Public License (GPL), incorporated herein by reference.
24 Drivers based on or derived from this code fall under the GPL and must
25 retain the authorship, copyright and license notice. This file is not
26 a complete program and may only be used when the entire operating
27 system is licensed under the GPL. License for under other terms may be
28 available. Contact the original author for details.
30 The original author may be reached as becker@scyld.com, or at
31 Scyld Computing Corporation
32 410 Severn Ave., Suite 210
33 Annapolis MD 21403
35 Support information and updates available at
36 http://www.scyld.com/network/netsemi.html
38 References:
40 http://www.scyld.com/expert/100mbps.html
41 http://www.scyld.com/expert/NWay.html
42 Datasheet is available from:
43 http://www.national.com/pf/DP/DP83815.html
47 /* Revision History */
50 13 Dec 2003 timlegge 1.1 Enabled Multicast Support
51 29 May 2001 mdc 1.0
52 Initial Release. Tested with Netgear FA311 and FA312 boards
54 /* Includes */
56 #include "etherboot.h"
57 #include "nic.h"
58 #include "pci.h"
60 /* defines */
62 #define OWN 0x80000000
63 #define DSIZE 0x00000FFF
64 #define CRC_SIZE 4
66 /* Time in ticks before concluding the transmitter is hung. */
67 #define TX_TIMEOUT (4*TICKS_PER_SEC)
69 #define TX_BUF_SIZE 1536
70 #define RX_BUF_SIZE 1536
72 #define NUM_RX_DESC 4 /* Number of Rx descriptor registers. */
74 typedef uint8_t u8;
75 typedef int8_t s8;
76 typedef uint16_t u16;
77 typedef int16_t s16;
78 typedef uint32_t u32;
79 typedef int32_t s32;
81 /* helpful macroes if on a big_endian machine for changing byte order.
82 not strictly needed on Intel */
83 #define get_unaligned(ptr) (*(ptr))
84 #define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
85 #define get_u16(ptr) (*(u16 *)(ptr))
86 #define virt_to_le32desc(addr) virt_to_bus(addr)
88 enum pcistuff {
89 PCI_USES_IO = 0x01,
90 PCI_USES_MEM = 0x02,
91 PCI_USES_MASTER = 0x04,
92 PCI_ADDR0 = 0x08,
93 PCI_ADDR1 = 0x10,
96 /* MMIO operations required */
97 #define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_MEM | PCI_ADDR1)
99 /* Offsets to the device registers.
100 Unlike software-only systems, device drivers interact with complex hardware.
101 It's not useful to define symbolic names for every register bit in the
102 device.
104 enum register_offsets {
105 ChipCmd = 0x00,
106 ChipConfig = 0x04,
107 EECtrl = 0x08,
108 PCIBusCfg = 0x0C,
109 IntrStatus = 0x10,
110 IntrMask = 0x14,
111 IntrEnable = 0x18,
112 TxRingPtr = 0x20,
113 TxConfig = 0x24,
114 RxRingPtr = 0x30,
115 RxConfig = 0x34,
116 ClkRun = 0x3C,
117 WOLCmd = 0x40,
118 PauseCmd = 0x44,
119 RxFilterAddr = 0x48,
120 RxFilterData = 0x4C,
121 BootRomAddr = 0x50,
122 BootRomData = 0x54,
123 SiliconRev = 0x58,
124 StatsCtrl = 0x5C,
125 StatsData = 0x60,
126 RxPktErrs = 0x60,
127 RxMissed = 0x68,
128 RxCRCErrs = 0x64,
129 PCIPM = 0x44,
130 PhyStatus = 0xC0,
131 MIntrCtrl = 0xC4,
132 MIntrStatus = 0xC8,
134 /* These are from the spec, around page 78... on a separate table. */
135 PGSEL = 0xCC,
136 PMDCSR = 0xE4,
137 TSTDAT = 0xFC,
138 DSPCFG = 0xF4,
139 SDCFG = 0x8C
142 /* Bit in ChipCmd. */
143 enum ChipCmdBits {
144 ChipReset = 0x100,
145 RxReset = 0x20,
146 TxReset = 0x10,
147 RxOff = 0x08,
148 RxOn = 0x04,
149 TxOff = 0x02,
150 TxOn = 0x01
153 /* Bits in the RxMode register. */
154 enum rx_mode_bits {
155 AcceptErr = 0x20,
156 AcceptRunt = 0x10,
157 AcceptBroadcast = 0xC0000000,
158 AcceptMulticast = 0x00200000,
159 AcceptAllMulticast = 0x20000000,
160 AcceptAllPhys = 0x10000000,
161 AcceptMyPhys = 0x08000000,
162 RxFilterEnable = 0x80000000
165 typedef struct _BufferDesc {
166 u32 link;
167 volatile u32 cmdsts;
168 u32 bufptr;
169 u32 software_use;
170 } BufferDesc;
172 /* Bits in network_desc.status */
173 enum desc_status_bits {
174 DescOwn = 0x80000000,
175 DescMore = 0x40000000,
176 DescIntr = 0x20000000,
177 DescNoCRC = 0x10000000,
178 DescPktOK = 0x08000000,
179 RxTooLong = 0x00400000
182 /* Globals */
184 static int natsemi_debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */
186 const char *nic_name;
188 static u32 SavedClkRun;
191 static unsigned short vendor, dev_id;
192 static unsigned long ioaddr;
194 static unsigned int cur_rx;
196 static unsigned int advertising;
198 static unsigned int rx_config;
199 static unsigned int tx_config;
201 /* Note: transmit and receive buffers and descriptors must be
202 longword aligned
205 static BufferDesc txd __attribute__ ((aligned(4)));
206 static BufferDesc rxd[NUM_RX_DESC] __attribute__ ((aligned(4)));
208 static unsigned char txb[TX_BUF_SIZE] __attribute__ ((aligned(4)));
209 static unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE] __attribute__ ((aligned(4)));
211 /* Function Prototypes */
213 static int natsemi_probe(struct dev *dev, struct pci_device *pci);
214 static int eeprom_read(long addr, int location);
215 static int mdio_read(int phy_id, int location);
216 static void natsemi_init(struct nic *nic);
217 static void natsemi_reset(struct nic *nic);
218 static void natsemi_init_rxfilter(struct nic *nic);
219 static void natsemi_init_txd(struct nic *nic);
220 static void natsemi_init_rxd(struct nic *nic);
221 static void natsemi_set_rx_mode(struct nic *nic);
222 static void natsemi_check_duplex(struct nic *nic);
223 static void natsemi_transmit(struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p);
224 static int natsemi_poll(struct nic *nic, int retrieve);
225 static void natsemi_disable(struct dev *dev);
226 static void natsemi_irq(struct nic *nic, irq_action_t action);
229 * Function: natsemi_probe
231 * Description: Retrieves the MAC address of the card, and sets up some
232 * globals required by other routines, and initializes the NIC, making it
233 * ready to send and receive packets.
235 * Side effects:
236 * leaves the ioaddress of the natsemi chip in the variable ioaddr.
237 * leaves the natsemi initialized, and ready to recieve packets.
239 * Returns: struct nic *: pointer to NIC data structure
242 static int
243 natsemi_probe(struct dev *dev, struct pci_device *pci)
245 struct nic *nic = (struct nic *)dev;
246 int i;
247 int prev_eedata;
248 u32 tmp;
250 if (pci->ioaddr == 0)
251 return 0;
253 adjust_pci_device(pci);
255 /* initialize some commonly used globals */
257 nic->irqno = 0;
258 nic->ioaddr = pci->ioaddr & ~3;
260 ioaddr = pci->ioaddr & ~3;
261 vendor = pci->vendor;
262 dev_id = pci->dev_id;
263 nic_name = pci->name;
265 /* natsemi has a non-standard PM control register
266 * in PCI config space. Some boards apparently need
267 * to be brought to D0 in this manner.
269 pcibios_read_config_dword(pci->bus, pci->devfn, PCIPM, &tmp);
270 if (tmp & (0x03|0x100)) {
271 /* D0 state, disable PME assertion */
272 u32 newtmp = tmp & ~(0x03|0x100);
273 pcibios_write_config_dword(pci->bus, pci->devfn, PCIPM, newtmp);
276 /* get MAC address */
278 prev_eedata = eeprom_read(ioaddr, 6);
279 for (i = 0; i < 3; i++) {
280 int eedata = eeprom_read(ioaddr, i + 7);
281 nic->node_addr[i*2] = (eedata << 1) + (prev_eedata >> 15);
282 nic->node_addr[i*2+1] = eedata >> 7;
283 prev_eedata = eedata;
286 printf("\nnatsemi_probe: MAC addr %! at ioaddr %#hX\n",
287 nic->node_addr, ioaddr);
288 printf("natsemi_probe: Vendor:%#hX Device:%#hX\n", vendor, dev_id);
290 /* Reset the chip to erase any previous misconfiguration. */
291 outl(ChipReset, ioaddr + ChipCmd);
293 advertising = mdio_read(1, 4);
295 u32 chip_config = inl(ioaddr + ChipConfig);
296 printf("%s: Transceiver default autoneg. %s "
297 "10%s %s duplex.\n",
298 nic_name,
299 chip_config & 0x2000 ? "enabled, advertise" : "disabled, force",
300 chip_config & 0x4000 ? "0" : "",
301 chip_config & 0x8000 ? "full" : "half");
303 printf("%s: Transceiver status %hX advertising %hX\n",
304 nic_name, (int)inl(ioaddr + 0x84), advertising);
306 /* Disable PME:
307 * The PME bit is initialized from the EEPROM contents.
308 * PCI cards probably have PME disabled, but motherboard
309 * implementations may have PME set to enable WakeOnLan.
310 * With PME set the chip will scan incoming packets but
311 * nothing will be written to memory. */
312 SavedClkRun = inl(ioaddr + ClkRun);
313 outl(SavedClkRun & ~0x100, ioaddr + ClkRun);
315 /* initialize device */
316 natsemi_init(nic);
318 dev->disable = natsemi_disable;
319 nic->poll = natsemi_poll;
320 nic->transmit = natsemi_transmit;
321 nic->irq = natsemi_irq;
323 return 1;
326 /* Read the EEPROM and MII Management Data I/O (MDIO) interfaces.
327 The EEPROM code is for the common 93c06/46 EEPROMs with 6 bit addresses.
330 /* Delay between EEPROM clock transitions.
331 No extra delay is needed with 33Mhz PCI, but future 66Mhz access may need
332 a delay. */
333 #define eeprom_delay(ee_addr) inl(ee_addr)
335 enum EEPROM_Ctrl_Bits {
336 EE_ShiftClk = 0x04,
337 EE_DataIn = 0x01,
338 EE_ChipSelect = 0x08,
339 EE_DataOut = 0x02
342 #define EE_Write0 (EE_ChipSelect)
343 #define EE_Write1 (EE_ChipSelect | EE_DataIn)
345 /* The EEPROM commands include the alway-set leading bit. */
346 enum EEPROM_Cmds {
347 EE_WriteCmd=(5 << 6), EE_ReadCmd=(6 << 6), EE_EraseCmd=(7 << 6),
350 static int eeprom_read(long addr, int location)
352 int i;
353 int retval = 0;
354 int ee_addr = addr + EECtrl;
355 int read_cmd = location | EE_ReadCmd;
356 outl(EE_Write0, ee_addr);
358 /* Shift the read command bits out. */
359 for (i = 10; i >= 0; i--) {
360 short dataval = (read_cmd & (1 << i)) ? EE_Write1 : EE_Write0;
361 outl(dataval, ee_addr);
362 eeprom_delay(ee_addr);
363 outl(dataval | EE_ShiftClk, ee_addr);
364 eeprom_delay(ee_addr);
366 outl(EE_ChipSelect, ee_addr);
367 eeprom_delay(ee_addr);
369 for (i = 0; i < 16; i++) {
370 outl(EE_ChipSelect | EE_ShiftClk, ee_addr);
371 eeprom_delay(ee_addr);
372 retval |= (inl(ee_addr) & EE_DataOut) ? 1 << i : 0;
373 outl(EE_ChipSelect, ee_addr);
374 eeprom_delay(ee_addr);
377 /* Terminate the EEPROM access. */
378 outl(EE_Write0, ee_addr);
379 outl(0, ee_addr);
381 return retval;
384 /* MII transceiver control section.
385 The 83815 series has an internal transceiver, and we present the
386 management registers as if they were MII connected. */
388 static int mdio_read(int phy_id, int location)
390 if (phy_id == 1 && location < 32)
391 return inl(ioaddr + 0x80 + (location<<2)) & 0xffff;
392 else
393 return 0xffff;
396 /* Function: natsemi_init
398 * Description: resets the ethernet controller chip and configures
399 * registers and data structures required for sending and receiving packets.
401 * Arguments: struct nic *nic: NIC data structure
403 * returns: void.
406 static void
407 natsemi_init(struct nic *nic)
409 natsemi_reset(nic);
411 /* Disable PME:
412 * The PME bit is initialized from the EEPROM contents.
413 * PCI cards probably have PME disabled, but motherboard
414 * implementations may have PME set to enable WakeOnLan.
415 * With PME set the chip will scan incoming packets but
416 * nothing will be written to memory. */
417 outl(SavedClkRun & ~0x100, ioaddr + ClkRun);
419 natsemi_init_rxfilter(nic);
421 natsemi_init_txd(nic);
422 natsemi_init_rxd(nic);
424 /* Initialize other registers. */
425 /* Configure the PCI bus bursts and FIFO thresholds. */
426 /* Configure for standard, in-spec Ethernet. */
427 if (inl(ioaddr + ChipConfig) & 0x20000000) { /* Full duplex */
428 tx_config = 0xD0801002;
429 rx_config = 0x10000020;
430 } else {
431 tx_config = 0x10801002;
432 rx_config = 0x0020;
434 outl(tx_config, ioaddr + TxConfig);
435 outl(rx_config, ioaddr + RxConfig);
437 natsemi_check_duplex(nic);
438 natsemi_set_rx_mode(nic);
440 outl(RxOn, ioaddr + ChipCmd);
444 * Function: natsemi_reset
446 * Description: soft resets the controller chip
448 * Arguments: struct nic *nic: NIC data structure
450 * Returns: void.
452 static void
453 natsemi_reset(struct nic *nic __unused)
455 outl(ChipReset, ioaddr + ChipCmd);
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. Also, we only want to do
460 this for rev C of the chip.
462 if (inl(ioaddr + SiliconRev) == 0x302) {
463 outw(0x0001, ioaddr + PGSEL);
464 outw(0x189C, ioaddr + PMDCSR);
465 outw(0x0000, ioaddr + TSTDAT);
466 outw(0x5040, ioaddr + DSPCFG);
467 outw(0x008C, ioaddr + SDCFG);
469 /* Disable interrupts using the mask. */
470 outl(0, ioaddr + IntrMask);
471 outl(0, ioaddr + IntrEnable);
474 /* Function: natsemi_init_rxfilter
476 * Description: sets receive filter address to our MAC address
478 * Arguments: struct nic *nic: NIC data structure
480 * returns: void.
483 static void
484 natsemi_init_rxfilter(struct nic *nic)
486 int i;
488 for (i = 0; i < ETH_ALEN; i += 2) {
489 outl(i, ioaddr + RxFilterAddr);
490 outw(nic->node_addr[i] + (nic->node_addr[i+1] << 8), ioaddr + RxFilterData);
495 * Function: natsemi_init_txd
497 * Description: initializes the Tx descriptor
499 * Arguments: struct nic *nic: NIC data structure
501 * returns: void.
504 static void
505 natsemi_init_txd(struct nic *nic __unused)
507 txd.link = (u32) 0;
508 txd.cmdsts = (u32) 0;
509 txd.bufptr = virt_to_bus(&txb[0]);
511 /* load Transmit Descriptor Register */
512 outl(virt_to_bus(&txd), ioaddr + TxRingPtr);
513 if (natsemi_debug > 1)
514 printf("natsemi_init_txd: TX descriptor register loaded with: %X\n",
515 inl(ioaddr + TxRingPtr));
518 /* Function: natsemi_init_rxd
520 * Description: initializes the Rx descriptor ring
522 * Arguments: struct nic *nic: NIC data structure
524 * Returns: void.
527 static void
528 natsemi_init_rxd(struct nic *nic __unused)
530 int i;
532 cur_rx = 0;
534 /* init RX descriptor */
535 for (i = 0; i < NUM_RX_DESC; i++) {
536 rxd[i].link = virt_to_bus((i+1 < NUM_RX_DESC) ? &rxd[i+1] : &rxd[0]);
537 rxd[i].cmdsts = (u32) RX_BUF_SIZE;
538 rxd[i].bufptr = virt_to_bus(&rxb[i*RX_BUF_SIZE]);
539 if (natsemi_debug > 1)
540 printf("natsemi_init_rxd: rxd[%d]=%X link=%X cmdsts=%X bufptr=%X\n",
541 i, &rxd[i], rxd[i].link, rxd[i].cmdsts, rxd[i].bufptr);
544 /* load Receive Descriptor Register */
545 outl(virt_to_bus(&rxd[0]), ioaddr + RxRingPtr);
547 if (natsemi_debug > 1)
548 printf("natsemi_init_rxd: RX descriptor register loaded with: %X\n",
549 inl(ioaddr + RxRingPtr));
552 /* Function: natsemi_set_rx_mode
554 * Description:
555 * sets the receive mode to accept all broadcast packets and packets
556 * with our MAC address, and reject all multicast packets.
558 * Arguments: struct nic *nic: NIC data structure
560 * Returns: void.
563 static void natsemi_set_rx_mode(struct nic *nic __unused)
565 u32 rx_mode = RxFilterEnable | AcceptBroadcast |
566 AcceptAllMulticast | AcceptMyPhys;
568 outl(rx_mode, ioaddr + RxFilterAddr);
571 static void natsemi_check_duplex(struct nic *nic __unused)
573 int duplex = inl(ioaddr + ChipConfig) & 0x20000000 ? 1 : 0;
575 if (natsemi_debug)
576 printf("%s: Setting %s-duplex based on negotiated link"
577 " capability.\n", nic_name,
578 duplex ? "full" : "half");
579 if (duplex) {
580 rx_config |= 0x10000000;
581 tx_config |= 0xC0000000;
582 } else {
583 rx_config &= ~0x10000000;
584 tx_config &= ~0xC0000000;
586 outl(tx_config, ioaddr + TxConfig);
587 outl(rx_config, ioaddr + RxConfig);
590 /* Function: natsemi_transmit
592 * Description: transmits a packet and waits for completion or timeout.
594 * Arguments: char d[6]: destination ethernet address.
595 * unsigned short t: ethernet protocol type.
596 * unsigned short s: size of the data-part of the packet.
597 * char *p: the data for the packet.
599 * Returns: void.
602 static void
603 natsemi_transmit(struct nic *nic,
604 const char *d, /* Destination */
605 unsigned int t, /* Type */
606 unsigned int s, /* size */
607 const char *p) /* Packet */
609 u32 to, nstype;
610 u32 tx_status;
612 /* Stop the transmitter */
613 outl(TxOff, ioaddr + ChipCmd);
615 /* load Transmit Descriptor Register */
616 outl(virt_to_bus(&txd), ioaddr + TxRingPtr);
617 if (natsemi_debug > 1)
618 printf("natsemi_transmit: TX descriptor register loaded with: %X\n",
619 inl(ioaddr + TxRingPtr));
621 memcpy(txb, d, ETH_ALEN);
622 memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);
623 nstype = htons(t);
624 memcpy(txb + 2 * ETH_ALEN, (char*)&nstype, 2);
625 memcpy(txb + ETH_HLEN, p, s);
627 s += ETH_HLEN;
628 s &= DSIZE;
630 if (natsemi_debug > 1)
631 printf("natsemi_transmit: sending %d bytes ethtype %hX\n", (int) s, t);
633 /* pad to minimum packet size */
634 while (s < ETH_ZLEN)
635 txb[s++] = '\0';
637 /* set the transmit buffer descriptor and enable Transmit State Machine */
638 txd.bufptr = virt_to_bus(&txb[0]);
639 txd.cmdsts = (u32) OWN | s;
641 /* restart the transmitter */
642 outl(TxOn, ioaddr + ChipCmd);
644 if (natsemi_debug > 1)
645 printf("natsemi_transmit: Queued Tx packet size %d.\n", (int) s);
647 to = currticks() + TX_TIMEOUT;
649 while ((((volatile u32) tx_status=txd.cmdsts) & OWN) && (currticks() < to))
650 /* wait */ ;
652 if (currticks() >= to) {
653 printf("natsemi_transmit: TX Timeout! Tx status %X.\n", tx_status);
656 if (!(tx_status & 0x08000000)) {
657 printf("natsemi_transmit: Transmit error, Tx status %X.\n", tx_status);
661 /* Function: natsemi_poll
663 * Description: checks for a received packet and returns it if found.
665 * Arguments: struct nic *nic: NIC data structure
667 * Returns: 1 if packet was received.
668 * 0 if no packet was received.
670 * Side effects:
671 * Returns (copies) the packet to the array nic->packet.
672 * Returns the length of the packet in nic->packetlen.
675 static int
676 natsemi_poll(struct nic *nic, int retrieve)
678 u32 rx_status = rxd[cur_rx].cmdsts;
679 int retstat = 0;
681 if (natsemi_debug > 2)
682 printf("natsemi_poll: cur_rx:%d, status:%X\n", cur_rx, rx_status);
684 if (!(rx_status & OWN))
685 return retstat;
687 if ( ! retrieve ) return 1;
689 if (natsemi_debug > 1)
690 printf("natsemi_poll: got a packet: cur_rx:%d, status:%X\n",
691 cur_rx, rx_status);
693 nic->packetlen = (rx_status & DSIZE) - CRC_SIZE;
695 if ((rx_status & (DescMore|DescPktOK|RxTooLong)) != DescPktOK) {
696 /* corrupted packet received */
697 printf("natsemi_poll: Corrupted packet received, buffer status = %X\n",
698 rx_status);
699 retstat = 0;
700 } else {
701 /* give packet to higher level routine */
702 memcpy(nic->packet, (rxb + cur_rx*RX_BUF_SIZE), nic->packetlen);
703 retstat = 1;
706 /* return the descriptor and buffer to receive ring */
707 rxd[cur_rx].cmdsts = RX_BUF_SIZE;
708 rxd[cur_rx].bufptr = virt_to_bus(&rxb[cur_rx*RX_BUF_SIZE]);
710 if (++cur_rx == NUM_RX_DESC)
711 cur_rx = 0;
713 /* re-enable the potentially idle receive state machine */
714 outl(RxOn, ioaddr + ChipCmd);
716 return retstat;
719 /* Function: natsemi_disable
721 * Description: Turns off interrupts and stops Tx and Rx engines
723 * Arguments: struct nic *nic: NIC data structure
725 * Returns: void.
728 static void
729 natsemi_disable(struct dev *dev)
731 struct nic *nic = (struct nic *)dev;
732 /* merge reset and disable */
733 natsemi_init(nic);
735 /* Disable interrupts using the mask. */
736 outl(0, ioaddr + IntrMask);
737 outl(0, ioaddr + IntrEnable);
739 /* Stop the chip's Tx and Rx processes. */
740 outl(RxOff | TxOff, ioaddr + ChipCmd);
742 /* Restore PME enable bit */
743 outl(SavedClkRun, ioaddr + ClkRun);
746 /* Function: natsemi_irq
748 * Description: Enable, Disable, or Force interrupts
750 * Arguments: struct nic *nic: NIC data structure
751 * irq_action_t action: requested action to perform
753 * Returns: void.
756 static void
757 natsemi_irq(struct nic *nic __unused, irq_action_t action __unused)
759 switch ( action ) {
760 case DISABLE :
761 break;
762 case ENABLE :
763 break;
764 case FORCE :
765 break;
769 static struct pci_id natsemi_nics[] = {
770 PCI_ROM(0x100b, 0x0020, "dp83815", "DP83815"),
773 struct pci_driver natsemi_driver = {
774 .type = NIC_DRIVER,
775 .name = "NATSEMI",
776 .probe = natsemi_probe,
777 .ids = natsemi_nics,
778 .id_count = sizeof(natsemi_nics)/sizeof(natsemi_nics[0]),
779 .class = 0,