tulip.c File Reference

#include "etherboot.h"
#include "nic.h"
#include <gpxe/ethernet.h>
#include <gpxe/pci.h>

Go to the source code of this file.

Data Structures

struct  pci_id_info
struct  pci_id_info::match_info
struct  tulip_chip_table
struct  medialeaf
struct  mediatable
struct  mediainfo
struct  tulip_rx_desc
struct  tulip_tx_desc
struct  tulip_private
struct  fixups

Defines

#define TX_TIME_OUT   2*TICKS_PER_SEC
#define get_unaligned(ptr)   (*(ptr))
#define put_unaligned(val, ptr)   ((void)( *(ptr) = (val) ))
#define get_u16(ptr)   (*(u16 *)(ptr))
#define virt_to_le32desc(addr)   virt_to_bus(addr)
#define TULIP_IOTYPE   PCI_USES_MASTER | PCI_USES_IO | PCI_ADDR0
#define TULIP_SIZE   0x80
#define FULL_DUPLEX_MAGIC   0x6969
#define MEDIA_MASK   31
#define EEPROM_ADDRLEN   6
#define EEPROM_SIZE   128
#define EE_WRITE_CMD   (5 << addr_len)
#define EE_READ_CMD   (6 << addr_len)
#define EE_ERASE_CMD   (7 << addr_len)
#define EE_SHIFT_CLK   0x02
#define EE_CS   0x01
#define EE_DATA_WRITE   0x04
#define EE_WRITE_0   0x01
#define EE_WRITE_1   0x05
#define EE_DATA_READ   0x08
#define EE_ENB   (0x4800 | EE_CS)
#define eeprom_delay()   inl(ee_addr)
#define BUFLEN   1536
#define DESC_RING_WRAP   0x02000000
#define TX_RING_SIZE   2
#define RX_RING_SIZE   4
#define tx_ring   tulip_bss.tx_ring
#define txb   tulip_bss.txb
#define rx_ring   tulip_bss.rx_ring
#define rxb   tulip_bss.rxb
#define mdio_delay()   inl(mdio_addr)
#define MDIO_SHIFT_CLK   0x10000
#define MDIO_DATA_WRITE0   0x00000
#define MDIO_DATA_WRITE1   0x20000
#define MDIO_ENB   0x00000
#define MDIO_ENB_IN   0x40000
#define MDIO_DATA_READ   0x80000

Enumerations

enum  tulip_chips {
  DC21040 = 0, DC21041 = 1, DC21140 = 2, DC21142 = 3,
  DC21143 = 3, LC82C168, MX98713, MX98715,
  MX98725, AX88141, AX88140, PNIC2,
  COMET, COMPEX9881, I21145, XIRCOM,
  SGThomson
}
enum  pci_id_flags_bits {
  PCI_USES_IO = 1, PCI_USES_MEM = 2, PCI_USES_MASTER = 4, PCI_ADDR0 = 0 << 4,
  PCI_ADDR1 = 1 << 4, PCI_ADDR2, PCI_ADDR3 = 3 << 4, PCI_USES_IO = 1,
  PCI_USES_MEM = 2, PCI_USES_MASTER = 4, PCI_ADDR0 = 0<<4, PCI_ADDR1 = 1<<4,
  PCI_ADDR2 = 2<<4, PCI_ADDR3 = 3<<4, PCI_ADDR_64BITS = 0x100, PCI_NO_ACPI_WAKE = 0x200,
  PCI_NO_MIN_LATENCY = 0x400, PCI_UNUSED_IRQ = 0x800
}
enum  tbl_flag {
  HAS_MII = 1, HAS_MEDIA_TABLE = 2, CSR12_IN_SROM = 4, ALWAYS_CHECK_MII = 8,
  HAS_PWRDWN = 0x10, MC_HASH_ONLY = 0x20, HAS_PNICNWAY = 0x80, HAS_NWAY = 0x40,
  HAS_INTR_MITIGATION = 0x100, IS_ASIX = 0x200, HAS_8023X = 0x400
}
enum  MediaIs {
  MediaIsFD = 1, MediaAlwaysFD = 2, MediaIsMII = 4, MediaIsFx = 8,
  MediaIs100 = 16
}
enum  tulip_offsets {
  CSR0 = 0, CSR1 = 0x08, CSR2 = 0x10, CSR3 = 0x18,
  CSR4 = 0x20, CSR5 = 0x28, CSR6 = 0x30, CSR7 = 0x38,
  CSR8 = 0x40, CSR9 = 0x48, CSR10 = 0x50, CSR11 = 0x58,
  CSR12 = 0x60, CSR13 = 0x68, CSR14 = 0x70, CSR15 = 0x78,
  CSR16 = 0x80, CSR20 = 0xA0
}
enum  status_bits {
  TimerInt = 0x800, TPLnkFail = 0x1000, TPLnkPass = 0x10, NormalIntr = 0x10000,
  AbnormalIntr = 0x8000, RxJabber = 0x200, RxDied = 0x100, RxNoBuf = 0x80,
  RxIntr = 0x40, TxFIFOUnderflow = 0x20, TxJabber = 0x08, TxNoBuf = 0x04,
  TxDied = 0x02, TxIntr = 0x01
}
enum  csr6_mode_bits {
  TxOn = 0x2000, RxOn = 0x0002, FullDuplex = 0x0200, AcceptBroadcast = 0x0100,
  AcceptAllMulticast = 0x0080, AcceptAllPhys = 0x0040, AcceptRunt = 0x0008
}
enum  desc_status_bits {
  DescOwn = 0x80000000, DescMore = 0x40000000, DescIntr = 0x20000000, DescNoCRC = 0x10000000,
  DescPktOK = 0x08000000, RxTooLong = 0x00400000, DescOwn = 0x8000, DescEndPacket = 0x4000,
  DescEndRing = 0x2000, LastFrag = 0x80000000, DescIntrOnTx = 0x8000, DescIntrOnDMADone = 0x80000000,
  DisableAlign = 0x00000001, DescOwnded = 0x80000000, RxDescFatalErr = 0x8000, RxWholePkt = 0x0300,
  DescOwn = 0x80000000, DescEndRing = 0x02000000, DescUseLink = 0x01000000, DescWholePkt = 0x60000000,
  DescStartPkt = 0x20000000, DescEndPkt = 0x40000000, DescIntr = 0x80000000
}

Functions

 FILE_LICENCE (GPL_ANY)
static int mdio_read (struct nic *nic, int phy_id, int location)
static void mdio_write (struct nic *nic, int phy_id, int location, int value)
static int read_eeprom (unsigned long ioaddr, int location, int addr_len)
static void parse_eeprom (struct nic *nic)
static int tulip_probe (struct nic *nic, struct pci_device *pci)
static void tulip_init_ring (struct nic *nic)
static void tulip_reset (struct nic *nic)
static void tulip_transmit (struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p)
static int tulip_poll (struct nic *nic, int retrieve)
static void tulip_disable (struct nic *nic)
static void nway_start (struct nic *nic)
static void pnic_do_nway (struct nic *nic)
static void select_media (struct nic *nic, int startup)
static void init_media (struct nic *nic)
static void start_link (struct nic *nic)
static int tulip_check_duplex (struct nic *nic)
static void tulip_wait (unsigned int nticks)
int mdio_read (struct nic *nic __unused, int phy_id, int location)
void mdio_write (struct nic *nic __unused, int phy_id, int location, int value)
static void tulip_init_ring (struct nic *nic __unused)
static void set_rx_mode (struct nic *nic __unused)
static void tulip_irq (struct nic *nic __unused, irq_action_t action __unused)
static void nway_start (struct nic *nic __unused)
static void pnic_do_nway (struct nic *nic __unused)
 PCI_DRIVER (tulip_driver, tulip_nics, PCI_NO_CLASS)
 DRIVER ("Tulip", nic_driver, pci_driver, tulip_driver, tulip_probe, tulip_disable)

Variables

static const int csr0 = 0x01A00000 | 0x8000
static const char *const medianame [32]
static struct pci_id_info pci_id_tbl []
static struct tulip_chip_table tulip_tbl []
static const char media_cap [32]
static u8 t21040_csr13 [] = {2,0x0C,8,4, 4,0,0,0, 0,0,0,0, 4,0,0,0}
static u16 t21041_csr13 [] = { 0xEF01, 0xEF09, 0xEF09, 0xEF01, 0xEF09, }
static u16 t21041_csr14 [] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, }
static u16 t21041_csr15 [] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }
static u16 t21142_csr14 [] = { 0xFFFF, 0x0705, 0x0705, 0x0000, 0x7F3D, }
static u32 ioaddr
struct {
   struct tulip_tx_desc   tx_ring [TX_RING_SIZE]
   unsigned char   txb [BUFLEN]
   struct tulip_rx_desc   rx_ring [RX_RING_SIZE]
   unsigned char   rxb [RX_RING_SIZE *BUFLEN]
   struct tulip_private   tpx
__shared
static struct tulip_privatetp
static struct fixups eeprom_fixups []
static const char * block_name []
static struct nic_operations tulip_operations
static struct pci_device_id tulip_nics []


Define Documentation

#define TX_TIME_OUT   2*TICKS_PER_SEC

Definition at line 125 of file tulip.c.

#define get_unaligned ( ptr   )     (*(ptr))

Definition at line 129 of file tulip.c.

#define put_unaligned ( val,
ptr   )     ((void)( *(ptr) = (val) ))

Definition at line 130 of file tulip.c.

Referenced by tulip_probe().

#define get_u16 ( ptr   )     (*(u16 *)(ptr))

Definition at line 131 of file tulip.c.

Referenced by parse_eeprom(), and select_media().

#define virt_to_le32desc ( addr   )     virt_to_bus(addr)

Definition at line 132 of file tulip.c.

#define TULIP_IOTYPE   PCI_USES_MASTER | PCI_USES_IO | PCI_ADDR0

Definition at line 134 of file tulip.c.

#define TULIP_SIZE   0x80

Definition at line 135 of file tulip.c.

#define FULL_DUPLEX_MAGIC   0x6969

Definition at line 141 of file tulip.c.

Referenced by select_media().

#define MEDIA_MASK   31

Definition at line 146 of file tulip.c.

Referenced by parse_eeprom().

#define EEPROM_ADDRLEN   6

Definition at line 348 of file tulip.c.

#define EEPROM_SIZE   128

Definition at line 349 of file tulip.c.

#define EE_WRITE_CMD   (5 << addr_len)

Definition at line 352 of file tulip.c.

#define EE_READ_CMD   (6 << addr_len)

Definition at line 353 of file tulip.c.

#define EE_ERASE_CMD   (7 << addr_len)

Definition at line 354 of file tulip.c.

#define EE_SHIFT_CLK   0x02

Definition at line 357 of file tulip.c.

#define EE_CS   0x01

Definition at line 358 of file tulip.c.

#define EE_DATA_WRITE   0x04

Definition at line 359 of file tulip.c.

#define EE_WRITE_0   0x01

Definition at line 360 of file tulip.c.

#define EE_WRITE_1   0x05

Definition at line 361 of file tulip.c.

#define EE_DATA_READ   0x08

Definition at line 362 of file tulip.c.

#define EE_ENB   (0x4800 | EE_CS)

Definition at line 363 of file tulip.c.

 
#define eeprom_delay (  )     inl(ee_addr)

Definition at line 368 of file tulip.c.

#define BUFLEN   1536

Definition at line 371 of file tulip.c.

#define DESC_RING_WRAP   0x02000000

Definition at line 380 of file tulip.c.

Referenced by tulip_init_ring().

#define TX_RING_SIZE   2

Definition at line 433 of file tulip.c.

#define RX_RING_SIZE   4

Definition at line 434 of file tulip.c.

