3c515.c File Reference

#include "etherboot.h"
#include "nic.h"
#include <gpxe/isapnp.h>
#include <gpxe/isa.h>
#include <gpxe/ethernet.h>

Go to the source code of this file.

Data Structures

union  wn3_config
struct  wn3_config::w3_config_fields
struct  boom_rx_desc
struct  boom_tx_desc
struct  corkscrew_private
struct  media_table

Defines

#define HZ   100
#define CORKSCREW   1
#define AUTOMEDIA   1
#define VORTEX_BUS_MASTER
#define TX_RING_SIZE   16
#define RX_RING_SIZE   16
#define PKT_BUF_SZ   1536
#define DRIVER_DEBUG   1
#define CORKSCREW_ID   10
#define EL3WINDOW(win_num)   outw(SelectWindow + (win_num), nic->ioaddr + EL3_CMD)
#define EL3_CMD   0x0e
#define EL3_STATUS   0x0e
#define RX_BYTES_MASK   (unsigned short) (0x07ff)

Enumerations

enum  corkscrew_cmd {
  TotalReset = 0 << 11, SelectWindow = 1 << 11, StartCoax = 2 << 11, RxDisable = 3 << 11,
  RxEnable = 4 << 11, RxReset = 5 << 11, UpStall = 6 << 11, UpUnstall = (6 << 11) + 1,
  DownStall = (6 << 11) + 2, DownUnstall = (6 << 11) + 3, RxDiscard = 8 << 11, TxEnable = 9 << 11,
  TxDisable, TxReset = 11 << 11, FakeIntr = 12 << 11, AckIntr = 13 << 11,
  SetIntrEnb = 14 << 11, SetStatusEnb = 15 << 11, SetRxFilter = 16 << 11, SetRxThreshold,
  SetTxThreshold = 18 << 11, SetTxStart = 19 << 11, StartDMAUp = 20 << 11, StartDMADown = (20 << 11) + 1,
  StatsEnable, StatsDisable = 22 << 11, StopCoax = 23 << 11
}
enum  RxFilter { RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 }
enum  corkscrew_status {
  IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004, TxAvailable = 0x0008,
  RxComplete = 0x0010, RxEarly = 0x0020, IntReq = 0x0040, StatsFull = 0x0080,
  DMADone = 1 << 8, DownComplete = 1 << 9, UpComplete = 1 << 10, DMAInProgress = 1 << 11,
  CmdInProgress = 1 << 12
}
enum  Window1 {
  TX_FIFO = 0x10, RX_FIFO = 0x10, RxErrors = 0x14, RxStatus = 0x18,
  Timer = 0x1A, TxStatus = 0x1B, TxFree = 0x1C
}
enum  Window0 { Wn0IRQ = 0x08, Wn0EepromCmd = 0x200A, Wn0EepromData = 0x200C }
enum  Win0_EEPROM_bits {
  EEPROM_Read = 0x80, EEPROM_WRITE = 0x40, EEPROM_ERASE = 0xC0, EEPROM_EWENB = 0x30,
  EEPROM_EWDIS = 0x00
}
enum  Window3 { Wn3_Config = 0, Wn3_MAC_Ctrl = 6, Wn3_Options = 8 }
enum  Window4 { Wn4_NetDiag = 6, Wn4_Media = 10 }
enum  Win4_Media_bits { Media_SQE = 0x0008, Media_10TP = 0x00C0, Media_Lnk = 0x0080, Media_LnkBeat = 0x0800 }
enum  Window7 { Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12 }
enum  MasterCtrl {
  PktStatus = 0x400, DownListPtr = 0x404, FragAddr = 0x408, FragLen,
  TxFreeThreshold = 0x40f, UpPktStatus = 0x410, UpListPtr = 0x418
}
enum  rx_desc_status { RxDComplete = 0x00008000, RxDError = 0x4000 }
enum  xcvr_types {
  XCVR_10baseT, XCVR_AUI, XCVR_10baseTOnly, XCVR_10base2,
  XCVR_100baseTx, XCVR_100baseFx, XCVR_MII = 6, XCVR_Default = 8
}

Functions

 FILE_LICENCE (GPL2_OR_LATER)
static void t3c515_wait (unsigned int nticks)
static int corkscrew_found_device (int ioaddr, int irq, int product_index, int options, struct nic *nic)
static int corkscrew_probe1 (int ioaddr, int irq, int product_index, struct nic *nic)
static void t515_reset (struct nic *nic)
static int t515_poll (struct nic *nic, int retrieve)
static void t515_transmit (struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p)
static void t515_disable (struct nic *nic, struct isapnp_device *isapnp)
static void t515_irq (struct nic *nic __unused, irq_action_t action __unused)
static int t515_probe (struct nic *nic, struct isapnp_device *isapnp)
 ISAPNP_DRIVER (t515_driver, t515_adapters)
 DRIVER ("3c515", nic_driver, isapnp_driver, t515_driver, t515_probe, t515_disable)
 ISA_ROM ("3c515","3c515 Fast EtherLink ISAPnP")

