iPXE
Data Structures | Defines | Enumerations | Functions | Variables
sundance.c File Reference
#include "etherboot.h"
#include "nic.h"
#include <ipxe/pci.h>
#include "mii.h"

Go to the source code of this file.

Data Structures

struct  netdev_desc
struct  sundance_private

Defines

#define drv_version   "v1.12"
#define drv_date   "2004-03-21"
#define HZ   100
#define virt_to_le32desc(addr)   cpu_to_le32(virt_to_bus(addr))
#define le32desc_to_virt(addr)   bus_to_virt(le32_to_cpu(addr))
#define TX_RING_SIZE   2
#define TX_QUEUE_LEN   10 /* Limit ring entries actually used. */
#define RX_RING_SIZE   4
#define TX_TIME_OUT   (4*HZ)
#define PKT_BUF_SZ   1536
#define rxb   rx_tx_buf.rxb
#define txb   rx_tx_buf.txb
#define EEPROM_SIZE   128
#define PCI_IOTYPE   (PCI_USES_MASTER | PCI_USES_IO | PCI_ADDR0)
#define MII_CNT   4
#define EEPROM_SA_OFFSET   0x10
#define DEFAULT_INTR
#define mdio_in(mdio_addr)   inb(mdio_addr)
#define mdio_out(value, mdio_addr)   outb(value, mdio_addr)
#define mdio_delay(mdio_addr)   inb(mdio_addr)
#define MDIO_EnbIn   (0)
#define MDIO_WRITE0   (MDIO_EnbOutput)
#define MDIO_WRITE1   (MDIO_Data | MDIO_EnbOutput)

Enumerations

enum  alta_offsets {
  DMACtrl = 0x00, TxListPtr = 0x04, TxDMABurstThresh = 0x08, TxDMAUrgentThresh = 0x09,
  TxDMAPollPeriod = 0x0a, RxDMAStatus = 0x0c, RxListPtr = 0x10, DebugCtrl0 = 0x1a,
  DebugCtrl1 = 0x1c, RxDMABurstThresh = 0x14, RxDMAUrgentThresh = 0x15, RxDMAPollPeriod = 0x16,
  LEDCtrl = 0x1a, ASICCtrl = 0x30, EEData = 0x34, EECtrl = 0x36,
  TxStartThresh = 0x3c, RxEarlyThresh = 0x3e, FlashAddr = 0x40, FlashData = 0x44,
  TxStatus = 0x46, TxFrameId = 0x47, DownCounter = 0x18, IntrClear = 0x4a,
  IntrEnable = 0x4c, IntrStatus = 0x4e, MACCtrl0 = 0x50, MACCtrl1 = 0x52,
  StationAddr = 0x54, MaxFrameSize = 0x5A, RxMode = 0x5c, MIICtrl = 0x5e,
  MulticastFilter0 = 0x60, MulticastFilter1 = 0x64, RxOctetsLow = 0x68, RxOctetsHigh = 0x6a,
  TxOctetsLow = 0x6c, TxOctetsHigh = 0x6e, TxFramesOK = 0x70, RxFramesOK = 0x72,
  StatsCarrierError = 0x74, StatsLateColl = 0x75, StatsMultiColl = 0x76, StatsOneColl = 0x77,
  StatsTxDefer = 0x78, RxMissed = 0x79, StatsTxXSDefer = 0x7a, StatsTxAbort = 0x7b,
  StatsBcastTx = 0x7c, StatsBcastRx = 0x7d, StatsMcastTx = 0x7e, StatsMcastRx = 0x7f,
  RxStatus = 0x0c
}
enum  ASICCtrl_HiWord_bit {
  GlobalReset = 0x0001, RxReset = 0x0002, TxReset = 0x0004, DMAReset = 0x0008,
  FIFOReset = 0x0010, NetworkReset = 0x0020, HostReset = 0x0040, ResetBusy = 0x0400
}
enum  intr_status_bits {
  IntrSummary = 0x0001, IntrPCIErr = 0x0002, IntrMACCtrl = 0x0008, IntrTxDone = 0x0004,
  IntrRxDone = 0x0010, IntrRxStart = 0x0020, IntrDrvRqst = 0x0040, StatsMax = 0x0080,
  LinkChange = 0x0100, IntrTxDMADone = 0x0200, IntrRxDMADone = 0x0400, NormalIntr = 0x10000,
  AbnormalIntr = 0x8000, IntrPCIErr = 0x2000, TimerInt = 0x800, IntrRxDied = 0x100,
  RxNoBuf = 0x80, IntrRxDone = 0x40, TxFIFOUnderflow = 0x20, RxErrIntr = 0x10,
  TxIdle = 0x04, IntrTxStopped = 0x02, IntrTxDone = 0x01
}
enum  rx_mode_bits {
  AcceptAllIPMulti = 0x20, AcceptMultiHash = 0x10, AcceptAll = 0x08, AcceptBroadcast = 0x04,
  AcceptMulticast = 0x02, AcceptMyPhys, AcceptErr = 0x80, AcceptRunt = 0x40,
  AcceptBroadcast = 0x20, AcceptMulticast = 0x10, AcceptAllPhys = 0x08, AcceptMyPhys = 0x02
}
enum  mac_ctrl0_bits { EnbFullDuplex = 0x20, EnbRcvLargeFrame = 0x40, EnbFlowCtrl = 0x100, EnbPassRxCRC = 0x200 }
enum  mac_ctrl1_bits {
  StatsEnable = 0x0020, StatsDisable = 0x0040, StatsEnabled = 0x0080, TxEnable = 0x0100,
  TxDisable = 0x0200, TxEnabled = 0x0400, RxEnable = 0x0800, RxDisable = 0x1000,
  RxEnabled = 0x2000
}
enum  desc_status_bits {
  DescOwn = 0x8000, DescEndPacket = 0x4000, DescEndRing = 0x2000, LastFrag = 0x80000000,
  DescIntrOnTx = 0x8000, DescIntrOnDMADone = 0x80000000, DisableAlign = 0x00000001, DescOwnded = 0x80000000,
  RxDescFatalErr = 0x8000, RxWholePkt = 0x0300, DescOwn = 0x80000000, DescEndRing = 0x02000000,
  DescUseLink = 0x01000000, DescWholePkt = 0x60000000, DescStartPkt = 0x20000000, DescEndPkt = 0x40000000,
  DescIntr = 0x80000000
}
enum  pci_id_flags_bits {
  PCI_USES_IO = 1, PCI_USES_MEM = 2, PCI_USES_MASTER = 4, PCI_ADDR0 = 0 << 4,
  PCI_ADDR1 = 1 << 4, PCI_ADDR2, PCI_ADDR3 = 3 << 4, PCI_USES_IO = 1,
  PCI_USES_MEM = 2, PCI_USES_MASTER = 4, PCI_ADDR0 = 0<<4, PCI_ADDR1 = 1<<4,
  PCI_ADDR2 = 2<<4, PCI_ADDR3 = 3<<4, PCI_ADDR_64BITS = 0x100, PCI_NO_ACPI_WAKE = 0x200,
  PCI_NO_MIN_LATENCY = 0x400, PCI_UNUSED_IRQ = 0x800
}
enum  chip_capability_flags { CanHaveMII = 1, KendinPktDropBug = 2, CanHaveMII = 1, HasBrokenTx = 2 }
enum  mii_reg_bits {
  MDIO_ShiftClk = 0x0001, MDIO_Data = 0x0002, MDIO_EnbOutput, MDIO_ShiftClk = 0x10000,
  MDIO_DataIn = 0x80000, MDIO_DataOut = 0x20000, MDIO_EnbOutput = 0x40000, MDIO_EnbIn = 0x00000
}