#define tx_ring   tulip_bss.tx_ring

Definition at line 442 of file tulip.c.

#define txb   tulip_bss.txb

Definition at line 443 of file tulip.c.

#define rx_ring   tulip_bss.rx_ring

Definition at line 444 of file tulip.c.

#define rxb   tulip_bss.rxb

Definition at line 445 of file tulip.c.

 
#define mdio_delay (  )     inl(mdio_addr)

Definition at line 565 of file tulip.c.

#define MDIO_SHIFT_CLK   0x10000

Definition at line 570 of file tulip.c.

Referenced by mdio_read(), and mdio_write().

#define MDIO_DATA_WRITE0   0x00000

Definition at line 571 of file tulip.c.

#define MDIO_DATA_WRITE1   0x20000

Definition at line 572 of file tulip.c.

Referenced by mdio_read(), and mdio_write().

#define MDIO_ENB   0x00000

Definition at line 573 of file tulip.c.

Referenced by mdio_read(), and mdio_write().

#define MDIO_ENB_IN   0x40000

Definition at line 574 of file tulip.c.

Referenced by mdio_read(), and mdio_write().

#define MDIO_DATA_READ   0x80000

Definition at line 575 of file tulip.c.

Referenced by mdio_read().


Enumeration Type Documentation

Enumerator:
DC21040 
DC21041 
DC21140 
DC21142 
DC21143 
LC82C168 
MX98713 
MX98715 
MX98725 
AX88141 
AX88140 
PNIC2 
COMET 
COMPEX9881 
I21145 
XIRCOM 
SGThomson 

Definition at line 156 of file tulip.c.

00156                  {
00157     DC21040=0, DC21041=1, DC21140=2, DC21142=3, DC21143=3,
00158     LC82C168, MX98713, MX98715, MX98725, AX88141, AX88140, PNIC2, COMET,
00159     COMPEX9881, I21145, XIRCOM, SGThomson,      /*Ramesh Chander*/
00160 };

Enumerator:
PCI_USES_IO 
PCI_USES_MEM 
PCI_USES_MASTER 
PCI_ADDR0 
PCI_ADDR1 
PCI_ADDR2 
PCI_ADDR3 
PCI_USES_IO 
PCI_USES_MEM 
PCI_USES_MASTER 
PCI_ADDR0 
PCI_ADDR1 
PCI_ADDR2 
PCI_ADDR3 
PCI_ADDR_64BITS 
PCI_NO_ACPI_WAKE 
PCI_NO_MIN_LATENCY 
PCI_UNUSED_IRQ 

Definition at line 162 of file tulip.c.

00162                        {
00163     /* Set PCI command register bits before calling probe1(). */
00164     PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
00165     /* Read and map the single following PCI BAR. */
00166     PCI_ADDR0=0<<4, PCI_ADDR1=1<<4, PCI_ADDR2=2<<4, PCI_ADDR3=3<<4,
00167     PCI_ADDR_64BITS=0x100, PCI_NO_ACPI_WAKE=0x200, PCI_NO_MIN_LATENCY=0x400,
00168     PCI_UNUSED_IRQ=0x800,
00169 };

enum tbl_flag

Enumerator:
HAS_MII 
HAS_MEDIA_TABLE 
CSR12_IN_SROM 
ALWAYS_CHECK_MII 
HAS_PWRDWN 
MC_HASH_ONLY 
HAS_PNICNWAY 
HAS_NWAY 
HAS_INTR_MITIGATION 
IS_ASIX 
HAS_8023X 

Definition at line 240 of file tulip.c.

00240               {
00241     HAS_MII=1, HAS_MEDIA_TABLE=2, CSR12_IN_SROM=4, ALWAYS_CHECK_MII=8,
00242     HAS_PWRDWN=0x10, MC_HASH_ONLY=0x20, /* Hash-only multicast filter. */
00243     HAS_PNICNWAY=0x80, HAS_NWAY=0x40,   /* Uses internal NWay xcvr. */
00244     HAS_INTR_MITIGATION=0x100, IS_ASIX=0x200, HAS_8023X=0x400,
00245 };

enum MediaIs

Enumerator:
MediaIsFD 
MediaAlwaysFD 
MediaIsMII 
MediaIsFx 
MediaIs100 

Definition at line 277 of file tulip.c.

00277              {
00278     MediaIsFD = 1, MediaAlwaysFD=2, MediaIsMII=4, MediaIsFx=8,
00279     MediaIs100=16};

Enumerator:
CSR0 
CSR1 
CSR2 
CSR3 
CSR4 
CSR5 
CSR6 
CSR7 
CSR8 
CSR9 
CSR10 
CSR11 
CSR12 
CSR13 
CSR14 
CSR15 
CSR16 
CSR20 

Definition at line 300 of file tulip.c.

00300                    {
00301     CSR0=0,     CSR1=0x08,  CSR2=0x10,  CSR3=0x18,  CSR4=0x20,  CSR5=0x28,
00302     CSR6=0x30,  CSR7=0x38,  CSR8=0x40,  CSR9=0x48, CSR10=0x50, CSR11=0x58,
00303     CSR12=0x60, CSR13=0x68, CSR14=0x70, CSR15=0x78, CSR16=0x80, CSR20=0xA0
00304 };

Enumerator:
TimerInt 
TPLnkFail 
TPLnkPass 
NormalIntr 
AbnormalIntr 
RxJabber 
RxDied 
RxNoBuf 
RxIntr 
TxFIFOUnderflow 
TxJabber 
TxNoBuf 
TxDied 
TxIntr 

Definition at line 307 of file tulip.c.

00307                  {
00308     TimerInt=0x800, TPLnkFail=0x1000, TPLnkPass=0x10,
00309     NormalIntr=0x10000, AbnormalIntr=0x8000,
00310     RxJabber=0x200, RxDied=0x100, RxNoBuf=0x80, RxIntr=0x40,
00311     TxFIFOUnderflow=0x20, TxJabber=0x08, TxNoBuf=0x04, TxDied=0x02, TxIntr=0x01,
00312 };

Enumerator:
TxOn 
RxOn 
FullDuplex 
AcceptBroadcast 
AcceptAllMulticast 
AcceptAllPhys 
AcceptRunt 

Definition at line 315 of file tulip.c.

00315                     {
00316         TxOn=0x2000, RxOn=0x0002, FullDuplex=0x0200,
00317         AcceptBroadcast=0x0100, AcceptAllMulticast=0x0080,
00318         AcceptAllPhys=0x0040, AcceptRunt=0x0008,
00319 };

Enumerator:
DescOwn 
DescMore 
DescIntr 
DescNoCRC 
DescPktOK 
RxTooLong 
DescOwn 
DescEndPacket 
DescEndRing 
LastFrag 
DescIntrOnTx 
DescIntrOnDMADone 
DisableAlign 
DescOwnded 
RxDescFatalErr 
RxWholePkt 
DescOwn 
DescEndRing 
DescUseLink 
DescWholePkt 
DescStartPkt 
DescEndPkt 
DescIntr 

Definition at line 322 of file tulip.c.

00322                       {
00323     DescOwnded=0x80000000, RxDescFatalErr=0x8000, RxWholePkt=0x0300,
00324 };


Function Documentation

FILE_LICENCE ( GPL_ANY   ) 

static int mdio_read ( struct nic nic,
int  phy_id,
int  location 
) [static]

static void mdio_write ( struct nic nic,
int  phy_id,
int  location,
int  value 
) [static]

static int read_eeprom ( unsigned long  ioaddr,
int  location,
int  addr_len 
) [static]

Definition at line 707 of file tulip.c.

References CSR9, EE_CS, EE_DATA_READ, EE_DATA_WRITE, EE_ENB, EE_READ_CMD, EE_SHIFT_CLK, eeprom_delay, inl, outl, and whereami().

00708 {
00709     int i;
00710     unsigned short retval = 0;
00711     long ee_addr = ioaddr + CSR9;
00712     int read_cmd = location | EE_READ_CMD;
00713 
00714 #ifdef TULIP_DEBUG_WHERE
00715     whereami("read_eeprom\n");
00716 #endif
00717 
00718     outl(EE_ENB & ~EE_CS, ee_addr);
00719     outl(EE_ENB, ee_addr);
00720 
00721     /* Shift the read command bits out. */
00722     for (i = 4 + addr_len; i >= 0; i--) {
00723         short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
00724         outl(EE_ENB | dataval, ee_addr);
00725         eeprom_delay();
00726         outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
00727         eeprom_delay();
00728     }
00729     outl(EE_ENB, ee_addr);
00730 
00731     for (i = 16; i > 0; i--) {
00732         outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
00733         eeprom_delay();
00734         retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
00735         outl(EE_ENB, ee_addr);
00736         eeprom_delay();
00737     }
00738 
00739     /* Terminate the EEPROM access. */
00740     outl(EE_ENB & ~EE_CS, ee_addr);
00741     return retval;
00742 }

static void parse_eeprom ( struct nic nic  )  [static]

Definition at line 748 of file tulip.c.

References fixups::addr0, fixups::addr1, fixups::addr2, tulip_private::chip_id, CSR12_IN_SROM, mediatable::csr12dir, mediatable::csr15dir, mediatable::csr15val, DC21041, mediatable::defaultmedia, ee_data, tulip_private::eeprom, eeprom_fixups, tulip_private::flags, get_u16, get_unaligned, mediatable::has_mii, mediatable::has_nonmii, mediatable::has_reset, mediatable::leafcount, medialeaf::leafdata, medialeaf::media, media, MEDIA_MASK, tulip_private::media_table_storage, medianame, memcpy, mediatable::mleaf, tulip_private::mtable, name, fixups::name, tulip_private::nic_name, nic::node_addr, NULL, printf(), tulip_private::sym_advertise, medialeaf::type, u16, u32, and whereami().

Referenced by tulip_probe().

