3c90x.c File Reference

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <byteswap.h>
#include <errno.h>
#include <gpxe/ethernet.h>
#include <gpxe/if_ether.h>
#include <gpxe/io.h>
#include <gpxe/iobuf.h>
#include <gpxe/malloc.h>
#include <gpxe/netdevice.h>
#include <gpxe/pci.h>
#include <gpxe/timer.h>
#include <gpxe/nvs.h>
#include "3c90x.h"

Go to the source code of this file.

Functions

 FILE_LICENCE (BSD2)
static void a3c90x_internal_IssueCommand (int ioaddr, int cmd, int param)
 a3c90x_internal_IssueCommand: sends a command to the 3c90x card and waits for it's completion
static void a3c90x_internal_SetWindow (struct INF_3C90X *inf_3c90x, int window)
 a3c90x_internal_SetWindow: selects a register window set.
static void a3c90x_internal_WaitForEeprom (struct INF_3C90X *inf_3c90x)
static int a3c90x_internal_ReadEeprom (struct nvs_device *nvs, unsigned int address, void *data, size_t len)
 a3c90x_internal_ReadEeprom - nvs routine to read eeprom data We only support reading one word(2 byte).
static int a3c90x_internal_WriteEeprom (struct nvs_device *nvs __unused, unsigned int address __unused, const void *data __unused, size_t len __unused)
 a3c90x_internal_WriteEeprom - nvs routine to write eeprom data currently not implemented
static void a3c90x_internal_ReadEepromContents (struct INF_3C90X *inf_3c90x)
static void a3c90x_reset (struct INF_3C90X *inf_3c90x)
 a3c90x_reset: exported function that resets the card to its default state.
static int a3c90x_setup_tx_ring (struct INF_3C90X *p)
 a3c90x_setup_tx_ring - Allocates TX ring, initialize tx_desc values
static void a3c90x_process_tx_packets (struct net_device *netdev)
 a3c90x_process_tx_packets - Checks for successfully sent packets, reports them to gPXE with netdev_tx_complete();
static void a3c90x_free_tx_ring (struct INF_3C90X *p)
static int a3c90x_transmit (struct net_device *netdev, struct io_buffer *iob)
 a3c90x_transmit - Transmits a packet.
static void a3c90x_prepare_rx_desc (struct INF_3C90X *p, unsigned int index)
 a3c90x_prepare_rx_desc - fills the rx desc with initial data
static void a3c90x_refill_rx_ring (struct INF_3C90X *p)
 a3c90x_refill_rx_ring -checks every entry in the rx ring and reallocates them as necessary.
static int a3c90x_setup_rx_ring (struct INF_3C90X *p)
 a3c90x_setup_rx_ring - Allocates RX ring, initialize rx_desc values
static void a3c90x_free_rx_ring (struct INF_3C90X *p)
static void a3c90x_free_rx_iobuf (struct INF_3C90X *p)
static void a3c90x_process_rx_packets (struct net_device *netdev)
 a3c90x_process_rx_packets - Checks for received packets, reports them to gPXE with netdev_rx() or netdev_rx_err() if there was an error while receiving the packet
static void a3c90x_poll (struct net_device *netdev)
 a3c90x_poll - Routine that gets called periodically.
static void a3c90x_free_resources (struct INF_3C90X *p)
static void a3c90x_remove (struct pci_device *pci)
 a3c90x_remove - Routine to remove the card.
static void a3c90x_irq (struct net_device *netdev, int enable)
static void a3c90x_hw_start (struct net_device *netdev)
 a3c90x_hw_start - Initialize hardware, copy MAC address to NIC registers, set default receiver
static int a3c90x_open (struct net_device *netdev)
 a3c90x_open - Routine to initialize the card.
static void a3c90x_close (struct net_device *netdev)
 a3c90x_close - free()s TX and RX ring, disablex RX/TX, resets NIC
static int a3c90x_probe (struct pci_device *pci, const struct pci_device_id *pci_id __unused)
 a3c90x_probe: exported routine to probe for the 3c905 card.

Variables

static struct net_device_operations a3c90x_operations
static struct pci_device_id a3c90x_nics []
struct pci_driver a3c90x_driver __pci_driver


Function Documentation

FILE_LICENCE ( BSD2   ) 

static void a3c90x_internal_IssueCommand ( int  ioaddr,
int  cmd,
int  param 
) [static]

a3c90x_internal_IssueCommand: sends a command to the 3c90x card and waits for it's completion

Parameters:
ioaddr IOAddress of the NIC
cmd Command to be issued
param Command parameter

Definition at line 70 of file 3c90x.c.

References DBG, DBG2, DBGP, INT_CMDINPROGRESS, inw, outw, and regCommandIntStatus_w.

Referenced by a3c90x_hw_start(), a3c90x_internal_SetWindow(), a3c90x_irq(), a3c90x_open(), a3c90x_poll(), a3c90x_prepare_rx_desc(), a3c90x_reset(), and a3c90x_transmit().

00071 {
00072         unsigned int val = (cmd << 11) | param;
00073         int cnt = 0;
00074 
00075         DBGP("a3c90x_internal_IssueCommand\n");
00076 
00077         /* Send the cmd to the cmd register */
00078         outw(val, ioaddr + regCommandIntStatus_w);
00079 
00080         /* Wait for the cmd to complete */
00081         for (cnt = 0; cnt < 100000; cnt++) {
00082                 if (inw(ioaddr + regCommandIntStatus_w) & INT_CMDINPROGRESS) {
00083                         continue;
00084                 } else {
00085                         DBG2("Command 0x%04X finished in time. cnt = %d.\n", cmd, cnt);
00086                         return;
00087                 }
00088         }
00089 
00090         DBG("Command 0x%04X DID NOT finish in time. cnt = %d.\n", cmd, cnt);
00091 }

static void a3c90x_internal_SetWindow ( struct INF_3C90X inf_3c90x,
int  window 
) [static]

a3c90x_internal_SetWindow: selects a register window set.

Parameters:
inf_3c90x private NIC data
window window to be selected

Definition at line 99 of file 3c90x.c.

References a3c90x_internal_IssueCommand(), cmdSelectRegisterWindow, INF_3C90X::CurrentWindow, DBGP, and INF_3C90X::IOAddr.

Referenced by a3c90x_hw_start(), a3c90x_internal_ReadEeprom(), and a3c90x_reset().

00100 {
00101         DBGP("a3c90x_internal_SetWindow\n");
00102         /* Window already as set? */
00103         if (inf_3c90x->CurrentWindow == window)
00104                 return;
00105 
00106         /* Issue the window command. */
00107         a3c90x_internal_IssueCommand(inf_3c90x->IOAddr,
00108                                      cmdSelectRegisterWindow, window);
00109         inf_3c90x->CurrentWindow = window;
00110 
00111         return;
00112 }