Functions

 FILE_LICENCE (GPL2_OR_LATER)
static int eeprom_read (long ioaddr, int location)
static int mdio_read (struct nic *nic, int phy_id, unsigned int location)
static void mdio_write (struct nic *nic, int phy_id, unsigned int location, int value)
static void set_rx_mode (struct nic *nic)
static void check_duplex (struct nic *nic)
static void init_ring (struct nic *nic __unused)
static void sundance_reset (struct nic *nic)
static void sundance_irq (struct nic *nic, irq_action_t action)
static int sundance_poll (struct nic *nic, int retrieve)
static void sundance_transmit (struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p)
static void sundance_disable (struct nic *nic __unused)
static int sundance_probe (struct nic *nic, struct pci_device *pci)
static void mdio_sync (long mdio_addr)
static int mdio_read (struct nic *nic __unused, int phy_id, unsigned int location)
static void mdio_write (struct nic *nic __unused, int phy_id, unsigned int location, int value)
static void set_rx_mode (struct nic *nic __unused)
 PCI_DRIVER (sundance_driver, sundance_nics, PCI_NO_CLASS)
 DRIVER ("SUNDANCE/PCI", nic_driver, pci_driver, sundance_driver, sundance_probe, sundance_disable)

Variables

static int mtu = 1514
static int rx_copybreak = 0
static int flowctrl = 1
static char media [] = "autosense"
static struct netdev_desc tx_ring [TX_RING_SIZE]
static struct netdev_desc rx_ring [RX_RING_SIZE]
struct {
   unsigned char   txb [PKT_BUF_SZ *TX_RING_SIZE]
   unsigned char   rxb [RX_RING_SIZE *PKT_BUF_SZ]
__shared
static u32 BASE
static struct sundance_private sdx
static struct sundance_privatesdc
static struct nic_operations sundance_operations
static struct pci_device_id sundance_nics []

Define Documentation

#define drv_version   "v1.12"

Definition at line 54 of file sundance.c.

#define drv_date   "2004-03-21"

Definition at line 55 of file sundance.c.

#define HZ   100

Definition at line 57 of file sundance.c.

Definition at line 60 of file sundance.c.

Referenced by init_ring(), sundance_reset(), and sundance_transmit().

Definition at line 61 of file sundance.c.

#define TX_RING_SIZE   2

Definition at line 92 of file sundance.c.

#define TX_QUEUE_LEN   10 /* Limit ring entries actually used. */

Definition at line 93 of file sundance.c.

#define RX_RING_SIZE   4

Definition at line 94 of file sundance.c.

Referenced by init_ring(), and sundance_poll().

#define TX_TIME_OUT   (4*HZ)

Definition at line 99 of file sundance.c.

Referenced by sundance_transmit().

#define PKT_BUF_SZ   1536

Definition at line 100 of file sundance.c.

Referenced by init_ring(), and sundance_poll().

#define rxb   rx_tx_buf.rxb

Definition at line 240 of file sundance.c.

#define txb   rx_tx_buf.txb

Definition at line 241 of file sundance.c.

#define EEPROM_SIZE   128

Definition at line 245 of file sundance.c.

Referenced by sundance_probe().

Definition at line 254 of file sundance.c.

#define MII_CNT   4

Definition at line 256 of file sundance.c.

Referenced by sundance_probe().

#define EEPROM_SA_OFFSET   0x10

Definition at line 280 of file sundance.c.

Referenced by sundance_probe().

#define DEFAULT_INTR
Value:
(IntrRxDMADone | IntrPCIErr | \
                        IntrDrvRqst | IntrTxDone | StatsMax | \
                        LinkChange)

Definition at line 281 of file sundance.c.

Referenced by sundance_irq(), and sundance_poll().

#define mdio_in (   mdio_addr)    inb(mdio_addr)

Definition at line 775 of file sundance.c.

Referenced by mdio_read().

#define mdio_out (   value,
  mdio_addr 
)    outb(value, mdio_addr)

Definition at line 776 of file sundance.c.

Referenced by mdio_read(), mdio_sync(), and mdio_write().

#define mdio_delay (   mdio_addr)    inb(mdio_addr)

Definition at line 777 of file sundance.c.

Referenced by mdio_read(), mdio_sync(), and mdio_write().

#define MDIO_EnbIn   (0)

Definition at line 783 of file sundance.c.

Referenced by mdio_read(), and mdio_write().