00749 {
00750     unsigned char *p, *ee_data = tp->eeprom;
00751     int new_advertise = 0;
00752     int i;
00753 
00754 #ifdef TULIP_DEBUG_WHERE
00755     whereami("parse_eeprom\n");
00756 #endif
00757 
00758     tp->mtable = 0;
00759     /* Detect an old-style (SA only) EEPROM layout:
00760        memcmp(ee_data, ee_data+16, 8). */
00761     for (i = 0; i < 8; i ++)
00762         if (ee_data[i] != ee_data[16+i])
00763             break;
00764     if (i >= 8) {
00765         /* Do a fix-up based on the vendor half of the station address. */
00766         for (i = 0; eeprom_fixups[i].name; i++) {
00767             if (nic->node_addr[0] == eeprom_fixups[i].addr0
00768                 &&  nic->node_addr[1] == eeprom_fixups[i].addr1
00769                 &&  nic->node_addr[2] == eeprom_fixups[i].addr2) {
00770                 if (nic->node_addr[2] == 0xE8  &&  ee_data[0x1a] == 0x55)
00771                     i++;                /* An Accton EN1207, not an outlaw Maxtech. */
00772                 memcpy(ee_data + 26, eeprom_fixups[i].newtable,
00773                        sizeof(eeprom_fixups[i].newtable));
00774 #ifdef TULIP_DEBUG
00775                 printf("%s: Old format EEPROM on '%s' board.\n%s: Using substitute media control info.\n",
00776                        tp->nic_name, eeprom_fixups[i].name, tp->nic_name);
00777 #endif
00778                 break;
00779             }
00780         }
00781         if (eeprom_fixups[i].name == NULL) { /* No fixup found. */
00782 #ifdef TULIP_DEBUG
00783             printf("%s: Old style EEPROM with no media selection information.\n",
00784                    tp->nic_name);
00785 #endif
00786             return;
00787         }
00788     }
00789 
00790     if (ee_data[19] > 1) {
00791 #ifdef TULIP_DEBUG
00792         printf("%s:  Multiport cards (%d ports) may not work correctly.\n", 
00793                tp->nic_name, ee_data[19]);
00794 #endif
00795     }
00796 
00797     p = (void *)ee_data + ee_data[27];
00798 
00799     if (ee_data[27] == 0) {             /* No valid media table. */
00800 #ifdef TULIP_DEBUG
00801         if (tulip_debug > 1) {
00802             printf("%s:  No Valid Media Table. ee_data[27] = %hhX\n", 
00803                    tp->nic_name, ee_data[27]);
00804         }
00805 #endif
00806     } else if (tp->chip_id == DC21041) {
00807         int media = get_u16(p);
00808         int count = p[2];
00809         p += 3;
00810 
00811         printf("%s: 21041 Media table, default media %hX (%s).\n",
00812                tp->nic_name, media,
00813                media & 0x0800 ? "Autosense" : medianame[media & 15]);
00814         for (i = 0; i < count; i++) {
00815             unsigned char media_block = *p++;
00816             int media_code = media_block & MEDIA_MASK;
00817             if (media_block & 0x40)
00818                 p += 6;
00819             switch(media_code) {
00820             case 0: new_advertise |= 0x0020; break;
00821             case 4: new_advertise |= 0x0040; break;
00822             }
00823             printf("%s:  21041 media #%d, %s.\n",
00824                    tp->nic_name, media_code, medianame[media_code]);
00825         }
00826     } else {
00827         unsigned char csr12dir = 0;
00828         int count;
00829         struct mediatable *mtable;
00830         u16 media = get_u16(p);
00831 
00832         p += 2;
00833         if (tp->flags & CSR12_IN_SROM)
00834             csr12dir = *p++;
00835         count = *p++;
00836 
00837         tp->mtable = mtable = (struct mediatable *)&tp->media_table_storage[0];
00838 
00839         mtable->defaultmedia = media;
00840         mtable->leafcount = count;
00841         mtable->csr12dir = csr12dir;
00842         mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0;
00843         mtable->csr15dir = mtable->csr15val = 0;
00844 
00845         printf("%s:  EEPROM default media type %s.\n", tp->nic_name,
00846                media & 0x0800 ? "Autosense" : medianame[media & MEDIA_MASK]);
00847 
00848         for (i = 0; i < count; i++) {
00849             struct medialeaf *leaf = &mtable->mleaf[i];
00850 
00851             if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */
00852                 leaf->type = 0;
00853                 leaf->media = p[0] & 0x3f;
00854                 leaf->leafdata = p;
00855                 if ((p[2] & 0x61) == 0x01)      /* Bogus, but Znyx boards do it. */
00856                     mtable->has_mii = 1;
00857                 p += 4;
00858             } else {
00859                 switch(leaf->type = p[1]) {
00860                 case 5:
00861                     mtable->has_reset = i;
00862                     leaf->media = p[2] & 0x0f;
00863                     break;
00864                 case 1: case 3:
00865                     mtable->has_mii = 1;
00866                     leaf->media = 11;
00867                     break;
00868                 case 2:
00869                     if ((p[2] & 0x3f) == 0) {
00870                         u32 base15 = (p[2] & 0x40) ? get_u16(p + 7) : 0x0008;
00871                         u16 *p1 = (u16 *)(p + (p[2] & 0x40 ? 9 : 3));
00872                         mtable->csr15dir = (get_unaligned(p1 + 0)<<16) + base15;
00873                         mtable->csr15val = (get_unaligned(p1 + 1)<<16) + base15;
00874                     }
00875                     /* Fall through. */
00876                 case 0: case 4:
00877                     mtable->has_nonmii = 1;
00878                     leaf->media = p[2] & MEDIA_MASK;
00879                     switch (leaf->media) {
00880                     case 0: new_advertise |= 0x0020; break;
00881                     case 4: new_advertise |= 0x0040; break;
00882                     case 3: new_advertise |= 0x0080; break;
00883                     case 5: new_advertise |= 0x0100; break;
00884                     case 6: new_advertise |= 0x0200; break;
00885                     }
00886                     break;
00887                 default:
00888                     leaf->media = 19;
00889                 }
00890                 leaf->leafdata = p + 2;
00891                 p += (p[0] & 0x3f) + 1;
00892             }
00893 #ifdef TULIP_DEBUG
00894             if (tulip_debug > 1  &&  leaf->media == 11) {
00895                 unsigned char *bp = leaf->leafdata;
00896                 printf("%s:  MII interface PHY %d, setup/reset sequences %d/%d long, capabilities %hhX %hhX.\n",
00897                        tp->nic_name, bp[0], bp[1], bp[2 + bp[1]*2],
00898                        bp[5 + bp[2 + bp[1]*2]*2], bp[4 + bp[2 + bp[1]*2]*2]);
00899             }
00900 #endif
00901             printf("%s:  Index #%d - Media %s (#%d) described "
00902                    "by a %s (%d) block.\n",
00903                    tp->nic_name, i, medianame[leaf->media], leaf->media,
00904                    leaf->type < 6 ? block_name[leaf->type] : "UNKNOWN",
00905                    leaf->type);
00906         }
00907         if (new_advertise)
00908             tp->sym_advertise = new_advertise;
00909     }
00910 }

static int tulip_probe ( struct nic nic,
struct pci_device pci 
) [static]

Definition at line 1235 of file tulip.c.

References adjust_pci_device(), tulip_private::chip_id, chip_idx, tulip_chip_table::chip_name, COMET, csr0, tulip_private::csr0, CSR5, CSR6, CSR7, CSR8, CSR9, DBG, DC21040, DC21041, DC21143, tulip_private::default_port, tulip_private::dev_id, pci_device::device, pci_device::driver_name, pci_id_info::drv_flags, ee_data, tulip_private::eeprom, EEPROM_SIZE, ETH_ALEN, eth_ntoa(), tulip_chip_table::flags, tulip_private::flags, HAS_8023X, HAS_MEDIA_TABLE, HAS_PWRDWN, pci_id_info::id, tulip_private::if_port, inl, nic::ioaddr, ioaddr, pci_device::ioaddr, nic::irqno, IS_ASIX, LC82C168, le16_to_cpu, media_cap, MediaIsMII, memcpy, tulip_private::mii_advertise, pci_id_info::name, name, tulip_private::nic_name, nic::nic_op, nic::node_addr, outl, parse_eeprom(), pci_id_info::match_info::pci, tulip_private::pci_id_idx, pci_id_info::match_info::pci_mask, pci_read_config_byte(), PCI_REVISION, pci_write_config_dword(), printf(), put_unaligned, read_eeprom(), tulip_private::revision, start_link(), TICKS_PER_SEC, tulip_reset(), tulip_tbl, tulip_wait(), u16, u32, u8, pci_device::vendor, tulip_private::vendor_id, and whereami().

01235                                                                    {
01236 
01237     u32 i;
01238     u8  chip_rev;
01239     u8 ee_data[EEPROM_SIZE];
01240     unsigned short sum;
01241     int chip_idx;
01242     static unsigned char last_phys_addr[ETH_ALEN] = {0x00, 'L', 'i', 'n', 'u', 'x'};
01243 
01244     if (pci->ioaddr == 0)
01245         return 0;
01246 
01247     ioaddr         = pci->ioaddr;
01248     nic->ioaddr    = pci->ioaddr & ~3;
01249     nic->irqno     = 0;
01250 
01251     /* point to private storage */
01252     tp = &tulip_bss.tpx;
01253 
01254     tp->vendor_id  = pci->vendor;
01255     tp->dev_id     = pci->device;
01256     tp->nic_name   = pci->driver_name;
01257 
01258     tp->if_port = 0;
01259     tp->default_port = 0;
01260 
01261     adjust_pci_device(pci);
01262 
01263     /* disable interrupts */
01264     outl(0x00000000, ioaddr + CSR7);
01265 
01266     /* Stop the chip's Tx and Rx processes. */
01267     outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
01268 
01269     /* Clear the missed-packet counter. */
01270     inl(ioaddr + CSR8);
01271 
01272     printf("\n");                /* so we start on a fresh line */
01273 #ifdef TULIP_DEBUG_WHERE
01274     whereami("tulip_probe\n");
01275 #endif
01276 
01277 #ifdef TULIP_DEBUG
01278     if (tulip_debug > 1)
01279         printf ("%s: Looking for Tulip Chip: Vendor=%hX  Device=%hX\n", tp->nic_name,
01280                 tp->vendor, tp->dev_id);
01281 #endif
01282 
01283     /* Figure out which chip we're dealing with */
01284     i = 0;
01285     chip_idx = -1;
01286   
01287     while (pci_id_tbl[i].name) {
01288         if ( (((u32) tp->dev_id << 16) | tp->vendor_id) == 
01289              (pci_id_tbl[i].id.pci & pci_id_tbl[i].id.pci_mask) ) {
01290             chip_idx = pci_id_tbl[i].drv_flags;
01291             break;
01292         }
01293         i++;
01294     }
01295 
01296     if (chip_idx == -1) {
01297         printf ("%s: Unknown Tulip Chip: Vendor=%hX  Device=%hX\n", tp->nic_name,
01298                 tp->vendor_id, tp->dev_id);
01299         return 0;
01300     }
01301 
01302     tp->pci_id_idx = i;
01303     tp->flags = tulip_tbl[chip_idx].flags;
01304 
01305 #ifdef TULIP_DEBUG
01306     if (tulip_debug > 1) {
01307         printf ("%s: tp->pci_id_idx == %d,  name == %s\n", tp->nic_name, 
01308                 tp->pci_id_idx, pci_id_tbl[tp->pci_id_idx].name);
01309         printf ("%s: chip_idx == %d, name == %s\n", tp->nic_name, chip_idx, 
01310                 tulip_tbl[chip_idx].chip_name);
01311     }
01312 #endif
01313   
01314     /* Bring the 21041/21143 out of sleep mode.
01315        Caution: Snooze mode does not work with some boards! */
01316     if (tp->flags & HAS_PWRDWN)
01317         pci_write_config_dword(pci, 0x40, 0x00000000);
01318 
01319     if (inl(ioaddr + CSR5) == 0xFFFFFFFF) {
01320         printf("%s: The Tulip chip at %X is not functioning.\n",
01321                tp->nic_name, (unsigned int) ioaddr);
01322         return 0;
01323     }
01324    
01325     pci_read_config_byte(pci, PCI_REVISION, &chip_rev);
01326 
01327     printf("%s: [chip: %s] rev %d at %hX\n", tp->nic_name,
01328            tulip_tbl[chip_idx].chip_name, chip_rev, (unsigned int) ioaddr);
01329     printf("%s: Vendor=%hX  Device=%hX", tp->nic_name, tp->vendor_id, tp->dev_id);
01330 
01331     if (chip_idx == DC21041  &&  inl(ioaddr + CSR9) & 0x8000) {
01332         printf(" 21040 compatible mode.");
01333         chip_idx = DC21040;
01334     }
01335 
01336     printf("\n");
01337 
01338     /* The SROM/EEPROM interface varies dramatically. */
01339     sum = 0;
01340     if (chip_idx == DC21040) {
01341         outl(0, ioaddr + CSR9);         /* Reset the pointer with a dummy write. */
01342         for (i = 0; i < ETH_ALEN; i++) {
01343             int value, boguscnt = 100000;
01344             do
01345                 value = inl(ioaddr + CSR9);
01346             while (value < 0  && --boguscnt > 0);
01347             nic->node_addr[i] = value;
01348             sum += value & 0xff;
01349         }
01350     } else if (chip_idx == LC82C168) {
01351         for (i = 0; i < 3; i++) {
01352             int value, boguscnt = 100000;
01353             outl(0x600 | i, ioaddr + 0x98);
01354             do
01355                 value = inl(ioaddr + CSR9);
01356             while (value < 0  && --boguscnt > 0);
01357             put_unaligned(le16_to_cpu(value), ((u16*)nic->node_addr) + i);
01358             sum += value & 0xffff;
01359         }
01360     } else if (chip_idx == COMET) {
01361         /* No need to read the EEPROM. */
01362         put_unaligned(inl(ioaddr + 0xA4), (u32 *)nic->node_addr);
01363         put_unaligned(inl(ioaddr + 0xA8), (u16 *)(nic->node_addr + 4));
01364         for (i = 0; i < ETH_ALEN; i ++)
01365             sum += nic->node_addr[i];
01366     } else {
01367         /* A serial EEPROM interface, we read now and sort it out later. */
01368         int sa_offset = 0;
01369         int ee_addr_size = read_eeprom(ioaddr, 0xff, 8) & 0x40000 ? 8 : 6;
01370 
01371         for (i = 0; i < sizeof(ee_data)/2; i++)
01372             ((u16 *)ee_data)[i] =
01373                 le16_to_cpu(read_eeprom(ioaddr, i, ee_addr_size));
01374 
01375         /* DEC now has a specification (see Notes) but early board makers
01376            just put the address in the first EEPROM locations. */
01377         /* This does  memcmp(eedata, eedata+16, 8) */
01378         for (i = 0; i < 8; i ++)
01379             if (ee_data[i] != ee_data[16+i])
01380                 sa_offset = 20;
01381         if (ee_data[0] == 0xff  &&  ee_data[1] == 0xff &&  ee_data[2] == 0) {
01382             sa_offset = 2;              /* Grrr, damn Matrox boards. */
01383         }
01384         for (i = 0; i < ETH_ALEN; i ++) {
01385             nic->node_addr[i] = ee_data[i + sa_offset];
01386             sum += ee_data[i + sa_offset];
01387         }
01388     }
01389     /* Lite-On boards have the address byte-swapped. */
01390     if ((nic->node_addr[0] == 0xA0  ||  nic->node_addr[0] == 0xC0)
01391         &&  nic->node_addr[1] == 0x00)
01392         for (i = 0; i < ETH_ALEN; i+=2) {
01393             char tmp = nic->node_addr[i];
01394             nic->node_addr[i] = nic->node_addr[i+1];
01395             nic->node_addr[i+1] = tmp;
01396         }
01397 
01398     if (sum == 0  || sum == ETH_ALEN*0xff) {
01399         printf("%s: EEPROM not present!\n", tp->nic_name);
01400         for (i = 0; i < ETH_ALEN-1; i++)
01401             nic->node_addr[i] = last_phys_addr[i];
01402         nic->node_addr[i] = last_phys_addr[i] + 1;
01403     }
01404 
01405     for (i = 0; i < ETH_ALEN; i++)
01406         last_phys_addr[i] = nic->node_addr[i];
01407 
01408     DBG ( "%s: %s at ioaddr %hX\n", tp->nic_name, eth_ntoa ( nic->node_addr ), 
01409           (unsigned int) ioaddr );
01410 
01411     tp->chip_id = chip_idx;
01412     tp->revision = chip_rev;
01413     tp->csr0 = csr0;
01414 
01415     /* BugFixes: The 21143-TD hangs with PCI Write-and-Invalidate cycles.
01416        And the ASIX must have a burst limit or horrible things happen. */
01417     if (chip_idx == DC21143  &&  chip_rev == 65)
01418         tp->csr0 &= ~0x01000000;
01419     else if (tp->flags & IS_ASIX)
01420         tp->csr0 |= 0x2000;
01421 
01422     if (media_cap[tp->default_port] & MediaIsMII) {
01423         static const u16 media2advert[] = { 0x20, 0x40, 0x03e0, 0x60,
01424                                             0x80, 0x100, 0x200 };
01425         tp->mii_advertise = media2advert[tp->default_port - 9];
01426         tp->mii_advertise |= (tp->flags & HAS_8023X); /* Matching bits! */
01427     }
01428 
01429     /* This is logically part of the probe routine, but too complex
01430        to write inline. */
01431     if (tp->flags & HAS_MEDIA_TABLE) {
01432         memcpy(tp->eeprom, ee_data, sizeof(tp->eeprom));
01433         parse_eeprom(nic);
01434     }
01435 
01436     start_link(nic);
01437 
01438     /* reset the device and make ready for tx and rx of packets */
01439     tulip_reset(nic);
01440     nic->nic_op = &tulip_operations;
01441 
01442     /* give the board a chance to reset before returning */
01443     tulip_wait(4*TICKS_PER_SEC);
01444 
01445     return 1;
01446 }

