iPXE
w89c840.c
Go to the documentation of this file.
1/*
2 * Etherboot - BOOTP/TFTP Bootstrap Program
3 *
4 * w89c840.c -- This file implements the winbond-840 driver for etherboot.
5 *
6 */
7
8/*
9 * Adapted by Igor V. Kovalenko
10 * -- <garrison@mail.ru>
11 * OR
12 * -- <iko@crec.mipt.ru>
13 * Initial adaptaion stage, including testing, completed 23 August 2000.
14 */
15
16/*
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.
21 *
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.
26 *
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., 51 Franklin Street, Fifth Floor, Boston, MA
30 * 02110-1301, USA.
31 */
32
33FILE_LICENCE ( GPL2_OR_LATER );
34
35/*
36 * date version by what
37 * Written: Aug 20 2000 V0.10 iko Initial revision.
38 * changes: Aug 22 2000 V0.90 iko Works!
39 * Aug 23 2000 V0.91 iko Cleanup, posted to etherboot
40 * maintainer.
41 * Aug 26 2000 V0.92 iko Fixed Rx ring handling.
42 * First Linux Kernel (TM)
43 * successfully loaded using
44 * this driver.
45 * Jan 07 2001 V0.93 iko Transmitter timeouts are handled
46 * using timer2 routines. Proposed
47 * by Ken Yap to eliminate CPU speed
48 * dependency.
49 * Dec 12 2003 V0.94 timlegge Fixed issues in 5.2, removed
50 * interrupt usage, enabled
51 * multicast support
52 *
53 * This is the etherboot driver for cards based on Winbond W89c840F chip.
54 *
55 * It was written from skeleton source, with Donald Becker's winbond-840.c
56 * kernel driver as a guideline. Mostly the w89c840 related definitions
57 * and the lower level routines have been cut-and-pasted into this source.
58 *
59 * Frankly speaking, about 90% of the code was obtained using cut'n'paste
60 * sequence :) while the remainder appeared while brainstorming
61 * Linux Kernel 2.4.0-testX source code. Thanks, Donald and Linus!
62 *
63 * There was a demand for using this card in a rather large
64 * remote boot environment at MSKP OVTI Lab of
65 * Moscow Institute for Physics and Technology (MIPT) -- http://www.mipt.ru/
66 * so you may count that for motivation.
67 *
68 */
69
70/*
71 * If you want to see debugging output then define W89C840_DEBUG
72 */
73
74/*
75#define W89C840_DEBUG
76*/
77
78/*
79 * Keep using IO_OPS for Etherboot driver!
80 */
81#define USE_IO_OPS
82
83#include "etherboot.h"
84#include "nic.h"
85#include <ipxe/pci.h>
86#include <ipxe/ethernet.h>
87
88static const char *w89c840_version = "driver Version 0.94 - December 12, 2003";
89
90/* Linux support functions */
91#define virt_to_le32desc(addr) virt_to_bus(addr)
92#define le32desc_to_virt(addr) bus_to_virt(addr)
93
94/*
95#define cpu_to_le32(val) (val)
96#define le32_to_cpu(val) (val)
97*/
98
99/* Operational parameters that are set at compile time. */
100
101/* Keep the ring sizes a power of two for compile efficiency.
102 The compiler will convert <unsigned>'%'<2^N> into a bit mask.
103 Making the Tx ring too large decreases the effectiveness of channel
104 bonding and packet priority.
105 There are no ill effects from too-large receive rings. */
106#define TX_RING_SIZE 2
107#define RX_RING_SIZE 2
108
109/* The presumed FIFO size for working around the Tx-FIFO-overflow bug.
110 To avoid overflowing we don't queue again until we have room for a
111 full-size packet.
112 */
113#define TX_FIFO_SIZE (2048)
114#define TX_BUG_FIFO_LIMIT (TX_FIFO_SIZE-1514-16)
115
116/* Operational parameters that usually are not changed. */
117/* Time in jiffies before concluding the transmitter is hung. */
118#define TX_TIMEOUT (10*1000)
119
120#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
121
122/*
123 * Used to be this much CPU loops on Celeron@400 (?),
124 * now using real timer and TX_TIMEOUT!
125 * #define TX_LOOP_COUNT 10000000
126 */
127
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".
132#endif
133
135
136#ifdef USE_IO_OPS
137#define W840_FLAGS (PCI_USES_IO | PCI_ADDR0 | PCI_USES_MASTER)
138#else
139#define W840_FLAGS (PCI_USES_MEM | PCI_ADDR1 | PCI_USES_MASTER)
140#endif
141
143
144/* This driver was written to use PCI memory space, however some x86 systems
145 work only with I/O space accesses. Pass -DUSE_IO_OPS to use PCI I/O space
146 accesses instead of memory space. */
147
148#ifdef USE_IO_OPS
149#undef readb
150#undef readw
151#undef readl
152#undef writeb
153#undef writew
154#undef writel
155#define readb inb
156#define readw inw
157#define readl inl
158#define writeb outb
159#define writew outw
160#define writel outl
161#endif
162
163/* Offsets to the Command and Status Registers, "CSRs".
164 While similar to the Tulip, these registers are longword aligned.
165 Note: It's not useful to define symbolic names for every register bit in
166 the device. The name can only partially document the semantics and make
167 the driver longer and more difficult to read.
168*/
178
179/* Bits in the interrupt status/enable registers. */
180/* The bits in the Intr Status/Enable registers, mostly interrupt sources. */
182 NormalIntr=0x10000, AbnormalIntr=0x8000,
183 IntrPCIErr=0x2000, TimerInt=0x800,
184 IntrRxDied=0x100, RxNoBuf=0x80, IntrRxDone=0x40,
187};
188
189/* Bits in the NetworkConfig register. */
195
197 MDIO_ShiftClk=0x10000, MDIO_DataIn=0x80000, MDIO_DataOut=0x20000,
198 MDIO_EnbOutput=0x40000, MDIO_EnbIn = 0x00000,
199};
200
201/* The Tulip Rx and Tx buffer descriptors. */
208
212 u32 buffer1, buffer2; /* We use only buffer 1. */
213};
214
215/* Bits in network_desc.status */
217 DescOwn=0x80000000, DescEndRing=0x02000000, DescUseLink=0x01000000,
218 DescWholePkt=0x60000000, DescStartPkt=0x20000000, DescEndPkt=0x40000000,
219 DescIntr=0x80000000,
220};
221#define PRIV_ALIGN 15 /* Required alignment mask */
222#define PRIV_ALIGN_BYTES 32
223
224static struct winbond_private
225{
226 /* Descriptor rings first for alignment. */
229 struct net_device *next_module; /* Link for devices of this type. */
230 void *priv_addr; /* Unaligned address for kfree */
231 const char *product_name;
232 /* Frequently used values: keep some adjacent for cache effect. */
235 int csr6;
237 unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */
238 unsigned int rx_buf_sz; /* Based on MTU+slack. */
239 unsigned int cur_tx, dirty_tx;
241 unsigned int tx_full:1; /* The Tx queue is full. */
242 /* These values are keep track of the transceiver/media in use. */
243 unsigned int full_duplex:1; /* Full-duplex operation requested. */
244 unsigned int duplex_lock:1;
245 unsigned int medialock:1; /* Do not sense media. */
246 unsigned int default_port:4; /* Last dev->if_port value. */
247 /* MII transceiver section. */
248 int mii_cnt; /* MII device addresses. */
249 u16 advertising; /* NWay media advertisement */
250 unsigned char phys[4]; /* MII device addresses. */
252
253/* NIC specific static variables go here */
254
255static int ioaddr;
256static unsigned short eeprom [0x40];
261#define w89c840_buf NIC_FAKE_BSS ( struct w89c840_bss )
262
263static int eeprom_read(long ioaddr, int location);
264static int mdio_read(int base_address, int phy_id, int location);
265#if 0
266static void mdio_write(int base_address, int phy_id, int location, int value);
267#endif
268
269static void check_duplex(void);
270static void set_rx_mode(void);
271static void init_ring(void);
272
273#if defined(W89C840_DEBUG)
274static void decode_interrupt(u32 intr_status)
275{
276 printf("Interrupt status: ");
277
278#define TRACE_INTR(_intr_) \
279 if (intr_status & (_intr_)) { printf (" " #_intr_); }
280
281 TRACE_INTR(NormalIntr);
282 TRACE_INTR(AbnormalIntr);
283 TRACE_INTR(IntrPCIErr);
284 TRACE_INTR(TimerInt);
285 TRACE_INTR(IntrRxDied);
286 TRACE_INTR(RxNoBuf);
287 TRACE_INTR(IntrRxDone);
288 TRACE_INTR(TxFIFOUnderflow);
289 TRACE_INTR(RxErrIntr);
290 TRACE_INTR(TxIdle);
291 TRACE_INTR(IntrTxStopped);
292 TRACE_INTR(IntrTxDone);
293
294 printf("\n");
295 /*sleep(1);*/
296}
297#endif
298
299/**************************************************************************
300w89c840_reset - Reset adapter
301***************************************************************************/
302static void w89c840_reset(struct nic *nic)
303{
304 int i;
305
306 /* Reset the chip to erase previous misconfiguration.
307 No hold time required! */
308 writel(0x00000001, ioaddr + PCIBusCfg);
309
310 init_ring();
311
314
315 for (i = 0; i < ETH_ALEN; i++)
317
318 /* Initialize other registers. */
319 /* Configure the PCI bus bursts and FIFO thresholds.
320 486: Set 8 longword cache alignment, 8 longword burst.
321 586: Set 16 longword cache alignment, no burst limit.
322 Cache alignment bits 15:14 Burst length 13:8
323 0000 <not allowed> 0000 align to cache 0800 8 longwords
324 4000 8 longwords 0100 1 longword 1000 16 longwords
325 8000 16 longwords 0200 2 longwords 2000 32 longwords
326 C000 32 longwords 0400 4 longwords
327 Wait the specified 50 PCI cycles after a reset by initializing
328 Tx and Rx queues and the address filter list. */
329
330 writel(0xE010, ioaddr + PCIBusCfg);
331
333 w840private.csr6 = 0x20022002;
334 check_duplex();
335 set_rx_mode();
336
337 /* Do not enable the interrupts Etherboot doesn't need them */
338/*
339 writel(0x1A0F5, ioaddr + IntrStatus);
340 writel(0x1A0F5, ioaddr + IntrEnable);
341*/
342#if defined(W89C840_DEBUG)
343 printf("winbond-840 : Done reset.\n");
344#endif
345}
346
347#if 0
348static void handle_intr(u32 intr_stat)
349{
350 if ((intr_stat & (NormalIntr|AbnormalIntr)) == 0) {
351 /* we are polling, do not return now */
352 /*return 0;*/
353 } else {
354 /* Acknowledge all of the current interrupt sources ASAP. */
355 writel(intr_stat & 0x001ffff, ioaddr + IntrStatus);
356 }
357
358 if (intr_stat & AbnormalIntr) {
359 /* There was an abnormal interrupt */
360 printf("\n-=- Abnormal interrupt.\n");
361
362#if defined(W89C840_DEBUG)
363 decode_interrupt(intr_stat);
364#endif
365
366 if (intr_stat & RxNoBuf) {
367 /* There was an interrupt */
368 printf("-=- <=> No receive buffers available.\n");
370 }
371 }
372}
373#endif
374
375/**************************************************************************
376w89c840_poll - Wait for a frame
377***************************************************************************/
378static int w89c840_poll(struct nic *nic, int retrieve)
379{
380 /* return true if there's an ethernet packet ready to read */
381 /* nic->packet should contain data on return */
382 /* nic->packetlen should contain length of data */
383 int packet_received = 0;
384
385#if defined(W89C840_DEBUG)
386 u32 intr_status = readl(ioaddr + IntrStatus);
387#endif
388
389 do {
390 /* Code from netdev_rx(dev) */
391
392 int entry = w840private.cur_rx % RX_RING_SIZE;
393
394 struct w840_rx_desc *desc = w840private.rx_head_desc;
395 s32 status = desc->status;
396
397 if (status & DescOwn) {
398 /* DescOwn bit is still set, we should wait for RX to complete */
399 packet_received = 0;
400 break;
401 }
402
403 if ( !retrieve ) {
404 packet_received = 1;
405 break;
406 }
407
408 if ((status & 0x38008300) != 0x0300) {
409 if ((status & 0x38000300) != 0x0300) {
410 /* Ingore earlier buffers. */
411 if ((status & 0xffff) != 0x7fff) {
412 printf("winbond-840 : Oversized Ethernet frame spanned "
413 "multiple buffers, entry %d status %X !\n",
414 w840private.cur_rx, (unsigned int) status);
415 }
416 } else if (status & 0x8000) {
417 /* There was a fatal error. */
418#if defined(W89C840_DEBUG)
419 printf("winbond-840 : Receive error, Rx status %X :", status);
420 if (status & 0x0890) {
421 printf(" RXLEN_ERROR");
422 }
423 if (status & 0x004C) {
424 printf(", FRAME_ERROR");
425 }
426 if (status & 0x0002) {
427 printf(", CRC_ERROR");
428 }
429 printf("\n");
430#endif
431
432 /* Simpy do a reset now... */
434
435 packet_received = 0;
436 break;
437 }
438 } else {
439 /* Omit the four octet CRC from the length. */
440 int pkt_len = ((status >> 16) & 0x7ff) - 4;
441
442#if defined(W89C840_DEBUG)
443 printf(" netdev_rx() normal Rx pkt ring %d length %d status %X\n", entry, pkt_len, status);
444#endif
445
447
448 /* Check if the packet is long enough to accept without copying
449 to a minimally-sized skbuff. */
450
451 memcpy(nic->packet, le32desc_to_virt(w840private.rx_ring[entry].buffer1), pkt_len);
452 packet_received = 1;
453
454 /* Release buffer to NIC */
455 w840private.rx_ring[entry].status = DescOwn;
456
457#if defined(W89C840_DEBUG)
458 /* You will want this info for the initial 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",
462 nic->packet[0], nic->packet[1], nic->packet[2], nic->packet[3],
463 nic->packet[4], nic->packet[5], nic->packet[6], nic->packet[7],
464 nic->packet[8], nic->packet[9], nic->packet[10],
465 nic->packet[11], nic->packet[12], nic->packet[13],
466 nic->packet[14], nic->packet[15], nic->packet[16],
467 nic->packet[17]);
468#endif
469
470 }
471
472 entry = (++w840private.cur_rx) % RX_RING_SIZE;
473 w840private.rx_head_desc = &w840private.rx_ring[entry];
474 } while (0);
475
476 return packet_received;
477}
478
479/**************************************************************************
480w89c840_transmit - Transmit a frame
481***************************************************************************/
482
484 struct nic *nic,
485 const char *d, /* Destination */
486 unsigned int t, /* Type */
487 unsigned int s, /* size */
488 const char *p) /* Packet */
489{
490 /* send the packet to destination */
491 unsigned entry;
492 int transmit_status;
493 unsigned long ct;
494
495 /* Caution: the write order is important here, set the field
496 with the "ownership" bits last. */
497
498 /* Fill in our transmit buffer */
499 entry = w840private.cur_tx % TX_RING_SIZE;
500
501 memcpy (w89c840_buf.tx_packet, d, ETH_ALEN); /* dst */
502 memcpy (w89c840_buf.tx_packet + ETH_ALEN, nic->node_addr, ETH_ALEN);/*src*/
503
504 *((char *) w89c840_buf.tx_packet + 12) = t >> 8; /* type */
505 *((char *) w89c840_buf.tx_packet + 13) = t;
506
507 memcpy (w89c840_buf.tx_packet + ETH_HLEN, p, s);
508 s += ETH_HLEN;
509
510 while (s < ETH_ZLEN)
511 *((char *) w89c840_buf.tx_packet + ETH_HLEN + (s++)) = 0;
512
513 w840private.tx_ring[entry].buffer1
514 = virt_to_le32desc(w89c840_buf.tx_packet);
515
516 w840private.tx_ring[entry].length = (DescWholePkt | (u32) s);
517 if (entry >= TX_RING_SIZE-1) /* Wrap ring */
518 w840private.tx_ring[entry].length |= (DescIntr | DescEndRing);
519 w840private.tx_ring[entry].status = (DescOwn);
520 w840private.cur_tx++;
521
522 w840private.tx_q_bytes = (u16) s;
524
525 /* Work around horrible bug in the chip by marking the queue as full
526 when we do not have FIFO room for a maximum sized packet. */
527
528 if ((w840private.drv_flags & HasBrokenTx) && w840private.tx_q_bytes > TX_BUG_FIFO_LIMIT) {
529 /* Actually this is left to help finding error tails later in debugging...
530 * See Linux kernel driver in winbond-840.c for details.
531 */
532 w840private.tx_full = 1;
533 }
534
535#if defined(W89C840_DEBUG)
536 printf("winbond-840 : Transmit frame # %d size %d queued in slot %d.\n", w840private.cur_tx, s, entry);
537#endif
538
539 /* Now wait for TX to complete. */
540 transmit_status = w840private.tx_ring[entry].status;
541
542 ct = currticks();
543 {
544#if defined W89C840_DEBUG
545 u32 intr_stat = 0;
546#endif
547 while (1) {
548
549#if defined(W89C840_DEBUG)
550 decode_interrupt(intr_stat);
551#endif
552
553 while ( (transmit_status & DescOwn) && ct + TX_TIMEOUT < currticks()) {
554
555 transmit_status = w840private.tx_ring[entry].status;
556 }
557
558 break;
559 }
560 }
561
562 if ((transmit_status & DescOwn) == 0) {
563
564#if defined(W89C840_DEBUG)
565 printf("winbond-840 : transmission complete after wait loop iterations, status %X\n",
566 w840private.tx_ring[entry].status);
567#endif
568
569 return;
570 }
571
572 /* Transmit timed out... */
573
574 printf("winbond-840 : transmission TIMEOUT : status %X\n",
575 (unsigned int) w840private.tx_ring[entry].status);
576
577 return;
578}
579
580/**************************************************************************
581w89c840_disable - Turn off ethernet interface
582***************************************************************************/
583static void w89c840_disable ( struct nic *nic, void *hwdev __unused ) {
584
586
587 /* Don't know what to do to disable the board. Is this needed at all? */
588 /* Yes, a live NIC can corrupt the loaded memory later [Ken] */
589 /* Stop the chip's Tx and Rx processes. */
590 writel(w840private.csr6 &= ~0x20FA, ioaddr + NetworkConfig);
591}
592
593/**************************************************************************
594w89c840_irq - Enable, Disable, or Force interrupts
595***************************************************************************/
596static void w89c840_irq(struct nic *nic __unused, irq_action_t action __unused)
597{
598 switch ( action ) {
599 case DISABLE :
600 break;
601 case ENABLE :
602 break;
603 case FORCE :
604 break;
605 }
606}
607
609 .connect = dummy_connect,
610 .poll = w89c840_poll,
611 .transmit = w89c840_transmit,
612 .irq = w89c840_irq,
613
614};
615
616static struct pci_device_id w89c840_nics[] = {
617PCI_ROM(0x1050, 0x0840, "winbond840", "Winbond W89C840F", 0),
618PCI_ROM(0x11f6, 0x2011, "compexrl100atx", "Compex RL100ATX", 0),
619};
620
621PCI_DRIVER ( w89c840_driver, w89c840_nics, PCI_NO_CLASS );
622
623/**************************************************************************
624w89c840_probe - Look for an adapter, this routine's visible to the outside
625***************************************************************************/
626static int w89c840_probe ( struct nic *nic, struct pci_device *p ) {
627
628
629 u16 sum = 0;
630 int i;
631 unsigned short value;
632
633 if (p->ioaddr == 0)
634 return 0;
635
636 nic->ioaddr = p->ioaddr;
637 nic->irqno = 0;
638
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);
641#endif
642
643 ioaddr = ioaddr & ~3; /* Mask the bit that says "this is an io addr" */
644
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
649
650 /* From Matt Hortman <mbhortman@acpthinclient.com> */
653
654 /* detected "Winbond W89c840 Fast Ethernet PCI NIC" */
655
656 } else if ( p->vendor == PCI_VENDOR_ID_COMPEX
658
659 /* detected "Compex RL100ATX Fast Ethernet PCI NIC" */
660
661 } else {
662 /* Gee, guess what? They missed again. */
663 printf("device ID : %X - is not a Compex RL100ATX NIC.\n",
664 p->device);
665 return 0;
666 }
667
668 printf(" %s\n", w89c840_version);
669
671
672 /* Ok. Got one. Read the eeprom. */
673 for (i = 0; i < 0x40; i++) {
675 eeprom[i] = value;
676 sum += value;
677 }
678
679 for (i=0;i<ETH_ALEN;i++) {
680 nic->node_addr[i] = (eeprom[i/2] >> (8*(i&1))) & 0xff;
681 }
682
683 DBG ( "Ethernet addr: %s\n", eth_ntoa ( nic->node_addr ) );
684
685#if defined(W89C840_DEBUG)
686 printf("winbond-840: EEPROM checksum %hX, got eeprom", sum);
687#endif
688
689 /* Reset the chip to erase previous misconfiguration.
690 No hold time required! */
691 writel(0x00000001, ioaddr + PCIBusCfg);
692
693 if (driver_flags & CanHaveMII) {
694 int phy, phy_idx = 0;
695 for (phy = 1; phy < 32 && phy_idx < 4; phy++) {
696 int mii_status = mdio_read(ioaddr, phy, 1);
697 if (mii_status != 0xffff && mii_status != 0x0000) {
698 w840private.phys[phy_idx++] = phy;
699 w840private.advertising = mdio_read(ioaddr, phy, 4);
700
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);
704#endif
705
706 }
707 }
708
709 w840private.mii_cnt = phy_idx;
710
711 if (phy_idx == 0) {
712 printf("winbond-840 : MII PHY not found -- this device may not operate correctly.\n");
713 }
714 }
715
716 /* point to NIC specific routines */
718
720
721 return 1;
722}
723
724/* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. These are
725 often serial bit streams generated by the host processor.
726 The example below is for the common 93c46 EEPROM, 64 16 bit words. */
727
728/* Delay between EEPROM clock transitions.
729 No extra delay is needed with 33Mhz PCI, but future 66Mhz access may need
730 a delay. Note that pre-2.0.34 kernels had a cache-alignment bug that
731 made udelay() unreliable.
732 The old method of using an ISA access as a delay, __SLOW_DOWN_IO__, is
733 depricated.
734*/
735#define eeprom_delay(ee_addr) readl(ee_addr)
736
741
742/* The EEPROM commands include the alway-set leading bit. */
744 EE_WriteCmd=(5 << 6), EE_ReadCmd=(6 << 6), EE_EraseCmd=(7 << 6),
745};
746
747static int eeprom_read(long addr, int location)
748{
749 int i;
750 int retval = 0;
751 int ee_addr = addr + EECtrl;
752 int read_cmd = location | EE_ReadCmd;
753 writel(EE_ChipSelect, ee_addr);
754
755 /* Shift the read command bits out. */
756 for (i = 10; i >= 0; i--) {
757 short dataval = (read_cmd & (1 << i)) ? EE_Write1 : EE_Write0;
758 writel(dataval, ee_addr);
759 eeprom_delay(ee_addr);
760 writel(dataval | EE_ShiftClk, ee_addr);
761 eeprom_delay(ee_addr);
762 }
763 writel(EE_ChipSelect, ee_addr);
764
765 for (i = 16; i > 0; i--) {
766 writel(EE_ChipSelect | EE_ShiftClk, ee_addr);
767 eeprom_delay(ee_addr);
768 retval = (retval << 1) | ((readl(ee_addr) & EE_DataIn) ? 1 : 0);
769 writel(EE_ChipSelect, ee_addr);
770 eeprom_delay(ee_addr);
771 }
772
773 /* Terminate the EEPROM access. */
774 writel(0, ee_addr);
775 return retval;
776}
777
778/* MII transceiver control section.
779 Read and write the MII registers using software-generated serial
780 MDIO protocol. See the MII specifications or DP83840A data sheet
781 for details.
782
783 The maximum data clock rate is 2.5 Mhz. The minimum timing is usually
784 met by back-to-back 33Mhz PCI cycles. */
785#define mdio_delay(mdio_addr) readl(mdio_addr)
786
787/* Set iff a MII transceiver on any interface requires mdio preamble.
788 This only set with older tranceivers, so the extra
789 code size of a per-interface flag is not worthwhile. */
790static char mii_preamble_required = 1;
791
792#define MDIO_WRITE0 (MDIO_EnbOutput)
793#define MDIO_WRITE1 (MDIO_DataOut | MDIO_EnbOutput)
794
795/* Generate the preamble required for initial synchronization and
796 a few older transceivers. */
797static void mdio_sync(long mdio_addr)
798{
799 int bits = 32;
800
801 /* Establish sync by sending at least 32 logic ones. */
802 while (--bits >= 0) {
803 writel(MDIO_WRITE1, mdio_addr);
804 mdio_delay(mdio_addr);
805 writel(MDIO_WRITE1 | MDIO_ShiftClk, mdio_addr);
806 mdio_delay(mdio_addr);
807 }
808}
809
810static int mdio_read(int base_address, int phy_id, int location)
811{
812 long mdio_addr = base_address + MIICtrl;
813 int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
814 int i, retval = 0;
815
817 mdio_sync(mdio_addr);
818
819 /* Shift the read command bits out. */
820 for (i = 15; i >= 0; i--) {
821 int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
822
823 writel(dataval, mdio_addr);
824 mdio_delay(mdio_addr);
825 writel(dataval | MDIO_ShiftClk, mdio_addr);
826 mdio_delay(mdio_addr);
827 }
828 /* Read the two transition, 16 data, and wire-idle bits. */
829 for (i = 20; i > 0; i--) {
830 writel(MDIO_EnbIn, mdio_addr);
831 mdio_delay(mdio_addr);
832 retval = (retval << 1) | ((readl(mdio_addr) & MDIO_DataIn) ? 1 : 0);
833 writel(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
834 mdio_delay(mdio_addr);
835 }
836 return (retval>>1) & 0xffff;
837}
838
839#if 0
840static void mdio_write(int base_address, int phy_id, int location, int value)
841{
842 long mdio_addr = base_address + MIICtrl;
843 int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
844 int i;
845
846 if (location == 4 && phy_id == w840private.phys[0])
847 w840private.advertising = value;
848
850 mdio_sync(mdio_addr);
851
852 /* Shift the command bits out. */
853 for (i = 31; i >= 0; i--) {
854 int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
855
856 writel(dataval, mdio_addr);
857 mdio_delay(mdio_addr);
858 writel(dataval | MDIO_ShiftClk, mdio_addr);
859 mdio_delay(mdio_addr);
860 }
861 /* Clear out extra bits. */
862 for (i = 2; i > 0; i--) {
863 writel(MDIO_EnbIn, mdio_addr);
864 mdio_delay(mdio_addr);
865 writel(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
866 mdio_delay(mdio_addr);
867 }
868 return;
869}
870#endif
871
872static void check_duplex(void)
873{
874 int mii_reg5 = mdio_read(ioaddr, w840private.phys[0], 5);
875 int negotiated = mii_reg5 & w840private.advertising;
876 int duplex;
877
878 if (w840private.duplex_lock || mii_reg5 == 0xffff)
879 return;
880
881 duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
882 if (w840private.full_duplex != duplex) {
883 w840private.full_duplex = duplex;
884
885#if defined(W89C840_DEBUG)
886 printf("winbond-840 : Setting %s-duplex based on MII # %d negotiated capability %X\n",
887 duplex ? "full" : "half", w840private.phys[0], negotiated);
888#endif
889
890 w840private.csr6 &= ~0x200;
891 w840private.csr6 |= duplex ? 0x200 : 0;
892 }
893}
894
895static void set_rx_mode(void)
896{
897 u32 mc_filter[2]; /* Multicast hash filter */
898 u32 rx_mode;
899
900 /* Accept all multicasts from now on. */
901 memset(mc_filter, 0xff, sizeof(mc_filter));
902
903/*
904 * works OK with multicast enabled.
905 */
906
908
909 writel(mc_filter[0], ioaddr + MulticastFilter0);
910 writel(mc_filter[1], ioaddr + MulticastFilter1);
911 w840private.csr6 &= ~0x00F8;
912 w840private.csr6 |= rx_mode;
914
915#if defined(W89C840_DEBUG)
916 printf("winbond-840 : Done setting RX mode.\n");
917#endif
918}
919
920/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
921static void init_ring(void)
922{
923 int i;
924 char * p;
925
926 w840private.tx_full = 0;
927 w840private.tx_q_bytes = w840private.cur_rx = w840private.cur_tx = 0;
928 w840private.dirty_rx = w840private.dirty_tx = 0;
929
930 w840private.rx_buf_sz = PKT_BUF_SZ;
931 w840private.rx_head_desc = &w840private.rx_ring[0];
932
933 /* Initial all Rx descriptors. Fill in the Rx buffers. */
934
935 p = &w89c840_buf.rx_packet[0];
936
937 for (i = 0; i < RX_RING_SIZE; i++) {
938 w840private.rx_ring[i].length = w840private.rx_buf_sz;
939 w840private.rx_ring[i].status = 0;
940 w840private.rx_ring[i].next_desc = virt_to_le32desc(&w840private.rx_ring[i+1]);
941
942 w840private.rx_ring[i].buffer1 = virt_to_le32desc(p + (PKT_BUF_SZ * i));
943 w840private.rx_ring[i].status = DescOwn | DescIntr;
944 }
945
946 /* Mark the last entry as wrapping the ring. */
947 w840private.rx_ring[i-1].length |= DescEndRing;
948 w840private.rx_ring[i-1].next_desc = virt_to_le32desc(&w840private.rx_ring[0]);
949
950 w840private.dirty_rx = (unsigned int)(i - RX_RING_SIZE);
951
952 for (i = 0; i < TX_RING_SIZE; i++) {
953 w840private.tx_ring[i].status = 0;
954 }
955 return;
956}
957
958
959DRIVER ( "W89C840F", nic_driver, pci_driver, w89c840_driver,
961
962/*
963 * Local variables:
964 * c-basic-offset: 8
965 * c-indent-level: 8
966 * tab-width: 8
967 * End:
968 */
#define PKT_BUF_SZ
Definition 3c515.c:87
#define TX_RING_SIZE
Definition 3c515.c:85
#define RX_RING_SIZE
Definition 3c515.c:86
eeprom
Definition 3c90x.h:232
#define TX_TIMEOUT
Definition amd8111e.c:57
uint16_t pkt_len
Definition aqc1xx.h:2
pseudo_bit_t value[0x00020]
Definition arbel.h:2
static volatile void * bits
Definition bitops.h:28
unsigned long retval
Definition xen.h:46
static unsigned long ioaddr
Definition davicom.c:129
#define le32desc_to_virt(addr)
Definition dmfe.c:59
uint32_t addr
Buffer address.
Definition dwmac.h:9
uint8_t status
Status.
Definition ena.h:5
struct ena_llq_option desc
Descriptor counts.
Definition ena.h:9
const char * eth_ntoa(const void *ll_addr)
Transcribe Ethernet address.
Definition ethernet.c:176
Ethernet protocol.
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:573
#define DBG(...)
Print a debugging message.
Definition compiler.h:498
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ETH_ZLEN
Definition if_ether.h:11
#define ETH_ALEN
Definition if_ether.h:9
#define ETH_HLEN
Definition if_ether.h:10
#define __attribute__(x)
Definition compiler.h:10
static __always_inline unsigned long virt_to_bus(volatile const void *addr)
Convert virtual address to a bus address.
Definition io.h:184
int32_t s32
Definition stdint.h:23
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)
Definition legacy.c:175
#define DRIVER(_name_text, _unused2, _unused3, _name, _probe, _disable, _fake_bss)
Definition nic.h:220
duplex
Definition nic.h:40
irq_action_t
Definition nic.h:34
@ FORCE
Definition nic.h:37
@ ENABLE
Definition nic.h:36
@ DISABLE
Definition nic.h:35
#define PCI_DRIVER(_name, _ids, _class)
Definition nic.h:105
static struct command_descriptor read_cmd
"read" command descriptor
Definition nvo_cmd.c:135
void adjust_pci_device(struct pci_device *pci)
Enable PCI device.
Definition pci.c:241
PCI bus.
#define PCI_ROM(_vendor, _device, _name, _description, _data)
Definition pci.h:308
@ DescOwn
Definition pcnet32.h:153
static void mdio_write(void *ioaddr, int phy_id, int reg, int val)
Definition sis190.c:93
@ IntrStatus
Definition sis190.h:77
@ AcceptMulticast
Definition sis190.h:134
@ AcceptRunt
Definition sis190.h:132
@ AcceptAllPhys
Definition sis190.h:136
@ AcceptMyPhys
Definition sis190.h:135
@ AcceptErr
Definition sis190.h:131
@ AcceptBroadcast
Definition sis190.h:133
A network device.
Definition netdevice.h:353
Definition nic.h:49
unsigned char * packet
Definition nic.h:53
unsigned char * node_addr
Definition nic.h:52
unsigned int packetlen
Definition nic.h:54
unsigned char irqno
Definition nic.h:56
unsigned int ioaddr
Definition nic.h:55
struct nic_operations * nic_op
Definition nic.h:50
A PCI device ID list entry.
Definition pci.h:175
A PCI device.
Definition pci.h:211
unsigned long ioaddr
I/O address.
Definition pci.h:226
uint16_t vendor
Vendor ID.
Definition pci.h:228
uint16_t device
Device ID.
Definition pci.h:230
A PCI driver.
Definition pci.h:252
u32 next_desc
Definition w89c840.c:206
char tx_packet[PKT_BUF_SZ *TX_RING_SIZE]
Definition w89c840.c:259
char rx_packet[PKT_BUF_SZ *RX_RING_SIZE]
Definition w89c840.c:258
void * priv_addr
Definition w89c840.c:230
unsigned int duplex_lock
Definition w89c840.c:244
struct net_device * next_module
Definition w89c840.c:229
const char * product_name
Definition w89c840.c:231
unsigned int medialock
Definition w89c840.c:245
unsigned int cur_rx
Definition w89c840.c:237
unsigned int rx_buf_sz
Definition w89c840.c:238
struct w840_rx_desc rx_ring[RX_RING_SIZE]
Definition w89c840.c:227
unsigned int default_port
Definition w89c840.c:246
unsigned int full_duplex
Definition w89c840.c:243
unsigned int cur_tx
Definition w89c840.c:239
unsigned int dirty_tx
Definition w89c840.c:239
unsigned char phys[4]
Definition w89c840.c:250
unsigned int dirty_rx
Definition w89c840.c:237
struct w840_rx_desc * rx_head_desc
Definition w89c840.c:236
struct pci_dev * pci_dev
Definition w89c840.c:234
unsigned int tx_full
Definition w89c840.c:241
struct w840_tx_desc tx_ring[TX_RING_SIZE]
Definition w89c840.c:228
chip_capability_flags
Definition sundance.c:254
@ CanHaveMII
Definition sundance.c:254
desc_status_bits
Definition sundance.c:215
@ DescEndRing
Definition sundance.c:218
#define MDIO_WRITE0
Definition sundance.c:785
mii_reg_bits
Definition sundance.c:780
@ MDIO_EnbOutput
Definition sundance.c:781
@ MDIO_ShiftClk
Definition sundance.c:781
#define MDIO_EnbIn
Definition sundance.c:784
intr_status_bits
Definition sundance.c:178
@ IntrTxDone
Definition sundance.c:180
@ IntrRxDone
Definition sundance.c:180
@ IntrPCIErr
Definition sundance.c:179
@ IntrEnable
Definition sundance.c:135
@ MIICtrl
Definition sundance.c:142
@ MulticastFilter0
Definition sundance.c:143
@ MulticastFilter1
Definition sundance.c:144
@ StationAddr
Definition sundance.c:139
@ EECtrl
Definition sundance.c:126
@ RxMissed
Definition sundance.c:156
#define MDIO_WRITE1
Definition sundance.c:786
rx_mode_bits
Definition sundance.c:187
unsigned long currticks(void)
Get current system time in ticks.
Definition timer.c:43
@ RxNoBuf
Definition tulip.c:304
@ AbnormalIntr
Definition tulip.c:303
@ TxFIFOUnderflow
Definition tulip.c:305
@ NormalIntr
Definition tulip.c:303
@ TimerInt
Definition tulip.c:302
#define u16
Definition vga.h:20
#define u32
Definition vga.h:21
int printf(const char *fmt,...)
Write a formatted string to the console.
Definition vsprintf.c:465
@ HasBrokenTx
Definition w89c840.c:134
#define readl
Definition w89c840.c:157
#define PRIV_ALIGN_BYTES
Definition w89c840.c:222
static struct nic_operations w89c840_operations
Definition w89c840.c:608
#define PKT_BUF_SZ
Definition w89c840.c:120
static char mii_preamble_required
Definition w89c840.c:790
static void check_duplex(void)
Definition w89c840.c:872
static void w89c840_disable(struct nic *nic, void *hwdev __unused)
Definition w89c840.c:583
static void init_ring(void)
Definition w89c840.c:921
static struct pci_device_id w89c840_nics[]
Definition w89c840.c:616
#define PCI_DEVICE_ID_WINBOND2_89C840
#define virt_to_le32desc(addr)
Definition w89c840.c:91
#define eeprom_delay(ee_addr)
Definition w89c840.c:735
#define TX_BUG_FIFO_LIMIT
Definition w89c840.c:114
#define writel
Definition w89c840.c:160
#define TX_RING_SIZE
Definition w89c840.c:106
static void w89c840_irq(struct nic *nic __unused, irq_action_t action __unused)
Definition w89c840.c:596
EEPROM_Ctrl_Bits
Definition w89c840.c:737
@ EE_DataIn
Definition w89c840.c:739
@ EE_ChipSelect
Definition w89c840.c:739
@ EE_Write0
Definition w89c840.c:738
@ EE_Write1
Definition w89c840.c:738
@ EE_ShiftClk
Definition w89c840.c:738
@ DescEndPkt
Definition w89c840.c:218
@ DescUseLink
Definition w89c840.c:217
@ DescIntr
Definition w89c840.c:219
@ DescWholePkt
Definition w89c840.c:218
@ DescStartPkt
Definition w89c840.c:218
#define PCI_DEVICE_ID_COMPEX_RL100ATX
static const char * w89c840_version
Definition w89c840.c:88
#define w89c840_buf
Definition w89c840.c:261
static void set_rx_mode(void)
Definition w89c840.c:895
static void mdio_sync(long mdio_addr)
Definition w89c840.c:797
#define PCI_VENDOR_ID_WINBOND2
static int mdio_read(int base_address, int phy_id, int location)
Definition w89c840.c:810
@ MDIO_DataIn
Definition w89c840.c:197
@ MDIO_DataOut
Definition w89c840.c:197
static void w89c840_transmit(struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p)
Definition w89c840.c:483
#define writeb
Definition w89c840.c:158
static int w89c840_poll(struct nic *nic, int retrieve)
Definition w89c840.c:378
static int w89c840_probe(struct nic *nic, struct pci_device *p)
Definition w89c840.c:626
static u32 driver_flags
Definition w89c840.c:142
@ IntrTxStopped
Definition w89c840.c:186
@ RxErrIntr
Definition w89c840.c:185
@ IntrRxDied
Definition w89c840.c:184
@ TxIdle
Definition w89c840.c:186
static void w89c840_reset(struct nic *nic)
Definition w89c840.c:302
#define mdio_delay(mdio_addr)
Definition w89c840.c:785
w840_offsets
Definition w89c840.c:169
@ CurRxBufAddr
Definition w89c840.c:174
@ BootRom
Definition w89c840.c:173
@ NetworkConfig
Definition w89c840.c:172
@ TxStartDemand
Definition w89c840.c:170
@ GPTimer
Definition w89c840.c:173
@ CurRxDescAddr
Definition w89c840.c:174
@ RxRingPtr
Definition w89c840.c:171
@ TxRingPtr
Definition w89c840.c:171
@ RxStartDemand
Definition w89c840.c:170
@ PCIBusCfg
Definition w89c840.c:170
@ CurTxDescAddr
Definition w89c840.c:176
@ CurTxBufAddr
Definition w89c840.c:176
static struct winbond_private w840private
EEPROM_Cmds
Definition w89c840.c:743
@ EE_ReadCmd
Definition w89c840.c:744
@ EE_WriteCmd
Definition w89c840.c:744
@ EE_EraseCmd
Definition w89c840.c:744
static int eeprom_read(long ioaddr, int location)
Definition w89c840.c:747
#define PCI_VENDOR_ID_COMPEX
#define RX_RING_SIZE
Definition w89c840.c:107