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
 
struct  w89c840_bss
 

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 w89c840_buf   NIC_FAKE_BSS ( struct w89c840_bss )
 
#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, void *hwdev __unused)
 
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, w89c840_buf)
 

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]
 
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.

◆ w89c840_buf

#define w89c840_buf   NIC_FAKE_BSS ( struct w89c840_bss )

Definition at line 261 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 735 of file w89c840.c.

◆ mdio_delay

#define mdio_delay (   mdio_addr)    readl(mdio_addr)

Definition at line 785 of file w89c840.c.

◆ MDIO_WRITE0

#define MDIO_WRITE0   (MDIO_EnbOutput)

Definition at line 792 of file w89c840.c.

◆ MDIO_WRITE1

#define MDIO_WRITE1   (MDIO_DataOut | MDIO_EnbOutput)

Definition at line 793 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 737 of file w89c840.c.

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

◆ EEPROM_Cmds

Enumerator
EE_WriteCmd 
EE_ReadCmd 
EE_EraseCmd 

Definition at line 743 of file w89c840.c.

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

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER  )

◆ eeprom_read()

static int eeprom_read ( long  ioaddr,
int  location 
)
static

Definition at line 747 of file w89c840.c.

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

References addr, EE_ChipSelect, EE_DataIn, EE_ReadCmd, EE_ShiftClk, EE_Write0, EE_Write1, EECtrl, eeprom_delay, read_cmd, 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 810 of file w89c840.c.

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

873 {
874  int mii_reg5 = mdio_read(ioaddr, w840private.phys[0], 5);
875  int negotiated = mii_reg5 & w840private.advertising;
876  int duplex;
877 
878  if (w840private.duplex_lock || mii_reg5 == 0xffff)
879  return;
880 
881  duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
882  if (w840private.full_duplex != duplex) {
884 
885 #if defined(W89C840_DEBUG)
886  printf("winbond-840 : Setting %s-duplex based on MII # %d negotiated capability %X\n",
887  duplex ? "full" : "half", w840private.phys[0], negotiated);
888 #endif
889 
890  w840private.csr6 &= ~0x200;
891  w840private.csr6 |= duplex ? 0x200 : 0;
892  }
893 }
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:810
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 895 of file w89c840.c.

896 {
897  u32 mc_filter[2]; /* Multicast hash filter */
898  u32 rx_mode;
899 
900  /* Accept all multicasts from now on. */
901  memset(mc_filter, 0xff, sizeof(mc_filter));
902 
903 /*
904  * works OK with multicast enabled.
905  */
906 
908 
909  writel(mc_filter[0], ioaddr + MulticastFilter0);
910  writel(mc_filter[1], ioaddr + MulticastFilter1);
911  w840private.csr6 &= ~0x00F8;
912  w840private.csr6 |= rx_mode;
914 
915 #if defined(W89C840_DEBUG)
916  printf("winbond-840 : Done setting RX mode.\n");
917 #endif
918 }
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 921 of file w89c840.c.

922 {
923  int i;
924  char * p;
925 
926  w840private.tx_full = 0;
929 
932 
933  /* Initial all Rx descriptors. Fill in the Rx buffers. */
934 
935  p = &w89c840_buf.rx_packet[0];
936 
937  for (i = 0; i < RX_RING_SIZE; i++) {
939  w840private.rx_ring[i].status = 0;
941 
944  }
945 
946  /* Mark the last entry as wrapping the ring. */
949 
950  w840private.dirty_rx = (unsigned int)(i - RX_RING_SIZE);
951 
952  for (i = 0; i < TX_RING_SIZE; i++) {
953  w840private.tx_ring[i].status = 0;
954  }
955  return;
956 }
#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
#define w89c840_buf
Definition: w89c840.c:261
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, w840private, and w89c840_buf.

Referenced by w89c840_reset().

◆ w89c840_reset()

static void w89c840_reset ( struct nic nic)
static

Definition at line 302 of file w89c840.c.