static void tulip_init_ring ( struct nic nic  )  [static]

Referenced by tulip_reset().

static void tulip_reset ( struct nic nic  )  [static]

Definition at line 972 of file tulip.c.

References tulip_private::chip_id, COMET, cpu_to_le32, tulip_private::csr0, CSR0, CSR1, CSR13, CSR14, CSR3, CSR4, tulip_private::csr6, CSR6, currticks(), tulip_private::flags, get_unaligned, mediatable::has_mii, init_media(), inl, ioaddr, IS_ASIX, LC82C168, MC_HASH_ONLY, tulip_private::mii_cnt, tulip_private::mtable, tulip_private::nic_name, nic::node_addr, outl, PNIC2, printf(), rx_ring, set_rx_mode(), tulip_check_duplex(), tulip_init_ring(), tulip_wait(), tx_ring, TX_TIME_OUT, txb, u16, u32, virt_to_le32desc, and whereami().

Referenced by tulip_disable(), and tulip_probe().

00973 {
00974     int i;
00975     unsigned long to;
00976 
00977 #ifdef TULIP_DEBUG_WHERE
00978     whereami("tulip_reset\n");
00979 #endif
00980 
00981     /* Stop Tx and RX */
00982     outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
00983 
00984     /* On some chip revs we must set the MII/SYM port before the reset!? */
00985     if (tp->mii_cnt  ||  (tp->mtable  &&  tp->mtable->has_mii)) {
00986         outl(0x814C0000, ioaddr + CSR6);
00987     }
00988  
00989     /* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
00990     outl(0x00000001, ioaddr + CSR0);
00991     tulip_wait(1);
00992 
00993     /* turn off reset and set cache align=16lword, burst=unlimit */
00994     outl(tp->csr0, ioaddr + CSR0);
00995 
00996     /*  Wait the specified 50 PCI cycles after a reset */
00997     tulip_wait(1);
00998 
00999     /* set up transmit and receive descriptors */
01000     tulip_init_ring(nic);
01001 
01002     if (tp->chip_id == PNIC2) {
01003         u32 addr_high = (nic->node_addr[1]<<8) + (nic->node_addr[0]<<0);
01004         /* This address setting does not appear to impact chip operation?? */
01005         outl((nic->node_addr[5]<<8) + nic->node_addr[4] +
01006              (nic->node_addr[3]<<24) + (nic->node_addr[2]<<16),
01007              ioaddr + 0xB0);
01008         outl(addr_high + (addr_high<<16), ioaddr + 0xB8);
01009     }
01010 
01011     /* MC_HASH_ONLY boards don't support setup packets */
01012     if (tp->flags & MC_HASH_ONLY) {
01013         u32 addr_low = cpu_to_le32(get_unaligned((u32 *)nic->node_addr));
01014         u32 addr_high = cpu_to_le32(get_unaligned((u16 *)(nic->node_addr+4)));
01015 
01016         /* clear multicast hash filters and setup MAC address filters */
01017         if (tp->flags & IS_ASIX) {
01018             outl(0, ioaddr + CSR13);
01019             outl(addr_low,  ioaddr + CSR14);
01020             outl(1, ioaddr + CSR13);
01021             outl(addr_high, ioaddr + CSR14);
01022             outl(2, ioaddr + CSR13);
01023             outl(0, ioaddr + CSR14);
01024             outl(3, ioaddr + CSR13);
01025             outl(0, ioaddr + CSR14);
01026         } else if (tp->chip_id == COMET) {
01027             outl(addr_low,  ioaddr + 0xA4);
01028             outl(addr_high, ioaddr + 0xA8);
01029             outl(0, ioaddr + 0xAC);
01030             outl(0, ioaddr + 0xB0);
01031         }
01032     } else {
01033         /* for other boards we send a setup packet to initialize
01034            the filters */
01035         u32 tx_flags = 0x08000000 | 192;
01036 
01037         /* construct perfect filter frame with mac address as first match
01038            and broadcast address for all others */
01039         for (i=0; i<192; i++) 
01040             txb[i] = 0xFF;
01041         txb[0] = nic->node_addr[0];
01042         txb[1] = nic->node_addr[1];
01043         txb[4] = nic->node_addr[2];
01044         txb[5] = nic->node_addr[3];
01045         txb[8] = nic->node_addr[4];
01046         txb[9] = nic->node_addr[5];
01047 
01048         tx_ring[0].length  = cpu_to_le32(tx_flags);
01049         tx_ring[0].buffer1 = virt_to_le32desc(&txb[0]);
01050         tx_ring[0].status  = cpu_to_le32(0x80000000);
01051     }
01052 
01053     /* Point to rx and tx descriptors */
01054     outl(virt_to_le32desc(&rx_ring[0]), ioaddr + CSR3);
01055     outl(virt_to_le32desc(&tx_ring[0]), ioaddr + CSR4);
01056 
01057     init_media(nic);
01058 
01059     /* set the chip's operating mode (but don't turn on xmit and recv yet) */
01060     outl((tp->csr6 & ~0x00002002), ioaddr + CSR6);
01061 
01062     /* send setup packet for cards that support it */
01063     if (!(tp->flags & MC_HASH_ONLY)) {
01064         /* enable transmit  wait for completion */
01065         outl(tp->csr6 | 0x00002000, ioaddr + CSR6);
01066         /* immediate transmit demand */
01067         outl(0, ioaddr + CSR1);
01068 
01069         to = currticks() + TX_TIME_OUT;
01070         while ((tx_ring[0].status & 0x80000000) && (currticks() < to))
01071             /* wait */ ;
01072 
01073         if (currticks() >= to) {
01074             printf ("%s: TX Setup Timeout.\n", tp->nic_name);
01075         }
01076     }
01077 
01078     if (tp->chip_id == LC82C168)
01079         tulip_check_duplex(nic);
01080 
01081     set_rx_mode(nic);   
01082         
01083     /* enable transmit and receive */
01084     outl(tp->csr6 | 0x00002002, ioaddr + CSR6);
01085 }

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

Definition at line 1091 of file tulip.c.

References cpu_to_le32, CSR1, CSR4, CSR6, currticks(), ETH_ALEN, ETH_HLEN, ETH_ZLEN, htons, inl, ioaddr, memcpy, tulip_private::nic_name, nic::node_addr, outl, printf(), tx_ring, TX_TIME_OUT, txb, u16, u32, u8, virt_to_le32desc, and whereami().