Variables

static int if_port
static struct corkscrew_privatevp
static struct media_table media_tbl []
static int options = -1
static char padmap []
static struct nic_operations t515_operations
static struct isapnp_device_id t515_adapters []


Define Documentation

#define HZ   100

Definition at line 64 of file 3c515.c.

Referenced by ns83820_run_bist().

#define CORKSCREW   1

Definition at line 68 of file 3c515.c.

#define AUTOMEDIA   1

Definition at line 75 of file 3c515.c.

#define VORTEX_BUS_MASTER

Definition at line 81 of file 3c515.c.

#define TX_RING_SIZE   16

#define RX_RING_SIZE   16

#define PKT_BUF_SZ   1536

#define DRIVER_DEBUG   1

Definition at line 91 of file 3c515.c.

#define CORKSCREW_ID   10

Definition at line 97 of file 3c515.c.

Referenced by t515_probe().

#define EL3WINDOW ( win_num   )     outw(SelectWindow + (win_num), nic->ioaddr + EL3_CMD)

Definition at line 99 of file 3c515.c.

Referenced by corkscrew_probe1(), and t515_reset().

#define EL3_CMD   0x0e

Definition at line 101 of file 3c515.c.

Referenced by t515_disable(), t515_poll(), t515_reset(), and t515_transmit().

#define EL3_STATUS   0x0e

Definition at line 102 of file 3c515.c.

Referenced by t515_poll(), t515_reset(), and t515_transmit().

#define RX_BYTES_MASK   (unsigned short) (0x07ff)

Definition at line 103 of file 3c515.c.


Enumeration Type Documentation

Enumerator:
TotalReset 
SelectWindow 
StartCoax 
RxDisable 
RxEnable 
RxReset 
UpStall 
UpUnstall 
DownStall 
DownUnstall 
RxDiscard 
TxEnable 
TxDisable 
TxReset 
FakeIntr 
AckIntr 
SetIntrEnb 
SetStatusEnb 
SetRxFilter 
SetRxThreshold 
SetTxThreshold 
SetTxStart 
StartDMAUp 
StartDMADown 
StatsEnable 
StatsDisable 
StopCoax 

Definition at line 105 of file 3c515.c.

00105                    {
00106         TotalReset = 0 << 11, SelectWindow = 1 << 11, StartCoax = 2 << 11,
00107         RxDisable = 3 << 11, RxEnable = 4 << 11, RxReset = 5 << 11,
00108         UpStall = 6 << 11, UpUnstall = (6 << 11) + 1,
00109         DownStall = (6 << 11) + 2, DownUnstall = (6 << 11) + 3,
00110         RxDiscard = 8 << 11, TxEnable = 9 << 11, TxDisable =
00111             10 << 11, TxReset = 11 << 11,
00112         FakeIntr = 12 << 11, AckIntr = 13 << 11, SetIntrEnb = 14 << 11,
00113         SetStatusEnb = 15 << 11, SetRxFilter = 16 << 11, SetRxThreshold =
00114             17 << 11,
00115         SetTxThreshold = 18 << 11, SetTxStart = 19 << 11,
00116         StartDMAUp = 20 << 11, StartDMADown = (20 << 11) + 1, StatsEnable =
00117             21 << 11,
00118         StatsDisable = 22 << 11, StopCoax = 23 << 11,
00119 };

enum RxFilter

Enumerator:
RxStation 
RxMulticast 
RxBroadcast 
RxProm 

Definition at line 122 of file 3c515.c.

00122               {
00123         RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8
00124 };

Enumerator:
IntLatch 
AdapterFailure 
TxComplete 
TxAvailable 
RxComplete 
RxEarly 
IntReq 
StatsFull 
DMADone 
DownComplete 
UpComplete 
DMAInProgress 
CmdInProgress 

Definition at line 127 of file 3c515.c.

00127                       {
00128         IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
00129         TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
00130         IntReq = 0x0040, StatsFull = 0x0080,
00131         DMADone = 1 << 8, DownComplete = 1 << 9, UpComplete = 1 << 10,
00132         DMAInProgress = 1 << 11,        /* DMA controller is still busy. */
00133         CmdInProgress = 1 << 12,        /* EL3_CMD is still busy. */
00134 };

enum Window1

Enumerator:
TX_FIFO 
RX_FIFO 
RxErrors 
RxStatus 
Timer 
TxStatus 
TxFree 

Definition at line 138 of file 3c515.c.

00138              {
00139         TX_FIFO = 0x10, RX_FIFO = 0x10, RxErrors = 0x14,
00140         RxStatus = 0x18, Timer = 0x1A, TxStatus = 0x1B,
00141         TxFree = 0x1C,          /* Remaining free bytes in Tx buffer. */
00142 };

