iPXE
Functions | Variables
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 More...
 
static void a3c90x_internal_SetWindow (struct INF_3C90X *inf_3c90x, int window)
 a3c90x_internal_SetWindow: selects a register window set. More...
 
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). More...
 
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 More...
 
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. More...
 
static int a3c90x_setup_tx_ring (struct INF_3C90X *p)
 a3c90x_setup_tx_ring - Allocates TX ring, initialize tx_desc values More...
 
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(); More...
 
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. More...
 
static void a3c90x_prepare_rx_desc (struct INF_3C90X *p, unsigned int index)
 a3c90x_prepare_rx_desc - fills the rx desc with initial data More...
 
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. More...
 
static int a3c90x_setup_rx_ring (struct INF_3C90X *p)
 a3c90x_setup_rx_ring - Allocates RX ring, initialize rx_desc values More...
 
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 More...
 
static void a3c90x_poll (struct net_device *netdev)
 a3c90x_poll - Routine that gets called periodically. More...
 
static void a3c90x_free_resources (struct INF_3C90X *p)
 
static void a3c90x_remove (struct pci_device *pci)
 a3c90x_remove - Routine to remove the card. More...
 
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 More...
 
static int a3c90x_open (struct net_device *netdev)
 a3c90x_open - Routine to initialize the card. More...
 
static void a3c90x_close (struct net_device *netdev)
 a3c90x_close - free()s TX and RX ring, disablex RX/TX, resets NIC More...
 
static int a3c90x_probe (struct pci_device *pci)
 a3c90x_probe: exported routine to probe for the 3c905 card. More...
 

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()

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
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 }
uint16_t inw(volatile uint16_t *io_addr)
Read 16-bit word from I/O-mapped device.
#define outw(data, io_addr)
Definition: io.h:319
static unsigned long ioaddr
Definition: davicom.c:129
#define DBGP(...)
Definition: compiler.h:532
struct hv_monitor_parameter param[4][32]
Parameters.
Definition: hyperv.h:24
#define INT_CMDINPROGRESS
Definition: 3c90x.h:261
void __asmcall int val
Definition: setjmp.h:28
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
struct golan_eqe_cmd cmd
Definition: CIB_PRM.h:29
#define DBG2(...)
Definition: compiler.h:515

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()

static 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. */
108  cmdSelectRegisterWindow, window);
109  inf_3c90x->CurrentWindow = window;
110 
111  return;
112 }
#define DBGP(...)
Definition: compiler.h:532
unsigned char CurrentWindow
Definition: 3c90x.h:295
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
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()

static 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 }
uint16_t inw(volatile uint16_t *io_addr)
Read 16-bit word from I/O-mapped device.
#define DBGP(...)
Definition: compiler.h:532
void udelay(unsigned long usecs)
Delay for a fixed number of microseconds.
Definition: timer.c:60
#define EEPROM_TIMEOUT
Definition: 3c90x.h:273
unsigned int IOAddr
Definition: 3c90x.h:296
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498

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

Referenced by a3c90x_internal_ReadEeprom().

◆ a3c90x_internal_ReadEeprom()

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
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 */
160  outw(address, inf_3c90x->IOAddr + regEepromCommand_0_w);
162 
163  /* read value */
164  *dest = inw(inf_3c90x->IOAddr + regEepromData_0_w);
165 
166  return 0;
167 }
uint16_t inw(volatile uint16_t *io_addr)
Read 16-bit word from I/O-mapped device.
#define outw(data, io_addr)
Definition: io.h:319
uint64_t address
Base address.
Definition: ena.h:24
struct nvs_device nvs
Definition: 3c90x.h:306
#define DBGP(...)
Definition: compiler.h:532
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
unsigned int is3c556
Definition: 3c90x.h:293
static void a3c90x_internal_SetWindow(struct INF_3C90X *inf_3c90x, int window)
a3c90x_internal_SetWindow: selects a register window set.
Definition: 3c90x.c:99
static void a3c90x_internal_WaitForEeprom(struct INF_3C90X *inf_3c90x)
Definition: 3c90x.c:114
static void * dest
Definition: strings.h:176
unsigned int IOAddr
Definition: 3c90x.h:296
uint32_t len
Length.
Definition: ena.h:14
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12

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()

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
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:589

References ENOTSUP.

Referenced by a3c90x_probe().

◆ a3c90x_internal_ReadEepromContents()

