#include "etherboot.h"#include "nic.h"#include <gpxe/pci.h>#include <gpxe/ethernet.h>Go to the source code of this file.
Data Structures | |
| struct | w840_rx_desc |
| struct | w840_tx_desc |
| struct | winbond_private |
Defines | |
| #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 |
| #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 |
| #define | PRIV_ALIGN_BYTES 32 |
| #define | PCI_DEVICE_ID_WINBOND2_89C840 0x0840 |
| #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 { HAS_MII_XCVR, HAS_CHIP_XCVR, 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 { RFCON = 0x00020000, RFCOFF = 0x00010000, LSCStatus = 0x00008000, ANCStatus = 0x00004000, FBE = 0x00002000, FBEMask = 0x00001800, ParityErr = 0x00000000, TargetErr = 0x00001000, MasterErr = 0x00000800, TUNF = 0x00000400, ROVF = 0x00000200, ETI = 0x00000100, ERI = 0x00000080, CNTOVF = 0x00000040, RBU = 0x00000020, TBU = 0x00000010, TI = 0x00000008, RI = 0x00000004, RxErr = 0x00000002, IntrSummary = 0x0001, IntrPCIErr = 0x0002, IntrMACCtrl = 0x0008, IntrTxDone = 0x0004, IntrRxDone = 0x0010, IntrRxStart = 0x0020, IntrDrvRqst = 0x0040, StatsMax = 0x0080, LinkChange = 0x0100, IntrTxDMADone = 0x0200, IntrRxDMADone = 0x0400, IntrRxDone = 0x0001, IntrRxErr = 0x0004, IntrRxEmpty = 0x0020, IntrTxDone = 0x0002, IntrTxError = 0x0008, IntrTxUnderrun = 0x0210, IntrPCIErr = 0x0040, IntrStatsMax = 0x0080, IntrRxEarly = 0x0100, IntrRxOverflow = 0x0400, IntrRxDropped = 0x0800, IntrRxNoBuf = 0x1000, IntrTxAborted = 0x2000, IntrLinkChange = 0x4000, IntrRxWakeUp = 0x8000, IntrNormalSummary = 0x0003, IntrAbnormalSummary = 0xC260, IntrTxDescRace = 0x080000, IntrTxErrSummary = 0x082218, 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 { RxModeMask = 0xe0, AcceptAllPhys = 0x80, AcceptBroadcast = 0x40, AcceptMulticast = 0x20, AcceptRunt = 0x08, ALP = 0x04, AcceptErr = 0x02, AcceptMyPhys = 0x00000000, RxEnable = 0x00000001, RxFlowCtrl = 0x00002000, TxEnable = 0x00040000, TxModeFDX = 0x00100000, TxThreshold = 0x00e00000, PS1000 = 0x00010000, PS10 = 0x00080000, FD = 0x00100000, AcceptErr = 0x20, AcceptRunt = 0x10, AcceptBroadcast = 0xC0000000, AcceptMulticast = 0x00200000, AcceptAllMulticast = 0x20000000, AcceptAllPhys = 0x10000000, AcceptMyPhys = 0x08000000, RxFilterEnable = 0x80000000, 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 = 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 } |
| enum | EEPROM_Ctrl_Bits { EE_ShiftClk = 0x04, EE_DataIn = 0x01, EE_ChipSelect = 0x08, EE_DataOut = 0x02, 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), 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 |
| #define TX_BUG_FIFO_LIMIT (TX_FIFO_SIZE-1514-16) |
| #define W840_FLAGS (PCI_USES_IO | PCI_ADDR0 | PCI_USES_MASTER) |
| #define readb inb |
Definition at line 154 of file w89c840.c.
Referenced by amd8111e_get_mac_address(), check_connection_type(), mac_get_cam(), mac_get_cam_mask(), skge_read8(), sky2_read8(), velocity_mii_read(), velocity_mii_write(), velocity_probe(), and velocity_set_media_mode().
| #define readw inw |
Definition at line 155 of file w89c840.c.
Referenced by __er16flash(), b44_read_eeprom(), hfa384x_getreg(), mac_get_cam(), skge_read16(), sky2_read16(), and velocity_mii_read().
| #define readl inl |
Definition at line 156 of file w89c840.c.
Referenced by __er32(), __er32flash(), amd8111e_disable_interrupt(), amd8111e_enable_interrupt(), amd8111e_force_interrupt(), amd8111e_init_hw_default(), amd8111e_poll(), amd8111e_poll_link(), amd8111e_read_phy(), amd8111e_start(), amd8111e_transmit(), amd8111e_wait_link(), arbel_cmd(), arbel_cmd_wait(), ath5k_hw_reg_read(), bflush(), br32(), cmdif_go_bit(), eeprom_read(), forcedeth_probe(), forcedeth_reset(), hermon_cmd(), hermon_cmd_wait(), mdio_read(), mii_rw(), mtnic_cmd(), ns83820_check_intr(), ns83820_disable(), ns83820_do_reset(), ns83820_getmac(), ns83820_probe(), ns83820_run_bist(), ns83820_set_multicast(), ns83820_transmit(), pci_push(), phantom_crb_access_128m(), phantom_crb_access_2m(), phantom_crb_access_32m(), phantom_readl(), phy_init(), phy_intr(), reg_delay(), skge_read32(), sky2_read32(), start_rx(), update_linkspeed(), and w89c840_poll().
| #define writeb outb |
Definition at line 157 of file w89c840.c.
Referenced by amd8111e_start(), enable_mii_autopoll(), mac_get_cam(), mac_get_cam_mask(), mac_set_cam(), mac_set_cam_mask(), mac_wol_reset(), safe_disable_mii_autopoll(), skge_write8(), sky2_write8(), sundance_reset(), velocity_disable(), velocity_init_registers(), velocity_mii_read(), velocity_mii_write(), velocity_set_media_mode(), and w89c840_reset().
| #define writew outw |
Definition at line 158 of file w89c840.c.
Referenced by __ew16flash(), amd8111e_init_hw_default(), amd8111e_start(), hfa384x_setreg(), init_flow_control_register(), mac_set_cam(), mac_wol_reset(), skge_write16(), sky2_write16(), velocity_disable(), velocity_give_many_rx_descs(), velocity_init_registers(), velocity_mii_write(), and velocity_rx_reset().
| #define writel outl |
Definition at line 159 of file w89c840.c.
Referenced by __ew32(), __ew32flash(), __vxge_hw_pio_mem_write32_lower(), __vxge_hw_pio_mem_write32_upper(), amd8111e_disable_interrupt(), amd8111e_enable_interrupt(), amd8111e_force_interrupt(), amd8111e_init_hw_default(), amd8111e_poll(), amd8111e_read_phy(), amd8111e_start(), amd8111e_transmit(), arbel_cmd(), arbel_poll_eq(), arbel_ring_doorbell(), ath5k_hw_reg_write(), bw32(), eeprom_read(), enable_flow_control_ability(), forcedeth_disable(), forcedeth_probe(), forcedeth_reset(), forcedeth_transmit(), hermon_cmd(), hermon_poll_eq(), hermon_post_send(), hermon_reset(), init_flow_control_register(), kick_tx(), linda_writel(), mdio_read(), mdio_sync(), mii_rw(), mtnic_cmd(), mtnic_reset(), mtnic_transmit(), ns83820_disable(), ns83820_do_reset(), ns83820_getmac(), ns83820_probe(), ns83820_reset(), ns83820_run_bist(), ns83820_set_multicast(), ns83820_setup_rx(), ns83820_transmit(), phantom_crb_access_128m(), phantom_crb_access_2m(), phantom_crb_access_32m(), phantom_writel(), phy_intr(), set_multicast(), set_rx_mode(), skge_write32(), sky2_write32(), start_rx(), start_tx(), stop_rx(), stop_tx(), txrx_reset(), update_linkspeed(), velocity_disable(), velocity_init_registers(), velocity_rx_reset(), velocity_soft_reset(), w89c840_disable(), w89c840_probe(), w89c840_reset(), and w89c840_transmit().
| #define PCI_DEVICE_ID_WINBOND2_89C840 0x0840 |
Referenced by w89c840_probe().
| #define PCI_DEVICE_ID_COMPEX_RL100ATX 0x2011 |
Referenced by w89c840_probe().
| enum w840_offsets |
Definition at line 168 of file w89c840.c.
00168 { 00169 PCIBusCfg=0x00, TxStartDemand=0x04, RxStartDemand=0x08, 00170 RxRingPtr=0x0C, TxRingPtr=0x10, 00171 IntrStatus=0x14, NetworkConfig=0x18, IntrEnable=0x1C, 00172 RxMissed=0x20, EECtrl=0x24, MIICtrl=0x24, BootRom=0x28, GPTimer=0x2C, 00173 CurRxDescAddr=0x30, CurRxBufAddr=0x34, /* Debug use */ 00174 MulticastFilter0=0x38, MulticastFilter1=0x3C, StationAddr=0x40, 00175 CurTxDescAddr=0x4C, CurTxBufAddr=0x50, 00176 };
| enum intr_status_bits |
Definition at line 180 of file w89c840.c.
00180 { 00181 NormalIntr=0x10000, AbnormalIntr=0x8000, 00182 IntrPCIErr=0x2000, TimerInt=0x800, 00183 IntrRxDied=0x100, RxNoBuf=0x80, IntrRxDone=0x40, 00184 TxFIFOUnderflow=0x20, RxErrIntr=0x10, 00185 TxIdle=0x04, IntrTxStopped=0x02, IntrTxDone=0x01, 00186 };
| enum rx_mode_bits |
Definition at line 189 of file w89c840.c.
00189 { 00190 AcceptErr=0x80, AcceptRunt=0x40, 00191 AcceptBroadcast=0x20, AcceptMulticast=0x10, 00192 AcceptAllPhys=0x08, AcceptMyPhys=0x02, 00193 };
| enum mii_reg_bits |
| MDIO_ShiftClk | |
| MDIO_Data | |
| MDIO_EnbOutput | |
| MDIO_ShiftClk | |
| MDIO_DataIn | |
| MDIO_DataOut | |
| MDIO_EnbOutput | |
| MDIO_EnbIn |
Definition at line 195 of file w89c840.c.
00195 { 00196 MDIO_ShiftClk=0x10000, MDIO_DataIn=0x80000, MDIO_DataOut=0x20000, 00197 MDIO_EnbOutput=0x40000, MDIO_EnbIn = 0x00000, 00198 };
| enum desc_status_bits |
Definition at line 215 of file w89c840.c.
00215 { 00216 DescOwn=0x80000000, DescEndRing=0x02000000, DescUseLink=0x01000000, 00217 DescWholePkt=0x60000000, DescStartPkt=0x20000000, DescEndPkt=0x40000000, 00218 DescIntr=0x80000000, 00219 };
| enum EEPROM_Ctrl_Bits |
| EE_ShiftClk | |
| EE_DataIn | |
| EE_ChipSelect | |
| EE_DataOut | |
| EE_ShiftClk | |
| EE_Write0 | |
| EE_Write1 | |
| EE_ChipSelect | |
| EE_DataIn |
Definition at line 733 of file w89c840.c.
00733 { 00734 EE_ShiftClk=0x02, EE_Write0=0x801, EE_Write1=0x805, 00735 EE_ChipSelect=0x801, EE_DataIn=0x08, 00736 };
| enum EEPROM_Cmds |
Definition at line 739 of file w89c840.c.
00739 { 00740 EE_WriteCmd=(5 << 6), EE_ReadCmd=(6 << 6), EE_EraseCmd=(7 << 6), 00741 };
| FILE_LICENCE | ( | GPL2_OR_LATER | ) |
| static int eeprom_read | ( | long | ioaddr, | |
| int | location | |||
| ) | [static] |
Definition at line 743 of file w89c840.c.
References EE_ChipSelect, EE_DataIn, EE_ReadCmd, EE_ShiftClk, EE_Write0, EE_Write1, EECtrl, eeprom_delay, readl, and writel.
00744 { 00745 int i; 00746 int retval = 0; 00747 int ee_addr = addr + EECtrl; 00748 int read_cmd = location | EE_ReadCmd; 00749 writel(EE_ChipSelect, ee_addr); 00750 00751 /* Shift the read command bits out. */ 00752 for (i = 10; i >= 0; i--) { 00753 short dataval = (read_cmd & (1 << i)) ? EE_Write1 : EE_Write0; 00754 writel(dataval, ee_addr); 00755 eeprom_delay(ee_addr); 00756 writel(dataval | EE_ShiftClk, ee_addr); 00757 eeprom_delay(ee_addr); 00758 } 00759 writel(EE_ChipSelect, ee_addr); 00760 00761 for (i = 16; i > 0; i--) { 00762 writel(EE_ChipSelect | EE_ShiftClk, ee_addr); 00763 eeprom_delay(ee_addr); 00764 retval = (retval << 1) | ((readl(ee_addr) & EE_DataIn) ? 1 : 0); 00765 writel(EE_ChipSelect, ee_addr); 00766 eeprom_delay(ee_addr); 00767 } 00768 00769 /* Terminate the EEPROM access. */ 00770 writel(0, ee_addr); 00771 return retval; 00772 }
| static int mdio_read | ( | int | base_address, | |
| int | phy_id, | |||
| int | location | |||
| ) | [static] |
Definition at line 806 of file w89c840.c.
References MDIO_DataIn, mdio_delay, MDIO_EnbIn, MDIO_ShiftClk, mdio_sync(), MDIO_WRITE0, MDIO_WRITE1, MIICtrl, readl, and writel.
00807 { 00808 long mdio_addr = base_address + MIICtrl; 00809 int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; 00810 int i, retval = 0; 00811 00812 if (mii_preamble_required) 00813 mdio_sync(mdio_addr); 00814 00815 /* Shift the read command bits out. */ 00816 for (i = 15; i >= 0; i--) { 00817 int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; 00818 00819 writel(dataval, mdio_addr); 00820 mdio_delay(mdio_addr); 00821 writel(dataval | MDIO_ShiftClk, mdio_addr); 00822 mdio_delay(mdio_addr); 00823 } 00824 /* Read the two transition, 16 data, and wire-idle bits. */ 00825 for (i = 20; i > 0; i--) { 00826 writel(MDIO_EnbIn, mdio_addr); 00827 mdio_delay(mdio_addr); 00828 retval = (retval << 1) | ((readl(mdio_addr) & MDIO_DataIn) ? 1 : 0); 00829 writel(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr); 00830 mdio_delay(mdio_addr); 00831 } 00832 return (retval>>1) & 0xffff; 00833 }
| static void check_duplex | ( | void | ) | [static] |
Definition at line 868 of file w89c840.c.
References winbond_private::advertising, winbond_private::csr6, winbond_private::duplex_lock, winbond_private::full_duplex, mdio_read(), winbond_private::phys, printf(), and w840private.
00869 { 00870 int mii_reg5 = mdio_read(ioaddr, w840private.phys[0], 5); 00871 int negotiated = mii_reg5 & w840private.advertising; 00872 int duplex; 00873 00874 if (w840private.duplex_lock || mii_reg5 == 0xffff) 00875 return; 00876 00877 duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040; 00878 if (w840private.full_duplex != duplex) { 00879 w840private.full_duplex = duplex; 00880 00881 #if defined(W89C840_DEBUG) 00882 printf("winbond-840 : Setting %s-duplex based on MII # %d negotiated capability %X\n", 00883 duplex ? "full" : "half", w840private.phys[0], negotiated); 00884 #endif 00885 00886 w840private.csr6 &= ~0x200; 00887 w840private.csr6 |= duplex ? 0x200 : 0; 00888 } 00889 }
| static void set_rx_mode | ( | void | ) | [static] |
Definition at line 891 of file w89c840.c.
References AcceptBroadcast, AcceptMulticast, AcceptMyPhys, winbond_private::csr6, memset(), MulticastFilter0, MulticastFilter1, NetworkConfig, printf(), u32, w840private, and writel.
00892 { 00893 u32 mc_filter[2]; /* Multicast hash filter */ 00894 u32 rx_mode; 00895 00896 /* Accept all multicasts from now on. */ 00897 memset(mc_filter, 0xff, sizeof(mc_filter)); 00898 00899 /* 00900 * works OK with multicast enabled. 00901 */ 00902 00903 rx_mode = AcceptBroadcast | AcceptMyPhys | AcceptMulticast; 00904 00905 writel(mc_filter[0], ioaddr + MulticastFilter0); 00906 writel(mc_filter[1], ioaddr + MulticastFilter1); 00907 w840private.csr6 &= ~0x00F8; 00908 w840private.csr6 |= rx_mode; 00909 writel(w840private.csr6, ioaddr + NetworkConfig); 00910 00911 #if defined(W89C840_DEBUG) 00912 printf("winbond-840 : Done setting RX mode.\n"); 00913 #endif 00914 }
| static void init_ring | ( | void | ) | [static] |
Definition at line 917 of file w89c840.c.
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_tx_desc::status, w840_rx_desc::status, winbond_private::tx_full, winbond_private::tx_q_bytes, winbond_private::tx_ring, TX_RING_SIZE, virt_to_le32desc, and w840private.
00918 { 00919 int i; 00920 char * p; 00921 00922 w840private.tx_full = 0; 00923 w840private.tx_q_bytes = w840private.cur_rx = w840private.cur_tx = 0; 00924 w840private.dirty_rx = w840private.dirty_tx = 0; 00925 00926 w840private.rx_buf_sz = PKT_BUF_SZ; 00927 w840private.rx_head_desc = &w840private.rx_ring[0]; 00928 00929 /* Initial all Rx descriptors. Fill in the Rx buffers. */ 00930 00931 p = &w89c840_buf.rx_packet[0]; 00932 00933 for (i = 0; i < RX_RING_SIZE; i++) { 00934 w840private.rx_ring[i].length = w840private.rx_buf_sz; 00935 w840private.rx_ring[i].status = 0; 00936 w840private.rx_ring[i].next_desc = virt_to_le32desc(&w840private.rx_ring[i+1]); 00937 00938 w840private.rx_ring[i].buffer1 = virt_to_le32desc(p + (PKT_BUF_SZ * i)); 00939 w840private.rx_ring[i].status = DescOwn | DescIntr; 00940 } 00941 00942 /* Mark the last entry as wrapping the ring. */ 00943 w840private.rx_ring[i-1].length |= DescEndRing; 00944 w840private.rx_ring[i-1].next_desc = virt_to_le32desc(&w840private.rx_ring[0]); 00945 00946 w840private.dirty_rx = (unsigned int)(i - RX_RING_SIZE); 00947 00948 for (i = 0; i < TX_RING_SIZE; i++) { 00949 w840private.tx_ring[i].status = 0; 00950 } 00951 return; 00952 }
| static void w89c840_reset | ( | struct nic * | nic | ) | [static] |
Definition at line 300 of file w89c840.c.
References check_duplex(), winbond_private::csr6, ETH_ALEN, init_ring(), 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().
00301 { 00302 int i; 00303 00304 /* Reset the chip to erase previous misconfiguration. 00305 No hold time required! */ 00306 writel(0x00000001, ioaddr + PCIBusCfg); 00307 00308 init_ring(); 00309 00310 writel(virt_to_bus(w840private.rx_ring), ioaddr + RxRingPtr); 00311 writel(virt_to_bus(w840private.tx_ring), ioaddr + TxRingPtr); 00312 00313 for (i = 0; i < ETH_ALEN; i++) 00314 writeb(nic->node_addr[i], ioaddr + StationAddr + i); 00315 00316 /* Initialize other registers. */ 00317 /* Configure the PCI bus bursts and FIFO thresholds. 00318 486: Set 8 longword cache alignment, 8 longword burst. 00319 586: Set 16 longword cache alignment, no burst limit. 00320 Cache alignment bits 15:14 Burst length 13:8 00321 0000 <not allowed> 0000 align to cache 0800 8 longwords 00322 4000 8 longwords 0100 1 longword 1000 16 longwords 00323 8000 16 longwords 0200 2 longwords 2000 32 longwords 00324 C000 32 longwords 0400 4 longwords 00325 Wait the specified 50 PCI cycles after a reset by initializing 00326 Tx and Rx queues and the address filter list. */ 00327 00328 writel(0xE010, ioaddr + PCIBusCfg); 00329 00330 writel(0, ioaddr + RxStartDemand); 00331 w840private.csr6 = 0x20022002; 00332 check_duplex(); 00333 set_rx_mode(); 00334 00335 /* Do not enable the interrupts Etherboot doesn't need them */ 00336 /* 00337 writel(0x1A0F5, ioaddr + IntrStatus); 00338 writel(0x1A0F5, ioaddr + IntrEnable); 00339 */ 00340 #if defined(W89C840_DEBUG) 00341 printf("winbond-840 : Done reset.\n"); 00342 #endif 00343 }
| static int w89c840_poll | ( | struct nic * | nic, | |
| int | retrieve | |||
| ) | [static] |
Definition at line 376 of file w89c840.c.
References w840_rx_desc::buffer1, winbond_private::cur_rx, DescOwn, entry, IntrStatus, le32desc_to_virt, memcpy, nic::packet, nic::packetlen, printf(), readl, winbond_private::rx_head_desc, winbond_private::rx_ring, RX_RING_SIZE, w840_rx_desc::status, u32, w840private, and w89c840_reset().
00377 { 00378 /* return true if there's an ethernet packet ready to read */ 00379 /* nic->packet should contain data on return */ 00380 /* nic->packetlen should contain length of data */ 00381 int packet_received = 0; 00382 00383 #if defined(W89C840_DEBUG) 00384 u32 intr_status = readl(ioaddr + IntrStatus); 00385 #endif 00386 00387 do { 00388 /* Code from netdev_rx(dev) */ 00389 00390 int entry = w840private.cur_rx % RX_RING_SIZE; 00391 00392 struct w840_rx_desc *desc = w840private.rx_head_desc; 00393 s32 status = desc->status; 00394 00395 if (status & DescOwn) { 00396 /* DescOwn bit is still set, we should wait for RX to complete */ 00397 packet_received = 0; 00398 break; 00399 } 00400 00401 if ( !retrieve ) { 00402 packet_received = 1; 00403 break; 00404 } 00405 00406 if ((status & 0x38008300) != 0x0300) { 00407 if ((status & 0x38000300) != 0x0300) { 00408 /* Ingore earlier buffers. */ 00409 if ((status & 0xffff) != 0x7fff) { 00410 printf("winbond-840 : Oversized Ethernet frame spanned " 00411 "multiple buffers, entry %d status %X !\n", 00412 w840private.cur_rx, (unsigned int) status); 00413 } 00414 } else if (status & 0x8000) { 00415 /* There was a fatal error. */ 00416 #if defined(W89C840_DEBUG) 00417 printf("winbond-840 : Receive error, Rx status %X :", status); 00418 if (status & 0x0890) { 00419 printf(" RXLEN_ERROR"); 00420 } 00421 if (status & 0x004C) { 00422 printf(", FRAME_ERROR"); 00423 } 00424 if (status & 0x0002) { 00425 printf(", CRC_ERROR"); 00426 } 00427 printf("\n"); 00428 #endif 00429 00430 /* Simpy do a reset now... */ 00431 w89c840_reset(nic); 00432 00433 packet_received = 0; 00434 break; 00435 } 00436 } else { 00437 /* Omit the four octet CRC from the length. */ 00438 int pkt_len = ((status >> 16) & 0x7ff) - 4; 00439 00440 #if defined(W89C840_DEBUG) 00441 printf(" netdev_rx() normal Rx pkt ring %d length %d status %X\n", entry, pkt_len, status); 00442 #endif 00443 00444 nic->packetlen = pkt_len; 00445 00446 /* Check if the packet is long enough to accept without copying 00447 to a minimally-sized skbuff. */ 00448 00449 memcpy(nic->packet, le32desc_to_virt(w840private.rx_ring[entry].buffer1), pkt_len); 00450 packet_received = 1; 00451 00452 /* Release buffer to NIC */ 00453 w840private.rx_ring[entry].status = DescOwn; 00454 00455 #if defined(W89C840_DEBUG) 00456 /* You will want this info for the initial debug. */ 00457 printf(" Rx data %hhX:%hhX:%hhX:%hhX:%hhX:" 00458 "%hhX %hhX:%hhX:%hhX:%hhX:%hhX:%hhX %hhX%hhX " 00459 "%hhX.%hhX.%hhX.%hhX.\n", 00460 nic->packet[0], nic->packet[1], nic->packet[2], nic->packet[3], 00461 nic->packet[4], nic->packet[5], nic->packet[6], nic->packet[7], 00462 nic->packet[8], nic->packet[9], nic->packet[10], 00463 nic->packet[11], nic->packet[12], nic->packet[13], 00464 nic->packet[14], nic->packet[15], nic->packet[16], 00465 nic->packet[17]); 00466 #endif 00467 00468 } 00469 00470 entry = (++w840private.cur_rx) % RX_RING_SIZE; 00471 w840private.rx_head_desc = &w840private.rx_ring[entry]; 00472 } while (0); 00473 00474 return packet_received; 00475 }
| static void w89c840_transmit | ( | struct nic * | nic, | |
| const char * | d, | |||
| unsigned int | t, | |||
| unsigned int | s, | |||
| const char * | p | |||
| ) | [static] |
Definition at line 481 of file w89c840.c.
References w840_tx_desc::buffer1, winbond_private::cur_tx, currticks(), DescEndRing, DescIntr, DescOwn, DescWholePkt, winbond_private::drv_flags, entry, ETH_ALEN, ETH_HLEN, ETH_ZLEN, HasBrokenTx, 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.
00487 { 00488 /* send the packet to destination */ 00489 unsigned entry; 00490 int transmit_status; 00491 unsigned long ct; 00492 00493 /* Caution: the write order is important here, set the field 00494 with the "ownership" bits last. */ 00495 00496 /* Fill in our transmit buffer */ 00497 entry = w840private.cur_tx % TX_RING_SIZE; 00498 00499 memcpy (w89c840_buf.tx_packet, d, ETH_ALEN); /* dst */ 00500 memcpy (w89c840_buf.tx_packet + ETH_ALEN, nic->node_addr, ETH_ALEN);/*src*/ 00501 00502 *((char *) w89c840_buf.tx_packet + 12) = t >> 8; /* type */ 00503 *((char *) w89c840_buf.tx_packet + 13) = t; 00504 00505 memcpy (w89c840_buf.tx_packet + ETH_HLEN, p, s); 00506 s += ETH_HLEN; 00507 00508 while (s < ETH_ZLEN) 00509 *((char *) w89c840_buf.tx_packet + ETH_HLEN + (s++)) = 0; 00510 00511 w840private.tx_ring[entry].buffer1 00512 = virt_to_le32desc(w89c840_buf.tx_packet); 00513 00514 w840private.tx_ring[entry].length = (DescWholePkt | (u32) s); 00515 if (entry >= TX_RING_SIZE-1) /* Wrap ring */ 00516 w840private.tx_ring[entry].length |= (DescIntr | DescEndRing); 00517 w840private.tx_ring[entry].status = (DescOwn); 00518 w840private.cur_tx++; 00519 00520 w840private.tx_q_bytes = (u16) s; 00521 writel(0, ioaddr + TxStartDemand); 00522 00523 /* Work around horrible bug in the chip by marking the queue as full 00524 when we do not have FIFO room for a maximum sized packet. */ 00525 00526 if ((w840private.drv_flags & HasBrokenTx) && w840private.tx_q_bytes > TX_BUG_FIFO_LIMIT) { 00527 /* Actually this is left to help finding error tails later in debugging... 00528 * See Linux kernel driver in winbond-840.c for details. 00529 */ 00530 w840private.tx_full = 1; 00531 } 00532 00533 #if defined(W89C840_DEBUG) 00534 printf("winbond-840 : Transmit frame # %d size %d queued in slot %d.\n", w840private.cur_tx, s, entry); 00535 #endif 00536 00537 /* Now wait for TX to complete. */ 00538 transmit_status = w840private.tx_ring[entry].status; 00539 00540 ct = currticks(); 00541 { 00542 #if defined W89C840_DEBUG 00543 u32 intr_stat = 0; 00544 #endif 00545 while (1) { 00546 00547 #if defined(W89C840_DEBUG) 00548 decode_interrupt(intr_stat); 00549 #endif 00550 00551 while ( (transmit_status & DescOwn) && ct + TX_TIMEOUT < currticks()) { 00552 00553 transmit_status = w840private.tx_ring[entry].status; 00554 } 00555 00556 break; 00557 } 00558 } 00559 00560 if ((transmit_status & DescOwn) == 0) { 00561 00562 #if defined(W89C840_DEBUG) 00563 printf("winbond-840 : transmission complete after wait loop iterations, status %X\n", 00564 w840private.tx_ring[entry].status); 00565 #endif 00566 00567 return; 00568 } 00569 00570 /* Transmit timed out... */ 00571 00572 printf("winbond-840 : transmission TIMEOUT : status %X\n", 00573 (unsigned int) w840private.tx_ring[entry].status); 00574 00575 return; 00576 }
| static void w89c840_disable | ( | struct nic * | nic | ) | [static] |
Definition at line 581 of file w89c840.c.
References winbond_private::csr6, NetworkConfig, w840private, w89c840_reset(), and writel.
00581 { 00582 00583 w89c840_reset(nic); 00584 00585 /* Don't know what to do to disable the board. Is this needed at all? */ 00586 /* Yes, a live NIC can corrupt the loaded memory later [Ken] */ 00587 /* Stop the chip's Tx and Rx processes. */ 00588 writel(w840private.csr6 &= ~0x20FA, ioaddr + NetworkConfig); 00589 }
| static void w89c840_irq | ( | struct nic *nic | __unused, | |
| irq_action_t action | __unused | |||
| ) | [static] |
| PCI_DRIVER | ( | w89c840_driver | , | |
| w89c840_nics | , | |||
| PCI_NO_CLASS | ||||
| ) |
| static int w89c840_probe | ( | struct nic * | nic, | |
| struct pci_device * | p | |||
| ) | [static] |
Definition at line 624 of file w89c840.c.
References adjust_pci_device(), winbond_private::advertising, pci_device::bus, CanHaveMII, DBG, pci_device::devfn, pci_device::device, driver_flags, eeprom_read(), ETH_ALEN, eth_ntoa(), nic::ioaddr, pci_device::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(), u16, pci_device::vendor, w840private, w89c840_reset(), w89c840_version, and writel.
00624 { 00625 00626 00627 u16 sum = 0; 00628 int i, j; 00629 unsigned short value; 00630 00631 if (p->ioaddr == 0) 00632 return 0; 00633 00634 nic->ioaddr = p->ioaddr; 00635 nic->irqno = 0; 00636 00637 #if defined(W89C840_DEBUG) 00638 printf("winbond-840: PCI bus %hhX device function %hhX: I/O address: %hX\n", p->bus, p->devfn, ioaddr); 00639 #endif 00640 00641 ioaddr = ioaddr & ~3; /* Mask the bit that says "this is an io addr" */ 00642 00643 #define PCI_DEVICE_ID_WINBOND2_89C840 0x0840 00644 #define PCI_DEVICE_ID_COMPEX_RL100ATX 0x2011 00645 00646 /* From Matt Hortman <mbhortman@acpthinclient.com> */ 00647 if (p->vendor == PCI_VENDOR_ID_WINBOND2 00648 && p->device == PCI_DEVICE_ID_WINBOND2_89C840) { 00649 00650 /* detected "Winbond W89c840 Fast Ethernet PCI NIC" */ 00651 00652 } else if ( p->vendor == PCI_VENDOR_ID_COMPEX 00653 && p->device == PCI_DEVICE_ID_COMPEX_RL100ATX) { 00654 00655 /* detected "Compex RL100ATX Fast Ethernet PCI NIC" */ 00656 00657 } else { 00658 /* Gee, guess what? They missed again. */ 00659 printf("device ID : %X - is not a Compex RL100ATX NIC.\n", 00660 p->device); 00661 return 0; 00662 } 00663 00664 printf(" %s\n", w89c840_version); 00665 00666 adjust_pci_device(p); 00667 00668 /* Ok. Got one. Read the eeprom. */ 00669 for (j = 0, i = 0; i < 0x40; i++) { 00670 value = eeprom_read(ioaddr, i); 00671 eeprom[i] = value; 00672 sum += value; 00673 } 00674 00675 for (i=0;i<ETH_ALEN;i++) { 00676 nic->node_addr[i] = (eeprom[i/2] >> (8*(i&1))) & 0xff; 00677 } 00678 00679 DBG ( "Ethernet addr: %s\n", eth_ntoa ( nic->node_addr ) ); 00680 00681 #if defined(W89C840_DEBUG) 00682 printf("winbond-840: EEPROM checksum %hX, got eeprom", sum); 00683 #endif 00684 00685 /* Reset the chip to erase previous misconfiguration. 00686 No hold time required! */ 00687 writel(0x00000001, ioaddr + PCIBusCfg); 00688 00689 if (driver_flags & CanHaveMII) { 00690 int phy, phy_idx = 0; 00691 for (phy = 1; phy < 32 && phy_idx < 4; phy++) { 00692 int mii_status = mdio_read(ioaddr, phy, 1); 00693 if (mii_status != 0xffff && mii_status != 0x0000) { 00694 w840private.phys[phy_idx++] = phy; 00695 w840private.advertising = mdio_read(ioaddr, phy, 4); 00696 00697 #if defined(W89C840_DEBUG) 00698 printf("winbond-840 : MII PHY found at address %d, status " 00699 "%X advertising %hX.\n", phy, mii_status, w840private.advertising); 00700 #endif 00701 00702 } 00703 } 00704 00705 w840private.mii_cnt = phy_idx; 00706 00707 if (phy_idx == 0) { 00708 printf("winbond-840 : MII PHY not found -- this device may not operate correctly.\n"); 00709 } 00710 } 00711 00712 /* point to NIC specific routines */ 00713 nic->nic_op = &w89c840_operations; 00714 00715 w89c840_reset(nic); 00716 00717 return 1; 00718 }
| static void mdio_sync | ( | long | mdio_addr | ) | [static] |
Definition at line 793 of file w89c840.c.
References mdio_delay, MDIO_ShiftClk, MDIO_WRITE1, and writel.
00794 { 00795 int bits = 32; 00796 00797 /* Establish sync by sending at least 32 logic ones. */ 00798 while (--bits >= 0) { 00799 writel(MDIO_WRITE1, mdio_addr); 00800 mdio_delay(mdio_addr); 00801 writel(MDIO_WRITE1 | MDIO_ShiftClk, mdio_addr); 00802 mdio_delay(mdio_addr); 00803 } 00804 }
| DRIVER | ( | "W89C840F" | , | |
| nic_driver | , | |||
| pci_driver | , | |||
| w89c840_driver | , | |||
| w89c840_probe | , | |||
| w89c840_disable | ||||
| ) |
const char* w89c840_version = "driver Version 0.94 - December 12, 2003" [static] |
u32 driver_flags = CanHaveMII | HasBrokenTx [static] |
struct winbond_private w840private [static] |
Referenced by check_duplex(), init_ring(), set_rx_mode(), w89c840_disable(), w89c840_poll(), w89c840_probe(), w89c840_reset(), and w89c840_transmit().
| struct { ... } __shared |
struct nic_operations w89c840_operations [static] |
Initial value:
{
.connect = dummy_connect,
.poll = w89c840_poll,
.transmit = w89c840_transmit,
.irq = w89c840_irq,
}
struct pci_device_id w89c840_nics[] [static] |
char mii_preamble_required = 1 [static] |
1.5.7.1