iPXE
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 <ipxe/ethernet.h>
#include <ipxe/if_ether.h>
#include <ipxe/io.h>
#include <ipxe/iobuf.h>
#include <ipxe/malloc.h>
#include <ipxe/netdevice.h>
#include <ipxe/pci.h>
#include <ipxe/timer.h>
#include <ipxe/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 iPXE 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 iPXE 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)
 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()

FILE_LICENCE ( BSD2 )

◆ a3c90x_internal_IssueCommand()

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
ioaddrIOAddress of the NIC
cmdCommand to be issued
paramCommand parameter

Definition at line 70 of file 3c90x.c.

71{
72 unsigned int val = (cmd << 11) | param;
73 int cnt = 0;
74
75 DBGP("a3c90x_internal_IssueCommand\n");
76
77 /* Send the cmd to the cmd register */
79
80 /* Wait for the cmd to complete */
81 for (cnt = 0; cnt < 100000; cnt++) {
83 continue;
84 } else {
85 DBG2("Command 0x%04X finished in time. cnt = %d.\n", cmd, cnt);
86 return;
87 }
88 }
89
90 DBG("Command 0x%04X DID NOT finish in time. cnt = %d.\n", cmd, cnt);
91}
@ regCommandIntStatus_w
Definition 3c90x.h:83
#define INT_CMDINPROGRESS
Definition 3c90x.h:261
struct golan_eqe_cmd cmd
Definition CIB_PRM.h:1
static unsigned long ioaddr
Definition davicom.c:129
#define DBGP(...)
Definition compiler.h:532
#define DBG2(...)
Definition compiler.h:515
#define DBG(...)
Print a debugging message.
Definition compiler.h:498
struct hv_monitor_parameter param[4][32]
Parameters.
Definition hyperv.h:13
#define inw(io_addr)
Definition io.h:292
#define outw(data, io_addr)
Definition io.h:320
void __asmcall int val
Definition setjmp.h:12

References cmd, DBG, DBG2, DBGP, INT_CMDINPROGRESS, inw, ioaddr, outw, param, regCommandIntStatus_w, and val.

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

◆ a3c90x_internal_SetWindow()

void a3c90x_internal_SetWindow ( struct INF_3C90X * inf_3c90x,
int window )
static

a3c90x_internal_SetWindow: selects a register window set.

Parameters
inf_3c90xprivate NIC data
windowwindow to be selected

Definition at line 99 of file 3c90x.c.

100{
101 DBGP("a3c90x_internal_SetWindow\n");
102 /* Window already as set? */
103 if (inf_3c90x->CurrentWindow == window)
104 return;
105
106 /* Issue the window command. */
109 inf_3c90x->CurrentWindow = window;
110
111 return;
112}
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
Definition 3c90x.c:70
@ cmdSelectRegisterWindow
Definition 3c90x.h:173
unsigned char CurrentWindow
Definition 3c90x.h:295
unsigned int IOAddr
Definition 3c90x.h:296

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

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

◆ a3c90x_internal_WaitForEeprom()

void a3c90x_internal_WaitForEeprom ( struct INF_3C90X * inf_3c90x)
static

Definition at line 114 of file 3c90x.c.

115{
116 int cnt = 0;
117
118 DBGP("a3c90x_internal_WaitForEeprom\n");
119
120 while (eepromBusy & inw(inf_3c90x->IOAddr + regEepromCommand_0_w)) {
121 if (cnt == EEPROM_TIMEOUT) {
122 DBG("Read from eeprom failed: timeout\n");
123 return;
124 }
125 udelay(1);
126 cnt++;
127 }
128}
@ regEepromCommand_0_w
Definition 3c90x.h:150
#define EEPROM_TIMEOUT
Definition 3c90x.h:273
@ eepromBusy
Definition 3c90x.h:233
void udelay(unsigned long usecs)
Delay for a fixed number of microseconds.
Definition timer.c:61

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

Referenced by a3c90x_internal_ReadEeprom().

◆ a3c90x_internal_ReadEeprom()

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
nvsnvs data.
addresseeprom address to read data from.
datadata is put here.
lennumber of bytes to read.

Definition at line 141 of file 3c90x.c.

142{
143 unsigned short *dest = (unsigned short *) data;
144 struct INF_3C90X *inf_3c90x =
145 container_of(nvs, struct INF_3C90X, nvs);
146
147 DBGP("a3c90x_internal_ReadEeprom\n");
148
149 /* we support reading 2 bytes only */
150 assert(len == 2);
151
152 /* Select correct window */
154
155 /* set eepromRead bits in command sent to NIC */
156 address += (inf_3c90x->is3c556 ? eepromRead_556 : eepromRead);
157
159 /* send address to NIC */
162
163 /* read value */
164 *dest = inw(inf_3c90x->IOAddr + regEepromData_0_w);
165
166 return 0;
167}
static void a3c90x_internal_WaitForEeprom(struct INF_3C90X *inf_3c90x)
Definition 3c90x.c:114
static void a3c90x_internal_SetWindow(struct INF_3C90X *inf_3c90x, int window)
a3c90x_internal_SetWindow: selects a register window set.
Definition 3c90x.c:99
@ regEepromData_0_w
Definition 3c90x.h:149
@ eepromRead
Definition 3c90x.h:234
@ eepromRead_556
Definition 3c90x.h:235
@ winEepromBios0
Definition 3c90x.h:166
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" retur dest)
Definition string.h:151
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
ring len
Length.
Definition dwmac.h:226
uint8_t data[48]
Additional event data.
Definition ena.h:11
uint64_t address
Base address.
Definition ena.h:13
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
struct nvs_device nvs
Definition 3c90x.h:306
unsigned int is3c556
Definition 3c90x.h:293

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

Referenced by a3c90x_probe().

◆ a3c90x_internal_WriteEeprom()

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
nvsnvs data.
addresseeprom address to read data from.
datadata is put here.
lennumber of bytes to read.

Definition at line 179 of file 3c90x.c.

182{
183 return -ENOTSUP;
184}
#define ENOTSUP
Operation not supported.
Definition errno.h:590

References __unused, address, data, ENOTSUP, and len.

