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

Go to the source code of this file.

Data Structures

struct  epic_rx_desc
struct  epic_tx_desc

Defines

#define LINUX_OUT_MACROS
#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 /* use at least 2 buffers for TX */
#define RX_RING_SIZE   2
#define PKT_BUF_SZ   1536 /* Size of each temporary Tx/Rx buffer.*/
#define EPIC_DEBUG   0 /* debug level */
#define TD_STDFLAGS   TD_LASTDESC
#define delay(nanosec)
#define rx_ring   epic100_bufs.rx_ring
#define tx_ring   epic100_bufs.tx_ring
#define rx_packet   epic100_bufs.rx_packet
#define tx_packet   epic100_bufs.tx_packet
#define MII_READOP   1
#define MII_WRITEOP   2

Functions

 FILE_LICENCE (GPL2_OR_LATER)
static void epic100_open (void)
static void epic100_init_ring (void)
static void epic100_disable (struct nic *nic)
static int epic100_poll (struct nic *nic, int retrieve)
static void epic100_transmit (struct nic *nic, const char *destaddr, unsigned int type, unsigned int len, const char *data)
static int mii_read (int phy_id, int location)
static void epic100_irq (struct nic *nic, irq_action_t action)
static int epic100_probe (struct nic *nic, struct pci_device *pci)
static void set_rx_mode (void)
static void epic100_disable (struct nic *nic __unused)
static void epic100_irq (struct nic *nic __unused, irq_action_t action __unused)
 PCI_DRIVER (epic100_driver, epic100_nics, PCI_NO_CLASS)
 DRIVER ("EPIC100", nic_driver, pci_driver, epic100_driver, epic100_probe, epic100_disable)

Variables

static struct nic_operations epic100_operations
static int ioaddr
static int command
static int intstat
static int intmask
static int genctl
static int eectl
static int test
static int mmctl
static int mmdata
static int lan0
static int mc0
static int rxcon
static int txcon
static int prcdar
static int ptcdar
static int eththr
static unsigned int cur_rx
static unsigned int cur_tx
static signed char phys [4]
struct {
   struct epic_rx_desc   rx_ring [RX_RING_SIZE]
   struct epic_tx_desc   tx_ring [TX_RING_SIZE]
   unsigned char   rx_packet [PKT_BUF_SZ *RX_RING_SIZE]
   unsigned char   tx_packet [PKT_BUF_SZ *TX_RING_SIZE]
__shared
static struct pci_device_id epic100_nics []

Define Documentation

Definition at line 7 of file epic100.c.

Definition at line 16 of file epic100.c.

Referenced by epic100_init_ring(), and epic100_open().

Definition at line 17 of file epic100.c.

#define TX_RING_SIZE   2 /* use at least 2 buffers for TX */

Definition at line 19 of file epic100.c.

Referenced by epic100_init_ring(), and epic100_transmit().

#define RX_RING_SIZE   2

Definition at line 20 of file epic100.c.

Referenced by epic100_init_ring(), and epic100_poll().

#define PKT_BUF_SZ   1536 /* Size of each temporary Tx/Rx buffer.*/

Definition at line 22 of file epic100.c.

Referenced by epic100_init_ring(), epic100_poll(), and epic100_transmit().

#define EPIC_DEBUG   0 /* debug level */

Definition at line 30 of file epic100.c.

#define TD_STDFLAGS   TD_LASTDESC

Definition at line 40 of file epic100.c.

Referenced by epic100_init_ring().

#define delay (   nanosec)
Value:
do { int _i = 3; while (--_i > 0) \
                                     { __SLOW_DOWN_IO; }} while (0)

Definition at line 49 of file epic100.c.

Definition at line 99 of file epic100.c.

Referenced by epic100_init_ring(), and epic100_poll().

Definition at line 100 of file epic100.c.

Referenced by epic100_init_ring(), and epic100_transmit().

#define MII_READOP   1

Definition at line 495 of file epic100.c.

Referenced by mii_read().

#define MII_WRITEOP   2

Definition at line 496 of file epic100.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER  )
static void epic100_open ( void  ) [static]

Definition at line 230 of file epic100.c.