01093 {
01094     u16 nstype;
01095     u32 to;
01096     u32 csr6 = inl(ioaddr + CSR6);
01097 
01098 #ifdef TULIP_DEBUG_WHERE    
01099     whereami("tulip_transmit\n");
01100 #endif
01101 
01102     /* Disable Tx */
01103     outl(csr6 & ~0x00002000, ioaddr + CSR6);
01104 
01105     memcpy(txb, d, ETH_ALEN);
01106     memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);
01107     nstype = htons((u16) t);
01108     memcpy(txb + 2 * ETH_ALEN, (u8 *)&nstype, 2);
01109     memcpy(txb + ETH_HLEN, p, s);
01110 
01111     s += ETH_HLEN;
01112     s &= 0x0FFF;
01113 
01114     /* pad to minimum packet size */
01115     while (s < ETH_ZLEN)  
01116         txb[s++] = '\0';
01117 
01118 #ifdef TULIP_DEBUG
01119     if (tulip_debug > 1)
01120         printf("%s: sending %d bytes ethtype %hX\n", tp->nic_name, s, t);
01121 #endif
01122         
01123     /* setup the transmit descriptor */
01124     /* 0x60000000 = no interrupt on completion */
01125     tx_ring[0].length = cpu_to_le32(0x60000000 | s);
01126     tx_ring[0].status = cpu_to_le32(0x80000000);
01127 
01128     /* Point to transmit descriptor */
01129     outl(virt_to_le32desc(&tx_ring[0]), ioaddr + CSR4);
01130 
01131     /* Enable Tx */
01132     outl(csr6 | 0x00002000, ioaddr + CSR6);
01133     /* immediate transmit demand */
01134     outl(0, ioaddr + CSR1);
01135 
01136     to = currticks() + TX_TIME_OUT;
01137     while ((tx_ring[0].status & 0x80000000) && (currticks() < to))
01138         /* wait */ ;
01139 
01140     if (currticks() >= to) {
01141         printf ("TX Timeout!\n");
01142     }
01143 
01144     /* Disable Tx */
01145     outl(csr6 & ~0x00002000, ioaddr + CSR6);
01146 }

static int tulip_poll ( struct nic nic,
int  retrieve 
) [static]

Definition at line 1151 of file tulip.c.

References BUFLEN, tulip_private::cur_rx, memcpy, nic::packet, nic::packetlen, rx_ring, RX_RING_SIZE, rxb, and whereami().

01152 {
01153 
01154 #ifdef TULIP_DEBUG_WHERE
01155     whereami("tulip_poll\n");
01156 #endif
01157 
01158     /* no packet waiting. packet still owned by NIC */
01159     if (rx_ring[tp->cur_rx].status & 0x80000000)
01160         return 0;
01161 
01162     if ( ! retrieve ) return 1;
01163 
01164 #ifdef TULIP_DEBUG_WHERE
01165     whereami("tulip_poll got one\n");
01166 #endif
01167 
01168     nic->packetlen = (rx_ring[tp->cur_rx].status & 0x3FFF0000) >> 16;
01169 
01170     /* if we get a corrupted packet. throw it away and move on */
01171     if (rx_ring[tp->cur_rx].status & 0x00008000) {
01172         /* return the descriptor and buffer to receive ring */
01173         rx_ring[tp->cur_rx].status = 0x80000000;
01174         tp->cur_rx = (++tp->cur_rx) % RX_RING_SIZE;
01175         return 0;
01176     }
01177 
01178     /* copy packet to working buffer */
01179     memcpy(nic->packet, rxb + tp->cur_rx * BUFLEN, nic->packetlen);
01180 
01181     /* return the descriptor and buffer to receive ring */
01182     rx_ring[tp->cur_rx].status = 0x80000000;
01183     tp->cur_rx = (++tp->cur_rx) % RX_RING_SIZE;
01184 
01185     return 1;
01186 }

static void tulip_disable ( struct nic nic  )  [static]

Definition at line 1191 of file tulip.c.

References CSR6, CSR7, CSR8, inl, ioaddr, outl, tulip_reset(), and whereami().

01191                                               {
01192 
01193 #ifdef TULIP_DEBUG_WHERE
01194     whereami("tulip_disable\n");
01195 #endif
01196 
01197     tulip_reset(nic);
01198 
01199     /* disable interrupts */
01200     outl(0x00000000, ioaddr + CSR7);
01201 
01202     /* Stop the chip's Tx and Rx processes. */
01203     outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
01204 
01205     /* Clear the missed-packet counter. */
01206     inl(ioaddr + CSR8);
01207 }

static void nway_start ( struct nic nic  )  [static]

Referenced by init_media(), and start_link().

static void pnic_do_nway ( struct nic nic  )  [static]

Referenced by init_media().

static void select_media ( struct nic nic,
int  startup 
) [static]

Definition at line 1760 of file tulip.c.

References tulip_private::advertising, tulip_private::chip_id, CSR11, CSR12, mediatable::csr12dir, CSR13, CSR14, CSR15, tulip_private::csr6, tulip_private::cur_index, DC21040, DC21041, tulip_private::default_port, tulip_private::full_duplex, FULL_DUPLEX_MAGIC, get_u16, mediatable::has_reset, tulip_private::if_port, inl, ioaddr, LC82C168, medialeaf::leafdata, mdio_write(), media_cap, MediaAlwaysFD, MediaIsFx, MediaIsMII, tulip_private::medialock, medianame, tulip_private::mii_advertise, tulip_private::mii_cnt, mediatable::mleaf, tulip_private::mtable, tulip_private::nic_name, outl, tulip_private::phys, printf(), t21040_csr13, t21041_csr13, t21041_csr14, t21041_csr15, t21142_csr14, medialeaf::type, u16, u32, u8, and whereami().

Referenced by init_media(), and start_link().

01761 {
01762     struct mediatable *mtable = tp->mtable;
01763     u32 new_csr6;
01764     int i;
01765 
01766 #ifdef TULIP_DEBUG_WHERE
01767     whereami("select_media\n");
01768 #endif
01769 
01770     if (mtable) {
01771         struct medialeaf *mleaf = &mtable->mleaf[tp->cur_index];
01772         unsigned char *p = mleaf->leafdata;
01773         switch (mleaf->type) {
01774         case 0:                                 /* 21140 non-MII xcvr. */
01775 #ifdef TULIP_DEBUG
01776             if (tulip_debug > 1)
01777                 printf("%s: Using a 21140 non-MII transceiver"
01778                        " with control setting %hhX.\n",
01779                        tp->nic_name, p[1]);
01780 #endif
01781             tp->if_port = p[0];
01782             if (startup)
01783                 outl(mtable->csr12dir | 0x100, ioaddr + CSR12);
01784             outl(p[1], ioaddr + CSR12);
01785             new_csr6 = 0x02000000 | ((p[2] & 0x71) << 18);
01786             break;
01787         case 2: case 4: {
01788             u16 setup[5];
01789             u32 csr13val, csr14val, csr15dir, csr15val;
01790             for (i = 0; i < 5; i++)
01791                 setup[i] = get_u16(&p[i*2 + 1]);
01792 
01793             tp->if_port = p[0] & 15;
01794             if (media_cap[tp->if_port] & MediaAlwaysFD)
01795                 tp->full_duplex = 1;
01796 
01797             if (startup && mtable->has_reset) {
01798                 struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset];
01799                 unsigned char *rst = rleaf->leafdata;
01800 #ifdef TULIP_DEBUG
01801                 if (tulip_debug > 1)
01802                     printf("%s: Resetting the transceiver.\n",
01803                            tp->nic_name);
01804 #endif
01805                 for (i = 0; i < rst[0]; i++)
01806                     outl(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15);
01807             }
01808 #ifdef TULIP_DEBUG
01809             if (tulip_debug > 1)
01810                 printf("%s: 21143 non-MII %s transceiver control "
01811                        "%hX/%hX.\n",
01812                        tp->nic_name, medianame[tp->if_port], setup[0], setup[1]);
01813 #endif
01814             if (p[0] & 0x40) {  /* SIA (CSR13-15) setup values are provided. */
01815                 csr13val = setup[0];
01816                 csr14val = setup[1];
01817                 csr15dir = (setup[3]<<16) | setup[2];
01818                 csr15val = (setup[4]<<16) | setup[2];
01819                 outl(0, ioaddr + CSR13);
01820                 outl(csr14val, ioaddr + CSR14);
01821                 outl(csr15dir, ioaddr + CSR15); /* Direction */
01822                 outl(csr15val, ioaddr + CSR15); /* Data */
01823                 outl(csr13val, ioaddr + CSR13);
01824             } else {
01825                 csr13val = 1;
01826                 csr14val = 0x0003FF7F;
01827                 csr15dir = (setup[0]<<16) | 0x0008;
01828                 csr15val = (setup[1]<<16) | 0x0008;
01829                 if (tp->if_port <= 4)
01830                     csr14val = t21142_csr14[tp->if_port];
01831                 if (startup) {
01832                     outl(0, ioaddr + CSR13);
01833                     outl(csr14val, ioaddr + CSR14);
01834                 }
01835                 outl(csr15dir, ioaddr + CSR15); /* Direction */
01836                 outl(csr15val, ioaddr + CSR15); /* Data */
01837                 if (startup) outl(csr13val, ioaddr + CSR13);
01838             }
01839 #ifdef TULIP_DEBUG
01840             if (tulip_debug > 1)
01841                 printf("%s:  Setting CSR15 to %X/%X.\n",
01842                        tp->nic_name, csr15dir, csr15val);
01843 #endif
01844             if (mleaf->type == 4)
01845                 new_csr6 = 0x82020000 | ((setup[2] & 0x71) << 18);
01846             else
01847                 new_csr6 = 0x82420000;
01848             break;
01849         }
01850         case 1: case 3: {
01851             int phy_num = p[0];
01852             int init_length = p[1];
01853             u16 *misc_info;
01854 
01855             tp->if_port = 11;
01856             new_csr6 = 0x020E0000;
01857             if (mleaf->type == 3) {     /* 21142 */
01858                 u16 *init_sequence = (u16*)(p+2);
01859                 u16 *reset_sequence = &((u16*)(p+3))[init_length];
01860                 int reset_length = p[2 + init_length*2];
01861                 misc_info = reset_sequence + reset_length;
01862                 if (startup)
01863                     for (i = 0; i < reset_length; i++)
01864                         outl(get_u16(&reset_sequence[i]) << 16, ioaddr + CSR15);
01865                 for (i = 0; i < init_length; i++)
01866                     outl(get_u16(&init_sequence[i]) << 16, ioaddr + CSR15);
01867             } else {
01868                 u8 *init_sequence = p + 2;
01869                 u8 *reset_sequence = p + 3 + init_length;
01870                 int reset_length = p[2 + init_length];
01871                 misc_info = (u16*)(reset_sequence + reset_length);
01872                 if (startup) {
01873                     outl(mtable->csr12dir | 0x100, ioaddr + CSR12);
01874                     for (i = 0; i < reset_length; i++)
01875                         outl(reset_sequence[i], ioaddr + CSR12);
01876                 }
01877                 for (i = 0; i < init_length; i++)
01878                     outl(init_sequence[i], ioaddr + CSR12);
01879             }
01880             tp->advertising[phy_num] = get_u16(&misc_info[1]) | 1;
01881             if (startup < 2) {
01882                 if (tp->mii_advertise == 0)
01883                     tp->mii_advertise = tp->advertising[phy_num];
01884 #ifdef TULIP_DEBUG
01885                 if (tulip_debug > 1)
01886                     printf("%s:  Advertising %hX on MII %d.\n",
01887                            tp->nic_name, tp->mii_advertise, tp->phys[phy_num]);
01888 #endif
01889                 mdio_write(nic, tp->phys[phy_num], 4, tp->mii_advertise);
01890             }
01891             break;
01892         }
01893         default:
01894             printf("%s:  Invalid media table selection %d.\n",
01895                    tp->nic_name, mleaf->type);
01896             new_csr6 = 0x020E0000;
01897         }
01898 #ifdef TULIP_DEBUG
01899         if (tulip_debug > 1)
01900             printf("%s: Using media type %s, CSR12 is %hhX.\n",
01901                    tp->nic_name, medianame[tp->if_port],
01902                    inl(ioaddr + CSR12) & 0xff);
01903 #endif
01904     } else if (tp->chip_id == DC21041) {
01905         int port = tp->if_port <= 4 ? tp->if_port : 0;
01906 #ifdef TULIP_DEBUG
01907         if (tulip_debug > 1)
01908             printf("%s: 21041 using media %s, CSR12 is %hX.\n",
01909                    tp->nic_name, medianame[port == 3 ? 12: port],
01910                    inl(ioaddr + CSR12));
01911 #endif
01912         outl(0x00000000, ioaddr + CSR13); /* Reset the serial interface */
01913         outl(t21041_csr14[port], ioaddr + CSR14);
01914         outl(t21041_csr15[port], ioaddr + CSR15);
01915         outl(t21041_csr13[port], ioaddr + CSR13);
01916         new_csr6 = 0x80020000;
01917     } else if (tp->chip_id == LC82C168) {
01918         if (startup && ! tp->medialock)
01919             tp->if_port = tp->mii_cnt ? 11 : 0;
01920 #ifdef TULIP_DEBUG
01921         if (tulip_debug > 1)
01922             printf("%s: PNIC PHY status is %hX, media %s.\n",
01923                    tp->nic_name, inl(ioaddr + 0xB8), medianame[tp->if_port]);
01924 #endif
01925         if (tp->mii_cnt) {
01926             new_csr6 = 0x810C0000;
01927             outl(0x0001, ioaddr + CSR15);
01928             outl(0x0201B07A, ioaddr + 0xB8);
01929         } else if (startup) {
01930             /* Start with 10mbps to do autonegotiation. */
01931             outl(0x32, ioaddr + CSR12);
01932             new_csr6 = 0x00420000;
01933             outl(0x0001B078, ioaddr + 0xB8);
01934             outl(0x0201B078, ioaddr + 0xB8);
01935         } else if (tp->if_port == 3  ||  tp->if_port == 5) {
01936             outl(0x33, ioaddr + CSR12);
01937             new_csr6 = 0x01860000;
01938             /* Trigger autonegotiation. */
01939             outl(startup ? 0x0201F868 : 0x0001F868, ioaddr + 0xB8);
01940         } else {
01941             outl(0x32, ioaddr + CSR12);
01942             new_csr6 = 0x00420000;
01943             outl(0x1F078, ioaddr + 0xB8);
01944         }
01945     } else if (tp->chip_id == DC21040) {                                        /* 21040 */
01946         /* Turn on the xcvr interface. */
01947 #ifdef TULIP_DEBUG
01948         int csr12 = inl(ioaddr + CSR12);
01949         if (tulip_debug > 1)
01950             printf("%s: 21040 media type is %s, CSR12 is %hhX.\n",
01951                    tp->nic_name, medianame[tp->if_port], csr12);
01952 #endif
01953         if (media_cap[tp->if_port] & MediaAlwaysFD)
01954             tp->full_duplex = 1;
01955         new_csr6 = 0x20000;
01956         /* Set the full duplux match frame. */
01957         outl(FULL_DUPLEX_MAGIC, ioaddr + CSR11);
01958         outl(0x00000000, ioaddr + CSR13); /* Reset the serial interface */
01959         if (t21040_csr13[tp->if_port] & 8) {
01960             outl(0x0705, ioaddr + CSR14);
01961             outl(0x0006, ioaddr + CSR15);
01962         } else {
01963             outl(0xffff, ioaddr + CSR14);
01964             outl(0x0000, ioaddr + CSR15);
01965         }
01966         outl(0x8f01 | t21040_csr13[tp->if_port], ioaddr + CSR13);
01967     } else {                                    /* Unknown chip type with no media table. */
01968         if (tp->default_port == 0)
01969             tp->if_port = tp->mii_cnt ? 11 : 3;
01970         if (media_cap[tp->if_port] & MediaIsMII) {
01971             new_csr6 = 0x020E0000;
01972         } else if (media_cap[tp->if_port] & MediaIsFx) {
01973             new_csr6 = 0x028600000;
01974         } else
01975             new_csr6 = 0x038600000;
01976 #ifdef TULIP_DEBUG
01977         if (tulip_debug > 1)
01978             printf("%s: No media description table, assuming "
01979                    "%s transceiver, CSR12 %hhX.\n",
01980                    tp->nic_name, medianame[tp->if_port],
01981                    inl(ioaddr + CSR12));
01982 #endif
01983     }
01984 
01985     tp->csr6 = new_csr6 | (tp->csr6 & 0xfdff) | (tp->full_duplex ? 0x0200 : 0);
01986     return;
01987 }