Referenced by a3c90x_probe().

◆ a3c90x_internal_ReadEepromContents()

void a3c90x_internal_ReadEepromContents ( struct INF_3C90X * inf_3c90x)
static

Definition at line 186 of file 3c90x.c.

187{
188 int eeprom_size = (inf_3c90x->isBrev ? 0x20 : 0x17) * 2;
189
190 DBGP("a3c90x_internal_ReadEepromContents\n");
191
192 nvs_read(&inf_3c90x->nvs, 0, inf_3c90x->eeprom, eeprom_size);
193}
int nvs_read(struct nvs_device *nvs, unsigned int address, void *data, size_t len)
Read from non-volatile storage device.
Definition nvs.c:76
unsigned char isBrev
Definition 3c90x.h:294
unsigned short eeprom[0x21]
Definition 3c90x.h:297

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

Referenced by a3c90x_probe().

◆ a3c90x_reset()

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_3c90xPrivate NIC data

Definition at line 204 of file 3c90x.c.

205{
206 DBGP("a3c90x_reset\n");
207 /* Send the reset command to the card */
208 DBG2("3c90x: Issuing RESET\n");
209
210 /* reset of the receiver on B-revision cards re-negotiates the link
211 * takes several seconds (a computer eternity), so we don't reset
212 * it here.
213 */
217
218 /* global reset command resets station mask, non-B revision cards
219 * require explicit reset of values
220 */
222 outw(0, inf_3c90x->IOAddr + regStationMask_2_3w + 0);
223 outw(0, inf_3c90x->IOAddr + regStationMask_2_3w + 2);
224 outw(0, inf_3c90x->IOAddr + regStationMask_2_3w + 4);
225
228
229 /* enable rxComplete and txComplete indications */
233
234 /* acknowledge any pending status flags */
237
238 return;
239}
#define INT_UPCOMPLETE
Definition 3c90x.h:260
@ cmdAcknowledgeInterrupt
Definition 3c90x.h:183
@ cmdGlobalReset
Definition 3c90x.h:172
@ cmdRxEnable
Definition 3c90x.h:176
@ cmdTxEnable
Definition 3c90x.h:179
@ cmdSetIndicationEnable
Definition 3c90x.h:185
@ regStationMask_2_3w
Definition 3c90x.h:140
@ globalResetMaskNetwork
Definition 3c90x.h:198
@ winAddressing2
Definition 3c90x.h:164
#define INT_TXCOMPLETE
Definition 3c90x.h:253

References a3c90x_internal_IssueCommand(), a3c90x_internal_SetWindow(), cmdAcknowledgeInterrupt, cmdGlobalReset, cmdRxEnable, cmdSetIndicationEnable, cmdTxEnable, DBG2, DBGP, globalResetMaskNetwork, INT_TXCOMPLETE, INT_UPCOMPLETE, INF_3C90X::IOAddr, outw, regStationMask_2_3w, and winAddressing2.

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

◆ a3c90x_setup_tx_ring()

int a3c90x_setup_tx_ring ( struct INF_3C90X * p)
static

a3c90x_setup_tx_ring - Allocates TX ring, initialize tx_desc values

Parameters
pPrivate NIC data
Return values
Returns0 on success, negative on failure

Definition at line 248 of file 3c90x.c.

249{
250 DBGP("a3c90x_setup_tx_ring\n");
251 p->tx_ring =
252 malloc_phys(TX_RING_SIZE * sizeof(struct TXD), TX_RING_ALIGN);
253
254 if (!p->tx_ring) {
255 DBG("Could not allocate TX-ring\n");
256 return -ENOMEM;
257 }
258
259 memset(p->tx_ring, 0, TX_RING_SIZE * sizeof(struct TXD));
260 p->tx_cur = 0;
261 p->tx_cnt = 0;
262 p->tx_tail = 0;
263
264 return 0;
265}
#define TX_RING_SIZE
Definition 3c515.c:85
#define TX_RING_ALIGN
Definition 3c90x.h:267
#define ENOMEM
Not enough space.
Definition errno.h:535
void * memset(void *dest, int character, size_t len) __nonnull
void * malloc_phys(size_t size, size_t phys_align)
Allocate memory with specified physical alignment.
Definition malloc.c:707
struct TXD * tx_ring
Definition 3c90x.h:302
unsigned int tx_cur
Definition 3c90x.h:298
unsigned int tx_tail
Definition 3c90x.h:300
unsigned int tx_cnt
Definition 3c90x.h:299
Definition 3c90x.h:276

References DBG, DBGP, ENOMEM, malloc_phys(), 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().

◆ a3c90x_process_tx_packets()

void a3c90x_process_tx_packets ( struct net_device * netdev)
static

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

Parameters
netdevNetwork device info

Definition at line 273 of file 3c90x.c.

274{
275 struct INF_3C90X *p = netdev->priv;
276 unsigned int downlist_ptr;
277
278 DBGP("a3c90x_process_tx_packets\n");
279
280 DBG2(" tx_cnt: %d\n", p->tx_cnt);
281
282 while (p->tx_tail != p->tx_cur) {
283
284 downlist_ptr = inl(p->IOAddr + regDnListPtr_l);
285
286 DBG2(" downlist_ptr: %#08x\n", downlist_ptr);
287 DBG2(" tx_tail: %d tx_cur: %d\n", p->tx_tail, p->tx_cur);
288
289 /* NIC is currently working on this tx desc */
290 if(downlist_ptr == virt_to_bus(p->tx_ring + p->tx_tail))
291 return;
292
294
295 DBG2("transmitted packet\n");
296 DBG2(" size: %zd\n", iob_len(p->tx_iobuf[p->tx_tail]));
297
298 p->tx_tail = (p->tx_tail + 1) % TX_RING_SIZE;
299 p->tx_cnt--;
300 }
301}
@ regDnListPtr_l
Definition 3c90x.h:76
static struct net_device * netdev
Definition gdbudp.c:53
#define inl(io_addr)
Definition io.h:301
static __always_inline unsigned long virt_to_bus(volatile const void *addr)
Convert virtual address to a bus address.
Definition io.h:184
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
static void netdev_tx_complete(struct net_device *netdev, struct io_buffer *iobuf)
Complete network transmission.
Definition netdevice.h:767
struct io_buffer * tx_iobuf[TX_RING_SIZE]
Definition 3c90x.h:304