#define MDIO_WRITE0   (MDIO_EnbOutput)

Definition at line 784 of file sundance.c.

Referenced by mdio_read(), and mdio_write().

Definition at line 785 of file sundance.c.

Referenced by mdio_read(), mdio_sync(), and mdio_write().


Enumeration Type Documentation

Enumerator:
DMACtrl 
TxListPtr 
TxDMABurstThresh 
TxDMAUrgentThresh 
TxDMAPollPeriod 
RxDMAStatus 
RxListPtr 
DebugCtrl0 
DebugCtrl1 
RxDMABurstThresh 
RxDMAUrgentThresh 
RxDMAPollPeriod 
LEDCtrl 
ASICCtrl 
EEData 
EECtrl 
TxStartThresh 
RxEarlyThresh 
FlashAddr 
FlashData 
TxStatus 
TxFrameId 
DownCounter 
IntrClear 
IntrEnable 
IntrStatus 
MACCtrl0 
MACCtrl1 
StationAddr 
MaxFrameSize 
RxMode 
MIICtrl 
MulticastFilter0 
MulticastFilter1 
RxOctetsLow 
RxOctetsHigh 
TxOctetsLow 
TxOctetsHigh 
TxFramesOK 
RxFramesOK 
StatsCarrierError 
StatsLateColl 
StatsMultiColl 
StatsOneColl 
StatsTxDefer 
RxMissed 
StatsTxXSDefer 
StatsTxAbort 
StatsBcastTx 
StatsBcastRx 
StatsMcastTx 
StatsMcastRx 
RxStatus 

Definition at line 110 of file sundance.c.

                  {
        DMACtrl = 0x00,
        TxListPtr = 0x04,
        TxDMABurstThresh = 0x08,
        TxDMAUrgentThresh = 0x09,
        TxDMAPollPeriod = 0x0a,
        RxDMAStatus = 0x0c,
        RxListPtr = 0x10,
        DebugCtrl0 = 0x1a,
        DebugCtrl1 = 0x1c,
        RxDMABurstThresh = 0x14,
        RxDMAUrgentThresh = 0x15,
        RxDMAPollPeriod = 0x16,
        LEDCtrl = 0x1a,
        ASICCtrl = 0x30,
        EEData = 0x34,
        EECtrl = 0x36,
        TxStartThresh = 0x3c,
        RxEarlyThresh = 0x3e,
        FlashAddr = 0x40,
        FlashData = 0x44,
        TxStatus = 0x46,
        TxFrameId = 0x47,
        DownCounter = 0x18,
        IntrClear = 0x4a,
        IntrEnable = 0x4c,
        IntrStatus = 0x4e,
        MACCtrl0 = 0x50,
        MACCtrl1 = 0x52,
        StationAddr = 0x54,
        MaxFrameSize = 0x5A,
        RxMode = 0x5c,
        MIICtrl = 0x5e,
        MulticastFilter0 = 0x60,
        MulticastFilter1 = 0x64,
        RxOctetsLow = 0x68,
        RxOctetsHigh = 0x6a,
        TxOctetsLow = 0x6c,
        TxOctetsHigh = 0x6e,
        TxFramesOK = 0x70,
        RxFramesOK = 0x72,
        StatsCarrierError = 0x74,
        StatsLateColl = 0x75,
        StatsMultiColl = 0x76,
        StatsOneColl = 0x77,
        StatsTxDefer = 0x78,
        RxMissed = 0x79,
        StatsTxXSDefer = 0x7a,
        StatsTxAbort = 0x7b,
        StatsBcastTx = 0x7c,
        StatsBcastRx = 0x7d,
        StatsMcastTx = 0x7e,
        StatsMcastRx = 0x7f,
        /* Aliased and bogus values! */
        RxStatus = 0x0c,
};
Enumerator:
GlobalReset 
RxReset 
TxReset 
DMAReset 
FIFOReset 
NetworkReset 
HostReset 
ResetBusy 

Definition at line 166 of file sundance.c.

                         {
        GlobalReset = 0x0001,
        RxReset = 0x0002,
        TxReset = 0x0004,
        DMAReset = 0x0008,
        FIFOReset = 0x0010,
        NetworkReset = 0x0020,
        HostReset = 0x0040,
        ResetBusy = 0x0400,
};
Enumerator:
IntrSummary 
IntrPCIErr 
IntrMACCtrl 
IntrTxDone 
IntrRxDone 
IntrRxStart 
IntrDrvRqst 
StatsMax 
LinkChange 
IntrTxDMADone 
IntrRxDMADone 
NormalIntr 
AbnormalIntr 
IntrPCIErr 
TimerInt 
IntrRxDied 
RxNoBuf 
IntrRxDone 
TxFIFOUnderflow 
RxErrIntr 
TxIdle 
IntrTxStopped 
IntrTxDone 

Definition at line 178 of file sundance.c.

                      {
        IntrSummary = 0x0001, IntrPCIErr = 0x0002, IntrMACCtrl = 0x0008,
        IntrTxDone = 0x0004, IntrRxDone = 0x0010, IntrRxStart = 0x0020,
        IntrDrvRqst = 0x0040,
        StatsMax = 0x0080, LinkChange = 0x0100,
        IntrTxDMADone = 0x0200, IntrRxDMADone = 0x0400,
};
Enumerator:
AcceptAllIPMulti 
AcceptMultiHash 
AcceptAll 
AcceptBroadcast 
AcceptMulticast 
AcceptMyPhys 
AcceptErr 
AcceptRunt 
AcceptBroadcast 
AcceptMulticast 
AcceptAllPhys 
AcceptMyPhys 

Definition at line 187 of file sundance.c.

                  {
        AcceptAllIPMulti = 0x20, AcceptMultiHash = 0x10, AcceptAll = 0x08,
        AcceptBroadcast = 0x04, AcceptMulticast = 0x02, AcceptMyPhys =
            0x01,
};
Enumerator:
EnbFullDuplex 
EnbRcvLargeFrame 
EnbFlowCtrl 
EnbPassRxCRC 