enum Window0

Enumerator:
Wn0IRQ 
Wn0EepromCmd 
Wn0EepromData 

Definition at line 143 of file 3c515.c.

00143              {
00144         Wn0IRQ = 0x08,
00145 #if defined(CORKSCREW)
00146         Wn0EepromCmd = 0x200A,  /* Corkscrew EEPROM command register. */
00147         Wn0EepromData = 0x200C, /* Corkscrew EEPROM results register. */
00148 #else
00149         Wn0EepromCmd = 10,      /* Window 0: EEPROM command register. */
00150         Wn0EepromData = 12,     /* Window 0: EEPROM results register. */
00151 #endif
00152 };

Enumerator:
EEPROM_Read 
EEPROM_WRITE 
EEPROM_ERASE 
EEPROM_EWENB 
EEPROM_EWDIS 

Definition at line 153 of file 3c515.c.

00153                       {
00154         EEPROM_Read = 0x80, EEPROM_WRITE = 0x40, EEPROM_ERASE = 0xC0,
00155         EEPROM_EWENB = 0x30,    /* Enable erasing/writing for 10 msec. */
00156         EEPROM_EWDIS = 0x00,    /* Disable EWENB before 10 msec timeout. */
00157 };

enum Window3

Enumerator:
Wn3_Config 
Wn3_MAC_Ctrl 
Wn3_Options 

Definition at line 159 of file 3c515.c.

00159              {                  /* Window 3: MAC/config bits. */
00160         Wn3_Config = 0, Wn3_MAC_Ctrl = 6, Wn3_Options = 8,
00161 };

enum Window4

Enumerator:
Wn4_NetDiag 
Wn4_Media 

Definition at line 174 of file 3c515.c.

00174              {
00175         Wn4_NetDiag = 6, Wn4_Media = 10,        /* Window 4: Xcvr/media bits. */
00176 };

Enumerator:
Media_SQE 
Media_10TP 
Media_Lnk 
Media_LnkBeat 

Definition at line 177 of file 3c515.c.

00177                      {
00178         Media_SQE = 0x0008,     /* Enable SQE error counting for AUI. */
00179         Media_10TP = 0x00C0,    /* Enable link beat and jabber for 10baseT. */
00180         Media_Lnk = 0x0080,     /* Enable just link beat for 100TX/100FX. */
00181         Media_LnkBeat = 0x0800,
00182 };

enum Window7

Enumerator:
Wn7_MasterAddr 
Wn7_MasterLen 
Wn7_MasterStatus 

Definition at line 183 of file 3c515.c.

00183              {                  /* Window 7: Bus Master control. */
00184         Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12,
00185 };

enum MasterCtrl

Enumerator:
PktStatus 
DownListPtr 
FragAddr 
FragLen 
TxFreeThreshold 
UpPktStatus 
UpListPtr 

Definition at line 188 of file 3c515.c.

00188                 {
00189         PktStatus = 0x400, DownListPtr = 0x404, FragAddr = 0x408, FragLen =
00190             0x40c,
00191         TxFreeThreshold = 0x40f, UpPktStatus = 0x410, UpListPtr = 0x418,
00192 };

Enumerator:
RxDComplete 
RxDError 

Definition at line 205 of file 3c515.c.

00205                     {
00206         RxDComplete = 0x00008000, RxDError = 0x4000,
00207         /* See boomerang_rx() for actual error bits */
00208 };

enum xcvr_types

Enumerator:
XCVR_10baseT 
XCVR_AUI 
XCVR_10baseTOnly 
XCVR_10base2 
XCVR_100baseTx 
XCVR_100baseFx 
XCVR_MII 
XCVR_Default 

Definition at line 243 of file 3c515.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER   ) 

static void t3c515_wait ( unsigned int  nticks  )  [static]

Definition at line 56 of file 3c515.c.

References currticks().

Referenced by corkscrew_probe1(), and t515_probe().

00057 {
00058         unsigned int to = currticks() + nticks;
00059         while (currticks() < to)
00060                 /* wait */ ;
00061 }

static int corkscrew_found_device ( int  ioaddr,
int  irq,
int  product_index,
int  options,
struct nic nic 
) [static]

Definition at line 655 of file 3c515.c.

References corkscrew_private::bus_master, corkscrew_probe1(), corkscrew_private::full_duplex, corkscrew_private::media_override, corkscrew_private::options, and corkscrew_private::product_name.

Referenced by t515_probe().

00657 {
00658         /* Direct copy from Becker 3c515.c with unecessary parts removed */
00659         vp->product_name = "3c515";
00660         vp->options = options;
00661         if (options >= 0) {
00662                 vp->media_override =
00663                     ((options & 7) == 2) ? 0 : options & 7;
00664                 vp->full_duplex = (options & 8) ? 1 : 0;
00665                 vp->bus_master = (options & 16) ? 1 : 0;
00666         } else {
00667                 vp->media_override = 7;
00668                 vp->full_duplex = 0;
00669                 vp->bus_master = 0;
00670         }
00671 
00672         corkscrew_probe1(ioaddr, irq, product_index, nic);
00673         return 0;
00674 }