References DBG2, DBGP, inl, INF_3C90X::IOAddr, iob_len(), netdev, 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().

◆ a3c90x_free_tx_ring()

void a3c90x_free_tx_ring ( struct INF_3C90X * p)
static

Definition at line 303 of file 3c90x.c.

304{
305 DBGP("a3c90x_free_tx_ring\n");
306
307 free_phys(p->tx_ring, TX_RING_SIZE * sizeof(struct TXD));
308 p->tx_ring = NULL;
309 /* io_buffers are free()ed by netdev_tx_complete[,_err]() */
310}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
void free_phys(void *ptr, size_t size)
Free memory allocated with malloc_phys()
Definition malloc.c:723

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

Referenced by a3c90x_free_resources().

◆ a3c90x_transmit()

int a3c90x_transmit ( struct net_device * netdev,
struct io_buffer * iob )
static

a3c90x_transmit - Transmits a packet.

Parameters
netdevNetwork device info
iobio_buffer containing the data to be send
Return values
Returns0 on success, negative on failure

Definition at line 320 of file 3c90x.c.

322{
323 struct INF_3C90X *inf_3c90x = netdev->priv;
324 struct TXD *tx_cur_desc;
325 struct TXD *tx_prev_desc;
326
327 unsigned int len;
328 unsigned int downlist_ptr;
329
330 DBGP("a3c90x_transmit\n");
331
332 if (inf_3c90x->tx_cnt == TX_RING_SIZE) {
333 DBG("TX-Ring overflow\n");
334 return -ENOBUFS;
335 }
336
337 inf_3c90x->tx_iobuf[inf_3c90x->tx_cur] = iob;
338 tx_cur_desc = inf_3c90x->tx_ring + inf_3c90x->tx_cur;
339
340 tx_prev_desc = inf_3c90x->tx_ring +
341 (((inf_3c90x->tx_cur + TX_RING_SIZE) - 1) % TX_RING_SIZE);
342
343 len = iob_len(iob);
344
345 /* Setup the DPD (download descriptor) */
346 tx_cur_desc->DnNextPtr = 0;
347
348 /* FrameStartHeader differs in 90x and >= 90xB
349 * It contains the packet length in 90x and a round up boundary and
350 * packet ID for 90xB and 90xC. Disable packet length round-up on the
351 * later revisions.
352 */
353 tx_cur_desc->FrameStartHeader =
354 fshTxIndicate | (inf_3c90x->isBrev ? fshRndupDefeat : len);
355
356 tx_cur_desc->DataAddr = virt_to_bus(iob->data);
357 tx_cur_desc->DataLength = len | downLastFrag;
358
359 /* We have to stall the download engine, so the NIC won't access the
360 * tx descriptor while we modify it. There is a way around this
361 * from revision B and upwards. To stay compatible with older revisions
362 * we don't use it here.
363 */
365 dnStall);
366
367 tx_prev_desc->DnNextPtr = virt_to_bus(tx_cur_desc);
368
369 downlist_ptr = inl(inf_3c90x->IOAddr + regDnListPtr_l);
370 if (downlist_ptr == 0) {
371 /* currently no DownList, sending a new one */
372 outl(virt_to_bus(tx_cur_desc),
373 inf_3c90x->IOAddr + regDnListPtr_l);
374 }
375
376 /* End Stall */
378 dnUnStall);
379
380 inf_3c90x->tx_cur = (inf_3c90x->tx_cur + 1) % TX_RING_SIZE;
381 inf_3c90x->tx_cnt++;
382
383 return 0;
384}
@ cmdStallCtl
Definition 3c90x.h:178
@ dnUnStall
Definition 3c90x.h:223
@ dnStall
Definition 3c90x.h:222
@ downLastFrag
Definition 3c90x.h:210
@ fshRndupDefeat
Definition 3c90x.h:205
@ fshTxIndicate
Definition 3c90x.h:203
#define ENOBUFS
No buffer space available.
Definition errno.h:499
#define outl(data, io_addr)
Definition io.h:330
volatile unsigned int DataLength
Definition 3c90x.h:280
volatile unsigned int DataAddr
Definition 3c90x.h:279
volatile unsigned int FrameStartHeader
Definition 3c90x.h:278
volatile unsigned int DnNextPtr
Definition 3c90x.h:277
void * data
Start of data.
Definition iobuf.h:53

References a3c90x_internal_IssueCommand(), cmdStallCtl, io_buffer::data, TXD::DataAddr, TXD::DataLength, DBG, DBGP, TXD::DnNextPtr, dnStall, dnUnStall, downLastFrag, ENOBUFS, TXD::FrameStartHeader, fshRndupDefeat, fshTxIndicate, inl, INF_3C90X::IOAddr, iob_len(), INF_3C90X::isBrev, len, netdev, 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().

◆ a3c90x_prepare_rx_desc()

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
pNIC private data
indexIndex for rx_iobuf and rx_ring array

Definition at line 393 of file 3c90x.c.

394{
395 DBGP("a3c90x_prepare_rx_desc\n");
396 DBG2("Populating rx_desc %d\n", index);
397
398 /* We have to stall the upload engine, so the NIC won't access the
399 * rx descriptor while we modify it. There is a way around this
400 * from revision B and upwards. To stay compatible with older revisions
401 * we don't use it here.
402 */
404
407 p->rx_ring[index].UpPktStatus = 0;
408
409 /* unstall upload engine */
411}
@ upUnStall
Definition 3c90x.h:220
@ upStall
Definition 3c90x.h:219
#define RX_BUF_SIZE
Definition 3c90x.h:269
@ upLastFrag
Definition 3c90x.h:209
long index
Definition bigint.h:65
struct RXD * rx_ring
Definition 3c90x.h:303
struct io_buffer * rx_iobuf[RX_RING_SIZE]
Definition 3c90x.h:305
volatile unsigned int DataAddr
Definition 3c90x.h:287
volatile unsigned int UpPktStatus
Definition 3c90x.h:286
volatile unsigned int DataLength
Definition 3c90x.h:288

