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

Go to the source code of this file.

Data Structures

struct  w840_rx_desc
 
struct  w840_tx_desc
 
struct  winbond_private
 

Macros

#define USE_IO_OPS
 
#define virt_to_le32desc(addr)   virt_to_bus(addr)
 
#define le32desc_to_virt(addr)   bus_to_virt(addr)
 
#define TX_RING_SIZE   2
 
#define RX_RING_SIZE   2
 
#define TX_FIFO_SIZE   (2048)
 
#define TX_BUG_FIFO_LIMIT   (TX_FIFO_SIZE-1514-16)
 
#define TX_TIMEOUT   (10*1000)
 
#define PKT_BUF_SZ   1536 /* Size of each temporary Rx buffer.*/
 
#define W840_FLAGS   (PCI_USES_IO | PCI_ADDR0 | PCI_USES_MASTER)
 
#define readb   inb
 
#define readw   inw
 
#define readl   inl
 
#define writeb   outb
 
#define writew   outw
 
#define writel   outl
 
#define PRIV_ALIGN   15 /* Required alignment mask */
 
#define PRIV_ALIGN_BYTES   32
 
#define PCI_VENDOR_ID_WINBOND2   0x1050
 
#define PCI_DEVICE_ID_WINBOND2_89C840   0x0840
 
#define PCI_VENDOR_ID_COMPEX   0x11f6
 
#define PCI_DEVICE_ID_COMPEX_RL100ATX   0x2011
 
#define eeprom_delay(ee_addr)   readl(ee_addr)
 
#define mdio_delay(mdio_addr)   readl(mdio_addr)
 
#define MDIO_WRITE0   (MDIO_EnbOutput)
 
#define MDIO_WRITE1   (MDIO_DataOut | MDIO_EnbOutput)
 

Enumerations

enum  chip_capability_flags { CanHaveMII = 1, KendinPktDropBug = 2, CanHaveMII =1, HasBrokenTx =2 }
 
enum  w840_offsets {
  PCIBusCfg =0x00, TxStartDemand =0x04, RxStartDemand =0x08, RxRingPtr =0x0C,
  TxRingPtr =0x10, IntrStatus =0x14, NetworkConfig =0x18, IntrEnable =0x1C,
  RxMissed =0x20, EECtrl =0x24, MIICtrl =0x24, BootRom =0x28,
  GPTimer =0x2C, CurRxDescAddr =0x30, CurRxBufAddr =0x34, MulticastFilter0 =0x38,
  MulticastFilter1 =0x3C, StationAddr =0x40, CurTxDescAddr =0x4C, CurTxBufAddr =0x50
}
 
enum  intr_status_bits {
  IntrSummary = 0x0001, IntrPCIErr = 0x0002, IntrMACCtrl = 0x0008, IntrTxDone = 0x0004,
  IntrRxDone = 0x0010, IntrRxStart = 0x0020, IntrDrvRqst = 0x0040, StatsMax = 0x0080,
  LinkChange = 0x0100, IntrTxDMADone = 0x0200, IntrRxDMADone = 0x0400, NormalIntr =0x10000,
  AbnormalIntr =0x8000, IntrPCIErr =0x2000, TimerInt =0x800, IntrRxDied =0x100,
  RxNoBuf =0x80, IntrRxDone =0x40, TxFIFOUnderflow =0x20, RxErrIntr =0x10,
  TxIdle =0x04, IntrTxStopped =0x02, IntrTxDone =0x01
}
 
enum  rx_mode_bits {
  AcceptAllIPMulti = 0x20, AcceptMultiHash = 0x10, AcceptAll = 0x08, AcceptBroadcast = 0x04,
  AcceptMulticast = 0x02, AcceptMyPhys, AcceptErr =0x80, AcceptRunt =0x40,
  AcceptBroadcast =0x20, AcceptMulticast =0x10, AcceptAllPhys =0x08, AcceptMyPhys =0x02
}
 
enum  mii_reg_bits {
  MDIO_ShiftClk = 0x0001, MDIO_Data = 0x0002, MDIO_EnbOutput, MDIO_ShiftClk =0x10000,
  MDIO_DataIn =0x80000, MDIO_DataOut =0x20000, MDIO_EnbOutput =0x40000, MDIO_EnbIn = 0x00000
}
 
enum  desc_status_bits {
  DescOwn = 0x8000, DescEndPacket = 0x4000, DescEndRing = 0x2000, LastFrag = 0x80000000,
  DescIntrOnTx = 0x8000, DescIntrOnDMADone = 0x80000000, DisableAlign = 0x00000001, DescOwnded =0x80000000,
  RxDescFatalErr =0x8000, RxWholePkt =0x0300, DescOwn =0x80000000, DescEndRing =0x02000000,
  DescUseLink =0x01000000, DescWholePkt =0x60000000, DescStartPkt =0x20000000, DescEndPkt =0x40000000,
  DescIntr =0x80000000
}
 
enum  EEPROM_Ctrl_Bits {
  EE_ShiftClk =0x02, EE_Write0 =0x801, EE_Write1 =0x805, EE_ChipSelect =0x801,
  EE_DataIn =0x08
}
 
enum  EEPROM_Cmds { EE_WriteCmd =(5 << 6), EE_ReadCmd =(6 << 6), EE_EraseCmd =(7 << 6) }
 

Functions

 FILE_LICENCE (GPL2_OR_LATER)
 
static int eeprom_read (long ioaddr, int location)
 
static int mdio_read (int base_address, int phy_id, int location)
 
static void check_duplex (void)
 
static void set_rx_mode (void)
 
static void init_ring (void)
 
static void w89c840_reset (struct nic *nic)
 
static int w89c840_poll (struct nic *nic, int retrieve)
 
static void w89c840_transmit (struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p)
 
static void w89c840_disable (struct nic *nic)
 
static void w89c840_irq (struct nic *nic __unused, irq_action_t action __unused)
 
 PCI_DRIVER (w89c840_driver, w89c840_nics, PCI_NO_CLASS)
 