static void a3c90x_internal_WaitForEeprom ( struct INF_3C90X inf_3c90x  )  [static]

Definition at line 114 of file 3c90x.c.

References DBG, DBGP, EEPROM_TIMEOUT, eepromBusy, inw, INF_3C90X::IOAddr, regEepromCommand_0_w, and udelay().

Referenced by a3c90x_internal_ReadEeprom().

00115 {
00116         int cnt = 0;
00117 
00118         DBGP("a3c90x_internal_WaitForEeprom\n");
00119 
00120         while (eepromBusy & inw(inf_3c90x->IOAddr + regEepromCommand_0_w)) {
00121                 if (cnt == EEPROM_TIMEOUT) {
00122                         DBG("Read from eeprom failed: timeout\n");
00123                         return;
00124                 }
00125                 udelay(1);
00126                 cnt++;
00127         }
00128 }

static int a3c90x_internal_ReadEeprom ( struct nvs_device nvs,
unsigned int  address,
void *  data,
size_t  len 
) [static]

a3c90x_internal_ReadEeprom - nvs routine to read eeprom data We only support reading one word(2 byte).

The nvs subsystem will make sure that the routine will never be called with len != 2.

Parameters:
nvs nvs data.
address eeprom address to read data from.
data data is put here.
len number of bytes to read.

Definition at line 141 of file 3c90x.c.

References a3c90x_internal_SetWindow(), a3c90x_internal_WaitForEeprom(), assert, container_of, DBGP, dest, eepromRead, eepromRead_556, inw, INF_3C90X::IOAddr, INF_3C90X::is3c556, outw, regEepromCommand_0_w, regEepromData_0_w, and winEepromBios0.

Referenced by a3c90x_probe().

00142 {
00143         unsigned short *dest = (unsigned short *) data;
00144         struct INF_3C90X *inf_3c90x =
00145             container_of(nvs, struct INF_3C90X, nvs);
00146 
00147         DBGP("a3c90x_internal_ReadEeprom\n");
00148 
00149         /* we support reading 2 bytes only */
00150         assert(len == 2);
00151 
00152         /* Select correct window */
00153         a3c90x_internal_SetWindow(inf_3c90x, winEepromBios0);
00154 
00155         /* set eepromRead bits in command sent to NIC */
00156         address += (inf_3c90x->is3c556 ? eepromRead_556 : eepromRead);
00157 
00158         a3c90x_internal_WaitForEeprom(inf_3c90x);
00159         /* send address to NIC */
00160         outw(address, inf_3c90x->IOAddr + regEepromCommand_0_w);
00161         a3c90x_internal_WaitForEeprom(inf_3c90x);
00162 
00163         /* read value */
00164         *dest = inw(inf_3c90x->IOAddr + regEepromData_0_w);
00165 
00166         return 0;
00167 }

static int a3c90x_internal_WriteEeprom ( struct nvs_device *nvs  __unused,
unsigned int address  __unused,
const void *data  __unused,
size_t len  __unused 
) [static]

a3c90x_internal_WriteEeprom - nvs routine to write eeprom data currently not implemented

Parameters:
nvs nvs data.
address eeprom address to read data from.
data data is put here.
len number of bytes to read.

Definition at line 179 of file 3c90x.c.

References ENOTSUP.

Referenced by a3c90x_probe().

00182 {
00183         return -ENOTSUP;
00184 }

static void a3c90x_internal_ReadEepromContents ( struct INF_3C90X inf_3c90x  )  [static]

Definition at line 186 of file 3c90x.c.

References DBGP, INF_3C90X::eeprom, INF_3C90X::isBrev, INF_3C90X::nvs, and nvs_read().

Referenced by a3c90x_probe().

00187 {
00188         int eeprom_size = (inf_3c90x->isBrev ? 0x20 : 0x17) * 2;
00189 
00190         DBGP("a3c90x_internal_ReadEepromContents\n");
00191 
00192         nvs_read(&inf_3c90x->nvs, 0, inf_3c90x->eeprom, eeprom_size);
00193 }

static void a3c90x_reset ( struct INF_3C90X inf_3c90x  )  [static]

a3c90x_reset: exported function that resets the card to its default state.

This is so the Linux driver can re-set the card up the way it wants to. If CFG_3C90X_PRESERVE_XCVR is defined, then the reset will not alter the selected transceiver that we used to download the boot image.

Parameters:
inf_3c90x Private NIC data

Definition at line 204 of file 3c90x.c.

References a3c90x_internal_IssueCommand(), a3c90x_internal_SetWindow(), cmdAcknowledgeInterrupt, cmdGlobalReset, cmdRxEnable, cmdRxReset, cmdSetIndicationEnable, cmdSetInterruptEnable, cmdTxEnable, cmdTxReset, DBG, DBGP, INT_TXCOMPLETE, INT_UPCOMPLETE, INF_3C90X::IOAddr, INF_3C90X::isBrev, outw, regStationMask_2_3w, and winAddressing2.

Referenced by a3c90x_close(), a3c90x_open(), a3c90x_probe(), and a3c90x_remove().

00205 {
00206         DBGP("a3c90x_reset\n");
00207         /* Send the reset command to the card */
00208         DBG("3c90x: Issuing RESET\n");
00209         a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdGlobalReset, 0);
00210 
00211         /* global reset command resets station mask, non-B revision cards
00212          * require explicit reset of values
00213          */
00214         a3c90x_internal_SetWindow(inf_3c90x, winAddressing2);
00215         outw(0, inf_3c90x->IOAddr + regStationMask_2_3w + 0);
00216         outw(0, inf_3c90x->IOAddr + regStationMask_2_3w + 2);
00217         outw(0, inf_3c90x->IOAddr + regStationMask_2_3w + 4);
00218 
00219         /* Issue transmit reset, wait for command completion */
00220         a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdTxReset, 0);
00221 
00222         a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdTxEnable, 0);
00223 
00224         /*
00225          * reset of the receiver on B-revision cards re-negotiates the link
00226          * takes several seconds (a computer eternity)
00227          */
00228         a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdRxReset,
00229                                      inf_3c90x->isBrev ? 0x04 : 0x00);
00230 
00231         a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdRxEnable, 0);
00232 
00233         a3c90x_internal_IssueCommand(inf_3c90x->IOAddr,
00234                                      cmdSetInterruptEnable, 0);
00235         /* enable rxComplete and txComplete */
00236         a3c90x_internal_IssueCommand(inf_3c90x->IOAddr,
00237                                      cmdSetIndicationEnable,
00238                                      INT_TXCOMPLETE | INT_UPCOMPLETE);
00239         /* acknowledge any pending status flags */
00240         a3c90x_internal_IssueCommand(inf_3c90x->IOAddr,
00241                                      cmdAcknowledgeInterrupt, 0x661);
00242 
00243         return;
00244 }