References a3c90x_internal_IssueCommand(), cmdStallCtl, io_buffer::data, RXD::DataAddr, RXD::DataLength, DBG2, DBGP, index, 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().

◆ a3c90x_refill_rx_ring()

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
pNIC private data

Definition at line 420 of file 3c90x.c.

421{
422 int i;
423 unsigned int status;
424 struct RXD *rx_cur_desc;
425
426 DBGP("a3c90x_refill_rx_ring\n");
427
428 for (i = 0; i < RX_RING_SIZE; i++) {
429 rx_cur_desc = p->rx_ring + i;
430 status = rx_cur_desc->UpPktStatus;
431
432 /* only refill used descriptor */
433 if (!(status & upComplete))
434 continue;
435
436 /* we still need to process this descriptor */
437 if (p->rx_iobuf[i] != NULL)
438 continue;
439
441 if (p->rx_iobuf[i] == NULL) {
442 DBG("alloc_iob() failed\n");
443 break;
444 }
445
447 }
448}
#define RX_RING_SIZE
Definition 3c515.c:86
static void a3c90x_prepare_rx_desc(struct INF_3C90X *p, unsigned int index)
a3c90x_prepare_rx_desc - fills the rx desc with initial data
Definition 3c90x.c:393
@ upComplete
Definition 3c90x.h:214
uint8_t status
Status.
Definition ena.h:5
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition iobuf.c:131
Definition 3c90x.h:284

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

Referenced by a3c90x_process_rx_packets(), and a3c90x_setup_rx_ring().

◆ a3c90x_setup_rx_ring()

int a3c90x_setup_rx_ring ( struct INF_3C90X * p)
static

a3c90x_setup_rx_ring - Allocates RX ring, initialize rx_desc values

Parameters
pPrivate NIC data
Return values
Returns0 on success, negative on failure

Definition at line 457 of file 3c90x.c.

458{
459 int i;
460
461 DBGP("a3c90x_setup_rx_ring\n");
462
463 p->rx_ring =
464 malloc_phys(RX_RING_SIZE * sizeof(struct RXD), RX_RING_ALIGN);
465
466 if (!p->rx_ring) {
467 DBG("Could not allocate RX-ring\n");
468 return -ENOMEM;
469 }
470
471 p->rx_cur = 0;
472
473 for (i = 0; i < RX_RING_SIZE; i++) {
474 p->rx_ring[i].UpNextPtr =
475 virt_to_bus(p->rx_ring + (i + 1));
476
477 /* these are needed so refill_rx_ring initializes the ring */
479 p->rx_iobuf[i] = NULL;
480 }
481
482 /* Loop the ring */
483 p->rx_ring[i - 1].UpNextPtr = virt_to_bus(p->rx_ring);
484
486
487 return 0;
488}
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.
Definition 3c90x.c:420
#define RX_RING_ALIGN
Definition 3c90x.h:268
unsigned int rx_cur
Definition 3c90x.h:301
volatile unsigned int UpNextPtr
Definition 3c90x.h:285

References a3c90x_refill_rx_ring(), DBG, DBGP, ENOMEM, malloc_phys(), 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().

◆ a3c90x_free_rx_ring()

void a3c90x_free_rx_ring ( struct INF_3C90X * p)
static

Definition at line 490 of file 3c90x.c.

491{
492 DBGP("a3c90x_free_rx_ring\n");
493
494 free_phys(p->rx_ring, RX_RING_SIZE * sizeof(struct RXD));
495 p->rx_ring = NULL;
496}

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

Referenced by a3c90x_free_resources().

◆ a3c90x_free_rx_iobuf()

void a3c90x_free_rx_iobuf ( struct INF_3C90X * p)
static

Definition at line 498 of file 3c90x.c.

499{
500 int i;
501
502 DBGP("a3c90x_free_rx_iobuf\n");
503
504 for (i = 0; i < RX_RING_SIZE; i++) {
505 free_iob(p->rx_iobuf[i]);
506 p->rx_iobuf[i] = NULL;
507 }
508}
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153

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

Referenced by a3c90x_free_resources().

◆ a3c90x_process_rx_packets()

void a3c90x_process_rx_packets ( struct net_device * netdev)
static

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

Parameters
netdevNetwork device info

Definition at line 517 of file 3c90x.c.

518{
519 int i;
520 unsigned int rx_status;
521 struct INF_3C90X *p = netdev->priv;
522 struct RXD *rx_cur_desc;
523
524 DBGP("a3c90x_process_rx_packets\n");
525
526 for (i = 0; i < RX_RING_SIZE; i++) {
527 rx_cur_desc = p->rx_ring + p->rx_cur;
528 rx_status = rx_cur_desc->UpPktStatus;
529
530 if (!(rx_status & upComplete) && !(rx_status & upError))
531 break;
532
533 if (p->rx_iobuf[p->rx_cur] == NULL)
534 break;
535
536 if (rx_status & upError) {
537 DBG("Corrupted packet received: %#x\n", rx_status);
539 -EINVAL);
540 } else {
541 /* if we're here, we've got good packet */
542 int packet_len;
543
544 packet_len = rx_status & 0x1FFF;
545 iob_put(p->rx_iobuf[p->rx_cur], packet_len);
546
547 DBG2("received packet\n");
548 DBG2(" size: %d\n", packet_len);
549
551 }
552
553 p->rx_iobuf[p->rx_cur] = NULL; /* invalidate rx desc */
554 p->rx_cur = (p->rx_cur + 1) % RX_RING_SIZE;
555 }
557
558}
@ upError
Definition 3c90x.h:215
#define EINVAL
Invalid argument.
Definition errno.h:429
#define iob_put(iobuf, len)
Definition iobuf.h:125
void netdev_rx(struct net_device *netdev, struct io_buffer *iobuf)
Add packet to receive queue.
Definition netdevice.c:549
void netdev_rx_err(struct net_device *netdev, struct io_buffer *iobuf, int rc)
Discard received packet.
Definition netdevice.c:587

