iPXE
Data Structures | Defines | Enumerations | Functions | Variables
3c515.c File Reference
#include "etherboot.h"
#include "nic.h"
#include <ipxe/isapnp.h>
#include <ipxe/isa.h>
#include <ipxe/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 /* Size of each temporary Rx buffer. */
#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 65 of file 3c515.c.

#define CORKSCREW   1

Definition at line 69 of file 3c515.c.

#define AUTOMEDIA   1

Definition at line 76 of file 3c515.c.

Definition at line 82 of file 3c515.c.

#define TX_RING_SIZE   16
#define RX_RING_SIZE   16
#define PKT_BUF_SZ   1536 /* Size of each temporary Rx buffer. */

Definition at line 88 of file 3c515.c.

Referenced by t515_reset().

#define DRIVER_DEBUG   1

Definition at line 92 of file 3c515.c.

#define CORKSCREW_ID   10

Definition at line 98 of file 3c515.c.

Referenced by t515_probe().

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

Definition at line 100 of file 3c515.c.

Referenced by corkscrew_probe1(), and t515_reset().

#define EL3_CMD   0x0e

Definition at line 102 of file 3c515.c.

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

#define EL3_STATUS   0x0e

Definition at line 103 of file 3c515.c.

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

#define RX_BYTES_MASK   (unsigned short) (0x07ff)

Definition at line 104 of file 3c515.c.

Referenced by t515_poll().


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 106 of file 3c515.c.

                   {
        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 =
            10 << 11, TxReset = 11 << 11,
        FakeIntr = 12 << 11, AckIntr = 13 << 11, SetIntrEnb = 14 << 11,
        SetStatusEnb = 15 << 11, SetRxFilter = 16 << 11, SetRxThreshold =
            17 << 11,
        SetTxThreshold = 18 << 11, SetTxStart = 19 << 11,
        StartDMAUp = 20 << 11, StartDMADown = (20 << 11) + 1, StatsEnable =
            21 << 11,
        StatsDisable = 22 << 11, StopCoax = 23 << 11,
};
enum RxFilter
Enumerator:
RxStation 
RxMulticast 
RxBroadcast 
RxProm 

Definition at line 123 of file 3c515.c.

              {
        RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8
};
Enumerator:
IntLatch 
AdapterFailure 
TxComplete 
TxAvailable 
RxComplete 
RxEarly 
IntReq 
StatsFull 
DMADone 
DownComplete 
UpComplete 
DMAInProgress 
CmdInProgress 

Definition at line 128 of file 3c515.c.

                      {
        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,        /* DMA controller is still busy. */
        CmdInProgress = 1 << 12,        /* EL3_CMD is still busy. */
};
enum Window1
Enumerator:
TX_FIFO 
RX_FIFO 
RxErrors 
RxStatus 
Timer 
TxStatus 
TxFree 

Definition at line 139 of file 3c515.c.

             {
        TX_FIFO = 0x10, RX_FIFO = 0x10, RxErrors = 0x14,
        RxStatus = 0x18, Timer = 0x1A, TxStatus = 0x1B,
        TxFree = 0x1C,          /* Remaining free bytes in Tx buffer. */
};
enum Window0
Enumerator:
Wn0IRQ 
Wn0EepromCmd 
Wn0EepromData 

Definition at line 144 of file 3c515.c.

             {
        Wn0IRQ = 0x08,
#if defined(CORKSCREW)
        Wn0EepromCmd = 0x200A,  /* Corkscrew EEPROM command register. */
        Wn0EepromData = 0x200C, /* Corkscrew EEPROM results register. */
#else
        Wn0EepromCmd = 10,      /* Window 0: EEPROM command register. */
        Wn0EepromData = 12,     /* Window 0: EEPROM results register. */
#endif
};
Enumerator:
EEPROM_Read 
EEPROM_WRITE 
EEPROM_ERASE 
EEPROM_EWENB 
EEPROM_EWDIS 

Definition at line 154 of file 3c515.c.

                      {
        EEPROM_Read = 0x80, EEPROM_WRITE = 0x40, EEPROM_ERASE = 0xC0,
        EEPROM_EWENB = 0x30,    /* Enable erasing/writing for 10 msec. */
        EEPROM_EWDIS = 0x00,    /* Disable EWENB before 10 msec timeout. */
};
enum Window3
Enumerator:
Wn3_Config 
Wn3_MAC_Ctrl 
Wn3_Options 