static int corkscrew_probe1 ( int  ioaddr,
int  irq,
int product_index  __unused,
struct nic nic 
) [static]

Definition at line 677 of file 3c515.c.

References corkscrew_private::autoselect, wn3_config::w3_config_fields::autoselect, corkscrew_private::available_media, corkscrew_private::capabilities, DBG, corkscrew_private::default_media, EEPROM_Read, EL3WINDOW, eth_ntoa(), corkscrew_private::full_bus_master_rx, corkscrew_private::full_bus_master_tx, htons, wn3_config::i, if_port, inl, inw, corkscrew_private::media_override, media_tbl, media_table::name, nic::node_addr, outw, printf(), corkscrew_private::product_name, wn3_config::w3_config_fields::ram_size, wn3_config::w3_config_fields::ram_split, wn3_config::w3_config_fields::ram_width, t3c515_wait(), wn3_config::u, Wn0EepromCmd, Wn0EepromData, Wn3_Config, Wn3_Options, and wn3_config::w3_config_fields::xcvr.

Referenced by corkscrew_found_device().

00679 {
00680         unsigned int eeprom[0x40], checksum = 0;        /* EEPROM contents */
00681         int i;
00682 
00683         printf("3Com %s at 0x%hX, ", vp->product_name, ioaddr);
00684 
00685         /* Read the station address from the EEPROM. */
00686         EL3WINDOW(0);
00687         for (i = 0; i < 0x18; i++) {
00688                 short *phys_addr = (short *) nic->node_addr;
00689                 int timer;
00690                 outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd);
00691                 /* Pause for at least 162 us. for the read to take place. */
00692                 for (timer = 4; timer >= 0; timer--) {
00693                         t3c515_wait(1);
00694                         if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) == 0)
00695                                 break;
00696                 }
00697                 eeprom[i] = inw(ioaddr + Wn0EepromData);
00698                 DBG ( "Value %d: %hX        ", i, eeprom[i] );
00699                 checksum ^= eeprom[i];
00700                 if (i < 3)
00701                         phys_addr[i] = htons(eeprom[i]);
00702         }
00703         checksum = (checksum ^ (checksum >> 8)) & 0xff;
00704         if (checksum != 0x00)
00705                 printf(" ***INVALID CHECKSUM 0x%hX*** ", checksum);
00706 
00707         DBG ( "%s", eth_ntoa ( nic->node_addr ) );
00708 
00709         if (eeprom[16] == 0x11c7) {     /* Corkscrew */
00710 
00711         }
00712         printf(", IRQ %d\n", irq);
00713         /* Tell them about an invalid IRQ. */
00714         if ( (irq <= 0 || irq > 15) ) {
00715                 DBG (" *** Warning: this IRQ is unlikely to work! ***\n" );
00716         }
00717 
00718         {
00719                 char *ram_split[] = { "5:3", "3:1", "1:1", "3:5" };
00720                 union wn3_config config;
00721                 EL3WINDOW(3);
00722                 vp->available_media = inw(ioaddr + Wn3_Options);
00723                 config.i = inl(ioaddr + Wn3_Config);
00724                 DBG ( "  Internal config register is %4.4x, "
00725                       "transceivers 0x%hX.\n",
00726                       config.i, inw(ioaddr + Wn3_Options) );
00727                 printf
00728                     ("  %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
00729                      8 << config.u.ram_size,
00730                      config.u.ram_width ? "word" : "byte",
00731                      ram_split[config.u.ram_split],
00732                      config.u.autoselect ? "autoselect/" : "",
00733                      media_tbl[config.u.xcvr].name);
00734                 if_port = config.u.xcvr;
00735                 vp->default_media = config.u.xcvr;
00736                 vp->autoselect = config.u.autoselect;
00737         }
00738         if (vp->media_override != 7) {
00739                 printf("  Media override to transceiver type %d (%s).\n",
00740                        vp->media_override,
00741                        media_tbl[vp->media_override].name);
00742                 if_port = vp->media_override;
00743         }
00744 
00745         vp->capabilities = eeprom[16];
00746         vp->full_bus_master_tx = (vp->capabilities & 0x20) ? 1 : 0;
00747         /* Rx is broken at 10mbps, so we always disable it. */
00748         /* vp->full_bus_master_rx = 0; */
00749         vp->full_bus_master_rx = (vp->capabilities & 0x20) ? 1 : 0;
00750 
00751         return 0;
00752 }

static void t515_reset ( struct nic nic  )  [static]

Definition at line 292 of file 3c515.c.