References CR_QUEUE_RX, CR_START_RX, epic100_init_ring(), eththr, GC_MRC_READ_MULT, GC_ONE_COPY, GC_RX_FIFO_THR_64, genctl, mii_read(), outl(), phys, prcdar, printf(), ptcdar, putchar(), rx_ring, set_rx_mode(), TC_EARLY_TX_ENABLE, TC_LM_FULL_DPX, TC_LM_NORMAL, TX_FIFO_THRESH, tx_ring, TX_SLOT_TIME, txcon, and virt_to_le32desc.

Referenced by epic100_probe(), and epic100_transmit().

{
    int mii_reg5;
    unsigned long tmp;

    epic100_init_ring();

    /* Pull the chip out of low-power mode, and set for PCI read multiple. */
    outl(GC_RX_FIFO_THR_64 | GC_MRC_READ_MULT | GC_ONE_COPY, genctl);

    outl(TX_FIFO_THRESH, eththr);

    tmp = TC_EARLY_TX_ENABLE | TX_SLOT_TIME;

    mii_reg5 = mii_read(phys[0], 5);
    if (mii_reg5 != 0xffff && (mii_reg5 & 0x0100)) {
        printf(" full-duplex mode");
        tmp |= TC_LM_FULL_DPX;
    } else
        tmp |= TC_LM_NORMAL;

    outl(tmp, txcon);

    /* Give address of RX and TX ring to the chip */
    outl(virt_to_le32desc(&rx_ring), prcdar);
    outl(virt_to_le32desc(&tx_ring), ptcdar);

    /* Start the chip's Rx process: receive unicast and broadcast */
    set_rx_mode();
    outl(CR_START_RX | CR_QUEUE_RX, command);

    putchar('\n');
}
static void epic100_init_ring ( void  ) [static]

Definition at line 266 of file epic100.c.

References cpu_to_le32, cur_rx, cur_tx, PKT_BUF_SZ, RRING_OWN, rx_packet, rx_ring, RX_RING_SIZE, TD_STDFLAGS, tx_packet, tx_ring, TX_RING_SIZE, virt_to_bus(), and virt_to_le32desc.

Referenced by epic100_open().

{
    int i;

    cur_rx = cur_tx = 0;

    for (i = 0; i < RX_RING_SIZE; i++) {
        rx_ring[i].status    = cpu_to_le32(RRING_OWN);  /* Owned by Epic chip */
        rx_ring[i].buflength = cpu_to_le32(PKT_BUF_SZ);
        rx_ring[i].bufaddr   = virt_to_bus(&rx_packet[i * PKT_BUF_SZ]);
        rx_ring[i].next      = virt_to_le32desc(&rx_ring[i + 1]) ;
    }
    /* Mark the last entry as wrapping the ring. */
    rx_ring[i-1].next = virt_to_le32desc(&rx_ring[0]);

    /*
     *The Tx buffer descriptor is filled in as needed,
     * but we do need to clear the ownership bit.
     */

    for (i = 0; i < TX_RING_SIZE; i++) {
        tx_ring[i].status  = 0x0000;                    /* Owned by CPU */
        tx_ring[i].buflength = 0x0000 | cpu_to_le32(TD_STDFLAGS << 16);
        tx_ring[i].bufaddr = virt_to_bus(&tx_packet[i * PKT_BUF_SZ]);
        tx_ring[i].next    = virt_to_le32desc(&tx_ring[i + 1]);
    }
        tx_ring[i-1].next    = virt_to_le32desc(&tx_ring[0]);
}
static void epic100_disable ( struct nic nic) [static]
static int epic100_poll ( struct nic nic,
int  retrieve 
) [static]

Definition at line 375 of file epic100.c.

References cpu_to_le32, CR_QUEUE_RX, CR_START_RX, cur_rx, entry, INTR_CLEARERRS, intstat, le32_to_cpu, memcpy(), outl(), PKT_BUF_SZ, printf(), RRING_OWN, rx_packet, rx_ring, RX_RING_SIZE, and status.