Definition at line 160 of file 3c515.c.

             {                  /* Window 3: MAC/config bits. */
        Wn3_Config = 0, Wn3_MAC_Ctrl = 6, Wn3_Options = 8,
};
enum Window4
Enumerator:
Wn4_NetDiag 
Wn4_Media 

Definition at line 175 of file 3c515.c.

             {
        Wn4_NetDiag = 6, Wn4_Media = 10,        /* Window 4: Xcvr/media bits. */
};
Enumerator:
Media_SQE 
Media_10TP 
Media_Lnk 
Media_LnkBeat 

Definition at line 178 of file 3c515.c.

                     {
        Media_SQE = 0x0008,     /* Enable SQE error counting for AUI. */
        Media_10TP = 0x00C0,    /* Enable link beat and jabber for 10baseT. */
        Media_Lnk = 0x0080,     /* Enable just link beat for 100TX/100FX. */
        Media_LnkBeat = 0x0800,
};
enum Window7
Enumerator:
Wn7_MasterAddr 
Wn7_MasterLen 
Wn7_MasterStatus 

Definition at line 184 of file 3c515.c.

             {                  /* Window 7: Bus Master control. */
        Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12,
};
enum MasterCtrl
Enumerator:
PktStatus 
DownListPtr 
FragAddr 
FragLen 
TxFreeThreshold 
UpPktStatus 
UpListPtr 

Definition at line 189 of file 3c515.c.

                {
        PktStatus = 0x400, DownListPtr = 0x404, FragAddr = 0x408, FragLen =
            0x40c,
        TxFreeThreshold = 0x40f, UpPktStatus = 0x410, UpListPtr = 0x418,
};
Enumerator:
RxDComplete 
RxDError 

Definition at line 206 of file 3c515.c.

                    {
        RxDComplete = 0x00008000, RxDError = 0x4000,
        /* See boomerang_rx() for actual error bits */
};
enum xcvr_types
Enumerator:
XCVR_10baseT 
XCVR_AUI 
XCVR_10baseTOnly 
XCVR_10base2 
XCVR_100baseTx 
XCVR_100baseFx 
XCVR_MII 
XCVR_Default 

Definition at line 244 of file 3c515.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER  )
static void t3c515_wait ( unsigned int  nticks) [static]

Definition at line 57 of file 3c515.c.

References currticks().

Referenced by corkscrew_probe1(), and t515_probe().

{
        unsigned int to = currticks() + nticks;
        while (currticks() < to)
                /* wait */ ;
}
static int corkscrew_found_device ( int  ioaddr,
int  irq,
int  product_index,
int  options,
struct nic nic 
) [static]

Definition at line 656 of file 3c515.c.

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

Referenced by t515_probe().

{
        /* Direct copy from Becker 3c515.c with unnecessary parts removed */
        vp->product_name = "3c515";
        vp->options = options;
        if (options >= 0) {
                vp->media_override =
                    ((options & 7) == 2) ? 0 : options & 7;
                vp->full_duplex = (options & 8) ? 1 : 0;
                vp->bus_master = (options & 16) ? 1 : 0;
        } else {
                vp->media_override = 7;
                vp->full_duplex = 0;
                vp->bus_master = 0;
        }

        corkscrew_probe1(ioaddr, irq, product_index, nic);
        return 0;
}
static int corkscrew_probe1 ( int  ioaddr,
int  irq,
int product_index  __unused,
struct nic nic 
) [static]

Definition at line 678 of file 3c515.c.

References wn3_config::w3_config_fields::autoselect, corkscrew_private::autoselect, corkscrew_private::available_media, corkscrew_private::capabilities, checksum, DBG, corkscrew_private::default_media, eeprom, 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, 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().