References AckIntr, AdapterFailure, corkscrew_private::autoselect, corkscrew_private::available_media, corkscrew_private::bus_master, CmdInProgress, corkscrew_private::cur_rx, corkscrew_private::cur_tx, DBG, corkscrew_private::default_media, corkscrew_private::dirty_rx, corkscrew_private::dirty_tx, DMADone, DownComplete, DownListPtr, EL3_CMD, EL3_STATUS, EL3WINDOW, corkscrew_private::full_bus_master_rx, corkscrew_private::full_bus_master_tx, corkscrew_private::full_duplex, wn3_config::i, if_port, inb, inl, IntLatch, IntReq, inw, nic::ioaddr, media_table::mask, Media_10TP, media_table::media_bits, corkscrew_private::media_override, Media_SQE, media_tbl, name, media_table::name, media_table::next, nic::node_addr, outb, outl, outw, PKT_BUF_SZ, printf(), RX_RING_SIZE, RxBroadcast, RxComplete, RxEarly, RxEnable, RxMulticast, RxProm, RxReset, RxStation, SetIntrEnb, SetRxFilter, SetStatusEnb, StartCoax, StatsFull, TX_RING_SIZE, corkscrew_private::tx_skbuff, TxAvailable, TxEnable, TxFreeThreshold, TxReset, wn3_config::u, UpComplete, Wn3_Config, Wn3_MAC_Ctrl, Wn4_Media, Wn4_NetDiag, and wn3_config::w3_config_fields::xcvr.

Referenced by t515_disable(), and t515_probe().

00293 {
00294         union wn3_config config;
00295         int i;
00296 
00297         /* Before initializing select the active media port. */
00298         EL3WINDOW(3);
00299         if (vp->full_duplex)
00300                 outb(0x20, nic->ioaddr + Wn3_MAC_Ctrl); /* Set the full-duplex bit. */
00301         config.i = inl(nic->ioaddr + Wn3_Config);
00302 
00303         if (vp->media_override != 7) {
00304                 DBG ( "Media override to transceiver %d (%s).\n",
00305                       vp->media_override,
00306                       media_tbl[vp->media_override].name);
00307                 if_port = vp->media_override;
00308         } else if (vp->autoselect) {
00309                 /* Find first available media type, starting with 100baseTx. */
00310                 if_port = 4;
00311                 while (!(vp->available_media & media_tbl[if_port].mask))
00312                         if_port = media_tbl[if_port].next;
00313 
00314                 DBG ( "Initial media type %s.\n",
00315                       media_tbl[if_port].name);
00316         } else
00317                 if_port = vp->default_media;
00318 
00319         config.u.xcvr = if_port;
00320         outl(config.i, nic->ioaddr + Wn3_Config);
00321 
00322         DBG ( "corkscrew_open() InternalConfig 0x%hX.\n",
00323               config.i);
00324 
00325         outw(TxReset, nic->ioaddr + EL3_CMD);
00326         for (i = 20; i >= 0; i--)
00327                 if (!(inw(nic->ioaddr + EL3_STATUS) & CmdInProgress))
00328                         break;
00329 
00330         outw(RxReset, nic->ioaddr + EL3_CMD);
00331         /* Wait a few ticks for the RxReset command to complete. */
00332         for (i = 20; i >= 0; i--)
00333                 if (!(inw(nic->ioaddr + EL3_STATUS) & CmdInProgress))
00334                         break;
00335 
00336         outw(SetStatusEnb | 0x00, nic->ioaddr + EL3_CMD);
00337 
00338 #ifdef debug_3c515
00339                 EL3WINDOW(4);
00340                 DBG ( "FIXME: fix print for irq, not 9" );
00341                 DBG ( "corkscrew_open() irq %d media status 0x%hX.\n",
00342                       9, inw(nic->ioaddr + Wn4_Media) );
00343 #endif
00344 
00345         /* Set the station address and mask in window 2 each time opened. */
00346         EL3WINDOW(2);
00347         for (i = 0; i < 6; i++)
00348                 outb(nic->node_addr[i], nic->ioaddr + i);
00349         for (; i < 12; i += 2)
00350                 outw(0, nic->ioaddr + i);
00351 
00352         if (if_port == 3)
00353                 /* Start the thinnet transceiver. We should really wait 50ms... */
00354                 outw(StartCoax, nic->ioaddr + EL3_CMD);
00355         EL3WINDOW(4);
00356         outw((inw(nic->ioaddr + Wn4_Media) & ~(Media_10TP | Media_SQE)) |
00357              media_tbl[if_port].media_bits, nic->ioaddr + Wn4_Media);
00358 
00359         /* Switch to the stats window, and clear all stats by reading. */
00360 /*      outw(StatsDisable, nic->ioaddr + EL3_CMD);*/
00361         EL3WINDOW(6);
00362         for (i = 0; i < 10; i++)
00363                 inb(nic->ioaddr + i);
00364         inw(nic->ioaddr + 10);
00365         inw(nic->ioaddr + 12);
00366         /* New: On the Vortex we must also clear the BadSSD counter. */
00367         EL3WINDOW(4);
00368         inb(nic->ioaddr + 12);
00369         /* ..and on the Boomerang we enable the extra statistics bits. */
00370         outw(0x0040, nic->ioaddr + Wn4_NetDiag);
00371 
00372         /* Switch to register set 7 for normal use. */
00373         EL3WINDOW(7);
00374 
00375         /* Temporarily left in place.  If these FIXMEs are printed
00376            it meand that special logic for that card may need to be added
00377            see Becker's 3c515.c driver */
00378         if (vp->full_bus_master_rx) {   /* Boomerang bus master. */
00379                 printf("FIXME: Is this if necessary");
00380                 vp->cur_rx = vp->dirty_rx = 0;
00381                 DBG ( "   Filling in the Rx ring.\n" );
00382                 for (i = 0; i < RX_RING_SIZE; i++) {
00383                         printf("FIXME: Is this if necessary");
00384                 }
00385         }
00386         if (vp->full_bus_master_tx) {   /* Boomerang bus master Tx. */
00387                 vp->cur_tx = vp->dirty_tx = 0;
00388                 outb(PKT_BUF_SZ >> 8, nic->ioaddr + TxFreeThreshold);   /* Room for a packet. */
00389                 /* Clear the Tx ring. */
00390                 for (i = 0; i < TX_RING_SIZE; i++)
00391                         vp->tx_skbuff[i] = 0;
00392                 outl(0, nic->ioaddr + DownListPtr);
00393         }
00394         /* Set receiver mode: presumably accept b-case and phys addr only. */
00395         outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm,
00396              nic->ioaddr + EL3_CMD);
00397 
00398         outw(RxEnable, nic->ioaddr + EL3_CMD);  /* Enable the receiver. */
00399         outw(TxEnable, nic->ioaddr + EL3_CMD);  /* Enable transmitter. */
00400         /* Allow status bits to be seen. */
00401         outw(SetStatusEnb | AdapterFailure | IntReq | StatsFull |
00402              (vp->full_bus_master_tx ? DownComplete : TxAvailable) |
00403              (vp->full_bus_master_rx ? UpComplete : RxComplete) |
00404              (vp->bus_master ? DMADone : 0), nic->ioaddr + EL3_CMD);
00405         /* Ack all pending events, and set active indicator mask. */
00406         outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
00407              nic->ioaddr + EL3_CMD);
00408         outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
00409              | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete,
00410              nic->ioaddr + EL3_CMD);
00411 
00412 }