{
    int entry;
    int retcode;
    unsigned long status;
    entry = cur_rx % RX_RING_SIZE;

    if ((rx_ring[entry].status & cpu_to_le32(RRING_OWN)) == RRING_OWN)
        return (0);

    if ( ! retrieve ) return 1;

    status = le32_to_cpu(rx_ring[entry].status);
    /* We own the next entry, it's a new packet. Send it up. */

#if     (EPIC_DEBUG > 4)
    printf("epic_poll: entry %d status %hX\n", entry, status);
#endif

    cur_rx++;
    if (status & 0x2000) {
        printf("epic_poll: Giant packet\n");
        retcode = 0;
    } else if (status & 0x0006) {
        /* Rx Frame errors are counted in hardware. */
        printf("epic_poll: Frame received with errors\n");
        retcode = 0;
    } else {
        /* Omit the four octet CRC from the length. */
        nic->packetlen = (status >> 16) - 4;
        memcpy(nic->packet, &rx_packet[entry * PKT_BUF_SZ], nic->packetlen);
        retcode = 1;
    }

    /* Clear all error sources. */
    outl(status & INTR_CLEARERRS, intstat);

    /* Give the descriptor back to the chip */
    rx_ring[entry].status = RRING_OWN;

    /* Restart Receiver */
    outl(CR_START_RX | CR_QUEUE_RX, command); 

    return retcode;
}
static void epic100_transmit ( struct nic nic,
const char *  destaddr,
unsigned int  type,
unsigned int  len,
const char *  data 
) [static]

Definition at line 305 of file epic100.c.

References cpu_to_le32, CR_QUEUE_TX, cur_tx, currticks(), entry, epic100_open(), ETH_ALEN, ETH_HLEN, ETH_ZLEN, htons, le32_to_cpu, memcpy(), outl(), PKT_BUF_SZ, printf(), status, TRING_OWN, tx_packet, tx_ring, and TX_RING_SIZE.

{
    unsigned short nstype;
    unsigned char *txp;
    int entry;
    unsigned long ct;

    /* Calculate the next Tx descriptor entry. */
    entry = cur_tx % TX_RING_SIZE;

    if ((tx_ring[entry].status & TRING_OWN) == TRING_OWN) {
        printf("eth_transmit: Unable to transmit. status=%4.4lx. Resetting...\n",
               tx_ring[entry].status);

        epic100_open();
        return;
    }

    txp = tx_packet + (entry * PKT_BUF_SZ);

    memcpy(txp, destaddr, ETH_ALEN);
    memcpy(txp + ETH_ALEN, nic->node_addr, ETH_ALEN);
    nstype = htons(type);
    memcpy(txp + 12, (char*)&nstype, 2);
    memcpy(txp + ETH_HLEN, data, len);

    len += ETH_HLEN;
        len &= 0x0FFF;
        while(len < ETH_ZLEN)
                txp[len++] = '\0';
    /*
     * Caution: the write order is important here,
     * set the base address with the "ownership"
     * bits last.
     */
   
    tx_ring[entry].buflength |= cpu_to_le32(len);
    tx_ring[entry].status = cpu_to_le32(len << 16) |
            cpu_to_le32(TRING_OWN);     /* Pass ownership to the chip. */

    cur_tx++;

    /* Trigger an immediate transmit demand. */
    outl(CR_QUEUE_TX, command);

    ct = currticks();
    /* timeout 10 ms for transmit */
    while ((le32_to_cpu(tx_ring[entry].status) & (TRING_OWN)) &&
                ct + 10*1000 < currticks())
        /* Wait */;

    if ((le32_to_cpu(tx_ring[entry].status) & TRING_OWN) != 0)
        printf("Oops, transmitter timeout, status=%4.4lX\n",
            tx_ring[entry].status);
}
static int mii_read ( int  phy_id,
int  location 
) [static]

Definition at line 499 of file epic100.c.

References inl(), inw(), MII_READOP, mmctl, mmdata, and outl().

Referenced by epic100_open(), epic100_probe(), mii_check_link(), mii_find(), mii_reset(), mii_restart(), realtek_phy_speed(), rhine_probe(), smscusb_mii_check_link(), and velocity_set_link().

{
    int i;

    outl((phy_id << 9) | (location << 4) | MII_READOP, mmctl);
    /* Typical operation takes < 50 ticks. */

    for (i = 4000; i > 0; i--)
        if ((inl(mmctl) & MII_READOP) == 0)
            break;
    return inw(mmdata);
}
static void epic100_irq ( struct nic nic,
irq_action_t  action 
) [static]
static int epic100_probe ( struct nic nic,
struct pci_device pci 
) [static]