Definition at line 193 of file sundance.c.

                    {
        EnbFullDuplex = 0x20, EnbRcvLargeFrame = 0x40,
        EnbFlowCtrl = 0x100, EnbPassRxCRC = 0x200,
};
Enumerator:
StatsEnable 
StatsDisable 
StatsEnabled 
TxEnable 
TxDisable 
TxEnabled 
RxEnable 
RxDisable 
RxEnabled 

Definition at line 197 of file sundance.c.

                    {
        StatsEnable = 0x0020, StatsDisable = 0x0040, StatsEnabled = 0x0080,
        TxEnable = 0x0100, TxDisable = 0x0200, TxEnabled = 0x0400,
        RxEnable = 0x0800, RxDisable = 0x1000, RxEnabled = 0x2000,
};
Enumerator:
DescOwn 
DescEndPacket 
DescEndRing 
LastFrag 
DescIntrOnTx 
DescIntrOnDMADone 
DisableAlign 
DescOwnded 
RxDescFatalErr 
RxWholePkt 
DescOwn 
DescEndRing 
DescUseLink 
DescWholePkt 
DescStartPkt 
DescEndPkt 
DescIntr 

Definition at line 215 of file sundance.c.

                      {
        DescOwn = 0x8000,
        DescEndPacket = 0x4000,
        DescEndRing = 0x2000,
        LastFrag = 0x80000000,
        DescIntrOnTx = 0x8000,
        DescIntrOnDMADone = 0x80000000,
        DisableAlign = 0x00000001,
};
Enumerator:
PCI_USES_IO 
PCI_USES_MEM 
PCI_USES_MASTER 
PCI_ADDR0 
PCI_ADDR1 
PCI_ADDR2 
PCI_ADDR3 
PCI_USES_IO 
PCI_USES_MEM 
PCI_USES_MASTER 
PCI_ADDR0 
PCI_ADDR1 
PCI_ADDR2 
PCI_ADDR3 
PCI_ADDR_64BITS 
PCI_NO_ACPI_WAKE 
PCI_NO_MIN_LATENCY 
PCI_UNUSED_IRQ 

Definition at line 247 of file sundance.c.

                       {
        PCI_USES_IO = 1, PCI_USES_MEM = 2, PCI_USES_MASTER = 4,
        PCI_ADDR0 = 0 << 4, PCI_ADDR1 = 1 << 4, PCI_ADDR2 =
            2 << 4, PCI_ADDR3 = 3 << 4,
};
Enumerator:
CanHaveMII 
KendinPktDropBug 
CanHaveMII 
HasBrokenTx 

Definition at line 253 of file sundance.c.

Enumerator:
MDIO_ShiftClk 
MDIO_Data 
MDIO_EnbOutput 
MDIO_ShiftClk 
MDIO_DataIn 
MDIO_DataOut 
MDIO_EnbOutput 
MDIO_EnbIn 

Definition at line 779 of file sundance.c.

                  {
        MDIO_ShiftClk = 0x0001, MDIO_Data = 0x0002, MDIO_EnbOutput =
            0x0004,
};

Function Documentation

FILE_LICENCE ( GPL2_OR_LATER  )
static int eeprom_read ( long  ioaddr,
int  location 
) [static]

Definition at line 752 of file sundance.c.

References EECtrl, EEData, inw(), and outw().

Referenced by sundance_probe().

{
        int boguscnt = 10000;   /* Typical 1900 ticks */
        outw(0x0200 | (location & 0xff), ioaddr + EECtrl);
        do {
                if (!(inw(ioaddr + EECtrl) & 0x8000)) {
                        return inw(ioaddr + EEData);
                }
        }
        while (--boguscnt > 0);
        return 0;
}
static int mdio_read ( struct nic nic,
int  phy_id,
unsigned int  location 
) [static]
static void mdio_write ( struct nic nic,
int  phy_id,
unsigned int  location,
int  value 
) [static]
static void set_rx_mode ( struct nic nic) [static]
static void check_duplex ( struct nic nic) [static]

Definition at line 291 of file sundance.c.

References mii_if_info::advertising, sundance_private::an_enable, BASE, DBG, EnbFullDuplex, mii_if_info::full_duplex, inw(), MACCtrl0, mdio_read(), sundance_private::mii_if, MII_LPA, sundance_private::nic_name, outw(), and sundance_private::phys.

Referenced by sundance_probe().

{
        int mii_lpa = mdio_read(nic, sdc->phys[0], MII_LPA);
        int negotiated = mii_lpa & sdc->mii_if.advertising;
        int duplex;

        /* Force media */
        if (!sdc->an_enable || mii_lpa == 0xffff) {
                if (sdc->mii_if.full_duplex)
                        outw(inw(BASE + MACCtrl0) | EnbFullDuplex,
                             BASE + MACCtrl0);
                return;
        }

        /* Autonegotiation */
        duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
        if (sdc->mii_if.full_duplex != duplex) {
                sdc->mii_if.full_duplex = duplex;
                DBG ("%s: Setting %s-duplex based on MII #%d "
                         "negotiated capability %4.4x.\n", sdc->nic_name,
                         duplex ? "full" : "half", sdc->phys[0],
                         negotiated );
                outw(inw(BASE + MACCtrl0) | duplex ? 0x20 : 0,
                     BASE + MACCtrl0);
        }
}
static void init_ring ( struct nic *nic  __unused) [static]

Definition at line 322 of file sundance.c.

References cpu_to_le32, sundance_private::cur_rx, LastFrag, PKT_BUF_SZ, rx_ring, RX_RING_SIZE, rxb, tx_ring, txb, virt_to_bus(), and virt_to_le32desc.

Referenced by sundance_reset().

