91#define virt_to_le32desc(addr) virt_to_bus(addr)
92#define le32desc_to_virt(addr) bus_to_virt(addr)
106#define TX_RING_SIZE 2
107#define RX_RING_SIZE 2
113#define TX_FIFO_SIZE (2048)
114#define TX_BUG_FIFO_LIMIT (TX_FIFO_SIZE-1514-16)
118#define TX_TIMEOUT (10*1000)
120#define PKT_BUF_SZ 1536
128#if !defined(__OPTIMIZE__)
129#warning You must compile this file with the correct options!
130#warning See the last lines of the source file.
131#error You must compile this driver with "-O".
137#define W840_FLAGS (PCI_USES_IO | PCI_ADDR0 | PCI_USES_MASTER)
139#define W840_FLAGS (PCI_USES_MEM | PCI_ADDR1 | PCI_USES_MASTER)
222#define PRIV_ALIGN_BYTES 32
261#define w89c840_buf NIC_FAKE_BSS ( struct w89c840_bss )
264static int mdio_read(
int base_address,
int phy_id,
int location);
266static void mdio_write(
int base_address,
int phy_id,
int location,
int value);
273#if defined(W89C840_DEBUG)
274static void decode_interrupt(
u32 intr_status)
276 printf(
"Interrupt status: ");
278#define TRACE_INTR(_intr_) \
279 if (intr_status & (_intr_)) { printf (" " #_intr_); }
342#if defined(W89C840_DEBUG)
343 printf(
"winbond-840 : Done reset.\n");
348static void handle_intr(
u32 intr_stat)
360 printf(
"\n-=- Abnormal interrupt.\n");
362#if defined(W89C840_DEBUG)
363 decode_interrupt(intr_stat);
368 printf(
"-=- <=> No receive buffers available.\n");
383 int packet_received = 0;
385#if defined(W89C840_DEBUG)
408 if ((
status & 0x38008300) != 0x0300) {
409 if ((
status & 0x38000300) != 0x0300) {
411 if ((
status & 0xffff) != 0x7fff) {
412 printf(
"winbond-840 : Oversized Ethernet frame spanned "
413 "multiple buffers, entry %d status %X !\n",
416 }
else if (
status & 0x8000) {
418#if defined(W89C840_DEBUG)
419 printf(
"winbond-840 : Receive error, Rx status %X :",
status);
442#if defined(W89C840_DEBUG)
443 printf(
" netdev_rx() normal Rx pkt ring %d length %d status %X\n", entry,
pkt_len,
status);
457#if defined(W89C840_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",
476 return packet_received;
535#if defined(W89C840_DEBUG)
536 printf(
"winbond-840 : Transmit frame # %d size %d queued in slot %d.\n",
w840private.cur_tx, s, entry);
540 transmit_status =
w840private.tx_ring[entry].status;
544#if defined W89C840_DEBUG
549#if defined(W89C840_DEBUG)
550 decode_interrupt(intr_stat);
555 transmit_status =
w840private.tx_ring[entry].status;
562 if ((transmit_status &
DescOwn) == 0) {
564#if defined(W89C840_DEBUG)
565 printf(
"winbond-840 : transmission complete after wait loop iterations, status %X\n",
574 printf(
"winbond-840 : transmission TIMEOUT : status %X\n",
617PCI_ROM(0x1050, 0x0840,
"winbond840",
"Winbond W89C840F", 0),
618PCI_ROM(0x11f6, 0x2011,
"compexrl100atx",
"Compex RL100ATX", 0),
631 unsigned short value;
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);
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
663 printf(
"device ID : %X - is not a Compex RL100ATX NIC.\n",
673 for (i = 0; i < 0x40; i++) {
685#if defined(W89C840_DEBUG)
686 printf(
"winbond-840: EEPROM checksum %hX, got eeprom", sum);
694 int phy, phy_idx = 0;
695 for (phy = 1; phy < 32 && phy_idx < 4; phy++) {
697 if (mii_status != 0xffff && mii_status != 0x0000) {
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);
712 printf(
"winbond-840 : MII PHY not found -- this device may not operate correctly.\n");
735#define eeprom_delay(ee_addr) readl(ee_addr)
756 for (i = 10; i >= 0; i--) {
765 for (i = 16; i > 0; i--) {
785#define mdio_delay(mdio_addr) readl(mdio_addr)
792#define MDIO_WRITE0 (MDIO_EnbOutput)
793#define MDIO_WRITE1 (MDIO_DataOut | MDIO_EnbOutput)
802 while (--
bits >= 0) {
810static int mdio_read(
int base_address,
int phy_id,
int location)
812 long mdio_addr = base_address +
MIICtrl;
813 int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
820 for (i = 15; i >= 0; i--) {
823 writel(dataval, mdio_addr);
829 for (i = 20; i > 0; i--) {
836 return (
retval>>1) & 0xffff;
840static void mdio_write(
int base_address,
int phy_id,
int location,
int value)
842 long mdio_addr = base_address +
MIICtrl;
843 int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) |
value;
846 if (location == 4 && phy_id ==
w840private.phys[0])
853 for (i = 31; i >= 0; i--) {
856 writel(dataval, mdio_addr);
862 for (i = 2; i > 0; i--) {
875 int negotiated = mii_reg5 &
w840private.advertising;
881 duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
885#if defined(W89C840_DEBUG)
886 printf(
"winbond-840 : Setting %s-duplex based on MII # %d negotiated capability %X\n",
901 memset(mc_filter, 0xff,
sizeof(mc_filter));
915#if defined(W89C840_DEBUG)
916 printf(
"winbond-840 : Done setting RX mode.\n");
pseudo_bit_t value[0x00020]
static volatile void * bits
static unsigned long ioaddr
#define le32desc_to_virt(addr)
uint32_t addr
Buffer address.
struct ena_llq_option desc
Descriptor counts.
const char * eth_ntoa(const void *ll_addr)
Transcribe Ethernet address.
#define __unused
Declare a variable or data structure as unused.
#define DBG(...)
Print a debugging message.
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
static __always_inline unsigned long virt_to_bus(volatile const void *addr)
Convert virtual address to a bus address.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
int dummy_connect(struct nic *nic __unused)
#define DRIVER(_name_text, _unused2, _unused3, _name, _probe, _disable, _fake_bss)
#define PCI_DRIVER(_name, _ids, _class)
static struct command_descriptor read_cmd
"read" command descriptor
void adjust_pci_device(struct pci_device *pci)
Enable PCI device.
#define PCI_ROM(_vendor, _device, _name, _description, _data)
static void mdio_write(void *ioaddr, int phy_id, int reg, int val)
unsigned char * node_addr
struct nic_operations * nic_op
A PCI device ID list entry.
unsigned long ioaddr
I/O address.
uint16_t vendor
Vendor ID.
uint16_t device
Device ID.
char tx_packet[PKT_BUF_SZ *TX_RING_SIZE]
char rx_packet[PKT_BUF_SZ *RX_RING_SIZE]
struct net_device * next_module
const char * product_name
struct w840_rx_desc rx_ring[RX_RING_SIZE]
unsigned int default_port
struct w840_rx_desc * rx_head_desc
struct w840_tx_desc tx_ring[TX_RING_SIZE]
unsigned long currticks(void)
Get current system time in ticks.
int printf(const char *fmt,...)
Write a formatted string to the console.
static struct nic_operations w89c840_operations
static char mii_preamble_required
static void check_duplex(void)
static void w89c840_disable(struct nic *nic, void *hwdev __unused)
static void init_ring(void)
static struct pci_device_id w89c840_nics[]
#define PCI_DEVICE_ID_WINBOND2_89C840
#define virt_to_le32desc(addr)
#define eeprom_delay(ee_addr)
#define TX_BUG_FIFO_LIMIT
static void w89c840_irq(struct nic *nic __unused, irq_action_t action __unused)
#define PCI_DEVICE_ID_COMPEX_RL100ATX
static const char * w89c840_version
static void set_rx_mode(void)
static void mdio_sync(long mdio_addr)
#define PCI_VENDOR_ID_WINBOND2
static int mdio_read(int base_address, int phy_id, int location)
static void w89c840_transmit(struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p)
static int w89c840_poll(struct nic *nic, int retrieve)
static int w89c840_probe(struct nic *nic, struct pci_device *p)
static void w89c840_reset(struct nic *nic)
#define mdio_delay(mdio_addr)
static struct winbond_private w840private
static int eeprom_read(long ioaddr, int location)
#define PCI_VENDOR_ID_COMPEX