Definition at line 108 of file epic100.c.

References COMMAND, DBG, EECTL, eectl, eeprom, epic100_open(), epic100_operations, eth_ntoa(), ETHTHR, eththr, GC_SOFT_RESET, GENCTL, genctl, INTMASK, intmask, INTR_DISABLE, INTSTAT, intstat, inw(), ioaddr, pci_device::ioaddr, LAN0, lan0, MC0, mc0, mii_read(), MMCTL, mmctl, MMDATA, mmdata, outl(), phy, phys, PRCDAR, prcdar, printf(), PTCDAR, ptcdar, read_eeprom(), RXCON, rxcon, TEST, test, TXCON, txcon, and value.

                                                          {

    int i;
    unsigned short* ap;
    unsigned int phy, phy_idx;

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

    /* Ideally we would detect all network cards in slot order.  That would
       be best done a central PCI probe dispatch, which wouldn't work
       well with the current structure.  So instead we detect just the
       Epic cards in slot order. */

    ioaddr = pci->ioaddr;

    nic->irqno  = 0;
    nic->ioaddr = pci->ioaddr & ~3;

    /* compute all used static epic100 registers address */
    command = ioaddr + COMMAND;         /* Control Register */
    intstat = ioaddr + INTSTAT;         /* Interrupt Status */
    intmask = ioaddr + INTMASK;         /* Interrupt Mask */
    genctl  = ioaddr + GENCTL;          /* General Control */
    eectl   = ioaddr + EECTL;           /* EEPROM Control  */
    test    = ioaddr + TEST;            /* Test register (clocks) */
    mmctl   = ioaddr + MMCTL;           /* MII Management Interface Control */
    mmdata  = ioaddr + MMDATA;          /* MII Management Interface Data */
    lan0    = ioaddr + LAN0;            /* MAC address. (0x40-0x48) */
    mc0     = ioaddr + MC0;             /* Multicast Control */
    rxcon   = ioaddr + RXCON;           /* Receive Control */
    txcon   = ioaddr + TXCON;           /* Transmit Control */
    prcdar  = ioaddr + PRCDAR;          /* PCI Receive Current Descr Address */
    ptcdar  = ioaddr + PTCDAR;          /* PCI Transmit Current Descr Address */
    eththr  = ioaddr + ETHTHR;          /* Early Transmit Threshold */

    /* Reset the chip & bring it out of low-power mode. */
    outl(GC_SOFT_RESET, genctl);

    /* Disable ALL interrupts by setting the interrupt mask. */
    outl(INTR_DISABLE, intmask);

    /*
     * set the internal clocks:
     * Application Note 7.15 says:
     *    In order to set the CLOCK TEST bit in the TEST register,
     *    perform the following:
     *
     *        Write 0x0008 to the test register at least sixteen
     *        consecutive times.
     *
     * The CLOCK TEST bit is Write-Only. Writing it several times
     * consecutively insures a successful write to the bit...
     */

    for (i = 0; i < 16; i++) {
        outl(0x00000008, test);
    }

#ifdef  DEBUG_EEPROM
{
    unsigned short sum = 0;
    unsigned short value;
    for (i = 0; i < 64; i++) {
        value = read_eeprom(i);
        eeprom[i] = value;
        sum += value;
    }
}

#if     (EPIC_DEBUG > 1)
    printf("EEPROM contents\n");
    for (i = 0; i < 64; i++) {
        printf(" %hhX%s", eeprom[i], i % 16 == 15 ? "\n" : "");
    }
#endif
#endif

    /* This could also be read from the EEPROM. */
    ap = (unsigned short*)nic->node_addr;
    for (i = 0; i < 3; i++)
        *ap++ = inw(lan0 + i*4);

    DBG ( " I/O %4.4x %s ", ioaddr, eth_ntoa ( nic->node_addr ) );

    /* Find the connected MII xcvrs. */
    for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(phys); phy++) {
        int mii_status = mii_read(phy, 0);

        if (mii_status != 0xffff  && mii_status != 0x0000) {
            phys[phy_idx++] = phy;
#if     (EPIC_DEBUG > 1)
            printf("MII transceiver found at address %d.\n", phy);
#endif
        }
    }
    if (phy_idx == 0) {
#if     (EPIC_DEBUG > 1)
        printf("***WARNING***: No MII transceiver found!\n");
#endif
        /* Use the known PHY address of the EPII. */
        phys[0] = 3;
    }

    epic100_open();
    nic->nic_op = &epic100_operations;

    return 1;
}
static void set_rx_mode ( void  ) [static]