303 {
304  int i;
305 
306  /* Reset the chip to erase previous misconfiguration.
307  No hold time required! */
308  writel(0x00000001, ioaddr + PCIBusCfg);
309 
310  init_ring();
311 
314 
315  for (i = 0; i < ETH_ALEN; i++)
316  writeb(nic->node_addr[i], ioaddr + StationAddr + i);
317 
318  /* Initialize other registers. */
319  /* Configure the PCI bus bursts and FIFO thresholds.
320  486: Set 8 longword cache alignment, 8 longword burst.
321  586: Set 16 longword cache alignment, no burst limit.
322  Cache alignment bits 15:14 Burst length 13:8
323  0000 <not allowed> 0000 align to cache 0800 8 longwords
324  4000 8 longwords 0100 1 longword 1000 16 longwords
325  8000 16 longwords 0200 2 longwords 2000 32 longwords
326  C000 32 longwords 0400 4 longwords
327  Wait the specified 50 PCI cycles after a reset by initializing
328  Tx and Rx queues and the address filter list. */
329 
330  writel(0xE010, ioaddr + PCIBusCfg);
331 
333  w840private.csr6 = 0x20022002;
334  check_duplex();
335  set_rx_mode();
336 
337  /* Do not enable the interrupts Etherboot doesn't need them */
338 /*
339  writel(0x1A0F5, ioaddr + IntrStatus);
340  writel(0x1A0F5, ioaddr + IntrEnable);
341 */
342 #if defined(W89C840_DEBUG)
343  printf("winbond-840 : Done reset.\n");
344 #endif
345 }
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:895
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:921
#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:872
#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 378 of file w89c840.c.

379 {
380  /* return true if there's an ethernet packet ready to read */
381  /* nic->packet should contain data on return */
382  /* nic->packetlen should contain length of data */
383  int packet_received = 0;
384 
385 #if defined(W89C840_DEBUG)
386  u32 intr_status = readl(ioaddr + IntrStatus);
387 #endif
388 
389  do {
390  /* Code from netdev_rx(dev) */
391 
392  int entry = w840private.cur_rx % RX_RING_SIZE;
393 
395  s32 status = desc->status;
396 
397  if (status & DescOwn) {
398  /* DescOwn bit is still set, we should wait for RX to complete */
399  packet_received = 0;
400  break;
401  }
402 
403  if ( !retrieve ) {
404  packet_received = 1;
405  break;
406  }
407 
408  if ((status & 0x38008300) != 0x0300) {
409  if ((status & 0x38000300) != 0x0300) {
410  /* Ingore earlier buffers. */
411  if ((status & 0xffff) != 0x7fff) {
412  printf("winbond-840 : Oversized Ethernet frame spanned "
413  "multiple buffers, entry %d status %X !\n",
414  w840private.cur_rx, (unsigned int) status);
415  }
416  } else if (status & 0x8000) {
417  /* There was a fatal error. */
418 #if defined(W89C840_DEBUG)
419  printf("winbond-840 : Receive error, Rx status %X :", status);
420  if (status & 0x0890) {
421  printf(" RXLEN_ERROR");
422  }
423  if (status & 0x004C) {
424  printf(", FRAME_ERROR");
425  }
426  if (status & 0x0002) {
427  printf(", CRC_ERROR");
428  }
429  printf("\n");
430 #endif
431 
432  /* Simpy do a reset now... */
434 
435  packet_received = 0;
436  break;
437  }
438  } else {
439  /* Omit the four octet CRC from the length. */
440  int pkt_len = ((status >> 16) & 0x7ff) - 4;
441 
442 #if defined(W89C840_DEBUG)
443  printf(" netdev_rx() normal Rx pkt ring %d length %d status %X\n", entry, pkt_len, status);
444 #endif
445 
446  nic->packetlen = pkt_len;
447 
448  /* Check if the packet is long enough to accept without copying
449  to a minimally-sized skbuff. */
450 
452  packet_received = 1;
453 
454  /* Release buffer to NIC */
456 
457 #if defined(W89C840_DEBUG)
458  /* You will want this info for the initial debug. */
459  printf(" Rx data %hhX:%hhX:%hhX:%hhX:%hhX:"
460  "%hhX %hhX:%hhX:%hhX:%hhX:%hhX:%hhX %hhX%hhX "
461  "%hhX.%hhX.%hhX.%hhX.\n",
462  nic->packet[0], nic->packet[1], nic->packet[2], nic->packet[3],
463  nic->packet[4], nic->packet[5], nic->packet[6], nic->packet[7],
464  nic->packet[8], nic->packet[9], nic->packet[10],
465  nic->packet[11], nic->packet[12], nic->packet[13],
466  nic->packet[14], nic->packet[15], nic->packet[16],
467  nic->packet[17]);
468 #endif
469 
470  }
471 
472  entry = (++w840private.cur_rx) % RX_RING_SIZE;
474  } while (0);
475 
476  return packet_received;
477 }
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:302
#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
struct ena_llq_option desc
Descriptor counts.
Definition: ena.h:20
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
uint16_t pkt_len
Definition: aqc1xx.h:37
Definition: nic.h:49
uint8_t status
Status.
Definition: ena.h:16
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, desc, DescOwn, IntrStatus, ioaddr, le32desc_to_virt, memcpy(), nic::packet, nic::packetlen, pkt_len, 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 483 of file w89c840.c.