static int t515_poll ( struct nic nic,
int  retrieve 
) [static]

Definition at line 417 of file 3c515.c.

References AckIntr, CmdInProgress, DBG, DMADone, DownComplete, EL3_CMD, EL3_STATUS, ETH_ALEN, inb, insw, IntLatch, IntReq, inw, nic::ioaddr, outw, nic::packet, nic::packetlen, printf(), RX_BYTES_MASK, RX_FIFO, RxComplete, RxDError, RxDiscard, RxEarly, RxStatus, SetIntrEnb, StatsFull, TxAvailable, udelay(), and UpComplete.

00418 {
00419         short status, cst;
00420         register short rx_fifo;
00421 
00422         cst = inw(nic->ioaddr + EL3_STATUS);
00423 
00424         if ((cst & RxComplete) == 0) {
00425                 /* Ack all pending events, and set active indicator mask. */
00426                 outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
00427                      nic->ioaddr + EL3_CMD);
00428                 outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete |
00429                      StatsFull | (vp->
00430                                   bus_master ? DMADone : 0) | UpComplete |
00431                      DownComplete, nic->ioaddr + EL3_CMD);
00432                 return 0;
00433         }
00434         status = inw(nic->ioaddr + RxStatus);
00435 
00436         if (status & RxDError) {
00437                 printf("RxDError\n");
00438                 outw(RxDiscard, nic->ioaddr + EL3_CMD);
00439                 return 0;
00440         }
00441 
00442         rx_fifo = status & RX_BYTES_MASK;
00443         if (rx_fifo == 0)
00444                 return 0;
00445 
00446         if ( ! retrieve ) return 1;
00447 
00448         DBG ( "[l=%d", rx_fifo );
00449         insw(nic->ioaddr + RX_FIFO, nic->packet, rx_fifo / 2);
00450         if (rx_fifo & 1)
00451                 nic->packet[rx_fifo - 1] = inb(nic->ioaddr + RX_FIFO);
00452         nic->packetlen = rx_fifo;
00453 
00454         while (1) {
00455                 status = inw(nic->ioaddr + RxStatus);
00456                 DBG ( "0x%hX*", status );
00457                 rx_fifo = status & RX_BYTES_MASK;
00458 
00459                 if (rx_fifo > 0) {
00460                         insw(nic->ioaddr + RX_FIFO, nic->packet + nic->packetlen,
00461                              rx_fifo / 2);
00462                         if (rx_fifo & 1)
00463                                 nic->packet[nic->packetlen + rx_fifo - 1] =
00464                                     inb(nic->ioaddr + RX_FIFO);
00465                         nic->packetlen += rx_fifo;
00466                         DBG ( "+%d", rx_fifo );
00467                 }
00468                 if ((status & RxComplete) == 0) {
00469                         DBG ( "=%d", nic->packetlen );
00470                         break;
00471                 }
00472                 udelay(1000);
00473         }
00474 
00475         /* acknowledge reception of packet */
00476         outw(RxDiscard, nic->ioaddr + EL3_CMD);
00477         while (inw(nic->ioaddr + EL3_STATUS) & CmdInProgress);
00478 #ifdef debug_3c515
00479         {
00480                 unsigned short type = 0;
00481                 type = (nic->packet[12] << 8) | nic->packet[13];
00482                 if (nic->packet[0] + nic->packet[1] + nic->packet[2] +
00483                     nic->packet[3] + nic->packet[4] + nic->packet[5] ==
00484                     0xFF * ETH_ALEN)
00485                         DBG ( ",t=0x%hX,b]", type );
00486                 else
00487                         DBG ( ",t=0x%hX]", type );
00488         }
00489 #endif
00490 
00491         return 1;
00492 }