static int a3c90x_setup_tx_ring ( struct INF_3C90X p  )  [static]

a3c90x_setup_tx_ring - Allocates TX ring, initialize tx_desc values

Parameters:
p Private NIC data
Return values:
Returns 0 on success, negative on failure

Definition at line 253 of file 3c90x.c.

References DBG, DBGP, ENOMEM, malloc_dma(), memset(), INF_3C90X::tx_cnt, INF_3C90X::tx_cur, INF_3C90X::tx_ring, TX_RING_ALIGN, TX_RING_SIZE, and INF_3C90X::tx_tail.

Referenced by a3c90x_open().

00254 {
00255         DBGP("a3c90x_setup_tx_ring\n");
00256         p->tx_ring =
00257             malloc_dma(TX_RING_SIZE * sizeof(struct TXD), TX_RING_ALIGN);
00258 
00259         if (!p->tx_ring) {
00260                 DBG("Could not allocate TX-ring\n");
00261                 return -ENOMEM;
00262         }
00263 
00264         memset(p->tx_ring, 0, TX_RING_SIZE * sizeof(struct TXD));
00265         p->tx_cur = 0;
00266         p->tx_cnt = 0;
00267         p->tx_tail = 0;
00268 
00269         return 0;
00270 }

static void a3c90x_process_tx_packets ( struct net_device netdev  )  [static]

a3c90x_process_tx_packets - Checks for successfully sent packets, reports them to gPXE with netdev_tx_complete();

Parameters:
netdev Network device info

Definition at line 278 of file 3c90x.c.

References DBG, DBGP, inl, INF_3C90X::IOAddr, iob_len(), netdev_priv(), netdev_tx_complete(), regDnListPtr_l, INF_3C90X::tx_cnt, INF_3C90X::tx_cur, INF_3C90X::tx_iobuf, INF_3C90X::tx_ring, TX_RING_SIZE, INF_3C90X::tx_tail, and virt_to_bus().

Referenced by a3c90x_poll().

00279 {
00280         struct INF_3C90X *p = netdev_priv(netdev);
00281         unsigned int downlist_ptr;
00282 
00283         DBGP("a3c90x_process_tx_packets\n");
00284 
00285         DBG("    tx_cnt: %d\n", p->tx_cnt);
00286 
00287         while (p->tx_tail != p->tx_cur) {
00288 
00289                 downlist_ptr = inl(p->IOAddr + regDnListPtr_l);
00290 
00291                 DBG("    downlist_ptr: %#08x\n", downlist_ptr);
00292                 DBG("    tx_tail: %d tx_cur: %d\n", p->tx_tail, p->tx_cur);
00293 
00294                 /* NIC is currently working on this tx desc */
00295                 if(downlist_ptr == virt_to_bus(p->tx_ring + p->tx_tail))
00296                         return;
00297 
00298                 netdev_tx_complete(netdev, p->tx_iobuf[p->tx_tail]);
00299 
00300                 DBG("transmitted packet\n");
00301                 DBG("    size: %zd\n", iob_len(p->tx_iobuf[p->tx_tail]));
00302 
00303                 p->tx_tail = (p->tx_tail + 1) % TX_RING_SIZE;
00304                 p->tx_cnt--;
00305         }
00306 }

static void a3c90x_free_tx_ring ( struct INF_3C90X p  )  [static]

Definition at line 308 of file 3c90x.c.

References DBGP, free_dma(), NULL, INF_3C90X::tx_ring, and TX_RING_SIZE.

Referenced by a3c90x_free_resources().

00309 {
00310         DBGP("a3c90x_free_tx_ring\n");
00311 
00312         free_dma(p->tx_ring, TX_RING_SIZE * sizeof(struct TXD));
00313         p->tx_ring = NULL;
00314         /* io_buffers are free()ed by netdev_tx_complete[,_err]() */
00315 }

static int a3c90x_transmit ( struct net_device netdev,
struct io_buffer iob 
) [static]

a3c90x_transmit - Transmits a packet.

Parameters:
netdev Network device info
iob io_buffer containing the data to be send
Return values:
Returns 0 on success, negative on failure

Definition at line 325 of file 3c90x.c.

References a3c90x_internal_IssueCommand(), cmdStallCtl, io_buffer::data, TXD::DataAddr, TXD::DataLength, DBG, DBGP, TXD::DnNextPtr, dnStall, dnUnStall, downLastFrag, ENOBUFS, TXD::FrameStartHeader, fshTxIndicate, inl, INF_3C90X::IOAddr, iob_len(), INF_3C90X::isBrev, netdev_priv(), outl, regDnListPtr_l, INF_3C90X::tx_cnt, INF_3C90X::tx_cur, INF_3C90X::tx_iobuf, INF_3C90X::tx_ring, TX_RING_SIZE, and virt_to_bus().

00327 {
00328         struct INF_3C90X *inf_3c90x = netdev_priv(netdev);
00329         struct TXD *tx_cur_desc;
00330         struct TXD *tx_prev_desc;
00331 
00332         unsigned int len;
00333         unsigned int downlist_ptr;
00334 
00335         DBGP("a3c90x_transmit\n");
00336 
00337         if (inf_3c90x->tx_cnt == TX_RING_SIZE) {
00338                 DBG("TX-Ring overflow\n");
00339                 return -ENOBUFS;
00340         }
00341 
00342         inf_3c90x->tx_iobuf[inf_3c90x->tx_cur] = iob;
00343         tx_cur_desc = inf_3c90x->tx_ring + inf_3c90x->tx_cur;
00344 
00345         tx_prev_desc = inf_3c90x->tx_ring +
00346             (((inf_3c90x->tx_cur + TX_RING_SIZE) - 1) % TX_RING_SIZE);
00347 
00348         len = iob_len(iob);
00349 
00350         /* Setup the DPD (download descriptor) */
00351         tx_cur_desc->DnNextPtr = 0;
00352 
00353         /* FrameStartHeader differs in 90x and >= 90xB
00354          * It contains length in 90x and a round up boundary and packet ID for
00355          * 90xB and 90xC. We can leave this to 0 for 90xB and 90xC.
00356          */
00357         tx_cur_desc->FrameStartHeader =
00358             fshTxIndicate | (inf_3c90x->isBrev ? 0x00 : len);
00359 
00360         tx_cur_desc->DataAddr = virt_to_bus(iob->data);
00361         tx_cur_desc->DataLength = len | downLastFrag;
00362 
00363         /* We have to stall the download engine, so the NIC won't access the
00364          * tx descriptor while we modify it. There is a way around this
00365          * from revision B and upwards. To stay compatible with older revisions
00366          * we don't use it here.
00367          */
00368         a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdStallCtl,
00369                                      dnStall);
00370 
00371         tx_prev_desc->DnNextPtr = virt_to_bus(tx_cur_desc);
00372 
00373         downlist_ptr = inl(inf_3c90x->IOAddr + regDnListPtr_l);
00374         if (downlist_ptr == 0) {
00375                 /* currently no DownList, sending a new one */
00376                 outl(virt_to_bus(tx_cur_desc),
00377                      inf_3c90x->IOAddr + regDnListPtr_l);
00378         }
00379 
00380         /* End Stall */
00381         a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdStallCtl,
00382                                      dnUnStall);
00383 
00384         inf_3c90x->tx_cur = (inf_3c90x->tx_cur + 1) % TX_RING_SIZE;
00385         inf_3c90x->tx_cnt++;
00386 
00387         return 0;
00388 }