static int w89c840_probe (struct nic *nic, struct pci_device *p)
 
static void mdio_sync (long mdio_addr)
 
 DRIVER ("W89C840F", nic_driver, pci_driver, w89c840_driver, w89c840_probe, w89c840_disable)
 

Variables

static const char * w89c840_version = "driver Version 0.94 - December 12, 2003"
 
static u32 driver_flags = CanHaveMII | HasBrokenTx
 
static struct winbond_private w840private
 
static int ioaddr
 
static unsigned short eeprom [0x40]
 
struct {
   char   rx_packet [PKT_BUF_SZ *RX_RING_SIZE]
 
   char   tx_packet [PKT_BUF_SZ *TX_RING_SIZE]
 
__shared
 
static struct nic_operations w89c840_operations
 
static struct pci_device_id w89c840_nics []
 
static char mii_preamble_required = 1
 

Macro Definition Documentation

◆ USE_IO_OPS

#define USE_IO_OPS

Definition at line 81 of file w89c840.c.

◆ virt_to_le32desc

#define virt_to_le32desc (   addr)    virt_to_bus(addr)

Definition at line 91 of file w89c840.c.

◆ le32desc_to_virt

#define le32desc_to_virt (   addr)    bus_to_virt(addr)

Definition at line 92 of file w89c840.c.

◆ TX_RING_SIZE

#define TX_RING_SIZE   2

Definition at line 106 of file w89c840.c.

◆ RX_RING_SIZE

#define RX_RING_SIZE   2

Definition at line 107 of file w89c840.c.

◆ TX_FIFO_SIZE

#define TX_FIFO_SIZE   (2048)

Definition at line 113 of file w89c840.c.

◆ TX_BUG_FIFO_LIMIT

#define TX_BUG_FIFO_LIMIT   (TX_FIFO_SIZE-1514-16)

Definition at line 114 of file w89c840.c.

◆ TX_TIMEOUT

#define TX_TIMEOUT   (10*1000)

Definition at line 118 of file w89c840.c.

◆ PKT_BUF_SZ

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

Definition at line 120 of file w89c840.c.

◆ W840_FLAGS

#define W840_FLAGS   (PCI_USES_IO | PCI_ADDR0 | PCI_USES_MASTER)

Definition at line 137 of file w89c840.c.

◆ readb

#define readb   inb

Definition at line 155 of file w89c840.c.

◆ readw

#define readw   inw

Definition at line 156 of file w89c840.c.

◆ readl

#define readl   inl

Definition at line 157 of file w89c840.c.

◆ writeb

#define writeb   outb

Definition at line 158 of file w89c840.c.

◆ writew

#define writew   outw

Definition at line 159 of file w89c840.c.

◆ writel

#define writel   outl

Definition at line 160 of file w89c840.c.

◆ PRIV_ALIGN

#define PRIV_ALIGN   15 /* Required alignment mask */

Definition at line 221 of file w89c840.c.

◆ PRIV_ALIGN_BYTES

#define PRIV_ALIGN_BYTES   32

Definition at line 222 of file w89c840.c.

◆ PCI_VENDOR_ID_WINBOND2

#define PCI_VENDOR_ID_WINBOND2   0x1050

◆ PCI_DEVICE_ID_WINBOND2_89C840

#define PCI_DEVICE_ID_WINBOND2_89C840   0x0840

◆ PCI_VENDOR_ID_COMPEX

#define PCI_VENDOR_ID_COMPEX   0x11f6

◆ PCI_DEVICE_ID_COMPEX_RL100ATX

#define PCI_DEVICE_ID_COMPEX_RL100ATX   0x2011

◆ eeprom_delay

#define eeprom_delay (   ee_addr)    readl(ee_addr)

Definition at line 734 of file w89c840.c.

◆ mdio_delay

#define mdio_delay (   mdio_addr)    readl(mdio_addr)

Definition at line 784 of file w89c840.c.

◆ MDIO_WRITE0

#define MDIO_WRITE0   (MDIO_EnbOutput)

Definition at line 791 of file w89c840.c.

◆ MDIO_WRITE1

#define MDIO_WRITE1   (MDIO_DataOut | MDIO_EnbOutput)

Definition at line 792 of file w89c840.c.

Enumeration Type Documentation

◆ chip_capability_flags

Enumerator
CanHaveMII 
KendinPktDropBug 
CanHaveMII 
HasBrokenTx 

Definition at line 134 of file w89c840.c.

◆ w840_offsets

Enumerator
PCIBusCfg 
TxStartDemand 
RxStartDemand 
RxRingPtr 
TxRingPtr 
IntrStatus 
NetworkConfig 
IntrEnable 
RxMissed 
EECtrl 
MIICtrl 
BootRom 
GPTimer 
CurRxDescAddr 
CurRxBufAddr 
MulticastFilter0 
MulticastFilter1 
StationAddr 
CurTxDescAddr 
CurTxBufAddr 

Definition at line 169 of file w89c840.c.

169  {
170  PCIBusCfg=0x00, TxStartDemand=0x04, RxStartDemand=0x08,
171  RxRingPtr=0x0C, TxRingPtr=0x10,
172  IntrStatus=0x14, NetworkConfig=0x18, IntrEnable=0x1C,
173  RxMissed=0x20, EECtrl=0x24, MIICtrl=0x24, BootRom=0x28, GPTimer=0x2C,
174  CurRxDescAddr=0x30, CurRxBufAddr=0x34, /* Debug use */
176  CurTxDescAddr=0x4C, CurTxBufAddr=0x50,
177 };

◆ intr_status_bits

Enumerator
IntrSummary 
IntrPCIErr 
IntrMACCtrl 
IntrTxDone 
IntrRxDone 
IntrRxStart 
IntrDrvRqst 
StatsMax 
LinkChange 
IntrTxDMADone 
IntrRxDMADone 
NormalIntr 
AbnormalIntr 
IntrPCIErr 
TimerInt 
IntrRxDied 
RxNoBuf 
IntrRxDone 
TxFIFOUnderflow 
RxErrIntr 
TxIdle 
IntrTxStopped 
IntrTxDone 

Definition at line 181 of file w89c840.c.

181  {
182  NormalIntr=0x10000, AbnormalIntr=0x8000,
183  IntrPCIErr=0x2000, TimerInt=0x800,
184  IntrRxDied=0x100, RxNoBuf=0x80, IntrRxDone=0x40,
185  TxFIFOUnderflow=0x20, RxErrIntr=0x10,
186  TxIdle=0x04, IntrTxStopped=0x02, IntrTxDone=0x01,
187 };

◆ rx_mode_bits

Enumerator
AcceptAllIPMulti 
AcceptMultiHash 
AcceptAll 
AcceptBroadcast 
AcceptMulticast 
AcceptMyPhys 
AcceptErr 
AcceptRunt 
AcceptBroadcast 
AcceptMulticast 
AcceptAllPhys 
AcceptMyPhys 

Definition at line 190 of file w89c840.c.

190  {
191  AcceptErr=0x80, AcceptRunt=0x40,
192  AcceptBroadcast=0x20, AcceptMulticast=0x10,
193  AcceptAllPhys=0x08, AcceptMyPhys=0x02,
194 };

◆ mii_reg_bits

Enumerator
MDIO_ShiftClk 
MDIO_Data 
MDIO_EnbOutput 
MDIO_ShiftClk 
MDIO_DataIn 
MDIO_DataOut 
MDIO_EnbOutput 
MDIO_EnbIn 

Definition at line 196 of file w89c840.c.

196  {
197  MDIO_ShiftClk=0x10000, MDIO_DataIn=0x80000, MDIO_DataOut=0x20000,
198  MDIO_EnbOutput=0x40000, MDIO_EnbIn = 0x00000,
199 };

◆ desc_status_bits

Enumerator
DescOwn 
DescEndPacket 
DescEndRing 
LastFrag 
DescIntrOnTx 
DescIntrOnDMADone 
DisableAlign 
DescOwnded 
RxDescFatalErr 
RxWholePkt 
DescOwn 
DescEndRing 
DescUseLink 
DescWholePkt 
DescStartPkt 
DescEndPkt 
DescIntr 

Definition at line 216 of file w89c840.c.

216  {
217  DescOwn=0x80000000, DescEndRing=0x02000000, DescUseLink=0x01000000,
218  DescWholePkt=0x60000000, DescStartPkt=0x20000000, DescEndPkt=0x40000000,
219  DescIntr=0x80000000,
220 };

◆ EEPROM_Ctrl_Bits

Enumerator
EE_ShiftClk 
EE_Write0 
EE_Write1 
EE_ChipSelect 
EE_DataIn 

Definition at line 736 of file w89c840.c.

736  {
737  EE_ShiftClk=0x02, EE_Write0=0x801, EE_Write1=0x805,
738  EE_ChipSelect=0x801, EE_DataIn=0x08,
739 };

◆ EEPROM_Cmds

Enumerator
EE_WriteCmd 
EE_ReadCmd 
EE_EraseCmd 

Definition at line 742 of file w89c840.c.

742  {
743  EE_WriteCmd=(5 << 6), EE_ReadCmd=(6 << 6), EE_EraseCmd=(7 << 6),
744 };

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER  )