{
        unsigned int eeprom[0x40], checksum = 0;        /* EEPROM contents */
        int i;

        printf("3Com %s at 0x%hX, ", vp->product_name, ioaddr);

        /* Read the station address from the EEPROM. */
        EL3WINDOW(0);
        for (i = 0; i < 0x18; i++) {
                short *phys_addr = (short *) nic->node_addr;
                int timer;
                outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd);
                /* Pause for at least 162 us. for the read to take place. */
                for (timer = 4; timer >= 0; timer--) {
                        t3c515_wait(1);
                        if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) == 0)
                                break;
                }
                eeprom[i] = inw(ioaddr + Wn0EepromData);
                DBG ( "Value %d: %hX        ", i, eeprom[i] );
                checksum ^= eeprom[i];
                if (i < 3)
                        phys_addr[i] = htons(eeprom[i]);
        }
        checksum = (checksum ^ (checksum >> 8)) & 0xff;
        if (checksum != 0x00)
                printf(" ***INVALID CHECKSUM 0x%hX*** ", checksum);

        DBG ( "%s", eth_ntoa ( nic->node_addr ) );

        if (eeprom[16] == 0x11c7) {     /* Corkscrew */

        }
        printf(", IRQ %d\n", irq);
        /* Tell them about an invalid IRQ. */
        if ( (irq <= 0 || irq > 15) ) {
                DBG (" *** Warning: this IRQ is unlikely to work! ***\n" );
        }

        {
                char *ram_split[] = { "5:3", "3:1", "1:1", "3:5" };
                union wn3_config config;
                EL3WINDOW(3);
                vp->available_media = inw(ioaddr + Wn3_Options);
                config.i = inl(ioaddr + Wn3_Config);
                DBG ( "  Internal config register is %4.4x, "
                      "transceivers 0x%hX.\n",
                      config.i, inw(ioaddr + Wn3_Options) );
                printf
                    ("  %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
                     8 << config.u.ram_size,
                     config.u.ram_width ? "word" : "byte",
                     ram_split[config.u.ram_split],
                     config.u.autoselect ? "autoselect/" : "",
                     media_tbl[config.u.xcvr].name);
                if_port = config.u.xcvr;
                vp->default_media = config.u.xcvr;
                vp->autoselect = config.u.autoselect;
        }
        if (vp->media_override != 7) {
                printf("  Media override to transceiver type %d (%s).\n",
                       vp->media_override,
                       media_tbl[vp->media_override].name);
                if_port = vp->media_override;
        }

        vp->capabilities = eeprom[16];
        vp->full_bus_master_tx = (vp->capabilities & 0x20) ? 1 : 0;
        /* Rx is broken at 10mbps, so we always disable it. */
        /* vp->full_bus_master_rx = 0; */
        vp->full_bus_master_rx = (vp->capabilities & 0x20) ? 1 : 0;

        return 0;
}
static void t515_reset ( struct nic nic) [static]

Definition at line 293 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(), media_table::mask, Media_10TP, media_table::media_bits, corkscrew_private::media_override, Media_SQE, media_tbl, media_table::name, name, media_table::next, NULL, 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().