static void a3c90x_prepare_rx_desc ( struct INF_3C90X p,
unsigned int  index 
) [static]

a3c90x_prepare_rx_desc - fills the rx desc with initial data

Parameters:
p NIC private data
index Index for rx_iobuf and rx_ring array

Definition at line 397 of file 3c90x.c.

References a3c90x_internal_IssueCommand(), cmdStallCtl, io_buffer::data, RXD::DataAddr, RXD::DataLength, DBG, DBGP, INF_3C90X::IOAddr, RX_BUF_SIZE, INF_3C90X::rx_iobuf, INF_3C90X::rx_ring, upLastFrag, RXD::UpPktStatus, upStall, upUnStall, and virt_to_bus().

Referenced by a3c90x_refill_rx_ring().

00398 {
00399         DBGP("a3c90x_prepare_rx_desc\n");
00400         DBG("Populating rx_desc %d\n", index);
00401 
00402         /* We have to stall the upload engine, so the NIC won't access the
00403          * rx descriptor while we modify it. There is a way around this
00404          * from revision B and upwards. To stay compatible with older revisions
00405          * we don't use it here.
00406          */
00407         a3c90x_internal_IssueCommand(p->IOAddr, cmdStallCtl, upStall);
00408 
00409         p->rx_ring[index].DataAddr = virt_to_bus(p->rx_iobuf[index]->data);
00410         p->rx_ring[index].DataLength = RX_BUF_SIZE | upLastFrag;
00411         p->rx_ring[index].UpPktStatus = 0;
00412 
00413         /* unstall upload engine */
00414         a3c90x_internal_IssueCommand(p->IOAddr, cmdStallCtl, upUnStall);
00415 }

static void a3c90x_refill_rx_ring ( struct INF_3C90X p  )  [static]

a3c90x_refill_rx_ring -checks every entry in the rx ring and reallocates them as necessary.

Then it calls a3c90x_prepare_rx_desc to fill the rx desc with initial data.

Parameters:
p NIC private data

Definition at line 424 of file 3c90x.c.

References a3c90x_prepare_rx_desc(), alloc_iob(), DBG, DBGP, NULL, RX_BUF_SIZE, INF_3C90X::rx_iobuf, INF_3C90X::rx_ring, RX_RING_SIZE, upComplete, and RXD::UpPktStatus.

Referenced by a3c90x_process_rx_packets(), and a3c90x_setup_rx_ring().

00425 {
00426         int i;
00427         unsigned int status;
00428         struct RXD *rx_cur_desc;
00429 
00430         DBGP("a3c90x_refill_rx_ring\n");
00431 
00432         for (i = 0; i < RX_RING_SIZE; i++) {
00433                 rx_cur_desc = p->rx_ring + i;
00434                 status = rx_cur_desc->UpPktStatus;
00435 
00436                 /* only refill used descriptor */
00437                 if (!(status & upComplete))
00438                         continue;
00439 
00440                 /* we still need to process this descriptor */
00441                 if (p->rx_iobuf[i] != NULL)
00442                         continue;
00443 
00444                 p->rx_iobuf[i] = alloc_iob(RX_BUF_SIZE);
00445                 if (p->rx_iobuf[i] == NULL) {
00446                         DBG("alloc_iob() failed\n");
00447                         break;
00448                 }
00449 
00450                 a3c90x_prepare_rx_desc(p, i);
00451         }
00452 }

static int a3c90x_setup_rx_ring ( struct INF_3C90X p  )  [static]

a3c90x_setup_rx_ring - Allocates RX ring, initialize rx_desc values

Parameters:
p Private NIC data
Return values:
Returns 0 on success, negative on failure

Definition at line 461 of file 3c90x.c.

References a3c90x_refill_rx_ring(), DBG, DBGP, ENOMEM, malloc_dma(), NULL, INF_3C90X::rx_cur, INF_3C90X::rx_iobuf, INF_3C90X::rx_ring, RX_RING_ALIGN, RX_RING_SIZE, upComplete, RXD::UpNextPtr, RXD::UpPktStatus, and virt_to_bus().

Referenced by a3c90x_open().

00462 {
00463         int i;
00464 
00465         DBGP("a3c90x_setup_rx_ring\n");
00466 
00467         p->rx_ring =
00468             malloc_dma(RX_RING_SIZE * sizeof(struct RXD), RX_RING_ALIGN);
00469 
00470         if (!p->rx_ring) {
00471                 DBG("Could not allocate RX-ring\n");
00472                 return -ENOMEM;
00473         }
00474 
00475         p->rx_cur = 0;
00476 
00477         for (i = 0; i < RX_RING_SIZE; i++) {
00478                 p->rx_ring[i].UpNextPtr =
00479                     virt_to_bus(p->rx_ring + (i + 1));
00480 
00481                 /* these are needed so refill_rx_ring initializes the ring */
00482                 p->rx_ring[i].UpPktStatus = upComplete;
00483                 p->rx_iobuf[i] = NULL;
00484         }
00485 
00486         /* Loop the ring */
00487         p->rx_ring[i - 1].UpNextPtr = virt_to_bus(p->rx_ring);
00488 
00489         a3c90x_refill_rx_ring(p);
00490 
00491         return 0;
00492 }

static void a3c90x_free_rx_ring ( struct INF_3C90X p  )  [static]