static void t515_transmit ( struct nic nic,
const char *  d,
unsigned int  t,
unsigned int  s,
const char *  p 
) [static]

Definition at line 503 of file 3c515.c.

References CmdInProgress, DBG, EL3_CMD, EL3_STATUS, ETH_ALEN, ETH_FRAME_LEN, ETH_HLEN, htons, inb, inw, nic::ioaddr, nic::node_addr, outb, outsw, outw, TX_FIFO, TxComplete, TxEnable, TxFree, TxReset, and TxStatus.

00507 {                               /* Packet */
00508         register int len;
00509         int pad;
00510         int status;
00511 
00512         DBG ( "{l=%d,t=0x%hX}", s + ETH_HLEN, t );
00513 
00514         /* swap bytes of type */
00515         t = htons(t);
00516 
00517         len = s + ETH_HLEN;     /* actual length of packet */
00518         pad = padmap[len & 3];
00519 
00520         /*
00521          * The 3c515 automatically pads short packets to minimum ethernet length,
00522          * but we drop packets that are too large. Perhaps we should truncate
00523          * them instead?
00524          Copied from 3c595.  Is this true for the 3c515?
00525          */
00526         if (len + pad > ETH_FRAME_LEN) {
00527                 return;
00528         }
00529         /* drop acknowledgements */
00530         while ((status = inb(nic->ioaddr + TxStatus)) & TxComplete) {
00531                 /*if(status & (TXS_UNDERRUN|0x88|TXS_STATUS_OVERFLOW)) { */
00532                 outw(TxReset, nic->ioaddr + EL3_CMD);
00533                 outw(TxEnable, nic->ioaddr + EL3_CMD);
00534 /*              }                                                          */
00535 
00536                 outb(0x0, nic->ioaddr + TxStatus);
00537         }
00538 
00539         while (inw(nic->ioaddr + TxFree) < len + pad + 4) {
00540                 /* no room in FIFO */
00541         }
00542 
00543         outw(len, nic->ioaddr + TX_FIFO);
00544         outw(0x0, nic->ioaddr + TX_FIFO);       /* Second dword meaningless */
00545 
00546         /* write packet */
00547         outsw(nic->ioaddr + TX_FIFO, d, ETH_ALEN / 2);
00548         outsw(nic->ioaddr + TX_FIFO, nic->node_addr, ETH_ALEN / 2);
00549         outw(t, nic->ioaddr + TX_FIFO);
00550         outsw(nic->ioaddr + TX_FIFO, p, s / 2);
00551 
00552         if (s & 1)
00553                 outb(*(p + s - 1), nic->ioaddr + TX_FIFO);
00554 
00555         while (pad--)
00556                 outb(0, nic->ioaddr + TX_FIFO); /* Padding */
00557 
00558         /* wait for Tx complete */
00559         while ((inw(nic->ioaddr + EL3_STATUS) & CmdInProgress) != 0);
00560 }

static void t515_disable ( struct nic nic,
struct isapnp_device isapnp 
) [static]

Definition at line 565 of file 3c515.c.

References deactivate_isapnp_device(), EL3_CMD, if_port, nic::ioaddr, outw, RxDisable, SetIntrEnb, StopCoax, t515_reset(), and TxDisable.