References a3c90x_refill_rx_ring(), DBG, DBG2, DBGP, EINVAL, iob_put, netdev, 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().

◆ a3c90x_poll()

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
netdevNetwork device info

Definition at line 568 of file 3c90x.c.

569{
570 struct INF_3C90X *p = netdev->priv;
571 uint16_t raw_status, int_status;
572
573 DBGP("a3c90x_poll\n");
574
575 raw_status = inw(p->IOAddr + regCommandIntStatus_w);
576 int_status = (raw_status & 0x0FFF);
577
578 if ( int_status == 0 )
579 return;
580
582 int_status);
583
584 if (int_status & INT_TXCOMPLETE)
585 outb(0x00, p->IOAddr + regTxStatus_b);
586
587 DBG2("poll: status = %#04x\n", raw_status);
588
590
592}
static void a3c90x_process_rx_packets(struct net_device *netdev)
a3c90x_process_rx_packets - Checks for received packets, reports them to iPXE with netdev_rx() or net...
Definition 3c90x.c:517
static void a3c90x_process_tx_packets(struct net_device *netdev)
a3c90x_process_tx_packets - Checks for successfully sent packets, reports them to iPXE with netdev_tx...
Definition 3c90x.c:273
@ regTxStatus_b
Definition 3c90x.h:80
unsigned short uint16_t
Definition stdint.h:11
#define outb(data, io_addr)
Definition io.h:310

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

◆ a3c90x_free_resources()

void a3c90x_free_resources ( struct INF_3C90X * p)
static

Definition at line 596 of file 3c90x.c.

597{
598 DBGP("a3c90x_free_resources\n");
599
603}
static void a3c90x_free_tx_ring(struct INF_3C90X *p)
Definition 3c90x.c:303
static void a3c90x_free_rx_iobuf(struct INF_3C90X *p)
Definition 3c90x.c:498
static void a3c90x_free_rx_ring(struct INF_3C90X *p)
Definition 3c90x.c:490

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

Referenced by a3c90x_close(), and a3c90x_open().

◆ a3c90x_remove()

void a3c90x_remove ( struct pci_device * pci)
static

a3c90x_remove - Routine to remove the card.

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

Parameters
pciPCI device info

Definition at line 611 of file 3c90x.c.

612{
613 struct net_device *netdev = pci_get_drvdata(pci);
614 struct INF_3C90X *inf_3c90x = netdev->priv;
615
616 DBGP("a3c90x_remove\n");
617
618 a3c90x_reset(inf_3c90x);
619
620 /* Disable the receiver and transmitter. */
623
627}
static void a3c90x_reset(struct INF_3C90X *inf_3c90x)
a3c90x_reset: exported function that resets the card to its default state.
Definition 3c90x.c:204
@ cmdTxDisable
Definition 3c90x.h:180
@ cmdRxDisable
Definition 3c90x.h:175
void unregister_netdev(struct net_device *netdev)
Unregister network device.
Definition netdevice.c:942
static void netdev_nullify(struct net_device *netdev)
Stop using a network device.
Definition netdevice.h:532
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition netdevice.h:576
static void * pci_get_drvdata(struct pci_device *pci)
Get PCI driver-private data.
Definition pci.h:376
A network device.
Definition netdevice.h:353

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

◆ a3c90x_irq()

void a3c90x_irq ( struct net_device * netdev,
int enable )
static

Definition at line 629 of file 3c90x.c.

630{
631 struct INF_3C90X *p = netdev->priv;
632
633 DBGP("a3c90x_irq\n");
634
635 if (enable == 0) {
636 /* disable interrupts */
639 } else {
646 0x661);
647 }
648}
@ cmdSetInterruptEnable
Definition 3c90x.h:184

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

◆ a3c90x_hw_start()

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 654 of file 3c90x.c.

