VirtualBox

source: vbox/trunk/src/VBox/Devices/PC/Etherboot-src/drivers/net/w89c840.c@ 1

Last change on this file since 1 was 1, checked in by vboxsync, 55 years ago

import

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette