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

Go to the source code of this file.

Data Structures

struct  connector_entry

Defines

#define CONNECTOR_UTP   0
#define CONNECTOR_AUI   1
#define CONNECTOR_BNC   3
#define CONNECTOR_TX   4
#define CONNECTOR_FX   5
#define CONNECTOR_MII   6

Functions

 FILE_LICENCE (BSD2)
static void vxgetlink (void)
static void vxsetlink (void)
static void t595_reset (struct nic *nic)
static void t595_transmit (struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p)
static int t595_poll (struct nic *nic, int retrieve)
static int eeprom_rdy ()
static int get_e (int offset)
static void t595_disable (struct nic *nic)
static void t595_irq (struct nic *nic __unused, irq_action_t action __unused)
static int t595_probe (struct nic *nic, struct pci_device *pci)
 PCI_DRIVER (t595_driver, t595_nics, PCI_NO_CLASS)
 DRIVER ("3C595", nic_driver, pci_driver, t595_driver, t595_probe, t595_disable)

Variables

static struct nic_operations t595_operations
static unsigned short eth_nic_base
static unsigned short vx_connector
static unsigned short vx_connectors
static struct connector_entry conn_tab [VX_CONNECTORS]
static char padmap []
static struct pci_device_id t595_nics []

Define Documentation

#define CONNECTOR_UTP   0

Referenced by vxsetlink().

#define CONNECTOR_AUI   1
#define CONNECTOR_BNC   3

Referenced by vxsetlink().

#define CONNECTOR_TX   4

Referenced by vxsetlink().

#define CONNECTOR_FX   5

Referenced by vxsetlink().

#define CONNECTOR_MII   6

Function Documentation

FILE_LICENCE ( BSD2  )
static void vxgetlink ( void  ) [static]

Definition at line 357 of file 3c595.c.

References BASE, conn_tab, GO_WINDOW, inl(), INTERNAL_CONNECTOR_BITS, INTERNAL_CONNECTOR_MASK, inw(), k, name, printf(), vx_connector, vx_connectors, VX_CONNECTORS, VX_W3_INTERNAL_CFG, and VX_W3_RESET_OPT.

Referenced by t595_probe().

{
    int n, k;

    GO_WINDOW(3);
    vx_connectors = inw(BASE + VX_W3_RESET_OPT) & 0x7f;
    for (n = 0, k = 0; k < VX_CONNECTORS; k++) {
      if (vx_connectors & conn_tab[k].bit) {
        if (n > 0) {
          printf("/");
        }
        printf("%s", conn_tab[k].name );
        n++;
      }
    }
    if (vx_connectors == 0) {
        printf("no connectors!");
        return;
    }
    GO_WINDOW(3);
    vx_connector = (inl(BASE + VX_W3_INTERNAL_CFG) 
                        & INTERNAL_CONNECTOR_MASK) 
                        >> INTERNAL_CONNECTOR_BITS;
    if (vx_connector & 0x10) {
        vx_connector &= 0x0f;
        printf("[*%s*]", conn_tab[vx_connector].name);
        printf(": disable 'auto select' with DOS util!");
    } else {
        printf("[*%s*]", conn_tab[vx_connector].name);
    }
}
static void vxsetlink ( void  ) [static]

Definition at line 390 of file 3c595.c.

References BASE, conn_tab, CONNECTOR_BNC, CONNECTOR_FX, CONNECTOR_TX, CONNECTOR_UTP, ENABLE_UTP, GO_WINDOW, inl(), INTERNAL_CONNECTOR_BITS, INTERNAL_CONNECTOR_MASK, LINKBEAT_ENABLE, name, NULL, outl(), outw(), printf(), reason, START_TRANSCEIVER, STOP_TRANSCEIVER, udelay(), VX_COMMAND, vx_connector, vx_connectors, VX_W3_INTERNAL_CFG, and VX_W4_MEDIA_TYPE.

Referenced by t595_reset().