{
        int i;

        sdc->cur_rx = 0;

        /* Initialize all the Rx descriptors */
        for (i = 0; i < RX_RING_SIZE; i++) {
                rx_ring[i].next_desc = virt_to_le32desc(&rx_ring[i + 1]);
                rx_ring[i].status = 0;
                rx_ring[i].length = 0;
                rx_ring[i].addr = 0;
        }

        /* Mark the last entry as wrapping the ring */
        rx_ring[i - 1].next_desc = virt_to_le32desc(&rx_ring[0]);

        for (i = 0; i < RX_RING_SIZE; i++) {
                rx_ring[i].addr = virt_to_le32desc(&rxb[i * PKT_BUF_SZ]);
                rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ | LastFrag);
        }

        /* We only use one transmit buffer, but two
         * descriptors so transmit engines have somewhere
         * to point should they feel the need */
        tx_ring[0].status = 0x00000000;
        tx_ring[0].addr = virt_to_bus(&txb[0]);
        tx_ring[0].next_desc = 0;       /* virt_to_bus(&tx_ring[1]); */

        /* This descriptor is never used */
        tx_ring[1].status = 0x00000000;
        tx_ring[1].addr = 0;    /*virt_to_bus(&txb[0]); */
        tx_ring[1].next_desc = 0;

        /* Mark the last entry as wrapping the ring,
         * though this should never happen */
        tx_ring[1].length = cpu_to_le32(LastFrag | PKT_BUF_SZ);
}
static void sundance_reset ( struct nic nic) [static]

Definition at line 364 of file sundance.c.

References ASICCtrl, BASE, DBG, DebugCtrl1, DownCounter, init_ring(), inl(), inw(), MACCtrl0, MACCtrl1, MaxFrameSize, sundance_private::mtu, sundance_private::nic_name, outb(), outl(), outw(), sundance_private::pci_rev_id, rx_ring, RxDMAPollPeriod, RxEnable, RxListPtr, RxStatus, set_rx_mode(), StationAddr, txb, TxEnable, TxStatus, virt_to_le32desc, and writeb().

Referenced by sundance_probe().

{
        int i;

        init_ring(nic);

        outl(virt_to_le32desc(&rx_ring[0]), BASE + RxListPtr);
        /* The Tx List Pointer is written as packets are queued */

        /* Initialize other registers. */
        /* __set_mac_addr(dev); */
        {
                u16 addr16;

                addr16 = (nic->node_addr[0] | (nic->node_addr[1] << 8));
                outw(addr16, BASE + StationAddr);
                addr16 = (nic->node_addr[2] | (nic->node_addr[3] << 8));
                outw(addr16, BASE + StationAddr + 2);
                addr16 = (nic->node_addr[4] | (nic->node_addr[5] << 8));
                outw(addr16, BASE + StationAddr + 4);
        }

        outw(sdc->mtu + 14, BASE + MaxFrameSize);
        if (sdc->mtu > 2047)    /* this will never happen with default options */
                outl(inl(BASE + ASICCtrl) | 0x0c, BASE + ASICCtrl);

        set_rx_mode(nic);

        outw(0, BASE + DownCounter);
        /* Set the chip to poll every N*30nsec */
        outb(100, BASE + RxDMAPollPeriod);

        /* Fix DFE-580TX packet drop issue */
        if (sdc->pci_rev_id >= 0x14)
                writeb(0x01, BASE + DebugCtrl1);

        outw(RxEnable | TxEnable, BASE + MACCtrl1);

        /* Construct a perfect filter frame with the mac address as first match
         * and broadcast for all others */
        for (i = 0; i < 192; i++)
                txb[i] = 0xFF;

        txb[0] = nic->node_addr[0];
        txb[1] = nic->node_addr[1];
        txb[2] = nic->node_addr[2];
        txb[3] = nic->node_addr[3];
        txb[4] = nic->node_addr[4];
        txb[5] = nic->node_addr[5];

        DBG ( "%s: Done sundance_reset, status: Rx %hX Tx %hX "
              "MAC Control %hX, %hX %hX\n",
              sdc->nic_name, (int) inl(BASE + RxStatus),
              (int) inw(BASE + TxStatus), (int) inl(BASE + MACCtrl0),
              (int) inw(BASE + MACCtrl1), (int) inw(BASE + MACCtrl0) );
}
static void sundance_irq ( struct nic nic,
irq_action_t  action 
) [static]

Definition at line 424 of file sundance.c.

References ASICCtrl, BASE, DEFAULT_INTR, IntrEnable, IntrStatus, inw(), and outw().

                                                                  {
        unsigned int intr_status;

        switch ( action ) {
        case DISABLE :
        case ENABLE :
                intr_status = inw(nic->ioaddr + IntrStatus);
                intr_status = intr_status & ~DEFAULT_INTR;
                if ( action == ENABLE ) 
                        intr_status = intr_status | DEFAULT_INTR;
                outw(intr_status, nic->ioaddr + IntrEnable);
                break;
        case FORCE :
                outw(0x0200, BASE + ASICCtrl);
                break;
        }
}
static int sundance_poll ( struct nic nic,
int  retrieve 
) [static]

Definition at line 444 of file sundance.c.

References cpu_to_le32, sundance_private::cur_rx, DBG, DEFAULT_INTR, DescOwn, entry, IntrRxDMADone, IntrRxDone, IntrStatus, inw(), LastFrag, le32_to_cpu, memcpy(), outw(), PKT_BUF_SZ, printf(), rx_copybreak, rx_ring, RX_RING_SIZE, rxb, and status.

{
        /* return true if there's an ethernet packet ready to read */
        /* nic->packet should contain data on return */
        /* nic->packetlen should contain length of data */
        int entry = sdc->cur_rx % RX_RING_SIZE;
        u32 frame_status = le32_to_cpu(rx_ring[entry].status);
        int intr_status;
        int pkt_len = 0;

        if (!(frame_status & DescOwn))
                return 0;

        /* There is a packet ready */
        if(!retrieve)
                return 1;

        intr_status = inw(nic->ioaddr + IntrStatus);
        outw(intr_status, nic->ioaddr + IntrStatus);

        pkt_len = frame_status & 0x1fff;

        if (frame_status & 0x001f4000) {
                DBG ( "Polling frame_status error\n" ); /* Do we really care about this */
        } else {
                if (pkt_len < rx_copybreak) {
                        /* FIXME: What should happen Will this ever occur */
                        printf("Poll Error: pkt_len < rx_copybreak");
                } else {
                        nic->packetlen = pkt_len;
                        memcpy(nic->packet, rxb +
                               (sdc->cur_rx * PKT_BUF_SZ), nic->packetlen);

                }
        }
        rx_ring[entry].length = cpu_to_le32(PKT_BUF_SZ | LastFrag);
        rx_ring[entry].status = 0;
        entry++;
        sdc->cur_rx = entry % RX_RING_SIZE;
        outw(DEFAULT_INTR & ~(IntrRxDone|IntrRxDMADone), 
                nic->ioaddr + IntrStatus);
        return 1;
}
static void sundance_transmit ( struct nic nic,
const char *  d,
unsigned int  t,
unsigned int  s,
const char *  p 
) [static]