◆ eeprom_read()

static int eeprom_read ( long  ioaddr,
int  location 
)
static

Definition at line 746 of file w89c840.c.

747 {
748  int i;
749  int retval = 0;
750  int ee_addr = addr + EECtrl;
751  int read_cmd = location | EE_ReadCmd;
752  writel(EE_ChipSelect, ee_addr);
753 
754  /* Shift the read command bits out. */
755  for (i = 10; i >= 0; i--) {
756  short dataval = (read_cmd & (1 << i)) ? EE_Write1 : EE_Write0;
757  writel(dataval, ee_addr);
758  eeprom_delay(ee_addr);
759  writel(dataval | EE_ShiftClk, ee_addr);
760  eeprom_delay(ee_addr);
761  }
762  writel(EE_ChipSelect, ee_addr);
763 
764  for (i = 16; i > 0; i--) {
765  writel(EE_ChipSelect | EE_ShiftClk, ee_addr);
766  eeprom_delay(ee_addr);
767  retval = (retval << 1) | ((readl(ee_addr) & EE_DataIn) ? 1 : 0);
768  writel(EE_ChipSelect, ee_addr);
769  eeprom_delay(ee_addr);
770  }
771 
772  /* Terminate the EEPROM access. */
773  writel(0, ee_addr);
774  return retval;
775 }
#define eeprom_delay(ee_addr)
Definition: w89c840.c:734
#define writel
Definition: w89c840.c:160
u32 addr
Definition: sky2.h:8
unsigned long retval
Definition: xen.h:45
#define readl
Definition: w89c840.c:157

References addr, EE_ChipSelect, EE_DataIn, EE_ReadCmd, EE_ShiftClk, EE_Write0, EE_Write1, EECtrl, eeprom_delay, readl, retval, and writel.

Referenced by w89c840_probe().

◆ mdio_read()

static int mdio_read ( int  base_address,
int  phy_id,
int  location 
)
static

Definition at line 809 of file w89c840.c.