Definition at line 218 of file epic100.c.

References mc0, memset(), outl(), outw(), and rxcon.

Referenced by epic100_open(), and sundance_reset().

{
        unsigned char mc_filter[8];
        int i;
        memset(mc_filter, 0xff, sizeof(mc_filter));
        outl(0x0C, rxcon);
        for(i = 0; i < 4; i++)
                outw(((unsigned short *)mc_filter)[i], mc0 + i*4);
        return;
}
static void epic100_disable ( struct nic *nic  __unused) [static]

Definition at line 422 of file epic100.c.

References GC_SOFT_RESET, genctl, and outl().

                                                         {
        /* Soft reset the chip. */
        outl(GC_SOFT_RESET, genctl);
}
static void epic100_irq ( struct nic *nic  __unused,
irq_action_t action  __unused 
) [static]

Definition at line 427 of file epic100.c.

{
  switch ( action ) {
  case DISABLE :
    break;
  case ENABLE :
    break;
  case FORCE :
    break;
  }
}
PCI_DRIVER ( epic100_driver  ,
epic100_nics  ,
PCI_NO_CLASS   
)
DRIVER ( "EPIC100"  ,
nic_driver  ,
pci_driver  ,
epic100_driver  ,
epic100_probe  ,
epic100_disable   
)

Variable Documentation

static struct nic_operations epic100_operations [static]
Initial value:
 {
        .connect        = dummy_connect,
        .poll           = epic100_poll,
        .transmit       = epic100_transmit,
        .irq            = epic100_irq,

}

Definition at line 64 of file epic100.c.

Referenced by epic100_probe().

int ioaddr [static]

Definition at line 66 of file epic100.c.

Referenced by epic100_probe().

int command [static]

Definition at line 68 of file epic100.c.

int intstat [static]

Definition at line 69 of file epic100.c.

Referenced by epic100_poll(), and epic100_probe().

int intmask [static]

Definition at line 70 of file epic100.c.

Referenced by epic100_probe().

int genctl [static]

Definition at line 71 of file epic100.c.

Referenced by epic100_disable(), epic100_open(), and epic100_probe().

int eectl [static]

Definition at line 72 of file epic100.c.

Referenced by epic100_probe().

int test [static]
int mmctl [static]

Definition at line 74 of file epic100.c.

Referenced by epic100_probe(), and mii_read().

int mmdata [static]

Definition at line 75 of file epic100.c.

Referenced by epic100_probe(), and mii_read().

int lan0 [static]

Definition at line 76 of file epic100.c.

Referenced by epic100_probe().

int mc0 [static]

Definition at line 77 of file epic100.c.

Referenced by epic100_probe(), and set_rx_mode().

int rxcon [static]

Definition at line 78 of file epic100.c.

Referenced by epic100_probe(), and set_rx_mode().

int txcon [static]

Definition at line 79 of file epic100.c.

Referenced by epic100_open(), and epic100_probe().

int prcdar [static]

Definition at line 80 of file epic100.c.

Referenced by epic100_open(), and epic100_probe().

int ptcdar [static]

Definition at line 81 of file epic100.c.

Referenced by epic100_open(), and epic100_probe().

int eththr [static]

Definition at line 82 of file epic100.c.

Referenced by epic100_open(), and epic100_probe().

unsigned int cur_rx [static]
unsigned int cur_tx [static]

Definition at line 84 of file epic100.c.

Referenced by epic100_init_ring(), and epic100_transmit().

signed char phys[4] [static]

Definition at line 90 of file epic100.c.

Definition at line 92 of file epic100.c.

Definition at line 94 of file epic100.c.

Definition at line 95 of file epic100.c.

struct { ... } __shared
struct pci_device_id epic100_nics[] [static]
Initial value:
 {
PCI_ROM(0x10b8, 0x0005, "epic100",    "SMC EtherPowerII", 0),           
PCI_ROM(0x10b8, 0x0006, "smc-83c175", "SMC EPIC/C 83c175", 0),
}

Definition at line 520 of file epic100.c.