Definition at line 494 of file 3c90x.c.

References DBGP, free_dma(), NULL, INF_3C90X::rx_ring, and RX_RING_SIZE.

Referenced by a3c90x_free_resources().

00495 {
00496         DBGP("a3c90x_free_rx_ring\n");
00497 
00498         free_dma(p->rx_ring, RX_RING_SIZE * sizeof(struct RXD));
00499         p->rx_ring = NULL;
00500 }

static void a3c90x_free_rx_iobuf ( struct INF_3C90X p  )  [static]

Definition at line 502 of file 3c90x.c.

References DBGP, free_iob(), NULL, INF_3C90X::rx_iobuf, and RX_RING_SIZE.

Referenced by a3c90x_free_resources().

00503 {
00504         int i;
00505 
00506         DBGP("a3c90x_free_rx_iobuf\n");
00507 
00508         for (i = 0; i < RX_RING_SIZE; i++) {
00509                 free_iob(p->rx_iobuf[i]);
00510                 p->rx_iobuf[i] = NULL;
00511         }
00512 }

static void a3c90x_process_rx_packets ( struct net_device netdev  )  [static]

a3c90x_process_rx_packets - Checks for received packets, reports them to gPXE with netdev_rx() or netdev_rx_err() if there was an error while receiving the packet

Parameters:
netdev Network device info

Definition at line 521 of file 3c90x.c.

References a3c90x_refill_rx_ring(), DBG, DBGP, EINVAL, iob_put, netdev_priv(), netdev_rx(), netdev_rx_err(), NULL, INF_3C90X::rx_cur, INF_3C90X::rx_iobuf, INF_3C90X::rx_ring, RX_RING_SIZE, upComplete, upError, and RXD::UpPktStatus.

Referenced by a3c90x_poll().

00522 {
00523         int i;
00524         unsigned int rx_status;
00525         struct INF_3C90X *p = netdev_priv(netdev);
00526         struct RXD *rx_cur_desc;
00527 
00528         DBGP("a3c90x_process_rx_packets\n");
00529 
00530         for (i = 0; i < RX_RING_SIZE; i++) {
00531                 rx_cur_desc = p->rx_ring + p->rx_cur;
00532                 rx_status = rx_cur_desc->UpPktStatus;
00533 
00534                 if (!(rx_status & upComplete) && !(rx_status & upError))
00535                         break;
00536 
00537                 if (p->rx_iobuf[p->rx_cur] == NULL)
00538                         break;
00539 
00540                 if (rx_status & upError) {
00541                         DBG("Corrupted packet received\n");
00542                         netdev_rx_err(netdev, p->rx_iobuf[p->rx_cur],
00543                                       -EINVAL);
00544                 } else {
00545                         /* if we're here, we've got good packet */
00546                         int packet_len;
00547 
00548                         packet_len = rx_status & 0x1FFF;
00549                         iob_put(p->rx_iobuf[p->rx_cur], packet_len);
00550 
00551                         DBG("received packet\n");
00552                         DBG("    size: %d\n", packet_len);
00553 
00554                         netdev_rx(netdev, p->rx_iobuf[p->rx_cur]);
00555                 }
00556 
00557                 p->rx_iobuf[p->rx_cur] = NULL;  /* invalidate rx desc */
00558                 p->rx_cur = (p->rx_cur + 1) % RX_RING_SIZE;
00559         }
00560         a3c90x_refill_rx_ring(p);
00561 
00562 }

static void a3c90x_poll ( struct net_device netdev  )  [static]

a3c90x_poll - Routine that gets called periodically.

Here we hanle transmitted and received packets. We could also check the link status from time to time, which we currently don't do.

Parameters:
netdev Network device info

Definition at line 572 of file 3c90x.c.

References a3c90x_internal_IssueCommand(), a3c90x_process_rx_packets(), a3c90x_process_tx_packets(), cmdAcknowledgeInterrupt, DBG, DBGP, INT_TXCOMPLETE, inw, INF_3C90X::IOAddr, netdev_priv(), outb, regCommandIntStatus_w, and regTxStatus_b.

00573 {
00574         struct INF_3C90X *p = netdev_priv(netdev);
00575         uint16_t raw_status, int_status;
00576 
00577         DBGP("a3c90x_poll\n");
00578 
00579         raw_status = inw(p->IOAddr + regCommandIntStatus_w);
00580         int_status = (raw_status & 0x0FFF);
00581 
00582         if ( int_status == 0 )
00583                 return;
00584 
00585         a3c90x_internal_IssueCommand(p->IOAddr, cmdAcknowledgeInterrupt,
00586                                      int_status);
00587 
00588         if (int_status & INT_TXCOMPLETE)
00589                 outb(0x00, p->IOAddr + regTxStatus_b);
00590 
00591         DBG("poll: status = %#04x\n", raw_status);
00592 
00593         a3c90x_process_tx_packets(netdev);
00594 
00595         a3c90x_process_rx_packets(netdev);
00596 }

static void a3c90x_free_resources ( struct INF_3C90X p  )  [static]

Definition at line 600 of file 3c90x.c.

References a3c90x_free_rx_iobuf(), a3c90x_free_rx_ring(), a3c90x_free_tx_ring(), and DBGP.

Referenced by a3c90x_close(), and a3c90x_open().

00601 {
00602         DBGP("a3c90x_free_resources\n");
00603 
00604         a3c90x_free_tx_ring(p);
00605         a3c90x_free_rx_ring(p);
00606         a3c90x_free_rx_iobuf(p);
00607 }

static void a3c90x_remove ( struct pci_device pci  )  [static]

a3c90x_remove - Routine to remove the card.

Unregisters the NIC from gPXE, disables RX/TX and resets the card.

Parameters:
pci PCI device info

Definition at line 615 of file 3c90x.c.

References a3c90x_reset(), cmdRxDisable, cmdTxDisable, DBGP, INF_3C90X::IOAddr, netdev, netdev_nullify(), netdev_priv(), netdev_put(), outw, pci_get_drvdata(), regCommandIntStatus_w, and unregister_netdev().

00616 {
00617         struct net_device *netdev = pci_get_drvdata(pci);
00618         struct INF_3C90X *inf_3c90x = netdev_priv(netdev);
00619 
00620         DBGP("a3c90x_remove\n");
00621 
00622         a3c90x_reset(inf_3c90x);
00623 
00624         /* Disable the receiver and transmitter. */
00625         outw(cmdRxDisable, inf_3c90x->IOAddr + regCommandIntStatus_w);
00626         outw(cmdTxDisable, inf_3c90x->IOAddr + regCommandIntStatus_w);
00627 
00628         unregister_netdev(netdev);
00629         netdev_nullify(netdev);
00630         netdev_put(netdev);
00631 }

