1N/A * w89c840.c -- This file implements the winbond-840 driver for etherboot. 1N/A * Adapted by Igor V. Kovalenko 1N/A * -- <garrison@mail.ru> 1N/A * -- <iko@crec.mipt.ru> 1N/A * Initial adaptaion stage, including testing, completed 23 August 2000. 1N/A * This program is free software; you can redistribute it and/or 1N/A * modify it under the terms of the GNU General Public License as 1N/A * published by the Free Software Foundation; either version 2, or (at 1N/A * your option) any later version. 1N/A * This program is distributed in the hope that it will be useful, but 1N/A * WITHOUT ANY WARRANTY; without even the implied warranty of 1N/A * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1N/A * General Public License for more details. 1N/A * You should have received a copy of the GNU General Public License 1N/A * along with this program; if not, write to the Free Software 1N/A * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 1N/A * date version by what 1N/A * Written: Aug 20 2000 V0.10 iko Initial revision. 1N/A * changes: Aug 22 2000 V0.90 iko Works! 1N/A * Aug 23 2000 V0.91 iko Cleanup, posted to etherboot 1N/A * Aug 26 2000 V0.92 iko Fixed Rx ring handling. 1N/A * First Linux Kernel (TM) 1N/A * successfully loaded using 1N/A * Jan 07 2001 V0.93 iko Transmitter timeouts are handled 1N/A * using timer2 routines. Proposed 1N/A * by Ken Yap to eliminate CPU speed 1N/A * Dec 12 2003 V0.94 timlegge Fixed issues in 5.2, removed 1N/A * interrupt usage, enabled 1N/A * This is the etherboot driver for cards based on Winbond W89c840F chip. 1N/A * kernel driver as a guideline. Mostly the w89c840 related definitions 1N/A * and the lower level routines have been cut-and-pasted into this source. 1N/A * Frankly speaking, about 90% of the code was obtained using cut'n'paste 1N/A * sequence :) while the remainder appeared while brainstorming 1N/A * Linux Kernel 2.4.0-testX source code. Thanks, Donald and Linus! 1N/A * There was a demand for using this card in a rather large 1N/A * remote boot environment at MSKP OVTI Lab of 1N/A * so you may count that for motivation. 1N/A * If you want to see debugging output then define W89C840_DEBUG 1N/A#define W89C840_DEBUG 1N/A * Keep using IO_OPS for Etherboot driver! 1N/A/* Linux support functions */ 1N/A#define cpu_to_le32(val) (val) 1N/A#define le32_to_cpu(val) (val) 1N/A/* Operational parameters that are set at compile time. */ 1N/A/* Keep the ring sizes a power of two for compile efficiency. 1N/A The compiler will convert <unsigned>'%'<2^N> into a bit mask. 1N/A Making the Tx ring too large decreases the effectiveness of channel 1N/A bonding and packet priority. 1N/A There are no ill effects from too-large receive rings. */ 1N/A/* The presumed FIFO size for working around the Tx-FIFO-overflow bug. 1N/A To avoid overflowing we don't queue again until we have room for a 1N/A/* Operational parameters that usually are not changed. */ 1N/A/* Time in jiffies before concluding the transmitter is hung. */ 1N/A * Used to be this much CPU loops on Celeron@400 (?), 1N/A * now using real timer and TX_TIMEOUT! 1N/A * #define TX_LOOP_COUNT 10000000 1N/A/* This driver was written to use PCI memory space, however some x86 systems 1N/A work only with I/O space accesses. Pass -DUSE_IO_OPS to use PCI I/O space 1N/A accesses instead of memory space. */ 1N/A/* Offsets to the Command and Status Registers, "CSRs". 1N/A While similar to the Tulip, these registers are longword aligned. 1N/A Note: It's not useful to define symbolic names for every register bit in 1N/A the device. The name can only partially document the semantics and make 1N/A the driver longer and more difficult to read. 1N/A/* The bits in the Intr Status/Enable registers, mostly interrupt sources. */ 1N/A/* Bits in the NetworkConfig register. */ 1N/A/* The Tulip Rx and Tx buffer descriptors. */ 1N/A /* Descriptor rings first for alignment. */ 1N/A /* Frequently used values: keep some adjacent for cache effect. */ 1N/A unsigned int tx_full:
1;
/* The Tx queue is full. */ 1N/A /* MII transceiver section. */ 1N/A unsigned char phys[
2];
/* MII device addresses. */ 1N/A/* NIC specific static variables go here */ 1N/A/************************************************************************** 1N/Aw89c840_reset - Reset adapter 1N/A***************************************************************************/ 1N/A /* Reset the chip to erase previous misconfiguration. 1N/A No hold time required! */ 1N/A /* Initialize other registers. */ 1N/A /* Configure the PCI bus bursts and FIFO thresholds. 1N/A 486: Set 8 longword cache alignment, 8 longword burst. 1N/A 586: Set 16 longword cache alignment, no burst limit. 1N/A Cache alignment bits 15:14 Burst length 13:8 1N/A 0000 <not allowed> 0000 align to cache 0800 8 longwords 1N/A 4000 8 longwords 0100 1 longword 1000 16 longwords 1N/A 8000 16 longwords 0200 2 longwords 2000 32 longwords 1N/A C000 32 longwords 0400 4 longwords 1N/A Wait the specified 50 PCI cycles after a reset by initializing 1N/A Tx and Rx queues and the address filter list. */ 1N/A /* Do not enable the interrupts Etherboot doesn't need them */ 1N/A writel(0x1A0F5, ioaddr + IntrStatus); 1N/A writel(0x1A0F5, ioaddr + IntrEnable); 1N/A /* we are polling, do not return now */ 1N/A /* Acknowledge all of the current interrupt sources ASAP. */ 1N/A /* There was an abnormal interrupt */ 1N/A /* There was an interrupt */ 1N/A printf(
"-=- <=> No receive buffers available.\n");
1N/A/************************************************************************** 1N/Aw89c840_poll - Wait for a frame 1N/A***************************************************************************/ 1N/A /* return true if there's an ethernet packet ready to read */ 1N/A /* nic->packet should contain data on return */ 1N/A /* nic->packetlen should contain length of data */ 1N/A /* Code from netdev_rx(dev) */ 1N/A /* DescOwn bit is still set, we should wait for RX to complete */ 1N/A /* Ingore earlier buffers. */ 1N/A printf(
"winbond-840 : Oversized Ethernet frame spanned " 1N/A "multiple buffers, entry %d status %X !\n",
1N/A /* There was a fatal error. */ 1N/A /* Simpy do a reset now... */ 1N/A /* Omit the four octet CRC from the length. */ 1N/A /* Check if the packet is long enough to accept without copying 1N/A to a minimally-sized skbuff. */ 1N/A /* Release buffer to NIC */ 1N/A /* You will want this info for the initial debug. */ 1N/A "%hhX %hhX:%hhX:%hhX:%hhX:%hhX:%hhX %hhX%hhX " 1N/A "%hhX.%hhX.%hhX.%hhX.\n",
1N/A/************************************************************************** 1N/Aw89c840_transmit - Transmit a frame 1N/A***************************************************************************/ 1N/A const char *d,
/* Destination */ 1N/A unsigned int t,
/* Type */ 1N/A unsigned int s,
/* size */ 1N/A const char *p)
/* Packet */ 1N/A /* send the packet to destination */ 1N/A /* Caution: the write order is important here, set the field 1N/A with the "ownership" bits last. */ 1N/A /* Fill in our transmit buffer */ 1N/A /* Work around horrible bug in the chip by marking the queue as full 1N/A when we do not have FIFO room for a maximum sized packet. */ 1N/A /* Actually this is left to help finding error tails later in debugging... 1N/A /* Now wait for TX to complete. */ 1N/A printf(
"winbond-840 : transmission complete after wait loop iterations, status %X\n",
1N/A /* Transmit timed out... */ 1N/A/************************************************************************** 1N/Aw89c840_disable - Turn off ethernet interface 1N/A***************************************************************************/ 1N/A /* merge reset and disable */ 1N/A /* Don't know what to do to disable the board. Is this needed at all? */ 1N/A /* Yes, a live NIC can corrupt the loaded memory later [Ken] */ 1N/A /* Stop the chip's Tx and Rx processes. */ 1N/A/************************************************************************** 1N/Aw89c840_irq - Enable, Disable, or Force interrupts 1N/A***************************************************************************/ 1N/A/************************************************************************** 1N/Aw89c840_probe - Look for an adapter, this routine's visible to the outside 1N/A***************************************************************************/ 1N/A /* From Matt Hortman <mbhortman@acpthinclient.com> */ 1N/A /* detected "Winbond W89c840 Fast Ethernet PCI NIC" */ 1N/A /* detected "Compex RL100ATX Fast Ethernet PCI NIC" */ 1N/A /* Gee, guess what? They missed again. */ 1N/A /* Ok. Got one. Read the eeprom. */ 1N/A for (j = 0, i = 0; i <
0x40; i++) {
1N/A printf(
"winbond-840: EEPROM checksum %hX, got eeprom",
sum);
1N/A /* Reset the chip to erase previous misconfiguration. 1N/A No hold time required! */ 1N/A printf(
"winbond-840 : MII PHY found at address %d, status " 1N/A printf(
"winbond-840 : MII PHY not found -- this device may not operate correctly.\n");
1N/A /* point to NIC specific routines */ 1N/A/* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. These are 1N/A often serial bit streams generated by the host processor. 1N/A The example below is for the common 93c46 EEPROM, 64 16 bit words. */ 1N/A/* Delay between EEPROM clock transitions. 1N/A No extra delay is needed with 33Mhz PCI, but future 66Mhz access may need 1N/A a delay. Note that pre-2.0.34 kernels had a cache-alignment bug that 1N/A made udelay() unreliable. 1N/A The old method of using an ISA access as a delay, __SLOW_DOWN_IO__, is 1N/A/* The EEPROM commands include the alway-set leading bit. */ 1N/A /* Shift the read command bits out. */ 1N/A for (i =
10; i >= 0; i--) {
1N/A for (i =
16; i > 0; i--) {
1N/A /* Terminate the EEPROM access. */ 1N/A/* MII transceiver control section. 1N/A Read and write the MII registers using software-generated serial 1N/A MDIO protocol. See the MII specifications or DP83840A data sheet 1N/A The maximum data clock rate is 2.5 Mhz. The minimum timing is usually 1N/A met by back-to-back 33Mhz PCI cycles. */ 1N/A/* Set iff a MII transceiver on any interface requires mdio preamble. 1N/A This only set with older tranceivers, so the extra 1N/A code size of a per-interface flag is not worthwhile. */ 1N/A/* Generate the preamble required for initial synchronization and 1N/A a few older transceivers. */ 1N/A /* Establish sync by sending at least 32 logic ones. */ 1N/A /* Shift the read command bits out. */ 1N/A for (i =
15; i >= 0; i--) {
1N/A /* Read the two transition, 16 data, and wire-idle bits. */ 1N/A for (i =
20; i > 0; i--) {
1N/A /* Shift the command bits out. */ 1N/A for (i =
31; i >= 0; i--) {
1N/A /* Clear out extra bits. */ 1N/A for (i =
2; i > 0; i--) {
1N/A printf(
"winbond-840 : Setting %s-duplex based on MII # %d negotiated capability %X\n",
1N/A /* Accept all multicasts from now on. */ 1N/A * works OK with multicast enabled. 1N/A printf(
"winbond-840 : Done setting RX mode.\n");
1N/A/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ 1N/A /* Initial all Rx descriptors. Fill in the Rx buffers. */ 1N/A /* Mark the last entry as wrapping the ring. */ 1N/APCI_ROM(
0x1050,
0x0840,
"winbond840",
"Winbond W89C840F"),
1N/APCI_ROM(
0x11f6,
0x2011,
"compexrl100atx",
"Compex RL100ATX"),