]> git.ipfire.org Git - people/ms/u-boot.git/blame - drivers/natsemi.c
* Patches by Yuli Barcohen, 13 Jul 2003:
[people/ms/u-boot.git] / drivers / natsemi.c
CommitLineData
fe8c2806
WD
1/*
2 natsemi.c: A U-Boot driver for the NatSemi DP8381x series.
3 Author: Mark A. Rakes (mark_rakes@vivato.net)
4
5 Adapted from an Etherboot driver written by:
6
7 Copyright (C) 2001 Entity Cyber, Inc.
8
9 This development of this Etherboot driver was funded by
10
11 Sicom Systems: http://www.sicompos.com/
12
13 Author: Marty Connor (mdc@thinguin.org)
14 Adapted from a Linux driver which was written by Donald Becker
15
16 This software may be used and distributed according to the terms
17 of the GNU Public License (GPL), incorporated herein by reference.
18
19 Original Copyright Notice:
20
21 Written/copyright 1999-2001 by Donald Becker.
22
23 This software may be used and distributed according to the terms of
24 the GNU General Public License (GPL), incorporated herein by reference.
25 Drivers based on or derived from this code fall under the GPL and must
26 retain the authorship, copyright and license notice. This file is not
27 a complete program and may only be used when the entire operating
28 system is licensed under the GPL. License for under other terms may be
29 available. Contact the original author for details.
30
31 The original author may be reached as becker@scyld.com, or at
32 Scyld Computing Corporation
33 410 Severn Ave., Suite 210
34 Annapolis MD 21403
35
36 Support information and updates available at
37 http://www.scyld.com/network/netsemi.html
38
39 References:
40 http://www.scyld.com/expert/100mbps.html
41 http://www.scyld.com/expert/NWay.html
42 Datasheet is available from:
43 http://www.national.com/pf/DP/DP83815.html
44*/
45
46/* Revision History
47 * October 2002 mar 1.0
48 * Initial U-Boot Release. Tested with Netgear FA311 board
49 * and dp83815 chipset on custom board
50*/
51
52/* Includes */
53#include <common.h>
54#include <malloc.h>
55#include <net.h>
56#include <asm/io.h>
57#include <pci.h>
58
59#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
60 defined(CONFIG_NATSEMI)
61
62/* defines */
63#define EEPROM_SIZE 0xb /*12 16-bit chunks, or 24 bytes*/
64
65#define DSIZE 0x00000FFF
66#define ETH_ALEN 6
67#define CRC_SIZE 4
68#define TOUT_LOOP 500000
69#define TX_BUF_SIZE 1536
70#define RX_BUF_SIZE 1536
71#define NUM_RX_DESC 4 /* Number of Rx descriptor registers. */
72
73/* Offsets to the device registers.
74 Unlike software-only systems, device drivers interact with complex hardware.
75 It's not useful to define symbolic names for every register bit in the
76 device. */
77enum register_offsets {
78 ChipCmd = 0x00,
79 ChipConfig = 0x04,
80 EECtrl = 0x08,
81 IntrMask = 0x14,
82 IntrEnable = 0x18,
83 TxRingPtr = 0x20,
84 TxConfig = 0x24,
85 RxRingPtr = 0x30,
86 RxConfig = 0x34,
87 ClkRun = 0x3C,
88 RxFilterAddr = 0x48,
89 RxFilterData = 0x4C,
90 SiliconRev = 0x58,
91 PCIPM = 0x44,
92 BasicControl = 0x80,
93 BasicStatus = 0x84,
94 /* These are from the spec, around page 78... on a separate table. */
95 PGSEL = 0xCC,
96 PMDCSR = 0xE4,
97 TSTDAT = 0xFC,
98 DSPCFG = 0xF4,
99 SDCFG = 0x8C
100};
101
102/* Bit in ChipCmd. */
103enum ChipCmdBits {
104 ChipReset = 0x100,
105 RxReset = 0x20,
106 TxReset = 0x10,
107 RxOff = 0x08,
108 RxOn = 0x04,
109 TxOff = 0x02,
110 TxOn = 0x01
111};
112
113enum ChipConfigBits {
114 LinkSts = 0x80000000,
115 HundSpeed = 0x40000000,
116 FullDuplex = 0x20000000,
117 TenPolarity = 0x10000000,
118 AnegDone = 0x08000000,
119 AnegEnBothBoth = 0x0000E000,
120 AnegDis100Full = 0x0000C000,
121 AnegEn100Both = 0x0000A000,
122 AnegDis100Half = 0x00008000,
123 AnegEnBothHalf = 0x00006000,
124 AnegDis10Full = 0x00004000,
125 AnegEn10Both = 0x00002000,
126 DuplexMask = 0x00008000,
127 SpeedMask = 0x00004000,
128 AnegMask = 0x00002000,
129 AnegDis10Half = 0x00000000,
130 ExtPhy = 0x00001000,
131 PhyRst = 0x00000400,
132 PhyDis = 0x00000200,
133 BootRomDisable = 0x00000004,
134 BEMode = 0x00000001,
135};
136
137enum TxConfig_bits {
138 TxDrthMask = 0x3f,
139 TxFlthMask = 0x3f00,
140 TxMxdmaMask = 0x700000,
141 TxMxdma_512 = 0x0,
142 TxMxdma_4 = 0x100000,
143 TxMxdma_8 = 0x200000,
144 TxMxdma_16 = 0x300000,
145 TxMxdma_32 = 0x400000,
146 TxMxdma_64 = 0x500000,
147 TxMxdma_128 = 0x600000,
148 TxMxdma_256 = 0x700000,
149 TxCollRetry = 0x800000,
150 TxAutoPad = 0x10000000,
151 TxMacLoop = 0x20000000,
152 TxHeartIgn = 0x40000000,
153 TxCarrierIgn = 0x80000000
154};
155
156enum RxConfig_bits {
157 RxDrthMask = 0x3e,
158 RxMxdmaMask = 0x700000,
159 RxMxdma_512 = 0x0,
160 RxMxdma_4 = 0x100000,
161 RxMxdma_8 = 0x200000,
162 RxMxdma_16 = 0x300000,
163 RxMxdma_32 = 0x400000,
164 RxMxdma_64 = 0x500000,
165 RxMxdma_128 = 0x600000,
166 RxMxdma_256 = 0x700000,
167 RxAcceptLong = 0x8000000,
168 RxAcceptTx = 0x10000000,
169 RxAcceptRunt = 0x40000000,
170 RxAcceptErr = 0x80000000
171};
172
173/* Bits in the RxMode register. */
174enum rx_mode_bits {
175 AcceptErr = 0x20,
176 AcceptRunt = 0x10,
177 AcceptBroadcast = 0xC0000000,
178 AcceptMulticast = 0x00200000,
179 AcceptAllMulticast = 0x20000000,
180 AcceptAllPhys = 0x10000000,
181 AcceptMyPhys = 0x08000000
182};
183
184typedef struct _BufferDesc {
185 u32 link;
186 vu_long cmdsts;
187 u32 bufptr;
188 u32 software_use;
189} BufferDesc;
190
191/* Bits in network_desc.status */
192enum desc_status_bits {
193 DescOwn = 0x80000000, DescMore = 0x40000000, DescIntr = 0x20000000,
194 DescNoCRC = 0x10000000, DescPktOK = 0x08000000,
195 DescSizeMask = 0xfff,
196
197 DescTxAbort = 0x04000000, DescTxFIFO = 0x02000000,
198 DescTxCarrier = 0x01000000, DescTxDefer = 0x00800000,
199 DescTxExcDefer = 0x00400000, DescTxOOWCol = 0x00200000,
200 DescTxExcColl = 0x00100000, DescTxCollCount = 0x000f0000,
201
202 DescRxAbort = 0x04000000, DescRxOver = 0x02000000,
203 DescRxDest = 0x01800000, DescRxLong = 0x00400000,
204 DescRxRunt = 0x00200000, DescRxInvalid = 0x00100000,
205 DescRxCRC = 0x00080000, DescRxAlign = 0x00040000,
206 DescRxLoop = 0x00020000, DesRxColl = 0x00010000,
207};
208
209/* Globals */
210#ifdef NATSEMI_DEBUG
211static int natsemi_debug = 0; /* 1 verbose debugging, 0 normal */
212#endif
213static u32 SavedClkRun;
214static unsigned int cur_rx;
215static unsigned int advertising;
216static unsigned int rx_config;
217static unsigned int tx_config;
218
219/* Note: transmit and receive buffers and descriptors must be
220 longword aligned */
221static BufferDesc txd __attribute__ ((aligned(4)));
222static BufferDesc rxd[NUM_RX_DESC] __attribute__ ((aligned(4)));
223
224static unsigned char txb[TX_BUF_SIZE] __attribute__ ((aligned(4)));
225static unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE]
226 __attribute__ ((aligned(4)));
227
228/* Function Prototypes */
229#if 0
230static void write_eeprom(struct eth_device *dev, long addr, int location,
231 short value);
232#endif
233static int read_eeprom(struct eth_device *dev, long addr, int location);
234static int mdio_read(struct eth_device *dev, int phy_id, int location);
235static int natsemi_init(struct eth_device *dev, bd_t * bis);
236static void natsemi_reset(struct eth_device *dev);
237static void natsemi_init_rxfilter(struct eth_device *dev);
238static void natsemi_init_txd(struct eth_device *dev);
239static void natsemi_init_rxd(struct eth_device *dev);
240static void natsemi_set_rx_mode(struct eth_device *dev);
241static void natsemi_check_duplex(struct eth_device *dev);
242static int natsemi_send(struct eth_device *dev, volatile void *packet,
243 int length);
244static int natsemi_poll(struct eth_device *dev);
245static void natsemi_disable(struct eth_device *dev);
246
247static struct pci_device_id supported[] = {
248 {PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_83815},
249 {}
250};
251
252#define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, a)
253#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a)
254
255static inline int
256INW(struct eth_device *dev, u_long addr)
257{
258 return le16_to_cpu(*(vu_short *) (addr + dev->iobase));
259}
260
261static int
262INL(struct eth_device *dev, u_long addr)
263{
264 return le32_to_cpu(*(vu_long *) (addr + dev->iobase));
265}
266
267static inline void
268OUTW(struct eth_device *dev, int command, u_long addr)
269{
270 *(vu_short *) ((addr + dev->iobase)) = cpu_to_le16(command);
271}
272
273static inline void
274OUTL(struct eth_device *dev, int command, u_long addr)
275{
276 *(vu_long *) ((addr + dev->iobase)) = cpu_to_le32(command);
277}
278
279/*
280 * Function: natsemi_initialize
281 *
282 * Description: Retrieves the MAC address of the card, and sets up some
283 * globals required by other routines, and initializes the NIC, making it
284 * ready to send and receive packets.
285 *
286 * Side effects:
287 * leaves the natsemi initialized, and ready to recieve packets.
288 *
289 * Returns: struct eth_device *: pointer to NIC data structure
290 */
291
292int
293natsemi_initialize(bd_t * bis)
294{
295 pci_dev_t devno;
296 int card_number = 0;
297 struct eth_device *dev;
298 u32 iobase, status, chip_config;
299 int i, idx = 0;
300 int prev_eedata;
301 u32 tmp;
302
303 while (1) {
304 /* Find PCI device(s) */
305 if ((devno = pci_find_devices(supported, idx++)) < 0) {
306 break;
307 }
308
8564acf9
WD
309 pci_read_config_dword(devno, PCI_BASE_ADDRESS_0, &iobase);
310 iobase &= ~0x3; /* bit 1: unused and bit 0: I/O Space Indicator */
fe8c2806
WD
311
312 pci_write_config_dword(devno, PCI_COMMAND,
313 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
314
315 /* Check if I/O accesses and Bus Mastering are enabled. */
316 pci_read_config_dword(devno, PCI_COMMAND, &status);
317 if (!(status & PCI_COMMAND_MEMORY)) {
318 printf("Error: Can not enable MEM access.\n");
319 continue;
320 } else if (!(status & PCI_COMMAND_MASTER)) {
321 printf("Error: Can not enable Bus Mastering.\n");
322 continue;
323 }
324
325 dev = (struct eth_device *) malloc(sizeof *dev);
326
327 sprintf(dev->name, "dp83815#%d", card_number);
328 dev->iobase = bus_to_phys(iobase);
329#ifdef NATSEMI_DEBUG
330 printf("natsemi: NatSemi ns8381[56] @ %#x\n", dev->iobase);
331#endif
332 dev->priv = (void *) devno;
333 dev->init = natsemi_init;
334 dev->halt = natsemi_disable;
335 dev->send = natsemi_send;
336 dev->recv = natsemi_poll;
337
338 eth_register(dev);
339
340 card_number++;
341
342 /* Set the latency timer for value. */
343 pci_write_config_byte(devno, PCI_LATENCY_TIMER, 0x20);
344
345 udelay(10 * 1000);
346
347 /* natsemi has a non-standard PM control register
348 * in PCI config space. Some boards apparently need
349 * to be brought to D0 in this manner. */
350 pci_read_config_dword(devno, PCIPM, &tmp);
351 if (tmp & (0x03 | 0x100)) {
352 /* D0 state, disable PME assertion */
353 u32 newtmp = tmp & ~(0x03 | 0x100);
354 pci_write_config_dword(devno, PCIPM, newtmp);
355 }
356
357 printf("natsemi: EEPROM contents:\n");
358 for (i = 0; i <= EEPROM_SIZE; i++) {
359 short eedata = read_eeprom(dev, EECtrl, i);
360 printf(" %04hx", eedata);
361 }
362 printf("\n");
363
364 /* get MAC address */
365 prev_eedata = read_eeprom(dev, EECtrl, 6);
366 for (i = 0; i < 3; i++) {
367 int eedata = read_eeprom(dev, EECtrl, i + 7);
368 dev->enetaddr[i*2] = (eedata << 1) + (prev_eedata >> 15);
369 dev->enetaddr[i*2+1] = eedata >> 7;
370 prev_eedata = eedata;
371 }
372
373 /* Reset the chip to erase any previous misconfiguration. */
374 OUTL(dev, ChipReset, ChipCmd);
375
376 advertising = mdio_read(dev, 1, 4);
377 chip_config = INL(dev, ChipConfig);
378#ifdef NATSEMI_DEBUG
379 printf("%s: Transceiver status %#08X advertising %#08X\n",
380 dev->name, (int) INL(dev, BasicStatus), advertising);
381 printf("%s: Transceiver default autoneg. %s 10%s %s duplex.\n",
382 dev->name, chip_config & AnegMask ? "enabled, advertise" :
383 "disabled, force", chip_config & SpeedMask ? "0" : "",
384 chip_config & DuplexMask ? "full" : "half");
385#endif
386 chip_config |= AnegEnBothBoth;
387#ifdef NATSEMI_DEBUG
388 printf("%s: changed to autoneg. %s 10%s %s duplex.\n",
389 dev->name, chip_config & AnegMask ? "enabled, advertise" :
390 "disabled, force", chip_config & SpeedMask ? "0" : "",
391 chip_config & DuplexMask ? "full" : "half");
392#endif
393 /*write new autoneg bits, reset phy*/
394 OUTL(dev, (chip_config | PhyRst), ChipConfig);
395 /*un-reset phy*/
396 OUTL(dev, chip_config, ChipConfig);
397
398 /* Disable PME:
399 * The PME bit is initialized from the EEPROM contents.
400 * PCI cards probably have PME disabled, but motherboard
401 * implementations may have PME set to enable WakeOnLan.
402 * With PME set the chip will scan incoming packets but
403 * nothing will be written to memory. */
404 SavedClkRun = INL(dev, ClkRun);
405 OUTL(dev, SavedClkRun & ~0x100, ClkRun);
406 }
407 return card_number;
408}
409
410/* Read the EEPROM and MII Management Data I/O (MDIO) interfaces.
411 The EEPROM code is for common 93c06/46 EEPROMs w/ 6bit addresses. */
412
413/* Delay between EEPROM clock transitions.
414 No extra delay is needed with 33Mhz PCI, but future 66Mhz
415 access may need a delay. */
416#define eeprom_delay(ee_addr) INL(dev, ee_addr)
417
418enum EEPROM_Ctrl_Bits {
419 EE_ShiftClk = 0x04,
420 EE_DataIn = 0x01,
421 EE_ChipSelect = 0x08,
422 EE_DataOut = 0x02
423};
424
425#define EE_Write0 (EE_ChipSelect)
426#define EE_Write1 (EE_ChipSelect | EE_DataIn)
427/* The EEPROM commands include the alway-set leading bit. */
428enum EEPROM_Cmds {
429 EE_WrEnCmd = (4 << 6), EE_WriteCmd = (5 << 6),
430 EE_ReadCmd = (6 << 6), EE_EraseCmd = (7 << 6),
431};
432
433#if 0
434static void
435write_eeprom(struct eth_device *dev, long addr, int location, short value)
436{
437 int i;
438 int ee_addr = (typeof(ee_addr))addr;
439 short wren_cmd = EE_WrEnCmd | 0x30; /*wren is 100 + 11XXXX*/
440 short write_cmd = location | EE_WriteCmd;
441
442#ifdef NATSEMI_DEBUG
443 printf("write_eeprom: %08x, %04hx, %04hx\n",
444 dev->iobase + ee_addr, write_cmd, value);
445#endif
446 /* Shift the write enable command bits out. */
447 for (i = 9; i >= 0; i--) {
448 short cmdval = (wren_cmd & (1 << i)) ? EE_Write1 : EE_Write0;
449 OUTL(dev, cmdval, ee_addr);
450 eeprom_delay(ee_addr);
451 OUTL(dev, cmdval | EE_ShiftClk, ee_addr);
452 eeprom_delay(ee_addr);
453 }
454
455 OUTL(dev, 0, ee_addr); /*bring chip select low*/
456 OUTL(dev, EE_ShiftClk, ee_addr);
457 eeprom_delay(ee_addr);
458
459 /* Shift the write command bits out. */
460 for (i = 9; i >= 0; i--) {
461 short cmdval = (write_cmd & (1 << i)) ? EE_Write1 : EE_Write0;
462 OUTL(dev, cmdval, ee_addr);
463 eeprom_delay(ee_addr);
464 OUTL(dev, cmdval | EE_ShiftClk, ee_addr);
465 eeprom_delay(ee_addr);
466 }
467
468 for (i = 0; i < 16; i++) {
469 short cmdval = (value & (1 << i)) ? EE_Write1 : EE_Write0;
470 OUTL(dev, cmdval, ee_addr);
471 eeprom_delay(ee_addr);
472 OUTL(dev, cmdval | EE_ShiftClk, ee_addr);
473 eeprom_delay(ee_addr);
474 }
475
476 OUTL(dev, 0, ee_addr); /*bring chip select low*/
477 OUTL(dev, EE_ShiftClk, ee_addr);
478 for (i = 0; i < 200000; i++) {
479 OUTL(dev, EE_Write0, ee_addr); /*poll for done*/
480 if (INL(dev, ee_addr) & EE_DataOut) {
481 break; /*finished*/
482 }
483 }
484 eeprom_delay(ee_addr);
485
486 /* Terminate the EEPROM access. */
487 OUTL(dev, EE_Write0, ee_addr);
488 OUTL(dev, 0, ee_addr);
489 return;
490}
491#endif
492
493static int
494read_eeprom(struct eth_device *dev, long addr, int location)
495{
496 int i;
497 int retval = 0;
498 int ee_addr = (typeof(ee_addr))addr;
499 int read_cmd = location | EE_ReadCmd;
500
501 OUTL(dev, EE_Write0, ee_addr);
502
503 /* Shift the read command bits out. */
504 for (i = 10; i >= 0; i--) {
505 short dataval = (read_cmd & (1 << i)) ? EE_Write1 : EE_Write0;
506 OUTL(dev, dataval, ee_addr);
507 eeprom_delay(ee_addr);
508 OUTL(dev, dataval | EE_ShiftClk, ee_addr);
509 eeprom_delay(ee_addr);
510 }
511 OUTL(dev, EE_ChipSelect, ee_addr);
512 eeprom_delay(ee_addr);
513
514 for (i = 0; i < 16; i++) {
515 OUTL(dev, EE_ChipSelect | EE_ShiftClk, ee_addr);
516 eeprom_delay(ee_addr);
517 retval |= (INL(dev, ee_addr) & EE_DataOut) ? 1 << i : 0;
518 OUTL(dev, EE_ChipSelect, ee_addr);
519 eeprom_delay(ee_addr);
520 }
521
522 /* Terminate the EEPROM access. */
523 OUTL(dev, EE_Write0, ee_addr);
524 OUTL(dev, 0, ee_addr);
525#ifdef NATSEMI_DEBUG
526 if (natsemi_debug)
527 printf("read_eeprom: %08x, %08x, retval %08x\n",
528 dev->iobase + ee_addr, read_cmd, retval);
529#endif
530 return retval;
531}
532
533/* MII transceiver control section.
534 The 83815 series has an internal transceiver, and we present the
535 management registers as if they were MII connected. */
536
537static int
538mdio_read(struct eth_device *dev, int phy_id, int location)
539{
540 if (phy_id == 1 && location < 32)
541 return INL(dev, BasicControl+(location<<2))&0xffff;
542 else
543 return 0xffff;
544}
545
546/* Function: natsemi_init
547 *
548 * Description: resets the ethernet controller chip and configures
549 * registers and data structures required for sending and receiving packets.
550 *
551 * Arguments: struct eth_device *dev: NIC data structure
552 *
553 * returns: int.
554 */
555
556static int
557natsemi_init(struct eth_device *dev, bd_t * bis)
558{
559
560 natsemi_reset(dev);
561
562 /* Disable PME:
563 * The PME bit is initialized from the EEPROM contents.
564 * PCI cards probably have PME disabled, but motherboard
565 * implementations may have PME set to enable WakeOnLan.
566 * With PME set the chip will scan incoming packets but
567 * nothing will be written to memory. */
568 OUTL(dev, SavedClkRun & ~0x100, ClkRun);
569
570 natsemi_init_rxfilter(dev);
571 natsemi_init_txd(dev);
572 natsemi_init_rxd(dev);
573
574 /* Configure the PCI bus bursts and FIFO thresholds. */
575 tx_config = TxAutoPad | TxCollRetry | TxMxdma_256 | (0x1002);
576 rx_config = RxMxdma_256 | 0x20;
577
578#ifdef NATSEMI_DEBUG
579 printf("%s: Setting TxConfig Register %#08X\n", dev->name, tx_config);
580 printf("%s: Setting RxConfig Register %#08X\n", dev->name, rx_config);
581#endif
582 OUTL(dev, tx_config, TxConfig);
583 OUTL(dev, rx_config, RxConfig);
584
585 natsemi_check_duplex(dev);
586 natsemi_set_rx_mode(dev);
587
588 OUTL(dev, (RxOn | TxOn), ChipCmd);
589 return 1;
590}
591
592/*
593 * Function: natsemi_reset
594 *
595 * Description: soft resets the controller chip
596 *
597 * Arguments: struct eth_device *dev: NIC data structure
598 *
599 * Returns: void.
600 */
601static void
602natsemi_reset(struct eth_device *dev)
603{
604 OUTL(dev, ChipReset, ChipCmd);
605
606 /* On page 78 of the spec, they recommend some settings for "optimum
607 performance" to be done in sequence. These settings optimize some
608 of the 100Mbit autodetection circuitry. Also, we only want to do
609 this for rev C of the chip. */
610 if (INL(dev, SiliconRev) == 0x302) {
611 OUTW(dev, 0x0001, PGSEL);
612 OUTW(dev, 0x189C, PMDCSR);
613 OUTW(dev, 0x0000, TSTDAT);
614 OUTW(dev, 0x5040, DSPCFG);
615 OUTW(dev, 0x008C, SDCFG);
616 }
617 /* Disable interrupts using the mask. */
618 OUTL(dev, 0, IntrMask);
619 OUTL(dev, 0, IntrEnable);
620}
621
622/* Function: natsemi_init_rxfilter
623 *
624 * Description: sets receive filter address to our MAC address
625 *
626 * Arguments: struct eth_device *dev: NIC data structure
627 *
628 * returns: void.
629 */
630
631static void
632natsemi_init_rxfilter(struct eth_device *dev)
633{
634 int i;
635
636 for (i = 0; i < ETH_ALEN; i += 2) {
637 OUTL(dev, i, RxFilterAddr);
638 OUTW(dev, dev->enetaddr[i] + (dev->enetaddr[i + 1] << 8),
639 RxFilterData);
640 }
641}
642
643/*
644 * Function: natsemi_init_txd
645 *
646 * Description: initializes the Tx descriptor
647 *
648 * Arguments: struct eth_device *dev: NIC data structure
649 *
650 * returns: void.
651 */
652
653static void
654natsemi_init_txd(struct eth_device *dev)
655{
656 txd.link = (u32) 0;
657 txd.cmdsts = (u32) 0;
658 txd.bufptr = (u32) & txb[0];
659
660 /* load Transmit Descriptor Register */
661 OUTL(dev, (u32) & txd, TxRingPtr);
662#ifdef NATSEMI_DEBUG
663 printf("natsemi_init_txd: TX descriptor reg loaded with: %#08X\n",
664 INL(dev, TxRingPtr));
665#endif
666}
667
668/* Function: natsemi_init_rxd
669 *
670 * Description: initializes the Rx descriptor ring
671 *
672 * Arguments: struct eth_device *dev: NIC data structure
673 *
674 * Returns: void.
675 */
676
677static void
678natsemi_init_rxd(struct eth_device *dev)
679{
680 int i;
681
682 cur_rx = 0;
683
684 /* init RX descriptor */
685 for (i = 0; i < NUM_RX_DESC; i++) {
686 rxd[i].link =
687 cpu_to_le32((i + 1 <
688 NUM_RX_DESC) ? (u32) & rxd[i +
689 1] : (u32) &
690 rxd[0]);
691 rxd[i].cmdsts = cpu_to_le32((u32) RX_BUF_SIZE);
692 rxd[i].bufptr = cpu_to_le32((u32) & rxb[i * RX_BUF_SIZE]);
693#ifdef NATSEMI_DEBUG
694 printf
695 ("natsemi_init_rxd: rxd[%d]=%p link=%X cmdsts=%lX bufptr=%X\n",
696 i, &rxd[i], le32_to_cpu(rxd[i].link),
697 rxd[i].cmdsts, rxd[i].bufptr);
698#endif
699 }
700
701 /* load Receive Descriptor Register */
702 OUTL(dev, (u32) & rxd[0], RxRingPtr);
703
704#ifdef NATSEMI_DEBUG
705 printf("natsemi_init_rxd: RX descriptor register loaded with: %X\n",
706 INL(dev, RxRingPtr));
707#endif
708}
709
710/* Function: natsemi_set_rx_mode
711 *
712 * Description:
713 * sets the receive mode to accept all broadcast packets and packets
714 * with our MAC address, and reject all multicast packets.
715 *
716 * Arguments: struct eth_device *dev: NIC data structure
717 *
718 * Returns: void.
719 */
720
721static void
722natsemi_set_rx_mode(struct eth_device *dev)
723{
724 u32 rx_mode = AcceptBroadcast | AcceptMyPhys;
725
726 OUTL(dev, rx_mode, RxFilterAddr);
727}
728
729static void
730natsemi_check_duplex(struct eth_device *dev)
731{
732 int duplex = INL(dev, ChipConfig) & FullDuplex ? 1 : 0;
733
734#ifdef NATSEMI_DEBUG
735 printf("%s: Setting %s-duplex based on negotiated link"
736 " capability.\n", dev->name, duplex ? "full" : "half");
737#endif
738 if (duplex) {
739 rx_config |= RxAcceptTx;
740 tx_config |= (TxCarrierIgn | TxHeartIgn);
741 } else {
742 rx_config &= ~RxAcceptTx;
743 tx_config &= ~(TxCarrierIgn | TxHeartIgn);
744 }
745 OUTL(dev, tx_config, TxConfig);
746 OUTL(dev, rx_config, RxConfig);
747}
748
749/* Function: natsemi_send
750 *
751 * Description: transmits a packet and waits for completion or timeout.
752 *
753 * Returns: void. */
754static int
755natsemi_send(struct eth_device *dev, volatile void *packet, int length)
756{
757 u32 i, status = 0;
758 u32 tx_status = 0;
759
760 /* Stop the transmitter */
761 OUTL(dev, TxOff, ChipCmd);
762
763#ifdef NATSEMI_DEBUG
764 if (natsemi_debug)
765 printf("natsemi_send: sending %d bytes\n", (int) length);
766#endif
767
768 /* set the transmit buffer descriptor and enable Transmit State Machine */
769 txd.link = cpu_to_le32(0);
770 txd.bufptr = cpu_to_le32(phys_to_bus((u32) packet));
771 txd.cmdsts = cpu_to_le32(DescOwn | length);
772
773 /* load Transmit Descriptor Register */
774 OUTL(dev, phys_to_bus((u32) & txd), TxRingPtr);
775#ifdef NATSEMI_DEBUG
776 if (natsemi_debug)
777 printf("natsemi_send: TX descriptor register loaded with: %#08X\n",
778 INL(dev, TxRingPtr));
779#endif
780 /* restart the transmitter */
781 OUTL(dev, TxOn, ChipCmd);
782
783 for (i = 0;
784 ((vu_long)tx_status = le32_to_cpu(txd.cmdsts)) & DescOwn;
785 i++) {
786 if (i >= TOUT_LOOP) {
787 printf
788 ("%s: tx error buffer not ready: txd.cmdsts == %#X\n",
789 dev->name, tx_status);
790 goto Done;
791 }
792 }
793
794 if (!(tx_status & DescPktOK)) {
795 printf("natsemi_send: Transmit error, Tx status %X.\n",
796 tx_status);
797 goto Done;
798 }
799
800 status = 1;
801 Done:
802 return status;
803}
804
805/* Function: natsemi_poll
806 *
807 * Description: checks for a received packet and returns it if found.
808 *
809 * Arguments: struct eth_device *dev: NIC data structure
810 *
811 * Returns: 1 if packet was received.
812 * 0 if no packet was received.
813 *
814 * Side effects:
815 * Returns (copies) the packet to the array dev->packet.
816 * Returns the length of the packet.
817 */
818
819static int
820natsemi_poll(struct eth_device *dev)
821{
822 int retstat = 0;
823 int length = 0;
824 u32 rx_status = le32_to_cpu(rxd[cur_rx].cmdsts);
825
826 if (!(rx_status & (u32) DescOwn))
827 return retstat;
828#ifdef NATSEMI_DEBUG
829 if (natsemi_debug)
830 printf("natsemi_poll: got a packet: cur_rx:%d, status:%X\n",
831 cur_rx, rx_status);
832#endif
833 length = (rx_status & DSIZE) - CRC_SIZE;
834
835 if ((rx_status & (DescMore | DescPktOK | DescRxLong)) != DescPktOK) {
836 printf
837 ("natsemi_poll: Corrupted packet received, buffer status = %X\n",
838 rx_status);
839 retstat = 0;
840 } else { /* give packet to higher level routine */
841 NetReceive((rxb + cur_rx * RX_BUF_SIZE), length);
842 retstat = 1;
843 }
844
845 /* return the descriptor and buffer to receive ring */
846 rxd[cur_rx].cmdsts = cpu_to_le32(RX_BUF_SIZE);
847 rxd[cur_rx].bufptr = cpu_to_le32((u32) & rxb[cur_rx * RX_BUF_SIZE]);
848
849 if (++cur_rx == NUM_RX_DESC)
850 cur_rx = 0;
851
852 /* re-enable the potentially idle receive state machine */
853 OUTL(dev, RxOn, ChipCmd);
854
855 return retstat;
856}
857
858/* Function: natsemi_disable
859 *
860 * Description: Turns off interrupts and stops Tx and Rx engines
861 *
862 * Arguments: struct eth_device *dev: NIC data structure
863 *
864 * Returns: void.
865 */
866
867static void
868natsemi_disable(struct eth_device *dev)
869{
870 /* Disable interrupts using the mask. */
871 OUTL(dev, 0, IntrMask);
872 OUTL(dev, 0, IntrEnable);
873
874 /* Stop the chip's Tx and Rx processes. */
875 OUTL(dev, RxOff | TxOff, ChipCmd);
876
877 /* Restore PME enable bit */
878 OUTL(dev, SavedClkRun, ClkRun);
879}
880
881#endif