static 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 }
unsigned short eeprom[0x21]
Definition: 3c90x.h:297
struct nvs_device nvs
Definition: 3c90x.h:306
#define DBGP(...)
Definition: compiler.h:532
unsigned char isBrev
Definition: 3c90x.h:294
int nvs_read(struct nvs_device *nvs, unsigned int address, void *data, size_t len)
Read from non-volatile storage device.
Definition: nvs.c:75

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

Referenced by a3c90x_probe().

◆ a3c90x_reset()

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_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 */
236  cmdAcknowledgeInterrupt, 0x661);
237 
238  return;
239 }
#define outw(data, io_addr)
Definition: io.h:319
#define INT_UPCOMPLETE
Definition: 3c90x.h:260
#define DBGP(...)
Definition: compiler.h:532
static void a3c90x_internal_SetWindow(struct INF_3C90X *inf_3c90x, int window)
a3c90x_internal_SetWindow: selects a register window set.
Definition: 3c90x.c:99
#define INT_TXCOMPLETE
Definition: 3c90x.h:253
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
unsigned int IOAddr
Definition: 3c90x.h:296
#define DBG2(...)
Definition: compiler.h:515

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()

static 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_dma(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 }
unsigned int tx_cnt
Definition: 3c90x.h:299
unsigned int tx_tail
Definition: 3c90x.h:300
#define TX_RING_ALIGN
Definition: 3c90x.h:267
#define ENOMEM
Not enough space.
Definition: errno.h:534
unsigned int tx_cur
Definition: 3c90x.h:298
#define DBGP(...)
Definition: compiler.h:532
Definition: 3c90x.h:276
struct TXD * tx_ring
Definition: 3c90x.h:302
static void *__malloc malloc_dma(size_t size, size_t phys_align)
Allocate memory for DMA.
Definition: malloc.h:66
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
#define TX_RING_SIZE
Definition: 3c515.c:86
void * memset(void *dest, int character, size_t len) __nonnull

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().

◆ a3c90x_process_tx_packets()

static 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(netdev);
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 }
static void * netdev_priv(struct net_device *netdev)
Get driver private area for this network device.
Definition: netdevice.h:566
static void netdev_tx_complete(struct net_device *netdev, struct io_buffer *iobuf)
Complete network transmission.
Definition: netdevice.h:746
unsigned int tx_cnt
Definition: 3c90x.h:299
unsigned int tx_tail
Definition: 3c90x.h:300
unsigned int tx_cur
Definition: 3c90x.h:298
static __always_inline unsigned long virt_to_bus(volatile const void *addr)
Convert virtual address to a bus address.
Definition: io.h:183
#define DBGP(...)
Definition: compiler.h:532
static struct net_device * netdev
Definition: gdbudp.c:52
struct TXD * tx_ring
Definition: 3c90x.h:302
struct io_buffer * tx_iobuf[TX_RING_SIZE]
Definition: 3c90x.h:304
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:151
unsigned int IOAddr
Definition: 3c90x.h:296
uint32_t inl(volatile uint32_t *io_addr)
Read 32-bit dword from I/O-mapped device.
#define TX_RING_SIZE
Definition: 3c515.c:86
#define DBG2(...)
Definition: compiler.h:515

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

◆ a3c90x_free_tx_ring()

static 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_dma(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 DBGP(...)
Definition: compiler.h:532
Definition: 3c90x.h:276
struct TXD * tx_ring
Definition: 3c90x.h:302
static void free_dma(void *ptr, size_t size)
Free memory allocated with malloc_dma()
Definition: malloc.h:81
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
#define TX_RING_SIZE
Definition: 3c515.c:86

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

Referenced by a3c90x_free_resources().

◆ a3c90x_transmit()

static 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(netdev);
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 }
static void * netdev_priv(struct net_device *netdev)
Get driver private area for this network device.
Definition: netdevice.h:566
unsigned int tx_cnt
Definition: 3c90x.h:299
volatile unsigned int DnNextPtr
Definition: 3c90x.h:277
volatile unsigned int DataAddr
Definition: 3c90x.h:279
unsigned int tx_cur
Definition: 3c90x.h:298
static __always_inline unsigned long virt_to_bus(volatile const void *addr)
Convert virtual address to a bus address.
Definition: io.h:183
#define DBGP(...)
Definition: compiler.h:532
static struct net_device * netdev
Definition: gdbudp.c:52
volatile unsigned int DataLength
Definition: 3c90x.h:280
Definition: 3c90x.h:276
struct TXD * tx_ring
Definition: 3c90x.h:302
#define outl(data, io_addr)
Definition: io.h:329
struct io_buffer * tx_iobuf[TX_RING_SIZE]
Definition: 3c90x.h:304
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:151
unsigned char isBrev
Definition: 3c90x.h:294
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
Definition: 3c90x.h:222
volatile unsigned int FrameStartHeader
Definition: 3c90x.h:278
unsigned int IOAddr
Definition: 3c90x.h:296
uint32_t len
Length.
Definition: ena.h:14
#define ENOBUFS
No buffer space available.
Definition: errno.h:498
void * data
Start of data.
Definition: iobuf.h:44
uint32_t inl(volatile uint32_t *io_addr)
Read 32-bit dword from I/O-mapped device.
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
#define TX_RING_SIZE
Definition: 3c515.c:86

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, 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().