static void a3c90x_irq ( struct net_device netdev,
int  enable 
) [static]

Definition at line 633 of file 3c90x.c.

References a3c90x_internal_IssueCommand(), cmdAcknowledgeInterrupt, cmdSetInterruptEnable, DBGP, INT_TXCOMPLETE, INT_UPCOMPLETE, INF_3C90X::IOAddr, and netdev_priv().

00634 {
00635         struct INF_3C90X *p = netdev_priv(netdev);
00636 
00637         DBGP("a3c90x_irq\n");
00638 
00639         if (enable == 0) {
00640                 /* disable interrupts */
00641                 a3c90x_internal_IssueCommand(p->IOAddr,
00642                                              cmdSetInterruptEnable, 0);
00643         } else {
00644                 a3c90x_internal_IssueCommand(p->IOAddr,
00645                                              cmdSetInterruptEnable,
00646                                              INT_TXCOMPLETE |
00647                                              INT_UPCOMPLETE);
00648                 a3c90x_internal_IssueCommand(p->IOAddr,
00649                                              cmdAcknowledgeInterrupt,
00650                                              0x661);
00651         }
00652 }

static void a3c90x_hw_start ( struct net_device netdev  )  [static]

a3c90x_hw_start - Initialize hardware, copy MAC address to NIC registers, set default receiver

Definition at line 658 of file 3c90x.c.

References a3c90x_internal_IssueCommand(), a3c90x_internal_SetWindow(), cfg, cmdAcknowledgeInterrupt, cmdEnableDcConverter, cmdSetIndicationEnable, cmdSetInterruptEnable, cmdSetRxFilter, cmdTxReset, DBG, DBGP, INF_3C90X::eeprom, ETH_ALEN, inl, INT_TXCOMPLETE, INT_UPCOMPLETE, inw, INF_3C90X::IOAddr, INF_3C90X::is3c556, INF_3C90X::isBrev, link100BaseFX, link10Base2, linkAUI, linkAutoneg, linkExternalMII, linkMII, net_device::ll_addr, netdev_priv(), outb, outl, outw, regInternalConfig_3_l, regResetMediaOptions_3_w, regResetOptions_2_w, regStationAddress_2_3w, regStationMask_2_3w, regTxFreeThresh_b, winAddressing2, winTxRxOptions3, and XCVR_MAGIC.

Referenced by a3c90x_open().

00659 {
00660         int i, c;
00661         unsigned int cfg;
00662         unsigned int mopt;
00663         unsigned short linktype;
00664         struct INF_3C90X *inf_3c90x = netdev_priv(netdev);
00665 
00666         DBGP("a3c90x_hw_start\n");
00667 
00668         /* 3C556: Invert MII power */
00669         if (inf_3c90x->is3c556) {
00670                 unsigned int tmp;
00671                 a3c90x_internal_SetWindow(inf_3c90x, winAddressing2);
00672                 tmp = inw(inf_3c90x->IOAddr + regResetOptions_2_w);
00673                 tmp |= 0x4000;
00674                 outw(tmp, inf_3c90x->IOAddr + regResetOptions_2_w);
00675         }
00676 
00677         /* Copy MAC address into the NIC registers */
00678         a3c90x_internal_SetWindow(inf_3c90x, winAddressing2);
00679         for (i = 0; i < ETH_ALEN; i++)
00680                 outb(netdev->ll_addr[i],
00681                      inf_3c90x->IOAddr + regStationAddress_2_3w + i);
00682         for (i = 0; i < ETH_ALEN; i++)
00683                 outb(0, inf_3c90x->IOAddr + regStationMask_2_3w + i);
00684 
00685         /* Read the media options register, print a message and set default
00686         * xcvr.
00687         *
00688         * Uses Media Option command on B revision, Reset Option on non-B
00689         * revision cards -- same register address
00690         */
00691         a3c90x_internal_SetWindow(inf_3c90x, winTxRxOptions3);
00692         mopt = inw(inf_3c90x->IOAddr + regResetMediaOptions_3_w);
00693 
00694         /* mask out VCO bit that is defined as 10baseFL bit on B-rev cards */
00695         if (!inf_3c90x->isBrev) {
00696                 mopt &= 0x7F;
00697         }
00698 
00699         DBG("Connectors present: ");
00700         c = 0;
00701         linktype = 0x0008;
00702         if (mopt & 0x01) {
00703                 DBG("%s100Base-T4", (c++) ? ", " : "");
00704                 linktype = linkMII;
00705         }
00706         if (mopt & 0x04) {
00707                 DBG("%s100Base-FX", (c++) ? ", " : "");
00708                 linktype = link100BaseFX;
00709         }
00710         if (mopt & 0x10) {
00711                 DBG("%s10Base-2", (c++) ? ", " : "");
00712                 linktype = link10Base2;
00713         }
00714         if (mopt & 0x20) {
00715                 DBG("%sAUI", (c++) ? ", " : "");
00716                 linktype = linkAUI;
00717         }
00718         if (mopt & 0x40) {
00719                 DBG("%sMII", (c++) ? ", " : "");
00720                 linktype = linkMII;
00721         }
00722         if ((mopt & 0xA) == 0xA) {
00723                 DBG("%s10Base-T / 100Base-TX", (c++) ? ", " : "");
00724                 linktype = linkAutoneg;
00725         } else if ((mopt & 0xA) == 0x2) {
00726                 DBG("%s100Base-TX", (c++) ? ", " : "");
00727                 linktype = linkAutoneg;
00728         } else if ((mopt & 0xA) == 0x8) {
00729                 DBG("%s10Base-T", (c++) ? ", " : "");
00730                 linktype = linkAutoneg;
00731         }
00732         DBG(".\n");
00733 
00734         /* Determine transceiver type to use, depending on value stored in
00735         * eeprom 0x16
00736         */
00737         if (inf_3c90x->isBrev) {
00738                 if ((inf_3c90x->eeprom[0x16] & 0xFF00) == XCVR_MAGIC) {
00739                         /* User-defined */
00740                         linktype = inf_3c90x->eeprom[0x16] & 0x000F;
00741                 }
00742         } else {
00743                 /* I don't know what MII MAC only mode is!!! */
00744                 if (linktype == linkExternalMII) {
00745                         if (inf_3c90x->isBrev)
00746                                 DBG("WARNING: MII External MAC Mode only supported on B-revision " "cards!!!!\nFalling Back to MII Mode\n");
00747                         linktype = linkMII;
00748                 }
00749         }
00750 
00751         /* enable DC converter for 10-Base-T */
00752         if (linktype == link10Base2) {
00753                 a3c90x_internal_IssueCommand(inf_3c90x->IOAddr,
00754                                              cmdEnableDcConverter, 0);
00755         }
00756 
00757         /* Set the link to the type we just determined. */
00758         a3c90x_internal_SetWindow(inf_3c90x, winTxRxOptions3);
00759         cfg = inl(inf_3c90x->IOAddr + regInternalConfig_3_l);
00760         cfg &= ~(0xF << 20);
00761         cfg |= (linktype << 20);
00762 
00763         DBG("Setting internal cfg register: 0x%08X (linktype: 0x%02X)\n",
00764             cfg, linktype);
00765 
00766         outl(cfg, inf_3c90x->IOAddr + regInternalConfig_3_l);
00767 
00768         /* Now that we set the xcvr type, reset the Tx and Rx */
00769         a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdTxReset, 0x00);
00770 
00771         if (!inf_3c90x->isBrev)
00772                 outb(0x01, inf_3c90x->IOAddr + regTxFreeThresh_b);
00773 
00774         /* Set the RX filter = receive only individual pkts & multicast & bcast. */
00775         a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdSetRxFilter,
00776                                      0x01 + 0x02 + 0x04);
00777 
00778 
00779         /*
00780         * set Indication and Interrupt flags , acknowledge any IRQ's
00781         */
00782         a3c90x_internal_IssueCommand(inf_3c90x->IOAddr,
00783                                      cmdSetInterruptEnable,
00784          INT_TXCOMPLETE | INT_UPCOMPLETE);
00785         a3c90x_internal_IssueCommand(inf_3c90x->IOAddr,
00786                                      cmdSetIndicationEnable,
00787          INT_TXCOMPLETE | INT_UPCOMPLETE);
00788         a3c90x_internal_IssueCommand(inf_3c90x->IOAddr,
00789                                      cmdAcknowledgeInterrupt, 0x661);
00790 }