810 {
811  long mdio_addr = base_address + MIICtrl;
812  int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
813  int i, retval = 0;
814 
816  mdio_sync(mdio_addr);
817 
818  /* Shift the read command bits out. */
819  for (i = 15; i >= 0; i--) {
820  int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
821 
822  writel(dataval, mdio_addr);
823  mdio_delay(mdio_addr);
824  writel(dataval | MDIO_ShiftClk, mdio_addr);
825  mdio_delay(mdio_addr);
826  }
827  /* Read the two transition, 16 data, and wire-idle bits. */
828  for (i = 20; i > 0; i--) {
829  writel(MDIO_EnbIn, mdio_addr);
830  mdio_delay(mdio_addr);
831  retval = (retval << 1) | ((readl(mdio_addr) & MDIO_DataIn) ? 1 : 0);
832  writel(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
833  mdio_delay(mdio_addr);
834  }
835  return (retval>>1) & 0xffff;
836 }
#define MDIO_WRITE1
Definition: w89c840.c:792
#define MDIO_WRITE0
Definition: w89c840.c:791
#define writel
Definition: w89c840.c:160
static void mdio_sync(long mdio_addr)
Definition: w89c840.c:796
unsigned long retval
Definition: xen.h:45
static char mii_preamble_required
Definition: w89c840.c:789
#define mdio_delay(mdio_addr)
Definition: w89c840.c:784
#define readl
Definition: w89c840.c:157

References MDIO_DataIn, mdio_delay, MDIO_EnbIn, MDIO_ShiftClk, mdio_sync(), MDIO_WRITE0, MDIO_WRITE1, mii_preamble_required, MIICtrl, readl, retval, and writel.

Referenced by check_duplex(), and w89c840_probe().

◆ check_duplex()

static void check_duplex ( void  )
static

Definition at line 871 of file w89c840.c.

872 {
873  int mii_reg5 = mdio_read(ioaddr, w840private.phys[0], 5);
874  int negotiated = mii_reg5 & w840private.advertising;
875  int duplex;
876 
877  if (w840private.duplex_lock || mii_reg5 == 0xffff)
878  return;
879 
880  duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
881  if (w840private.full_duplex != duplex) {
883 
884 #if defined(W89C840_DEBUG)
885  printf("winbond-840 : Setting %s-duplex based on MII # %d negotiated capability %X\n",
886  duplex ? "full" : "half", w840private.phys[0], negotiated);
887 #endif
888 
889  w840private.csr6 &= ~0x200;
890  w840private.csr6 |= duplex ? 0x200 : 0;
891  }
892 }
int printf(const char *fmt,...)
Write a formatted string to the console.
Definition: vsprintf.c:464
static int mdio_read(int base_address, int phy_id, int location)
Definition: w89c840.c:809
static int ioaddr
Definition: w89c840.c:255
unsigned char phys[4]
Definition: w89c840.c:250
unsigned int duplex_lock
Definition: w89c840.c:244
duplex
Definition: nic.h:40
unsigned int full_duplex
Definition: w89c840.c:243
static struct winbond_private w840private

References winbond_private::advertising, winbond_private::csr6, winbond_private::duplex_lock, winbond_private::full_duplex, ioaddr, mdio_read(), winbond_private::phys, printf(), and w840private.

Referenced by w89c840_reset().

◆ set_rx_mode()

static void set_rx_mode ( void  )
static

Definition at line 894 of file w89c840.c.

895 {
896  u32 mc_filter[2]; /* Multicast hash filter */
897  u32 rx_mode;
898 
899  /* Accept all multicasts from now on. */
900  memset(mc_filter, 0xff, sizeof(mc_filter));
901 
902 /*
903  * works OK with multicast enabled.
904  */
905 
907 
908  writel(mc_filter[0], ioaddr + MulticastFilter0);
909  writel(mc_filter[1], ioaddr + MulticastFilter1);
910  w840private.csr6 &= ~0x00F8;
911  w840private.csr6 |= rx_mode;
913 
914 #if defined(W89C840_DEBUG)
915  printf("winbond-840 : Done setting RX mode.\n");
916 #endif
917 }
int printf(const char *fmt,...)
Write a formatted string to the console.
Definition: vsprintf.c:464
static int ioaddr
Definition: w89c840.c:255
#define writel
Definition: w89c840.c:160
static struct winbond_private w840private
uint32_t u32
Definition: stdint.h:23
void * memset(void *dest, int character, size_t len) __nonnull

References AcceptBroadcast, AcceptMulticast, AcceptMyPhys, winbond_private::csr6, ioaddr, memset(), MulticastFilter0, MulticastFilter1, NetworkConfig, printf(), w840private, and writel.

Referenced by w89c840_reset().

◆ init_ring()

static void init_ring ( void  )
static

Definition at line 920 of file w89c840.c.

921 {
922  int i;
923  char * p;
924 
925  w840private.tx_full = 0;
928 
931 
932  /* Initial all Rx descriptors. Fill in the Rx buffers. */
933 
934  p = &w89c840_buf.rx_packet[0];
935 
936  for (i = 0; i < RX_RING_SIZE; i++) {
938  w840private.rx_ring[i].status = 0;
940 
943  }
944 
945  /* Mark the last entry as wrapping the ring. */
948 
949  w840private.dirty_rx = (unsigned int)(i - RX_RING_SIZE);
950 
951  for (i = 0; i < TX_RING_SIZE; i++) {
952  w840private.tx_ring[i].status = 0;
953  }
954  return;
955 }
#define virt_to_le32desc(addr)
Definition: w89c840.c:91
u32 buffer1
Definition: w89c840.c:205
s32 status
Definition: w89c840.c:210
unsigned int dirty_rx
Definition: w89c840.c:237
struct w840_tx_desc tx_ring[TX_RING_SIZE]
Definition: w89c840.c:228
unsigned int tx_full
Definition: w89c840.c:241
#define RX_RING_SIZE
Definition: w89c840.c:107
struct w840_rx_desc * rx_head_desc
Definition: w89c840.c:236
#define PKT_BUF_SZ
Definition: w89c840.c:120
unsigned int rx_buf_sz
Definition: w89c840.c:238
unsigned int cur_rx
Definition: w89c840.c:237
s32 status
Definition: w89c840.c:203
u32 next_desc
Definition: w89c840.c:206
unsigned int cur_tx
Definition: w89c840.c:239
static struct winbond_private w840private
struct w840_rx_desc rx_ring[RX_RING_SIZE]
Definition: w89c840.c:227
#define TX_RING_SIZE
Definition: w89c840.c:106
unsigned int dirty_tx
Definition: w89c840.c:239
s32 length
Definition: w89c840.c:204

References w840_rx_desc::buffer1, winbond_private::cur_rx, winbond_private::cur_tx, DescEndRing, DescIntr, DescOwn, winbond_private::dirty_rx, winbond_private::dirty_tx, w840_rx_desc::length, w840_rx_desc::next_desc, PKT_BUF_SZ, winbond_private::rx_buf_sz, winbond_private::rx_head_desc, winbond_private::rx_ring, RX_RING_SIZE, w840_rx_desc::status, w840_tx_desc::status, winbond_private::tx_full, winbond_private::tx_q_bytes, winbond_private::tx_ring, TX_RING_SIZE, virt_to_le32desc, and w840private.

Referenced by w89c840_reset().

◆ w89c840_reset()

static void w89c840_reset ( struct nic nic)
static

Definition at line 301 of file w89c840.c.

302 {
303  int i;
304 
305  /* Reset the chip to erase previous misconfiguration.
306  No hold time required! */
307  writel(0x00000001, ioaddr + PCIBusCfg);
308 
309  init_ring();
310 
313 
314  for (i = 0; i < ETH_ALEN; i++)
315  writeb(nic->node_addr[i], ioaddr + StationAddr + i);
316 
317  /* Initialize other registers. */
318  /* Configure the PCI bus bursts and FIFO thresholds.
319  486: Set 8 longword cache alignment, 8 longword burst.
320  586: Set 16 longword cache alignment, no burst limit.
321  Cache alignment bits 15:14 Burst length 13:8
322  0000 <not allowed> 0000 align to cache 0800 8 longwords
323  4000 8 longwords 0100 1 longword 1000 16 longwords
324  8000 16 longwords 0200 2 longwords 2000 32 longwords
325  C000 32 longwords 0400 4 longwords
326  Wait the specified 50 PCI cycles after a reset by initializing
327  Tx and Rx queues and the address filter list. */
328 
329  writel(0xE010, ioaddr + PCIBusCfg);
330 
332  w840private.csr6 = 0x20022002;
333  check_duplex();
334  set_rx_mode();
335 
336  /* Do not enable the interrupts Etherboot doesn't need them */
337 /*
338  writel(0x1A0F5, ioaddr + IntrStatus);
339  writel(0x1A0F5, ioaddr + IntrEnable);
340 */
341 #if defined(W89C840_DEBUG)
342  printf("winbond-840 : Done reset.\n");
343 #endif
344 }
int printf(const char *fmt,...)
Write a formatted string to the console.
Definition: vsprintf.c:464
struct w840_tx_desc tx_ring[TX_RING_SIZE]
Definition: w89c840.c:228
static void set_rx_mode(void)
Definition: w89c840.c:894
static int ioaddr
Definition: w89c840.c:255
static __always_inline unsigned long virt_to_bus(volatile const void *addr)
Convert virtual address to a bus address.
Definition: io.h:183
#define writel
Definition: w89c840.c:160
static void init_ring(void)
Definition: w89c840.c:920
#define ETH_ALEN
Definition: if_ether.h:8
Definition: nic.h:49
unsigned char * node_addr
Definition: nic.h:52
static void check_duplex(void)
Definition: w89c840.c:871
#define writeb
Definition: w89c840.c:158
static struct winbond_private w840private
struct w840_rx_desc rx_ring[RX_RING_SIZE]
Definition: w89c840.c:227

References check_duplex(), winbond_private::csr6, ETH_ALEN, init_ring(), ioaddr, nic::node_addr, PCIBusCfg, printf(), winbond_private::rx_ring, RxRingPtr, RxStartDemand, set_rx_mode(), StationAddr, winbond_private::tx_ring, TxRingPtr, virt_to_bus(), w840private, writeb, and writel.

Referenced by w89c840_disable(), w89c840_poll(), and w89c840_probe().

◆ w89c840_poll()

static int w89c840_poll ( struct nic nic,
int  retrieve 
)
static

Definition at line 377 of file w89c840.c.

378 {
379  /* return true if there's an ethernet packet ready to read */
380  /* nic->packet should contain data on return */
381  /* nic->packetlen should contain length of data */
382  int packet_received = 0;
383 
384 #if defined(W89C840_DEBUG)
385  u32 intr_status = readl(ioaddr + IntrStatus);
386 #endif
387 
388  do {
389  /* Code from netdev_rx(dev) */
390 
392 
393  struct w840_rx_desc *desc = w840private.rx_head_desc;
394  s32 status = desc->status;
395 
396  if (status & DescOwn) {
397  /* DescOwn bit is still set, we should wait for RX to complete */
398  packet_received = 0;
399  break;
400  }
401 
402  if ( !retrieve ) {
403  packet_received = 1;
404  break;
405  }
406 
407  if ((status & 0x38008300) != 0x0300) {
408  if ((status & 0x38000300) != 0x0300) {
409  /* Ingore earlier buffers. */
410  if ((status & 0xffff) != 0x7fff) {
411  printf("winbond-840 : Oversized Ethernet frame spanned "
412  "multiple buffers, entry %d status %X !\n",
413  w840private.cur_rx, (unsigned int) status);
414  }
415  } else if (status & 0x8000) {
416  /* There was a fatal error. */
417 #if defined(W89C840_DEBUG)
418  printf("winbond-840 : Receive error, Rx status %X :", status);
419  if (status & 0x0890) {
420  printf(" RXLEN_ERROR");
421  }
422  if (status & 0x004C) {
423  printf(", FRAME_ERROR");
424  }
425  if (status & 0x0002) {
426  printf(", CRC_ERROR");
427  }
428  printf("\n");
429 #endif
430 
431  /* Simpy do a reset now... */
433 
434  packet_received = 0;
435  break;
436  }
437  } else {
438  /* Omit the four octet CRC from the length. */
439  int pkt_len = ((status >> 16) & 0x7ff) - 4;
440 
441 #if defined(W89C840_DEBUG)
442  printf(" netdev_rx() normal Rx pkt ring %d length %d status %X\n", entry, pkt_len, status);
443 #endif
444 
445  nic->packetlen = pkt_len;
446 
447  /* Check if the packet is long enough to accept without copying
448  to a minimally-sized skbuff. */
449 
451  packet_received = 1;
452 
453  /* Release buffer to NIC */
455 
456 #if defined(W89C840_DEBUG)
457  /* You will want this info for the initial debug. */
458  printf(" Rx data %hhX:%hhX:%hhX:%hhX:%hhX:"
459  "%hhX %hhX:%hhX:%hhX:%hhX:%hhX:%hhX %hhX%hhX "
460  "%hhX.%hhX.%hhX.%hhX.\n",
461  nic->packet[0], nic->packet[1], nic->packet[2], nic->packet[3],
462  nic->packet[4], nic->packet[5], nic->packet[6], nic->packet[7],
463  nic->packet[8], nic->packet[9], nic->packet[10],
464  nic->packet[11], nic->packet[12], nic->packet[13],
465  nic->packet[14], nic->packet[15], nic->packet[16],
466  nic->packet[17]);
467 #endif
468 
469  }
470 
473  } while (0);
474 
475  return packet_received;
476 }
u32 buffer1
Definition: w89c840.c:205
int printf(const char *fmt,...)
Write a formatted string to the console.
Definition: vsprintf.c:464
int32_t s32
Definition: stdint.h:22
static void w89c840_reset(struct nic *nic)
Definition: w89c840.c:301
#define RX_RING_SIZE
Definition: w89c840.c:107
struct w840_rx_desc * rx_head_desc
Definition: w89c840.c:236
static int ioaddr
Definition: w89c840.c:255
uint8_t status
Status.
Definition: ena.h:16
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define le32desc_to_virt(addr)
Definition: w89c840.c:92
unsigned int cur_rx
Definition: w89c840.c:237
unsigned int packetlen
Definition: nic.h:54
union aes_table_entry entry[256]
Table entries, indexed by S(N)
Definition: aes.c:26
Definition: nic.h:49
unsigned char * packet
Definition: nic.h:53
s32 status
Definition: w89c840.c:203
static struct winbond_private w840private
struct w840_rx_desc rx_ring[RX_RING_SIZE]
Definition: w89c840.c:227
uint32_t u32
Definition: stdint.h:23
#define readl
Definition: w89c840.c:157

References w840_rx_desc::buffer1, winbond_private::cur_rx, DescOwn, entry, IntrStatus, ioaddr, le32desc_to_virt, memcpy(), nic::packet, nic::packetlen, printf(), readl, winbond_private::rx_head_desc, winbond_private::rx_ring, RX_RING_SIZE, status, w840_rx_desc::status, w840private, and w89c840_reset().

◆ w89c840_transmit()

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

Definition at line 482 of file w89c840.c.

488 {
489  /* send the packet to destination */
490  unsigned entry;
491  int transmit_status;
492  unsigned long ct;
493 
494  /* Caution: the write order is important here, set the field
495  with the "ownership" bits last. */
496 
497  /* Fill in our transmit buffer */
499 
500  memcpy (w89c840_buf.tx_packet, d, ETH_ALEN); /* dst */
501  memcpy (w89c840_buf.tx_packet + ETH_ALEN, nic->node_addr, ETH_ALEN);/*src*/
502 
503  *((char *) w89c840_buf.tx_packet + 12) = t >> 8; /* type */
504  *((char *) w89c840_buf.tx_packet + 13) = t;
505 
506  memcpy (w89c840_buf.tx_packet + ETH_HLEN, p, s);
507  s += ETH_HLEN;
508 
509  while (s < ETH_ZLEN)
510  *((char *) w89c840_buf.tx_packet + ETH_HLEN + (s++)) = 0;
511 
513  = virt_to_le32desc(w89c840_buf.tx_packet);
514 
516  if (entry >= TX_RING_SIZE-1) /* Wrap ring */
520 
521  w840private.tx_q_bytes = (u16) s;
523 
524  /* Work around horrible bug in the chip by marking the queue as full
525  when we do not have FIFO room for a maximum sized packet. */
526 
528  /* Actually this is left to help finding error tails later in debugging...
529  * See Linux kernel driver in winbond-840.c for details.
530  */
531  w840private.tx_full = 1;
532  }
533 
534 #if defined(W89C840_DEBUG)
535  printf("winbond-840 : Transmit frame # %d size %d queued in slot %d.\n", w840private.cur_tx, s, entry);
536 #endif
537 
538  /* Now wait for TX to complete. */
539  transmit_status = w840private.tx_ring[entry].status;
540 
541  ct = currticks();
542  {
543 #if defined W89C840_DEBUG
544  u32 intr_stat = 0;
545 #endif
546  while (1) {
547 
548 #if defined(W89C840_DEBUG)
549  decode_interrupt(intr_stat);
550 #endif
551 
552  while ( (transmit_status & DescOwn) && ct + TX_TIMEOUT < currticks()) {
553 
554  transmit_status = w840private.tx_ring[entry].status;
555  }
556 
557  break;
558  }
559  }
560 
561  if ((transmit_status & DescOwn) == 0) {
562 
563 #if defined(W89C840_DEBUG)
564  printf("winbond-840 : transmission complete after wait loop iterations, status %X\n",
566 #endif
567 
568  return;
569  }
570 
571  /* Transmit timed out... */
572 
573  printf("winbond-840 : transmission TIMEOUT : status %X\n",
574  (unsigned int) w840private.tx_ring[entry].status);
575 
576  return;
577 }
#define virt_to_le32desc(addr)
Definition: w89c840.c:91
#define u16
Definition: vga.h:20
s32 status
Definition: w89c840.c:210
int printf(const char *fmt,...)
Write a formatted string to the console.
Definition: vsprintf.c:464
s32 length
Definition: w89c840.c:211
struct w840_tx_desc tx_ring[TX_RING_SIZE]
Definition: w89c840.c:228
unsigned int tx_full
Definition: w89c840.c:241
static int ioaddr
Definition: w89c840.c:255
#define TX_TIMEOUT
Definition: w89c840.c:118
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define ETH_HLEN
Definition: if_ether.h:9
u32 buffer1
Definition: w89c840.c:212
#define u32
Definition: vga.h:21
#define writel
Definition: w89c840.c:160
union aes_table_entry entry[256]
Table entries, indexed by S(N)
Definition: aes.c:26
#define ETH_ALEN
Definition: if_ether.h:8
#define ETH_ZLEN
Definition: if_ether.h:10
Definition: nic.h:49
unsigned char * node_addr
Definition: nic.h:52
#define TX_BUG_FIFO_LIMIT
Definition: w89c840.c:114
uint32_t d
Definition: md4.c:31
unsigned int cur_tx
Definition: w89c840.c:239
unsigned long currticks(void)
Get current system time in ticks.
Definition: timer.c:42
static struct winbond_private w840private
#define TX_RING_SIZE
Definition: w89c840.c:106
uint32_t u32
Definition: stdint.h:23

References w840_tx_desc::buffer1, winbond_private::cur_tx, currticks(), d, DescEndRing, DescIntr, DescOwn, DescWholePkt, winbond_private::drv_flags, entry, ETH_ALEN, ETH_HLEN, ETH_ZLEN, HasBrokenTx, ioaddr, w840_tx_desc::length, memcpy(), nic::node_addr, printf(), w840_tx_desc::status, TX_BUG_FIFO_LIMIT, winbond_private::tx_full, winbond_private::tx_q_bytes, winbond_private::tx_ring, TX_RING_SIZE, TX_TIMEOUT, TxStartDemand, u16, u32, virt_to_le32desc, w840private, and writel.

◆ w89c840_disable()

static void w89c840_disable ( struct nic nic)
static

Definition at line 582 of file w89c840.c.

582  {
583 
585 
586  /* Don't know what to do to disable the board. Is this needed at all? */
587  /* Yes, a live NIC can corrupt the loaded memory later [Ken] */
588  /* Stop the chip's Tx and Rx processes. */
589  writel(w840private.csr6 &= ~0x20FA, ioaddr + NetworkConfig);
590 }
static void w89c840_reset(struct nic *nic)
Definition: w89c840.c:301
static int ioaddr
Definition: w89c840.c:255
#define writel
Definition: w89c840.c:160
Definition: nic.h:49
static struct winbond_private w840private

References winbond_private::csr6, ioaddr, NetworkConfig, w840private, w89c840_reset(), and writel.

◆ w89c840_irq()

static void w89c840_irq ( struct nic *nic  __unused,
irq_action_t action  __unused 
)
static

Definition at line 595 of file w89c840.c.

596 {
597  switch ( action ) {
598  case DISABLE :
599  break;
600  case ENABLE :
601  break;
602  case FORCE :
603  break;
604  }
605 }
Definition: nic.h:35
Definition: nic.h:37
Definition: nic.h:36

References DISABLE, ENABLE, and FORCE.

◆ PCI_DRIVER()

PCI_DRIVER ( w89c840_driver  ,
w89c840_nics  ,
PCI_NO_CLASS   
)

◆ w89c840_probe()

static int w89c840_probe ( struct nic nic,
struct pci_device p 
)
static

Definition at line 625 of file w89c840.c.

625  {
626 
627 
628  u16 sum = 0;
629  int i;
630  unsigned short value;
631 
632  if (p->ioaddr == 0)
633  return 0;
634 
635  nic->ioaddr = p->ioaddr;
636  nic->irqno = 0;
637 
638 #if defined(W89C840_DEBUG)
639  printf("winbond-840: PCI bus %hhX device function %hhX: I/O address: %hX\n", p->bus, p->devfn, ioaddr);
640 #endif
641 
642  ioaddr = ioaddr & ~3; /* Mask the bit that says "this is an io addr" */
643 
644 #define PCI_VENDOR_ID_WINBOND2 0x1050
645 #define PCI_DEVICE_ID_WINBOND2_89C840 0x0840
646 #define PCI_VENDOR_ID_COMPEX 0x11f6
647 #define PCI_DEVICE_ID_COMPEX_RL100ATX 0x2011
648 
649  /* From Matt Hortman <mbhortman@acpthinclient.com> */
652 
653  /* detected "Winbond W89c840 Fast Ethernet PCI NIC" */
654 
655  } else if ( p->vendor == PCI_VENDOR_ID_COMPEX
657 
658  /* detected "Compex RL100ATX Fast Ethernet PCI NIC" */
659 
660  } else {
661  /* Gee, guess what? They missed again. */
662  printf("device ID : %X - is not a Compex RL100ATX NIC.\n",
663  p->device);
664  return 0;
665  }
666 
667  printf(" %s\n", w89c840_version);
668 
670 
671  /* Ok. Got one. Read the eeprom. */
672  for (i = 0; i < 0x40; i++) {
673  value = eeprom_read(ioaddr, i);
674  eeprom[i] = value;
675  sum += value;
676  }
677 
678  for (i=0;i<ETH_ALEN;i++) {
679  nic->node_addr[i] = (eeprom[i/2] >> (8*(i&1))) & 0xff;
680  }
681 
682  DBG ( "Ethernet addr: %s\n", eth_ntoa ( nic->node_addr ) );
683 
684 #if defined(W89C840_DEBUG)
685  printf("winbond-840: EEPROM checksum %hX, got eeprom", sum);
686 #endif
687 
688  /* Reset the chip to erase previous misconfiguration.
689  No hold time required! */
690  writel(0x00000001, ioaddr + PCIBusCfg);
691 
692  if (driver_flags & CanHaveMII) {
693  int phy, phy_idx = 0;
694  for (phy = 1; phy < 32 && phy_idx < 4; phy++) {
695  int mii_status = mdio_read(ioaddr, phy, 1);
696  if (mii_status != 0xffff && mii_status != 0x0000) {
697  w840private.phys[phy_idx++] = phy;
699 
700 #if defined(W89C840_DEBUG)
701  printf("winbond-840 : MII PHY found at address %d, status "
702  "%X advertising %hX.\n", phy, mii_status, w840private.advertising);
703 #endif
704 
705  }
706  }
707 
708  w840private.mii_cnt = phy_idx;
709 
710  if (phy_idx == 0) {
711  printf("winbond-840 : MII PHY not found -- this device may not operate correctly.\n");
712  }
713  }
714 
715  /* point to NIC specific routines */
717 
719 
720  return 1;
721 }
unsigned char irqno
Definition: nic.h:56
uint16_t u16
Definition: stdint.h:21
int printf(const char *fmt,...)
Write a formatted string to the console.
Definition: vsprintf.c:464
unsigned long ioaddr
I/O address.
Definition: pci.h:200
static u32 driver_flags
Definition: w89c840.c:142
static void w89c840_reset(struct nic *nic)
Definition: w89c840.c:301
static int mdio_read(int base_address, int phy_id, int location)
Definition: w89c840.c:809
static int eeprom_read(long ioaddr, int location)
Definition: w89c840.c:746
void adjust_pci_device(struct pci_device *pci)
Enable PCI device.
Definition: pci.c:149
eeprom
Definition: 3c90x.h:232
static int ioaddr
Definition: w89c840.c:255
unsigned int ioaddr
Definition: nic.h:55
uint16_t device
Device ID.
Definition: pci.h:204
#define PCI_DEVICE_ID_COMPEX_RL100ATX
#define writel
Definition: w89c840.c:160
pseudo_bit_t value[0x00020]
Definition: arbel.h:13
const char * eth_ntoa(const void *ll_addr)
Transcribe Ethernet address.
Definition: ethernet.c:175
#define ETH_ALEN
Definition: if_ether.h:8
Definition: nic.h:49
#define PCI_VENDOR_ID_WINBOND2
unsigned char phys[4]
Definition: w89c840.c:250
uint16_t vendor
Vendor ID.
Definition: pci.h:202
static const char * w89c840_version
Definition: w89c840.c:88
unsigned char * node_addr
Definition: nic.h:52
#define PCI_VENDOR_ID_COMPEX
static struct nic_operations w89c840_operations
Definition: w89c840.c:607
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
struct nic_operations * nic_op
Definition: nic.h:50
static struct winbond_private w840private
#define PCI_DEVICE_ID_WINBOND2_89C840