655{
656 int i, c;
657 unsigned int cfg;
658 unsigned int mopt;
659 unsigned short linktype;
660 struct INF_3C90X *inf_3c90x = netdev->priv;
661
662 DBGP("a3c90x_hw_start\n");
663
664 /* 3C556: Invert MII power */
665 if (inf_3c90x->is3c556) {
666 unsigned int tmp;
668 tmp = inw(inf_3c90x->IOAddr + regResetOptions_2_w);
669 tmp |= 0x4000;
670 outw(tmp, inf_3c90x->IOAddr + regResetOptions_2_w);
671 }
672
673 /* Copy MAC address into the NIC registers */
675 for (i = 0; i < ETH_ALEN; i++)
676 outb(netdev->ll_addr[i],
677 inf_3c90x->IOAddr + regStationAddress_2_3w + i);
678 for (i = 0; i < ETH_ALEN; i++)
679 outb(0, inf_3c90x->IOAddr + regStationMask_2_3w + i);
680
681 /* Read the media options register, print a message and set default
682 * xcvr.
683 *
684 * Uses Media Option command on B revision, Reset Option on non-B
685 * revision cards -- same register address
686 */
688 mopt = inw(inf_3c90x->IOAddr + regResetMediaOptions_3_w);
689
690 /* mask out VCO bit that is defined as 10baseFL bit on B-rev cards */
691 if (!inf_3c90x->isBrev) {
692 mopt &= 0x7F;
693 }
694
695 DBG2("Connectors present: ");
696 c = 0;
697 linktype = 0x0008;
698 if (mopt & 0x01) {
699 DBG2("%s100Base-T4", (c++) ? ", " : "");
701 }
702 if (mopt & 0x04) {
703 DBG2("%s100Base-FX", (c++) ? ", " : "");
705 }
706 if (mopt & 0x10) {
707 DBG2("%s10Base-2", (c++) ? ", " : "");
709 }
710 if (mopt & 0x20) {
711 DBG2("%sAUI", (c++) ? ", " : "");
713 }
714 if (mopt & 0x40) {
715 DBG2("%sMII", (c++) ? ", " : "");
717 }
718 if ((mopt & 0xA) == 0xA) {
719 DBG2("%s10Base-T / 100Base-TX", (c++) ? ", " : "");
721 } else if ((mopt & 0xA) == 0x2) {
722 DBG2("%s100Base-TX", (c++) ? ", " : "");
724 } else if ((mopt & 0xA) == 0x8) {
725 DBG2("%s10Base-T", (c++) ? ", " : "");
727 }
728 DBG2(".\n");
729
730 /* Determine transceiver type to use, depending on value stored in
731 * eeprom 0x16
732 */
733 if (inf_3c90x->isBrev) {
734 if ((inf_3c90x->eeprom[0x16] & 0xFF00) == XCVR_MAGIC) {
735 /* User-defined */
736 linktype = inf_3c90x->eeprom[0x16] & 0x000F;
737 }
738 } else {
739 /* I don't know what MII MAC only mode is!!! */
740 if (linktype == linkExternalMII) {
741 if (inf_3c90x->isBrev)
742 DBG("WARNING: MII External MAC Mode only supported on B-revision " "cards!!!!\nFalling Back to MII Mode\n");
744 }
745 }
746
747 /* enable DC converter for 10-Base-T */
748 if (linktype == link10Base2) {
751 }
752
753 /* Set the link to the type we just determined. */
755 cfg = inl(inf_3c90x->IOAddr + regInternalConfig_3_l);
756 cfg &= ~(0xF << 20);
757 cfg |= (linktype << 20);
758
759 DBG2("Setting internal cfg register: 0x%08X (linktype: 0x%02X)\n",
760 cfg, linktype);
761
762 outl(cfg, inf_3c90x->IOAddr + regInternalConfig_3_l);
763
764 /* Now that we set the xcvr type, reset the Tx and Rx */
766
767 if (!inf_3c90x->isBrev)
768 outb(0x01, inf_3c90x->IOAddr + regTxFreeThresh_b);
769
770 /* Set the RX filter = receive only individual pkts & multicast & bcast. */
772 0x01 + 0x02 + 0x04);
773
774
775 /*
776 * set Indication and Interrupt flags , acknowledge any IRQ's
777 */
786}
#define XCVR_MAGIC
Definition 3c90x.h:55
linktype
Definition 3c90x.h:240
@ linkAutoneg
Definition 3c90x.h:246
@ linkAUI
Definition 3c90x.h:242
@ link10Base2
Definition 3c90x.h:243
@ linkMII
Definition 3c90x.h:245
@ linkExternalMII
Definition 3c90x.h:247
@ link100BaseFX
Definition 3c90x.h:244
@ cmdTxReset
Definition 3c90x.h:181
@ cmdSetRxFilter
Definition 3c90x.h:186
@ cmdEnableDcConverter
Definition 3c90x.h:174
@ regTxFreeThresh_b
Definition 3c90x.h:72
@ regResetMediaOptions_3_w
Definition 3c90x.h:130
@ regInternalConfig_3_l
Definition 3c90x.h:134
@ regStationAddress_2_3w
Definition 3c90x.h:141
@ regResetOptions_2_w
Definition 3c90x.h:139
@ winTxRxOptions3
Definition 3c90x.h:163
#define ETH_ALEN
Definition if_ether.h:9
unsigned long tmp
Definition linux_pci.h:65
@ cfg
Definition sis900.h:23

References a3c90x_internal_IssueCommand(), a3c90x_internal_SetWindow(), cfg, cmdAcknowledgeInterrupt, cmdEnableDcConverter, cmdSetIndicationEnable, cmdSetInterruptEnable, cmdSetRxFilter, cmdTxReset, DBG, DBG2, 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, netdev, outb, outl, outw, regInternalConfig_3_l, regResetMediaOptions_3_w, regResetOptions_2_w, regStationAddress_2_3w, regStationMask_2_3w, regTxFreeThresh_b, tmp, winAddressing2, winTxRxOptions3, and XCVR_MAGIC.

Referenced by a3c90x_open().

◆ a3c90x_open()

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
netdevNetwork device info
Return values
Returns0 on success, negative on failure

Definition at line 796 of file 3c90x.c.

797{
798 int rc;
799 struct INF_3C90X *inf_3c90x = netdev->priv;
800
801 DBGP("a3c90x_open\n");
802
804
805 rc = a3c90x_setup_tx_ring(inf_3c90x);
806 if (rc != 0) {
807 DBG("Error setting up TX Ring\n");
808 goto error;
809 }
810
811 rc = a3c90x_setup_rx_ring(inf_3c90x);
812 if (rc != 0) {
813 DBG("Error setting up RX Ring\n");
814 goto error;
815 }
816
818
819 /* send rx_ring address to NIC */
820 outl(virt_to_bus(inf_3c90x->rx_ring),
821 inf_3c90x->IOAddr + regUpListPtr_l);
822
824
825 /* set maximum allowed receive packet length */
828
829 /* enable packet transmission and reception */
832
833 return 0;
834
835 error:
836 a3c90x_free_resources(inf_3c90x);
837 a3c90x_reset(inf_3c90x);
838 return rc;
839}
static int a3c90x_setup_rx_ring(struct INF_3C90X *p)
a3c90x_setup_rx_ring - Allocates RX ring, initialize rx_desc values
Definition 3c90x.c:457
static int a3c90x_setup_tx_ring(struct INF_3C90X *p)
a3c90x_setup_tx_ring - Allocates TX ring, initialize tx_desc values
Definition 3c90x.c:248
static void a3c90x_free_resources(struct INF_3C90X *p)
Definition 3c90x.c:596
static void a3c90x_hw_start(struct net_device *netdev)
a3c90x_hw_start - Initialize hardware, copy MAC address to NIC registers, set default receiver
Definition 3c90x.c:654
@ regUpListPtr_l
Definition 3c90x.h:68
@ regMaxPktSize_3_w
Definition 3c90x.h:133
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
struct arbelprm_completion_with_error error
Definition arbel.h:1

References a3c90x_free_resources(), a3c90x_hw_start(), a3c90x_internal_IssueCommand(), a3c90x_internal_SetWindow(), a3c90x_reset(), a3c90x_setup_rx_ring(), a3c90x_setup_tx_ring(), cmdRxEnable, cmdStallCtl, cmdTxEnable, DBG, DBGP, error, INF_3C90X::IOAddr, netdev, outl, rc, regMaxPktSize_3_w, regUpListPtr_l, RX_BUF_SIZE, INF_3C90X::rx_ring, upStall, upUnStall, virt_to_bus(), and winTxRxOptions3.