static int a3c90x_open ( struct net_device netdev  )  [static]

a3c90x_open - Routine to initialize the card.

Initialize hardware, allocate TX and RX ring, send RX ring address to the NIC.

Parameters:
netdev Network device info
Return values:
Returns 0 on success, negative on failure

Definition at line 800 of file 3c90x.c.

References a3c90x_free_resources(), a3c90x_hw_start(), a3c90x_internal_IssueCommand(), a3c90x_reset(), a3c90x_setup_rx_ring(), a3c90x_setup_tx_ring(), cmdRxEnable, cmdTxEnable, DBG, DBGP, INF_3C90X::IOAddr, netdev_priv(), outl, regUpListPtr_l, INF_3C90X::rx_ring, and virt_to_bus().

00801 {
00802         int rc;
00803         struct INF_3C90X *inf_3c90x = netdev_priv(netdev);
00804 
00805         DBGP("a3c90x_open\n");
00806 
00807         a3c90x_hw_start(netdev);
00808 
00809         rc = a3c90x_setup_tx_ring(inf_3c90x);
00810         if (rc != 0) {
00811                 DBG("Error setting up TX Ring\n");
00812                 goto error;
00813         }
00814 
00815         rc = a3c90x_setup_rx_ring(inf_3c90x);
00816         if (rc != 0) {
00817                 DBG("Error setting up RX Ring\n");
00818                 goto error;
00819         }
00820 
00821         /* send rx_ring address to NIC */
00822         outl(virt_to_bus(inf_3c90x->rx_ring),
00823              inf_3c90x->IOAddr + regUpListPtr_l);
00824 
00825         /* enable packet transmission and reception */
00826         a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdTxEnable, 0);
00827         a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdRxEnable, 0);
00828 
00829         return 0;
00830 
00831       error:
00832         a3c90x_free_resources(inf_3c90x);
00833         a3c90x_reset(inf_3c90x);
00834         return rc;
00835 }

static void a3c90x_close ( struct net_device netdev  )  [static]

a3c90x_close - free()s TX and RX ring, disablex RX/TX, resets NIC

Parameters:
netdev Network device info

Definition at line 842 of file 3c90x.c.

References a3c90x_free_resources(), a3c90x_reset(), cmdRxDisable, cmdTxDisable, DBGP, INF_3C90X::IOAddr, netdev_priv(), outw, and regCommandIntStatus_w.

00843 {
00844         struct INF_3C90X *inf_3c90x = netdev_priv(netdev);
00845 
00846         DBGP("a3c90x_close\n");
00847 
00848         a3c90x_reset(inf_3c90x);
00849         outw(cmdRxDisable, inf_3c90x->IOAddr + regCommandIntStatus_w);
00850         outw(cmdTxDisable, inf_3c90x->IOAddr + regCommandIntStatus_w);
00851         a3c90x_free_resources(inf_3c90x);
00852 }

static int a3c90x_probe ( struct pci_device pci,
const struct pci_device_id *pci_id  __unused 
) [static]

a3c90x_probe: exported routine to probe for the 3c905 card.

If this routine is called, the pci functions did find the card. We read the eeprom here and get the MAC address. Initialization is done in a3c90x_open().

Parameters:
pci PCI device info @ pci_id PCI device IDs
Return values:
rc Returns 0 on success, negative on failure

Definition at line 873 of file 3c90x.c.

References a3c90x_internal_ReadEeprom(), a3c90x_internal_ReadEepromContents(), a3c90x_internal_WriteEeprom(), a3c90x_reset(), adjust_pci_device(), alloc_etherdev(), nvs_device::block_size, INF_3C90X::CurrentWindow, DBG, DBGP, pci_device::dev, net_device::dev, pci_device::device, INF_3C90X::eeprom, eepromHwAddrOffset, EINVAL, ENOMEM, net_device::hw_addr, INF_3C90X::IOAddr, pci_device::ioaddr, INF_3C90X::is3c556, INF_3C90X::isBrev, memset(), netdev, netdev_init(), netdev_link_up(), netdev_priv(), netdev_put(), INF_3C90X::nvs, pci_set_drvdata(), nvs_device::read, register_netdev(), nvs_device::size, pci_device::vendor, winNone, nvs_device::word_len_log2, and nvs_device::write.