{
        union wn3_config config;
        int i;

        /* Before initializing select the active media port. */
        EL3WINDOW(3);
        if (vp->full_duplex)
                outb(0x20, nic->ioaddr + Wn3_MAC_Ctrl); /* Set the full-duplex bit. */
        config.i = inl(nic->ioaddr + Wn3_Config);

        if (vp->media_override != 7) {
                DBG ( "Media override to transceiver %d (%s).\n",
                      vp->media_override,
                      media_tbl[vp->media_override].name);
                if_port = vp->media_override;
        } else if (vp->autoselect) {
                /* Find first available media type, starting with 100baseTx. */
                if_port = 4;
                while (!(vp->available_media & media_tbl[if_port].mask))
                        if_port = media_tbl[if_port].next;

                DBG ( "Initial media type %s.\n",
                      media_tbl[if_port].name);
        } else
                if_port = vp->default_media;

        config.u.xcvr = if_port;
        outl(config.i, nic->ioaddr + Wn3_Config);

        DBG ( "corkscrew_open() InternalConfig 0x%hX.\n",
              config.i);

        outw(TxReset, nic->ioaddr + EL3_CMD);
        for (i = 20; i >= 0; i--)
                if (!(inw(nic->ioaddr + EL3_STATUS) & CmdInProgress))
                        break;

        outw(RxReset, nic->ioaddr + EL3_CMD);
        /* Wait a few ticks for the RxReset command to complete. */
        for (i = 20; i >= 0; i--)
                if (!(inw(nic->ioaddr + EL3_STATUS) & CmdInProgress))
                        break;

        outw(SetStatusEnb | 0x00, nic->ioaddr + EL3_CMD);

#ifdef debug_3c515
                EL3WINDOW(4);
                DBG ( "FIXME: fix print for irq, not 9" );
                DBG ( "corkscrew_open() irq %d media status 0x%hX.\n",
                      9, inw(nic->ioaddr + Wn4_Media) );
#endif

        /* Set the station address and mask in window 2 each time opened. */
        EL3WINDOW(2);
        for (i = 0; i < 6; i++)
                outb(nic->node_addr[i], nic->ioaddr + i);
        for (; i < 12; i += 2)
                outw(0, nic->ioaddr + i);

        if (if_port == 3)
                /* Start the thinnet transceiver. We should really wait 50ms... */
                outw(StartCoax, nic->ioaddr + EL3_CMD);
        EL3WINDOW(4);
        outw((inw(nic->ioaddr + Wn4_Media) & ~(Media_10TP | Media_SQE)) |
             media_tbl[if_port].media_bits, nic->ioaddr + Wn4_Media);

        /* Switch to the stats window, and clear all stats by reading. */
/*      outw(StatsDisable, nic->ioaddr + EL3_CMD);*/
        EL3WINDOW(6);
        for (i = 0; i < 10; i++)
                inb(nic->ioaddr + i);
        inw(nic->ioaddr + 10);
        inw(nic->ioaddr + 12);
        /* New: On the Vortex we must also clear the BadSSD counter. */
        EL3WINDOW(4);
        inb(nic->ioaddr + 12);
        /* ..and on the Boomerang we enable the extra statistics bits. */
        outw(0x0040, nic->ioaddr + Wn4_NetDiag);

        /* Switch to register set 7 for normal use. */
        EL3WINDOW(7);

        /* Temporarily left in place.  If these FIXMEs are printed
           it meand that special logic for that card may need to be added
           see Becker's 3c515.c driver */
        if (vp->full_bus_master_rx) {   /* Boomerang bus master. */
                printf("FIXME: Is this if necessary");
                vp->cur_rx = vp->dirty_rx = 0;
                DBG ( "   Filling in the Rx ring.\n" );
                for (i = 0; i < RX_RING_SIZE; i++) {
                        printf("FIXME: Is this if necessary");
                }
        }
        if (vp->full_bus_master_tx) {   /* Boomerang bus master Tx. */
                vp->cur_tx = vp->dirty_tx = 0;
                outb(PKT_BUF_SZ >> 8, nic->ioaddr + TxFreeThreshold);   /* Room for a packet. */
                /* Clear the Tx ring. */
                for (i = 0; i < TX_RING_SIZE; i++)
                        vp->tx_skbuff[i] = NULL;
                outl(0, nic->ioaddr + DownListPtr);
        }
        /* Set receiver mode: presumably accept b-case and phys addr only. */
        outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm,
             nic->ioaddr + EL3_CMD);

        outw(RxEnable, nic->ioaddr + EL3_CMD);  /* Enable the receiver. */
        outw(TxEnable, nic->ioaddr + EL3_CMD);  /* Enable transmitter. */
        /* Allow status bits to be seen. */
        outw(SetStatusEnb | AdapterFailure | IntReq | StatsFull |
             (vp->full_bus_master_tx ? DownComplete : TxAvailable) |
             (vp->full_bus_master_rx ? UpComplete : RxComplete) |
             (vp->bus_master ? DMADone : 0), nic->ioaddr + EL3_CMD);
        /* Ack all pending events, and set active indicator mask. */
        outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
             nic->ioaddr + EL3_CMD);
        outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
             | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete,
             nic->ioaddr + EL3_CMD);

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

Definition at line 418 of file 3c515.c.

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