◆ a3c90x_prepare_rx_desc()

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
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 }
struct RXD * rx_ring
Definition: 3c90x.h:303
#define RX_BUF_SIZE
Definition: 3c90x.h:269
volatile unsigned int DataLength
Definition: 3c90x.h:288
volatile unsigned int UpPktStatus
Definition: 3c90x.h:286
static __always_inline unsigned long virt_to_bus(volatile const void *addr)
Convert virtual address to a bus address.
Definition: io.h:183
#define DBGP(...)
Definition: compiler.h:532
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
Definition: 3c90x.h:219
unsigned int IOAddr
Definition: 3c90x.h:296
volatile unsigned int DataAddr
Definition: 3c90x.h:287
void * data
Start of data.
Definition: iobuf.h:44
uint64_t index
Index of the first segment within the content.
Definition: pccrc.h:21
#define DBG2(...)
Definition: compiler.h:515
struct io_buffer * rx_iobuf[RX_RING_SIZE]
Definition: 3c90x.h:305

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()

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
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 
440  p->rx_iobuf[i] = alloc_iob(RX_BUF_SIZE);
441  if (p->rx_iobuf[i] == NULL) {
442  DBG("alloc_iob() failed\n");
443  break;
444  }
445 
447  }
448 }
struct RXD * rx_ring
Definition: 3c90x.h:303
#define RX_BUF_SIZE
Definition: 3c90x.h:269
volatile unsigned int UpPktStatus
Definition: 3c90x.h:286
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition: iobuf.c:128
uint8_t status
Status.
Definition: ena.h:16
#define DBGP(...)
Definition: compiler.h:532
Definition: 3c90x.h:284
#define RX_RING_SIZE
Definition: 3c515.c:87
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
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
struct io_buffer * rx_iobuf[RX_RING_SIZE]
Definition: 3c90x.h:305

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()

static 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_dma(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 }
struct RXD * rx_ring
Definition: 3c90x.h:303
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
volatile unsigned int UpPktStatus
Definition: 3c90x.h:286
#define ENOMEM
Not enough space.
Definition: errno.h:534
unsigned int rx_cur
Definition: 3c90x.h:301
static __always_inline unsigned long virt_to_bus(volatile const void *addr)
Convert virtual address to a bus address.
Definition: io.h:183
#define RX_RING_ALIGN
Definition: 3c90x.h:268
#define DBGP(...)
Definition: compiler.h:532
Definition: 3c90x.h:284
#define RX_RING_SIZE
Definition: 3c515.c:87
static void *__malloc malloc_dma(size_t size, size_t phys_align)
Allocate memory for DMA.
Definition: malloc.h:66
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
volatile unsigned int UpNextPtr
Definition: 3c90x.h:285
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
struct io_buffer * rx_iobuf[RX_RING_SIZE]
Definition: 3c90x.h:305

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().

◆ a3c90x_free_rx_ring()

static 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_dma(p->rx_ring, RX_RING_SIZE * sizeof(struct RXD));
495  p->rx_ring = NULL;
496 }
struct RXD * rx_ring
Definition: 3c90x.h:303
#define DBGP(...)
Definition: compiler.h:532
Definition: 3c90x.h:284
#define RX_RING_SIZE
Definition: 3c515.c:87
static void free_dma(void *ptr, size_t size)
Free memory allocated with malloc_dma()
Definition: malloc.h:81
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

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

Referenced by a3c90x_free_resources().

◆ a3c90x_free_rx_iobuf()

static 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:145
#define DBGP(...)
Definition: compiler.h:532
#define RX_RING_SIZE
Definition: 3c515.c:87
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
struct io_buffer * rx_iobuf[RX_RING_SIZE]
Definition: 3c90x.h:305

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

Referenced by a3c90x_free_resources().