◆ a3c90x_close()

void a3c90x_close ( struct net_device * netdev)
static

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

Parameters
netdevNetwork device info

Definition at line 846 of file 3c90x.c.

847{
848 struct INF_3C90X *inf_3c90x = netdev->priv;
849
850 DBGP("a3c90x_close\n");
851
852 a3c90x_reset(inf_3c90x);
855 a3c90x_free_resources(inf_3c90x);
856}

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

◆ a3c90x_probe()

int a3c90x_probe ( struct pci_device * pci)
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
pciPCI device info @ pci_id PCI device IDs
Return values
rcReturns 0 on success, negative on failure

Definition at line 877 of file 3c90x.c.

878{
879
880 struct net_device *netdev;
881 struct INF_3C90X *inf_3c90x;
882 unsigned char *HWAddr;
883 int rc;
884
885 DBGP("a3c90x_probe\n");
886
887 if (pci->ioaddr == 0)
888 return -EINVAL;
889
890 netdev = alloc_etherdev(sizeof(*inf_3c90x));
891 if (!netdev)
892 return -ENOMEM;
893
896 netdev->dev = &pci->dev;
897
898 inf_3c90x = netdev->priv;
899 memset(inf_3c90x, 0, sizeof(*inf_3c90x));
900
902
903 inf_3c90x->is3c556 = (pci->device == 0x6055);
904 inf_3c90x->IOAddr = pci->ioaddr;
905 inf_3c90x->CurrentWindow = winNone;
906
907 inf_3c90x->isBrev = 1;
908 switch (pci->device) {
909 case 0x9000: /* 10 Base TPO */
910 case 0x9001: /* 10/100 T4 */
911 case 0x9050: /* 10/100 TPO */
912 case 0x9051: /* 10 Base Combo */
913 inf_3c90x->isBrev = 0;
914 break;
915 }
916
917 DBG2("[3c90x]: found NIC(0x%04X, 0x%04X), isBrev=%d, is3c556=%d\n",
918 pci->vendor, pci->device, inf_3c90x->isBrev,
919 inf_3c90x->is3c556);
920
921 /* initialize nvs device */
922 inf_3c90x->nvs.word_len_log2 = 1; /* word */
923 inf_3c90x->nvs.size = (inf_3c90x->isBrev ? 0x20 : 0x17);
924 inf_3c90x->nvs.block_size = 1;
927
928 /* reset NIC before accessing any data from it */
929 a3c90x_reset(inf_3c90x);
930
931 /* load eeprom contents to inf_3c90x->eeprom */
933
934 HWAddr = netdev->hw_addr;
935
936 /* Retrieve the Hardware address */
937 HWAddr[0] = inf_3c90x->eeprom[eepromHwAddrOffset + 0] >> 8;
938 HWAddr[1] = inf_3c90x->eeprom[eepromHwAddrOffset + 0] & 0xFF;
939 HWAddr[2] = inf_3c90x->eeprom[eepromHwAddrOffset + 1] >> 8;
940 HWAddr[3] = inf_3c90x->eeprom[eepromHwAddrOffset + 1] & 0xFF;
941 HWAddr[4] = inf_3c90x->eeprom[eepromHwAddrOffset + 2] >> 8;
942 HWAddr[5] = inf_3c90x->eeprom[eepromHwAddrOffset + 2] & 0xFF;
943
944 if ((rc = register_netdev(netdev)) != 0) {
945 DBG("3c90x: register_netdev() failed\n");
947 return rc;
948 }
949
950 /* we don't handle linkstates yet, so we're always up */
952
953 return 0;
954}
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
Definition 3c90x.c:179
static struct net_device_operations a3c90x_operations
Definition 3c90x.c:858
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)...
Definition 3c90x.c:141
static void a3c90x_internal_ReadEepromContents(struct INF_3C90X *inf_3c90x)
Definition 3c90x.c:186
@ eepromHwAddrOffset
Definition 3c90x.h:236
@ winNone
Definition 3c90x.h:158
struct net_device * alloc_etherdev(size_t priv_size)
Allocate Ethernet device.
Definition ethernet.c:265
int register_netdev(struct net_device *netdev)
Register network device.
Definition netdevice.c:760
static void netdev_link_up(struct net_device *netdev)
Mark network device as having link up.
Definition netdevice.h:789
static void netdev_init(struct net_device *netdev, struct net_device_operations *op)
Initialise a network device.
Definition netdevice.h:519
void adjust_pci_device(struct pci_device *pci)
Enable PCI device.
Definition pci.c:241
static void pci_set_drvdata(struct pci_device *pci, void *priv)
Set PCI driver-private data.
Definition pci.h:366
unsigned int block_size
Data block size (in words)
Definition nvs.h:37
unsigned int word_len_log2
Word length.
Definition nvs.h:23
int(* read)(struct nvs_device *nvs, unsigned int address, void *data, size_t len)
Read data from device.
Definition nvs.h:48
unsigned int size
Device size (in words)
Definition nvs.h:25
int(* write)(struct nvs_device *nvs, unsigned int address, const void *data, size_t len)
Write data to device.
Definition nvs.h:60
unsigned long ioaddr
I/O address.
Definition pci.h:226
struct device dev
Generic device.
Definition pci.h:213
uint16_t vendor
Vendor ID.
Definition pci.h:228
uint16_t device
Device ID.
Definition pci.h:230

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

Variable Documentation

◆ a3c90x_operations

struct net_device_operations a3c90x_operations
static
Initial value:
= {
.open = a3c90x_open,
.close = a3c90x_close,
.poll = a3c90x_poll,
.transmit = a3c90x_transmit,
.irq = a3c90x_irq,
}
static int a3c90x_transmit(struct net_device *netdev, struct io_buffer *iob)
a3c90x_transmit - Transmits a packet.
Definition 3c90x.c:320
static int a3c90x_open(struct net_device *netdev)
a3c90x_open - Routine to initialize the card.
Definition 3c90x.c:796
static void a3c90x_poll(struct net_device *netdev)
a3c90x_poll - Routine that gets called periodically.
Definition 3c90x.c:568
static void a3c90x_irq(struct net_device *netdev, int enable)
Definition 3c90x.c:629
static void a3c90x_close(struct net_device *netdev)
a3c90x_close - free()s TX and RX ring, disablex RX/TX, resets NIC
Definition 3c90x.c:846