{       
    int i, j;
    char *reason, *warning;
    static signed char prev_conn = -1;

    if (prev_conn == -1) {
        prev_conn = vx_connector;
    }

    i = vx_connector;       /* default in EEPROM */
    reason = "default";
    warning = NULL;

    if ((vx_connectors & conn_tab[vx_connector].bit) == 0) {
        warning = "strange connector type in EEPROM.";
        reason = "forced";
        i = CONNECTOR_UTP;
    }

        if (warning) {
            printf("warning: %s\n", warning);
        }
        printf("selected %s. (%s)\n", conn_tab[i].name, reason);

    /* Set the selected connector. */
    GO_WINDOW(3);
    j = inl(BASE + VX_W3_INTERNAL_CFG) & ~INTERNAL_CONNECTOR_MASK;
    outl(j | (i <<INTERNAL_CONNECTOR_BITS), BASE + VX_W3_INTERNAL_CFG);

    /* First, disable all. */
    outw(STOP_TRANSCEIVER, BASE + VX_COMMAND);
    udelay(8000);
    GO_WINDOW(4);
    outw(0, BASE + VX_W4_MEDIA_TYPE);

    /* Second, enable the selected one. */
    switch(i) {
      case CONNECTOR_UTP:
        GO_WINDOW(4);
        outw(ENABLE_UTP, BASE + VX_W4_MEDIA_TYPE);
        break;
      case CONNECTOR_BNC:
        outw(START_TRANSCEIVER,BASE + VX_COMMAND);
        udelay(8000);
        break;
      case CONNECTOR_TX:
      case CONNECTOR_FX:
        GO_WINDOW(4);
        outw(LINKBEAT_ENABLE, BASE + VX_W4_MEDIA_TYPE);
        break;
      default:  /* AUI and MII fall here */
        break;
    }
    GO_WINDOW(1); 
}
static void t595_reset ( struct nic nic) [static]

Definition at line 68 of file 3c595.c.

References ACK_INTR, BASE, C_INTR_LATCH, ETH_ALEN, FIL_BRDCST, FIL_INDIVIDUAL, FIL_MULTICAST, GO_WINDOW, inb(), outb(), outw(), RX_DISABLE, RX_DISCARD_TOP_PACK, RX_ENABLE, RX_RESET, S_CARD_FAILURE, S_RX_COMPLETE, S_TX_AVAIL, S_TX_COMPLETE, SET_INTR_MASK, SET_RD_0_MASK, SET_RX_FILTER, STOP_TRANSCEIVER, TX_DISABLE, TX_ENABLE, TX_RESET, udelay(), VX_BUSY_WAIT, VX_COMMAND, VX_W1_TX_STATUS, VX_W2_ADDR_0, and vxsetlink().

Referenced by t595_disable(), and t595_probe().