Definition at line 491 of file sundance.c.

References BASE, cpu_to_le32, currticks(), ETH_ALEN, ETH_HLEN, ETH_ZLEN, htons, LastFrag, MACCtrl1, memcpy(), outl(), outw(), printf(), status, tx_ring, TX_TIME_OUT, txb, TxDisable, TxEnable, TxListPtr, TxStatus, and virt_to_le32desc.

{                               /* Packet */
        u16 nstype;
        u32 to;

        /* Disable the Tx */
        outw(TxDisable, BASE + MACCtrl1);

        memcpy(txb, d, ETH_ALEN);
        memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);
        nstype = htons((u16) t);
        memcpy(txb + 2 * ETH_ALEN, (u8 *) & nstype, 2);
        memcpy(txb + ETH_HLEN, p, s);

        s += ETH_HLEN;
        s &= 0x0FFF;
        while (s < ETH_ZLEN)
                txb[s++] = '\0';

        /* Setup the transmit descriptor */
        tx_ring[0].length = cpu_to_le32(s | LastFrag);
        tx_ring[0].status = cpu_to_le32(0x00000001);

        /* Point to transmit descriptor */
        outl(virt_to_le32desc(&tx_ring[0]), BASE + TxListPtr);

        /* Enable Tx */
        outw(TxEnable, BASE + MACCtrl1);
        /* Trigger an immediate send */
        outw(0, BASE + TxStatus);

        to = currticks() + TX_TIME_OUT;
        while (!(tx_ring[0].status & 0x00010000) && (currticks() < to));        /* wait */

        if (currticks() >= to) {
                printf("TX Time Out");
        }
        /* Disable Tx */
        outw(TxDisable, BASE + MACCtrl1);

}
static void sundance_disable ( struct nic *nic  __unused) [static]

Definition at line 539 of file sundance.c.

References BASE, IntrEnable, MACCtrl1, outw(), RxDisable, StatsDisable, and TxDisable.

                                                          {
        /* put the card in its initial state */
        /* This function serves 3 purposes.
         * This disables DMA and interrupts so we don't receive
         *  unexpected packets or interrupts from the card after
         *  etherboot has finished.
         * This frees resources so etherboot may use
         *  this driver on another interface
         * This allows etherboot to reinitialize the interface
         *  if something is something goes wrong.
         */
        outw(0x0000, BASE + IntrEnable);
        /* Stop the Chipchips Tx and Rx Status */
        outw(TxDisable | RxDisable | StatsDisable, BASE + MACCtrl1);
}
static int sundance_probe ( struct nic nic,
struct pci_device pci 
) [static]

Definition at line 566 of file sundance.c.

