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