References adjust_pci_device(), winbond_private::advertising, CanHaveMII, DBG, pci_device::device, driver_flags, eeprom_read(), ETH_ALEN, eth_ntoa(), nic::ioaddr, pci_device::ioaddr, ioaddr, nic::irqno, mdio_read(), winbond_private::mii_cnt, nic::nic_op, nic::node_addr, PCI_DEVICE_ID_COMPEX_RL100ATX, PCI_DEVICE_ID_WINBOND2_89C840, PCI_VENDOR_ID_COMPEX, PCI_VENDOR_ID_WINBOND2, PCIBusCfg, winbond_private::phys, printf(), value, pci_device::vendor, w840private, w89c840_operations, w89c840_reset(), w89c840_version, and writel.

◆ mdio_sync()

static void mdio_sync ( long  mdio_addr)
static

Definition at line 796 of file w89c840.c.

797 {
798  int bits = 32;
799 
800  /* Establish sync by sending at least 32 logic ones. */
801  while (--bits >= 0) {
802  writel(MDIO_WRITE1, mdio_addr);
803  mdio_delay(mdio_addr);
804  writel(MDIO_WRITE1 | MDIO_ShiftClk, mdio_addr);
805  mdio_delay(mdio_addr);
806  }
807 }
#define MDIO_WRITE1
Definition: w89c840.c:792
#define writel
Definition: w89c840.c:160
static volatile void * bits
Definition: bitops.h:27
#define mdio_delay(mdio_addr)
Definition: w89c840.c:784

