2 * Etherboot - BOOTP/TFTP Bootstrap Program
4 * w89c840.c -- This file implements the winbond-840 driver for etherboot.
9 * Adapted by Igor V. Kovalenko
10 * -- <garrison@mail.ru>
12 * -- <iko@crec.mipt.ru>
13 * Initial adaptaion stage, including testing, completed 23 August 2000.
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License as
19 * published by the Free Software Foundation; either version 2, or (at
20 * your option) any later version.
22 * This program is distributed in the hope that it will be useful, but
23 * WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33 * date version by what
34 * Written: Aug 20 2000 V0.10 iko Initial revision.
35 * changes: Aug 22 2000 V0.90 iko Works!
36 * Aug 23 2000 V0.91 iko Cleanup, posted to etherboot
38 * Aug 26 2000 V0.92 iko Fixed Rx ring handling.
39 * First Linux Kernel (TM)
40 * successfully loaded using
42 * Jan 07 2001 V0.93 iko Transmitter timeouts are handled
43 * using timer2 routines. Proposed
44 * by Ken Yap to eliminate CPU speed
46 * Dec 12 2003 V0.94 timlegge Fixed issues in 5.2, removed
47 * interrupt usage, enabled
50 * This is the etherboot driver for cards based on Winbond W89c840F chip.
52 * It was written from skeleton source, with Donald Becker's winbond-840.c
53 * kernel driver as a guideline. Mostly the w89c840 related definitions
54 * and the lower level routines have been cut-and-pasted into this source.
56 * Frankly speaking, about 90% of the code was obtained using cut'n'paste
57 * sequence :) while the remainder appeared while brainstorming
58 * Linux Kernel 2.4.0-testX source code. Thanks, Donald and Linus!
60 * There was a demand for using this card in a rather large
61 * remote boot environment at MSKP OVTI Lab of
62 * Moscow Institute for Physics and Technology (MIPT) -- http://www.mipt.ru/
63 * so you may count that for motivation.
68 * If you want to see debugging output then define W89C840_DEBUG
76 * Keep using IO_OPS for Etherboot driver!
80 #include "etherboot.h"
83 #include <gpxe/ethernet.h>
86 static const char *w89c840_version
= "driver Version 0.94 - December 12, 2003";
88 /* Linux support functions */
89 #define virt_to_le32desc(addr) virt_to_bus(addr)
90 #define le32desc_to_virt(addr) bus_to_virt(addr)
93 #define cpu_to_le32(val) (val)
94 #define le32_to_cpu(val) (val)
97 /* Operational parameters that are set at compile time. */
99 /* Keep the ring sizes a power of two for compile efficiency.
100 The compiler will convert <unsigned>'%'<2^N> into a bit mask.
101 Making the Tx ring too large decreases the effectiveness of channel
102 bonding and packet priority.
103 There are no ill effects from too-large receive rings. */
104 #define TX_RING_SIZE 2
105 #define RX_RING_SIZE 2
107 /* The presumed FIFO size for working around the Tx-FIFO-overflow bug.
108 To avoid overflowing we don't queue again until we have room for a
111 #define TX_FIFO_SIZE (2048)
112 #define TX_BUG_FIFO_LIMIT (TX_FIFO_SIZE-1514-16)
114 /* Operational parameters that usually are not changed. */
115 /* Time in jiffies before concluding the transmitter is hung. */
116 #define TX_TIMEOUT (10*TICKS_PER_MS)
118 #define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
121 * Used to be this much CPU loops on Celeron@400 (?),
122 * now using real timer and TX_TIMEOUT!
123 * #define TX_LOOP_COUNT 10000000
126 #if !defined(__OPTIMIZE__)
127 #warning You must compile this file with the correct options!
128 #warning See the last lines of the source file.
129 #error You must compile this driver with "-O".
132 enum chip_capability_flags
{CanHaveMII
=1, HasBrokenTx
=2};
135 #define W840_FLAGS (PCI_USES_IO | PCI_ADDR0 | PCI_USES_MASTER)
137 #define W840_FLAGS (PCI_USES_MEM | PCI_ADDR1 | PCI_USES_MASTER)
140 static u32 driver_flags
= CanHaveMII
| HasBrokenTx
;
142 /* This driver was written to use PCI memory space, however some x86 systems
143 work only with I/O space accesses. Pass -DUSE_IO_OPS to use PCI I/O space
144 accesses instead of memory space. */
161 /* Offsets to the Command and Status Registers, "CSRs".
162 While similar to the Tulip, these registers are longword aligned.
163 Note: It's not useful to define symbolic names for every register bit in
164 the device. The name can only partially document the semantics and make
165 the driver longer and more difficult to read.
168 PCIBusCfg
=0x00, TxStartDemand
=0x04, RxStartDemand
=0x08,
169 RxRingPtr
=0x0C, TxRingPtr
=0x10,
170 IntrStatus
=0x14, NetworkConfig
=0x18, IntrEnable
=0x1C,
171 RxMissed
=0x20, EECtrl
=0x24, MIICtrl
=0x24, BootRom
=0x28, GPTimer
=0x2C,
172 CurRxDescAddr
=0x30, CurRxBufAddr
=0x34, /* Debug use */
173 MulticastFilter0
=0x38, MulticastFilter1
=0x3C, StationAddr
=0x40,
174 CurTxDescAddr
=0x4C, CurTxBufAddr
=0x50,
177 /* Bits in the interrupt status/enable registers. */
178 /* The bits in the Intr Status/Enable registers, mostly interrupt sources. */
179 enum intr_status_bits
{
180 NormalIntr
=0x10000, AbnormalIntr
=0x8000,
181 IntrPCIErr
=0x2000, TimerInt
=0x800,
182 IntrRxDied
=0x100, RxNoBuf
=0x80, IntrRxDone
=0x40,
183 TxFIFOUnderflow
=0x20, RxErrIntr
=0x10,
184 TxIdle
=0x04, IntrTxStopped
=0x02, IntrTxDone
=0x01,
187 /* Bits in the NetworkConfig register. */
189 AcceptErr
=0x80, AcceptRunt
=0x40,
190 AcceptBroadcast
=0x20, AcceptMulticast
=0x10,
191 AcceptAllPhys
=0x08, AcceptMyPhys
=0x02,
195 MDIO_ShiftClk
=0x10000, MDIO_DataIn
=0x80000, MDIO_DataOut
=0x20000,
196 MDIO_EnbOutput
=0x40000, MDIO_EnbIn
= 0x00000,
199 /* The Tulip Rx and Tx buffer descriptors. */
200 struct w840_rx_desc
{
207 struct w840_tx_desc
{
210 u32 buffer1
, buffer2
; /* We use only buffer 1. */
213 /* Bits in network_desc.status */
214 enum desc_status_bits
{
215 DescOwn
=0x80000000, DescEndRing
=0x02000000, DescUseLink
=0x01000000,
216 DescWholePkt
=0x60000000, DescStartPkt
=0x20000000, DescEndPkt
=0x40000000,
219 #define PRIV_ALIGN 15 /* Required alignment mask */
220 #define PRIV_ALIGN_BYTES 32
222 static struct winbond_private
224 /* Descriptor rings first for alignment. */
225 struct w840_rx_desc rx_ring
[RX_RING_SIZE
];
226 struct w840_tx_desc tx_ring
[TX_RING_SIZE
];
227 struct net_device
*next_module
; /* Link for devices of this type. */
228 void *priv_addr
; /* Unaligned address for kfree */
229 const char *product_name
;
230 /* Frequently used values: keep some adjacent for cache effect. */
231 int chip_id
, drv_flags
;
232 struct pci_dev
*pci_dev
;
234 struct w840_rx_desc
*rx_head_desc
;
235 unsigned int cur_rx
, dirty_rx
; /* Producer/consumer ring indices */
236 unsigned int rx_buf_sz
; /* Based on MTU+slack. */
237 unsigned int cur_tx
, dirty_tx
;
239 unsigned int tx_full
:1; /* The Tx queue is full. */
240 /* These values are keep track of the transceiver/media in use. */
241 unsigned int full_duplex
:1; /* Full-duplex operation requested. */
242 unsigned int duplex_lock
:1;
243 unsigned int medialock
:1; /* Do not sense media. */
244 unsigned int default_port
:4; /* Last dev->if_port value. */
245 /* MII transceiver section. */
246 int mii_cnt
; /* MII device addresses. */
247 u16 advertising
; /* NWay media advertisement */
248 unsigned char phys
[2]; /* MII device addresses. */
249 } w840private
__attribute__ ((aligned (PRIV_ALIGN_BYTES
)));
251 /* NIC specific static variables go here */
254 static unsigned short eeprom
[0x40];
256 char rx_packet
[PKT_BUF_SZ
* RX_RING_SIZE
];
257 char tx_packet
[PKT_BUF_SZ
* TX_RING_SIZE
];
258 } w89c840_buf __shared
;
260 static int eeprom_read(long ioaddr
, int location
);
261 static int mdio_read(int base_address
, int phy_id
, int location
);
263 static void mdio_write(int base_address
, int phy_id
, int location
, int value
);
266 static void check_duplex(void);
267 static void set_rx_mode(void);
268 static void init_ring(void);
270 #if defined(W89C840_DEBUG)
271 static void decode_interrupt(u32 intr_status
)
273 printf("Interrupt status: ");
275 #define TRACE_INTR(_intr_) \
276 if (intr_status & (_intr_)) { printf (" " #_intr_); }
278 TRACE_INTR(NormalIntr
);
279 TRACE_INTR(AbnormalIntr
);
280 TRACE_INTR(IntrPCIErr
);
281 TRACE_INTR(TimerInt
);
282 TRACE_INTR(IntrRxDied
);
284 TRACE_INTR(IntrRxDone
);
285 TRACE_INTR(TxFIFOUnderflow
);
286 TRACE_INTR(RxErrIntr
);
288 TRACE_INTR(IntrTxStopped
);
289 TRACE_INTR(IntrTxDone
);
296 /**************************************************************************
297 w89c840_reset - Reset adapter
298 ***************************************************************************/
299 static void w89c840_reset(struct nic
*nic
)
303 /* Reset the chip to erase previous misconfiguration.
304 No hold time required! */
305 writel(0x00000001, ioaddr
+ PCIBusCfg
);
309 writel(virt_to_bus(w840private
.rx_ring
), ioaddr
+ RxRingPtr
);
310 writel(virt_to_bus(w840private
.tx_ring
), ioaddr
+ TxRingPtr
);
312 for (i
= 0; i
< ETH_ALEN
; i
++)
313 writeb(nic
->node_addr
[i
], ioaddr
+ StationAddr
+ i
);
315 /* Initialize other registers. */
316 /* Configure the PCI bus bursts and FIFO thresholds.
317 486: Set 8 longword cache alignment, 8 longword burst.
318 586: Set 16 longword cache alignment, no burst limit.
319 Cache alignment bits 15:14 Burst length 13:8
320 0000 <not allowed> 0000 align to cache 0800 8 longwords
321 4000 8 longwords 0100 1 longword 1000 16 longwords
322 8000 16 longwords 0200 2 longwords 2000 32 longwords
323 C000 32 longwords 0400 4 longwords
324 Wait the specified 50 PCI cycles after a reset by initializing
325 Tx and Rx queues and the address filter list. */
327 writel(0xE010, ioaddr
+ PCIBusCfg
);
329 writel(0, ioaddr
+ RxStartDemand
);
330 w840private
.csr6
= 0x20022002;
334 /* Do not enable the interrupts Etherboot doesn't need them */
336 writel(0x1A0F5, ioaddr + IntrStatus);
337 writel(0x1A0F5, ioaddr + IntrEnable);
339 #if defined(W89C840_DEBUG)
340 printf("winbond-840 : Done reset.\n");
345 static void handle_intr(u32 intr_stat
)
347 if ((intr_stat
& (NormalIntr
|AbnormalIntr
)) == 0) {
348 /* we are polling, do not return now */
351 /* Acknowledge all of the current interrupt sources ASAP. */
352 writel(intr_stat
& 0x001ffff, ioaddr
+ IntrStatus
);
355 if (intr_stat
& AbnormalIntr
) {
356 /* There was an abnormal interrupt */
357 printf("\n-=- Abnormal interrupt.\n");
359 #if defined(W89C840_DEBUG)
360 decode_interrupt(intr_stat
);
363 if (intr_stat
& RxNoBuf
) {
364 /* There was an interrupt */
365 printf("-=- <=> No receive buffers available.\n");
366 writel(0, ioaddr
+ RxStartDemand
);
372 /**************************************************************************
373 w89c840_poll - Wait for a frame
374 ***************************************************************************/
375 static int w89c840_poll(struct nic
*nic
, int retrieve
)
377 /* return true if there's an ethernet packet ready to read */
378 /* nic->packet should contain data on return */
379 /* nic->packetlen should contain length of data */
380 int packet_received
= 0;
382 #if defined(W89C840_DEBUG)
383 u32 intr_status
= readl(ioaddr
+ IntrStatus
);
387 /* Code from netdev_rx(dev) */
389 int entry
= w840private
.cur_rx
% RX_RING_SIZE
;
391 struct w840_rx_desc
*desc
= w840private
.rx_head_desc
;
392 s32 status
= desc
->status
;
394 if (status
& DescOwn
) {
395 /* DescOwn bit is still set, we should wait for RX to complete */
405 if ((status
& 0x38008300) != 0x0300) {
406 if ((status
& 0x38000300) != 0x0300) {
407 /* Ingore earlier buffers. */
408 if ((status
& 0xffff) != 0x7fff) {
409 printf("winbond-840 : Oversized Ethernet frame spanned "
410 "multiple buffers, entry %d status %X !\n",
411 w840private
.cur_rx
, (unsigned int) status
);
413 } else if (status
& 0x8000) {
414 /* There was a fatal error. */
415 #if defined(W89C840_DEBUG)
416 printf("winbond-840 : Receive error, Rx status %X :", status
);
417 if (status
& 0x0890) {
418 printf(" RXLEN_ERROR");
420 if (status
& 0x004C) {
421 printf(", FRAME_ERROR");
423 if (status
& 0x0002) {
424 printf(", CRC_ERROR");
429 /* Simpy do a reset now... */
436 /* Omit the four octet CRC from the length. */
437 int pkt_len
= ((status
>> 16) & 0x7ff) - 4;
439 #if defined(W89C840_DEBUG)
440 printf(" netdev_rx() normal Rx pkt ring %d length %d status %X\n", entry
, pkt_len
, status
);
443 nic
->packetlen
= pkt_len
;
445 /* Check if the packet is long enough to accept without copying
446 to a minimally-sized skbuff. */
448 memcpy(nic
->packet
, le32desc_to_virt(w840private
.rx_ring
[entry
].buffer1
), pkt_len
);
451 /* Release buffer to NIC */
452 w840private
.rx_ring
[entry
].status
= DescOwn
;
454 #if defined(W89C840_DEBUG)
455 /* You will want this info for the initial debug. */
456 printf(" Rx data %hhX:%hhX:%hhX:%hhX:%hhX:"
457 "%hhX %hhX:%hhX:%hhX:%hhX:%hhX:%hhX %hhX%hhX "
458 "%hhX.%hhX.%hhX.%hhX.\n",
459 nic
->packet
[0], nic
->packet
[1], nic
->packet
[2], nic
->packet
[3],
460 nic
->packet
[4], nic
->packet
[5], nic
->packet
[6], nic
->packet
[7],
461 nic
->packet
[8], nic
->packet
[9], nic
->packet
[10],
462 nic
->packet
[11], nic
->packet
[12], nic
->packet
[13],
463 nic
->packet
[14], nic
->packet
[15], nic
->packet
[16],
469 entry
= (++w840private
.cur_rx
) % RX_RING_SIZE
;
470 w840private
.rx_head_desc
= &w840private
.rx_ring
[entry
];
473 return packet_received
;
476 /**************************************************************************
477 w89c840_transmit - Transmit a frame
478 ***************************************************************************/
480 static void w89c840_transmit(
482 const char *d
, /* Destination */
483 unsigned int t
, /* Type */
484 unsigned int s
, /* size */
485 const char *p
) /* Packet */
487 /* send the packet to destination */
491 /* Caution: the write order is important here, set the field
492 with the "ownership" bits last. */
494 /* Fill in our transmit buffer */
495 entry
= w840private
.cur_tx
% TX_RING_SIZE
;
497 memcpy (w89c840_buf
.tx_packet
, d
, ETH_ALEN
); /* dst */
498 memcpy (w89c840_buf
.tx_packet
+ ETH_ALEN
, nic
->node_addr
, ETH_ALEN
);/*src*/
500 *((char *) w89c840_buf
.tx_packet
+ 12) = t
>> 8; /* type */
501 *((char *) w89c840_buf
.tx_packet
+ 13) = t
;
503 memcpy (w89c840_buf
.tx_packet
+ ETH_HLEN
, p
, s
);
507 *((char *) w89c840_buf
.tx_packet
+ ETH_HLEN
+ (s
++)) = 0;
509 w840private
.tx_ring
[entry
].buffer1
510 = virt_to_le32desc(w89c840_buf
.tx_packet
);
512 w840private
.tx_ring
[entry
].length
= (DescWholePkt
| (u32
) s
);
513 if (entry
>= TX_RING_SIZE
-1) /* Wrap ring */
514 w840private
.tx_ring
[entry
].length
|= (DescIntr
| DescEndRing
);
515 w840private
.tx_ring
[entry
].status
= (DescOwn
);
516 w840private
.cur_tx
++;
518 w840private
.tx_q_bytes
= (u16
) s
;
519 writel(0, ioaddr
+ TxStartDemand
);
521 /* Work around horrible bug in the chip by marking the queue as full
522 when we do not have FIFO room for a maximum sized packet. */
524 if ((w840private
.drv_flags
& HasBrokenTx
) && w840private
.tx_q_bytes
> TX_BUG_FIFO_LIMIT
) {
525 /* Actually this is left to help finding error tails later in debugging...
526 * See Linux kernel driver in winbond-840.c for details.
528 w840private
.tx_full
= 1;
531 #if defined(W89C840_DEBUG)
532 printf("winbond-840 : Transmit frame # %d size %d queued in slot %d.\n", w840private
.cur_tx
, s
, entry
);
535 /* Now wait for TX to complete. */
536 transmit_status
= w840private
.tx_ring
[entry
].status
;
538 load_timer2(TX_TIMEOUT
);
541 #if defined W89C840_DEBUG
546 #if defined(W89C840_DEBUG)
547 decode_interrupt(intr_stat
);
550 while ( (transmit_status
& DescOwn
) && timer2_running()) {
552 transmit_status
= w840private
.tx_ring
[entry
].status
;
559 if ((transmit_status
& DescOwn
) == 0) {
561 #if defined(W89C840_DEBUG)
562 printf("winbond-840 : transmission complete after wait loop iterations, status %X\n",
563 w840private
.tx_ring
[entry
].status
);
569 /* Transmit timed out... */
571 printf("winbond-840 : transmission TIMEOUT : status %X\n",
572 (unsigned int) w840private
.tx_ring
[entry
].status
);
577 /**************************************************************************
578 w89c840_disable - Turn off ethernet interface
579 ***************************************************************************/
580 static void w89c840_disable ( struct nic
*nic
) {
584 /* Don't know what to do to disable the board. Is this needed at all? */
585 /* Yes, a live NIC can corrupt the loaded memory later [Ken] */
586 /* Stop the chip's Tx and Rx processes. */
587 writel(w840private
.csr6
&= ~0x20FA, ioaddr
+ NetworkConfig
);
590 /**************************************************************************
591 w89c840_irq - Enable, Disable, or Force interrupts
592 ***************************************************************************/
593 static void w89c840_irq(struct nic
*nic __unused
, irq_action_t action __unused
)
605 static struct nic_operations w89c840_operations
= {
606 .connect
= dummy_connect
,
607 .poll
= w89c840_poll
,
608 .transmit
= w89c840_transmit
,
613 static struct pci_device_id w89c840_nics
[] = {
614 PCI_ROM(0x1050, 0x0840, "winbond840", "Winbond W89C840F"),
615 PCI_ROM(0x11f6, 0x2011, "compexrl100atx", "Compex RL100ATX"),
618 PCI_DRIVER ( w89c840_driver
, w89c840_nics
, PCI_NO_CLASS
);
620 /**************************************************************************
621 w89c840_probe - Look for an adapter, this routine's visible to the outside
622 ***************************************************************************/
623 static int w89c840_probe ( struct nic
*nic
, struct pci_device
*p
) {
628 unsigned short value
;
633 nic
->ioaddr
= p
->ioaddr
;
636 #if defined(W89C840_DEBUG)
637 printf("winbond-840: PCI bus %hhX device function %hhX: I/O address: %hX\n", p
->bus
, p
->devfn
, ioaddr
);
640 ioaddr
= ioaddr
& ~3; /* Mask the bit that says "this is an io addr" */
642 #define PCI_DEVICE_ID_WINBOND2_89C840 0x0840
643 #define PCI_DEVICE_ID_COMPEX_RL100ATX 0x2011
645 /* From Matt Hortman <mbhortman@acpthinclient.com> */
646 if (p
->vendor
== PCI_VENDOR_ID_WINBOND2
647 && p
->device
== PCI_DEVICE_ID_WINBOND2_89C840
) {
649 /* detected "Winbond W89c840 Fast Ethernet PCI NIC" */
651 } else if ( p
->vendor
== PCI_VENDOR_ID_COMPEX
652 && p
->device
== PCI_DEVICE_ID_COMPEX_RL100ATX
) {
654 /* detected "Compex RL100ATX Fast Ethernet PCI NIC" */
657 /* Gee, guess what? They missed again. */
658 printf("device ID : %X - is not a Compex RL100ATX NIC.\n",
663 printf(" %s\n", w89c840_version
);
665 adjust_pci_device(p
);
667 /* Ok. Got one. Read the eeprom. */
668 for (j
= 0, i
= 0; i
< 0x40; i
++) {
669 value
= eeprom_read(ioaddr
, i
);
674 for (i
=0;i
<ETH_ALEN
;i
++) {
675 nic
->node_addr
[i
] = (eeprom
[i
/2] >> (8*(i
&1))) & 0xff;
678 DBG ( "Ethernet addr: %s\n", eth_ntoa ( nic
->node_addr
) );
680 #if defined(W89C840_DEBUG)
681 printf("winbond-840: EEPROM checksum %hX, got eeprom", sum
);
684 /* Reset the chip to erase previous misconfiguration.
685 No hold time required! */
686 writel(0x00000001, ioaddr
+ PCIBusCfg
);
688 if (driver_flags
& CanHaveMII
) {
689 int phy
, phy_idx
= 0;
690 for (phy
= 1; phy
< 32 && phy_idx
< 4; phy
++) {
691 int mii_status
= mdio_read(ioaddr
, phy
, 1);
692 if (mii_status
!= 0xffff && mii_status
!= 0x0000) {
693 w840private
.phys
[phy_idx
++] = phy
;
694 w840private
.advertising
= mdio_read(ioaddr
, phy
, 4);
696 #if defined(W89C840_DEBUG)
697 printf("winbond-840 : MII PHY found at address %d, status "
698 "%X advertising %hX.\n", phy
, mii_status
, w840private
.advertising
);
704 w840private
.mii_cnt
= phy_idx
;
707 printf("winbond-840 : MII PHY not found -- this device may not operate correctly.\n");
711 /* point to NIC specific routines */
712 nic
->nic_op
= &w89c840_operations
;
719 /* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. These are
720 often serial bit streams generated by the host processor.
721 The example below is for the common 93c46 EEPROM, 64 16 bit words. */
723 /* Delay between EEPROM clock transitions.
724 No extra delay is needed with 33Mhz PCI, but future 66Mhz access may need
725 a delay. Note that pre-2.0.34 kernels had a cache-alignment bug that
726 made udelay() unreliable.
727 The old method of using an ISA access as a delay, __SLOW_DOWN_IO__, is
730 #define eeprom_delay(ee_addr) readl(ee_addr)
732 enum EEPROM_Ctrl_Bits
{
733 EE_ShiftClk
=0x02, EE_Write0
=0x801, EE_Write1
=0x805,
734 EE_ChipSelect
=0x801, EE_DataIn
=0x08,
737 /* The EEPROM commands include the alway-set leading bit. */
739 EE_WriteCmd
=(5 << 6), EE_ReadCmd
=(6 << 6), EE_EraseCmd
=(7 << 6),
742 static int eeprom_read(long addr
, int location
)
746 int ee_addr
= addr
+ EECtrl
;
747 int read_cmd
= location
| EE_ReadCmd
;
748 writel(EE_ChipSelect
, ee_addr
);
750 /* Shift the read command bits out. */
751 for (i
= 10; i
>= 0; i
--) {
752 short dataval
= (read_cmd
& (1 << i
)) ? EE_Write1
: EE_Write0
;
753 writel(dataval
, ee_addr
);
754 eeprom_delay(ee_addr
);
755 writel(dataval
| EE_ShiftClk
, ee_addr
);
756 eeprom_delay(ee_addr
);
758 writel(EE_ChipSelect
, ee_addr
);
760 for (i
= 16; i
> 0; i
--) {
761 writel(EE_ChipSelect
| EE_ShiftClk
, ee_addr
);
762 eeprom_delay(ee_addr
);
763 retval
= (retval
<< 1) | ((readl(ee_addr
) & EE_DataIn
) ? 1 : 0);
764 writel(EE_ChipSelect
, ee_addr
);
765 eeprom_delay(ee_addr
);
768 /* Terminate the EEPROM access. */
773 /* MII transceiver control section.
774 Read and write the MII registers using software-generated serial
775 MDIO protocol. See the MII specifications or DP83840A data sheet
778 The maximum data clock rate is 2.5 Mhz. The minimum timing is usually
779 met by back-to-back 33Mhz PCI cycles. */
780 #define mdio_delay(mdio_addr) readl(mdio_addr)
782 /* Set iff a MII transceiver on any interface requires mdio preamble.
783 This only set with older tranceivers, so the extra
784 code size of a per-interface flag is not worthwhile. */
785 static char mii_preamble_required
= 1;
787 #define MDIO_WRITE0 (MDIO_EnbOutput)
788 #define MDIO_WRITE1 (MDIO_DataOut | MDIO_EnbOutput)
790 /* Generate the preamble required for initial synchronization and
791 a few older transceivers. */
792 static void mdio_sync(long mdio_addr
)
796 /* Establish sync by sending at least 32 logic ones. */
797 while (--bits
>= 0) {
798 writel(MDIO_WRITE1
, mdio_addr
);
799 mdio_delay(mdio_addr
);
800 writel(MDIO_WRITE1
| MDIO_ShiftClk
, mdio_addr
);
801 mdio_delay(mdio_addr
);
805 static int mdio_read(int base_address
, int phy_id
, int location
)
807 long mdio_addr
= base_address
+ MIICtrl
;
808 int mii_cmd
= (0xf6 << 10) | (phy_id
<< 5) | location
;
811 if (mii_preamble_required
)
812 mdio_sync(mdio_addr
);
814 /* Shift the read command bits out. */
815 for (i
= 15; i
>= 0; i
--) {
816 int dataval
= (mii_cmd
& (1 << i
)) ? MDIO_WRITE1
: MDIO_WRITE0
;
818 writel(dataval
, mdio_addr
);
819 mdio_delay(mdio_addr
);
820 writel(dataval
| MDIO_ShiftClk
, mdio_addr
);
821 mdio_delay(mdio_addr
);
823 /* Read the two transition, 16 data, and wire-idle bits. */
824 for (i
= 20; i
> 0; i
--) {
825 writel(MDIO_EnbIn
, mdio_addr
);
826 mdio_delay(mdio_addr
);
827 retval
= (retval
<< 1) | ((readl(mdio_addr
) & MDIO_DataIn
) ? 1 : 0);
828 writel(MDIO_EnbIn
| MDIO_ShiftClk
, mdio_addr
);
829 mdio_delay(mdio_addr
);
831 return (retval
>>1) & 0xffff;
835 static void mdio_write(int base_address
, int phy_id
, int location
, int value
)
837 long mdio_addr
= base_address
+ MIICtrl
;
838 int mii_cmd
= (0x5002 << 16) | (phy_id
<< 23) | (location
<<18) | value
;
841 if (location
== 4 && phy_id
== w840private
.phys
[0])
842 w840private
.advertising
= value
;
844 if (mii_preamble_required
)
845 mdio_sync(mdio_addr
);
847 /* Shift the command bits out. */
848 for (i
= 31; i
>= 0; i
--) {
849 int dataval
= (mii_cmd
& (1 << i
)) ? MDIO_WRITE1
: MDIO_WRITE0
;
851 writel(dataval
, mdio_addr
);
852 mdio_delay(mdio_addr
);
853 writel(dataval
| MDIO_ShiftClk
, mdio_addr
);
854 mdio_delay(mdio_addr
);
856 /* Clear out extra bits. */
857 for (i
= 2; i
> 0; i
--) {
858 writel(MDIO_EnbIn
, mdio_addr
);
859 mdio_delay(mdio_addr
);
860 writel(MDIO_EnbIn
| MDIO_ShiftClk
, mdio_addr
);
861 mdio_delay(mdio_addr
);
867 static void check_duplex(void)
869 int mii_reg5
= mdio_read(ioaddr
, w840private
.phys
[0], 5);
870 int negotiated
= mii_reg5
& w840private
.advertising
;
873 if (w840private
.duplex_lock
|| mii_reg5
== 0xffff)
876 duplex
= (negotiated
& 0x0100) || (negotiated
& 0x01C0) == 0x0040;
877 if (w840private
.full_duplex
!= duplex
) {
878 w840private
.full_duplex
= duplex
;
880 #if defined(W89C840_DEBUG)
881 printf("winbond-840 : Setting %s-duplex based on MII # %d negotiated capability %X\n",
882 duplex
? "full" : "half", w840private
.phys
[0], negotiated
);
885 w840private
.csr6
&= ~0x200;
886 w840private
.csr6
|= duplex
? 0x200 : 0;
890 static void set_rx_mode(void)
892 u32 mc_filter
[2]; /* Multicast hash filter */
895 /* Accept all multicasts from now on. */
896 memset(mc_filter
, 0xff, sizeof(mc_filter
));
899 * works OK with multicast enabled.
902 rx_mode
= AcceptBroadcast
| AcceptMyPhys
| AcceptMulticast
;
904 writel(mc_filter
[0], ioaddr
+ MulticastFilter0
);
905 writel(mc_filter
[1], ioaddr
+ MulticastFilter1
);
906 w840private
.csr6
&= ~0x00F8;
907 w840private
.csr6
|= rx_mode
;
908 writel(w840private
.csr6
, ioaddr
+ NetworkConfig
);
910 #if defined(W89C840_DEBUG)
911 printf("winbond-840 : Done setting RX mode.\n");
915 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
916 static void init_ring(void)
921 w840private
.tx_full
= 0;
922 w840private
.tx_q_bytes
= w840private
.cur_rx
= w840private
.cur_tx
= 0;
923 w840private
.dirty_rx
= w840private
.dirty_tx
= 0;
925 w840private
.rx_buf_sz
= PKT_BUF_SZ
;
926 w840private
.rx_head_desc
= &w840private
.rx_ring
[0];
928 /* Initial all Rx descriptors. Fill in the Rx buffers. */
930 p
= &w89c840_buf
.rx_packet
[0];
932 for (i
= 0; i
< RX_RING_SIZE
; i
++) {
933 w840private
.rx_ring
[i
].length
= w840private
.rx_buf_sz
;
934 w840private
.rx_ring
[i
].status
= 0;
935 w840private
.rx_ring
[i
].next_desc
= virt_to_le32desc(&w840private
.rx_ring
[i
+1]);
937 w840private
.rx_ring
[i
].buffer1
= virt_to_le32desc(p
+ (PKT_BUF_SZ
* i
));
938 w840private
.rx_ring
[i
].status
= DescOwn
| DescIntr
;
941 /* Mark the last entry as wrapping the ring. */
942 w840private
.rx_ring
[i
-1].length
|= DescEndRing
;
943 w840private
.rx_ring
[i
-1].next_desc
= virt_to_le32desc(&w840private
.rx_ring
[0]);
945 w840private
.dirty_rx
= (unsigned int)(i
- RX_RING_SIZE
);
947 for (i
= 0; i
< TX_RING_SIZE
; i
++) {
948 w840private
.tx_ring
[i
].status
= 0;
954 DRIVER ( "W89C840F", nic_driver
, pci_driver
, w89c840_driver
,
955 w89c840_probe
, w89c840_disable
);