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

Go to the source code of this file.

Data Structures

struct  pci_id_info
struct  pci_id_info::match_info
struct  TLanList
struct  tlan_private

Defines

#define drv_version   "v1.4"
#define drv_date   "01-17-2004"
#define HZ   100
#define TX_TIME_OUT   (6*HZ)
#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   tlan_buffers.tx_ring
#define txb   tlan_buffers.txb
#define rx_ring   tlan_buffers.rx_ring
#define rxb   tlan_buffers.rxb
#define board_found   1
#define valid_link   0

Typedefs

typedef u8 TLanBuffer [TLAN_MAX_FRAME_SIZE]

Enumerations

enum  tlan_nics {
  NETEL10 = 0, NETEL100 = 1, NETFLEX3I = 2, THUNDER = 3,
  NETFLEX3B, NETEL100PI = 5, NETEL100D = 6, NETEL100I = 7,
  OC2183 = 8, OC2325 = 9, OC2326, NETELLIGENT_10_100_WS_5100 = 11,
  NETELLIGENT_10_T2 = 12
}

Functions

 FILE_LICENCE (GPL2_OR_LATER)
static void TLan_ResetLists (struct nic *nic __unused)
static void TLan_ResetAdapter (struct nic *nic __unused)
static void TLan_FinishReset (struct nic *nic __unused)
static void TLan_EeSendStart (u16)
static int TLan_EeSendByte (u16, u8, int)
static void TLan_EeReceiveByte (u16, u8 *, int)
static int TLan_EeReadByte (u16 io_base, u8, u8 *)
static void TLan_PhyDetect (struct nic *nic)
static void TLan_PhyPowerDown (struct nic *nic)
static void TLan_PhyPowerUp (struct nic *nic)
static void TLan_SetMac (struct nic *nic __unused, int areg, unsigned char *mac)
static void TLan_PhyReset (struct nic *nic)
static void TLan_PhyStartLink (struct nic *nic)
static void TLan_PhyFinishAutoNeg (struct nic *nic)
static void refill_rx (struct nic *nic __unused)
static int TLan_MiiReadReg (struct nic *nic __unused, u16, u16, u16 *)
static void TLan_MiiSendData (u16, u32, unsigned)
static void TLan_MiiSync (u16)
static void TLan_MiiWriteReg (struct nic *nic __unused, u16, u16, u16)
void TLan_FinishReset (struct nic *nic)
static int tlan_poll (struct nic *nic, int retrieve)
static void tlan_transmit (struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p)
static void tlan_disable (struct nic *nic __unused)
static void tlan_irq (struct nic *nic __unused, irq_action_t action __unused)
static void TLan_SetMulticastList (struct nic *nic)
static int tlan_probe (struct nic *nic, struct pci_device *pci)
 PCI_DRIVER (tlan_driver, tlan_nics, PCI_NO_CLASS)
 DRIVER ("TLAN/PCI", nic_driver, pci_driver, tlan_driver, tlan_probe, tlan_disable)

Variables

static const char * media []
static struct pci_id_info tlan_pci_tbl []
struct {
   struct TLanList   tx_ring [TLAN_NUM_TX_LISTS]
   unsigned char   txb [TLAN_MAX_FRAME_SIZE
      *TLAN_NUM_TX_LISTS]
   struct TLanList   rx_ring [TLAN_NUM_RX_LISTS]
   unsigned char   rxb [TLAN_MAX_FRAME_SIZE
      *TLAN_NUM_RX_LISTS]
__shared
static int chip_idx
static struct tlan_private TLanPrivateInfo
static struct tlan_privatepriv
static u32 BASE
static struct nic_operations tlan_operations
static struct pci_device_id tlan_nics []

Define Documentation

#define drv_version   "v1.4"

Definition at line 51 of file tlan.c.

#define drv_date   "01-17-2004"

Definition at line 52 of file tlan.c.

#define HZ   100

Definition at line 55 of file tlan.c.

#define TX_TIME_OUT   (6*HZ)

Definition at line 56 of file tlan.c.

Referenced by tlan_transmit().

Definition at line 59 of file tlan.c.

Referenced by TLan_ResetLists(), and tlan_transmit().

Definition at line 60 of file tlan.c.

Definition at line 188 of file tlan.c.

#define txb   tlan_buffers.txb

Definition at line 189 of file tlan.c.

Definition at line 190 of file tlan.c.

#define rxb   tlan_buffers.rxb

Definition at line 191 of file tlan.c.

#define board_found   1

Definition at line 778 of file tlan.c.

#define valid_link   0

Definition at line 779 of file tlan.c.


Typedef Documentation

Definition at line 193 of file tlan.c.


Enumeration Type Documentation

enum tlan_nics
Enumerator:
NETEL10 
NETEL100 
NETFLEX3I 
THUNDER 
NETFLEX3B 
NETEL100PI 
NETEL100D 
NETEL100I 
OC2183 
OC2325 
OC2326 
NETELLIGENT_10_100_WS_5100 
NETELLIGENT_10_T2 

Definition at line 101 of file tlan.c.

               {
        NETEL10 = 0, NETEL100 = 1, NETFLEX3I = 2, THUNDER = 3, NETFLEX3B =
            4, NETEL100PI = 5,
        NETEL100D = 6, NETEL100I = 7, OC2183 = 8, OC2325 = 9, OC2326 =
            10, NETELLIGENT_10_100_WS_5100 = 11,
        NETELLIGENT_10_T2 = 12
};

Function Documentation

FILE_LICENCE ( GPL2_OR_LATER  )
static void TLan_ResetLists ( struct nic *nic  __unused) [static]

Definition at line 242 of file tlan.c.

References TLanList::address, TLanList::buffer, TLanList::count, TLanList::cStat, tlan_private::cur_rx, tlan_private::dirty_rx, tlan_private::rx_buf_sz, rx_ring, rxb, TLAN_CSTAT_READY, TLAN_CSTAT_UNUSED, TLAN_LAST_BUFFER, TLAN_MAX_FRAME_SIZE, TLAN_NUM_RX_LISTS, TLAN_NUM_TX_LISTS, tx_ring, txb, tlan_private::txHead, tlan_private::txTail, virt_to_bus(), and virt_to_le32desc.

Referenced by tlan_probe().

{

        int i;
        struct TLanList *list;
        priv->txHead = 0;
        priv->txTail = 0;

        for (i = 0; i < TLAN_NUM_TX_LISTS; i++) {
                list = &tx_ring[i];
                list->cStat = TLAN_CSTAT_UNUSED;
                list->buffer[0].address = virt_to_bus(txb + 
                                (i * TLAN_MAX_FRAME_SIZE)); 
                list->buffer[2].count = 0;
                list->buffer[2].address = 0;
                list->buffer[9].address = 0;
        }

        priv->cur_rx = 0;
        priv->rx_buf_sz = (TLAN_MAX_FRAME_SIZE);
//      priv->rx_head_desc = &rx_ring[0];

        /* Initialize all the Rx descriptors */
        for (i = 0; i < TLAN_NUM_RX_LISTS; i++) {
                rx_ring[i].forward = virt_to_le32desc(&rx_ring[i + 1]);
                rx_ring[i].cStat = TLAN_CSTAT_READY;
                rx_ring[i].frameSize = TLAN_MAX_FRAME_SIZE;
                rx_ring[i].buffer[0].count =
                    TLAN_MAX_FRAME_SIZE | TLAN_LAST_BUFFER;
                rx_ring[i].buffer[0].address =
                    virt_to_le32desc(&rxb[i * TLAN_MAX_FRAME_SIZE]);
                rx_ring[i].buffer[1].count = 0;
                rx_ring[i].buffer[1].address = 0;
        }

        /* Mark the last entry as wrapping the ring */
        rx_ring[i - 1].forward = virt_to_le32desc(&rx_ring[0]);
        priv->dirty_rx = (unsigned int) (i - TLAN_NUM_RX_LISTS);

} /* TLan_ResetLists */
void TLan_ResetAdapter ( struct nic *nic  __unused) [static]

Definition at line 300 of file tlan.c.

References addr, tlan_private::aui, BASE, chip_idx, data, data8, tlan_private::duplex, FALSE, flags, inl(), nic, outl(), outw(), tlan_private::phyNum, tlan_private::phyOnline, TLAN_ACOMMIT, TLAN_ADAPTER_BIT_RATE_PHY, TLAN_ADAPTER_UNMANAGED_PHY, TLAN_AREG_0, TLAN_DIO_ADR, TLAN_DIO_DATA, TLan_DioWrite16(), TLan_DioWrite32(), TLan_DioWrite8(), TLAN_DUPLEX_FULL, TLan_FinishReset(), TLAN_HASH_2, TLAN_HC_AD_RST, TLAN_HC_INT_OFF, TLAN_HC_LD_THR, TLAN_HC_LD_TMR, TLAN_HOST_CMD, TLAN_ID_RX_EOC, TLAN_ID_TX_EOC, TLAN_INT_DIS, TLAN_NET_CFG_1CHAN, TLAN_NET_CFG_1FRAG, TLAN_NET_CFG_BIT, TLAN_NET_CFG_PHY_EN, TLAN_NET_CONFIG, TLAN_NET_SIO, TLAN_NET_SIO_NMRST, TLan_PhyDetect(), TLan_PhyPowerDown(), TLan_SetBit, tlan_private::tlanFullDuplex, tlan_private::tlanRev, TRUE, and udelay().

Referenced by tlan_probe().

{
        int i;
        u32 addr;
        u32 data;
        u8 data8;

        priv->tlanFullDuplex = FALSE;
        priv->phyOnline = 0;
/*  1.  Assert reset bit. */

        data = inl(BASE + TLAN_HOST_CMD);
        data |= TLAN_HC_AD_RST;
        outl(data, BASE + TLAN_HOST_CMD);

        udelay(1000);

/*  2.  Turn off interrupts. ( Probably isn't necessary ) */

        data = inl(BASE + TLAN_HOST_CMD);
        data |= TLAN_HC_INT_OFF;
        outl(data, BASE + TLAN_HOST_CMD);
/*  3.  Clear AREGs and HASHs. */

        for (i = TLAN_AREG_0; i <= TLAN_HASH_2; i += 4) {
                TLan_DioWrite32(BASE, (u16) i, 0);
        }

/*  4.  Setup NetConfig register. */

        data =
            TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;
        TLan_DioWrite16(BASE, TLAN_NET_CONFIG, (u16) data);

/*  5.  Load Ld_Tmr and Ld_Thr in HOST_CMD. */

        outl(TLAN_HC_LD_TMR | 0x3f, BASE + TLAN_HOST_CMD);
        outl(TLAN_HC_LD_THR | 0x0, BASE + TLAN_HOST_CMD);

/*  6.  Unreset the MII by setting NMRST (in NetSio) to 1. */

        outw(TLAN_NET_SIO, BASE + TLAN_DIO_ADR);
        addr = BASE + TLAN_DIO_DATA + TLAN_NET_SIO;
        TLan_SetBit(TLAN_NET_SIO_NMRST, addr);

/*  7.  Setup the remaining registers. */

        if (priv->tlanRev >= 0x30) {
                data8 = TLAN_ID_TX_EOC | TLAN_ID_RX_EOC;
                TLan_DioWrite8(BASE, TLAN_INT_DIS, data8);
        }
        TLan_PhyDetect(nic);
        data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN;

        if (tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_BIT_RATE_PHY) {
                data |= TLAN_NET_CFG_BIT;
                if (priv->aui == 1) {
                        TLan_DioWrite8(BASE, TLAN_ACOMMIT, 0x0a);
                } else if (priv->duplex == TLAN_DUPLEX_FULL) {
                        TLan_DioWrite8(BASE, TLAN_ACOMMIT, 0x00);
                        priv->tlanFullDuplex = TRUE;
                } else {
                        TLan_DioWrite8(BASE, TLAN_ACOMMIT, 0x08);
                }
        }

        if (priv->phyNum == 0) {
                data |= TLAN_NET_CFG_PHY_EN;
        }
        TLan_DioWrite16(BASE, TLAN_NET_CONFIG, (u16) data);

        if (tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_UNMANAGED_PHY) {
                TLan_FinishReset(nic);
        } else {
                TLan_PhyPowerDown(nic);
        }

}       /* TLan_ResetAdapter */
static void TLan_FinishReset ( struct nic *nic  __unused) [static]
void TLan_EeSendStart ( u16  io_base) [static]
int TLan_EeSendByte ( u16  io_base,
u8  data,
int  stop 
) [static]

Definition at line 921 of file tlan.c.

References outw(), TLan_ClearBit, TLAN_DIO_ADR, TLAN_DIO_DATA, TLan_GetBit, TLAN_NET_SIO, TLAN_NET_SIO_ECLOK, TLAN_NET_SIO_EDATA, TLAN_NET_SIO_ETXEN, and TLan_SetBit.

Referenced by TLan_EeReadByte().

{
        int err;
        u8 place;
        u16 sio;

        outw(TLAN_NET_SIO, io_base + TLAN_DIO_ADR);
        sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;

        /* Assume clock is low, tx is enabled; */
        for (place = 0x80; place != 0; place >>= 1) {
                if (place & data)
                        TLan_SetBit(TLAN_NET_SIO_EDATA, sio);
                else
                        TLan_ClearBit(TLAN_NET_SIO_EDATA, sio);
                TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
                TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio);
        }
        TLan_ClearBit(TLAN_NET_SIO_ETXEN, sio);
        TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
        err = TLan_GetBit(TLAN_NET_SIO_EDATA, sio);
        TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio);
        TLan_SetBit(TLAN_NET_SIO_ETXEN, sio);

        if ((!err) && stop) {
                TLan_ClearBit(TLAN_NET_SIO_EDATA, sio); /* STOP, raise data while clock is high */
                TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
                TLan_SetBit(TLAN_NET_SIO_EDATA, sio);
        }

        return (err);

}       /* TLan_EeSendByte */
void TLan_EeReceiveByte ( u16  io_base,
u8 data,
int  stop 
) [static]

Definition at line 979 of file tlan.c.

References outw(), TLan_ClearBit, TLAN_DIO_ADR, TLAN_DIO_DATA, TLan_GetBit, TLAN_NET_SIO, TLAN_NET_SIO_ECLOK, TLAN_NET_SIO_EDATA, TLAN_NET_SIO_ETXEN, and TLan_SetBit.

Referenced by TLan_EeReadByte().

{
        u8 place;
        u16 sio;

        outw(TLAN_NET_SIO, io_base + TLAN_DIO_ADR);
        sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;
        *data = 0;

        /* Assume clock is low, tx is enabled; */
        TLan_ClearBit(TLAN_NET_SIO_ETXEN, sio);
        for (place = 0x80; place; place >>= 1) {
                TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
                if (TLan_GetBit(TLAN_NET_SIO_EDATA, sio))
                        *data |= place;
                TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio);
        }

        TLan_SetBit(TLAN_NET_SIO_ETXEN, sio);
        if (!stop) {
                TLan_ClearBit(TLAN_NET_SIO_EDATA, sio); /* Ack = 0 */
                TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
                TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio);
        } else {
                TLan_SetBit(TLAN_NET_SIO_EDATA, sio);   /* No ack = 1 (?) */
                TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
                TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio);
                TLan_ClearBit(TLAN_NET_SIO_EDATA, sio); /* STOP, raise data while clock is high */
                TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
                TLan_SetBit(TLAN_NET_SIO_EDATA, sio);
        }

}       /* TLan_EeReceiveByte */
int TLan_EeReadByte ( u16  io_base,
u8  ee_addr,
u8 data 
) [static]

Definition at line 1034 of file tlan.c.

References ret, TLAN_EEPROM_ACK, TLAN_EEPROM_STOP, TLan_EeReceiveByte(), TLan_EeSendByte(), and TLan_EeSendStart().

Referenced by tlan_probe().

{
        int err;
        int ret = 0;


        TLan_EeSendStart(io_base);
        err = TLan_EeSendByte(io_base, 0xA0, TLAN_EEPROM_ACK);
        if (err) {
                ret = 1;
                goto fail;
        }
        err = TLan_EeSendByte(io_base, ee_addr, TLAN_EEPROM_ACK);
        if (err) {
                ret = 2;
                goto fail;
        }
        TLan_EeSendStart(io_base);
        err = TLan_EeSendByte(io_base, 0xA1, TLAN_EEPROM_ACK);
        if (err) {
                ret = 3;
                goto fail;
        }
        TLan_EeReceiveByte(io_base, data, TLAN_EEPROM_STOP);
      fail:

        return ret;

}       /* TLan_EeReadByte */
void TLan_PhyDetect ( struct nic nic) [static]