static void init_media ( struct nic nic  )  [static]

Definition at line 1603 of file tulip.c.

References AX88140, AX88141, tulip_private::chip_id, COMET, COMPEX9881, CSR12, CSR13, CSR14, CSR15, CSR5, CSR6, tulip_private::csr6, tulip_private::cur_index, DC21041, DC21142, DC21143, tulip_private::default_port, mediatable::defaultmedia, tulip_private::full_duplex, tulip_private::if_port, inl, inw, ioaddr, LC82C168, mediatable::leafcount, mdio_read(), medialeaf::media, media_cap, MediaAlwaysFD, MediaIsMII, medianame, tulip_private::mii_cnt, mediatable::mleaf, tulip_private::mtable, MX98713, MX98715, MX98725, tulip_private::nic_name, NULL, nway_start(), tulip_private::nwayset, outl, tulip_private::phys, PNIC2, pnic_do_nway(), printf(), tulip_private::saved_if_port, select_media(), TPLnkPass, and whereami().

Referenced by tulip_reset().

01604 {
01605     int i;
01606 
01607 #ifdef TULIP_DEBUG_WHERE
01608     whereami("init_media\n");
01609 #endif
01610 
01611     tp->saved_if_port = tp->if_port;
01612     if (tp->if_port == 0)
01613         tp->if_port = tp->default_port;
01614 
01615     /* Allow selecting a default media. */
01616     i = 0;
01617     if (tp->mtable == NULL)
01618         goto media_picked;
01619     if (tp->if_port) {
01620         int looking_for = media_cap[tp->if_port] & MediaIsMII ? 11 :
01621             (tp->if_port == 12 ? 0 : tp->if_port);
01622         for (i = 0; i < tp->mtable->leafcount; i++)
01623             if (tp->mtable->mleaf[i].media == looking_for) {
01624                 printf("%s: Using user-specified media %s.\n",
01625                        tp->nic_name, medianame[tp->if_port]);
01626                 goto media_picked;
01627             }
01628     }
01629     if ((tp->mtable->defaultmedia & 0x0800) == 0) {
01630         int looking_for = tp->mtable->defaultmedia & 15;
01631         for (i = 0; i < tp->mtable->leafcount; i++)
01632             if (tp->mtable->mleaf[i].media == looking_for) {
01633                 printf("%s: Using EEPROM-set media %s.\n",
01634                        tp->nic_name, medianame[looking_for]);
01635                 goto media_picked;
01636             }
01637     }
01638     /* Start sensing first non-full-duplex media. */
01639     for (i = tp->mtable->leafcount - 1;
01640          (media_cap[tp->mtable->mleaf[i].media] & MediaAlwaysFD) && i > 0; i--)
01641         ;
01642  media_picked:
01643 
01644     tp->csr6 = 0;
01645     tp->cur_index = i;
01646     tp->nwayset = 0;
01647 
01648     if (tp->if_port) {
01649         if (tp->chip_id == DC21143  &&  media_cap[tp->if_port] & MediaIsMII) {
01650             /* We must reset the media CSRs when we force-select MII mode. */
01651             outl(0x0000, ioaddr + CSR13);
01652             outl(0x0000, ioaddr + CSR14);
01653             outl(0x0008, ioaddr + CSR15);
01654         }
01655         select_media(nic, 1);
01656         return;
01657     }
01658     switch(tp->chip_id) {
01659     case DC21041:
01660         /* tp->nway = 1;*/
01661         nway_start(nic);
01662         break;
01663     case DC21142:
01664         if (tp->mii_cnt) {
01665             select_media(nic, 1);
01666 #ifdef TULIP_DEBUG
01667             if (tulip_debug > 1)
01668                 printf("%s: Using MII transceiver %d, status %hX.\n",
01669                        tp->nic_name, tp->phys[0], mdio_read(nic, tp->phys[0], 1));
01670 #endif
01671             outl(0x82020000, ioaddr + CSR6);
01672             tp->csr6 = 0x820E0000;
01673             tp->if_port = 11;
01674             outl(0x0000, ioaddr + CSR13);
01675             outl(0x0000, ioaddr + CSR14);
01676         } else
01677             nway_start(nic);
01678         break;
01679     case PNIC2:
01680         nway_start(nic);
01681         break;
01682     case LC82C168:
01683         if (tp->mii_cnt) {
01684             tp->if_port = 11;
01685             tp->csr6 = 0x814C0000 | (tp->full_duplex ? 0x0200 : 0);
01686             outl(0x0001, ioaddr + CSR15);
01687         } else if (inl(ioaddr + CSR5) & TPLnkPass)
01688             pnic_do_nway(nic);
01689         else {
01690             /* Start with 10mbps to do autonegotiation. */
01691             outl(0x32, ioaddr + CSR12);
01692             tp->csr6 = 0x00420000;
01693             outl(0x0001B078, ioaddr + 0xB8);
01694             outl(0x0201B078, ioaddr + 0xB8);
01695         }
01696         break;
01697     case MX98713: case COMPEX9881:
01698         tp->if_port = 0;
01699         tp->csr6 = 0x01880000 | (tp->full_duplex ? 0x0200 : 0);
01700         outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80);
01701         break;
01702     case MX98715: case MX98725:
01703         /* Provided by BOLO, Macronix - 12/10/1998. */
01704         tp->if_port = 0;
01705         tp->csr6 = 0x01a80200;
01706         outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80);
01707         outl(0x11000 | inw(ioaddr + 0xa0), ioaddr + 0xa0);
01708         break;
01709     case COMET:
01710         /* Enable automatic Tx underrun recovery */
01711         outl(inl(ioaddr + 0x88) | 1, ioaddr + 0x88);
01712         tp->if_port = 0;
01713         tp->csr6 = 0x00040000;
01714         break;
01715     case AX88140: case AX88141:
01716         tp->csr6 = tp->mii_cnt ? 0x00040100 : 0x00000100;
01717         break;
01718     default:
01719         select_media(nic, 1);
01720     }
01721 }

static void start_link ( struct nic nic  )  [static]

Definition at line 1448 of file tulip.c.

References tulip_private::advertising, ALWAYS_CHECK_MII, tulip_private::chip_id, COMET, COMPEX9881, CSR12, mediatable::csr12dir, CSR13, CSR14, CSR15, CSR6, tulip_private::cur_index, DC21040, DC21041, DC21140, DC21142, tulip_private::default_port, tulip_private::flags, tulip_private::full_duplex, HAS_MII, mediatable::has_mii, tulip_private::if_port, inl, ioaddr, LC82C168, mediatable::leafcount, mdio_read(), mdio_write(), medialeaf::media, media_cap, MediaIs100, MediaIsMII, tulip_private::mii_advertise, tulip_private::mii_cnt, mediatable::mleaf, tulip_private::mtable, MX98713, MX98715, MX98725, tulip_private::nic_name, tulip_private::nway, nway_start(), tulip_private::nwayset, outl, tulip_private::phys, PNIC2, printf(), tulip_private::saved_if_port, select_media(), tulip_private::sym_advertise, and whereami().

Referenced by tulip_probe().