{
        int i;

        /***********************************************************
                        Reset 3Com 595 card
        *************************************************************/

        /* stop card */
        outw(RX_DISABLE, BASE + VX_COMMAND);
        outw(RX_DISCARD_TOP_PACK, BASE + VX_COMMAND);
        VX_BUSY_WAIT;
        outw(TX_DISABLE, BASE + VX_COMMAND);
        outw(STOP_TRANSCEIVER, BASE + VX_COMMAND);
        udelay(8000);
        outw(RX_RESET, BASE + VX_COMMAND);
        VX_BUSY_WAIT;
        outw(TX_RESET, BASE + VX_COMMAND);
        VX_BUSY_WAIT;
        outw(C_INTR_LATCH, BASE + VX_COMMAND);
        outw(SET_RD_0_MASK, BASE + VX_COMMAND);
        outw(SET_INTR_MASK, BASE + VX_COMMAND);
        outw(SET_RX_FILTER, BASE + VX_COMMAND);

        /*
        * initialize card
        */
        VX_BUSY_WAIT;

        GO_WINDOW(0);

        /* Disable the card */
/*      outw(0, BASE + VX_W0_CONFIG_CTRL); */

        /* Configure IRQ to none */
/*      outw(SET_IRQ(0), BASE + VX_W0_RESOURCE_CFG); */

        /* Enable the card */
/*      outw(ENABLE_DRQ_IRQ, BASE + VX_W0_CONFIG_CTRL); */

        GO_WINDOW(2);

        /* Reload the ether_addr. */
        for (i = 0; i < ETH_ALEN; i++)
                outb(nic->node_addr[i], BASE + VX_W2_ADDR_0 + i);

        outw(RX_RESET, BASE + VX_COMMAND);
        VX_BUSY_WAIT;
        outw(TX_RESET, BASE + VX_COMMAND);
        VX_BUSY_WAIT;

        /* Window 1 is operating window */
        GO_WINDOW(1);
        for (i = 0; i < 31; i++)
                inb(BASE + VX_W1_TX_STATUS);

        outw(SET_RD_0_MASK | S_CARD_FAILURE | S_RX_COMPLETE |
                S_TX_COMPLETE | S_TX_AVAIL, BASE + VX_COMMAND);
        outw(SET_INTR_MASK | S_CARD_FAILURE | S_RX_COMPLETE |
                S_TX_COMPLETE | S_TX_AVAIL, BASE + VX_COMMAND);

/*
 * Attempt to get rid of any stray interrupts that occurred during
 * configuration.  On the i386 this isn't possible because one may
 * already be queued.  However, a single stray interrupt is
 * unimportant.
 */

        outw(ACK_INTR | 0xff, BASE + VX_COMMAND);

        outw(SET_RX_FILTER | FIL_INDIVIDUAL |
            FIL_BRDCST|FIL_MULTICAST, BASE + VX_COMMAND);

        vxsetlink();
/*{
        int i,j;
        i = CONNECTOR_TX;
        GO_WINDOW(3);
        j = inl(BASE + VX_W3_INTERNAL_CFG) & ~INTERNAL_CONNECTOR_MASK;
        outl(BASE + VX_W3_INTERNAL_CFG, j | (i <<INTERNAL_CONNECTOR_BITS));
        GO_WINDOW(4);
        outw(LINKBEAT_ENABLE, BASE + VX_W4_MEDIA_TYPE);
        GO_WINDOW(1);
}*/

        /* start tranciever and receiver */
        outw(RX_ENABLE, BASE + VX_COMMAND);
        outw(TX_ENABLE, BASE + VX_COMMAND);

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

Definition at line 165 of file 3c595.c.

References BASE, ETH_ALEN, ETH_FRAME_LEN, ETH_HLEN, htons, inb(), inw(), len, outb(), outsw(), outw(), pad, padmap, printf(), S_COMMAND_IN_PROGRESS, status, TX_ENABLE, TX_RESET, TXS_COMPLETE, TXS_MAX_COLLISION, TXS_STATUS_OVERFLOW, TXS_UNDERRUN, VX_COMMAND, VX_STATUS, VX_W1_FREE_TX, VX_W1_TX_PIO_WR_1, and VX_W1_TX_STATUS.

{
        register int len;
        int pad;
        int status;

#ifdef EDEBUG
        printf("{l=%d,t=%hX}",s+ETH_HLEN,t);
#endif

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

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

        /*
        * The 3c595 automatically pads short packets to minimum ethernet length,
        * but we drop packets that are too large. Perhaps we should truncate
        * them instead?
        */
        if (len + pad > ETH_FRAME_LEN) {
                return;
        }

        /* drop acknowledgements */
        while(( status=inb(BASE + VX_W1_TX_STATUS) )& TXS_COMPLETE ) {
                if(status & (TXS_UNDERRUN|TXS_MAX_COLLISION|TXS_STATUS_OVERFLOW)) {
                        outw(TX_RESET, BASE + VX_COMMAND);
                        outw(TX_ENABLE, BASE + VX_COMMAND);
                }

                outb(0x0, BASE + VX_W1_TX_STATUS);
        }

        while (inw(BASE + VX_W1_FREE_TX) < len + pad + 4) {
                /* no room in FIFO */
        }

        outw(len, BASE + VX_W1_TX_PIO_WR_1);
        outw(0x0, BASE + VX_W1_TX_PIO_WR_1);    /* Second dword meaningless */

        /* write packet */
        outsw(BASE + VX_W1_TX_PIO_WR_1, d, ETH_ALEN/2);
        outsw(BASE + VX_W1_TX_PIO_WR_1, nic->node_addr, ETH_ALEN/2);
        outw(t, BASE + VX_W1_TX_PIO_WR_1);
        outsw(BASE + VX_W1_TX_PIO_WR_1, p, s / 2);
        if (s & 1)
                outb(*(p+s - 1), BASE + VX_W1_TX_PIO_WR_1);

        while (pad--)
                outb(0, BASE + VX_W1_TX_PIO_WR_1);      /* Padding */

        /* wait for Tx complete */
        while((inw(BASE + VX_STATUS) & S_COMMAND_IN_PROGRESS) != 0)
                ;
}
static int t595_poll ( struct nic nic,
int  retrieve 
) [static]

Definition at line 231 of file 3c595.c.

References ACK_INTR, BASE, C_INTR_LATCH, ERR_RX, ETH_ALEN, inb(), insw(), inw(), outw(), printf(), RX_BYTES_MASK, RX_DISCARD_TOP_PACK, RX_INCOMPLETE, S_COMMAND_IN_PROGRESS, S_RX_COMPLETE, status, type, udelay(), VX_COMMAND, VX_STATUS, VX_W1_RX_PIO_RD_1, and VX_W1_RX_STATUS.

{
        /* common variables */
        /* variables for 3C595 */
        short status, cst;
        register short rx_fifo;

        cst=inw(BASE + VX_STATUS);

#ifdef EDEBUG
        if(cst & 0x1FFF)
                printf("-%hX-",cst);
#endif

        if( (cst & S_RX_COMPLETE)==0 ) {
                /* acknowledge  everything */
                outw(ACK_INTR | cst, BASE + VX_COMMAND);
                outw(C_INTR_LATCH, BASE + VX_COMMAND);

                return 0;
        }

        status = inw(BASE + VX_W1_RX_STATUS);
#ifdef EDEBUG
        printf("*%hX*",status);
#endif

        if (status & ERR_RX) {
                outw(RX_DISCARD_TOP_PACK, BASE + VX_COMMAND);
                return 0;
        }

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

        if ( ! retrieve ) return 1;

                /* read packet */
#ifdef EDEBUG
        printf("[l=%d",rx_fifo);
#endif
        insw(BASE + VX_W1_RX_PIO_RD_1, nic->packet, rx_fifo / 2);
        if(rx_fifo & 1)
                nic->packet[rx_fifo-1]=inb(BASE + VX_W1_RX_PIO_RD_1);
        nic->packetlen=rx_fifo;

        while(1) {
                status = inw(BASE + VX_W1_RX_STATUS);
#ifdef EDEBUG
                printf("*%hX*",status);
#endif
                rx_fifo = status & RX_BYTES_MASK;

                if(rx_fifo>0) {
                        insw(BASE + VX_W1_RX_PIO_RD_1, nic->packet+nic->packetlen, rx_fifo / 2);
                        if(rx_fifo & 1)
                                nic->packet[nic->packetlen+rx_fifo-1]=inb(BASE + VX_W1_RX_PIO_RD_1);
                        nic->packetlen+=rx_fifo;
#ifdef EDEBUG
                        printf("+%d",rx_fifo);
#endif
                }
                if(( status & RX_INCOMPLETE )==0) {
#ifdef EDEBUG
                        printf("=%d",nic->packetlen);
#endif
                        break;
                }
                udelay(1000);
        }

        /* acknowledge reception of packet */
        outw(RX_DISCARD_TOP_PACK, BASE + VX_COMMAND);
        while (inw(BASE + VX_STATUS) & S_COMMAND_IN_PROGRESS);
#ifdef EDEBUG
{
        unsigned short type = 0;        /* used by EDEBUG */
        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)
                printf(",t=%hX,b]",type);
        else
                printf(",t=%hX]",type);
}
#endif
        return 1;
}
static int eeprom_rdy ( ) [static]