Definition at line 1341 of file tlan.c.

References chip_idx, control, flags, MII_BMCR, MII_PHYSID1, MII_PHYSID2, tlan_private::phy, phy, tlan_private::phyNum, printf(), TLAN_ADAPTER_UNMANAGED_PHY, TLan_MiiReadReg(), TLAN_PHY_MAX_ADDR, and TLAN_PHY_NONE.

Referenced by TLan_ResetAdapter().

{
        u16 control;
        u16 hi;
        u16 lo;
        u32 phy;

        if (tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_UNMANAGED_PHY) {
                priv->phyNum = 0xFFFF;
                return;
        }

        TLan_MiiReadReg(nic, TLAN_PHY_MAX_ADDR, MII_PHYSID1, &hi);

        if (hi != 0xFFFF) {
                priv->phy[0] = TLAN_PHY_MAX_ADDR;
        } else {
                priv->phy[0] = TLAN_PHY_NONE;
        }

        priv->phy[1] = TLAN_PHY_NONE;
        for (phy = 0; phy <= TLAN_PHY_MAX_ADDR; phy++) {
                TLan_MiiReadReg(nic, phy, MII_BMCR, &control);
                TLan_MiiReadReg(nic, phy, MII_PHYSID1, &hi);
                TLan_MiiReadReg(nic, phy, MII_PHYSID2, &lo);
                if ((control != 0xFFFF) || (hi != 0xFFFF)
                    || (lo != 0xFFFF)) {
                        printf("PHY found at %hX %hX %hX %hX\n", 
                               (unsigned int) phy, control, hi, lo);
                        if ((priv->phy[1] == TLAN_PHY_NONE)
                            && (phy != TLAN_PHY_MAX_ADDR)) {
                                priv->phy[1] = phy;
                        }
                }
        }

        if (priv->phy[1] != TLAN_PHY_NONE) {
                priv->phyNum = 1;
        } else if (priv->phy[0] != TLAN_PHY_NONE) {
                priv->phyNum = 0;
        } else {
                printf
                    ("TLAN:  Cannot initialize device, no PHY was found!\n");
        }

}                               /* TLan_PhyDetect */
void TLan_PhyPowerDown ( struct nic nic) [static]

Definition at line 1388 of file tlan.c.

References BASE, BMCR_ISOLATE, BMCR_LOOPBACK, BMCR_PDOWN, chip_idx, DBG, flags, mdelay(), MII_BMCR, tlan_private::nic_name, tlan_private::phy, tlan_private::phyNum, TLAN_ADAPTER_USE_INTERN_10, TLan_MiiSync(), TLan_MiiWriteReg(), TLAN_PHY_NONE, TLan_PhyPowerUp(), and value.

Referenced by TLan_PhyFinishAutoNeg(), TLan_PhyStartLink(), and TLan_ResetAdapter().

{

        u16 value;
        DBG ( "%s: Powering down PHY(s).\n", priv->nic_name );
        value = BMCR_PDOWN | BMCR_LOOPBACK | BMCR_ISOLATE;
        TLan_MiiSync(BASE);
        TLan_MiiWriteReg(nic, priv->phy[priv->phyNum], MII_BMCR, value);
        if ((priv->phyNum == 0) && (priv->phy[1] != TLAN_PHY_NONE)
            &&
            (!(tlan_pci_tbl[chip_idx].
               flags & TLAN_ADAPTER_USE_INTERN_10))) {
                TLan_MiiSync(BASE);
                TLan_MiiWriteReg(nic, priv->phy[1], MII_BMCR, value);
        }

        /* Wait for 50 ms and powerup
         * This is abitrary.  It is intended to make sure the
         * tranceiver settles.
         */
        /* TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_PUP ); */
        mdelay(50);
        TLan_PhyPowerUp(nic);

}                               /* TLan_PhyPowerDown */
void TLan_PhyPowerUp ( struct nic nic) [static]

Definition at line 1415 of file tlan.c.

References BASE, BMCR_LOOPBACK, DBG, mdelay(), MII_BMCR, tlan_private::nic_name, tlan_private::phy, tlan_private::phyNum, TLan_MiiSync(), TLan_MiiWriteReg(), TLan_PhyReset(), and value.

Referenced by TLan_PhyPowerDown().

{
        u16 value;

        DBG ( "%s: Powering up PHY.\n", priv->nic_name );
        TLan_MiiSync(BASE);
        value = BMCR_LOOPBACK;
        TLan_MiiWriteReg(nic, priv->phy[priv->phyNum], MII_BMCR, value);
        TLan_MiiSync(BASE);
        /* Wait for 500 ms and reset the
         * tranceiver.  The TLAN docs say both 50 ms and
         * 500 ms, so do the longer, just in case.
         */
        mdelay(500);
        TLan_PhyReset(nic);
        /* TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_RESET ); */

}                               /* TLan_PhyPowerUp */
void TLan_SetMac ( struct nic *nic  __unused,
int  areg,
unsigned char *  mac 
) [static]

Definition at line 1307 of file tlan.c.

References BASE, NULL, TLAN_AREG_0, and TLan_DioWrite8().

Referenced by TLan_FinishReset(), and TLan_SetMulticastList().

{
        int i;

        areg *= 6;

        if (mac != NULL) {
                for (i = 0; i < 6; i++)
                        TLan_DioWrite8(BASE, TLAN_AREG_0 + areg + i,
                                       mac[i]);
        } else {
                for (i = 0; i < 6; i++)
                        TLan_DioWrite8(BASE, TLAN_AREG_0 + areg + i, 0);
        }

}                               /* TLan_SetMac */
void TLan_PhyReset ( struct nic nic) [static]

Definition at line 1434 of file tlan.c.

References BASE, BMCR_LOOPBACK, BMCR_RESET, DBG, mdelay(), MII_BMCR, tlan_private::nic_name, tlan_private::phy, phy, tlan_private::phyNum, TLan_MiiReadReg(), TLan_MiiSync(), TLan_MiiWriteReg(), TLan_PhyStartLink(), and value.

Referenced by TLan_PhyPowerUp().

{
        u16 phy;
        u16 value;

        phy = priv->phy[priv->phyNum];

        DBG ( "%s: Reseting PHY.\n", priv->nic_name );
        TLan_MiiSync(BASE);
        value = BMCR_LOOPBACK | BMCR_RESET;
        TLan_MiiWriteReg(nic, phy, MII_BMCR, value);
        TLan_MiiReadReg(nic, phy, MII_BMCR, &value);
        while (value & BMCR_RESET) {
                TLan_MiiReadReg(nic, phy, MII_BMCR, &value);
        }

        /* Wait for 500 ms and initialize.
         * I don't remember why I wait this long.
         * I've changed this to 50ms, as it seems long enough.
         */
        /* TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_START_LINK ); */
        mdelay(50);
        TLan_PhyStartLink(nic);

}                               /* TLan_PhyReset */
void TLan_PhyStartLink ( struct nic nic) [static]

Definition at line 1461 of file tlan.c.

References tlan_private::aui, BASE, BMCR_FULLDPLX, BMCR_SPEED100, BMSR_ANEGCAPABLE, control, data, DBG, tlan_private::duplex, mdelay(), MII_ADVERTISE, MII_BMCR, MII_BMSR, tlan_private::nic_name, tlan_private::phy, phy, tlan_private::phyNum, tlan_private::speed, status, TLan_DioWrite16(), TLAN_DUPLEX_FULL, TLAN_DUPLEX_HALF, TLan_FinishReset(), TLan_MiiReadReg(), TLan_MiiWriteReg(), TLAN_NET_CFG_1CHAN, TLAN_NET_CFG_1FRAG, TLAN_NET_CFG_PHY_EN, TLAN_NET_CONFIG, TLan_PhyFinishAutoNeg(), TLan_PhyPowerDown(), TLAN_SPEED_10, TLAN_SPEED_100, TLAN_TC_AUISEL, TLAN_TLPHY_CTL, tlan_private::tlanFullDuplex, and TRUE.

Referenced by TLan_PhyReset().