01449 {
01450     int i;
01451 
01452 #ifdef TULIP_DEBUG_WHERE
01453     whereami("start_link\n");
01454 #endif
01455 
01456     if ((tp->flags & ALWAYS_CHECK_MII) ||
01457         (tp->mtable  &&  tp->mtable->has_mii) ||
01458         ( ! tp->mtable  &&  (tp->flags & HAS_MII))) {
01459         unsigned int phy, phy_idx;
01460         if (tp->mtable  &&  tp->mtable->has_mii) {
01461             for (i = 0; i < tp->mtable->leafcount; i++)
01462                 if (tp->mtable->mleaf[i].media == 11) {
01463                     tp->cur_index = i;
01464                     tp->saved_if_port = tp->if_port;
01465                     select_media(nic, 2);
01466                     tp->if_port = tp->saved_if_port;
01467                     break;
01468                 }
01469         }
01470 
01471         /* Find the connected MII xcvrs. */
01472         for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys);
01473              phy++) {
01474             int mii_status = mdio_read(nic, phy, 1);
01475             if ((mii_status & 0x8301) == 0x8001 ||
01476                 ((mii_status & 0x8000) == 0  && (mii_status & 0x7800) != 0)) {
01477                 int mii_reg0 = mdio_read(nic, phy, 0);
01478                 int mii_advert = mdio_read(nic, phy, 4);
01479                 int to_advert;
01480 
01481                 if (tp->mii_advertise)
01482                     to_advert = tp->mii_advertise;
01483                 else if (tp->advertising[phy_idx])
01484                     to_advert = tp->advertising[phy_idx];
01485                 else                    /* Leave unchanged. */
01486                     tp->mii_advertise = to_advert = mii_advert;
01487 
01488                 tp->phys[phy_idx++] = phy;
01489                 printf("%s:  MII transceiver %d config %hX status %hX advertising %hX.\n",
01490                        tp->nic_name, phy, mii_reg0, mii_status, mii_advert);
01491                                 /* Fixup for DLink with miswired PHY. */
01492                 if (mii_advert != to_advert) {
01493                     printf("%s:  Advertising %hX on PHY %d previously advertising %hX.\n",
01494                            tp->nic_name, to_advert, phy, mii_advert);
01495                     mdio_write(nic, phy, 4, to_advert);
01496                 }
01497                                 /* Enable autonegotiation: some boards default to off. */
01498                 mdio_write(nic, phy, 0, mii_reg0 |
01499                            (tp->full_duplex ? 0x1100 : 0x1000) |
01500                            (media_cap[tp->default_port]&MediaIs100 ? 0x2000:0));
01501             }
01502         }
01503         tp->mii_cnt = phy_idx;
01504         if (tp->mtable  &&  tp->mtable->has_mii  &&  phy_idx == 0) {
01505             printf("%s: ***WARNING***: No MII transceiver found!\n",
01506                    tp->nic_name);
01507             tp->phys[0] = 1;
01508         }
01509     }
01510 
01511     /* Reset the xcvr interface and turn on heartbeat. */
01512     switch (tp->chip_id) {
01513     case DC21040:
01514         outl(0x00000000, ioaddr + CSR13);
01515         outl(0x00000004, ioaddr + CSR13);
01516         break;
01517     case DC21041:
01518         /* This is nway_start(). */
01519         if (tp->sym_advertise == 0)
01520             tp->sym_advertise = 0x0061;
01521         outl(0x00000000, ioaddr + CSR13);
01522         outl(0xFFFFFFFF, ioaddr + CSR14);
01523         outl(0x00000008, ioaddr + CSR15); /* Listen on AUI also. */
01524         outl(inl(ioaddr + CSR6) | 0x0200, ioaddr + CSR6);
01525         outl(0x0000EF01, ioaddr + CSR13);
01526         break;
01527     case DC21140: default:
01528         if (tp->mtable)
01529             outl(tp->mtable->csr12dir | 0x100, ioaddr + CSR12);
01530         break;
01531     case DC21142:
01532     case PNIC2:
01533         if (tp->mii_cnt  ||  media_cap[tp->if_port] & MediaIsMII) {
01534             outl(0x82020000, ioaddr + CSR6);
01535             outl(0x0000, ioaddr + CSR13);
01536             outl(0x0000, ioaddr + CSR14);
01537             outl(0x820E0000, ioaddr + CSR6);
01538         } else
01539             nway_start(nic);
01540         break;
01541     case LC82C168:
01542         if ( ! tp->mii_cnt) {
01543             tp->nway = 1;
01544             tp->nwayset = 0;
01545             outl(0x00420000, ioaddr + CSR6);
01546             outl(0x30, ioaddr + CSR12);
01547             outl(0x0001F078, ioaddr + 0xB8);
01548             outl(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */
01549         }
01550         break;
01551     case MX98713: case COMPEX9881:
01552         outl(0x00000000, ioaddr + CSR6);
01553         outl(0x000711C0, ioaddr + CSR14); /* Turn on NWay. */
01554         outl(0x00000001, ioaddr + CSR13);
01555         break;
01556     case MX98715: case MX98725:
01557         outl(0x01a80000, ioaddr + CSR6);
01558         outl(0xFFFFFFFF, ioaddr + CSR14);
01559         outl(0x00001000, ioaddr + CSR12);
01560         break;
01561     case COMET:
01562         /* No initialization necessary. */
01563         break;
01564     }
01565 }

static int tulip_check_duplex ( struct nic nic  )  [static]

Definition at line 1995 of file tulip.c.

References tulip_private::advertising, tulip_private::csr6, tulip_private::full_duplex, mdio_read(), tulip_private::nic_name, tulip_private::phys, and printf().

Referenced by tulip_reset().

01996 {
01997         unsigned int bmsr, lpa, negotiated, new_csr6;
01998 
01999         bmsr = mdio_read(nic, tp->phys[0], 1);
02000         lpa = mdio_read(nic, tp->phys[0], 5);
02001 
02002 #ifdef TULIP_DEBUG
02003         if (tulip_debug > 1)
02004                 printf("%s: MII status %#x, Link partner report "
02005                            "%#x.\n", tp->nic_name, bmsr, lpa);
02006 #endif
02007 
02008         if (bmsr == 0xffff)
02009                 return -2;
02010         if ((bmsr & 4) == 0) { 
02011                 int new_bmsr = mdio_read(nic, tp->phys[0], 1); 
02012                 if ((new_bmsr & 4) == 0) { 
02013 #ifdef TULIP_DEBUG
02014                         if (tulip_debug  > 1)
02015                                 printf("%s: No link beat on the MII interface,"
02016                                            " status %#x.\n", tp->nic_name, 
02017                                            new_bmsr);
02018 #endif
02019                         return -1;
02020                 }
02021         }
02022         tp->full_duplex = lpa & 0x140;
02023 
02024         new_csr6 = tp->csr6;
02025         negotiated = lpa & tp->advertising[0];
02026 
02027         if(negotiated & 0x380) new_csr6 &= ~0x400000; 
02028         else                   new_csr6 |= 0x400000;
02029         if (tp->full_duplex)   new_csr6 |= 0x200; 
02030         else                   new_csr6 &= ~0x200;
02031 
02032         if (new_csr6 != tp->csr6) {
02033                 tp->csr6 = new_csr6;
02034 
02035 #ifdef TULIP_DEBUG
02036                 if (tulip_debug > 0)
02037                         printf("%s: Setting %s-duplex based on MII"
02038                                    "#%d link partner capability of %#x.\n",
02039                                    tp->nic_name, 
02040                                    tp->full_duplex ? "full" : "half",
02041                                    tp->phys[0], lpa);
02042 #endif
02043                 return 1;
02044         }
02045 
02046         return 0;
02047 }

static void tulip_wait ( unsigned int  nticks  )  [static]

Definition at line 545 of file tulip.c.

References currticks().

Referenced by tulip_probe(), and tulip_reset().

00546 {
00547     unsigned int to = currticks() + nticks;
00548     while (currticks() < to)
00549         /* wait */ ;
00550 }

int mdio_read ( struct nic *nic  __unused,
int  phy_id,
int  location 
)

Definition at line 582 of file tulip.c.

References pcnet32_private::a, tulip_private::chip_id, COMET, CSR9, inl, ioaddr, LC82C168, MDIO_DATA_READ, MDIO_DATA_WRITE1, mdio_delay, MDIO_ENB, MDIO_ENB_IN, MDIO_SHIFT_CLK, pcnet32_private::mii, outl, pcnet32_access::read_bcr, u16, whereami(), and pcnet32_access::write_bcr.