489 {
490  /* send the packet to destination */
491  unsigned entry;
492  int transmit_status;
493  unsigned long ct;
494 
495  /* Caution: the write order is important here, set the field
496  with the "ownership" bits last. */
497 
498  /* Fill in our transmit buffer */
499  entry = w840private.cur_tx % TX_RING_SIZE;
500 
501  memcpy (w89c840_buf.tx_packet, d, ETH_ALEN); /* dst */
502  memcpy (w89c840_buf.tx_packet + ETH_ALEN, nic->node_addr, ETH_ALEN);/*src*/
503 
504  *((char *) w89c840_buf.tx_packet + 12) = t >> 8; /* type */
505  *((char *) w89c840_buf.tx_packet + 13) = t;
506 
507  memcpy (w89c840_buf.tx_packet + ETH_HLEN, p, s);
508  s += ETH_HLEN;
509 
510  while (s < ETH_ZLEN)
511  *((char *) w89c840_buf.tx_packet + ETH_HLEN + (s++)) = 0;
512 
514  = virt_to_le32desc(w89c840_buf.tx_packet);
515 
516  w840private.tx_ring[entry].length = (DescWholePkt | (u32) s);
517  if (entry >= TX_RING_SIZE-1) /* Wrap ring */
519  w840private.tx_ring[entry].status = (DescOwn);
521 
522  w840private.tx_q_bytes = (u16) s;
524 
525  /* Work around horrible bug in the chip by marking the queue as full
526  when we do not have FIFO room for a maximum sized packet. */
527 
529  /* Actually this is left to help finding error tails later in debugging...
530  * See Linux kernel driver in winbond-840.c for details.
531  */
532  w840private.tx_full = 1;
533  }
534 
535 #if defined(W89C840_DEBUG)
536  printf("winbond-840 : Transmit frame # %d size %d queued in slot %d.\n", w840private.cur_tx, s, entry);
537 #endif
538 
539  /* Now wait for TX to complete. */
540  transmit_status = w840private.tx_ring[entry].status;
541 
542  ct = currticks();
543  {
544 #if defined W89C840_DEBUG
545  u32 intr_stat = 0;
546 #endif
547  while (1) {
548 
549 #if defined(W89C840_DEBUG)
550  decode_interrupt(intr_stat);
551 #endif
552 
553  while ( (transmit_status & DescOwn) && ct + TX_TIMEOUT < currticks()) {
554 
555  transmit_status = w840private.tx_ring[entry].status;
556  }
557 
558  break;
559  }
560  }
561 
562  if ((transmit_status & DescOwn) == 0) {
563 
564 #if defined(W89C840_DEBUG)
565  printf("winbond-840 : transmission complete after wait loop iterations, status %X\n",
566  w840private.tx_ring[entry].status);
567 #endif
568 
569  return;
570  }
571 
572  /* Transmit timed out... */
573 
574  printf("winbond-840 : transmission TIMEOUT : status %X\n",
575  (unsigned int) w840private.tx_ring[entry].status);
576 
577  return;
578 }
#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 w89c840_buf
Definition: w89c840.c:261
#define u32
Definition: vga.h:21
#define writel
Definition: w89c840.c:160
#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
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(), DescEndRing, DescIntr, DescOwn, DescWholePkt, winbond_private::drv_flags, 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, w89c840_buf, and writel.

◆ w89c840_disable()

static void w89c840_disable ( struct nic nic,
void *hwdev  __unused 
)
static

Definition at line 583 of file w89c840.c.

583  {
584 
586 
587  /* Don't know what to do to disable the board. Is this needed at all? */
588  /* Yes, a live NIC can corrupt the loaded memory later [Ken] */
589  /* Stop the chip's Tx and Rx processes. */
590  writel(w840private.csr6 &= ~0x20FA, ioaddr + NetworkConfig);
591 }
static void w89c840_reset(struct nic *nic)
Definition: w89c840.c:302
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 596 of file w89c840.c.

597 {
598  switch ( action ) {
599  case DISABLE :
600  break;
601  case ENABLE :
602  break;
603  case FORCE :
604  break;
605  }
606 }
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 626 of file w89c840.c.