◆ a3c90x_process_rx_packets()

static 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(netdev);
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 
550  netdev_rx(netdev, p->rx_iobuf[p->rx_cur]);
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 }
struct RXD * rx_ring
Definition: 3c90x.h:303
#define EINVAL
Invalid argument.
Definition: errno.h:428
static void * netdev_priv(struct net_device *netdev)
Get driver private area for this network device.
Definition: netdevice.h:566
#define iob_put(iobuf, len)
Definition: iobuf.h:116
void netdev_rx_err(struct net_device *netdev, struct io_buffer *iobuf, int rc)
Discard received packet.
Definition: netdevice.c:501
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
volatile unsigned int UpPktStatus
Definition: 3c90x.h:286
Definition: 3c90x.h:215
unsigned int rx_cur
Definition: 3c90x.h:301
#define DBGP(...)
Definition: compiler.h:532
static struct net_device * netdev
Definition: gdbudp.c:52
Definition: 3c90x.h:284
#define RX_RING_SIZE
Definition: 3c515.c:87
void netdev_rx(struct net_device *netdev, struct io_buffer *iobuf)
Add packet to receive queue.
Definition: netdevice.c:470
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
#define DBG2(...)
Definition: compiler.h:515
struct io_buffer * rx_iobuf[RX_RING_SIZE]
Definition: 3c90x.h:305

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

◆ a3c90x_poll()

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

Definition at line 568 of file 3c90x.c.

569 {
570  struct INF_3C90X *p = netdev_priv(netdev);
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 * netdev_priv(struct net_device *netdev)
Get driver private area for this network device.
Definition: netdevice.h:566
unsigned short uint16_t
Definition: stdint.h:11
uint16_t inw(volatile uint16_t *io_addr)
Read 16-bit word from I/O-mapped device.
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
#define DBGP(...)
Definition: compiler.h:532
static struct net_device * netdev
Definition: gdbudp.c:52
#define INT_TXCOMPLETE
Definition: 3c90x.h:253
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_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
#define outb(data, io_addr)
Definition: io.h:309
unsigned int IOAddr
Definition: 3c90x.h:296
#define DBG2(...)
Definition: compiler.h:515

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

◆ a3c90x_free_resources()

static 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
#define DBGP(...)
Definition: compiler.h:532
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()

static 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(netdev);
615 
616  DBGP("a3c90x_remove\n");
617 
618  a3c90x_reset(inf_3c90x);
619 
620  /* Disable the receiver and transmitter. */
623 
627 }
static void * netdev_priv(struct net_device *netdev)
Get driver private area for this network device.
Definition: netdevice.h:566
#define outw(data, io_addr)
Definition: io.h:319
#define DBGP(...)
Definition: compiler.h:532
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition: netdevice.h:555
static struct net_device * netdev
Definition: gdbudp.c:52
void unregister_netdev(struct net_device *netdev)
Unregister network device.
Definition: netdevice.c:844
A network device.
Definition: netdevice.h:348
static void netdev_nullify(struct net_device *netdev)
Stop using a network device.
Definition: netdevice.h:511
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
static void * pci_get_drvdata(struct pci_device *pci)
Get PCI driver-private data.
Definition: pci.h:348
unsigned int IOAddr
Definition: 3c90x.h:296

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().

◆ a3c90x_irq()

static 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(netdev);
632 
633  DBGP("a3c90x_irq\n");
634 
635  if (enable == 0) {
636  /* disable interrupts */
639  } else {
646  0x661);
647  }
648 }
static void * netdev_priv(struct net_device *netdev)
Get driver private area for this network device.
Definition: netdevice.h:566
#define INT_UPCOMPLETE
Definition: 3c90x.h:260
#define DBGP(...)
Definition: compiler.h:532
static struct net_device * netdev
Definition: gdbudp.c:52
#define INT_TXCOMPLETE
Definition: 3c90x.h:253
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
unsigned int IOAddr
Definition: 3c90x.h:296

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