Definition at line 858 of file 3c90x.c.

858 {
859 .open = a3c90x_open,
860 .close = a3c90x_close,
861 .poll = a3c90x_poll,
862 .transmit = a3c90x_transmit,
863 .irq = a3c90x_irq,
864};

Referenced by __attribute__(), and a3c90x_probe().

◆ a3c90x_nics

struct pci_device_id a3c90x_nics[]
static
Initial value:
= {
PCI_ROM(0x10b7, 0x1201, "3c982a", "3Com982A", 0),
PCI_ROM(0x10b7, 0x1202, "3c982b", "3Com982B", 0),
PCI_ROM(0x10b7, 0x4500, "3c450", "3Com450 HomePNA Tornado", 0),
PCI_ROM(0x10b7, 0x6055, "3c556", "3C556", 0),
PCI_ROM(0x10b7, 0x7646, "3csoho100-tx", "3CSOHO100-TX", 0),
PCI_ROM(0x10b7, 0x9000, "3c905-tpo", "3Com900-TPO", 0),
PCI_ROM(0x10b7, 0x9001, "3c905-t4", "3Com900-Combo", 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, 0x9050, "3c905-tpo100", "3Com905-TX", 0),
PCI_ROM(0x10b7, 0x9051, "3c905-combo", "3Com905-T4", 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),
}
#define PCI_ROM(_vendor, _device, _name, _description, _data)
Definition pci.h:308

Definition at line 956 of file 3c90x.c.

956 {
957/* Original 90x revisions: */
958 PCI_ROM(0x10b7, 0x1201, "3c982a", "3Com982A", 0),
959 PCI_ROM(0x10b7, 0x1202, "3c982b", "3Com982B", 0),
960 PCI_ROM(0x10b7, 0x4500, "3c450", "3Com450 HomePNA Tornado", 0),
961 PCI_ROM(0x10b7, 0x6055, "3c556", "3C556", 0), /* Huricane */
962 PCI_ROM(0x10b7, 0x7646, "3csoho100-tx", "3CSOHO100-TX", 0), /* Hurricane */
963 PCI_ROM(0x10b7, 0x9000, "3c905-tpo", "3Com900-TPO", 0), /* 10 Base TPO */
964 PCI_ROM(0x10b7, 0x9001, "3c905-t4", "3Com900-Combo", 0), /* 10/100 T4 */
965/* Newer 90xB revisions: */
966 PCI_ROM(0x10b7, 0x9004, "3c905b-tpo", "3Com900B-TPO", 0), /* 10 Base TPO */
967 PCI_ROM(0x10b7, 0x9005, "3c905b-combo", "3Com900B-Combo", 0), /* 10 Base Combo */
968 PCI_ROM(0x10b7, 0x9006, "3c905b-tpb2", "3Com900B-2/T", 0), /* 10 Base TP and Base2 */
969 PCI_ROM(0x10b7, 0x900a, "3c905b-fl", "3Com900B-FL", 0), /* 10 Base FL */
970 PCI_ROM(0x10b7, 0x9050, "3c905-tpo100", "3Com905-TX", 0), /* 100 Base TX / 10/100 TPO */
971 PCI_ROM(0x10b7, 0x9051, "3c905-combo", "3Com905-T4", 0), /* 100 Base T4 / 10 Base Combo */
972 PCI_ROM(0x10b7, 0x9055, "3c905b-tpo100", "3Com905B-TX", 0), /* 10/100 TPO */
973 PCI_ROM(0x10b7, 0x9056, "3c905b-t4", "3Com905B-T4", 0), /* 10/100 T4 */
974 PCI_ROM(0x10b7, 0x9058, "3c905b-9058", "3Com905B-9058", 0), /* Cyclone 10/100/BNC */
975 PCI_ROM(0x10b7, 0x905a, "3c905b-fx", "3Com905B-FL", 0), /* 100 Base FX / 10 Base FX */
976/* Newer 90xC revision: */
977 PCI_ROM(0x10b7, 0x9200, "3c905c-tpo", "3Com905C-TXM", 0), /* 10/100 TPO (3C905C-TXM) */
978 PCI_ROM(0x10b7, 0x9202, "3c920b-emb-ati", "3c920B-EMB-WNM (ATI Radeon 9100 IGP)", 0), /* 3c920B-EMB-WNM (ATI Radeon 9100 IGP) */
979 PCI_ROM(0x10b7, 0x9210, "3c920b-emb-wnm", "3Com20B-EMB WNM", 0),
980 PCI_ROM(0x10b7, 0x9800, "3c980", "3Com980-Cyclone", 0), /* Cyclone */
981 PCI_ROM(0x10b7, 0x9805, "3c9805", "3Com9805", 0), /* Dual Port Server Cyclone */
982};

◆ __pci_driver

struct pci_driver a3c90x_driver __pci_driver
Initial value:
= {
.ids = a3c90x_nics,
.id_count = (sizeof(a3c90x_nics) / sizeof(a3c90x_nics[0])),
.probe = a3c90x_probe,
}
static struct pci_device_id a3c90x_nics[]
Definition 3c90x.c:956
static void a3c90x_remove(struct pci_device *pci)
a3c90x_remove - Routine to remove the card.
Definition 3c90x.c:611
static int a3c90x_probe(struct pci_device *pci)
a3c90x_probe: exported routine to probe for the 3c905 card.
Definition 3c90x.c:877
static struct xen_remove_from_physmap * remove
Definition xenmem.h:40

Definition at line 984 of file 3c90x.c.

984 {
985 .ids = a3c90x_nics,
986 .id_count = (sizeof(a3c90x_nics) / sizeof(a3c90x_nics[0])),
987 .probe = a3c90x_probe,
989};