00566                                                           {
00567 
00568         t515_reset(nic);
00569 
00570         /* This is a hack.  Since ltsp worked on my
00571            system without any disable functionality I
00572            have no way to determine if this works */
00573 
00574         /* Disable the receiver and transmitter. */
00575         outw(RxDisable, nic->ioaddr + EL3_CMD);
00576         outw(TxDisable, nic->ioaddr + EL3_CMD);
00577 
00578         if (if_port == XCVR_10base2)
00579                 /* Turn off thinnet power.  Green! */
00580                 outw(StopCoax, nic->ioaddr + EL3_CMD);
00581 
00582 
00583         outw(SetIntrEnb | 0x0000, nic->ioaddr + EL3_CMD);
00584 
00585         deactivate_isapnp_device ( isapnp );
00586         return;
00587 }

static void t515_irq ( struct nic *nic  __unused,
irq_action_t action  __unused 
) [static]

Definition at line 589 of file 3c515.c.

References DISABLE, ENABLE, and FORCE.

00590 {
00591   switch ( action ) {
00592   case DISABLE :
00593     break;
00594   case ENABLE :
00595     break;
00596   case FORCE :
00597     break;
00598   }
00599 }

static int t515_probe ( struct nic nic,
struct isapnp_device isapnp 
) [static]

Definition at line 613 of file 3c515.c.

References activate_isapnp_device(), corkscrew_found_device(), CORKSCREW_ID, DBG, EEPROM_Read, inl, inw, isapnp_device::ioaddr, nic::ioaddr, isapnp_device::irqno, nic::irqno, nic::nic_op, outw, t3c515_wait(), t515_reset(), Wn0EepromCmd, and Wn0EepromData.

00613                                                                         {
00614 
00615         /* Direct copy from Beckers 3c515.c removing any ISAPNP sections */
00616 
00617         nic->ioaddr = isapnp->ioaddr;
00618         nic->irqno = isapnp->irqno;
00619         activate_isapnp_device ( isapnp );
00620 
00621         /* Check the resource configuration for a matching ioaddr. */
00622         if ((unsigned)(inw(nic->ioaddr + 0x2002) & 0x1f0)
00623             != (nic->ioaddr & 0x1f0)) {
00624                 DBG ( "3c515 ioaddr mismatch\n" );
00625                 return 0;
00626         }
00627 
00628         /* Verify by reading the device ID from the EEPROM. */
00629         {
00630                 int timer;
00631                 outw(EEPROM_Read + 7, nic->ioaddr + Wn0EepromCmd);
00632                 /* Pause for at least 162 us. for the read to take place. */
00633                 for (timer = 4; timer >= 0; timer--) {
00634                         t3c515_wait(1);
00635                         if ((inw(nic->ioaddr + Wn0EepromCmd) & 0x0200) == 0)
00636                                 break;
00637                 }
00638                 if (inw(nic->ioaddr + Wn0EepromData) != 0x6d50) {
00639                         DBG ( "3c515 read incorrect vendor ID from EEPROM" );
00640                         return 0;
00641                 }
00642 
00643         }
00644         DBG ( "3c515 Resource configuration register 0x%X, DCR 0x%hX.\n",
00645               inl(nic->ioaddr + 0x2002), inw(nic->ioaddr + 0x2000) );
00646         corkscrew_found_device(nic->ioaddr, nic->irqno, CORKSCREW_ID,
00647                                options, nic);
00648         
00649         t515_reset(nic);        
00650         nic->nic_op     = &t515_operations;
00651         return 1;
00652 }

ISAPNP_DRIVER ( t515_driver  ,
t515_adapters   
)

DRIVER ( "3c515"  ,
nic_driver  ,
isapnp_driver  ,
t515_driver  ,
t515_probe  ,
t515_disable   
)

ISA_ROM ( "3c515"  ,
"3c515 Fast EtherLink ISAPnP"   
)


Variable Documentation

int if_port [static]

Definition at line 65 of file 3c515.c.

Referenced by corkscrew_probe1(), t515_disable(), and t515_reset().

struct corkscrew_private* vp [static]

Definition at line 66 of file 3c515.c.

struct media_table media_tbl[] [static]

Referenced by corkscrew_probe1(), and t515_reset().

int options = -1 [static]

Definition at line 285 of file 3c515.c.

Referenced by dhcppkt_init(), dhcppkt_store(), ifec_net_open(), and pcnet32_probe().

char padmap[] [static]

Initial value:

 {
        0, 3, 2, 1
}

Definition at line 497 of file 3c515.c.

Referenced by t509_transmit(), and t595_transmit().

Initial value:

 {
        .connect        = dummy_connect,
        .poll           = t515_poll,
        .transmit       = t515_transmit,
        .irq            = t515_irq,

}

Definition at line 601 of file 3c515.c.

struct isapnp_device_id t515_adapters[] [static]

Initial value:

 {
        { "3c515 (ISAPnP)", ISAPNP_VENDOR('T','C','M'), 0x5051 },
}

Definition at line 754 of file 3c515.c.


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