{

        u16 ability;
        u16 control;
        u16 data;
        u16 phy;
        u16 status;
        u16 tctl;

        phy = priv->phy[priv->phyNum];
        DBG ( "%s: Trying to activate link.\n", priv->nic_name );
        TLan_MiiReadReg(nic, phy, MII_BMSR, &status);
        TLan_MiiReadReg(nic, phy, MII_BMSR, &ability);

        if ((status & BMSR_ANEGCAPABLE) && (!priv->aui)) {
                ability = status >> 11;
                if (priv->speed == TLAN_SPEED_10 &&
                    priv->duplex == TLAN_DUPLEX_HALF) {
                        TLan_MiiWriteReg(nic, phy, MII_BMCR, 0x0000);
                } else if (priv->speed == TLAN_SPEED_10 &&
                           priv->duplex == TLAN_DUPLEX_FULL) {
                        priv->tlanFullDuplex = TRUE;
                        TLan_MiiWriteReg(nic, phy, MII_BMCR, 0x0100);
                } else if (priv->speed == TLAN_SPEED_100 &&
                           priv->duplex == TLAN_DUPLEX_HALF) {
                        TLan_MiiWriteReg(nic, phy, MII_BMCR, 0x2000);
                } else if (priv->speed == TLAN_SPEED_100 &&
                           priv->duplex == TLAN_DUPLEX_FULL) {
                        priv->tlanFullDuplex = TRUE;
                        TLan_MiiWriteReg(nic, phy, MII_BMCR, 0x2100);
                } else {

                        /* Set Auto-Neg advertisement */
                        TLan_MiiWriteReg(nic, phy, MII_ADVERTISE,
                                         (ability << 5) | 1);
                        /* Enablee Auto-Neg */
                        TLan_MiiWriteReg(nic, phy, MII_BMCR, 0x1000);
                        /* Restart Auto-Neg */
                        TLan_MiiWriteReg(nic, phy, MII_BMCR, 0x1200);
                        /* Wait for 4 sec for autonegotiation
                         * to complete.  The max spec time is less than this
                         * but the card need additional time to start AN.
                         * .5 sec should be plenty extra.
                         */
                        DBG ( "TLAN: %s: Starting autonegotiation.\n",
                               priv->nic_name );
                        mdelay(4000);
                        TLan_PhyFinishAutoNeg(nic);
                        /* TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_PHY_FINISH_AN ); */
                        return;
                }

        }

        if ((priv->aui) && (priv->phyNum != 0)) {
                priv->phyNum = 0;
                data =
                    TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN |
                    TLAN_NET_CFG_PHY_EN;
                TLan_DioWrite16(BASE, TLAN_NET_CONFIG, data);
                mdelay(50);
                /* TLan_SetTimer( dev, (40*HZ/1000), TLAN_TIMER_PHY_PDOWN ); */
                TLan_PhyPowerDown(nic);
                return;
        } else if (priv->phyNum == 0) {
                control = 0;
                TLan_MiiReadReg(nic, phy, TLAN_TLPHY_CTL, &tctl);
                if (priv->aui) {
                        tctl |= TLAN_TC_AUISEL;
                } else {
                        tctl &= ~TLAN_TC_AUISEL;
                        if (priv->duplex == TLAN_DUPLEX_FULL) {
                                control |= BMCR_FULLDPLX;
                                priv->tlanFullDuplex = TRUE;
                        }
                        if (priv->speed == TLAN_SPEED_100) {
                                control |= BMCR_SPEED100;
                        }
                }
                TLan_MiiWriteReg(nic, phy, MII_BMCR, control);
                TLan_MiiWriteReg(nic, phy, TLAN_TLPHY_CTL, tctl);
        }

        /* Wait for 2 sec to give the tranceiver time
         * to establish link.
         */
        /* TLan_SetTimer( dev, (4*HZ), TLAN_TIMER_FINISH_RESET ); */
        mdelay(2000);
        TLan_FinishReset(nic);

}                               /* TLan_PhyStartLink */
void TLan_PhyFinishAutoNeg ( struct nic nic) [static]

Definition at line 1554 of file tlan.c.

References BASE, BMCR_ANENABLE, BMCR_FULLDPLX, BMSR_ANEGCOMPLETE, chip_idx, data, DBG, tlan_private::duplex, flags, mdelay(), MII_ADVERTISE, MII_BMCR, MII_BMSR, MII_LPA, tlan_private::neg_be_verbose, tlan_private::nic_name, tlan_private::phy, phy, tlan_private::phyNum, printf(), status, TLAN_ADAPTER_USE_INTERN_10, TLan_DioWrite16(), TLAN_DUPLEX_FULL, TLan_FinishReset(), TLan_MiiReadReg(), TLan_MiiWriteReg(), TLAN_NET_CFG_1CHAN, TLAN_NET_CFG_1FRAG, TLAN_NET_CFG_PHY_EN, TLAN_NET_CONFIG, TLan_PhyPowerDown(), tlan_private::tlanFullDuplex, TRUE, and udelay().

Referenced by TLan_PhyStartLink().

{

        u16 an_adv;
        u16 an_lpa;
        u16 data;
        u16 mode;
        u16 phy;
        u16 status;

        phy = priv->phy[priv->phyNum];

        TLan_MiiReadReg(nic, phy, MII_BMSR, &status);
        udelay(1000);
        TLan_MiiReadReg(nic, phy, MII_BMSR, &status);

        if (!(status & BMSR_ANEGCOMPLETE)) {
                /* Wait for 8 sec to give the process
                 * more time.  Perhaps we should fail after a while.
                 */
                if (!priv->neg_be_verbose++) {
                        printf
                            ("TLAN:  Giving autonegotiation more time.\n");
                        printf
                            ("TLAN:  Please check that your adapter has\n");
                        printf
                            ("TLAN:  been properly connected to a HUB or Switch.\n");
                        printf
                            ("TLAN:  Trying to establish link in the background...\n");
                }
                mdelay(8000);
                TLan_PhyFinishAutoNeg(nic);
                /* TLan_SetTimer( dev, (8*HZ), TLAN_TIMER_PHY_FINISH_AN ); */
                return;
        }

        DBG ( "TLAN: %s: Autonegotiation complete.\n", priv->nic_name );
        TLan_MiiReadReg(nic, phy, MII_ADVERTISE, &an_adv);
        TLan_MiiReadReg(nic, phy, MII_LPA, &an_lpa);
        mode = an_adv & an_lpa & 0x03E0;
        if (mode & 0x0100) {
                printf("Full Duplex\n");
                priv->tlanFullDuplex = TRUE;
        } else if (!(mode & 0x0080) && (mode & 0x0040)) {
                priv->tlanFullDuplex = TRUE;
                printf("Full Duplex\n");
        }

        if ((!(mode & 0x0180))
            && (tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_USE_INTERN_10)
            && (priv->phyNum != 0)) {
                priv->phyNum = 0;
                data =
                    TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN |
                    TLAN_NET_CFG_PHY_EN;
                TLan_DioWrite16(BASE, TLAN_NET_CONFIG, data);
                /* TLan_SetTimer( nic, (400*HZ/1000), TLAN_TIMER_PHY_PDOWN ); */
                mdelay(400);
                TLan_PhyPowerDown(nic);
                return;
        }

        if (priv->phyNum == 0) {
                if ((priv->duplex == TLAN_DUPLEX_FULL)
                    || (an_adv & an_lpa & 0x0040)) {
                        TLan_MiiWriteReg(nic, phy, MII_BMCR,
                                         BMCR_ANENABLE | BMCR_FULLDPLX);
                        DBG 
                            ( "TLAN:  Starting internal PHY with FULL-DUPLEX\n" );
                } else {
                        TLan_MiiWriteReg(nic, phy, MII_BMCR,
                                         BMCR_ANENABLE);
                        DBG 
                            ( "TLAN:  Starting internal PHY with HALF-DUPLEX\n" );
                }
        }

        /* Wait for 100 ms.  No reason in partiticular.
         */
        /* TLan_SetTimer( dev, (HZ/10), TLAN_TIMER_FINISH_RESET ); */
        mdelay(100);
        TLan_FinishReset(nic);

}                               /* TLan_PhyFinishAutoNeg */
static void refill_rx ( struct nic *nic  __unused) [static]
int TLan_MiiReadReg ( struct nic *nic  __unused,
u16  phy,
u16  reg,
u16 val 
) [static]

Definition at line 1101 of file tlan.c.