00875 {
00876 
00877         struct net_device *netdev;
00878         struct INF_3C90X *inf_3c90x;
00879         unsigned char *HWAddr;
00880         int rc;
00881 
00882         DBGP("a3c90x_probe\n");
00883 
00884         if (pci->ioaddr == 0)
00885                 return -EINVAL;
00886 
00887         netdev = alloc_etherdev(sizeof(*inf_3c90x));
00888         if (!netdev)
00889                 return -ENOMEM;
00890 
00891         netdev_init(netdev, &a3c90x_operations);
00892         pci_set_drvdata(pci, netdev);
00893         netdev->dev = &pci->dev;
00894 
00895         inf_3c90x = netdev_priv(netdev);
00896         memset(inf_3c90x, 0, sizeof(*inf_3c90x));
00897 
00898         adjust_pci_device(pci);
00899 
00900         inf_3c90x->is3c556 = (pci->device == 0x6055);
00901         inf_3c90x->IOAddr = pci->ioaddr;
00902         inf_3c90x->CurrentWindow = winNone;
00903 
00904         inf_3c90x->isBrev = 1;
00905         switch (pci->device) {
00906         case 0x9000:            /* 10 Base TPO             */
00907         case 0x9001:            /* 10/100 T4               */
00908         case 0x9050:            /* 10/100 TPO              */
00909         case 0x9051:            /* 10 Base Combo           */
00910                 inf_3c90x->isBrev = 0;
00911                 break;
00912         }
00913 
00914         DBG("[3c90x]: found NIC(0x%04X, 0x%04X), isBrev=%d, is3c556=%d\n",
00915             pci->vendor, pci->device, inf_3c90x->isBrev,
00916             inf_3c90x->is3c556);
00917 
00918         /* initialize nvs device */
00919         inf_3c90x->nvs.word_len_log2 = 1;       /* word */
00920         inf_3c90x->nvs.size = (inf_3c90x->isBrev ? 0x20 : 0x17);
00921         inf_3c90x->nvs.block_size = 1;
00922         inf_3c90x->nvs.read = a3c90x_internal_ReadEeprom;
00923         inf_3c90x->nvs.write = a3c90x_internal_WriteEeprom;
00924 
00925         /* reset NIC before accessing any data from it */
00926         a3c90x_reset(inf_3c90x);
00927 
00928         /* load eeprom contents to inf_3c90x->eeprom */
00929         a3c90x_internal_ReadEepromContents(inf_3c90x);
00930 
00931         HWAddr = netdev->hw_addr;
00932 
00933         /* Retrieve the Hardware address */
00934         HWAddr[0] = inf_3c90x->eeprom[eepromHwAddrOffset + 0] >> 8;
00935         HWAddr[1] = inf_3c90x->eeprom[eepromHwAddrOffset + 0] & 0xFF;
00936         HWAddr[2] = inf_3c90x->eeprom[eepromHwAddrOffset + 1] >> 8;
00937         HWAddr[3] = inf_3c90x->eeprom[eepromHwAddrOffset + 1] & 0xFF;
00938         HWAddr[4] = inf_3c90x->eeprom[eepromHwAddrOffset + 2] >> 8;
00939         HWAddr[5] = inf_3c90x->eeprom[eepromHwAddrOffset + 2] & 0xFF;
00940 
00941         /* we don't handle linkstates yet, so we're always up */
00942         netdev_link_up(netdev);
00943 
00944         if ((rc = register_netdev(netdev)) != 0) {
00945                 DBG("3c90x: register_netdev() failed\n");
00946                 netdev_put(netdev);
00947                 return rc;
00948         }
00949 
00950         return 0;
00951 }


Variable Documentation

Initial value:

 {
        .open = a3c90x_open,
        .close = a3c90x_close,
        .poll = a3c90x_poll,
        .transmit = a3c90x_transmit,
        .irq = a3c90x_irq,
}

Definition at line 854 of file 3c90x.c.

struct pci_device_id a3c90x_nics[] [static]

Initial value:

 {

        PCI_ROM(0x10b7, 0x6055, "3c556", "3C556", 0),   
        PCI_ROM(0x10b7, 0x9000, "3c905-tpo", "3Com900-TPO", 0), 
        PCI_ROM(0x10b7, 0x9001, "3c905-t4", "3Com900-Combo", 0),        
        PCI_ROM(0x10b7, 0x9050, "3c905-tpo100", "3Com905-TX", 0),       
        PCI_ROM(0x10b7, 0x9051, "3c905-combo", "3Com905-T4", 0),        

        PCI_ROM(0x10b7, 0x9004, "3c905b-tpo", "3Com900B-TPO", 0),       
        PCI_ROM(0x10b7, 0x9005, "3c905b-combo", "3Com900B-Combo", 0),   
        PCI_ROM(0x10b7, 0x9006, "3c905b-tpb2", "3Com900B-2/T", 0),      
        PCI_ROM(0x10b7, 0x900a, "3c905b-fl", "3Com900B-FL", 0), 
        PCI_ROM(0x10b7, 0x9055, "3c905b-tpo100", "3Com905B-TX", 0),     
        PCI_ROM(0x10b7, 0x9056, "3c905b-t4", "3Com905B-T4", 0), 
        PCI_ROM(0x10b7, 0x9058, "3c905b-9058", "3Com905B-9058", 0),     
        PCI_ROM(0x10b7, 0x905a, "3c905b-fx", "3Com905B-FL", 0), 

        PCI_ROM(0x10b7, 0x9200, "3c905c-tpo", "3Com905C-TXM", 0),       
        PCI_ROM(0x10b7, 0x9202, "3c920b-emb-ati", "3c920B-EMB-WNM (ATI Radeon 9100 IGP)", 0),   
        PCI_ROM(0x10b7, 0x9210, "3c920b-emb-wnm", "3Com20B-EMB WNM", 0),
        PCI_ROM(0x10b7, 0x9800, "3c980", "3Com980-Cyclone", 0), 
        PCI_ROM(0x10b7, 0x9805, "3c9805", "3Com9805", 0),       
        PCI_ROM(0x10b7, 0x7646, "3csoho100-tx", "3CSOHO100-TX", 0),     
        PCI_ROM(0x10b7, 0x4500, "3c450", "3Com450 HomePNA Tornado", 0),
        PCI_ROM(0x10b7, 0x1201, "3c982a", "3Com982A", 0),
        PCI_ROM(0x10b7, 0x1202, "3c982b", "3Com982B", 0),
}

Definition at line 953 of file 3c90x.c.

struct pci_driver a3c90x_driver __pci_driver

Initial value:

 {
        .ids = a3c90x_nics,
        .id_count = (sizeof(a3c90x_nics) / sizeof(a3c90x_nics[0])),
        .probe = a3c90x_probe,
        .remove = a3c90x_remove,
}

Definition at line 981 of file 3c90x.c.


Generated on Tue Apr 6 20:01:18 2010 for gPXE by  doxygen 1.5.7.1