References adjust_pci_device(), ADVERTISE_100FULL, ADVERTISE_100HALF, ADVERTISE_10FULL, ADVERTISE_10HALF, mii_if_info::advertising, sundance_private::an_enable, ASICCtrl, BASE, BMCR_FULLDPLX, BMCR_SPEED100, check_duplex(), DBG, pci_device::device, ee_data, eeprom_read(), EEPROM_SA_OFFSET, EEPROM_SIZE, EnbFlowCtrl, ETH_ALEN, flowctrl, sundance_private::flowctrl, mii_if_info::full_duplex, pci_device::id, inl(), inw(), pci_device::ioaddr, pci_device::irq, le16_to_cpu, MACCtrl0, mdio_read(), mdio_write(), media, MII_ADVERTISE, MII_BMCR, MII_BMSR, MII_CNT, sundance_private::mii_if, MII_LPA, sundance_private::mii_preamble_required, mtu, sundance_private::mtu, MulticastFilter1, pci_device_id::name, sundance_private::nic_name, outw(), pci_read_config_byte(), sundance_private::pci_rev_id, PCI_REVISION, phy, mii_if_info::phy_id, sundance_private::phys, printf(), ResetBusy, sdx, sundance_private::speed, speed, strcasecmp(), sundance_operations, sundance_reset(), udelay(), and pci_device::vendor.

                                                                      {

        u8 ee_data[EEPROM_SIZE];
        u16 mii_ctl;
        int i;
        int speed;

        if (pci->ioaddr == 0)
                return 0;

        /* BASE is used throughout to address the card */
        BASE = pci->ioaddr;
        printf(" sundance.c: Found %s Vendor=0x%hX Device=0x%hX\n",
               pci->id->name, pci->vendor, pci->device);

        /* Get the MAC Address by reading the EEPROM */
        for (i = 0; i < 3; i++) {
                ((u16 *) ee_data)[i] =
                    le16_to_cpu(eeprom_read(BASE, i + EEPROM_SA_OFFSET));
        }
        /* Update the nic structure with the MAC Address */
        for (i = 0; i < ETH_ALEN; i++) {
                nic->node_addr[i] = ee_data[i];
        }

        /* Set the card as PCI Bus Master */
        adjust_pci_device(pci);

//      sdc->mii_if.dev = pci;
//      sdc->mii_if.phy_id_mask = 0x1f;
//      sdc->mii_if.reg_num_mask = 0x1f;

        /* point to private storage */
        sdc = &sdx;

        sdc->nic_name = pci->id->name;
        sdc->mtu = mtu;

        pci_read_config_byte(pci, PCI_REVISION, &sdc->pci_rev_id);

        DBG ( "Device revision id: %hx\n", sdc->pci_rev_id );

        /* Print out some hardware info */
        DBG ( "%s: %s at ioaddr %hX, ",
              pci->id->name, nic->node_addr, (unsigned int) BASE);

        sdc->mii_preamble_required = 0;
        if (1) {
                int phy, phy_idx = 0;
                sdc->phys[0] = 1;       /* Default Setting */
                sdc->mii_preamble_required++;
                for (phy = 1; phy < 32 && phy_idx < MII_CNT; phy++) {
                        int mii_status = mdio_read(nic, phy, MII_BMSR);
                        if (mii_status != 0xffff && mii_status != 0x0000) {
                                sdc->phys[phy_idx++] = phy;
                                sdc->mii_if.advertising =
                                    mdio_read(nic, phy, MII_ADVERTISE);
                                if ((mii_status & 0x0040) == 0)
                                        sdc->mii_preamble_required++;
                                DBG 
                                    ( "%s: MII PHY found at address %d, status " "%hX advertising %hX\n", sdc->nic_name, phy, mii_status, sdc->mii_if.advertising );
                        }
                }
                sdc->mii_preamble_required--;
                if (phy_idx == 0)
                        printf("%s: No MII transceiver found!\n",
                               sdc->nic_name);
                sdc->mii_if.phy_id = sdc->phys[0];
        }

        /* Parse override configuration */
        sdc->an_enable = 1;
        if (strcasecmp(media, "autosense") != 0) {
                sdc->an_enable = 0;
                if (strcasecmp(media, "100mbps_fd") == 0 ||
                    strcasecmp(media, "4") == 0) {
                        sdc->speed = 100;
                        sdc->mii_if.full_duplex = 1;
                } else if (strcasecmp(media, "100mbps_hd") == 0
                           || strcasecmp(media, "3") == 0) {
                        sdc->speed = 100;
                        sdc->mii_if.full_duplex = 0;
                } else if (strcasecmp(media, "10mbps_fd") == 0 ||
                           strcasecmp(media, "2") == 0) {
                        sdc->speed = 10;
                        sdc->mii_if.full_duplex = 1;
                } else if (strcasecmp(media, "10mbps_hd") == 0 ||
                           strcasecmp(media, "1") == 0) {
                        sdc->speed = 10;
                        sdc->mii_if.full_duplex = 0;
                } else {
                        sdc->an_enable = 1;
                }
        }
        if (flowctrl == 1)
                sdc->flowctrl = 1;

        /* Fibre PHY? */
        if (inl(BASE + ASICCtrl) & 0x80) {
                /* Default 100Mbps Full */
                if (sdc->an_enable) {
                        sdc->speed = 100;
                        sdc->mii_if.full_duplex = 1;
                        sdc->an_enable = 0;
                }
        }

        /* The Linux driver uses flow control and resets the link here.  This means the
           mii section from above would need to be re done I believe.  Since it serves
           no real purpose leave it out. */

        /* Force media type */
        if (!sdc->an_enable) {
                mii_ctl = 0;
                mii_ctl |= (sdc->speed == 100) ? BMCR_SPEED100 : 0;
                mii_ctl |= (sdc->mii_if.full_duplex) ? BMCR_FULLDPLX : 0;
                mdio_write(nic, sdc->phys[0], MII_BMCR, mii_ctl);
                printf("Override speed=%d, %s duplex\n",
                       sdc->speed,
                       sdc->mii_if.full_duplex ? "Full" : "Half");
        }

        /* Reset the chip to erase previous misconfiguration */
        DBG ( "ASIC Control is %#x\n", inl(BASE + ASICCtrl) );
        outw(0x007f, BASE + ASICCtrl + 2);

        /*
        * wait for reset to complete
        * this is heavily inspired by the linux sundance driver
        * according to the linux driver it can take up to 1ms for the reset
        * to complete
        */
        i = 0;
        while(inl(BASE + ASICCtrl) & (ResetBusy << 16)) {
                if(i++ >= 10) {
                        DBG("sundance: NIC reset did not complete.\n");
                        break;
                }
                udelay(100);
        }

        DBG ( "ASIC Control is now %#x.\n", inl(BASE + ASICCtrl) );

        sundance_reset(nic);
        if (sdc->an_enable) {
                u16 mii_advertise, mii_lpa;
                mii_advertise =
                    mdio_read(nic, sdc->phys[0], MII_ADVERTISE);
                mii_lpa = mdio_read(nic, sdc->phys[0], MII_LPA);
                mii_advertise &= mii_lpa;
                if (mii_advertise & ADVERTISE_100FULL)
                        sdc->speed = 100;
                else if (mii_advertise & ADVERTISE_100HALF)
                        sdc->speed = 100;
                else if (mii_advertise & ADVERTISE_10FULL)
                        sdc->speed = 10;
                else if (mii_advertise & ADVERTISE_10HALF)
                        sdc->speed = 10;
        } else {
                mii_ctl = mdio_read(nic, sdc->phys[0], MII_BMCR);
                speed = (mii_ctl & BMCR_SPEED100) ? 100 : 10;
                sdc->speed = speed;
                printf("%s: Link changed: %dMbps ,", sdc->nic_name, speed);
                printf("%s duplex.\n", (mii_ctl & BMCR_FULLDPLX) ?
                       "full" : "half");
        }
        check_duplex(nic);
        if (sdc->flowctrl && sdc->mii_if.full_duplex) {
                outw(inw(BASE + MulticastFilter1 + 2) | 0x0200,
                     BASE + MulticastFilter1 + 2);
                outw(inw(BASE + MACCtrl0) | EnbFlowCtrl, BASE + MACCtrl0);
        }
        printf("%dMbps, %s-Duplex\n", sdc->speed,
               sdc->mii_if.full_duplex ? "Full" : "Half");

        /* point to NIC specific routines */
        nic->nic_op     = &sundance_operations;

        nic->irqno  = pci->irq;
        nic->ioaddr = BASE;

        return 1;
}
static void mdio_sync ( long  mdio_addr) [static]

Definition at line 789 of file sundance.c.

References mdio_delay, mdio_out, MDIO_ShiftClk, and MDIO_WRITE1.