References BASE, FALSE, outw(), TLan_ClearBit, TLAN_DIO_ADR, TLAN_DIO_DATA, TLan_GetBit, TLan_MiiSendData(), TLan_MiiSync(), TLAN_NET_SIO, TLAN_NET_SIO_MCLK, TLAN_NET_SIO_MDATA, TLAN_NET_SIO_MINTEN, TLAN_NET_SIO_MTXEN, TLan_SetBit, and TRUE.

Referenced by TLan_FinishReset(), TLan_PhyDetect(), TLan_PhyFinishAutoNeg(), TLan_PhyReset(), and TLan_PhyStartLink().

{
        u8 nack;
        u16 sio, tmp;
        u32 i;
        int err;
        int minten;

        err = FALSE;
        outw(TLAN_NET_SIO, BASE + TLAN_DIO_ADR);
        sio = BASE + TLAN_DIO_DATA + TLAN_NET_SIO;

        TLan_MiiSync(BASE);

        minten = TLan_GetBit(TLAN_NET_SIO_MINTEN, sio);
        if (minten)
                TLan_ClearBit(TLAN_NET_SIO_MINTEN, sio);

        TLan_MiiSendData(BASE, 0x1, 2); /* Start ( 01b ) */
        TLan_MiiSendData(BASE, 0x2, 2); /* Read  ( 10b ) */
        TLan_MiiSendData(BASE, phy, 5); /* Device #      */
        TLan_MiiSendData(BASE, reg, 5); /* Register #    */


        TLan_ClearBit(TLAN_NET_SIO_MTXEN, sio); /* Change direction */

        TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);  /* Clock Idle bit */
        TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
        TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);  /* Wait 300ns */

        nack = TLan_GetBit(TLAN_NET_SIO_MDATA, sio);    /* Check for ACK */
        TLan_SetBit(TLAN_NET_SIO_MCLK, sio);    /* Finish ACK */
        if (nack) {             /* No ACK, so fake it */
                for (i = 0; i < 16; i++) {
                        TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);
                        TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
                }
                tmp = 0xffff;
                err = TRUE;
        } else {                /* ACK, so read data */
                for (tmp = 0, i = 0x8000; i; i >>= 1) {
                        TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);
                        if (TLan_GetBit(TLAN_NET_SIO_MDATA, sio))
                                tmp |= i;
                        TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
                }
        }


        TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);  /* Idle cycle */
        TLan_SetBit(TLAN_NET_SIO_MCLK, sio);

        if (minten)
                TLan_SetBit(TLAN_NET_SIO_MINTEN, sio);

        *val = tmp;

        return err;

}                               /* TLan_MiiReadReg */
void TLan_MiiSendData ( u16  base_port,
u32  data,
unsigned  num_bits 
) [static]

Definition at line 1180 of file tlan.c.

References outw(), TLan_ClearBit, TLAN_DIO_ADR, TLAN_DIO_DATA, TLan_GetBit, TLAN_NET_SIO, TLAN_NET_SIO_MCLK, TLAN_NET_SIO_MDATA, TLAN_NET_SIO_MTXEN, and TLan_SetBit.

Referenced by TLan_MiiReadReg(), and TLan_MiiWriteReg().

{
        u16 sio;
        u32 i;

        if (num_bits == 0)
                return;

        outw(TLAN_NET_SIO, base_port + TLAN_DIO_ADR);
        sio = base_port + TLAN_DIO_DATA + TLAN_NET_SIO;
        TLan_SetBit(TLAN_NET_SIO_MTXEN, sio);

        for (i = (0x1 << (num_bits - 1)); i; i >>= 1) {
                TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);
                (void) TLan_GetBit(TLAN_NET_SIO_MCLK, sio);
                if (data & i)
                        TLan_SetBit(TLAN_NET_SIO_MDATA, sio);
                else
                        TLan_ClearBit(TLAN_NET_SIO_MDATA, sio);
                TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
                (void) TLan_GetBit(TLAN_NET_SIO_MCLK, sio);
        }

}                               /* TLan_MiiSendData */
void TLan_MiiSync ( u16  base_port) [static]
void TLan_MiiWriteReg ( struct nic *nic  __unused,
u16  phy,
u16  reg,
u16  val 
) [static]

Definition at line 1255 of file tlan.c.

References BASE, outw(), TLan_ClearBit, TLAN_DIO_ADR, TLAN_DIO_DATA, TLan_GetBit, TLan_MiiSendData(), TLan_MiiSync(), TLAN_NET_SIO, TLAN_NET_SIO_MCLK, TLAN_NET_SIO_MINTEN, and TLan_SetBit.

Referenced by TLan_FinishReset(), TLan_PhyFinishAutoNeg(), TLan_PhyPowerDown(), TLan_PhyPowerUp(), TLan_PhyReset(), and TLan_PhyStartLink().

{
        u16 sio;
        int minten;

        outw(TLAN_NET_SIO, BASE + TLAN_DIO_ADR);
        sio = BASE + TLAN_DIO_DATA + TLAN_NET_SIO;

        TLan_MiiSync(BASE);

        minten = TLan_GetBit(TLAN_NET_SIO_MINTEN, sio);
        if (minten)
                TLan_ClearBit(TLAN_NET_SIO_MINTEN, sio);

        TLan_MiiSendData(BASE, 0x1, 2); /* Start ( 01b ) */
        TLan_MiiSendData(BASE, 0x1, 2); /* Write ( 01b ) */
        TLan_MiiSendData(BASE, phy, 5); /* Device #      */
        TLan_MiiSendData(BASE, reg, 5); /* Register #    */

        TLan_MiiSendData(BASE, 0x2, 2); /* Send ACK */
        TLan_MiiSendData(BASE, val, 16);        /* Send Data */

        TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);  /* Idle cycle */
        TLan_SetBit(TLAN_NET_SIO_MCLK, sio);

        if (minten)
                TLan_SetBit(TLAN_NET_SIO_MINTEN, sio);


}                               /* TLan_MiiWriteReg */
void TLan_FinishReset ( struct nic nic)

Definition at line 379 of file tlan.c.

References tlan_private::aui, BASE, BMSR_LSTATUS, chip_idx, data, DBG, flags, tlan_private::link, mdelay(), media, MII_BMSR, MII_LPA, MII_PHYSID1, MII_PHYSID2, NAT_SEM_ID1, NAT_SEM_ID2, tlan_private::nic_name, outb(), outl(), partner, tlan_private::phy, phy, tlan_private::phyNum, tlan_private::phyOnline, rx_ring, status, TLAN_ADAPTER_UNMANAGED_PHY, TLAN_CH_PARM, TLan_DioRead8(), TLan_DioWrite16(), TLan_DioWrite8(), TLan_FinishReset(), TLAN_HC_GO, TLAN_HC_INT_ON, TLAN_HC_RT, TLAN_HOST_CMD, TLAN_LED_LINK, TLAN_LED_REG, TLAN_MAX_RX, TLan_MiiReadReg(), TLan_MiiWriteReg(), TLAN_NET_CMD, TLAN_NET_CMD_DUPLEX, TLAN_NET_CMD_NRESET, TLAN_NET_CMD_NWRAP, TLAN_NET_MASK, TLAN_NET_MASK_MASK4, TLAN_NET_MASK_MASK5, TLAN_NET_MASK_MASK7, TLAN_NET_SIO, TLAN_NET_SIO_MINTEN, TLAN_PHY_AN_EN_STAT, TLAN_PHY_DUPLEX_FULL, TLAN_PHY_SPEED_100, TLan_SetMac(), TLAN_TC_INTEN, TLAN_TLPHY_CTL, TLAN_TLPHY_PAR, tlan_private::tlanFullDuplex, udelay(), and virt_to_bus().