◆ a3c90x_hw_start()

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 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(netdev);
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++) ? ", " : "");
700  linktype = linkMII;
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++) ? ", " : "");
712  linktype = linkAUI;
713  }
714  if (mopt & 0x40) {
715  DBG2("%sMII", (c++) ? ", " : "");
716  linktype = linkMII;
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");
743  linktype = linkMII;
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  */
785  cmdAcknowledgeInterrupt, 0x661);
786 }
static void * netdev_priv(struct net_device *netdev)
Get driver private area for this network device.
Definition: netdevice.h:566
uint16_t inw(volatile uint16_t *io_addr)
Read 16-bit word from I/O-mapped device.
unsigned short eeprom[0x21]
Definition: 3c90x.h:297
#define outw(data, io_addr)
Definition: io.h:319
#define INT_UPCOMPLETE
Definition: 3c90x.h:260
static __always_inline void off_t int c
Definition: efi_uaccess.h:87
#define DBGP(...)
Definition: compiler.h:532
unsigned int is3c556
Definition: 3c90x.h:293
static struct net_device * netdev
Definition: gdbudp.c:52
static void a3c90x_internal_SetWindow(struct INF_3C90X *inf_3c90x, int window)
a3c90x_internal_SetWindow: selects a register window set.
Definition: 3c90x.c:99
#define INT_TXCOMPLETE
Definition: 3c90x.h:253
#define outl(data, io_addr)
Definition: io.h:329
Definition: 3c90x.h:245
uint8_t * tmp
Definition: entropy.h:156
unsigned char isBrev
Definition: 3c90x.h:294
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
#define ETH_ALEN
Definition: if_ether.h:8
Definition: sis900.h:23
#define outb(data, io_addr)
Definition: io.h:309
unsigned int IOAddr
Definition: 3c90x.h:296
uint32_t inl(volatile uint32_t *io_addr)
Read 32-bit dword from I/O-mapped device.
uint8_t ll_addr[MAX_LL_ADDR_LEN]
Link-layer address.
Definition: netdevice.h:381
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
linktype
Definition: 3c90x.h:240
#define XCVR_MAGIC
Definition: 3c90x.h:55
Definition: 3c90x.h:242
#define DBG2(...)
Definition: compiler.h:515

References a3c90x_internal_IssueCommand(), a3c90x_internal_SetWindow(), c, 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, net_device::ll_addr, netdev, netdev_priv(), 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()

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
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(netdev);
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 */
827  outl(RX_BUF_SIZE, inf_3c90x->IOAddr + regMaxPktSize_3_w);
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 }
struct RXD * rx_ring
Definition: 3c90x.h:303
static void * netdev_priv(struct net_device *netdev)
Get driver private area for this network device.
Definition: netdevice.h:566
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define RX_BUF_SIZE
Definition: 3c90x.h:269
static void a3c90x_free_resources(struct INF_3C90X *p)
Definition: 3c90x.c:596
struct arbelprm_completion_with_error error
Definition: arbel.h:12
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 __always_inline unsigned long virt_to_bus(volatile const void *addr)
Convert virtual address to a bus address.
Definition: io.h:183
#define DBGP(...)
Definition: compiler.h:532
static struct net_device * netdev
Definition: gdbudp.c:52
static void a3c90x_internal_SetWindow(struct INF_3C90X *inf_3c90x, int window)
a3c90x_internal_SetWindow: selects a register window set.
Definition: 3c90x.c:99
#define outl(data, io_addr)
Definition: io.h:329
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
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
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
Definition: 3c90x.h:219
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
unsigned int IOAddr
Definition: 3c90x.h:296
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498

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, netdev_priv(), outl, rc, regMaxPktSize_3_w, regUpListPtr_l, RX_BUF_SIZE, INF_3C90X::rx_ring, upStall, upUnStall, virt_to_bus(), and winTxRxOptions3.

◆ a3c90x_close()

static 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(netdev);
849 
850  DBGP("a3c90x_close\n");
851 
852  a3c90x_reset(inf_3c90x);
855  a3c90x_free_resources(inf_3c90x);
856 }
static void * netdev_priv(struct net_device *netdev)
Get driver private area for this network device.
Definition: netdevice.h:566
#define outw(data, io_addr)
Definition: io.h:319
static void a3c90x_free_resources(struct INF_3C90X *p)
Definition: 3c90x.c:596
#define DBGP(...)
Definition: compiler.h:532
static struct net_device * netdev
Definition: gdbudp.c:52
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
unsigned int IOAddr
Definition: 3c90x.h:296

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

◆ a3c90x_probe()

