/************************************************************************** w89c840_disable - Turn off ethernet interface ***************************************************************************/ static void w89c840_disable ( struct nic *nic ) { w89c840_reset(nic); /* Don't know what to do to disable the board. Is this needed at all? */ /* Yes, a live NIC can corrupt the loaded memory later [Ken] */ /* Stop the chip's Tx and Rx processes. */ writel(w840private.csr6 &= ~0x20FA, ioaddr + NetworkConfig); }
struct nic *w89c840_probe(struct nic *nic, unsigned short *probe_addrs, struct pci_device *p) { u16 sum = 0; int i, j, to; unsigned short value; int options; int promisc; if (probe_addrs == 0 || probe_addrs[0] == 0) return 0; ioaddr = probe_addrs[0]; #if defined(W89C840_DEBUG) printf("winbond-840: PCI bus %hhX device function %hhX: I/O address: %hX\n", p->bus, p->devfn, ioaddr); #endif ioaddr = ioaddr & ~3; if (p->vendor == PCI_VENDOR_ID_WINBOND2 && p->dev_id == PCI_DEVICE_ID_WINBOND2_89C840) { } else if ( p->vendor == PCI_VENDOR_ID_COMPEX && p->dev_id == PCI_DEVICE_ID_COMPEX_RL100ATX) { } else { printf("device ID : %X - is not a Compex RL100ATX NIC.\n", p->dev_id); return 0; } printf(" %s\n", w89c840_version); adjust_pci_device(p); for (j = 0, i = 0; i < 0x40; i++) { value = eeprom_read(ioaddr, i); eeprom[i] = value; sum += value; } for (i=0;i<ETH_ALEN;i++) { nic->node_addr[i] = (eeprom[i/2] >> (8*(i&1))) & 0xff; } printf ("Ethernet addr: %!\n", nic->node_addr); #if defined(W89C840_DEBUG) printf("winbond-840: EEPROM checksum %hX, got eeprom", sum); #endif writel(0x00000001, ioaddr + PCIBusCfg); if (driver_flags & CanHaveMII) { int phy, phy_idx = 0; for (phy = 1; phy < 32 && phy_idx < 4; phy++) { int mii_status = mdio_read(ioaddr, phy, 1); if (mii_status != 0xffff && mii_status != 0x0000) { w840private.phys[phy_idx++] = phy; w840private.advertising = mdio_read(ioaddr, phy, 4); #if defined(W89C840_DEBUG) printf("winbond-840 : MII PHY found at address %d, status " "%X advertising %hX.\n", phy, mii_status, w840private.advertising); #endif } } w840private.mii_cnt = phy_idx; if (phy_idx == 0) { printf("winbond-840 : MII PHY not found -- this device may not operate correctly.\n"); } } nic->reset = w89c840_reset; nic->poll = w89c840_poll; nic->transmit = w89c840_transmit; nic->disable = w89c840_disable; w89c840_reset(nic); return nic; }
/************************************************************************** w89c840_poll - Wait for a frame ***************************************************************************/ static int w89c840_poll(struct nic *nic, int retrieve) { /* return true if there's an ethernet packet ready to read */ /* nic->packet should contain data on return */ /* nic->packetlen should contain length of data */ int packet_received = 0; #if defined(W89C840_DEBUG) u32 intr_status = readl(ioaddr + IntrStatus); #endif do { /* Code from netdev_rx(dev) */ int entry = w840private.cur_rx % RX_RING_SIZE; struct w840_rx_desc *desc = w840private.rx_head_desc; s32 status = desc->status; if (status & DescOwn) { /* DescOwn bit is still set, we should wait for RX to complete */ packet_received = 0; break; } if ( !retrieve ) { packet_received = 1; break; } if ((status & 0x38008300) != 0x0300) { if ((status & 0x38000300) != 0x0300) { /* Ingore earlier buffers. */ if ((status & 0xffff) != 0x7fff) { printf("winbond-840 : Oversized Ethernet frame spanned " "multiple buffers, entry %d status %X !\n", w840private.cur_rx, (unsigned int) status); } } else if (status & 0x8000) { /* There was a fatal error. */ #if defined(W89C840_DEBUG) printf("winbond-840 : Receive error, Rx status %X :", status); if (status & 0x0890) { printf(" RXLEN_ERROR"); } if (status & 0x004C) { printf(", FRAME_ERROR"); } if (status & 0x0002) { printf(", CRC_ERROR"); } printf("\n"); #endif /* Simpy do a reset now... */ w89c840_reset(nic); packet_received = 0; break; } } else { /* Omit the four octet CRC from the length. */ int pkt_len = ((status >> 16) & 0x7ff) - 4; #if defined(W89C840_DEBUG) printf(" netdev_rx() normal Rx pkt ring %d length %d status %X\n", entry, pkt_len, status); #endif nic->packetlen = pkt_len; /* Check if the packet is long enough to accept without copying to a minimally-sized skbuff. */ memcpy(nic->packet, le32desc_to_virt(w840private.rx_ring[entry].buffer1), pkt_len); packet_received = 1; /* Release buffer to NIC */ w840private.rx_ring[entry].status = DescOwn; #if defined(W89C840_DEBUG) /* You will want this info for the initial debug. */ printf(" Rx data %hhX:%hhX:%hhX:%hhX:%hhX:" "%hhX %hhX:%hhX:%hhX:%hhX:%hhX:%hhX %hhX%hhX " "%hhX.%hhX.%hhX.%hhX.\n", nic->packet[0], nic->packet[1], nic->packet[2], nic->packet[3], nic->packet[4], nic->packet[5], nic->packet[6], nic->packet[7], nic->packet[8], nic->packet[9], nic->packet[10], nic->packet[11], nic->packet[12], nic->packet[13], nic->packet[14], nic->packet[15], nic->packet[16], nic->packet[17]); #endif } entry = (++w840private.cur_rx) % RX_RING_SIZE; w840private.rx_head_desc = &w840private.rx_ring[entry]; } while (0); return packet_received; }
static int w89c840_poll(struct nic *nic) { int packet_received = 0; u32 intr_status = readl(ioaddr + IntrStatus); do { int entry = w840private.cur_rx % RX_RING_SIZE; struct w840_rx_desc *desc = w840private.rx_head_desc; s32 status = desc->status; if (status & DescOwn) { packet_received = 0; break; } if ((status & 0x38008300) != 0x0300) { if ((status & 0x38000300) != 0x0300) { if ((status & 0xffff) != 0x7fff) { printf("winbond-840 : Oversized Ethernet frame spanned " "multiple buffers, entry %d status %X !\n", w840private.cur_rx, status); } } else if (status & 0x8000) { #if defined(W89C840_DEBUG) printf("winbond-840 : Receive error, Rx status %X :", status); if (status & 0x0890) { printf(" RXLEN_ERROR"); } if (status & 0x004C) { printf(", FRAME_ERROR"); } if (status & 0x0002) { printf(", CRC_ERROR"); } printf("\n"); #endif w89c840_reset(nic); packet_received = 0; break; } } else { int pkt_len = ((status >> 16) & 0x7ff) - 4; #if defined(W89C840_DEBUG) printf(" netdev_rx() normal Rx pkt ring %d length %d status %X\n", entry, pkt_len, status); #endif nic->packetlen = pkt_len; memcpy(nic->packet, le32desc_to_virt(w840private.rx_ring[entry].buffer1), pkt_len); packet_received = 1; w840private.rx_ring[entry].status = DescOwn; #if defined(W89C840_DEBUG) printf(" Rx data %hhX:%hhX:%hhX:%hhX:%hhX:" "%hhX %hhX:%hhX:%hhX:%hhX:%hhX:%hhX %hhX%hhX " "%hhX.%hhX.%hhX.%hhX.\n", nic->packet[0], nic->packet[1], nic->packet[2], nic->packet[3], nic->packet[4], nic->packet[5], nic->packet[6], nic->packet[7], nic->packet[8], nic->packet[9], nic->packet[10], nic->packet[11], nic->packet[12], nic->packet[13], nic->packet[14], nic->packet[15], nic->packet[16], nic->packet[17]); #endif } entry = (++w840private.cur_rx) % RX_RING_SIZE; w840private.rx_head_desc = &w840private.rx_ring[entry]; } while (0); if (intr_status & (AbnormalIntr | TxFIFOUnderflow | IntrPCIErr |TimerInt | IntrTxStopped)) { handle_intr(intr_status); } return packet_received; }