{

        u8 data;
        u32 phy;
        u8 sio;
        u16 status;
        u16 partner;
        u16 tlphy_ctl;
        u16 tlphy_par;
        u16 tlphy_id1, tlphy_id2;
        int i;

        phy = priv->phy[priv->phyNum];

        data = TLAN_NET_CMD_NRESET | TLAN_NET_CMD_NWRAP;
        if (priv->tlanFullDuplex) {
                data |= TLAN_NET_CMD_DUPLEX;
        }
        TLan_DioWrite8(BASE, TLAN_NET_CMD, data);
        data = TLAN_NET_MASK_MASK4 | TLAN_NET_MASK_MASK5;
        if (priv->phyNum == 0) {
                data |= TLAN_NET_MASK_MASK7;
        }
        TLan_DioWrite8(BASE, TLAN_NET_MASK, data);
        TLan_DioWrite16(BASE, TLAN_MAX_RX, ((1536) + 7) & ~7);
        TLan_MiiReadReg(nic, phy, MII_PHYSID1, &tlphy_id1);
        TLan_MiiReadReg(nic, phy, MII_PHYSID2, &tlphy_id2);

        if ((tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_UNMANAGED_PHY)
            || (priv->aui)) {
                status = BMSR_LSTATUS;
                DBG ( "TLAN:  %s: Link forced.\n", priv->nic_name );
        } else {
                TLan_MiiReadReg(nic, phy, MII_BMSR, &status);
                udelay(1000);
                TLan_MiiReadReg(nic, phy, MII_BMSR, &status);
                if ((status & BMSR_LSTATUS) &&  /* We only support link info on Nat.Sem. PHY's */
                    (tlphy_id1 == NAT_SEM_ID1)
                    && (tlphy_id2 == NAT_SEM_ID2)) {
                        TLan_MiiReadReg(nic, phy, MII_LPA, &partner);
                        TLan_MiiReadReg(nic, phy, TLAN_TLPHY_PAR,
                                        &tlphy_par);

                        DBG ( "TLAN: %s: Link active with ",
                               priv->nic_name );
                        if (!(tlphy_par & TLAN_PHY_AN_EN_STAT)) {
                                DBG ( "forced 10%sMbps %s-Duplex\n",
                                       tlphy_par & TLAN_PHY_SPEED_100 ? ""
                                       : "0",
                                       tlphy_par & TLAN_PHY_DUPLEX_FULL ?
                                       "Full" : "Half" );
                        } else {
                                DBG 
                                    ( "AutoNegotiation enabled, at 10%sMbps %s-Duplex\n",
                                     tlphy_par & TLAN_PHY_SPEED_100 ? "" :
                                     "0",
                                     tlphy_par & TLAN_PHY_DUPLEX_FULL ?
                                     "Full" : "Half" );
                                DBG ( "TLAN: Partner capability: " );
                                for (i = 5; i <= 10; i++)
                                        if (partner & (1 << i)) {
                                                DBG ( "%s", media[i - 5] );
                                        }
                                DBG ( "\n" );
                        }

                        TLan_DioWrite8(BASE, TLAN_LED_REG, TLAN_LED_LINK);
#ifdef MONITOR
                        /* We have link beat..for now anyway */
                        priv->link = 1;
                        /*Enabling link beat monitoring */
                        /* TLan_SetTimer( nic, (10*HZ), TLAN_TIMER_LINK_BEAT ); */
                        mdelay(10000);
                        TLan_PhyMonitor(nic);
#endif
                } else if (status & BMSR_LSTATUS) {
                        DBG ( "TLAN: %s: Link active\n", priv->nic_name );
                        TLan_DioWrite8(BASE, TLAN_LED_REG, TLAN_LED_LINK);
                }
        }

        if (priv->phyNum == 0) {
                TLan_MiiReadReg(nic, phy, TLAN_TLPHY_CTL, &tlphy_ctl);
                tlphy_ctl |= TLAN_TC_INTEN;
                TLan_MiiWriteReg(nic, phy, TLAN_TLPHY_CTL, tlphy_ctl);
                sio = TLan_DioRead8(BASE, TLAN_NET_SIO);
                sio |= TLAN_NET_SIO_MINTEN;
                TLan_DioWrite8(BASE, TLAN_NET_SIO, sio);
        }

        if (status & BMSR_LSTATUS) {
                TLan_SetMac(nic, 0, nic->node_addr);
                priv->phyOnline = 1;
                outb((TLAN_HC_INT_ON >> 8), BASE + TLAN_HOST_CMD + 1);
                outl(virt_to_bus(&rx_ring), BASE + TLAN_CH_PARM);
                outl(TLAN_HC_GO | TLAN_HC_RT, BASE + TLAN_HOST_CMD);
        } else {
                DBG 
                    ( "TLAN: %s: Link inactive, will retry in 10 secs...\n",
                     priv->nic_name );
                /* TLan_SetTimer( nic, (10*HZ), TLAN_TIMER_FINISH_RESET ); */
                mdelay(10000);
                TLan_FinishReset(nic);
                return;

        }

}       /* TLan_FinishReset */
static int tlan_poll ( struct nic nic,
int  retrieve 
) [static]

Definition at line 492 of file tlan.c.

References BASE, TLanList::cStat, tlan_private::cur_rx, DBG, entry, inw(), le32_to_cpu, memcpy(), outl(), outw(), refill_rx(), rx_ring, rxb, TLAN_CH_PARM, TLAN_CSTAT_EOC, TLAN_CSTAT_FRM_CMP, TLAN_CSTAT_READY, TLAN_HC_ACK, TLAN_HC_GO, TLAN_HC_RT, TLAN_HOST_CMD, TLAN_HOST_INT, TLAN_MAX_FRAME_SIZE, and TLAN_NUM_RX_LISTS.

{
        /* 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 */
        u32 framesize;
        u32 host_cmd = 0;
        u32 ack = 1;
        int eoc = 0;
        int entry = priv->cur_rx % TLAN_NUM_RX_LISTS;
        u16 tmpCStat = le32_to_cpu(rx_ring[entry].cStat);
        u16 host_int = inw(BASE + TLAN_HOST_INT);

        if ((tmpCStat & TLAN_CSTAT_FRM_CMP) && !retrieve)
          return 1;

        outw(host_int, BASE + TLAN_HOST_INT);

        if (!(tmpCStat & TLAN_CSTAT_FRM_CMP))
                return 0;

        /* printf("PI-1: 0x%hX\n", host_int); */
        if (tmpCStat & TLAN_CSTAT_EOC)
                eoc = 1;

        framesize = rx_ring[entry].frameSize;

        nic->packetlen = framesize;

        DBG ( ".%d.", (unsigned int) framesize ); 
     
        memcpy(nic->packet, rxb +
               (priv->cur_rx * TLAN_MAX_FRAME_SIZE), nic->packetlen);

        rx_ring[entry].cStat = 0;

        DBG ( "%d", entry );  

        entry = (entry + 1) % TLAN_NUM_RX_LISTS;
        priv->cur_rx = entry;
        if (eoc) {
                if ((rx_ring[entry].cStat & TLAN_CSTAT_READY) ==
                    TLAN_CSTAT_READY) {
                        ack |= TLAN_HC_GO | TLAN_HC_RT;
                        host_cmd = TLAN_HC_ACK | ack | 0x001C0000;
                        outl(host_cmd, BASE + TLAN_HOST_CMD);
                }
        } else {
                host_cmd = TLAN_HC_ACK | ack | (0x000C0000);
                outl(host_cmd, BASE + TLAN_HOST_CMD);
                
                DBG ( "AC: 0x%hX\n", inw(BASE + TLAN_CH_PARM) ); 
                DBG ( "PI-2: 0x%hX\n", inw(BASE + TLAN_HOST_INT) );
        }
        refill_rx(nic);
        return (1);             /* initially as this is called to flush the input */
}
static void tlan_transmit ( struct nic nic,
const char *  d,
unsigned int  t,
unsigned int  s,
const char *  p 
) [static]

Definition at line 568 of file tlan.c.

References TLanList::address, BASE, TLanList::buffer, CIRC_INC, TLanList::count, TLanList::cStat, currticks(), DBG, entry, ETH_ALEN, ETH_HLEN, ETH_ZLEN, TLanList::forward, TLanList::frameSize, htons, inw(), memcpy(), tlan_private::nic_name, outl(), tlan_private::phyOnline, printf(), TLAN_CH_PARM, TLAN_CSTAT_EOC, TLAN_CSTAT_FRM_CMP, TLAN_CSTAT_READY, TLAN_CSTAT_UNUSED, TLAN_HC_ACK, TLAN_HC_GO, TLAN_HOST_CMD, TLAN_HOST_INT, TLAN_LAST_BUFFER, TLAN_MAX_FRAME_SIZE, TLAN_NUM_TX_LISTS, tlan_private::tlanRev, tx_ring, TX_TIME_OUT, txb, tlan_private::txHead, tlan_private::txInProgress, tlan_private::txList, tlan_private::txTail, u16, and virt_to_le32desc.