Referenced by mdio_read(), and mdio_write().

{
        int bits = 32;

        /* Establish sync by sending at least 32 logic ones. */
        while (--bits >= 0) {
                mdio_out(MDIO_WRITE1, mdio_addr);
                mdio_delay(mdio_addr);
                mdio_out(MDIO_WRITE1 | MDIO_ShiftClk, mdio_addr);
                mdio_delay(mdio_addr);
        }
}
static int mdio_read ( struct nic *nic  __unused,
int  phy_id,
unsigned int  location 
) [static]

Definition at line 803 of file sundance.c.

References BASE, MDIO_Data, mdio_delay, MDIO_EnbIn, mdio_in, mdio_out, MDIO_ShiftClk, mdio_sync(), MDIO_WRITE0, MDIO_WRITE1, sundance_private::mii_preamble_required, and MIICtrl.

{
        long mdio_addr = BASE + MIICtrl;
        int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
        int i, retval = 0;

        if (sdc->mii_preamble_required)
                mdio_sync(mdio_addr);

        /* Shift the read command bits out. */
        for (i = 15; i >= 0; i--) {
                int dataval =
                    (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;

                mdio_out(dataval, mdio_addr);
                mdio_delay(mdio_addr);
                mdio_out(dataval | MDIO_ShiftClk, mdio_addr);
                mdio_delay(mdio_addr);
        }
        /* Read the two transition, 16 data, and wire-idle bits. */
        for (i = 19; i > 0; i--) {
                mdio_out(MDIO_EnbIn, mdio_addr);
                mdio_delay(mdio_addr);
                retval = (retval << 1) | ((mdio_in(mdio_addr) & MDIO_Data)
                                          ? 1 : 0);
                mdio_out(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
                mdio_delay(mdio_addr);
        }
        return (retval >> 1) & 0xffff;
}
static void mdio_write ( struct nic *nic  __unused,
int  phy_id,
unsigned int  location,
int  value 
) [static]

Definition at line 835 of file sundance.c.

References BASE, mdio_delay, MDIO_EnbIn, mdio_out, MDIO_ShiftClk, mdio_sync(), MDIO_WRITE0, MDIO_WRITE1, sundance_private::mii_preamble_required, and MIICtrl.

{
        long mdio_addr = BASE + MIICtrl;
        int mii_cmd =
            (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
        int i;

        if (sdc->mii_preamble_required)
                mdio_sync(mdio_addr);

        /* Shift the command bits out. */
        for (i = 31; i >= 0; i--) {
                int dataval =
                    (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
                mdio_out(dataval, mdio_addr);
                mdio_delay(mdio_addr);
                mdio_out(dataval | MDIO_ShiftClk, mdio_addr);
                mdio_delay(mdio_addr);
        }
        /* Clear out extra bits. */
        for (i = 2; i > 0; i--) {
                mdio_out(MDIO_EnbIn, mdio_addr);
                mdio_delay(mdio_addr);
                mdio_out(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
                mdio_delay(mdio_addr);
        }
        return;
}
static void set_rx_mode ( struct nic *nic  __unused) [static]

Definition at line 865 of file sundance.c.

References AcceptBroadcast, AcceptMulticast, AcceptMyPhys, BASE, sundance_private::flowctrl, mii_if_info::full_duplex, memset(), sundance_private::mii_if, MulticastFilter0, outb(), outw(), and RxMode.

{
        int i;
        u16 mc_filter[4];       /* Multicast hash filter */
        u32 rx_mode;

        memset(mc_filter, 0xff, sizeof(mc_filter));
        rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;

        if (sdc->mii_if.full_duplex && sdc->flowctrl)
                mc_filter[3] |= 0x0200;
        for (i = 0; i < 4; i++)
                outw(mc_filter[i], BASE + MulticastFilter0 + i * 2);
        outb(rx_mode, BASE + RxMode);
        return;
}
PCI_DRIVER ( sundance_driver  ,
sundance_nics  ,
PCI_NO_CLASS   
)
DRIVER ( "SUNDANCE/PCI"  ,
nic_driver  ,
pci_driver  ,
sundance_driver  ,
sundance_probe  ,
sundance_disable   
)

Variable Documentation

int mtu = 1514 [static]

Definition at line 64 of file sundance.c.

int rx_copybreak = 0 [static]

Definition at line 74 of file sundance.c.

Referenced by sundance_poll().

int flowctrl = 1 [static]
char media[] = "autosense" [static]

Definition at line 85 of file sundance.c.

Referenced by parse_eeprom(), pcnet32_chip_detect(), smc9000_probe(), and sundance_probe().

struct netdev_desc tx_ring[TX_RING_SIZE] [static]

Definition at line 229 of file sundance.c.

struct netdev_desc rx_ring[RX_RING_SIZE] [static]

Definition at line 232 of file sundance.c.

unsigned char txb[PKT_BUF_SZ *TX_RING_SIZE]

Definition at line 237 of file sundance.c.

unsigned char rxb[RX_RING_SIZE *PKT_BUF_SZ]

Definition at line 238 of file sundance.c.

struct { ... } __shared
u32 BASE [static]
struct sundance_private sdx [static]

Referenced by sundance_probe().

struct sundance_private* sdc [static]

Definition at line 277 of file sundance.c.

struct nic_operations sundance_operations [static]
Initial value:
 {
        .connect        = dummy_connect,
        .poll           = sundance_poll,
        .transmit       = sundance_transmit,
        .irq            = sundance_irq,

}

Definition at line 555 of file sundance.c.

Referenced by sundance_probe().

struct pci_device_id sundance_nics[] [static]
Initial value:
 {
        PCI_ROM(0x13f0, 0x0201, "sundance", "ST201 Sundance 'Alta' based Adaptor", 0),
        PCI_ROM(0x1186, 0x1002, "dfe530txs", "D-Link DFE530TXS (Sundance ST201 Alta)", 0),
        PCI_ROM(0x13f0, 0x0200, "ip100a", "IC+ IP100A", 0),
}

Definition at line 882 of file sundance.c.