Definition at line 326 of file 3c595.c.

References BASE, is_eeprom_busy, MAX_EEPROMBUSY, printf(), and udelay().

Referenced by get_e().

{
        int i;

        for (i = 0; is_eeprom_busy(BASE) && i < MAX_EEPROMBUSY; i++)
                udelay(1000);
        if (i >= MAX_EEPROMBUSY) {
                /* printf("3c595: eeprom failed to come ready.\n"); */
                printf("3c595: eeprom is busy.\n"); /* memory in EPROM is tight */
                return (0);
        }
        return (1);
}
static int get_e ( int  offset) [static]

Definition at line 345 of file 3c595.c.

References BASE, EEPROM_CMD_RD, eeprom_rdy(), inw(), outw(), VX_W0_EEPROM_COMMAND, and VX_W0_EEPROM_DATA.

Referenced by t595_probe().

{
        if (!eeprom_rdy())
                return (0xffff);
        outw(EEPROM_CMD_RD | offset, BASE + VX_W0_EEPROM_COMMAND);
        if (!eeprom_rdy())
                return (0xffff);
        return (inw(BASE + VX_W0_EEPROM_DATA));
}
static void t595_disable ( struct nic nic) [static]
static void t595_irq ( struct nic *nic  __unused,
irq_action_t action  __unused 
) [static]

Definition at line 458 of file 3c595.c.

{
  switch ( action ) {
  case DISABLE :
    break;
  case ENABLE :
    break;
  case FORCE :
    break;
  }
}
static int t595_probe ( struct nic nic,
struct pci_device pci 
) [static]