{                               /* Packet */
        u16 nstype;
        u32 to;
        struct TLanList *tail_list;
        struct TLanList *head_list;
        u8 *tail_buffer;
        u32 ack = 0;
        u32 host_cmd;
        int eoc = 0;
        u16 tmpCStat;
        u16 host_int = inw(BASE + TLAN_HOST_INT);

        int entry = 0;

        DBG ( "INT0-0x%hX\n", host_int );

        if (!priv->phyOnline) {
                printf("TRANSMIT:  %s PHY is not ready\n", priv->nic_name);
                return;
        }

        tail_list = priv->txList + priv->txTail;

        if (tail_list->cStat != TLAN_CSTAT_UNUSED) {
                printf("TRANSMIT: %s is busy (Head=%p Tail=%x)\n",
                       priv->nic_name, priv->txList, (unsigned int) priv->txTail);
                tx_ring[entry].cStat = TLAN_CSTAT_UNUSED;
//              priv->txBusyCount++;
                return;
        }

        tail_list->forward = 0;

        tail_buffer = txb + (priv->txTail * TLAN_MAX_FRAME_SIZE);

        /* send the packet to destination */
        memcpy(tail_buffer, d, ETH_ALEN);
        memcpy(tail_buffer + ETH_ALEN, nic->node_addr, ETH_ALEN);
        nstype = htons((u16) t);
        memcpy(tail_buffer + 2 * ETH_ALEN, (u8 *) & nstype, 2);
        memcpy(tail_buffer + ETH_HLEN, p, s);

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

        /*=====================================================*/
        /* Receive
         * 0000 0000 0001 1100
         * 0000 0000 0000 1100
         * 0000 0000 0000 0011 = 0x0003
         *
         * 0000 0000 0000 0000 0000 0000 0000 0011
         * 0000 0000 0000 1100 0000 0000 0000 0000 = 0x000C0000
         *
         * Transmit
         * 0000 0000 0001 1100
         * 0000 0000 0000 0100
         * 0000 0000 0000 0001 = 0x0001
         *
         * 0000 0000 0000 0000 0000 0000 0000 0001
         * 0000 0000 0000 0100 0000 0000 0000 0000 = 0x00040000
         * */

        /* Setup the transmit descriptor */
        tail_list->frameSize = (u16) s;
        tail_list->buffer[0].count = TLAN_LAST_BUFFER | (u32) s;
        tail_list->buffer[1].count = 0;
        tail_list->buffer[1].address = 0;

        tail_list->cStat = TLAN_CSTAT_READY;

        DBG ( "INT1-0x%hX\n", inw(BASE + TLAN_HOST_INT) );

        if (!priv->txInProgress) {
                priv->txInProgress = 1;
                outl(virt_to_le32desc(tail_list), BASE + TLAN_CH_PARM);
                outl(TLAN_HC_GO, BASE + TLAN_HOST_CMD);
        } else {
                if (priv->txTail == 0) {
                        DBG ( "Out buffer\n" );
                        (priv->txList + (TLAN_NUM_TX_LISTS - 1))->forward =
                            virt_to_le32desc(tail_list);
                } else {
                        DBG ( "Fix this \n" );
                        (priv->txList + (priv->txTail - 1))->forward =
                            virt_to_le32desc(tail_list);
                }
        }
        
        CIRC_INC(priv->txTail, TLAN_NUM_TX_LISTS);

        DBG ( "INT2-0x%hX\n", inw(BASE + TLAN_HOST_INT) );

        to = currticks() + TX_TIME_OUT;
        while ((tail_list->cStat == TLAN_CSTAT_READY) && currticks() < to);

        head_list = priv->txList + priv->txHead;
        while (((tmpCStat = head_list->cStat) & TLAN_CSTAT_FRM_CMP) 
                        && (ack < 255)) {
                ack++;
                if(tmpCStat & TLAN_CSTAT_EOC)
                        eoc =1;
                head_list->cStat = TLAN_CSTAT_UNUSED;
                CIRC_INC(priv->txHead, TLAN_NUM_TX_LISTS);
                head_list = priv->txList + priv->txHead;
                
        }
        if(!ack)
                printf("Incomplete TX Frame\n");

        if(eoc) {
                head_list = priv->txList + priv->txHead;
                if ((head_list->cStat & TLAN_CSTAT_READY) == TLAN_CSTAT_READY) {
                        outl(virt_to_le32desc(head_list), BASE + TLAN_CH_PARM);
                        ack |= TLAN_HC_GO;
                } else {
                        priv->txInProgress = 0;
                }
        }
        if(ack) {
                host_cmd = TLAN_HC_ACK | ack;
                outl(host_cmd, BASE + TLAN_HOST_CMD);
        }
        
        if(priv->tlanRev < 0x30 ) {
                ack = 1;
                head_list = priv->txList + priv->txHead;
                if ((head_list->cStat & TLAN_CSTAT_READY) == TLAN_CSTAT_READY) {
                        outl(virt_to_le32desc(head_list), BASE + TLAN_CH_PARM);
                        ack |= TLAN_HC_GO;
                } else {
                        priv->txInProgress = 0;
                }
                host_cmd = TLAN_HC_ACK | ack | 0x00140000;
                outl(host_cmd, BASE + TLAN_HOST_CMD);
                
        }
                        
        if (currticks() >= to) {
                printf("TX Time Out");
        }
}
static void tlan_disable ( struct nic *nic  __unused) [static]

Definition at line 720 of file tlan.c.

References BASE, outl(), TLAN_HC_AD_RST, and TLAN_HOST_CMD.

                                                      {
        /* 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.
         *
         */
        outl(TLAN_HC_AD_RST, BASE + TLAN_HOST_CMD);
}
static void tlan_irq ( struct nic *nic  __unused,
irq_action_t action  __unused 
) [static]

Definition at line 738 of file tlan.c.

{
  switch ( action ) {
  case DISABLE :
    break;
  case ENABLE :
    break;
  case FORCE :
    break;
  }
}
static void TLan_SetMulticastList ( struct nic nic) [static]

Definition at line 758 of file tlan.c.

References BASE, NULL, TLan_DioRead8(), TLan_DioWrite32(), TLan_DioWrite8(), TLAN_HASH_1, TLAN_HASH_2, TLAN_NET_CMD, TLAN_NET_CMD_CAF, and TLan_SetMac().

Referenced by tlan_probe().

                                                   {
        int i;
        u8 tmp;

        /* !IFF_PROMISC */
        tmp = TLan_DioRead8(BASE, TLAN_NET_CMD);
        TLan_DioWrite8(BASE, TLAN_NET_CMD, tmp & ~TLAN_NET_CMD_CAF);

        /* IFF_ALLMULTI */
        for(i = 0; i< 3; i++)
                TLan_SetMac(nic, i + 1, NULL);
        TLan_DioWrite32(BASE, TLAN_HASH_1, 0xFFFFFFFF);
        TLan_DioWrite32(BASE, TLAN_HASH_2, 0xFFFFFFFF);

        
}
static int tlan_probe ( struct nic nic,
struct pci_device pci 
) [static]

Definition at line 780 of file tlan.c.