626  {
627 
628 
629  u16 sum = 0;
630  int i;
631  unsigned short value;
632 
633  if (p->ioaddr == 0)
634  return 0;
635 
636  nic->ioaddr = p->ioaddr;
637  nic->irqno = 0;
638 
639 #if defined(W89C840_DEBUG)
640  printf("winbond-840: PCI bus %hhX device function %hhX: I/O address: %hX\n", p->bus, p->devfn, ioaddr);
641 #endif
642 
643  ioaddr = ioaddr & ~3; /* Mask the bit that says "this is an io addr" */
644 
645 #define PCI_VENDOR_ID_WINBOND2 0x1050
646 #define PCI_DEVICE_ID_WINBOND2_89C840 0x0840
647 #define PCI_VENDOR_ID_COMPEX 0x11f6
648 #define PCI_DEVICE_ID_COMPEX_RL100ATX 0x2011
649 
650  /* From Matt Hortman <mbhortman@acpthinclient.com> */
653 
654  /* detected "Winbond W89c840 Fast Ethernet PCI NIC" */
655 
656  } else if ( p->vendor == PCI_VENDOR_ID_COMPEX
658 
659  /* detected "Compex RL100ATX Fast Ethernet PCI NIC" */
660 
661  } else {
662  /* Gee, guess what? They missed again. */
663  printf("device ID : %X - is not a Compex RL100ATX NIC.\n",
664  p->device);
665  return 0;
666  }
667 
668  printf(" %s\n", w89c840_version);
669 
671 
672  /* Ok. Got one. Read the eeprom. */
673  for (i = 0; i < 0x40; i++) {
674  value = eeprom_read(ioaddr, i);
675  eeprom[i] = value;
676  sum += value;
677  }
678 
679  for (i=0;i<ETH_ALEN;i++) {
680  nic->node_addr[i] = (eeprom[i/2] >> (8*(i&1))) & 0xff;
681  }
682 
683  DBG ( "Ethernet addr: %s\n", eth_ntoa ( nic->node_addr ) );
684 
685 #if defined(W89C840_DEBUG)
686  printf("winbond-840: EEPROM checksum %hX, got eeprom", sum);
687 #endif
688 
689  /* Reset the chip to erase previous misconfiguration.
690  No hold time required! */
691  writel(0x00000001, ioaddr + PCIBusCfg);
692 
693  if (driver_flags & CanHaveMII) {
694  int phy, phy_idx = 0;
695  for (phy = 1; phy < 32 && phy_idx < 4; phy++) {
696  int mii_status = mdio_read(ioaddr, phy, 1);
697  if (mii_status != 0xffff && mii_status != 0x0000) {
698  w840private.phys[phy_idx++] = phy;
700 
701 #if defined(W89C840_DEBUG)
702  printf("winbond-840 : MII PHY found at address %d, status "
703  "%X advertising %hX.\n", phy, mii_status, w840private.advertising);
704 #endif
705 
706  }
707  }
708 
709  w840private.mii_cnt = phy_idx;
710 
711  if (phy_idx == 0) {
712  printf("winbond-840 : MII PHY not found -- this device may not operate correctly.\n");
713  }
714  }
715 
716  /* point to NIC specific routines */
718 
720 
721  return 1;
722 }
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:225
static u32 driver_flags
Definition: w89c840.c:142
static void w89c840_reset(struct nic *nic)
Definition: w89c840.c:302
static int mdio_read(int base_address, int phy_id, int location)
Definition: w89c840.c:810
static int eeprom_read(long ioaddr, int location)
Definition: w89c840.c:747
void adjust_pci_device(struct pci_device *pci)
Enable PCI device.
Definition: pci.c:240
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:229
pseudo_bit_t value[0x00020]
Definition: arbel.h:13
#define PCI_DEVICE_ID_COMPEX_RL100ATX
#define writel
Definition: w89c840.c:160
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:227
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:608
#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 797 of file w89c840.c.

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

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  ,
w89c840_buf   
)

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.

◆ 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:175
static int w89c840_poll(struct nic *nic, int retrieve)
Definition: w89c840.c:378
static void w89c840_irq(struct nic *nic __unused, irq_action_t action __unused)
Definition: w89c840.c:596
static void w89c840_transmit(struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p)
Definition: w89c840.c:483

Definition at line 608 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:307

Definition at line 616 of file w89c840.c.

◆ mii_preamble_required

char mii_preamble_required = 1
static

Definition at line 790 of file w89c840.c.

Referenced by mdio_read().