00583 {
00584     int i;
00585     int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
00586     int retval = 0;
00587     long mdio_addr = ioaddr + CSR9;
00588 
00589 #ifdef TULIP_DEBUG_WHERE
00590     whereami("mdio_read\n");
00591 #endif
00592 
00593     if (tp->chip_id == LC82C168) {
00594         int i = 1000;
00595         outl(0x60020000 + (phy_id<<23) + (location<<18), ioaddr + 0xA0);
00596         inl(ioaddr + 0xA0);
00597         inl(ioaddr + 0xA0);
00598         while (--i > 0)
00599             if ( ! ((retval = inl(ioaddr + 0xA0)) & 0x80000000))
00600                 return retval & 0xffff;
00601         return 0xffff;
00602     }
00603 
00604     if (tp->chip_id == COMET) {
00605         if (phy_id == 1) {
00606             if (location < 7)
00607                 return inl(ioaddr + 0xB4 + (location<<2));
00608             else if (location == 17)
00609                 return inl(ioaddr + 0xD0);
00610             else if (location >= 29 && location <= 31)
00611                 return inl(ioaddr + 0xD4 + ((location-29)<<2));
00612         }
00613         return 0xffff;
00614     }
00615 
00616     /* Establish sync by sending at least 32 logic ones. */
00617     for (i = 32; i >= 0; i--) {
00618         outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
00619         mdio_delay();
00620         outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
00621         mdio_delay();
00622     }
00623     /* Shift the read command bits out. */
00624     for (i = 15; i >= 0; i--) {
00625         int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
00626 
00627         outl(MDIO_ENB | dataval, mdio_addr);
00628         mdio_delay();
00629         outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
00630         mdio_delay();
00631     }
00632     /* Read the two transition, 16 data, and wire-idle bits. */
00633     for (i = 19; i > 0; i--) {
00634         outl(MDIO_ENB_IN, mdio_addr);
00635         mdio_delay();
00636         retval = (retval << 1) | ((inl(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
00637         outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
00638         mdio_delay();
00639     }
00640     return (retval>>1) & 0xffff;
00641 }

void mdio_write ( struct nic *nic  __unused,
int  phy_id,
int  location,
int  value 
)

Definition at line 643 of file tulip.c.

References tulip_private::chip_id, COMET, CSR9, inl, ioaddr, LC82C168, MDIO_DATA_WRITE1, mdio_delay, MDIO_ENB, MDIO_ENB_IN, MDIO_SHIFT_CLK, outl, and whereami().

00644 {
00645     int i;
00646     int cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
00647     long mdio_addr = ioaddr + CSR9;
00648 
00649 #ifdef TULIP_DEBUG_WHERE
00650     whereami("mdio_write\n");
00651 #endif
00652 
00653     if (tp->chip_id == LC82C168) {
00654         int i = 1000;
00655         outl(cmd, ioaddr + 0xA0);
00656         do
00657             if ( ! (inl(ioaddr + 0xA0) & 0x80000000))
00658                 break;
00659         while (--i > 0);
00660         return;
00661     }
00662 
00663     if (tp->chip_id == COMET) {
00664         if (phy_id != 1)
00665             return;
00666         if (location < 7)
00667             outl(value, ioaddr + 0xB4 + (location<<2));
00668         else if (location == 17)
00669             outl(value, ioaddr + 0xD0);
00670         else if (location >= 29 && location <= 31)
00671             outl(value, ioaddr + 0xD4 + ((location-29)<<2));
00672         return;
00673     }
00674 
00675     /* Establish sync by sending 32 logic ones. */
00676     for (i = 32; i >= 0; i--) {
00677         outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
00678         mdio_delay();
00679         outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
00680         mdio_delay();
00681     }
00682     /* Shift the command bits out. */
00683     for (i = 31; i >= 0; i--) {
00684         int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
00685         outl(MDIO_ENB | dataval, mdio_addr);
00686         mdio_delay();
00687         outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
00688         mdio_delay();
00689     }
00690     /* Clear out extra bits. */
00691     for (i = 2; i > 0; i--) {
00692         outl(MDIO_ENB_IN, mdio_addr);
00693         mdio_delay();
00694         outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
00695         mdio_delay();
00696     }
00697 }

static void tulip_init_ring ( struct nic *nic  __unused  )  [static]

Definition at line 916 of file tulip.c.

References BUFLEN, cpu_to_le32, tulip_private::cur_rx, DESC_RING_WRAP, rx_ring, RX_RING_SIZE, rxb, tx_ring, txb, virt_to_le32desc, and whereami().

00917 {
00918     int i;
00919 
00920 #ifdef TULIP_DEBUG_WHERE
00921     whereami("tulip_init_ring\n");
00922 #endif
00923 
00924     tp->cur_rx = 0;
00925 
00926     for (i = 0; i < RX_RING_SIZE; i++) {
00927         rx_ring[i].status  = cpu_to_le32(0x80000000);
00928         rx_ring[i].length  = cpu_to_le32(BUFLEN);
00929         rx_ring[i].buffer1 = virt_to_le32desc(&rxb[i * BUFLEN]);
00930         rx_ring[i].buffer2 = virt_to_le32desc(&rx_ring[i+1]);
00931     }
00932     /* Mark the last entry as wrapping the ring. */
00933     rx_ring[i-1].length    = cpu_to_le32(DESC_RING_WRAP | BUFLEN);
00934     rx_ring[i-1].buffer2   = virt_to_le32desc(&rx_ring[0]);
00935 
00936     /* We only use 1 transmit buffer, but we use 2 descriptors so
00937        transmit engines have somewhere to point to if they feel the need */
00938 
00939     tx_ring[0].status  = 0x00000000;
00940     tx_ring[0].buffer1 = virt_to_le32desc(&txb[0]);
00941     tx_ring[0].buffer2 = virt_to_le32desc(&tx_ring[1]);
00942 
00943     /* this descriptor should never get used, since it will never be owned
00944        by the machine (status will always == 0) */
00945     tx_ring[1].status  = 0x00000000;
00946     tx_ring[1].buffer1 = virt_to_le32desc(&txb[0]);
00947     tx_ring[1].buffer2 = virt_to_le32desc(&tx_ring[0]);
00948 
00949     /* Mark the last entry as wrapping the ring, though this should never happen */
00950     tx_ring[1].length  = cpu_to_le32(DESC_RING_WRAP | BUFLEN);
00951 }

static void set_rx_mode ( struct nic *nic  __unused  )  [static]

Definition at line 954 of file tulip.c.

References AcceptAllMulticast, tulip_private::csr6, CSR6, inl, ioaddr, and outl.

00954                                                   {
00955         int csr6 = inl(ioaddr + CSR6) & ~0x00D5;
00956 
00957         tp->csr6 &= ~0x00D5;
00958  
00959         /* !IFF_PROMISC */
00960         tp->csr6 |= AcceptAllMulticast;
00961         csr6 |= AcceptAllMulticast;
00962 
00963         outl(csr6, ioaddr + CSR6);
00964 
00965         
00966         
00967 }

static void tulip_irq ( struct nic *nic  __unused,
irq_action_t action  __unused 
) [static]

Definition at line 1212 of file tulip.c.

References DISABLE, ENABLE, and FORCE.

01213 {
01214   switch ( action ) {
01215   case DISABLE :
01216     break;
01217   case ENABLE :
01218     break;
01219   case FORCE :
01220     break;
01221   }
01222 }

static void nway_start ( struct nic *nic  __unused  )  [static]

Definition at line 1567 of file tulip.c.

References tulip_private::chip_id, CSR12, CSR13, CSR14, CSR15, mediatable::csr15dir, mediatable::csr15val, CSR6, tulip_private::csr6, DC21041, tulip_private::if_port, ioaddr, tulip_private::lpar, tulip_private::mediasense, tulip_private::mtable, tulip_private::nic_name, tulip_private::nway, tulip_private::nwayset, outl, outw, PNIC2, printf(), tulip_private::sym_advertise, and whereami().

01568 {
01569     int csr14 = ((tp->sym_advertise & 0x0780) << 9)  |
01570         ((tp->sym_advertise&0x0020)<<1) | 0xffbf;
01571 
01572 #ifdef TULIP_DEBUG_WHERE
01573     whereami("nway_start\n");
01574 #endif
01575 
01576     tp->if_port = 0;
01577     tp->nway = tp->mediasense = 1;
01578     tp->nwayset = tp->lpar = 0;
01579     if (tp->chip_id == PNIC2) {
01580         tp->csr6 = 0x01000000 | (tp->sym_advertise & 0x0040 ? 0x0200 : 0);
01581         return;
01582     }
01583 #ifdef TULIP_DEBUG
01584     if (tulip_debug > 1)
01585         printf("%s: Restarting internal NWay autonegotiation, %X.\n",
01586                tp->nic_name, csr14);
01587 #endif
01588     outl(0x0001, ioaddr + CSR13);
01589     outl(csr14, ioaddr + CSR14);
01590     tp->csr6 = 0x82420000 | (tp->sym_advertise & 0x0040 ? 0x0200 : 0);
01591     outl(tp->csr6, ioaddr + CSR6);
01592     if (tp->mtable  &&  tp->mtable->csr15dir) {
01593         outl(tp->mtable->csr15dir, ioaddr + CSR15);
01594         outl(tp->mtable->csr15val, ioaddr + CSR15);
01595     } else if (tp->chip_id != PNIC2)
01596         outw(0x0008, ioaddr + CSR15);
01597     if (tp->chip_id == DC21041)                 /* Trigger NWAY. */
01598         outl(0xEF01, ioaddr + CSR12);
01599     else
01600         outl(0x1301, ioaddr + CSR12);
01601 }

static void pnic_do_nway ( struct nic *nic  __unused  )  [static]

Definition at line 1723 of file tulip.c.

References CSR12, CSR6, tulip_private::csr6, tulip_private::full_duplex, tulip_private::if_port, inl, ioaddr, medianame, tulip_private::nic_name, tulip_private::nwayset, outl, printf(), u32, and whereami().

01724 {
01725     u32 phy_reg = inl(ioaddr + 0xB8);
01726     u32 new_csr6 = tp->csr6 & ~0x40C40200;
01727 
01728 #ifdef TULIP_DEBUG_WHERE
01729     whereami("pnic_do_nway\n");
01730 #endif
01731 
01732     if (phy_reg & 0x78000000) { /* Ignore baseT4 */
01733         if (phy_reg & 0x20000000)               tp->if_port = 5;
01734         else if (phy_reg & 0x40000000)  tp->if_port = 3;
01735         else if (phy_reg & 0x10000000)  tp->if_port = 4;
01736         else if (phy_reg & 0x08000000)  tp->if_port = 0;
01737         tp->nwayset = 1;
01738         new_csr6 = (tp->if_port & 1) ? 0x01860000 : 0x00420000;
01739         outl(0x32 | (tp->if_port & 1), ioaddr + CSR12);
01740         if (tp->if_port & 1)
01741             outl(0x1F868, ioaddr + 0xB8);
01742         if (phy_reg & 0x30000000) {
01743             tp->full_duplex = 1;
01744             new_csr6 |= 0x00000200;
01745         }
01746 #ifdef TULIP_DEBUG
01747         if (tulip_debug > 1)
01748             printf("%s: PNIC autonegotiated status %X, %s.\n",
01749                    tp->nic_name, phy_reg, medianame[tp->if_port]);
01750 #endif
01751         if (tp->csr6 != new_csr6) {
01752             tp->csr6 = new_csr6;
01753             outl(tp->csr6 | 0x0002, ioaddr + CSR6);     /* Restart Tx */
01754             outl(tp->csr6 | 0x2002, ioaddr + CSR6);
01755         }
01756     }
01757 }

PCI_DRIVER ( tulip_driver  ,
tulip_nics  ,
PCI_NO_CLASS   
)

DRIVER ( "Tulip"  ,
nic_driver  ,
pci_driver  ,
tulip_driver  ,
tulip_probe  ,
tulip_disable   
)


Variable Documentation

const int csr0 = 0x01A00000 | 0x8000 [static]

Definition at line 143 of file tulip.c.

Referenced by tulip_probe().

const char* const medianame[32] [static]

Initial value:

 {
    "10baseT", "10base2", "AUI", "100baseTx",
    "10baseT-FDX", "100baseTx-FDX", "100baseT4", "100baseFx",
    "100baseFx-FDX", "MII 10baseT", "MII 10baseT-FDX", "MII",
    "10baseT(forced)", "MII 100baseTx", "MII 100baseTx-FDX", "MII 100baseT4",
    "MII 100baseFx-HDX", "MII 100baseFx-FDX", "Home-PNA 1Mbps", "Invalid-19",
}

Definition at line 147 of file tulip.c.

Referenced by init_media(), parse_eeprom(), pnic_do_nway(), and select_media().

struct pci_id_info pci_id_tbl[] [static]

Definition at line 182 of file tulip.c.

struct tulip_chip_table tulip_tbl[] [static]

Referenced by tulip_probe().

const char media_cap[32] [static]

Initial value:

{0,0,0,16,  3,19,16,24,  27,4,7,5, 0,20,23,20, 20,31,0,0, }

Definition at line 281 of file tulip.c.

Referenced by init_media(), select_media(), start_link(), and tulip_probe().

u8 t21040_csr13[] = {2,0x0C,8,4, 4,0,0,0, 0,0,0,0, 4,0,0,0} [static]

Definition at line 283 of file tulip.c.

Referenced by select_media().

u16 t21041_csr13[] = { 0xEF01, 0xEF09, 0xEF09, 0xEF01, 0xEF09, } [static]

Definition at line 286 of file tulip.c.

Referenced by select_media().

u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, } [static]

Definition at line 287 of file tulip.c.

Referenced by select_media().

u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, } [static]

Definition at line 288 of file tulip.c.

Referenced by select_media().

u16 t21142_csr14[] = { 0xFFFF, 0x0705, 0x0705, 0x0000, 0x7F3D, } [static]

Definition at line 293 of file tulip.c.

Referenced by select_media().

u32 ioaddr [static]

Definition at line 399 of file tulip.c.

struct tulip_tx_desc tx_ring[TX_RING_SIZE]

Definition at line 436 of file tulip.c.

unsigned char txb[BUFLEN]

Definition at line 437 of file tulip.c.

struct tulip_rx_desc rx_ring[RX_RING_SIZE]

Definition at line 438 of file tulip.c.

unsigned char rxb[RX_RING_SIZE *BUFLEN]

Definition at line 439 of file tulip.c.

Definition at line 440 of file tulip.c.

struct { ... } __shared

struct tulip_private* tp [static]

struct fixups eeprom_fixups[] [static]

Referenced by parse_eeprom().

const char* block_name[] [static]

Initial value:

 {"21140 non-MII", "21140 MII PHY",
                                    "21142 Serial PHY", "21142 MII PHY", "21143 SYM PHY", "21143 reset method"}

Definition at line 486 of file tulip.c.

Initial value:

 {
        .connect        = dummy_connect,
        .poll           = tulip_poll,
        .transmit       = tulip_transmit,
        .irq            = tulip_irq,

}

Definition at line 1224 of file tulip.c.

struct pci_device_id tulip_nics[] [static]

Definition at line 2049 of file tulip.c.


Generated on Tue Apr 6 20:01:43 2010 for gPXE by  doxygen 1.5.7.1