{
        short status, cst;
        register short rx_fifo;

        cst = inw(nic->ioaddr + EL3_STATUS);

        if ((cst & RxComplete) == 0) {
                /* Ack all pending events, and set active indicator mask. */
                outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
                     nic->ioaddr + EL3_CMD);
                outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete |
                     StatsFull | (vp->
                                  bus_master ? DMADone : 0) | UpComplete |
                     DownComplete, nic->ioaddr + EL3_CMD);
                return 0;
        }
        status = inw(nic->ioaddr + RxStatus);

        if (status & RxDError) {
                printf("RxDError\n");
                outw(RxDiscard, nic->ioaddr + EL3_CMD);
                return 0;
        }

        rx_fifo = status & RX_BYTES_MASK;
        if (rx_fifo == 0)
                return 0;

        if ( ! retrieve ) return 1;

        DBG ( "[l=%d", rx_fifo );
        insw(nic->ioaddr + RX_FIFO, nic->packet, rx_fifo / 2);
        if (rx_fifo & 1)
                nic->packet[rx_fifo - 1] = inb(nic->ioaddr + RX_FIFO);
        nic->packetlen = rx_fifo;

        while (1) {
                status = inw(nic->ioaddr + RxStatus);
                DBG ( "0x%hX*", status );
                rx_fifo = status & RX_BYTES_MASK;

                if (rx_fifo > 0) {
                        insw(nic->ioaddr + RX_FIFO, nic->packet + nic->packetlen,
                             rx_fifo / 2);
                        if (rx_fifo & 1)
                                nic->packet[nic->packetlen + rx_fifo - 1] =
                                    inb(nic->ioaddr + RX_FIFO);
                        nic->packetlen += rx_fifo;
                        DBG ( "+%d", rx_fifo );
                }
                if ((status & RxComplete) == 0) {
                        DBG ( "=%d", nic->packetlen );
                        break;
                }
                udelay(1000);
        }

        /* acknowledge reception of packet */
        outw(RxDiscard, nic->ioaddr + EL3_CMD);
        while (inw(nic->ioaddr + EL3_STATUS) & CmdInProgress);
#ifdef debug_3c515
        {
                unsigned short type = 0;
                type = (nic->packet[12] << 8) | nic->packet[13];
                if (nic->packet[0] + nic->packet[1] + nic->packet[2] +
                    nic->packet[3] + nic->packet[4] + nic->packet[5] ==
                    0xFF * ETH_ALEN)
                        DBG ( ",t=0x%hX,b]", type );
                else
                        DBG ( ",t=0x%hX]", type );
        }
#endif

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

Definition at line 504 of file 3c515.c.

References CmdInProgress, DBG, EL3_CMD, EL3_STATUS, ETH_ALEN, ETH_FRAME_LEN, ETH_HLEN, htons, inb(), inw(), len, outb(), outsw(), outw(), pad, status, TX_FIFO, TxComplete, TxEnable, TxFree, TxReset, and TxStatus.

{                               /* Packet */
        register int len;
        int pad;
        int status;

        DBG ( "{l=%d,t=0x%hX}", s + ETH_HLEN, t );

        /* swap bytes of type */
        t = htons(t);

        len = s + ETH_HLEN;     /* actual length of packet */
        pad = padmap[len & 3];

        /*
         * The 3c515 automatically pads short packets to minimum ethernet length,
         * but we drop packets that are too large. Perhaps we should truncate
         * them instead?
         Copied from 3c595.  Is this true for the 3c515?
         */
        if (len + pad > ETH_FRAME_LEN) {
                return;
        }
        /* drop acknowledgements */
        while ((status = inb(nic->ioaddr + TxStatus)) & TxComplete) {
                /*if(status & (TXS_UNDERRUN|0x88|TXS_STATUS_OVERFLOW)) { */
                outw(TxReset, nic->ioaddr + EL3_CMD);
                outw(TxEnable, nic->ioaddr + EL3_CMD);
/*              }                                                          */

                outb(0x0, nic->ioaddr + TxStatus);
        }

        while (inw(nic->ioaddr + TxFree) < len + pad + 4) {
                /* no room in FIFO */
        }

        outw(len, nic->ioaddr + TX_FIFO);
        outw(0x0, nic->ioaddr + TX_FIFO);       /* Second dword meaningless */

        /* write packet */
        outsw(nic->ioaddr + TX_FIFO, d, ETH_ALEN / 2);
        outsw(nic->ioaddr + TX_FIFO, nic->node_addr, ETH_ALEN / 2);
        outw(t, nic->ioaddr + TX_FIFO);
        outsw(nic->ioaddr + TX_FIFO, p, s / 2);

        if (s & 1)
                outb(*(p + s - 1), nic->ioaddr + TX_FIFO);

        while (pad--)
                outb(0, nic->ioaddr + TX_FIFO); /* Padding */

        /* wait for Tx complete */
        while ((inw(nic->ioaddr + EL3_STATUS) & CmdInProgress) != 0);
}
static void t515_disable ( struct nic nic,
struct isapnp_device *  isapnp 
) [static]