References adjust_pci_device(), BASE, chip_idx, data, DBG, tlan_private::dev_id, pci_device::device, tlan_private::eoc, eth_ntoa(), pci_id_info::id, pci_device::id, inl(), pci_device::ioaddr, pci_device_id::name, name, tlan_private::nic_name, outw(), pci_id_info::match_info::pci, printf(), TLAN_DEF_REVISION, TLan_DioRead8(), TLan_EeReadByte(), TLAN_HC_INT_OFF, TLAN_HOST_CMD, tlan_operations, TLan_ResetAdapter(), TLan_ResetLists(), TLan_SetMulticastList(), TLanPrivateInfo, tlan_private::tlanRev, tx_ring, tlan_private::txList, udelay(), pci_device::vendor, and tlan_private::vendor_id.

                                                                  {

        u16 data = 0;
        int err;
        int i;

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

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

        BASE = pci->ioaddr;

        /* Set nic as PCI bus master */
        adjust_pci_device(pci);
        
        /* Point to private storage */
        priv = &TLanPrivateInfo;

        /* Figure out which chip we're dealing with */
        i = 0;
        chip_idx = -1;
        while (tlan_pci_tbl[i].name) {
                if ((((u32) pci->device << 16) | pci->vendor) ==
                    (tlan_pci_tbl[i].id.pci & 0xffffffff)) {
                        chip_idx = i;
                        break;
                }
                i++;
        }
        if (chip_idx == -1)
                return 0;

        priv->vendor_id = pci->vendor;
        priv->dev_id = pci->device;
        priv->nic_name = pci->id->name;
        priv->eoc = 0;

        err = 0;
        for (i = 0; i < 6; i++)
                err |= TLan_EeReadByte(BASE,
                                       (u8) tlan_pci_tbl[chip_idx].
                                       addrOfs + i,
                                       (u8 *) & nic->node_addr[i]);
        if (err) {
            printf ( "TLAN: %s: Error reading MAC from eeprom: %d\n",
                    pci->id->name, err);
        } else {
            DBG ( "%s: %s at ioaddr %#lX, ", 
                  pci->id->name, eth_ntoa ( nic->node_addr ), pci->ioaddr );
        }

        priv->tlanRev = TLan_DioRead8(BASE, TLAN_DEF_REVISION);
        printf("revision: 0x%hX\n", priv->tlanRev);

        TLan_ResetLists(nic);
        TLan_ResetAdapter(nic);

        data = inl(BASE + TLAN_HOST_CMD);
        data |= TLAN_HC_INT_OFF;
        outw(data, BASE + TLAN_HOST_CMD);

        TLan_SetMulticastList(nic);
        udelay(100); 
        priv->txList = tx_ring;

/*      if (board_found && valid_link)
        {*/
        /* point to NIC specific routines */
        nic->nic_op     = &tlan_operations;
        return 1;
}
PCI_DRIVER ( tlan_driver  ,
tlan_nics  ,
PCI_NO_CLASS   
)
DRIVER ( "TLAN/PCI"  ,
nic_driver  ,
pci_driver  ,
tlan_driver  ,
tlan_probe  ,
tlan_disable   
)

Variable Documentation

const char* media[] [static]
Initial value:
 {
        "10BaseT-HD ", "10BaseT-FD ", "100baseTx-HD ",
        "100baseTx-FD", "100baseT4", NULL
}

Definition at line 95 of file tlan.c.

Referenced by TLan_FinishReset().

struct pci_id_info tlan_pci_tbl[] [static]

Definition at line 120 of file tlan.c.

Definition at line 183 of file tlan.c.

Definition at line 184 of file tlan.c.

Definition at line 185 of file tlan.c.

Definition at line 186 of file tlan.c.

struct { ... } __shared
int chip_idx [static]
struct tlan_private TLanPrivateInfo [static]

Referenced by tlan_probe().

struct tlan_private* priv [static]

Definition at line 224 of file tlan.c.

Referenced by atacmd_identify_done(), efidev_set_drvdata(), eisa_set_drvdata(), forcedeth_close(), forcedeth_irq(), forcedeth_link_status(), forcedeth_open(), forcedeth_poll(), forcedeth_probe(), forcedeth_remove(), forcedeth_transmit(), grf5101_rf_init(), grf5101_rf_set_channel(), grf5101_rf_stop(), grf5101_write_phy_antenna(), ib_cq_set_drvdata(), ib_madx_set_ownerdata(), ib_path_set_ownerdata(), ib_qp_set_drvdata(), ib_qp_set_ownerdata(), ib_set_drvdata(), ib_wq_set_drvdata(), ifec_check_ru_status(), ifec_free(), ifec_get_rx_desc(), ifec_init_eeprom(), ifec_mdio_read(), ifec_mdio_setup(), ifec_mdio_write(), ifec_net_close(), ifec_net_irq(), ifec_net_open(), ifec_net_poll(), ifec_net_transmit(), ifec_pci_probe(), ifec_refill_rx_ring(), ifec_reprime_ru(), ifec_reset(), ifec_rx_process(), ifec_rx_setup(), ifec_scb_cmd(), ifec_scb_cmd_wait(), ifec_spi_read_bit(), ifec_spi_write_bit(), ifec_tx_process(), ifec_tx_setup(), ifec_tx_wake(), isa_set_drvdata(), linux_set_drvdata(), max2820_rf_init(), max2820_rf_set_channel(), max2820_write_phy_antenna(), myri10ge_interrupt_handler(), myri10ge_net_close(), myri10ge_net_open(), myri10ge_net_poll(), myri10ge_net_transmit(), myri10ge_nvs_read(), myri10ge_nvs_write(), myri10ge_pci_probe(), nv_process_rx_packets(), nv_process_tx_packets(), pci_set_drvdata(), pcnet32_close(), pcnet32_irq(), pcnet32_mdio_read(), pcnet32_mdio_write(), pcnet32_open(), pcnet32_poll(), pcnet32_probe(), pcnet32_process_rx_packets(), pcnet32_process_tx_packets(), pcnet32_transmit(), rootdev_set_drvdata(), rtl818x_config(), rtl818x_free_rx_ring(), rtl818x_free_tx_ring(), rtl818x_handle_rx(), rtl818x_handle_tx(), rtl818x_init_hw(), rtl818x_init_rx_ring(), rtl818x_init_tx_ring(), rtl818x_irq(), rtl818x_poll(), rtl818x_probe(), rtl818x_set_hwaddr(), rtl818x_spi_read_bit(), rtl818x_spi_write_bit(), rtl818x_start(), rtl818x_stop(), rtl818x_tx(), rtl818x_write_phy(), rtl8225_read(), rtl8225_rf_conf_erp(), rtl8225_rf_init(), rtl8225_rf_set_channel(), rtl8225_rf_set_tx_power(), rtl8225_rf_stop(), rtl8225_write(), rtl8225x_rf_init(), rtl8225z2_rf_init(), rtl8225z2_rf_set_tx_power(), sa2400_rf_init(), sa2400_rf_set_channel(), sa2400_write_phy_antenna(), scsicmd_read_capacity_cmd(), scsicmd_read_capacity_done(), t509_set_drvdata(), undi_set_drvdata(), usb_bus_set_hostdata(), usb_endpoint_set_hostdata(), usb_func_set_drvdata(), usb_hub_set_drvdata(), usb_set_hostdata(), vmbus_set_drvdata(), write_grf5101(), write_max2820(), write_sa2400(), and xen_set_drvdata().

u32 BASE [static]
struct nic_operations tlan_operations [static]
Initial value:
 {
        .connect        = dummy_connect,
        .poll           = tlan_poll,
        .transmit       = tlan_transmit,
        .irq            = tlan_irq,

}

Definition at line 750 of file tlan.c.

Referenced by tlan_probe().

struct pci_device_id tlan_nics[] [static]
Initial value:
 {
        PCI_ROM(0x0e11, 0xae34, "netel10", "Compaq Netelligent 10 T PCI UTP", 0),
        PCI_ROM(0x0e11, 0xae32, "netel100","Compaq Netelligent 10/100 TX PCI UTP", 0),
        PCI_ROM(0x0e11, 0xae35, "netflex3i", "Compaq Integrated NetFlex-3/P", 0),
        PCI_ROM(0x0e11, 0xf130, "thunder", "Compaq NetFlex-3/P", 0),
        PCI_ROM(0x0e11, 0xf150, "netflex3b", "Compaq NetFlex-3/P", 0),
        PCI_ROM(0x0e11, 0xae43, "netel100pi", "Compaq Netelligent Integrated 10/100 TX UTP", 0),
        PCI_ROM(0x0e11, 0xae40, "netel100d", "Compaq Netelligent Dual 10/100 TX PCI UTP", 0),
        PCI_ROM(0x0e11, 0xb011, "netel100i", "Compaq Netelligent 10/100 TX Embedded UTP", 0),
        PCI_ROM(0x108d, 0x0013, "oc2183", "Olicom OC-2183/2185", 0),
        PCI_ROM(0x108d, 0x0012, "oc2325", "Olicom OC-2325", 0),
        PCI_ROM(0x108d, 0x0014, "oc2326", "Olicom OC-2326", 0),
        PCI_ROM(0x0e11, 0xb030, "netelligent_10_100_ws_5100", "Compaq Netelligent 10/100 TX UTP", 0),
        PCI_ROM(0x0e11, 0xb012, "netelligent_10_t2", "Compaq Netelligent 10 T/2 PCI UTP/Coax", 0),
}

Definition at line 1699 of file tlan.c.