static 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 
895  pci_set_drvdata(pci, netdev);
896  netdev->dev = &pci->dev;
897 
898  inf_3c90x = netdev_priv(netdev);
899  memset(inf_3c90x, 0, sizeof(*inf_3c90x));
900 
901  adjust_pci_device(pci);
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;
925  inf_3c90x->nvs.read = a3c90x_internal_ReadEeprom;
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 }
#define EINVAL
Invalid argument.
Definition: errno.h:428
int(* write)(struct nvs_device *nvs, unsigned int address, const void *data, size_t len)
Write data to device.
Definition: nvs.h:59
static void * netdev_priv(struct net_device *netdev)
Get driver private area for this network device.
Definition: netdevice.h:566
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
unsigned int word_len_log2
Word length.
Definition: nvs.h:22
unsigned short eeprom[0x21]
Definition: 3c90x.h:297
unsigned long ioaddr
I/O address.
Definition: pci.h:200
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 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
void adjust_pci_device(struct pci_device *pci)
Enable PCI device.
Definition: pci.c:149
struct device dev
Generic device.
Definition: pci.h:189
struct nvs_device nvs
Definition: 3c90x.h:306
static void netdev_init(struct net_device *netdev, struct net_device_operations *op)
Initialise a network device.
Definition: netdevice.h:498
static void pci_set_drvdata(struct pci_device *pci, void *priv)
Set PCI driver-private data.
Definition: pci.h:338
#define ENOMEM
Not enough space.
Definition: errno.h:534
uint16_t device
Device ID.
Definition: pci.h:204
unsigned int block_size
Data block size (in words)
Definition: nvs.h:36
#define DBGP(...)
Definition: compiler.h:532
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition: netdevice.h:555
unsigned int is3c556
Definition: 3c90x.h:293
static void netdev_link_up(struct net_device *netdev)
Mark network device as having link up.
Definition: netdevice.h:768
static struct net_device * netdev
Definition: gdbudp.c:52
static void a3c90x_internal_ReadEepromContents(struct INF_3C90X *inf_3c90x)
Definition: 3c90x.c:186
int(* read)(struct nvs_device *nvs, unsigned int address, void *data, size_t len)
Read data from device.
Definition: nvs.h:47
int register_netdev(struct net_device *netdev)
Register network device.
Definition: netdevice.c:667
A network device.
Definition: netdevice.h:348
unsigned char isBrev
Definition: 3c90x.h:294
unsigned char CurrentWindow
Definition: 3c90x.h:295
Definition: 3c90x.h:158
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
uint16_t vendor
Vendor ID.
Definition: pci.h:202
struct device * dev
Underlying hardware device.
Definition: netdevice.h:360
unsigned int IOAddr
Definition: 3c90x.h:296
static struct net_device_operations a3c90x_operations
Definition: 3c90x.c:858
struct net_device * alloc_etherdev(size_t priv_size)
Allocate Ethernet device.
Definition: ethernet.c:264
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
uint8_t hw_addr[MAX_HW_ADDR_LEN]
Hardware address.
Definition: netdevice.h:375
unsigned int size
Device size (in words)
Definition: nvs.h:24
#define DBG2(...)
Definition: compiler.h:515
void * memset(void *dest, int character, size_t len) __nonnull

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, net_device::dev, pci_device::device, INF_3C90X::eeprom, eepromHwAddrOffset, EINVAL, ENOMEM, net_device::hw_addr, pci_device::ioaddr, INF_3C90X::IOAddr, INF_3C90X::is3c556, INF_3C90X::isBrev, memset(), netdev, netdev_init(), netdev_link_up(), netdev_priv(), 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_open(struct net_device *netdev)
a3c90x_open - Routine to initialize the card.
Definition: 3c90x.c:796
static void a3c90x_irq(struct net_device *netdev, int enable)
Definition: 3c90x.c:629
static void a3c90x_poll(struct net_device *netdev)
a3c90x_poll - Routine that gets called periodically.
Definition: 3c90x.c:568
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
static int a3c90x_transmit(struct net_device *netdev, struct io_buffer *iob)
a3c90x_transmit - Transmits a packet.
Definition: 3c90x.c:320

Definition at line 858 of file 3c90x.c.

Referenced by a3c90x_probe().

◆ a3c90x_nics

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),
}
#define PCI_ROM(_vendor, _device, _name, _description, _data)
Definition: pci.h:283

Definition at line 956 of file 3c90x.c.

◆ __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 int a3c90x_probe(struct pci_device *pci)
a3c90x_probe: exported routine to probe for the 3c905 card.
Definition: 3c90x.c:877
static void a3c90x_remove(struct pci_device *pci)
a3c90x_remove - Routine to remove the card.
Definition: 3c90x.c:611
static struct pci_device_id a3c90x_nics[]
Definition: 3c90x.c:956
static struct xen_remove_from_physmap * remove
Definition: xenmem.h:39

Definition at line 984 of file 3c90x.c.