Definition at line 566 of file 3c515.c.

References EL3_CMD, if_port, outw(), RxDisable, SetIntrEnb, StopCoax, t515_reset(), and TxDisable.

                                                          {

        t515_reset(nic);

        /* This is a hack.  Since ltsp worked on my
           system without any disable functionality I
           have no way to determine if this works */

        /* Disable the receiver and transmitter. */
        outw(RxDisable, nic->ioaddr + EL3_CMD);
        outw(TxDisable, nic->ioaddr + EL3_CMD);

        if (if_port == XCVR_10base2)
                /* Turn off thinnet power.  Green! */
                outw(StopCoax, nic->ioaddr + EL3_CMD);


        outw(SetIntrEnb | 0x0000, nic->ioaddr + EL3_CMD);

        deactivate_isapnp_device ( isapnp );
        return;
}
static void t515_irq ( struct nic *nic  __unused,
irq_action_t action  __unused 
) [static]

Definition at line 590 of file 3c515.c.

{
  switch ( action ) {
  case DISABLE :
    break;
  case ENABLE :
    break;
  case FORCE :
    break;
  }
}
static int t515_probe ( struct nic nic,
struct isapnp_device *  isapnp 
) [static]

Definition at line 614 of file 3c515.c.

References corkscrew_found_device(), CORKSCREW_ID, DBG, EEPROM_Read, inl(), inw(), outw(), t3c515_wait(), t515_operations, t515_reset(), timer, Wn0EepromCmd, and Wn0EepromData.

                                                                        {

        /* Direct copy from Beckers 3c515.c removing any ISAPNP sections */

        nic->ioaddr = isapnp->ioaddr;
        nic->irqno = isapnp->irqno;
        activate_isapnp_device ( isapnp );

        /* Check the resource configuration for a matching ioaddr. */
        if ((unsigned)(inw(nic->ioaddr + 0x2002) & 0x1f0)
            != (nic->ioaddr & 0x1f0)) {
                DBG ( "3c515 ioaddr mismatch\n" );
                return 0;
        }

        /* Verify by reading the device ID from the EEPROM. */
        {
                int timer;
                outw(EEPROM_Read + 7, nic->ioaddr + Wn0EepromCmd);
                /* Pause for at least 162 us. for the read to take place. */
                for (timer = 4; timer >= 0; timer--) {
                        t3c515_wait(1);
                        if ((inw(nic->ioaddr + Wn0EepromCmd) & 0x0200) == 0)
                                break;
                }
                if (inw(nic->ioaddr + Wn0EepromData) != 0x6d50) {
                        DBG ( "3c515 read incorrect vendor ID from EEPROM" );
                        return 0;
                }

        }
        DBG ( "3c515 Resource configuration register 0x%X, DCR 0x%hX.\n",
              inl(nic->ioaddr + 0x2002), inw(nic->ioaddr + 0x2000) );
        corkscrew_found_device(nic->ioaddr, nic->irqno, CORKSCREW_ID,
                               options, nic);
        
        t515_reset(nic);        
        nic->nic_op     = &t515_operations;
        return 1;
}
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 66 of file 3c515.c.

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

struct corkscrew_private* vp [static]

Definition at line 67 of file 3c515.c.

struct media_table media_tbl[] [static]

Referenced by corkscrew_probe1(), and t515_reset().

int options = -1 [static]
char padmap[] [static]
Initial value:
 {
        0, 3, 2, 1
}

Definition at line 498 of file 3c515.c.

struct nic_operations t515_operations [static]
Initial value:
 {
        .connect        = dummy_connect,
        .poll           = t515_poll,
        .transmit       = t515_transmit,
        .irq            = t515_irq,

}

Definition at line 602 of file 3c515.c.

Referenced by t515_probe().

struct isapnp_device_id t515_adapters[] [static]
Initial value:
 {
        { "3c515 (ISAPnP)", ISAPNP_VENDOR('T','C','M'), 0x5051 },
}

Definition at line 755 of file 3c515.c.