References bits, mdio_delay, MDIO_ShiftClk, MDIO_WRITE1, and writel.

Referenced by mdio_read().

◆ DRIVER()

DRIVER ( "W89C840F"  ,
nic_driver  ,
pci_driver  ,
w89c840_driver  ,
w89c840_probe  ,
w89c840_disable   
)

Variable Documentation

◆ w89c840_version

const char* w89c840_version = "driver Version 0.94 - December 12, 2003"
static

Definition at line 88 of file w89c840.c.

Referenced by w89c840_probe().

◆ driver_flags

u32 driver_flags = CanHaveMII | HasBrokenTx
static

Definition at line 142 of file w89c840.c.

Referenced by w89c840_probe().

◆ w840private

struct winbond_private w840private
static

◆ ioaddr

int ioaddr
static

◆ eeprom

unsigned short eeprom[0x40]
static

Definition at line 256 of file w89c840.c.

◆ rx_packet

char rx_packet[PKT_BUF_SZ *RX_RING_SIZE]

Definition at line 258 of file w89c840.c.

◆ tx_packet

char tx_packet[PKT_BUF_SZ *TX_RING_SIZE]

Definition at line 259 of file w89c840.c.

◆ __shared

struct { ... } __shared

◆ w89c840_operations

struct nic_operations w89c840_operations
static
Initial value:
= {
.connect = dummy_connect,
.poll = w89c840_poll,
.transmit = w89c840_transmit,
.irq = w89c840_irq,
}
int dummy_connect(struct nic *nic __unused)
Definition: legacy.c:151
static int w89c840_poll(struct nic *nic, int retrieve)
Definition: w89c840.c:377
static void w89c840_irq(struct nic *nic __unused, irq_action_t action __unused)
Definition: w89c840.c:595
static void w89c840_transmit(struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p)
Definition: w89c840.c:482

Definition at line 607 of file w89c840.c.

Referenced by w89c840_probe().

◆ w89c840_nics

struct pci_device_id w89c840_nics[]
static
Initial value:
= {
PCI_ROM(0x1050, 0x0840, "winbond840", "Winbond W89C840F", 0),
PCI_ROM(0x11f6, 0x2011, "compexrl100atx", "Compex RL100ATX", 0),
}
#define PCI_ROM(_vendor, _device, _name, _description, _data)
Definition: pci.h:283

Definition at line 615 of file w89c840.c.

◆ mii_preamble_required

char mii_preamble_required = 1
static

Definition at line 789 of file w89c840.c.

Referenced by mdio_read().