Definition at line 473 of file 3c595.c.

References BASE, DBG, EEPROM_OEM_ADDR_0, eth_nic_base, eth_ntoa(), get_e(), GLOBAL_RESET, GO_WINDOW, htons, pci_device::ioaddr, ntohs, outw(), t595_operations, t595_reset(), VX_BUSY_WAIT, VX_COMMAND, VX_W2_ADDR_0, and vxgetlink().

                                                                  {

        int i;
        unsigned short *p;

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

        nic->irqno  = 0;
        nic->ioaddr = pci->ioaddr;

        GO_WINDOW(0);
        outw(GLOBAL_RESET, BASE + VX_COMMAND);
        VX_BUSY_WAIT;

        vxgetlink();

/*
        printf("\nEEPROM:");
        for (i = 0; i < (EEPROMSIZE/2); i++) {
          printf("%hX:", get_e(i));
        }
        printf("\n");
*/
        /*
        * Read the station address from the eeprom
        */
        p = (unsigned short *) nic->node_addr;
        for (i = 0; i < 3; i++) {
                GO_WINDOW(0);
                p[i] = htons(get_e(EEPROM_OEM_ADDR_0 + i));
                GO_WINDOW(2);
                outw(ntohs(p[i]), BASE + VX_W2_ADDR_0 + (i * 2));
        }

        DBG ( "Ethernet address: %s\n", eth_ntoa (nic->node_addr) );

        t595_reset(nic);
        nic->nic_op     = &t595_operations;
        return 1;

}
PCI_DRIVER ( t595_driver  ,
t595_nics  ,
PCI_NO_CLASS   
)
DRIVER ( "3C595"  ,
nic_driver  ,
pci_driver  ,
t595_driver  ,
t595_probe  ,
t595_disable   
)

Variable Documentation

static struct nic_operations t595_operations [static]
Initial value:
 {
        .connect        = dummy_connect,
        .poll           = t595_poll,
        .transmit       = t595_transmit,
        .irq            = t595_irq,

}

Definition at line 36 of file 3c595.c.

Referenced by t595_probe().

unsigned short eth_nic_base [static]

Definition at line 38 of file 3c595.c.

Referenced by t595_probe().

unsigned short vx_connector [static]

Definition at line 39 of file 3c595.c.

Referenced by vxgetlink(), and vxsetlink().

unsigned short vx_connectors [static]

Definition at line 39 of file 3c595.c.

Referenced by vxgetlink(), and vxsetlink().

Referenced by vxgetlink(), and vxsetlink().

char padmap[] [static]
Initial value:
 {
        0, 3, 2, 1}

Definition at line 162 of file 3c595.c.

Referenced by t595_transmit().

struct pci_device_id t595_nics[] [static]
Initial value:
 {
PCI_ROM(0x10b7, 0x5900, "3c590",           "3Com590", 0),               
PCI_ROM(0x10b7, 0x5950, "3c595",           "3Com595", 0),               
PCI_ROM(0x10b7, 0x5951, "3c595-1",         "3Com595", 0),               
PCI_ROM(0x10b7, 0x5952, "3c595-2",         "3Com595", 0),               
PCI_ROM(0x10b7, 0x9000, "3c900-tpo",       "3Com900-TPO", 0),   
PCI_ROM(0x10b7, 0x9001, "3c900-t4",        "3Com900-Combo", 0), 
PCI_ROM(0x10b7, 0x9004, "3c900b-tpo",      "3Com900B-TPO", 0),  
PCI_ROM(0x10b7, 0x9005, "3c900b-combo",    "3Com900B-Combo", 0),        
PCI_ROM(0x10b7, 0x9006, "3c900b-tpb2",     "3Com900B-2/T", 0),  
PCI_ROM(0x10b7, 0x900a, "3c900b-fl",       "3Com900B-FL", 0),   
PCI_ROM(0x10b7, 0x9800, "3c980-cyclone-1", "3Com980-Cyclone", 0),       
PCI_ROM(0x10b7, 0x9805, "3c9805-1",        "3Com9805", 0),              
PCI_ROM(0x10b7, 0x7646, "3csoho100-tx-1",  "3CSOHO100-TX", 0),  
PCI_ROM(0x10b7, 0x4500, "3c450-1",         "3Com450 HomePNA Tornado", 0),
}

Definition at line 525 of file 3c595.c.