add pipacs package (thanks to Janos)
[openwrt/svn-archive/archive.git] / openwrt / target / linux / linux-2.4 / patches / ar531x / 001-ar531x-ethernet.patch
1 diff -urN linux-2.4.32.new/arch/mips/ar531x/ae531xlnx.c linux-2.4.32.new-eth/arch/mips/ar531x/ae531xlnx.c
2 --- linux-2.4.32.new/arch/mips/ar531x/ae531xlnx.c 1970-01-01 01:00:00.000000000 +0100
3 +++ linux-2.4.32.new-eth/arch/mips/ar531x/ae531xlnx.c 2005-12-25 11:54:20.756273952 +0000
4 @@ -0,0 +1,1534 @@
5 +/*
6 + * This file is subject to the terms and conditions of the GNU General Public
7 + * License. See the file "COPYING" in the main directory of this archive
8 + * for more details.
9 + *
10 + * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
11 + */
12 +
13 +/*
14 + * Ethernet driver for Atheros' ae531x ethernet MAC.
15 + * This is a fairly generic driver, but it's intended
16 + * for use in typical Atheros products.
17 + */
18 +
19 +#include <linux/config.h>
20 +#include <linux/types.h>
21 +#include <linux/delay.h>
22 +#include <linux/netdevice.h>
23 +#include <linux/etherdevice.h>
24 +#include <linux/init.h>
25 +#include <linux/skbuff.h>
26 +#include <asm/io.h>
27 +
28 +#include "ar531xlnx.h"
29 +#include "ae531xreg.h"
30 +#include "ae531xmac.h"
31 +
32 +/*
33 + * A word about CONFIG_VENETDEV: It's intended to support two
34 + * "virtualized ethernet devices" that share a single underlying MAC.
35 + * To upper layers, it appears that the hardware supports two MACs,
36 + * with enet0 used for LAN ports and enet1 used for a WAN port. This
37 + * is useful, for instance, when building a 5-port router on hardware
38 + * that uses only one of the AR5312's ethernet MACs.
39 + *
40 + * Virtualization is accomplished through trickery at the ethernet
41 + * PHY layer. We use PHY hardware to determine which port a packet
42 + * was received on, and in order to direct a packet to a particular
43 + * port or set of ports.
44 + *
45 + * The code is mostly written to be generalized to more than two
46 + * virtual devices; but it's intended for one multi-port LAN enet
47 + * device and one single-port WAN enet device.
48 + */
49 +
50 +#define AE531X_LAN_PORT 0
51 +#ifdef CONFIG_VENETDEV
52 +#define AE531X_DEV_PER_MAC 2
53 +#define AE531X_WAN_PORT 1
54 +#else
55 +#define AE531X_DEV_PER_MAC 1
56 +#endif
57 +
58 +
59 +/*
60 + * ae531x_MAC_state contains driver-specific linux-specific per-MAC information.
61 + * The OSinfo member of ae531x_MAC_t points to one of these.
62 + */
63 +typedef struct ae531x_MAC_state {
64 + int irq;
65 + struct tq_struct restart_task;
66 + struct net_device_stats stats;
67 + struct ae531x_dev_sw_state *dev_sw_state[AE531X_DEV_PER_MAC];
68 + int primary_dev;
69 + ae531x_MAC_t MACInfo; /* hardware state */
70 +} ae531x_MAC_state_t;
71 +
72 +/*
73 + * ae531x_dev_sw_state contains driver-specific linux-specific per-device
74 + * information. The net_device priv member points to one of these, and
75 + * this structure contains a pointer to the associated MAC information.
76 + * In the case of CONFIG_VENETDEV, each virtual device has its own
77 + * ae531x_dev_sw_state, and virtual devices that share a physical MAC
78 + * point to the same ae531x_MAC_state.
79 + */
80 +typedef struct ae531x_dev_sw_state {
81 + int enetUnit; /* system unit number "eth%d" */
82 + int unit_on_MAC; /* MAC-relative unit number */
83 + struct net_device *dev;
84 + ae531x_MAC_state_t *MAC_state; /* underlying MAC hw/sw state */
85 +#ifdef CONFIG_VENETDEV
86 + BOOL isLAN; /* 0-->WAN; 1-->LAN */
87 +#endif
88 +} ae531x_dev_sw_state_t;
89 +
90 +/*
91 + * Driver-independent linux-specific per-ethernet device software information.
92 + * Regarding CONFIG_VENETDEV: If a system has 2 physical MACs, and each
93 + * physical MAC has 2 virtual ethernet devices (one for LAN and one for WAN),
94 + * then there are a total of 4 ethernet devices.
95 + */
96 +static struct net_device *ae531x_MAC_dev[AR531X_NUM_ENET_MAC * AE531X_DEV_PER_MAC];
97 +
98 +/* Driver-dependent per-MAC information */
99 +static ae531x_MAC_state_t per_MAC_info[AR531X_NUM_ENET_MAC];
100 +
101 +/*
102 + * Receive buffers need enough room to hold the following:
103 + * 1) a max MTU-sized packet.
104 + * 2) space for an ethernet header
105 + * 3) room at the beginning of the receive buffer in order
106 + * to facilitate cooperating drivers that need to PREpend
107 + * data.
108 + * 4) Depending on configuration, we may need some additional
109 + * room at the END of the rx buffer for phy-supplied
110 + * trailers (if any). (c.f. CONFIG_VENETDEV)
111 + *
112 + * The DMA engine insists on 32-bit aligned RX buffers.
113 + * TBDXXX: With current code, the IP stack ends up looking
114 + * at misaligned headers with word operations. The misaligned
115 + * reads are software-emulated via handle_adel_int. We'd
116 + * rather align the buffers on a 16-bit boundary, but the
117 + * DMA engine doesn't permit it???
118 + */
119 +
120 +#ifdef CONFIG_VLAN_8021Q
121 +#define ETH_MAX_MTU 1522
122 +#define HLEN 18
123 +#else
124 +#define ETH_MAX_MTU 1518
125 +#define HLEN ETH_HLEN
126 +#endif
127 +
128 +#define AE531X_RX_BUF_SIZE \
129 + (((2 + RXBUFF_RESERVE + HLEN + ETH_MAX_MTU + PHY_TRAILER_SIZE) + 3) & ~3)
130 +
131 +/* Forward references to local functions */
132 +static void ae531x_TxReap(ae531x_MAC_state_t *MAC_state);
133 +static int ae531x_phy_poll(void *data);
134 +static int ae531x_MAC_stop(struct net_device *dev);
135 +static int ae531x_MAC_open(struct net_device *dev);
136 +
137 +/* Global to track number of MACs */
138 +
139 +int ar531x_num_enet_macs;
140 +
141 +#undef DEBUG_VENETDEV
142 +#define AR531X_NAPI
143 +
144 +#if defined(CONFIG_VENETDEV) && defined(DEBUG_VENETDEV)
145 +static int cloned_counter;
146 +static int expand_counter;
147 +static int both_counter;
148 +#endif
149 +
150 +#ifdef AR531X_NAPI
151 +/*******************************************************************************
152 +* ae531x_MAC_poll checks for received packets, and sends data
153 +* up the stack.
154 +*/
155 +int
156 +ae531x_MAC_poll(struct net_device *dev, int *budget)
157 +{
158 + struct sk_buff *skb;
159 + struct sk_buff *newskb;
160 + char *rxBufp;
161 + int unused_length;
162 + VIRT_ADDR rxDesc;
163 + int length;
164 + ae531x_dev_sw_state_t *dev_sw_state;
165 + ae531x_MAC_state_t *MAC_state;
166 + ae531x_MAC_t *MACInfo;
167 + u32 cmdsts;
168 + int rx_limit;
169 + int rx_received;
170 + int rxDescCount;
171 + struct net_device *rxdev;
172 + int early_stop;
173 + int retval;
174 +#ifdef CONFIG_VENETDEV
175 + int i;
176 +#endif
177 +
178 + ARRIVE();
179 +
180 + dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
181 + MAC_state = dev_sw_state->MAC_state;
182 + MACInfo = &MAC_state->MACInfo;
183 + rx_limit = MAC_state->dev_sw_state[MAC_state->primary_dev]->dev->quota;
184 + rx_received = 0;
185 +
186 +#ifdef CONFIG_VENETDEV
187 + /*
188 + * Non-primary devs don't explicitly get polled by the upper layers;
189 + * rather, they rely on primary_dev polling to feed packets. But in
190 + * order to keep netif_receive_skb happy, we need to temporarily put the
191 + * net_devices into "polling mode". We pull them back out before
192 + * leaving this function.
193 + */
194 + for (i=0; i<AE531X_DEV_PER_MAC; i++) {
195 + if ((MAC_state->dev_sw_state[i]->dev) &&
196 + (MAC_state->dev_sw_state[i]->unit_on_MAC != MAC_state->primary_dev)) {
197 + netif_rx_schedule(MAC_state->dev_sw_state[i]->dev);
198 + }
199 + }
200 +#endif
201 + rxDescCount = 0;
202 +
203 + early_stop = 0;
204 + do {
205 + for(;;) {
206 + // ae531x_AckIntr(MACInfo, (DmaIntRxCompleted | DmaIntRxNoBuffer));
207 +
208 + rxDesc = MACInfo->rxQueue.curDescAddr;
209 + cmdsts = AE531X_DESC_STATUS_GET(KSEG1ADDR(rxDesc));
210 +
211 + AE531X_PRINT(AE531X_DEBUG_RX,
212 + ("examine rxDesc %p with cmdsts=0x%x\n",
213 + (void *)rxDesc, cmdsts));
214 +
215 + if (cmdsts & DescOwnByDma) {
216 + /* There's nothing left to process in the RX ring */
217 + goto rx_all_done;
218 + }
219 +
220 + rxDescCount++;
221 +
222 + AE531X_CONSUME_DESC((&MACInfo->rxQueue));
223 +
224 + // A_DATA_CACHE_INVAL(rxDesc, AE531X_DESC_SIZE);
225 +
226 + /* Process a packet */
227 + length = AE531X_DESC_STATUS_RX_SIZE(cmdsts) - ETH_CRC_LEN;
228 + if ( (cmdsts & (DescRxFirst |DescRxLast | DescRxErrors)) ==
229 + (DescRxFirst | DescRxLast) ) {
230 + /* Descriptor status indicates "NO errors" */
231 + skb = AE531X_DESC_SWPTR_GET(rxDesc);
232 +
233 + /*
234 + * Allocate a replacement skb.
235 + * We want to get another buffer ready for Rx ASAP.
236 + */
237 + newskb = (struct sk_buff *)ae531x_rxbuf_alloc(MACInfo, &rxBufp, &unused_length);
238 + if(newskb == NULL ) {
239 + /*
240 + * Give this descriptor back to the DMA engine,
241 + * and drop the received packet.
242 + */
243 + MAC_state->stats.rx_dropped++;
244 + AE531X_PRINT(AE531X_DEBUG_ERROR,
245 + ("Can't allocate new skb\n"));
246 + } else {
247 + AE531X_DESC_BUFPTR_SET(rxDesc, rxBufp);
248 + AE531X_DESC_SWPTR_SET(rxDesc, newskb);
249 + }
250 +
251 + AE531X_DESC_STATUS_SET(rxDesc, DescOwnByDma);
252 + A_DATA_CACHE_FLUSH_INVAL(rxDesc, AE531X_DESC_SIZE);
253 + // rxDesc = NULL; /* sanity -- cannot use rxDesc now */
254 + sysWbFlush();
255 +
256 + if (newskb == NULL) {
257 + retval = 1;
258 + goto rx_no_skbs;
259 + } else {
260 + /* Sync data cache w.r.t. DMA */
261 + // A_DATA_CACHE_INVAL(skb->data, length);
262 +
263 +#ifdef CONFIG_VENETDEV
264 + /* Determine which associated device owns this rx buffer */
265 + {
266 + int fromLAN;
267 +
268 + fromLAN = phyDetermineSource(skb->data, length);
269 +
270 + if (fromLAN == -1) {
271 + /*
272 + * Could not determine source, so drop the packet
273 + */
274 + dev_kfree_skb(skb);
275 + continue;
276 + }
277 +
278 + length -= PHY_TRAILER_SIZE;
279 + if (fromLAN) {
280 + dev_sw_state = MAC_state->dev_sw_state[AE531X_LAN_PORT];
281 + } else {
282 + dev_sw_state = MAC_state->dev_sw_state[AE531X_WAN_PORT];
283 + }
284 + }
285 +#endif
286 + rxdev = dev_sw_state->dev;
287 +
288 + if (rxdev == NULL) {
289 + /*
290 + * We received a packet for a virtual enet device
291 + * that is no longer up. Ignore it.
292 + */
293 + dev_kfree_skb(skb);
294 + continue;
295 + }
296 +
297 + /* Advance data pointer to show that there's data here */
298 + skb_put(skb, length);
299 + skb->protocol = eth_type_trans(skb, rxdev);
300 + skb->dev = rxdev;
301 + rxdev->last_rx = jiffies;
302 + rxdev->quota--;
303 +
304 + if (rx_limit-- < 0) {
305 + early_stop=1;
306 + /* We've done enough for now -- more later */
307 + AE531X_PRINT(AE531X_DEBUG_RX_STOP,
308 + ("Enet%d RX early stop. Quota=%d rxDescCount=%d budget=%d\n",
309 + MACInfo->unit, dev->quota, rxDescCount, *budget));
310 + }
311 + rx_received++;
312 +
313 + /* Send the data up the stack */
314 + AE531X_PRINT(AE531X_DEBUG_RX,
315 + ("Send data up stack: skb=%p data=%p length=%d\n",
316 + (void *)skb, (void *)skb->data, length));
317 +
318 + netif_receive_skb(skb);
319 +
320 + MAC_state->stats.rx_packets++;
321 + MAC_state->stats.rx_bytes += length;
322 + }
323 + } else {
324 + /* Descriptor status indicates ERRORS */
325 + MAC_state->stats.rx_errors++;
326 +
327 + if (cmdsts & (DescRxRunt | DescRxLateColl)) {
328 + AE531X_PRINT(AE531X_DEBUG_ERROR,
329 + ("Runt | RX Late Collision Error\n"));
330 + MAC_state->stats.collisions++;
331 + }
332 +
333 + if (cmdsts & DescRxLengthError) {
334 + AE531X_PRINT(AE531X_DEBUG_ERROR,
335 + ("RX Length Error\n"));
336 + MAC_state->stats.rx_length_errors++;
337 + }
338 +
339 + if (cmdsts & DescRxCrc) {
340 + AE531X_PRINT(AE531X_DEBUG_ERROR,
341 + ("RX CRC Error\n"));
342 + MAC_state->stats.rx_crc_errors++;
343 + }
344 +
345 + if (cmdsts & DescRxDribbling) {
346 + AE531X_PRINT(AE531X_DEBUG_ERROR,
347 + ("Dribbling Error\n"));
348 + MAC_state->stats.rx_frame_errors++;
349 + }
350 +
351 + AE531X_PRINT(AE531X_DEBUG_ERROR,
352 + ("Bad receive. rxDesc=%p cmdsts=0x%8.8x\n",
353 + (void *)rxDesc, cmdsts));
354 +
355 + /* Give this one back */
356 + AE531X_DESC_STATUS_SET(rxDesc, DescOwnByDma);
357 + A_DATA_CACHE_FLUSH_INVAL(rxDesc, AE531X_DESC_SIZE);
358 + sysWbFlush();
359 + }
360 + }
361 + } while ((!early_stop) &&
362 + ae531x_ReadDmaReg(MACInfo, DmaStatus) & DmaIntRxCompleted);
363 +
364 +rx_all_done:
365 + AE531X_PRINT(AE531X_DEBUG_RX,
366 + ("rx done (%d)\n", rxDescCount));
367 + *budget -= rxDescCount;
368 +
369 + if (!early_stop) {
370 + netif_rx_complete(dev);
371 +
372 + ae531x_SetDmaReg(MACInfo, DmaIntrEnb,
373 + DmaIeRxCompleted | DmaIeRxNoBuffer);
374 + ae531x_WriteDmaReg(MACInfo, DmaRxPollDemand, 0);
375 + }
376 +
377 + retval = early_stop;
378 +
379 +rx_no_skbs:
380 +
381 +#ifdef CONFIG_VENETDEV
382 + for (i=0; i<AE531X_DEV_PER_MAC; i++) {
383 + if ((MAC_state->dev_sw_state[i]->dev) &&
384 + (MAC_state->dev_sw_state[i]->unit_on_MAC !=
385 + MAC_state->primary_dev)) {
386 + netif_rx_complete(MAC_state->dev_sw_state[i]->dev);
387 + }
388 + }
389 +#endif
390 +
391 + LEAVE();
392 + return retval;
393 +}
394 +#endif
395 +
396 +#ifndef AR531X_NAPI
397 +/*******************************************************************************
398 +* ae531x_MAC_recv checks for received packets, and sends data
399 +* up the stack.
400 +*/
401 +static void
402 +ae531x_MAC_recv(struct net_device *dev)
403 +{
404 + struct sk_buff *skb;
405 + struct sk_buff *newskb;
406 + char *rxBufp;
407 + int unused_length;
408 + VIRT_ADDR rxDesc;
409 + int length;
410 + ae531x_dev_sw_state_t *dev_sw_state;
411 + ae531x_MAC_state_t *MAC_state;
412 + ae531x_MAC_t *MACInfo;
413 + u32 cmdsts;
414 + int rx_limit;
415 + int rx_received;
416 + struct net_device *rxdev;
417 + int retval;
418 +
419 + ARRIVE();
420 +
421 + dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
422 + MAC_state = dev_sw_state->MAC_state;
423 + MACInfo = &MAC_state->MACInfo;
424 + rx_limit = MAC_state->dev_sw_state[MAC_state->primary_dev]->dev->quota;
425 + rx_received = 0;
426 +
427 + for(;;) {
428 + rxDesc = MACInfo->rxQueue.curDescAddr;
429 + cmdsts = AE531X_DESC_STATUS_GET(KSEG1ADDR(rxDesc));
430 +
431 + AE531X_PRINT(AE531X_DEBUG_RX,
432 + ("examine rxDesc %p with cmdsts=0x%x\n",
433 + (void *)rxDesc, cmdsts));
434 +
435 + if (cmdsts & DescOwnByDma) {
436 + /* There's nothing left to process in the RX ring */
437 + break;
438 + }
439 +
440 + AE531X_CONSUME_DESC((&MACInfo->rxQueue));
441 +
442 + // A_DATA_CACHE_INVAL(rxDesc, AE531X_DESC_SIZE);
443 +
444 + /* Process a packet */
445 + length = AE531X_DESC_STATUS_RX_SIZE(cmdsts) - ETH_CRC_LEN;
446 + if ( (cmdsts & (DescRxFirst |DescRxLast | DescRxErrors)) ==
447 + (DescRxFirst | DescRxLast) ) {
448 + /* Descriptor status indicates "NO errors" */
449 + skb = AE531X_DESC_SWPTR_GET(rxDesc);
450 +
451 + /*
452 + * Allocate a replacement skb.
453 + * We want to get another buffer ready for Rx ASAP.
454 + */
455 + newskb = (struct sk_buff *)ae531x_rxbuf_alloc(MACInfo,
456 + &rxBufp,
457 + &unused_length);
458 + if(newskb == NULL ) {
459 + /*
460 + * Give this descriptor back to the DMA engine,
461 + * and drop the received packet.
462 + */
463 + MAC_state->stats.rx_dropped++;
464 + AE531X_PRINT(AE531X_DEBUG_ERROR,
465 + ("Can't allocate new skb\n"));
466 + } else {
467 + AE531X_DESC_BUFPTR_SET(rxDesc, rxBufp);
468 + AE531X_DESC_SWPTR_SET(rxDesc, newskb);
469 + }
470 +
471 + AE531X_DESC_STATUS_SET(rxDesc, DescOwnByDma);
472 + A_DATA_CACHE_FLUSH_INVAL(rxDesc, AE531X_DESC_SIZE);
473 + sysWbFlush();
474 +
475 + if (newskb == NULL) {
476 + break;
477 + } else {
478 +#ifdef CONFIG_VENETDEV
479 + /* Determine which associated device owns this rx buffer */
480 + {
481 + int fromLAN;
482 +
483 + fromLAN = phyDetermineSource(skb->data, length);
484 +
485 + if (fromLAN == -1) {
486 + /*
487 + * Could not determine source, so drop the packet
488 + */
489 + dev_kfree_skb(skb);
490 + continue;
491 + }
492 +
493 + length -= PHY_TRAILER_SIZE;
494 + if (fromLAN) {
495 + dev_sw_state =
496 + MAC_state->dev_sw_state[AE531X_LAN_PORT];
497 + } else {
498 + dev_sw_state =
499 + MAC_state->dev_sw_state[AE531X_WAN_PORT];
500 + }
501 + }
502 +#endif
503 + rxdev = dev_sw_state->dev;
504 +
505 + if (rxdev == NULL) {
506 + /*
507 + * We received a packet for a virtual enet device
508 + * that is no longer up. Ignore it.
509 + */
510 + dev_kfree_skb(skb);
511 + continue;
512 + }
513 +
514 + /* Advance data pointer to show that there's data here */
515 + skb_put(skb, length);
516 + skb->protocol = eth_type_trans(skb, rxdev);
517 + skb->dev = rxdev;
518 + rxdev->last_rx = jiffies;
519 + rxdev->quota--;
520 +
521 + rx_received++;
522 +
523 + /* Send the data up the stack */
524 + AE531X_PRINT(AE531X_DEBUG_RX,
525 + ("Send data up stack: skb=%p data=%p length=%d\n",
526 + (void *)skb, (void *)skb->data, length));
527 +
528 + netif_rx(skb);
529 +
530 + MAC_state->stats.rx_packets++;
531 + MAC_state->stats.rx_bytes += length;
532 + }
533 + } else {
534 + /* Descriptor status indicates ERRORS */
535 + MAC_state->stats.rx_errors++;
536 +
537 + if (cmdsts & (DescRxRunt | DescRxLateColl)) {
538 + MAC_state->stats.collisions++;
539 + }
540 +
541 + if (cmdsts & DescRxLengthError) {
542 + MAC_state->stats.rx_length_errors++;
543 + }
544 +
545 + if (cmdsts & DescRxCrc) {
546 + MAC_state->stats.rx_crc_errors++;
547 + }
548 +
549 + if (cmdsts & DescRxDribbling) {
550 + MAC_state->stats.rx_frame_errors++;
551 + }
552 +
553 + AE531X_PRINT(AE531X_DEBUG_ERROR,
554 + ("Bad receive. rxDesc=%p cmdsts=0x%8.8x\n",
555 + (void *)rxDesc, cmdsts));
556 + }
557 + }
558 +
559 + LEAVE();
560 + return;
561 +}
562 +#endif
563 +
564 +/*******************************************************************************
565 +* ae531x_restart stops all ethernet devices associated with a physical MAC,
566 +* then shuts down the MAC. Then it re-opens all devices that were in use.
567 +* TBDXXX: needs testing!
568 +*/
569 +static void
570 +ae531x_restart(void *data)
571 +{
572 + ae531x_MAC_t *MACInfo = (ae531x_MAC_t *)data;
573 + ae531x_MAC_state_t *MAC_state = (ae531x_MAC_state_t *)MACInfo->OSinfo;
574 + struct net_device *saved_dev[AE531X_DEV_PER_MAC];
575 + int i;
576 +
577 + for (i=0; i<AE531X_DEV_PER_MAC; i++) {
578 + if ((saved_dev[i] = MAC_state->dev_sw_state[i]->dev) != NULL) {
579 + ae531x_MAC_stop(saved_dev[i]);
580 + }
581 + }
582 +
583 + for (i=0; i<AE531X_DEV_PER_MAC; i++) {
584 + if (saved_dev[i])
585 + ae531x_MAC_open(saved_dev[i]);
586 + }
587 +}
588 +
589 +/*******************************************************************************
590 +* ae531x_MAC_intr handle interrupts from an ethernet MAC.
591 +* It checks MAC status registers, and dispatches as appropriate.
592 +*/
593 +void
594 +ae531x_MAC_intr(int cpl, void *dev_id, struct pt_regs *regs)
595 +{
596 + ae531x_MAC_state_t *MAC_state;
597 + ae531x_MAC_t *MACInfo;
598 + u32 regIsr;
599 + u32 regImr;
600 + u32 pendIntrs;
601 + struct net_device * primary_dev;
602 +
603 + ARRIVE();
604 +
605 + MACInfo = (ae531x_MAC_t *)dev_id;
606 + MAC_state = (ae531x_MAC_state_t *)MACInfo->OSinfo;
607 + primary_dev = MAC_state->dev_sw_state[MAC_state->primary_dev]->dev;
608 +
609 + for(;;) {
610 + /* Clear any unhandled intr causes. */
611 + ae531x_WriteDmaReg(MACInfo, DmaStatus, UnhandledIntrMask);
612 +
613 + regIsr = ae531x_ReadDmaReg(MACInfo, DmaStatus);
614 +
615 + regImr = ae531x_ReadDmaReg(MACInfo, DmaIntrEnb);
616 + pendIntrs = regIsr & regImr;
617 +
618 + AE531X_PRINT(AE531X_DEBUG_INT,
619 + ("ethmac%d: intIsr=0x%8.8x intImr=0x%8.8x\n",
620 + MACInfo->unit, regIsr, regImr));
621 +
622 + if ((pendIntrs & DmaAllIntCauseMask) == 0)
623 + break;
624 +
625 + if ((pendIntrs & DmaIntRxCompleted) ||
626 + (pendIntrs & DmaIntRxNoBuffer)) {
627 +#ifdef AR531X_NAPI
628 + if (netif_rx_schedule_prep(primary_dev)) {
629 + ae531x_ClearDmaReg(MACInfo,
630 + DmaIntrEnb,
631 + DmaIeRxCompleted | DmaIeRxNoBuffer);
632 + ae531x_AckIntr(MACInfo,
633 + DmaIntRxCompleted | DmaIntRxNoBuffer);
634 + (void)ae531x_ReadDmaReg(MACInfo, DmaIntrEnb);
635 + __netif_rx_schedule(primary_dev);
636 + } else {
637 + AE531X_PRINT(AE531X_DEBUG_ERROR,
638 + ("%s: Interrupt (0x%8.8x/0x%8.8x) while in poll. regs@%p, pc=%p, ra=%p\n",
639 + __FILE__,
640 + regIsr,
641 + ae531x_ReadDmaReg(MACInfo, DmaIntrEnb),
642 + (void *)regs,
643 + (void *)regs->cp0_epc,
644 + (void *)regs->regs[31]));
645 + ae531x_ClearDmaReg(MACInfo,
646 + DmaIntrEnb,
647 + DmaIeRxCompleted | DmaIeRxNoBuffer);
648 + ae531x_AckIntr(MACInfo,
649 + DmaIntRxCompleted | DmaIntRxNoBuffer);
650 + }
651 +#else
652 + ae531x_MAC_recv(primary_dev);
653 + ae531x_AckIntr(MACInfo,
654 + DmaIntRxCompleted | DmaIntRxNoBuffer);
655 +#endif
656 + }
657 +
658 + if (pendIntrs &
659 + (DmaIntTxStopped | DmaIntTxJabber | DmaIntTxUnderflow)) {
660 + AE531X_PRINT(AE531X_DEBUG_ERROR,
661 + ("ethmac%d: TX Error Intr (0x%x)\n",
662 + MACInfo->unit, pendIntrs));
663 + ae531x_AckIntr(MACInfo,
664 + (DmaIntTxStopped | DmaIntTxJabber | DmaIntTxUnderflow));
665 + }
666 +
667 + if (pendIntrs & DmaIntBusError) {
668 + AE531X_PRINT(AE531X_DEBUG_ERROR,
669 + ("ethmac%d: DMA Bus Error Intr (0x%x)\n",
670 + MACInfo->unit, pendIntrs));
671 + ae531x_AckIntr(MACInfo, DmaIntBusError);
672 + /* Reset the chip, if it's not already being done */
673 + if (ae531x_IsInResetMode(MACInfo)) {
674 + goto intr_done;
675 + }
676 + ae531x_BeginResetMode(MACInfo);
677 + schedule_task(&MAC_state->restart_task);
678 + }
679 +
680 + if (pendIntrs & DmaIntRxStopped) {
681 + AE531X_PRINT(AE531X_DEBUG_ERROR,
682 + ("ethmac%d: RX Stopped Intr (0x%x)\n",
683 + MACInfo->unit, pendIntrs));
684 + ae531x_AckIntr(MACInfo, DmaIntRxStopped);
685 + }
686 + }
687 +
688 + ae531x_DmaIntEnable(MACInfo);
689 +
690 +intr_done:
691 + LEAVE();
692 +}
693 +
694 +/*******************************************************************************
695 +* ae531x_MAC_get_stats returns statistics for a specified device
696 +*/
697 +static struct net_device_stats*
698 +ae531x_MAC_get_stats(struct net_device *dev)
699 +{
700 + ae531x_dev_sw_state_t *dev_sw_state;
701 + ae531x_MAC_state_t *MAC_state;
702 +
703 + ARRIVE();
704 + dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
705 + MAC_state = dev_sw_state->MAC_state;
706 +
707 + LEAVE();
708 + return &MAC_state->stats;
709 +}
710 +
711 +#define AE531X_PHY_POLL_SECONDS 2
712 +
713 +/*******************************************************************************
714 +* ae531x_phy_poll periodically checks for changes in phy status
715 +* (e.g. dropped link).
716 +*/
717 +static int
718 +ae531x_phy_poll(void *data)
719 +{
720 + ae531x_dev_sw_state_t *dev_sw_state = (ae531x_dev_sw_state_t *)data;
721 + ae531x_MAC_t *MACInfo = &dev_sw_state->MAC_state->MACInfo;
722 + int unit = dev_sw_state->enetUnit;
723 +
724 +#if defined(CONFIG_VENETDEV) && defined(DEBUG_VENETDEV)
725 + int previous_cloned = 0;
726 + int previous_expand = 0;
727 + int previous_both = 0;
728 +#endif
729 +
730 + daemonize();
731 + reparent_to_init();
732 + spin_lock_irq(&current->sigmask_lock);
733 + sigemptyset(&current->blocked);
734 + recalc_sigpending(current);
735 + spin_unlock_irq(&current->sigmask_lock);
736 +
737 + snprintf(current->comm, sizeof(current->comm), "%s",
738 + dev_sw_state->dev->name);
739 +
740 + for(;;) {
741 + if (MACInfo->port_is_up) {
742 + phyCheckStatusChange(unit);
743 + }
744 +
745 +#if defined(CONFIG_VENETDEV) && defined(DEBUG_VENETDEV)
746 + if (cloned_counter != previous_cloned) {
747 + printk("Cloned Counter: %d (delta %d)\n",
748 + cloned_counter, cloned_counter - previous_cloned);
749 + previous_cloned = cloned_counter;
750 + }
751 + if (expand_counter != previous_expand) {
752 + printk("Expand Counter: %d (delta %d)\n",
753 + expand_counter, expand_counter - previous_expand);
754 + previous_expand = expand_counter;
755 + }
756 + if (both_counter != previous_both) {
757 + printk("Expand & Cloned Counter: %d (delta %d)\n",
758 + both_counter, both_counter - previous_both);
759 + previous_both = both_counter;
760 + }
761 +#endif
762 +
763 + set_current_state(TASK_UNINTERRUPTIBLE);
764 + schedule_timeout(AE531X_PHY_POLL_SECONDS * HZ);
765 + }
766 +
767 + return 0;
768 +}
769 +
770 +
771 +/*******************************************************************************
772 +* ae531x_MAC_set_rx_mode is used to set the RX mode options, such as
773 +* promiscuous or multicast.
774 +*/
775 +static void
776 +ae531x_MAC_set_rx_mode(struct net_device *dev)
777 +{
778 + ae531x_dev_sw_state_t *dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
779 + ae531x_MAC_state_t *MAC_state=dev_sw_state->MAC_state;
780 + ae531x_MAC_t *MACInfo = &MAC_state->MACInfo;
781 +
782 + if (dev->flags & IFF_PROMISC) {
783 + ae531x_SetMacReg(MACInfo, MacControl, MacPromiscuousModeOn);
784 + } else {
785 + ae531x_ClearMacReg(MACInfo, MacControl, MacPromiscuousModeOn);
786 + }
787 +
788 + if (dev->flags & IFF_MULTICAST) {
789 + ae531x_SetMacReg(MACInfo, MacControl, MacMulticastFilterOff);
790 + } else {
791 + ae531x_ClearMacReg(MACInfo, MacControl, MacMulticastFilterOff);
792 + }
793 +}
794 +
795 +/*******************************************************************************
796 +* ae531x_MAC_open is the standard Linux open function. It puts
797 +* hardware into a known good state, allocates queues, starts
798 +* the phy polling task, and arranges for interrupts to be handled.
799 +*/
800 +static int
801 +ae531x_MAC_open(struct net_device *dev)
802 +{
803 + ae531x_dev_sw_state_t *dev_sw_state;
804 + ae531x_MAC_state_t *MAC_state;
805 + ae531x_MAC_t *MACInfo;
806 + int rv;
807 + struct tq_struct *restart_task;
808 + pid_t phy_poll_pid;
809 +
810 + ARRIVE();
811 +
812 + dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
813 + dev_sw_state->dev = dev;
814 + MAC_state = dev_sw_state->MAC_state;
815 + MACInfo = &MAC_state->MACInfo;
816 +
817 + restart_task = &MAC_state->restart_task;
818 + restart_task->routine = ae531x_restart;
819 + restart_task->data = (void *)MACInfo;
820 +
821 + AE531X_PRINT(AE531X_DEBUG_RESET,
822 + ("ae531x_MAC_open eth%d ethmac%d macBase=0x%x dmaBase=0x%x irq=0x%x\n",
823 + dev_sw_state->enetUnit,
824 + MACInfo->unit,
825 + MACInfo->macBase,
826 + MACInfo->dmaBase,
827 + MAC_state->irq));
828 +
829 + if (!MACInfo->port_is_up) {
830 + /* Bring MAC and PHY out of reset */
831 + ae531x_reset(MACInfo);
832 +
833 + /* Attach interrupt handler */
834 + rv = request_irq(MAC_state->irq, ae531x_MAC_intr, SA_INTERRUPT,
835 + "ae531x_MAC_intr", (void *)MACInfo);
836 + if (rv < 0) {
837 + AE531X_PRINT(AE531X_DEBUG_ERROR,
838 + ("request_irq(0x%x) failed (%d)\n",
839 + MAC_state->irq, rv));
840 + goto open_failure;
841 + }
842 +
843 + /* Initialize PHY */
844 + phySetup(MACInfo->unit, MACInfo->phyBase);
845 +
846 + /* Start thread to poll for phy link status changes */
847 + phy_poll_pid = kernel_thread(ae531x_phy_poll,
848 + dev_sw_state,
849 + CLONE_FS | CLONE_FILES);
850 + if (phy_poll_pid < 0) {
851 + AE531X_PRINT(AE531X_DEBUG_ERROR,
852 + ("ethmac%d unable to start Phy Poll thread\n",
853 + MACInfo->unit));
854 + }
855 +
856 + /* Allocate RX/TX Queues */
857 + if (ae531x_AllocateQueues(MACInfo) < 0) {
858 + AE531X_PRINT(AE531X_DEBUG_RESET, ("Queue allocation failed"));
859 + free_irq(MAC_state->irq, (void *)MACInfo);
860 + goto open_failure;
861 + }
862 +
863 + /* Initialize DMA and descriptors */
864 + ae531x_DmaReset(MACInfo);
865 +
866 + /* Initialize MAC */
867 + ae531x_MACReset(MACInfo);
868 +
869 + /* Set RX mode */
870 + ae531x_MAC_set_rx_mode(dev);
871 +
872 + /* Enable Receive/Transmit */
873 + ae531x_EnableComm(MACInfo);
874 +
875 + MAC_state->primary_dev = dev_sw_state->unit_on_MAC;
876 + MACInfo->port_is_up = TRUE;
877 + }
878 +
879 + dev->trans_start = jiffies;
880 +
881 + LEAVE();
882 + return 0;
883 +
884 +open_failure:
885 + LEAVE();
886 + return -1;
887 +}
888 +
889 +/*
890 + * Shut down MAC hardware.
891 + */
892 +static void
893 +ae531x_MAC_shutdown(ae531x_MAC_state_t *MAC_state)
894 +{
895 + ae531x_MAC_t *MACInfo;
896 +
897 + MACInfo = &MAC_state->MACInfo;
898 + MACInfo->port_is_up = FALSE;
899 +
900 + /* Disable Receive/Transmit */
901 + ae531x_DisableComm(MACInfo);
902 +
903 + /* Disable Interrupts */
904 + ae531x_DmaIntDisable(MACInfo);
905 + sysWbFlush();
906 + free_irq(MAC_state->irq, (void *)MACInfo);
907 +
908 + /* Free Transmit & Receive skb's/descriptors */
909 + ae531x_TxReap(MAC_state); /* one last time */
910 + ae531x_FreeQueues(MACInfo);
911 +}
912 +
913 +/*******************************************************************************
914 +* ae531x_MAC_stop is the standard Linux stop function. It undoes
915 +* everything set up by ae531x_MAC_open.
916 +*/
917 +static int
918 +ae531x_MAC_stop(struct net_device *dev)
919 +{
920 + ae531x_dev_sw_state_t *dev_sw_state;
921 + ae531x_MAC_state_t *MAC_state;
922 + ae531x_MAC_t *MACInfo;
923 + int i;
924 +
925 + ARRIVE();
926 +
927 + dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
928 + MAC_state = dev_sw_state->MAC_state;
929 + MACInfo = &MAC_state->MACInfo;
930 +
931 + for (i=0; i<AE531X_DEV_PER_MAC; i++) {
932 + if ((MAC_state->dev_sw_state[i]->dev) &&
933 + (MAC_state->dev_sw_state[i]->dev != dev_sw_state->dev)) {
934 + break;
935 + }
936 + }
937 +
938 + if (i < AE531X_DEV_PER_MAC) {
939 + /* Physical MAC is still in use */
940 + if (MAC_state->primary_dev == dev_sw_state->unit_on_MAC) {
941 + /*
942 + * If the primary_dev is being stopped
943 + * then we need to assign a new one.
944 + */
945 + MAC_state->primary_dev = i;
946 + }
947 + } else {
948 + /* Physical MAC is no longer in use */
949 + ae531x_MAC_shutdown(MAC_state);
950 + }
951 +
952 + dev_sw_state->dev = NULL;
953 +
954 + LEAVE();
955 + return 0;
956 +}
957 +
958 +/*******************************************************************************
959 +* ae531x_rxbuf_alloc - Allocate an skb to be associated with an RX descriptor.
960 +*
961 +* RETURNS: A pointer to the skb. Also returns a pointer to the underlying
962 +* buffer and the size of that buffer.
963 +*/
964 +void *
965 +ae531x_rxbuf_alloc(ae531x_MAC_t *MACInfo, char **rxBuffp, int *rxBuffSizep)
966 +{
967 + struct sk_buff *skb;
968 + char *rxBuff;
969 + int rxBuffSize;
970 +
971 + skb = dev_alloc_skb(AE531X_RX_BUF_SIZE);
972 + if (skb) {
973 + /* Add 2 to align the IP header on a DWORD boundary */
974 + skb_reserve(skb, RXBUFF_RESERVE + 2);
975 +
976 + rxBuffSize = skb_tailroom(skb);
977 + rxBuff = skb->tail;
978 +
979 + *rxBuffp = rxBuff;
980 + *rxBuffSizep = rxBuffSize;
981 +
982 + A_DATA_CACHE_INVAL(rxBuff, rxBuffSize);
983 + }
984 +
985 + return skb;
986 +}
987 +
988 +/*******************************************************************************
989 +* ae531x_swptr_free - Free the skb, if any, associated with a descriptor.
990 +*/
991 +void
992 +ae531x_swptr_free(VIRT_ADDR desc)
993 +{
994 + struct sk_buff *skb;
995 +
996 + skb = (struct sk_buff *)AE531X_DESC_SWPTR_GET(desc);
997 + if (skb) {
998 + AE531X_DESC_SWPTR_SET(desc, NULL);
999 + kfree_skb(skb);
1000 + }
1001 +}
1002 +
1003 +/*******************************************************************************
1004 +*
1005 +* ae531x_TxReap - the driver Tx completion routine.
1006 +*
1007 +* This routine reaps sk_buffs which have already been transmitted.
1008 +*
1009 +*/
1010 +static void
1011 +ae531x_TxReap(ae531x_MAC_state_t *MAC_state)
1012 +{
1013 + AE531X_QUEUE *txq;
1014 + VIRT_ADDR txDesc;
1015 + UINT32 cmdsts;
1016 + struct sk_buff *skb;
1017 + int reaped;
1018 + ae531x_MAC_t *MACInfo;
1019 + static int aeUselessReap = 0;
1020 +
1021 + ARRIVE();
1022 +
1023 + MACInfo = &MAC_state->MACInfo;
1024 + txq = &MACInfo->txQueue;
1025 + reaped = 0;
1026 +
1027 + while (1) {
1028 + txDesc = AE531X_QUEUE_ELE_NEXT_GET(txq, txq->reapDescAddr);
1029 + if (txDesc == txq->curDescAddr) {
1030 + break;
1031 + }
1032 +
1033 + cmdsts = AE531X_DESC_STATUS_GET(KSEG1ADDR(txDesc));
1034 + if (cmdsts & DescOwnByDma) {
1035 + break;
1036 + }
1037 +
1038 + /* Release sk_buff associated with completed transmit */
1039 + skb = (struct sk_buff *)AE531X_DESC_SWPTR_GET(txDesc);
1040 +
1041 + if (skb) {
1042 + kfree_skb(skb);
1043 + AE531X_DESC_SWPTR_SET(txDesc, NULL);
1044 + }
1045 +
1046 + /* Update statistics according to completed transmit desc */
1047 + if (cmdsts & DescTxErrors) {
1048 + AE531X_PRINT(AE531X_DEBUG_ERROR,
1049 + ("enetmac%d Tx prior error: 0x%8.8x <0x%8.8x> 0x%8.8x\n",
1050 + MACInfo->unit,
1051 + cmdsts,
1052 + DescTxErrors,
1053 + (int)txDesc));
1054 + MAC_state->stats.tx_errors++;
1055 + if (cmdsts & (DescTxLateCollision | DescTxExcCollisions)) {
1056 + MAC_state->stats.tx_aborted_errors++;
1057 + }
1058 + if (cmdsts & (DescTxLostCarrier | DescTxNoCarrier)) {
1059 + MAC_state->stats.tx_carrier_errors++;
1060 + }
1061 + } else {
1062 + MAC_state->stats.tx_bytes += AE531X_DESC_STATUS_RX_SIZE(cmdsts);
1063 + MAC_state->stats.tx_packets++;
1064 + }
1065 +
1066 + MAC_state->stats.collisions +=
1067 + ((cmdsts & DescTxCollMask) >> DescTxCollShift);
1068 +
1069 + txq->reapDescAddr = txDesc;
1070 + reaped++;
1071 + }
1072 +
1073 + if (reaped > 0) {
1074 + int i;
1075 +
1076 + AE531X_PRINT(AE531X_DEBUG_TX_REAP,
1077 + ("reaped %d\n", reaped));
1078 +
1079 + /*
1080 + * Re-start transmit queues for all ethernet devices
1081 + * associated with this MAC.
1082 + */
1083 + for (i=0; i<AE531X_DEV_PER_MAC; i++) {
1084 + if (MAC_state->dev_sw_state[i]->dev)
1085 + netif_start_queue(MAC_state->dev_sw_state[i]->dev);
1086 + }
1087 + } else {
1088 + aeUselessReap++;
1089 + }
1090 +
1091 + LEAVE();
1092 +}
1093 +
1094 +/*******************************************************************************
1095 +* ae531x_MAC_start_xmit sends a packet.
1096 +*/
1097 +static int
1098 +ae531x_MAC_start_xmit(struct sk_buff *skb, struct net_device *dev)
1099 +{
1100 + ae531x_dev_sw_state_t *dev_sw_state;
1101 + ae531x_MAC_state_t *MAC_state;
1102 + ae531x_MAC_t *MACInfo;
1103 + u32 buf;
1104 + u32 ctrlen;
1105 + u32 length;
1106 + int mtu;
1107 + int max_buf_size;
1108 + VIRT_ADDR txDesc;
1109 +
1110 + ARRIVE();
1111 +
1112 + dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
1113 + MAC_state = dev_sw_state->MAC_state;
1114 + MACInfo = &MAC_state->MACInfo;
1115 +
1116 + length = skb->len;
1117 +
1118 + /* Check if this port is up, else toss packet */
1119 + if (!MACInfo->port_is_up) {
1120 + buf = virt_to_bus(skb->data);
1121 + AE531X_PRINT(AE531X_DEBUG_ERROR,
1122 + ("eth%d Tx Down, dropping buf=0x%8.8x, length=0x%8.8x, skb=%p\n",
1123 + dev_sw_state->enetUnit, buf, length, (void *)skb));
1124 +
1125 + MAC_state->stats.tx_dropped++;
1126 + MAC_state->stats.tx_carrier_errors++;
1127 + goto dropFrame;
1128 + }
1129 +
1130 + if (ae531x_IsInResetMode(MACInfo)) {
1131 + AE531X_PRINT(AE531X_DEBUG_ERROR,
1132 + ("eth%d Tx: In Chip reset - drop frame\n",
1133 + dev_sw_state->enetUnit));
1134 +
1135 + MAC_state->stats.tx_dropped++;
1136 + MAC_state->stats.tx_aborted_errors++;
1137 + goto dropFrame;
1138 + }
1139 +
1140 + /* Check if we can transport this packet */
1141 + length = max((u32)60, length); /* total length */
1142 + mtu = dev->mtu;
1143 + max_buf_size = mtu + HLEN;
1144 + if (length > max_buf_size) {
1145 + AE531X_PRINT(AE531X_DEBUG_ERROR,
1146 + ("eth%d Tx: length %d too long. mtu=%d, trailer=%d\n",
1147 + dev_sw_state->enetUnit, length, mtu, PHY_TRAILER_SIZE));
1148 +
1149 + MAC_state->stats.tx_errors++;
1150 + MAC_state->stats.tx_aborted_errors++;
1151 +
1152 + goto dropFrame;
1153 + }
1154 +
1155 + /* Reap any old, completed Tx descriptors */
1156 + ae531x_TxReap(MAC_state);
1157 +
1158 + txDesc = MACInfo->txQueue.curDescAddr;
1159 + if (txDesc == MACInfo->txQueue.reapDescAddr) {
1160 + int i;
1161 +
1162 + AE531X_PRINT(AE531X_DEBUG_ERROR,
1163 + ("eth%d Tx: cannot get txDesc\n",
1164 + dev_sw_state->enetUnit));
1165 +
1166 + MAC_state->stats.tx_dropped++;
1167 + MAC_state->stats.tx_fifo_errors++;
1168 +
1169 + /*
1170 + * Stop transmit queues for any ethernet devices
1171 + * associated with this MAC.
1172 + */
1173 + for (i=0; i<AE531X_DEV_PER_MAC; i++) {
1174 + if (MAC_state->dev_sw_state[i]->dev)
1175 + netif_stop_queue(MAC_state->dev_sw_state[i]->dev);
1176 + }
1177 + goto dropFrame;
1178 + }
1179 +
1180 +#ifdef CONFIG_VENETDEV
1181 + {
1182 + struct sk_buff *newskb;
1183 +
1184 + if (skb_cloned(skb) || (skb_tailroom(skb) < PHY_TRAILER_SIZE)) {
1185 +#ifdef DEBUG_VENETDEV
1186 + if (skb_cloned(skb)) {
1187 + cloned_counter++;
1188 + if (skb_tailroom(skb) < PHY_TRAILER_SIZE) {
1189 + both_counter++;
1190 + }
1191 + } else {
1192 + expand_counter++;
1193 + }
1194 +#endif
1195 + newskb = skb_copy_expand(skb, 0, PHY_TRAILER_SIZE, GFP_ATOMIC);
1196 + if (newskb == NULL) {
1197 + goto dropFrame;
1198 + }
1199 +
1200 + dev_kfree_skb(skb);
1201 + skb = newskb;
1202 + }
1203 +
1204 + phySetDestinationPort(skb->data, length, dev_sw_state->isLAN);
1205 + skb_put(skb, PHY_TRAILER_SIZE);
1206 + length += PHY_TRAILER_SIZE;
1207 + }
1208 +#endif
1209 +
1210 + /* We won't fail now; so consume this descriptor */
1211 + AE531X_CONSUME_DESC((&MACInfo->txQueue));
1212 +
1213 + /* Update the descriptor */
1214 + buf = virt_to_bus(skb->data);
1215 + A_DATA_CACHE_FLUSH(skb->data, skb->len);
1216 + AE531X_DESC_BUFPTR_SET(txDesc, buf);
1217 + AE531X_DESC_SWPTR_SET(txDesc, skb);
1218 + ctrlen = AE531X_DESC_CTRLEN_GET(txDesc);
1219 + ctrlen = (ctrlen & (DescEndOfRing)) |
1220 + DescTxFirst |
1221 + DescTxLast |
1222 + DescTxIntEnable;
1223 +
1224 + ctrlen |= ((length << DescSize1Shift) & DescSize1Mask);
1225 +
1226 + AE531X_DESC_CTRLEN_SET(txDesc, ctrlen);
1227 + AE531X_DESC_STATUS_SET(txDesc, DescOwnByDma);
1228 +
1229 + AE531X_PRINT(AE531X_DEBUG_TX,
1230 + ("eth%d Tx: Desc=0x%8.8x, L=0x%8.8x, D=0x%8.8x, d=0x%8.8x, length=0x%8.8x\n",
1231 + dev_sw_state->enetUnit,
1232 + (UINT32)txDesc,
1233 + AE531X_DESC_CTRLEN_GET(txDesc),
1234 + buf,
1235 + AE531X_DESC_LNKBUF_GET(txDesc),
1236 + length));
1237 +
1238 + /* Must not use txDesc after this point */
1239 + A_DATA_CACHE_FLUSH_INVAL(txDesc, AE531X_DESC_SIZE);
1240 +
1241 + /* Alert DMA engine to resume Tx */
1242 + ae531x_WriteDmaReg(MACInfo, DmaTxPollDemand, 0);
1243 + sysWbFlush();
1244 +
1245 + MAC_state->stats.tx_packets++;
1246 + MAC_state->stats.tx_bytes += length;
1247 +
1248 + /* Tell upper layers to keep it coming */
1249 + dev->trans_start = jiffies;
1250 +
1251 + LEAVE();
1252 + return 0;
1253 +
1254 +dropFrame:
1255 + dev_kfree_skb(skb);
1256 +
1257 + LEAVE();
1258 + return 0;
1259 +}
1260 +
1261 +
1262 +/*******************************************************************************
1263 +* ae531x_MAC_tx_timeout handles transmit timeouts
1264 +*/
1265 +static void
1266 +ae531x_MAC_tx_timeout(struct net_device *dev)
1267 +{
1268 + ae531x_dev_sw_state_t *dev_sw_state;
1269 + ae531x_MAC_state_t *MAC_state;
1270 + ae531x_MAC_t *MACInfo;
1271 +
1272 + ARRIVE();
1273 +
1274 + dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
1275 + MAC_state = dev_sw_state->MAC_state;
1276 + MACInfo = &MAC_state->MACInfo;
1277 +
1278 + AE531X_PRINT(AE531X_DEBUG_ERROR,
1279 + ("enet%d: Tx timeout\n", dev_sw_state->enetUnit));
1280 +
1281 + ae531x_restart(MACInfo);
1282 +
1283 + LEAVE();
1284 +}
1285 +
1286 +
1287 +/*******************************************************************************
1288 +* ae531x_MAC_do_ioctl is a placeholder for future ioctls.
1289 +*/
1290 +static int
1291 +ae531x_MAC_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1292 +{
1293 + int rv;
1294 + ae531x_MAC_t *MACInfo;
1295 + struct ioctl_data {
1296 + u32 unit;
1297 + u32 addr;
1298 + u32 data;
1299 + } *req;
1300 + ae531x_dev_sw_state_t *dev_sw_state;
1301 + ae531x_MAC_state_t *MAC_state;
1302 +
1303 + ARRIVE();
1304 +
1305 + dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
1306 + MAC_state = dev_sw_state->MAC_state;
1307 + MACInfo = &MAC_state->MACInfo;
1308 +
1309 + req = (struct ioctl_data *)ifr->ifr_data;
1310 +
1311 + switch( cmd ) {
1312 + default:
1313 + AE531X_PRINT(AE531X_DEBUG_ERROR,
1314 + ("Unsupported ioctl: 0x%x\n", cmd));
1315 + rv = -EOPNOTSUPP;
1316 + }
1317 +
1318 + LEAVE();
1319 + return rv;
1320 +}
1321 +
1322 +/*******************************************************************************
1323 +* ae531x_MAC_set_mac_address sets a new hardware address for the device
1324 +*/
1325 +static int
1326 +ae531x_MAC_set_mac_address(struct net_device *dev, void *addr)
1327 +{
1328 + struct sockaddr *saddr = (struct sockaddr *)addr;
1329 +
1330 + /* update dev struct */
1331 + memcpy(dev->dev_addr, &saddr->sa_data[0], dev->addr_len);
1332 +
1333 + return 0;
1334 +}
1335 +
1336 +/******************************************************************************
1337 +* macAddrGet - Given a MACInfo pointer, return a pointer to an
1338 +* array of chars that holds the corresponding MAC address.
1339 +*/
1340 +char *macAddrGet(ae531x_MAC_t *MACInfo)
1341 +{
1342 + // return enet_mac_address_get(MACInfo->unit);
1343 + return ae531x_MAC_dev[MACInfo->unit]->dev_addr;
1344 +}
1345 +
1346 +static void
1347 +ae531x_MAC_setup_fntable(struct net_device *dev)
1348 +{
1349 + /* Set a default (should be overridden by software) */
1350 + u8 default_MAC_address[] = { 0x00, 0x03, 0x7f, 0xe0, 0x02, 0xbF };
1351 +
1352 + ARRIVE();
1353 +
1354 + dev->get_stats = ae531x_MAC_get_stats;
1355 + dev->open = ae531x_MAC_open;
1356 + dev->stop = ae531x_MAC_stop;
1357 + dev->hard_start_xmit = ae531x_MAC_start_xmit;
1358 + dev->do_ioctl = ae531x_MAC_do_ioctl;
1359 +#ifdef AR531X_NAPI
1360 + dev->poll = ae531x_MAC_poll;
1361 + dev->weight = 16;
1362 +#endif
1363 + dev->tx_timeout = ae531x_MAC_tx_timeout;
1364 + dev->features = NETIF_F_HW_CSUM |\
1365 + NETIF_F_HIGHDMA;
1366 + dev->set_mac_address = ae531x_MAC_set_mac_address;
1367 + dev->set_multicast_list = ae531x_MAC_set_rx_mode;
1368 +
1369 + /* Copy default MAC address into device descriptor */
1370 + memcpy(dev->dev_addr, default_MAC_address, dev->addr_len );
1371 +
1372 + LEAVE();
1373 +}
1374 +
1375 +/*
1376 + * ae531x_twisted_enet() returns 1 for chips where there is only one usable
1377 + * MAC, and that MAC is 1.
1378 + */
1379 +static BOOL
1380 +ae531x_twisted_enet(void)
1381 +{
1382 + int wisoc_revision;
1383 + int flash_bus_width;
1384 +
1385 + wisoc_revision = (sysRegRead(AR531X_REV) & AR531X_REV_MAJ) >>
1386 + AR531X_REV_MAJ_S;
1387 + if (wisoc_revision == AR531X_REV_MAJ_AR2313)
1388 + return TRUE;
1389 +
1390 + flash_bus_width = sysRegRead(AR531X_FLASHCTL0) & FLASHCTL_MWx16;
1391 +
1392 + if (flash_bus_width == 0) {
1393 + printk("Found AR2312-01\n");
1394 + return TRUE; /* AR2312-01 has 8 bit flash bus */
1395 + } else {
1396 + printk("Found AR2312-00\n");
1397 + return FALSE;
1398 + }
1399 +}
1400 +
1401 +int
1402 +ae531x_MAC_setup(void)
1403 +{
1404 + int i;
1405 + int next_dev;
1406 + int rev;
1407 + struct net_device *dev;
1408 + ae531x_dev_sw_state_t *dev_sw_state;
1409 + ae531x_MAC_state_t *MAC_state;
1410 + ae531x_MAC_t *MACInfo;
1411 +
1412 + ARRIVE();
1413 +
1414 +#if 0
1415 + /*
1416 + * This does not work since the AR2312 and AR5312 both have the same
1417 + * revision information in the CPU :-(
1418 + */
1419 + rev = (sysRegRead(AR531X_REV) & AR531X_REV_CHIP);
1420 +
1421 + if ((rev & AR531X_REV_MIN) == AR5312_REV_MIN_SINGLE_ENET) {
1422 + ar531x_num_enet_macs = 1;
1423 + } else {
1424 + ar531x_num_enet_macs = 2;
1425 + }
1426 +#else
1427 + /*
1428 + * Need to select the number of ethernet MACs based on the config
1429 + * information (sadly)
1430 + */
1431 +#ifdef CONFIG_AR5312
1432 + ar531x_num_enet_macs = 2;
1433 +#else
1434 + ar531x_num_enet_macs = 1;
1435 +#endif
1436 +#endif
1437 +
1438 + next_dev = 0;
1439 + for (i=0; i<ar531x_num_enet_macs; i++) {
1440 +
1441 + dev = ae531x_MAC_dev[next_dev] =
1442 + init_etherdev(NULL, sizeof(ae531x_dev_sw_state_t));
1443 +
1444 + if (dev == NULL) {
1445 + LEAVE();
1446 + return -1;
1447 + }
1448 +
1449 + ae531x_MAC_setup_fntable(dev);
1450 +
1451 + dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
1452 + dev_sw_state->enetUnit = next_dev;
1453 + dev_sw_state->unit_on_MAC = 0;
1454 + MAC_state = &per_MAC_info[i];
1455 + dev_sw_state->MAC_state = MAC_state;
1456 + MAC_state->dev_sw_state[AE531X_LAN_PORT] = dev_sw_state;
1457 + MAC_state->primary_dev = -1;
1458 +
1459 + next_dev++;
1460 +
1461 +#ifdef CONFIG_VENETDEV
1462 + {
1463 + ae531x_dev_sw_state_t *lan_dev_sw_state;
1464 +
1465 + lan_dev_sw_state = dev_sw_state;
1466 +
1467 + dev = ae531x_MAC_dev[next_dev] =
1468 + init_etherdev(NULL, sizeof(ae531x_dev_sw_state_t));
1469 +
1470 + if (dev == NULL) {
1471 + LEAVE();
1472 + return -1;
1473 + }
1474 +
1475 + ae531x_MAC_setup_fntable(dev);
1476 +
1477 + dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
1478 + dev_sw_state->enetUnit = next_dev;
1479 + dev_sw_state->unit_on_MAC = 1;
1480 + dev_sw_state->MAC_state = MAC_state;
1481 + MAC_state->dev_sw_state[AE531X_WAN_PORT] = dev_sw_state;
1482 + lan_dev_sw_state->isLAN = TRUE; /* enet0 is LAN */
1483 + dev_sw_state->isLAN = FALSE ; /* enet1 is WAN */
1484 +
1485 + next_dev++;
1486 + }
1487 +#endif
1488 +
1489 + /* Initialize per-MAC information */
1490 + MACInfo = &MAC_state->MACInfo;
1491 + MACInfo->unit = i;
1492 +
1493 + if (ar531x_num_enet_macs == 1) {
1494 + if (ae531x_twisted_enet()) {
1495 + MACInfo->macBase =
1496 + (u32)(PHYS_TO_K1(AR531X_ENET1)+AE531X_MAC_OFFSET);
1497 + MACInfo->dmaBase =
1498 + (u32)(PHYS_TO_K1(AR531X_ENET1)+AE531X_DMA_OFFSET);
1499 + MACInfo->phyBase =
1500 + (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET);
1501 + MAC_state->irq = AR531X_IRQ_ENET1_INTRS;
1502 + } else {
1503 + MACInfo->macBase =
1504 + (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_MAC_OFFSET);
1505 + MACInfo->dmaBase =
1506 + (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_DMA_OFFSET);
1507 + MACInfo->phyBase =
1508 + (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET);
1509 + MAC_state->irq = AR531X_IRQ_ENET0_INTRS;
1510 + }
1511 + } else {
1512 + if (MACInfo->unit == 0) {
1513 + MACInfo->macBase =
1514 + (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_MAC_OFFSET);
1515 + MACInfo->dmaBase =
1516 + (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_DMA_OFFSET);
1517 + MACInfo->phyBase =
1518 + (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET);
1519 + MAC_state->irq = AR531X_IRQ_ENET0_INTRS;
1520 + } else {
1521 + MACInfo->macBase =
1522 + (u32)(PHYS_TO_K1(AR531X_ENET1)+AE531X_MAC_OFFSET);
1523 + MACInfo->dmaBase =
1524 + (u32)(PHYS_TO_K1(AR531X_ENET1)+AE531X_DMA_OFFSET);
1525 + MACInfo->phyBase =
1526 + (u32)(PHYS_TO_K1(AR531X_ENET1)+AE531X_PHY_OFFSET);
1527 + MAC_state->irq = AR531X_IRQ_ENET1_INTRS;
1528 + }
1529 + }
1530 + MACInfo->OSinfo = (void *)MAC_state;
1531 + }
1532 +
1533 + LEAVE();
1534 + return 0;
1535 +}
1536 +
1537 +module_init(ae531x_MAC_setup);
1538 +
1539 diff -urN linux-2.4.32.new/arch/mips/ar531x/ae531xmac.c linux-2.4.32.new-eth/arch/mips/ar531x/ae531xmac.c
1540 --- linux-2.4.32.new/arch/mips/ar531x/ae531xmac.c 1970-01-01 01:00:00.000000000 +0100
1541 +++ linux-2.4.32.new-eth/arch/mips/ar531x/ae531xmac.c 2005-12-25 11:54:20.771271672 +0000
1542 @@ -0,0 +1,942 @@
1543 +/*
1544 + * This file is subject to the terms and conditions of the GNU General Public
1545 + * License. See the file "COPYING" in the main directory of this archive
1546 + * for more details.
1547 + *
1548 + * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
1549 + */
1550 +
1551 +
1552 +/*
1553 + * Ethernet driver for Atheros' ae531x ethernet MAC.
1554 + */
1555 +
1556 +#if linux
1557 +#include <linux/config.h>
1558 +#include <linux/types.h>
1559 +#include <linux/delay.h>
1560 +#include <linux/netdevice.h>
1561 +#include <linux/etherdevice.h>
1562 +#include <linux/init.h>
1563 +#include <asm/io.h>
1564 +
1565 +#include "ar531xlnx.h"
1566 +#endif /* linux */
1567 +
1568 +#include "ae531xreg.h"
1569 +#include "ae531xmac.h"
1570 +
1571 +int ae531x_MAC_debug = AE531X_DEBUG_ERROR;
1572 +
1573 +/*
1574 + * These externs are for functions that this layer relies on
1575 + * that have OS-dependent implementations.
1576 + */
1577 +extern UINT8 *macAddrGet(ae531x_MAC_t *MACInfo);
1578 +
1579 +/* Forward references to local functions */
1580 +static void ae531x_QueueDestroy(AE531X_QUEUE *q);
1581 +
1582 +
1583 +/******************************************************************************
1584 +*
1585 +* ae531x_ReadMacReg - read AE MAC register
1586 +*
1587 +* RETURNS: register value
1588 +*/
1589 +UINT32
1590 +ae531x_ReadMacReg(ae531x_MAC_t *MACInfo, UINT32 reg)
1591 +{
1592 + UINT32 addr = MACInfo->macBase+reg;
1593 + UINT32 data;
1594 +
1595 + data = RegRead(addr);
1596 + return data;
1597 +}
1598 +
1599 +
1600 +/******************************************************************************
1601 +*
1602 +* ae531x_WriteMacReg - write AE MAC register
1603 +*
1604 +* RETURNS: N/A
1605 +*/
1606 +void
1607 +ae531x_WriteMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data)
1608 +{
1609 + UINT32 addr = MACInfo->macBase+reg;
1610 +
1611 + RegWrite(data, addr);
1612 +}
1613 +
1614 +
1615 +/******************************************************************************
1616 +*
1617 +* ae531x_SetMacReg - set bits in AE MAC register
1618 +*
1619 +* RETURNS: N/A
1620 +*/
1621 +void
1622 +ae531x_SetMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val)
1623 +{
1624 + UINT32 addr = MACInfo->macBase+reg;
1625 + UINT32 data = RegRead(addr);
1626 +
1627 + data |= val;
1628 + RegWrite(data, addr);
1629 +}
1630 +
1631 +
1632 +/******************************************************************************
1633 +*
1634 +* ae531x_ClearMacReg - clear bits in AE MAC register
1635 +*
1636 +* RETURNS: N/A
1637 +*/
1638 +void
1639 +ae531x_ClearMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val)
1640 +{
1641 + UINT32 addr = MACInfo->macBase+reg;
1642 + UINT32 data = RegRead(addr);
1643 +
1644 + data &= ~val;
1645 + RegWrite(data, addr);
1646 +}
1647 +
1648 +
1649 +/******************************************************************************
1650 +*
1651 +* ae531x_ReadDmaReg - read AE DMA register
1652 +*
1653 +* RETURNS: register value
1654 +*/
1655 +UINT32
1656 +ae531x_ReadDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg)
1657 +{
1658 + UINT32 addr = MACInfo->dmaBase+reg;
1659 + UINT32 data = RegRead(addr);
1660 +
1661 + return data;
1662 +}
1663 +
1664 +
1665 +/******************************************************************************
1666 +*
1667 +* ae531x_WriteDmaReg - write AE DMA register
1668 +*
1669 +* RETURNS: N/A
1670 +*/
1671 +void
1672 +ae531x_WriteDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data)
1673 +{
1674 + UINT32 addr = MACInfo->dmaBase+reg;
1675 +
1676 + RegWrite(data, addr);
1677 +}
1678 +
1679 +
1680 +/******************************************************************************
1681 + *
1682 + * ae531x_AckIntr - clear interrupt bits in the status register.
1683 + * Note: Interrupt bits are *cleared* by writing a 1.
1684 + */
1685 +void
1686 +ae531x_AckIntr(ae531x_MAC_t *MACInfo, UINT32 data)
1687 +{
1688 + ae531x_WriteDmaReg(MACInfo, DmaStatus, data);
1689 +}
1690 +
1691 +
1692 +/******************************************************************************
1693 +*
1694 +* ae531x_SetDmaReg - set bits in an AE DMA register
1695 +*
1696 +* RETURNS: N/A
1697 +*/
1698 +void
1699 +ae531x_SetDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val)
1700 +{
1701 + UINT32 addr = MACInfo->dmaBase+reg;
1702 + UINT32 data = RegRead(addr);
1703 +
1704 + data |= val;
1705 + RegWrite(data, addr);
1706 +}
1707 +
1708 +
1709 +/******************************************************************************
1710 +*
1711 +* ae531x_ClearDmaReg - clear bits in an AE DMA register
1712 +*
1713 +* RETURNS: N/A
1714 +*/
1715 +void
1716 +ae531x_ClearDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val)
1717 +{
1718 + UINT32 addr = MACInfo->dmaBase+reg;
1719 + UINT32 data = RegRead(addr);
1720 +
1721 + data &= ~val;
1722 + RegWrite(data, addr);
1723 +}
1724 +
1725 +
1726 +/******************************************************************************
1727 +*
1728 +* ae531x_ReadMiiReg - read PHY registers via AE MAC Mii addr/data registers
1729 +*
1730 +* RETURNS: register value
1731 +*/
1732 +UINT32
1733 +ae531x_ReadMiiReg(UINT32 phyBase, UINT32 reg)
1734 +{
1735 + UINT32 data;
1736 + UINT32 addr = phyBase+reg;
1737 +
1738 + data = RegRead(addr);
1739 + return data;
1740 +}
1741 +
1742 +
1743 +/******************************************************************************
1744 +*
1745 +* ae531x_WriteMiiReg - write PHY registers via AE MAC Mii addr/data registers
1746 +*
1747 +* RETURNS: N/A
1748 +*/
1749 +void
1750 +ae531x_WriteMiiReg(UINT32 phyBase, UINT32 reg, UINT32 data)
1751 +{
1752 + UINT32 addr = phyBase+reg;
1753 +
1754 + RegWrite(data, addr);
1755 +}
1756 +
1757 +
1758 +/******************************************************************************
1759 +*
1760 +* ae531x_MiiRead - read AE Mii register
1761 +*
1762 +* RETURNS: register value
1763 +*/
1764 +UINT16
1765 +ae531x_MiiRead(UINT32 phyBase, UINT32 phyAddr, UINT8 reg)
1766 +{
1767 + UINT32 addr;
1768 + UINT16 data;
1769 +
1770 + addr = ((phyAddr << MiiDevShift) & MiiDevMask) | ((reg << MiiRegShift) & MiiRegMask);
1771 +
1772 + ae531x_WriteMiiReg(phyBase, MacMiiAddr, addr );
1773 + do {
1774 + /* nop */
1775 + } while ((ae531x_ReadMiiReg(phyBase, MacMiiAddr ) & MiiBusy) == MiiBusy);
1776 +
1777 + data = ae531x_ReadMiiReg(phyBase, MacMiiData) & 0xFFFF;
1778 +
1779 + return data;
1780 +}
1781 +
1782 +
1783 +/******************************************************************************
1784 +*
1785 +* ae531x_MiiWrite - write AE Mii register
1786 +*
1787 +* RETURNS: N/A
1788 +*/
1789 +void
1790 +ae531x_MiiWrite(UINT32 phyBase, UINT32 phyAddr, UINT8 reg, UINT16 data)
1791 +{
1792 + UINT32 addr;
1793 +
1794 + ae531x_WriteMiiReg(phyBase, MacMiiData, data );
1795 +
1796 + addr = ((phyAddr << MiiDevShift) & MiiDevMask) |
1797 + ((reg << MiiRegShift) & MiiRegMask) | MiiWrite;
1798 + ae531x_WriteMiiReg(phyBase, MacMiiAddr, addr );
1799 +
1800 + do {
1801 + /* nop */
1802 + } while ((ae531x_ReadMiiReg(phyBase, MacMiiAddr ) & MiiBusy) == MiiBusy);
1803 +}
1804 +
1805 +
1806 +/*******************************************************************************
1807 +* ae531x_BeginResetMode - enter a special "reset mode" in which
1808 +* -no interrupts are expected from the device
1809 +* -the device will not transmit nor receive
1810 +* -attempts to send or receive will return with an error and
1811 +* -the device will be reset at the next convenient opportunity.
1812 +*/
1813 +void
1814 +ae531x_BeginResetMode(ae531x_MAC_t *MACInfo)
1815 +{
1816 + /* Set the reset flag */
1817 + MACInfo->aeProcessRst = 1;
1818 +}
1819 +
1820 +
1821 +/*******************************************************************************
1822 +* ae531x_EndResetMode - exit the special "reset mode" entered
1823 +* earlier via a call to ae531x_BeginResetMode.
1824 +*/
1825 +void
1826 +ae531x_EndResetMode(ae531x_MAC_t *MACInfo)
1827 +{
1828 + MACInfo->aeProcessRst = 0;
1829 +}
1830 +
1831 +
1832 +/*******************************************************************************
1833 +* ae531x_IsInResetMode - determine whether or not the device is
1834 +* currently in "reset mode" (i.e. that a device reset is pending)
1835 +*/
1836 +BOOL
1837 +ae531x_IsInResetMode(ae531x_MAC_t *MACInfo)
1838 +{
1839 + return MACInfo->aeProcessRst;
1840 +}
1841 +
1842 +
1843 +/******************************************************************************
1844 +*
1845 +* ae531x_DmaRxStart - Start Rx
1846 +*
1847 +* RETURNS: N/A
1848 +*/
1849 +static void
1850 +ae531x_DmaRxStart(ae531x_MAC_t *MACInfo)
1851 +{
1852 + ae531x_SetDmaReg(MACInfo, DmaControl, DmaRxStart);
1853 + sysWbFlush();
1854 +}
1855 +
1856 +
1857 +/******************************************************************************
1858 +*
1859 +* ae531x_DmaRxStop - Stop Rx
1860 +*
1861 +* RETURNS: N/A
1862 +*/
1863 +void
1864 +ae531x_DmaRxStop(ae531x_MAC_t *MACInfo)
1865 +{
1866 + ae531x_ClearDmaReg(MACInfo, DmaControl, DmaRxStart);
1867 + sysWbFlush();
1868 +}
1869 +
1870 +
1871 +/******************************************************************************
1872 +*
1873 +* ae531x_DmaTxStart - Start Tx
1874 +*
1875 +* RETURNS: N/A
1876 +*/
1877 +void
1878 +ae531x_DmaTxStart(ae531x_MAC_t *MACInfo)
1879 +{
1880 + ae531x_SetDmaReg(MACInfo, DmaControl, DmaTxStart);
1881 + sysWbFlush();
1882 +}
1883 +
1884 +
1885 +/******************************************************************************
1886 +*
1887 +* ae531x_DmaTxStop - Stop Tx
1888 +*
1889 +* RETURNS: N/A
1890 +*/
1891 +void
1892 +ae531x_DmaTxStop(ae531x_MAC_t *MACInfo)
1893 +{
1894 + ae531x_ClearDmaReg(MACInfo, DmaControl, DmaTxStart);
1895 + sysWbFlush();
1896 +}
1897 +
1898 +
1899 +/******************************************************************************
1900 +*
1901 +* ae531x_DmaIntEnable - Enable DMA interrupts
1902 +*
1903 +* RETURNS: N/A
1904 +*/
1905 +void
1906 +ae531x_DmaIntEnable(ae531x_MAC_t *MACInfo)
1907 +{
1908 + ae531x_WriteDmaReg(MACInfo, DmaIntrEnb, DmaIntEnable);
1909 +}
1910 +
1911 +
1912 +/******************************************************************************
1913 +*
1914 +* ae531x_DmaIntDisable - Disable DMA interrupts
1915 +*
1916 +* RETURNS: N/A
1917 +*/
1918 +void
1919 +ae531x_DmaIntDisable(ae531x_MAC_t *MACInfo)
1920 +{
1921 + ae531x_WriteDmaReg(MACInfo, DmaIntrEnb, DmaIntDisable);
1922 +}
1923 +
1924 +
1925 +/******************************************************************************
1926 +*
1927 +* ae531x_DmaIntClear - Clear DMA interrupts
1928 +*
1929 +* RETURNS: N/A
1930 +*/
1931 +static void
1932 +ae531x_DmaIntClear(ae531x_MAC_t *MACInfo)
1933 +{
1934 + /* clear all interrupt requests */
1935 + ae531x_WriteDmaReg(MACInfo, DmaStatus,
1936 + ae531x_ReadDmaReg(MACInfo, DmaStatus));
1937 +}
1938 +
1939 +
1940 +/******************************************************************************
1941 +* Initialize generic queue data
1942 +*/
1943 +void
1944 +ae531x_QueueInit(AE531X_QUEUE *q, char *pMem, int count)
1945 +{
1946 + ARRIVE();
1947 + q->firstDescAddr = pMem;
1948 + q->lastDescAddr = (VIRT_ADDR)((UINT32)q->firstDescAddr +
1949 + (count - 1) * AE531X_QUEUE_ELE_SIZE);
1950 + q->curDescAddr = q->firstDescAddr;
1951 + q->count = count;
1952 + LEAVE();
1953 +}
1954 +
1955 +
1956 +/******************************************************************************
1957 +* ae531x_TxQueueCreate - create a circular queue of descriptors for Transmit
1958 +*/
1959 +static int
1960 +ae531x_TxQueueCreate(ae531x_MAC_t *MACInfo,
1961 + AE531X_QUEUE *q,
1962 + char *pMem,
1963 + int count)
1964 +{
1965 + int i;
1966 + VIRT_ADDR descAddr;
1967 +
1968 + ARRIVE();
1969 +
1970 + ae531x_QueueInit(q, pMem, count);
1971 + q->reapDescAddr = q->lastDescAddr;
1972 +
1973 + /* Initialize Tx buffer descriptors. */
1974 + for (i=0, descAddr=q->firstDescAddr;
1975 + i<count;
1976 + i++, descAddr=(VIRT_ADDR)((UINT32)descAddr + AE531X_QUEUE_ELE_SIZE))
1977 + {
1978 + /* Update the size, BUFPTR, and SWPTR fields */
1979 +
1980 + AE531X_DESC_STATUS_SET(descAddr, 0);
1981 + AE531X_DESC_CTRLEN_SET(descAddr, 0);
1982 +
1983 + AE531X_DESC_BUFPTR_SET(descAddr, (UINT32)0);
1984 + AE531X_DESC_LNKBUF_SET(descAddr, (UINT32)0);
1985 + AE531X_DESC_SWPTR_SET(descAddr, (void *)0);
1986 + } /* for each desc */
1987 +
1988 + /* Make the queue circular */
1989 + AE531X_DESC_CTRLEN_SET(q->lastDescAddr,
1990 + DescEndOfRing|AE531X_DESC_CTRLEN_GET(q->lastDescAddr));
1991 +
1992 + AE531X_PRINT(AE531X_DEBUG_RESET,
1993 + ("ethmac%d Txbuf begin = %x, end = %x\n",
1994 + MACInfo->unit,
1995 + (UINT32)q->firstDescAddr,
1996 + (UINT32)q->lastDescAddr));
1997 +
1998 + LEAVE();
1999 + return 0;
2000 +}
2001 +
2002 +
2003 +/******************************************************************************
2004 +* ae531x_RxQueueCreate - create a circular queue of Rx descriptors
2005 +*/
2006 +int
2007 +ae531x_RxQueueCreate(ae531x_MAC_t *MACInfo,
2008 + AE531X_QUEUE *q,
2009 + char *pMem,
2010 + int count)
2011 +{
2012 + int i;
2013 + VIRT_ADDR descAddr;
2014 +
2015 + ARRIVE();
2016 +
2017 + ae531x_QueueInit(q, pMem, count);
2018 + q->reapDescAddr = NULL;
2019 +
2020 +
2021 + /* Initialize Rx buffer descriptors */
2022 + for (i=0, descAddr=q->firstDescAddr;
2023 + i<count;
2024 + i++, descAddr=(VIRT_ADDR)((UINT32)descAddr + AE531X_QUEUE_ELE_SIZE))
2025 + {
2026 + void *swptr;
2027 + char *rxBuffer;
2028 + int rxBufferSize;
2029 +
2030 + swptr = ae531x_rxbuf_alloc(MACInfo, &rxBuffer, &rxBufferSize);
2031 + if (swptr == NULL) {
2032 + AE531X_PRINT(AE531X_DEBUG_RESET,
2033 + ("ethmac%d RX queue: ae531x_rxbuf_alloc failed\n",
2034 + MACInfo->unit));
2035 + ae531x_QueueDestroy(q);
2036 + return -1;
2037 + }
2038 + AE531X_DESC_SWPTR_SET(descAddr, swptr);
2039 +
2040 + AE531X_DESC_STATUS_SET(descAddr, DescOwnByDma);
2041 + AE531X_DESC_CTRLEN_SET(descAddr, rxBufferSize);
2042 + AE531X_DESC_BUFPTR_SET(descAddr, virt_to_bus(rxBuffer));
2043 + AE531X_DESC_LNKBUF_SET(descAddr, (UINT32)0);
2044 + } /* for each desc */
2045 +
2046 + /* Make the queue circular */
2047 + AE531X_DESC_CTRLEN_SET(q->lastDescAddr,
2048 + DescEndOfRing|AE531X_DESC_CTRLEN_GET(q->lastDescAddr));
2049 +
2050 + AE531X_PRINT(AE531X_DEBUG_RESET,
2051 + ("ethmac%d Rxbuf begin = %x, end = %x\n",
2052 + MACInfo->unit,
2053 + (UINT32)q->firstDescAddr,
2054 + (UINT32)q->lastDescAddr));
2055 +
2056 + LEAVE();
2057 + return 0;
2058 +}
2059 +
2060 +
2061 +/******************************************************************************
2062 +* ae531x_QueueDestroy -- Free all buffers and descriptors associated
2063 +* with a queue.
2064 +*/
2065 +static void
2066 +ae531x_QueueDestroy(AE531X_QUEUE *q)
2067 +{
2068 + int i;
2069 + int count;
2070 + VIRT_ADDR descAddr;
2071 +
2072 + ARRIVE();
2073 +
2074 + count = q->count;
2075 +
2076 + for (i=0, descAddr=q->firstDescAddr;
2077 + i<count;
2078 + i++, descAddr=(VIRT_ADDR)((UINT32)descAddr + AE531X_QUEUE_ELE_SIZE)) {
2079 +
2080 + AE531X_DESC_STATUS_SET(descAddr, 0);
2081 + AE531X_DESC_CTRLEN_SET(descAddr, 0);
2082 + AE531X_DESC_BUFPTR_SET(descAddr, (UINT32)0);
2083 + AE531X_DESC_LNKBUF_SET(descAddr, (UINT32)0);
2084 +
2085 + ae531x_swptr_free(descAddr); /* Free OS-specific software pointer */
2086 + }
2087 +
2088 + LEAVE();
2089 +}
2090 +
2091 +static void
2092 +ae531x_TxQueueDestroy(ae531x_MAC_t *MACInfo)
2093 +{
2094 + ae531x_QueueDestroy(&MACInfo->txQueue);
2095 +}
2096 +
2097 +static void
2098 +ae531x_RxQueueDestroy(ae531x_MAC_t *MACInfo)
2099 +{
2100 + ae531x_QueueDestroy(&MACInfo->rxQueue);
2101 +}
2102 +
2103 +
2104 +/******************************************************************************
2105 +* ae531x_AllocateQueues - Allocate receive and transmit queues
2106 +*/
2107 +int
2108 +ae531x_AllocateQueues(ae531x_MAC_t *MACInfo)
2109 +{
2110 + size_t QMemSize;
2111 + char *pTxBuf = NULL;
2112 + char *pRxBuf = NULL;
2113 +
2114 + ARRIVE();
2115 +
2116 + MACInfo->txDescCount = AE531X_TX_DESC_COUNT_DEFAULT;
2117 + QMemSize = AE531X_QUEUE_ELE_SIZE * MACInfo->txDescCount;
2118 + pTxBuf = MALLOC(QMemSize);
2119 + if (pTxBuf == NULL) {
2120 + AE531X_PRINT(AE531X_DEBUG_RESET,
2121 + ("ethmac%d Failed to allocate TX queue\n", MACInfo->unit));
2122 + goto AllocQFail;
2123 + }
2124 +
2125 + if (ae531x_TxQueueCreate(MACInfo, &MACInfo->txQueue, pTxBuf,
2126 + MACInfo->txDescCount) < 0)
2127 + {
2128 + AE531X_PRINT(AE531X_DEBUG_RESET,
2129 + ("ethmac%d Failed to create TX queue\n", MACInfo->unit));
2130 + goto AllocQFail;
2131 + }
2132 +
2133 + MACInfo->rxDescCount = AE531X_RX_DESC_COUNT_DEFAULT;
2134 + QMemSize = AE531X_QUEUE_ELE_SIZE * MACInfo->rxDescCount;
2135 + pRxBuf = MALLOC(QMemSize);
2136 + if (pRxBuf == NULL) {
2137 + AE531X_PRINT(AE531X_DEBUG_RESET,
2138 + ("ethmac%d Failed to allocate RX queue\n", MACInfo->unit));
2139 + goto AllocQFail;
2140 + }
2141 +
2142 + if (ae531x_RxQueueCreate(MACInfo, &MACInfo->rxQueue, pRxBuf,
2143 + MACInfo->rxDescCount) < 0)
2144 + {
2145 + AE531X_PRINT(AE531X_DEBUG_RESET,
2146 + ("ethmac%d Failed to create RX queue\n", MACInfo->unit));
2147 + goto AllocQFail;
2148 + }
2149 +
2150 + AE531X_PRINT(AE531X_DEBUG_RESET,
2151 + ("ethmac%d Memory setup complete.\n", MACInfo->unit));
2152 +
2153 + LEAVE();
2154 + return 0;
2155 +
2156 +AllocQFail:
2157 + MACInfo->txDescCount = 0; /* sanity */
2158 + MACInfo->rxDescCount = 0; /* sanity */
2159 +
2160 + if (pTxBuf) {
2161 + FREE(pTxBuf);
2162 + }
2163 + if (pRxBuf) {
2164 + FREE(pRxBuf);
2165 + }
2166 +
2167 + LEAVE();
2168 + return -1;
2169 +}
2170 +
2171 +
2172 +/******************************************************************************
2173 +*
2174 +* ae531x_FreeQueues - Free Transmit & Receive queues
2175 +*/
2176 +void
2177 +ae531x_FreeQueues(ae531x_MAC_t *MACInfo)
2178 +{
2179 + ae531x_TxQueueDestroy(MACInfo);
2180 + FREE(MACInfo->txQueue.firstDescAddr);
2181 +
2182 + ae531x_RxQueueDestroy(MACInfo);
2183 + FREE(MACInfo->rxQueue.firstDescAddr);
2184 +}
2185 +
2186 +/******************************************************************************
2187 +*
2188 +* ae531x_DmaReset - Reset DMA and TLI controllers
2189 +*
2190 +* RETURNS: N/A
2191 +*/
2192 +void
2193 +ae531x_DmaReset(ae531x_MAC_t *MACInfo)
2194 +{
2195 + int i;
2196 + UINT32 descAddr;
2197 +
2198 + ARRIVE();
2199 +
2200 + /* Disable device interrupts prior to any errors during stop */
2201 + intDisable(MACInfo->ilevel);
2202 +
2203 + /* Disable MAC rx and tx */
2204 + ae531x_ClearMacReg(MACInfo, MacControl, (MacRxEnable | MacTxEnable));
2205 +
2206 + /* Reset dma controller */
2207 + ae531x_WriteDmaReg(MACInfo, DmaBusMode, DmaResetOn);
2208 +
2209 + /* Delay 2 usec */
2210 + sysUDelay(2);
2211 +
2212 + /* Flush the rx queue */
2213 + descAddr = (UINT32)MACInfo->rxQueue.firstDescAddr;
2214 + MACInfo->rxQueue.curDescAddr = MACInfo->rxQueue.firstDescAddr;
2215 + for (i=0;
2216 + i<(MACInfo->rxDescCount);
2217 + i++, descAddr += AE531X_QUEUE_ELE_SIZE) {
2218 + AE531X_DESC_STATUS_SET(descAddr, DescOwnByDma);
2219 + }
2220 +
2221 + /* Flush the tx queue */
2222 + descAddr = (UINT32)MACInfo->txQueue.firstDescAddr;
2223 + MACInfo->txQueue.curDescAddr = MACInfo->txQueue.firstDescAddr;
2224 + MACInfo->txQueue.reapDescAddr = MACInfo->txQueue.lastDescAddr;
2225 + for (i=0;
2226 + i<(MACInfo->txDescCount);
2227 + i++, descAddr += AE531X_QUEUE_ELE_SIZE) {
2228 + AE531X_DESC_STATUS_SET (descAddr, 0);
2229 + }
2230 +
2231 + /* Set init register values */
2232 + ae531x_WriteDmaReg(MACInfo, DmaBusMode, DmaBusModeInit);
2233 +
2234 + /* Install the first Tx and Rx queues on the device */
2235 + ae531x_WriteDmaReg(MACInfo, DmaRxBaseAddr,
2236 + (UINT32)MACInfo->rxQueue.firstDescAddr);
2237 + ae531x_WriteDmaReg(MACInfo, DmaTxBaseAddr,
2238 + (UINT32)MACInfo->txQueue.firstDescAddr);
2239 +
2240 + ae531x_WriteDmaReg(MACInfo, DmaControl, DmaStoreAndForward);
2241 +
2242 + ae531x_WriteDmaReg(MACInfo, DmaIntrEnb, DmaIntDisable);
2243 +
2244 + AE531X_PRINT(AE531X_DEBUG_RESET,
2245 + ("ethmac%d: DMA RESET!\n", MACInfo->unit));
2246 +
2247 + /* Turn on device interrupts -- enable most errors */
2248 + ae531x_DmaIntClear(MACInfo); /* clear interrupt requests */
2249 + ae531x_DmaIntEnable(MACInfo); /* enable interrupts */
2250 + /* Enable receive interrupts separately (they are not part
2251 + * of the main group since they are enabled & disabled by
2252 + * the polling routine.
2253 + */
2254 + ae531x_SetDmaReg(MACInfo, DmaIntrEnb,
2255 + (DmaIntRxNoBuffer | DmaIntRxCompleted));
2256 +
2257 + ae531x_EndResetMode(MACInfo);
2258 +
2259 + intEnable(MACInfo->ilevel);
2260 +
2261 + LEAVE();
2262 +}
2263 +
2264 +
2265 +/******************************************************************************
2266 +*
2267 +* ae531x_MACAddressSet - Set the ethernet address
2268 +*
2269 +* Sets the ethernet address according to settings in flash.
2270 +*
2271 +* RETURNS: void
2272 +*/
2273 +static void
2274 +ae531x_MACAddressSet(ae531x_MAC_t *MACInfo)
2275 +{
2276 + unsigned int data;
2277 + UINT8 *macAddr;
2278 +
2279 + ARRIVE();
2280 +
2281 + macAddr = macAddrGet(MACInfo);
2282 +
2283 + /* set our MAC address */
2284 + data = (macAddr[5]<<8) | macAddr[4];
2285 + ae531x_WriteMacReg(MACInfo, MacAddrHigh, data );
2286 +
2287 + data = (macAddr[3]<<24) | (macAddr[2]<<16) | (macAddr[1]<<8) | macAddr[0];
2288 + ae531x_WriteMacReg(MACInfo, MacAddrLow, data );
2289 +
2290 + AE531X_PRINT(AE531X_DEBUG_RESET,
2291 + ("ethmac%d Verify MAC address %8.8X %8.8X \n",
2292 + MACInfo->unit,
2293 + ae531x_ReadMacReg(MACInfo, MacAddrLow),
2294 + ae531x_ReadMacReg(MACInfo, MacAddrHigh)));
2295 +
2296 + AE531X_PRINT(AE531X_DEBUG_RESET,
2297 + (" sb = %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
2298 + 0xff&macAddr[0],
2299 + 0xff&macAddr[1],
2300 + 0xff&macAddr[2],
2301 + 0xff&macAddr[3],
2302 + 0xff&macAddr[4],
2303 + 0xff&macAddr[5]));
2304 + LEAVE();
2305 +}
2306 +
2307 +
2308 +/******************************************************************************
2309 +*
2310 +* ae_SetMACFromPhy - read Phy settings and update Mac
2311 +* with current duplex and speed.
2312 +*
2313 +* RETURNS:
2314 +*/
2315 +static void
2316 +ae531x_SetMACFromPhy(ae531x_MAC_t *MACInfo)
2317 +{
2318 + UINT32 macCtl;
2319 + BOOL fullDuplex;
2320 +
2321 + ARRIVE();
2322 +
2323 + /* Get duplex mode from Phy */
2324 + fullDuplex = phyIsFullDuplex(MACInfo->unit);
2325 +
2326 + /* Flag is set for full duplex mode, else cleared */
2327 + macCtl = ae531x_ReadMacReg(MACInfo, MacControl);
2328 +
2329 + if (fullDuplex) {
2330 + /* set values of control registers */
2331 + macCtl &= ~MacDisableRxOwn;
2332 + macCtl |= MacFullDuplex;
2333 + ae531x_WriteMacReg(MACInfo, MacControl, macCtl);
2334 + ae531x_WriteMacReg(MACInfo, MacFlowControl, MacFlowControlInitFdx);
2335 +#if 0
2336 + printk ("[Full Duplex] CTRL=%#x FLOW=%#x\n", macCtl,
2337 + MacFlowControlInitFdx);
2338 +#endif
2339 + } else {
2340 + /* set values of control registers */
2341 + ae531x_WriteMacReg(MACInfo, MacFlowControl, MacFlowControlInitHdx);
2342 + macCtl |= MacDisableRxOwn;
2343 + macCtl &= ~MacFullDuplex;
2344 + ae531x_WriteMacReg(MACInfo, MacControl, macCtl);
2345 +#if 0
2346 + printk ("[Half Duplex] CTRL=%#x FLOW=%#x\n", macCtl,
2347 + MacFlowControlInitHdx);
2348 +#endif
2349 + }
2350 +
2351 + LEAVE();
2352 +}
2353 +
2354 +
2355 +/******************************************************************************
2356 +* ae531x_MACReset -- sets MAC address and duplex.
2357 +*/
2358 +void
2359 +ae531x_MACReset(ae531x_MAC_t *MACInfo)
2360 +{
2361 + ae531x_MACAddressSet(MACInfo);
2362 +
2363 + ae531x_SetMACFromPhy(MACInfo);
2364 +}
2365 +
2366 +
2367 +/******************************************************************************
2368 +* ae531x_EnableComm -- enable Transmit and Receive
2369 +*/
2370 +void
2371 +ae531x_EnableComm(ae531x_MAC_t *MACInfo)
2372 +{
2373 + ae531x_SetMacReg(MACInfo, MacControl, (MacRxEnable | MacTxEnable));
2374 + ae531x_DmaRxStart(MACInfo); /* start receiver */
2375 + ae531x_DmaTxStart(MACInfo); /* start transmitter */
2376 +}
2377 +
2378 +
2379 +/******************************************************************************
2380 +* ae531x_DisableComm -- disable Transmit and Receive
2381 +*/
2382 +void
2383 +ae531x_DisableComm(ae531x_MAC_t *MACInfo)
2384 +{
2385 + ae531x_ClearMacReg(MACInfo, MacControl, (MacRxEnable | MacTxEnable));
2386 +}
2387 +
2388 +
2389 +/******************************************************************************
2390 +* ae531x_reset -- Cold reset ethernet interface
2391 +*/
2392 +void
2393 +ae531x_reset(ae531x_MAC_t *MACInfo)
2394 +{
2395 + UINT32 mask = 0;
2396 + UINT32 regtmp;
2397 +
2398 + if (ar531x_num_enet_macs == 2) {
2399 + if (MACInfo->unit == 0) {
2400 + mask = AR531X_RESET_ENET0 | AR531X_RESET_EPHY0;
2401 + } else {
2402 + mask = AR531X_RESET_ENET1 | AR531X_RESET_EPHY1;
2403 + }
2404 + } else {
2405 + mask = AR531X_RESET_ENET0 | AR531X_RESET_EPHY0 |
2406 + AR531X_RESET_ENET1 | AR531X_RESET_EPHY1;
2407 + }
2408 +
2409 + /* Put into reset */
2410 + regtmp = sysRegRead(AR531X_RESET);
2411 + sysRegWrite(AR531X_RESET, regtmp | mask);
2412 + sysMsDelay(15);
2413 +
2414 + /* Pull out of reset */
2415 + regtmp = sysRegRead(AR531X_RESET);
2416 + sysRegWrite(AR531X_RESET, regtmp & ~mask);
2417 + sysUDelay(25);
2418 +
2419 + /* Enable */
2420 + if (ar531x_num_enet_macs == 2) {
2421 + if (MACInfo->unit == 0) {
2422 + mask = AR531X_ENABLE_ENET0;
2423 + } else {
2424 + mask = AR531X_ENABLE_ENET1;
2425 + }
2426 + } else {
2427 + mask = AR531X_ENABLE_ENET0 | AR531X_ENABLE_ENET1;
2428 + }
2429 + regtmp = sysRegRead(AR531X_ENABLE);
2430 + sysRegWrite(AR531X_ENABLE, regtmp | mask);
2431 +}
2432 +
2433 +
2434 +/******************************************************************************
2435 +* ae531x_unitLinkLost -- Called from PHY layer to notify the MAC layer
2436 +* that there are no longer any live links associated with a MAC.
2437 +*/
2438 +void
2439 +ae531x_unitLinkLost(int ethUnit)
2440 +{
2441 + AE531X_PRINT(AE531X_DEBUG_LINK_CHANGE,
2442 + ("enetmac%d link down\n", ethUnit));
2443 +}
2444 +
2445 +
2446 +/******************************************************************************
2447 +* ae531x_unitLinkGained -- Called from PHY layer to notify the MAC layer
2448 +* that there are 1 or more live links associated with a MAC.
2449 +*/
2450 +void
2451 +ae531x_unitLinkGained(int ethUnit)
2452 +{
2453 + AE531X_PRINT(AE531X_DEBUG_LINK_CHANGE,
2454 + ("enet%d link up\n", ethUnit));
2455 +}
2456 +
2457 +/******************************************************************************
2458 +* ae531x_ethMacDefault -- Called from PHY layer to determine the default
2459 +* ethernet MAC. On some "twisted" platforms, the only usable MAC is 1,
2460 +* while on others the usable MAC is 0. Future boards may allow both MACs
2461 +* to be used; in this case, return -1 to indicate that there IS NO default
2462 +* MAC.
2463 +*
2464 +* Note: one some AR2312 platforms the PHY needs to be accessed through
2465 +* MAC 0, even though the MAC itself is addressed through MAC 1. Since this
2466 +* function is used by the PHY layer to determine which MAC it should use,
2467 +* the twisted case is limited to the one where the PHY is actually addressed
2468 +* through MAC 1 rather than MAC 0.
2469 +*/
2470 +int
2471 +ae531x_ethMacDefault(void)
2472 +{
2473 + /*
2474 + * Where there are two MACs, there is no real default
2475 + */
2476 + if (ar531x_num_enet_macs == 2)
2477 + return -1;
2478 +
2479 + /*
2480 + * All single MAC platforms seem to address the PHY through MAC 0,
2481 + * even when they use MAC 1 for the actual MAC functions.
2482 + */
2483 + return 0;
2484 +}
2485 diff -urN linux-2.4.32.new/arch/mips/ar531x/ae531xmac.h linux-2.4.32.new-eth/arch/mips/ar531x/ae531xmac.h
2486 --- linux-2.4.32.new/arch/mips/ar531x/ae531xmac.h 1970-01-01 01:00:00.000000000 +0100
2487 +++ linux-2.4.32.new-eth/arch/mips/ar531x/ae531xmac.h 2005-12-25 11:54:20.819264376 +0000
2488 @@ -0,0 +1,208 @@
2489 +/*
2490 + * This file is subject to the terms and conditions of the GNU General Public
2491 + * License. See the file "COPYING" in the main directory of this archive
2492 + * for more details.
2493 + *
2494 + * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
2495 + */
2496 +
2497 +/*
2498 + * See README to understand the decomposition of the ethernet driver.
2499 + *
2500 + * This file contains OS-independent pure software definitions for
2501 + * ethernet support on the AR531X platform.
2502 + */
2503 +
2504 +#ifndef _AE531XMAC_H_
2505 +#define _AE531XMAC_H_
2506 +
2507 +/*
2508 + * DEBUG switches to control verbosity.
2509 + * Just modify the value of ae531x_MAC_debug.
2510 + */
2511 +#define AE531X_DEBUG_ALL 0xffffffff
2512 +#define AE531X_DEBUG_ERROR 0x00000001 /* Unusual conditions and Errors */
2513 +#define AE531X_DEBUG_ARRIVE 0x00000002 /* Arrive into a function */
2514 +#define AE531X_DEBUG_LEAVE 0x00000004 /* Leave a function */
2515 +#define AE531X_DEBUG_RESET 0x00000008 /* Reset */
2516 +#define AE531X_DEBUG_TX 0x00000010 /* Transmit */
2517 +#define AE531X_DEBUG_TX_REAP 0x00000020 /* Transmit Descriptor Reaping */
2518 +#define AE531X_DEBUG_RX 0x00000040 /* Receive */
2519 +#define AE531X_DEBUG_RX_STOP 0x00000080 /* Receive Early Stop */
2520 +#define AE531X_DEBUG_INT 0x00000100 /* Interrupts */
2521 +#define AE531X_DEBUG_LINK_CHANGE 0x00000200 /* PHY Link status changed */
2522 +
2523 +extern int ae531x_MAC_debug;
2524 +
2525 +extern int ar531x_num_enet_macs;
2526 +
2527 +#define AE531X_PRINT(FLG, X) \
2528 +{ \
2529 + if (ae531x_MAC_debug & (FLG)) { \
2530 + DEBUG_PRINTF("%s#%d:%s ", \
2531 + __FILE__, \
2532 + __LINE__, \
2533 + __FUNCTION__); \
2534 + DEBUG_PRINTF X; \
2535 + } \
2536 +}
2537 +
2538 +#define ARRIVE() AE531X_PRINT(AE531X_DEBUG_ARRIVE, ("Arrive{\n"))
2539 +#define LEAVE() AE531X_PRINT(AE531X_DEBUG_LEAVE, ("}Leave\n"))
2540 +
2541 +#define RegRead(addr) \
2542 + (*(volatile unsigned int *)(addr))
2543 +
2544 +#define RegWrite(val,addr) \
2545 + ((*(volatile unsigned int *)(addr)) = (val))
2546 +
2547 +/*****************************************************************
2548 + * Phy code is broken out into a separate layer, so that different
2549 + * PHY hardware can easily be supported.
2550 + *
2551 + * These functions are provided by the PHY layer for use by the MAC layer.
2552 + * phySetup -- Set phy hardware appropriately for a MAC unit
2553 + *
2554 + * phyCheckStatusChange -- Look for dropped/initiated links on any
2555 + * phy port associated with a MAC unit
2556 + *
2557 + * phyIsSpeed100 -- Determines whether or not a PHY is up and
2558 + * running at 100Mbit
2559 + *
2560 + * phyIsFullDuplex -- Determines whether or not a PHY is up and
2561 + * running in Full Duplex mode
2562 + *
2563 + */
2564 +#ifdef CONFIG_MARVELL_ENET_PHY
2565 +/*
2566 + * Mapping of generic phy APIs to Marvell Ethernet Switch phy functions.
2567 + */
2568 +#include "mvPhy.h"
2569 +#define phySetup(ethUnit, phyBase) mv_phySetup((ethUnit), (phyBase))
2570 +#define phyCheckStatusChange(ethUnit) mv_phyCheckStatusChange(ethUnit)
2571 +#define phyIsSpeed100(ethUnit) mv_phyIsSpeed100(ethUnit)
2572 +#define phyIsFullDuplex(ethUnit) mv_phyIsFullDuplex(ethUnit)
2573 +
2574 +#ifdef CONFIG_VENETDEV
2575 +#define PHY_TRAILER_SIZE MV_PHY_TRAILER_SIZE
2576 +extern int mv_phyDetermineSource(char *data, int len);
2577 +extern void mv_phySetDestinationPort(char *data, int len, int fromLAN);
2578 +#define phyDetermineSource(data, len) mv_phyDetermineSource((data), (len))
2579 +#define phySetDestinationPort(data, len, fromLAN) mv_phySetDestinationPort((data), (len), (fromLAN))
2580 +#else
2581 +#define PHY_TRAILER_SIZE 0
2582 +#endif
2583 +#endif /* CONFIG_MARVELL_ENET_PHY */
2584 +
2585 +#if defined(CONFIG_KENDIN_ENET_PHY) || defined(CONFIG_REALTEK_ENET_PHY)
2586 +/*
2587 + * Mapping of generic phy APIs to Kendin KS8721B and RealTek RTL8201BL phys.
2588 + */
2589 +#include "rtPhy.h"
2590 +#define phySetup(ethUnit, phyBase) rt_phySetup((ethUnit), (phyBase))
2591 +#define phyCheckStatusChange(ethUnit) rt_phyCheckStatusChange(ethUnit)
2592 +#define phyIsSpeed100(ethUnit) rt_phyIsSpeed100(ethUnit)
2593 +#define phyIsFullDuplex(ethUnit) rt_phyIsFullDuplex(ethUnit)
2594 +#endif
2595 +
2596 +#if !defined(PHY_TRAILER_SIZE)
2597 +#define PHY_TRAILER_SIZE 0
2598 +#endif
2599 +
2600 +/*****************************************************************
2601 + * MAC-independent interface to be used by PHY code
2602 + *
2603 + * These functions are provided by the MAC layer for use by the PHY layer.
2604 + */
2605 +#define phyRegRead ae531x_MiiRead
2606 +#define phyRegWrite ae531x_MiiWrite
2607 +#define phyLinkLost(ethUnit) ae531x_unitLinkLost(ethUnit)
2608 +#define phyLinkGained(ethUnit) ae531x_unitLinkGained(ethUnit)
2609 +#define phyEthMacDefault() ae531x_ethMacDefault()
2610 +
2611 +void ae531x_unitLinkLost(int unit);
2612 +void ae531x_unitLinkGained(int unit);
2613 +int ae531x_ethMacDefault(void);
2614 +
2615 +
2616 +/* RXBUFF_RESERVE enables building header on WLAN-side in place */
2617 +#define RXBUFF_RESERVE 96
2618 +#define ETH_CRC_LEN 4
2619 +
2620 +/*****************************************************************
2621 + * Descriptor queue
2622 + */
2623 +typedef struct ae531x_queue {
2624 + VIRT_ADDR firstDescAddr; /* descriptor array address */
2625 + VIRT_ADDR lastDescAddr; /* last descriptor address */
2626 + VIRT_ADDR curDescAddr; /* current descriptor address */
2627 + VIRT_ADDR reapDescAddr; /* current tail of tx descriptors reaped */
2628 + UINT16 count; /* number of elements */
2629 +} AE531X_QUEUE;
2630 +
2631 +/* Given a descriptor, return the next one in a circular list */
2632 +#define AE531X_QUEUE_ELE_NEXT_GET(q, descAddr) \
2633 + ((descAddr) == (q)->lastDescAddr) ? (q)->firstDescAddr : \
2634 + (VIRT_ADDR)((UINT32)(descAddr) + AE531X_QUEUE_ELE_SIZE)
2635 +
2636 +/* Move the "current descriptor" forward to the next one */
2637 +#define AE531X_CONSUME_DESC(q) \
2638 + q->curDescAddr = AE531X_QUEUE_ELE_NEXT_GET(q, q->curDescAddr)
2639 +
2640 +/*****************************************************************
2641 + * Per-ethernet-MAC OS-independent information
2642 + */
2643 +typedef struct ae531x_MAC_s {
2644 + u32 unit; /* MAC unit ID */
2645 + u32 macBase; /* MAC base address */
2646 + u32 dmaBase; /* DMA base address */
2647 + u32 phyBase; /* PHY base address */
2648 + AE531X_QUEUE txQueue; /* Transmit descriptor queue */
2649 + AE531X_QUEUE rxQueue; /* Receive descriptor queue */
2650 + UINT16 txDescCount; /* Transmit descriptor count */
2651 + UINT16 rxDescCount; /* Receive descriptor count */
2652 + BOOL aeProcessRst; /* flag to indicate reset in progress */
2653 + BOOL port_is_up; /* flag to indicate port is up */
2654 + void *OSinfo; /* OS-dependent data */
2655 +} ae531x_MAC_t;
2656 +
2657 +#define AE531X_TX_DESC_COUNT_DEFAULT 64 /* Transmit descriptors */
2658 +#define AE531X_RX_DESC_COUNT_DEFAULT 64 /* Receive descriptors */
2659 +
2660 +
2661 +/*****************************************************************
2662 + * Interfaces exported by the OS-independent MAC layer
2663 + */
2664 +void ae531x_BeginResetMode(ae531x_MAC_t *MACInfo);
2665 +void ae531x_EndResetMode(ae531x_MAC_t *MACInfo);
2666 +BOOL ae531x_IsInResetMode(ae531x_MAC_t *MACInfo);
2667 +int ae531x_RxQueueCreate(ae531x_MAC_t *MACInfo, AE531X_QUEUE *q,
2668 + char *pMem, int count);
2669 +int ae531x_QueueDelete(struct ae531x_queue *q);
2670 +void ae531x_DmaReset(ae531x_MAC_t *MACInfo);
2671 +void ae531x_MACReset(ae531x_MAC_t *MACInfo);
2672 +void ae531x_EnableComm(ae531x_MAC_t *MACInfo);
2673 +void ae531x_DisableComm(ae531x_MAC_t *MACInfo);
2674 +void ae531x_reset(ae531x_MAC_t *MACInfo);
2675 +int ae531x_AllocateQueues(ae531x_MAC_t *MACInfo);
2676 +void ae531x_FreeQueues(ae531x_MAC_t *MACInfo);
2677 +void ae531x_QueueInit(AE531X_QUEUE *q, char *pMem, int count);
2678 +UINT32 ae531x_ReadMacReg(ae531x_MAC_t *MACInfo, UINT32 reg);
2679 +void ae531x_WriteMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data);
2680 +void ae531x_SetMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
2681 +void ae531x_ClearMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
2682 +void ae531x_SetDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
2683 +void ae531x_ClearDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
2684 +UINT32 ae531x_ReadDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg);
2685 +void ae531x_WriteDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data);
2686 +UINT32 ae531x_ReadMiiReg(UINT32 phyBase, UINT32 reg);
2687 +void ae531x_WriteMiiReg(UINT32 phyBase, UINT32 reg, UINT32 data);
2688 +UINT16 ae531x_MiiRead(UINT32 phyBase, UINT32 phyAddr, UINT8 reg);
2689 +void ae531x_MiiWrite(UINT32 phyBase, UINT32 phyAddr, UINT8 reg, UINT16 data);
2690 +void ae531x_DmaIntEnable(ae531x_MAC_t *MACInfo);
2691 +void ae531x_DmaIntDisable(ae531x_MAC_t *MACInfo);
2692 +void ae531x_AckIntr(ae531x_MAC_t *MACInfo, UINT32 val);
2693 +void *ae531x_rxbuf_alloc(ae531x_MAC_t *MACInfo, char **rxBptr, int *rxBSize);
2694 +void ae531x_swptr_free(VIRT_ADDR txDesc);
2695 +
2696 +#endif /* _AE531XMAC_H_ */
2697 diff -urN linux-2.4.32.new/arch/mips/ar531x/ae531xreg.h linux-2.4.32.new-eth/arch/mips/ar531x/ae531xreg.h
2698 --- linux-2.4.32.new/arch/mips/ar531x/ae531xreg.h 1970-01-01 01:00:00.000000000 +0100
2699 +++ linux-2.4.32.new-eth/arch/mips/ar531x/ae531xreg.h 2005-12-25 11:54:20.834262096 +0000
2700 @@ -0,0 +1,437 @@
2701 +/*
2702 + * This file is subject to the terms and conditions of the GNU General Public
2703 + * License. See the file "COPYING" in the main directory of this archive
2704 + * for more details.
2705 + *
2706 + * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
2707 + */
2708 +
2709 +/*
2710 + * See README to understand the decomposition of the ethernet driver.
2711 + *
2712 + * Register definitions for Atheros AR531X Ethernet MAC.
2713 + */
2714 +
2715 +#ifndef _AE531XREG_H_
2716 +#define _AE531XREG_H_
2717 +
2718 +#define AE531X_MAC_OFFSET 0x0000
2719 +#define AE531X_PHY_OFFSET 0x0000 /* Same as MAC offset */
2720 +#define AE531X_DMA_OFFSET 0x1000
2721 +
2722 +/***********************************************************/
2723 +/* MAC110 registers, base address is BAR+AE531X_MAC_OFFSET */
2724 +/***********************************************************/
2725 +#define MacControl 0x00 /* control */
2726 +#define MacAddrHigh 0x04 /* address high */
2727 +#define MacAddrLow 0x08 /* address low */
2728 +#define MacMultiHashHigh 0x0C /* multicast hash table high */
2729 +#define MacMultiHashLow 0x10 /* multicast hash table low */
2730 +#define MacMiiAddr 0x14 /* MII address */
2731 +#define MacMiiData 0x18 /* MII data */
2732 +#define MacFlowControl 0x1C /* Flow control */
2733 +#define MacVlan1Tag 0x4C /* VLAN1 tag */
2734 +#define MacVlan2Tag 0x50 /* VLAN2 tag */
2735 +
2736 +
2737 +/***************************************************************/
2738 +/* DMA engine registers, base address is BAR+AE531X_DMA_OFFSET */
2739 +/***************************************************************/
2740 +#define DmaBusMode 0x00 /* CSR0 - Bus Mode */
2741 +#define DmaTxPollDemand 0x04 /* CSR1 - Transmit Poll Demand */
2742 +#define DmaRxPollDemand 0x08 /* CSR2 - Receive Poll Demand */
2743 +#define DmaRxBaseAddr 0x0C /* CSR3 - Receive list base address */
2744 +#define DmaTxBaseAddr 0x10 /* CSR4 - Transmit list base address */
2745 +#define DmaStatus 0x14 /* CSR5 - Dma status */
2746 +#define DmaControl 0x18 /* CSR6 - Dma control */
2747 +#define DmaIntrEnb 0x1C /* CSR7 - Interrupt enable */
2748 +#define DmaOverflowCnt 0x20 /* CSR8 - Missed Frame and Buff Overflow counter */
2749 +#define DmaTxCurrAddr 0x50 /* CSR20 - Current host transmit buffer address */
2750 +#define DmaRxCurrAddr 0x54 /* CSR21 - Current host receive buffer address */
2751 +
2752 +/**********************************************************/
2753 +/* MAC Control register layout */
2754 +/**********************************************************/
2755 +#define MacFilterOff 0x80000000 /* Receive all incoming packets RW */
2756 +#define MacFilterOn 0 /* Receive filtered packets only 0 */
2757 +#define MacBigEndian 0x40000000 /* Big endian mode RW */
2758 +#define MacLittleEndian 0 /* Little endian 0 */
2759 +#define MacHeartBeatOff 0x10000000 /* Heartbeat signal qual disable RW*/
2760 +#define MacHeartBeatOn 0 /* Heartbeat signal qual enable 0 */
2761 +#define MacSelectSrl 0x08000000 /* Select SRL port RW */
2762 +#define MacSelectMii 0 /* Select MII port 0 */
2763 +#define MacDisableRxOwn 0x00800000 /* Disable receive own packets RW */
2764 +#define MacEnableRxOwn 0 /* Enable receive own packets 0 */
2765 +#define MacLoopbackExt 0x00400000 /* External loopback RW */
2766 +#define MacLoopbackInt 0x00200000 /* Internal loopback */
2767 +#define MacLoopbackOff 0 /* Normal mode 00 */
2768 +#define MacFullDuplex 0x00100000 /* Full duplex mode RW */
2769 +#define MacHalfDuplex 0 /* Half duplex mode 0 */
2770 +#define MacMulticastFilterOff 0x00080000 /* Pass all multicast packets RW */
2771 +#define MacMulticastFilterOn 0 /* Pass filtered mcast packets 0 */
2772 +#define MacPromiscuousModeOn 0x00040000 /* Receive all valid packets RW 1 */
2773 +#define MacPromiscuousModeOff 0 /* Receive filtered packets only */
2774 +#define MacFilterInverse 0x00020000 /* Inverse filtering RW */
2775 +#define MacFilterNormal 0 /* Normal filtering 0 */
2776 +#define MacBadFramesEnable 0x00010000 /* Pass bad frames RW */
2777 +#define MacBadFramesDisable 0 /* Do not pass bad frames 0 */
2778 +#define MacPerfectFilterOff 0x00008000 /* Hash filtering only RW */
2779 +#define MacPerfectFilterOn 0 /* Both perfect and hash filtering 0 */
2780 +#define MacHashFilterOn 0x00002000 /* perform hash filtering RW */
2781 +#define MacHashFilterOff 0 /* perfect filtering only 0 */
2782 +#define MacLateCollisionOn 0x00001000 /* Enable late collision control RW */
2783 +#define MacLateCollisionOff 0 /* Disable late collision control 0 */
2784 +#define MacBroadcastDisable 0x00000800 /* Disable reception of bcast frames RW */
2785 +#define MacBroadcastEnable 0 /* Enable broadcast frames 0 */
2786 +#define MacRetryDisable 0x00000400 /* Disable retransmission RW */
2787 +#define MacRetryEnable 0 /* Enable retransmission 0 */
2788 +#define MacPadStripEnable 0x00000100 /* Pad stripping enable RW */
2789 +#define MacPadStripDisable 0 /* Pad stripping disable 0 */
2790 +#define MacBackoff 0 /* Backoff Limit RW 00 */
2791 +#define MacDeferralCheckEnable 0x00000020 /* Deferral check enable RW */
2792 +#define MacDeferralCheckDisable 0 /* Deferral check disable 0 */
2793 +#define MacTxEnable 0x00000008 /* Transmitter enable RW */
2794 +#define MacTxDisable 0 /* Transmitter disable 0 */
2795 +#define MacRxEnable 0x00000004 /* Receiver enable RW */
2796 +#define MacRxDisable 0 /* Receiver disable 0 */
2797 +
2798 +
2799 +/**********************************************************/
2800 +/* MII address register layout */
2801 +/**********************************************************/
2802 +#define MiiDevMask 0x0000F800 /* MII device address */
2803 +#define MiiDevShift 11
2804 +#define MiiRegMask 0x000007C0 /* MII register */
2805 +#define MiiRegShift 6
2806 +#define MiiWrite 0x00000002 /* Write to register */
2807 +#define MiiRead 0 /* Read from register */
2808 +#define MiiBusy 0x00000001 /* MII interface is busy */
2809 +
2810 +/**********************************************************/
2811 +/* MII Data register layout */
2812 +/**********************************************************/
2813 +#define MiiDataMask 0x0000FFFF /* MII Data */
2814 +
2815 +/**********************************************************/
2816 +/* MAC flow control register layout */
2817 +/**********************************************************/
2818 +#define MacPauseTimeMask 0xFFFF0000 /* PAUSE TIME field in ctrl frame */
2819 +#define MacPauseTimeShift 15
2820 +#define MacControlFrameEnable 0x00000004 /* Enable pass ctrl frames to host */
2821 +#define MacControlFrameDisable 0 /* Do not pass ctrl frames to host */
2822 +#define MacFlowControlEnable 0x00000002 /* Enable flow control */
2823 +#define MacFlowControlDisable 0 /* Disable flow control */
2824 +#define MacSendPauseFrame 0x00000001 /* send pause frame */
2825 +
2826 +/**********************************************************/
2827 +/* DMA bus mode register layout */
2828 +/**********************************************************/
2829 +#define DmaRxAlign16 0x01000000 /* Force all rx buffers to align on odd hw bndry */
2830 +#define DmaBigEndianDes 0x00100000 /* Big endian data buffer descriptors RW */
2831 +#define DmaLittleEndianDesc 0 /* Little endian data descriptors */
2832 +#define DmaBurstLength32 0x00002000 /* Dma burst length 32 RW */
2833 +#define DmaBurstLength16 0x00001000 /* Dma burst length 16 */
2834 +#define DmaBurstLength8 0x00000800 /* Dma burst length 8 */
2835 +#define DmaBurstLength4 0x00000400 /* Dma burst length 4 */
2836 +#define DmaBurstLength2 0x00000200 /* Dma burst length 2 */
2837 +#define DmaBurstLength1 0x00000100 /* Dma burst length 1 */
2838 +#define DmaBurstLength0 0x00000000 /* Dma burst length 0 */
2839 +#define DmaBigEndianData 0x00000080 /* Big endian data buffers RW */
2840 +#define DmaLittleEndianData 0 /* Little endian data buffers 0 */
2841 +#define DmaDescriptorSkip16 0x00000040 /* number of dwords to skip RW */
2842 +#define DmaDescriptorSkip8 0x00000020 /* between two unchained descriptors */
2843 +#define DmaDescriptorSkip4 0x00000010
2844 +#define DmaDescriptorSkip2 0x00000008
2845 +#define DmaDescriptorSkip1 0x00000004
2846 +#define DmaDescriptorSkip0 0
2847 +#define DmaReceivePriorityOff 0x00000002 /* equal rx and tx priorities RW */
2848 +#define DmaReceivePriorityOn 0 /* Rx has prioryty over Tx 0 */
2849 +#define DmaResetOn 0x00000001 /* Reset DMA engine RW */
2850 +#define DmaResetOff 0
2851 +
2852 +/**********************************************************/
2853 +/* DMA Status register layout */
2854 +/**********************************************************/
2855 +#define DmaRxAbort 0x01000000 /* receiver bus abort R 0 */
2856 +#define DmaTxAbort 0x00800000 /* transmitter bus abort R 0 */
2857 +#define DmaTxState 0x00700000 /* Transmit process state R 000 */
2858 +#define DmaTxStopped 0x00000000 /* Stopped */
2859 +#define DmaTxFetching 0x00100000 /* Running - fetching the descriptor */
2860 +#define DmaTxWaiting 0x00200000 /* Running - waiting for end of transmission */
2861 +#define DmaTxReading 0x00300000 /* Running - reading the data from memory */
2862 +#define DmaTxSuspended 0x00600000 /* Suspended */
2863 +#define DmaTxClosing 0x00700000 /* Running - closing descriptor */
2864 +#define DmaRxState 0x000E0000 /* Receive process state 000 */
2865 +#define DmaRxStopped 0x00000000 /* Stopped */
2866 +#define DmaRxFetching 0x00020000 /* Running - fetching the descriptor */
2867 +#define DmaRxChecking 0x00040000 /* Running - checking for end of packet */
2868 +#define DmaRxWaiting 0x00060000 /* Running - waiting for packet */
2869 +#define DmaRxSuspended 0x00080000 /* Suspended */
2870 +#define DmaRxClosing 0x000A0000 /* Running - closing descriptor */
2871 +#define DmaRxFlushing 0x000C0000 /* Running - flushing the current frame */
2872 +#define DmaRxQueuing 0x000E0000 /* Running - queuing the recieve frame into host memory */
2873 +#define DmaIntNormal 0x00010000 /* Normal interrupt summary RW 0 */
2874 +#define DmaIntAbnormal 0x00008000 /* Abnormal interrupt summary RW 0 */
2875 +#define DmaIntEarlyRx 0x00004000 /* Early receive interrupt (Normal) RW 0 */
2876 +#define DmaIntBusError 0x00002000 /* Fatal bus error (Abnormal) RW 0 */
2877 +#define DmaIntEarlyTx 0x00000400 /* Early transmit interrupt RW 0 */
2878 +#define DmaIntRxStopped 0x00000100 /* Receive process stopped (Abnormal) RW 0 */
2879 +#define DmaIntRxNoBuffer 0x00000080 /* Receive buffer unavailable (Abnormal) RW 0*/
2880 +#define DmaIntRxCompleted 0x00000040 /* Completion of frame reception(Normal) RW 0*/
2881 +#define DmaIntTxUnderflow 0x00000020 /* Transmit underflow (Abnormal) RW 0 */
2882 +#define DmaIntTxJabber 0x00000008 /* Transmit Jabber Timeout (Abnormal) RW 0 */
2883 +#define DmaIntTxNoBuffer 0x00000004 /* Transmit buffer unavailable (Normal) RW 0*/
2884 +#define DmaIntTxStopped 0x00000002 /* Transmit process stopped (Abnormal) RW 0 */
2885 +#define DmaIntTxCompleted 0x00000001 /* Transmit completed (Normal) RW 0 */
2886 +
2887 +/**********************************************************/
2888 +/* DMA control register layout */
2889 +/**********************************************************/
2890 +#define DmaStoreAndForward 0x00200000 /* Store and forward RW 0 */
2891 +#define DmaTxThreshCtl256 0x0000c000 /* Non-SF threshold is 256 words */
2892 +#define DmaTxThreshCtl128 0x00008000 /* Non-SF threshold is 128 words */
2893 +#define DmaTxThreshCtl064 0x00004000 /* Non-SF threshold is 64 words */
2894 +#define DmaTxThreshCtl032 0x00000000 /* Non-SF threshold is 32 words */
2895 +#define DmaTxStart 0x00002000 /* Start/Stop transmission RW 0 */
2896 +#define DmaTxSecondFrame 0x00000004 /* Operate on second frame RW 0 */
2897 +#define DmaRxStart 0x00000002 /* Start/Stop reception RW 0 */
2898 +
2899 +/**********************************************************/
2900 +/* DMA interrupt enable register layout */
2901 +/**********************************************************/
2902 +#define DmaIeNormal DmaIntNormal /* Normal interrupt enable RW 0 */
2903 +#define DmaIeAbnormal DmaIntAbnormal /* Abnormal interrupt enable RW 0 */
2904 +#define DmaIeEarlyRx DmaIntEarlyRx /* Early receive interrupt enable RW 0 */
2905 +#define DmaIeBusError DmaIntBusError /* Fatal bus error enable RW 0 */
2906 +#define DmaIeEarlyTx DmaIntEarlyTx /* Early transmit interrupt enable RW 0 */
2907 +#define DmaIeRxStopped DmaIntRxStopped /* Receive process stopped enable RW 0 */
2908 +#define DmaIeRxNoBuffer DmaIntRxNoBuffer /* Receive buffer unavailable enable RW 0 */
2909 +#define DmaIeRxCompleted DmaIntRxCompleted /* Completion of frame reception enable RW 0 */
2910 +#define DmaIeTxUnderflow DmaIntTxUnderflow /* Transmit underflow enable RW 0 */
2911 +#define DmaIeTxJabber DmaIntTxJabber /* Transmit jabber timeout RW 0 */
2912 +#define DmaIeTxNoBuffer DmaIntTxNoBuffer /* Transmit buffer unavailable enable RW 0 */
2913 +#define DmaIeTxStopped DmaIntTxStopped /* Transmit process stopped enable RW 0 */
2914 +#define DmaIeTxCompleted DmaIntTxCompleted /* Transmit completed enable RW 0 */
2915 +
2916 +/****************************************************************/
2917 +/* DMA Missed Frame and Buffer Overflow Counter register layout */
2918 +/****************************************************************/
2919 +#define DmaRxBufferMissedFrame 0xffff0000 /* cleared on read */
2920 +#define DmaMissedFrameShift 16
2921 +#define DmaRxBufferOverflowCnt 0x0000ffff /* cleared on read */
2922 +#define DmaMissedFrameCountMask 0x0000ffff
2923 +
2924 +/**********************************************************/
2925 +/* DMA Engine descriptor layout */
2926 +/**********************************************************/
2927 +/* status word of DMA descriptor */
2928 +#define DescOwnByDma 0x80000000 /* Descriptor is owned by DMA engine */
2929 +#define DescFrameLengthMask 0x3FFF0000 /* Receive descriptor frame length */
2930 +#define DescFrameLengthShift 16
2931 +#define DescError 0x00008000 /* Error summary bit OR of following bits */
2932 +#define DescRxTruncated 0x00004000 /* Rx - no more descs for receive frame */
2933 +#define DescRxLengthError 0x00001000 /* Rx - frame size not matching with length field */
2934 +#define DescRxRunt 0x00000800 /* Rx - runt frame, damaged by a
2935 + collision or term before 64 bytes */
2936 +#define DescRxMulticast 0x00000400 /* Rx - received frame is multicast */
2937 +#define DescRxFirst 0x00000200 /* Rx - first descriptor of the frame */
2938 +#define DescRxLast 0x00000100 /* Rx - last descriptor of the frame */
2939 +#define DescRxLongFrame 0x00000080 /* Rx - frame is longer than 1518 bytes */
2940 +#define DescRxLateColl 0x00000040 /* Rx - frame was damaged by a late collision */
2941 +#define DescRxFrameEther 0x00000020 /* Rx - Frame type Ethernet 802.3*/
2942 +#define DescRxMiiError 0x00000008 /* Rx - error reported by MII interface */
2943 +#define DescRxDribbling 0x00000004 /* Rx - frame contains noninteger multiple of 8 bits */
2944 +#define DescRxCrc 0x00000002 /* Rx - CRC error */
2945 +#define DescTxTimeout 0x00004000 /* Tx - Transmit jabber timeout */
2946 +#define DescTxLostCarrier 0x00000800 /* Tx - carrier lost during tramsmission */
2947 +#define DescTxNoCarrier 0x00000400 /* Tx - no carrier signal from tranceiver */
2948 +#define DescTxLateCollision 0x00000200 /* Tx - transmission aborted due to collision */
2949 +#define DescTxExcCollisions 0x00000100 /* Tx - transmission aborted after 16 collisions */
2950 +#define DescTxHeartbeatFail 0x00000080 /* Tx - heartbeat collision check failure */
2951 +#define DescTxCollMask 0x00000078 /* Tx - Collision count */
2952 +#define DescTxCollShift 3
2953 +#define DescTxExcDeferral 0x00000004 /* Tx - excessive deferral */
2954 +#define DescTxUnderflow 0x00000002 /* Tx - late data arrival from memory */
2955 +#define DescTxDeferred 0x00000001 /* Tx - frame transmision deferred */
2956 +
2957 +/* length word of DMA descriptor */
2958 +#define DescTxIntEnable 0x80000000 /* Tx - interrupt on completion */
2959 +#define DescTxLast 0x40000000 /* Tx - Last segment of the frame */
2960 +#define DescTxFirst 0x20000000 /* Tx - First segment of the frame */
2961 +#define DescTxDisableCrc 0x04000000 /* Tx - Add CRC disabled (first segment only) */
2962 +#define DescEndOfRing 0x02000000 /* End of descriptors ring */
2963 +#define DescChain 0x01000000 /* Second buffer address is chain address */
2964 +#define DescTxDisablePadd 0x00800000 /* disable padding */
2965 +#define DescSize2Mask 0x003FF800 /* Buffer 2 size */
2966 +#define DescSize2Shift 11
2967 +#define DescSize1Mask 0x000007FF /* Buffer 1 size */
2968 +#define DescSize1Shift 0
2969 +
2970 +/**********************************************************/
2971 +/* Initial register values */
2972 +/**********************************************************/
2973 +/* Full-duplex mode with perfect filter on */
2974 +#define MacControlInitFdx \
2975 + ( MacFilterOn \
2976 + | MacLittleEndian \
2977 + | MacHeartBeatOn \
2978 + | MacSelectMii \
2979 + | MacEnableRxOwn \
2980 + | MacLoopbackOff \
2981 + | MacFullDuplex \
2982 + | MacMulticastFilterOn \
2983 + | MacPromiscuousModeOff \
2984 + | MacFilterNormal \
2985 + | MacBadFramesDisable \
2986 + | MacPerfectFilterOn \
2987 + | MacHashFilterOff \
2988 + | MacLateCollisionOff \
2989 + | MacBroadcastEnable \
2990 + | MacRetryEnable \
2991 + | MacPadStripDisable \
2992 + | MacDeferralCheckDisable \
2993 + | MacTxEnable \
2994 + | MacRxEnable)
2995 +
2996 +/* Full-duplex mode */
2997 +#define MacFlowControlInitFdx \
2998 + ( MacControlFrameDisable \
2999 + | MacFlowControlEnable)
3000 +
3001 +/* Half-duplex mode with perfect filter on */
3002 +#define MacControlInitHdx \
3003 + ( MacFilterOn \
3004 + | MacLittleEndian \
3005 + | MacHeartBeatOn \
3006 + | MacSelectMii \
3007 + | MacDisableRxOwn \
3008 + | MacLoopbackOff \
3009 + | MacHalfDuplex \
3010 + | MacMulticastFilterOn \
3011 + | MacPromiscuousModeOff \
3012 + | MacFilterNormal \
3013 + | MacBadFramesDisable \
3014 + | MacPerfectFilterOn \
3015 + | MacHashFilterOff \
3016 + | MacLateCollisionOff \
3017 + | MacBroadcastEnable \
3018 + | MacRetryEnable \
3019 + | MacPadStripDisable \
3020 + | MacDeferralCheckDisable \
3021 + | MacTxEnable \
3022 + | MacRxEnable)
3023 +
3024 +/* Half-duplex mode */
3025 +#define MacFlowControlInitHdx \
3026 + ( MacControlFrameDisable \
3027 + | MacFlowControlDisable)
3028 +
3029 +/* Bus Mode Rx odd half word align */
3030 +#define DmaBusModeInit \
3031 + ( DmaLittleEndianDesc \
3032 + | DmaRxAlign16 \
3033 + | DmaBurstLength4 \
3034 + | DmaBigEndianData \
3035 + | DmaDescriptorSkip1 \
3036 + | DmaReceivePriorityOn \
3037 + | DmaResetOff)
3038 +
3039 +#define DmaControlInit (DmaStoreAndForward)
3040 +
3041 +/* Interrupt groups */
3042 +#define DmaIntEnable \
3043 + ( DmaIeNormal \
3044 + | DmaIeAbnormal \
3045 + | DmaIntBusError \
3046 + | DmaIntRxStopped \
3047 + | DmaIntTxUnderflow \
3048 + | DmaIntTxStopped)
3049 +
3050 +#define DmaIntDisable 0
3051 +
3052 +#define DmaAllIntCauseMask \
3053 + ( DmaIeNormal \
3054 + | DmaIeAbnormal \
3055 + | DmaIntEarlyRx \
3056 + | DmaIntBusError \
3057 + | DmaIntEarlyTx \
3058 + | DmaIntRxStopped \
3059 + | DmaIntRxNoBuffer \
3060 + | DmaIntRxCompleted \
3061 + | DmaIntTxUnderflow \
3062 + | DmaIntTxJabber \
3063 + | DmaIntTxNoBuffer \
3064 + | DmaIntTxStopped \
3065 + | DmaIntTxCompleted)
3066 +
3067 +#define UnhandledIntrMask \
3068 + (DmaAllIntCauseMask \
3069 + & ~(DmaIntRxNoBuffer \
3070 + | DmaIntTxStopped \
3071 + | DmaIntTxJabber \
3072 + | DmaIntTxUnderflow \
3073 + | DmaIntBusError \
3074 + | DmaIntRxCompleted ))
3075 +
3076 +#define DescRxErrors \
3077 + (DescRxTruncated \
3078 + | DescRxRunt \
3079 + | DescRxLateColl \
3080 + | DescRxMiiError \
3081 + | DescRxCrc)
3082 +
3083 +#define DescTxErrors \
3084 + ( DescTxTimeout \
3085 + | DescTxLateCollision \
3086 + | DescTxExcCollisions \
3087 + | DescTxExcDeferral \
3088 + | DescTxUnderflow)
3089 +
3090 +/**********************************************************/
3091 +/* Descriptor Layout */
3092 +/**********************************************************/
3093 +#define AE531X_DESC_STATUS 0x00 /* Status offset */
3094 +#define AE531X_DESC_CTRLEN 0x04 /* Control and Length offset */
3095 +#define AE531X_DESC_BUFPTR 0x08 /* Buffer pointer offset */
3096 +#define AE531X_DESC_LNKBUF 0x0c /* Link field offset, or ptr to 2nd buf */
3097 +#define AE531X_DESC_SWPTR 0x10 /* OS-Dependent software pointer */
3098 +
3099 +#define AE531X_DESC_SIZE 0x10 /* 4 words, 16 bytes */
3100 +#define AE531X_QUEUE_ELE_SIZE 0x14 /* with software pointer extension */
3101 +
3102 +/* Accessors to the dma descriptor fields */
3103 +#define AE531X_DESC_STATUS_GET(ptr) \
3104 + *(volatile UINT32 *)((UINT32)(ptr) + AE531X_DESC_STATUS)
3105 +
3106 +#define AE531X_DESC_STATUS_SET(ptr, val) \
3107 + AE531X_DESC_STATUS_GET(ptr) = (val)
3108 +
3109 +#define AE531X_DESC_CTRLEN_GET(ptr) \
3110 + *(volatile UINT32 *)((UINT32)ptr + AE531X_DESC_CTRLEN)
3111 +
3112 +#define AE531X_DESC_CTRLEN_SET(ptr, val) \
3113 + AE531X_DESC_CTRLEN_GET(ptr) = (val)
3114 +
3115 +#define AE531X_DESC_BUFPTR_GET(ptr) \
3116 + *(volatile UINT32 *)((UINT32)ptr + AE531X_DESC_BUFPTR)
3117 +
3118 +#define AE531X_DESC_BUFPTR_SET(ptr,val) \
3119 + AE531X_DESC_BUFPTR_GET(ptr) = (UINT32)(val)
3120 +
3121 +#define AE531X_DESC_LNKBUF_GET(ptr) \
3122 + *(volatile UINT32 *)((UINT32)ptr + AE531X_DESC_LNKBUF)
3123 +
3124 +#define AE531X_DESC_LNKBUF_SET(ptr, val) \
3125 + AE531X_DESC_LNKBUF_GET(ptr) = (val)
3126 +
3127 +#define AE531X_DESC_SWPTR_GET(ptr) \
3128 + (void *)(*(volatile UINT32 *) ((UINT32)ptr + AE531X_DESC_SWPTR))
3129 +
3130 +#define AE531X_DESC_SWPTR_SET(ptr,val) \
3131 + AE531X_DESC_SWPTR_GET(ptr) = (void *)(val)
3132 +
3133 +/* Get size of Rx data from desc, in bytes */
3134 +#define AE531X_DESC_STATUS_RX_SIZE(x) \
3135 + (((x) & DescFrameLengthMask) >> DescFrameLengthShift)
3136 +
3137 +#endif /* _AE531XREG_H_ */
3138 diff -urN linux-2.4.32.new/arch/mips/ar531x/Makefile linux-2.4.32.new-eth/arch/mips/ar531x/Makefile
3139 --- linux-2.4.32.new/arch/mips/ar531x/Makefile 2005-12-24 20:29:42.010325312 +0000
3140 +++ linux-2.4.32.new-eth/arch/mips/ar531x/Makefile 2005-12-25 12:03:16.213872024 +0000
3141 @@ -28,6 +28,13 @@
3142 ar531xirq.o \
3143 ar531xintr.o \
3144 ar531xgpio.o \
3145 - ar531xksyms.o
3146 + ar531xksyms.o \
3147 + ae531xlnx.o \
3148 + ae531xmac.o
3149
3150 include $(TOPDIR)/Rules.make
3151 +obj-$(CONFIG_MARVELL_ENET_PHY) += mvPhy.o
3152 +obj-$(CONFIG_KENDIN_ENET_PHY)) += rtPhy.o
3153 +obj-$(CONFIG_REALTEK_ENET_PHY) += rtPhy.o
3154 +
3155 +
3156 diff -urN linux-2.4.32.new/arch/mips/ar531x/mvPhy.c linux-2.4.32.new-eth/arch/mips/ar531x/mvPhy.c
3157 --- linux-2.4.32.new/arch/mips/ar531x/mvPhy.c 1970-01-01 01:00:00.000000000 +0100
3158 +++ linux-2.4.32.new-eth/arch/mips/ar531x/mvPhy.c 2005-12-25 11:54:39.730389448 +0000
3159 @@ -0,0 +1,1237 @@
3160 +/*
3161 + * This file is subject to the terms and conditions of the GNU General Public
3162 + * License. See the file "COPYING" in the main directory of this archive
3163 + * for more details.
3164 + *
3165 + * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
3166 + */
3167 +
3168 +/*
3169 +* Manage the ethernet PHY switch, Marvell 88E6060.
3170 +*
3171 +* This module is intended to be largely OS and platform-independent.
3172 +*/
3173 +
3174 +#if defined(linux)
3175 +#include <linux/config.h>
3176 +#include <linux/types.h>
3177 +#include <linux/netdevice.h>
3178 +#include <linux/etherdevice.h>
3179 +#include <linux/delay.h>
3180 +
3181 +#include "ar531xlnx.h"
3182 +#endif
3183 +
3184 +#if defined(__ECOS)
3185 +#include "ae531xecos.h"
3186 +#endif
3187 +
3188 +
3189 +#include "ae531xmac.h"
3190 +#include "ae531xreg.h"
3191 +#include "mvPhy.h"
3192 +
3193 +#if /* DEBUG */ 1
3194 +#define MV_DEBUG_ERROR 0x00000001
3195 +#define MV_DEBUG_PHYSETUP 0x00000002
3196 +#define MV_DEBUG_PHYCHANGE 0x00000004
3197 +
3198 +int mvPhyDebug = MV_DEBUG_ERROR;
3199 +
3200 +#define MV_PRINT(FLG, X) \
3201 +{ \
3202 + if (mvPhyDebug & (FLG)) { \
3203 + DEBUG_PRINTF X; \
3204 + } \
3205 +}
3206 +#else
3207 +#define MV_PRINT(FLG, X)
3208 +#endif
3209 +
3210 +#ifdef CONFIG_VENETDEV
3211 +/*
3212 + * On AR5312 with CONFIG_VENETDEV==1,
3213 + * ports 0..3 are LAN ports (accessed through ae0)
3214 + * port 4 is the WAN port. (accessed through ae1)
3215 + *
3216 + * The phy switch settings in the mvPhyInfo table are set accordingly.
3217 + */
3218 +#define MV_WAN_PORT 4
3219 +#define MV_IS_LAN_PORT(port) ((port) < MV_WAN_PORT)
3220 +#define MV_IS_WAN_PORT(port) ((port) == MV_WAN_PORT)
3221 +#endif
3222 +
3223 +/*
3224 + * Track per-PHY port information.
3225 + */
3226 +typedef struct {
3227 + BOOL isEnetPort; /* normal enet port */
3228 + BOOL isPhyAlive; /* last known state of link */
3229 + int ethUnit; /* MAC associated with this phy port */
3230 + UINT32 phyBase;
3231 + UINT32 phyAddr; /* PHY registers associated with this phy port */
3232 + UINT32 switchPortAddr; /* switch port regs assoc'ed with this phy port */
3233 + UINT32 VLANTableSetting; /* Value to be written to VLAN table */
3234 +} mvPhyInfo_t;
3235 +
3236 +/******************************************************************************
3237 + * Per-PHY information, indexed by PHY unit number.
3238 + *
3239 + * This table is board-dependent. It includes information
3240 + * about which enet MAC controls which PHY port.
3241 + */
3242 +mvPhyInfo_t mvPhyInfo[] = {
3243 + /*
3244 + * On AP30/AR5312, all PHYs are associated with MAC0.
3245 + * AP30/AR5312's MAC1 isn't used for anything.
3246 + * CONFIG_VENETDEV==1 (router) configuration:
3247 + * Ports 0,1,2, and 3 are "LAN ports"
3248 + * Port 4 is a WAN port
3249 + * Port 5 connects to MAC0 in the AR5312
3250 + * CONFIG_VENETDEV==0 (bridge) configuration:
3251 + * Ports 0,1,2,3,4 are "LAN ports"
3252 + * Port 5 connects to the MAC0 in the AR5312
3253 + */
3254 + {isEnetPort: TRUE, /* phy port 0 -- LAN port 0 */
3255 + isPhyAlive: FALSE,
3256 + ethUnit: 0,
3257 + phyBase: 0,
3258 + phyAddr: 0x10,
3259 + switchPortAddr: 0x18,
3260 +#ifdef CONFIG_VENETDEV
3261 + VLANTableSetting: 0x2e
3262 +#else
3263 + VLANTableSetting: 0x3e
3264 +#endif
3265 + },
3266 +
3267 + {isEnetPort: TRUE, /* phy port 1 -- LAN port 1 */
3268 + isPhyAlive: FALSE,
3269 + ethUnit: 0,
3270 + phyBase: 0,
3271 + phyAddr: 0x11,
3272 + switchPortAddr: 0x19,
3273 +#ifdef CONFIG_VENETDEV
3274 + VLANTableSetting: 0x2d
3275 +#else
3276 + VLANTableSetting: 0x3d
3277 +#endif
3278 + },
3279 +
3280 + {isEnetPort: TRUE, /* phy port 2 -- LAN port 2 */
3281 + isPhyAlive: FALSE,
3282 + ethUnit: 0,
3283 + phyBase: 0,
3284 + phyAddr: 0x12,
3285 + switchPortAddr: 0x1a,
3286 +#ifdef CONFIG_VENETDEV
3287 + VLANTableSetting: 0x2b
3288 +#else
3289 + VLANTableSetting: 0x3b
3290 +#endif
3291 + },
3292 +
3293 + {isEnetPort: TRUE, /* phy port 3 -- LAN port 3 */
3294 + isPhyAlive: FALSE,
3295 + ethUnit: 0,
3296 + phyBase: 0,
3297 + phyAddr: 0x13,
3298 + switchPortAddr: 0x1b,
3299 +#ifdef CONFIG_VENETDEV
3300 + VLANTableSetting: 0x27
3301 +#else
3302 + VLANTableSetting: 0x37
3303 +#endif
3304 + },
3305 +
3306 + {isEnetPort: TRUE, /* phy port 4 -- WAN port or LAN port 4 */
3307 + isPhyAlive: FALSE,
3308 + ethUnit: 0,
3309 + phyBase: 0,
3310 + phyAddr: 0x14,
3311 + switchPortAddr: 0x1c,
3312 +#ifdef CONFIG_VENETDEV
3313 + VLANTableSetting: 0x1020 /* WAN port */
3314 +#else
3315 + VLANTableSetting: 0x2f /* LAN port 4 */
3316 +#endif
3317 + },
3318 +
3319 + {isEnetPort: FALSE, /* phy port 5 -- CPU port (no RJ45 connector) */
3320 + isPhyAlive: TRUE,
3321 + ethUnit: 0,
3322 + phyBase: 0,
3323 + phyAddr: 0x15,
3324 + switchPortAddr: 0x1d,
3325 +#ifdef CONFIG_VENETDEV
3326 + VLANTableSetting: 0x0f /* Send only to LAN ports */
3327 +#else
3328 + VLANTableSetting: 0x1f /* Send to all ports */
3329 +#endif
3330 + },
3331 +};
3332 +
3333 +#define MV_PHY_MAX (sizeof(mvPhyInfo) / sizeof(mvPhyInfo[0]))
3334 +
3335 +/* Range of valid PHY IDs is [MIN..MAX] */
3336 +#define MV_ID_MIN 0
3337 +#define MV_ID_MAX (MV_PHY_MAX-1)
3338 +
3339 +/* Convenience macros to access myPhyInfo */
3340 +#define MV_IS_ENET_PORT(phyUnit) (mvPhyInfo[phyUnit].isEnetPort)
3341 +#define MV_IS_PHY_ALIVE(phyUnit) (mvPhyInfo[phyUnit].isPhyAlive)
3342 +#define MV_ETHUNIT(phyUnit) (mvPhyInfo[phyUnit].ethUnit)
3343 +#define MV_PHYBASE(phyUnit) (mvPhyInfo[phyUnit].phyBase)
3344 +#define MV_PHYADDR(phyUnit) (mvPhyInfo[phyUnit].phyAddr)
3345 +#define MV_SWITCH_PORT_ADDR(phyUnit) (mvPhyInfo[phyUnit].switchPortAddr)
3346 +#define MV_VLAN_TABLE_SETTING(phyUnit) (mvPhyInfo[phyUnit].VLANTableSetting)
3347 +
3348 +#define MV_IS_ETHUNIT(phyUnit, ethUnit) \
3349 + (MV_IS_ENET_PORT(phyUnit) && \
3350 + MV_ETHUNIT(phyUnit) == (ethUnit))
3351 +
3352 +
3353 +/* Forward references */
3354 +BOOL mv_phyIsLinkAlive(int phyUnit);
3355 +LOCAL void mv_VLANInit(int ethUnit);
3356 +LOCAL void mv_enableConfiguredPorts(int ethUnit);
3357 +LOCAL void mv_verifyReady(int ethUnit);
3358 +BOOL mv_phySetup(int ethUnit, UINT32 phyBase);
3359 +BOOL mv_phyIsFullDuplex(int ethUnit);
3360 +BOOL mv_phyIsSpeed100(int phyUnit);
3361 +LOCAL BOOL mv_validPhyId(int phyUnit);
3362 +void mv_flushATUDB(int phyUnit);
3363 +void mv_phyCheckStatusChange(int ethUnit);
3364 +#if DEBUG
3365 +void mv_phyShow(int phyUnit);
3366 +void mv_phySet(int phyUnit, UINT32 regnum, UINT32 value);
3367 +void mv_switchPortSet(int phyUnit, UINT32 regnum, UINT32 value);
3368 +void mv_switchGlobalSet(int phyUnit, UINT32 regnum, UINT32 value);
3369 +void mv_showATUDB(int phyUnit);
3370 +void mv_countGoodFrames(int phyUnit);
3371 +void mv_countBadFrames(int phyUnit);
3372 +void mv_showFrameCounts(int phyUnit);
3373 +#endif
3374 +
3375 +
3376 +/******************************************************************************
3377 +*
3378 +* mv_phyIsLinkAlive - test to see if the specified link is alive
3379 +*
3380 +* RETURNS:
3381 +* TRUE --> link is alive
3382 +* FALSE --> link is down
3383 +*/
3384 +BOOL
3385 +mv_phyIsLinkAlive(int phyUnit)
3386 +{
3387 + UINT16 phyHwStatus;
3388 + UINT32 phyBase;
3389 + UINT32 phyAddr;
3390 +
3391 + phyBase = MV_PHYBASE(phyUnit);
3392 + phyAddr = MV_PHYADDR(phyUnit);
3393 +
3394 + phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
3395 +
3396 + if (phyHwStatus & MV_STATUS_REAL_TIME_LINK_UP) {
3397 + return TRUE;
3398 + } else {
3399 + return FALSE;
3400 + }
3401 +}
3402 +
3403 +/******************************************************************************
3404 +*
3405 +* mv_VLANInit - initialize "port-based VLANs" for the specified enet unit.
3406 +*/
3407 +LOCAL void
3408 +mv_VLANInit(int ethUnit)
3409 +{
3410 + int phyUnit;
3411 + UINT32 phyBase;
3412 + UINT32 switchPortAddr;
3413 +
3414 + for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
3415 + if (MV_ETHUNIT(phyUnit) != ethUnit) {
3416 + continue;
3417 + }
3418 +
3419 + phyBase = MV_PHYBASE(phyUnit);
3420 + switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
3421 +
3422 + phyRegWrite(phyBase, switchPortAddr, MV_PORT_BASED_VLAN_MAP,
3423 + MV_VLAN_TABLE_SETTING(phyUnit));
3424 + }
3425 +}
3426 +
3427 +#define phyPortConfigured(phyUnit) TRUE /* TBDFREEDOM2 */
3428 +
3429 +/******************************************************************************
3430 +*
3431 +* mv_enableConfiguredPorts - enable whichever PHY ports are supposed
3432 +* to be enabled according to administrative configuration.
3433 +*/
3434 +LOCAL void
3435 +mv_enableConfiguredPorts(int ethUnit)
3436 +{
3437 + int phyUnit;
3438 + UINT32 phyBase;
3439 + UINT32 switchPortAddr;
3440 + UINT16 portControl;
3441 + UINT16 portAssociationVector;
3442 +
3443 + for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
3444 + if (MV_ETHUNIT(phyUnit) != ethUnit) {
3445 + continue;
3446 + }
3447 +
3448 + phyBase = MV_PHYBASE(phyUnit);
3449 + switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
3450 +
3451 + if (phyPortConfigured(phyUnit)) {
3452 +
3453 + portControl = MV_PORT_CONTROL_PORT_STATE_FORWARDING;
3454 +#ifdef CONFIG_VENETDEV
3455 + if (!MV_IS_ENET_PORT(phyUnit)) { /* CPU port */
3456 + portControl |= MV_PORT_CONTROL_INGRESS_TRAILER
3457 + | MV_PORT_CONTROL_EGRESS_MODE;
3458 + }
3459 +#endif
3460 + phyRegWrite(phyBase, switchPortAddr, MV_PORT_CONTROL, portControl);
3461 +
3462 + if (MV_IS_ENET_PORT(phyUnit)) {
3463 + portAssociationVector = 1 << phyUnit;
3464 + } else {
3465 + /* Disable learning on the CPU port */
3466 + portAssociationVector = 0;
3467 + }
3468 + phyRegWrite(phyBase, switchPortAddr,
3469 + MV_PORT_ASSOCIATION_VECTOR, portAssociationVector);
3470 + }
3471 + }
3472 +}
3473 +
3474 +/******************************************************************************
3475 +*
3476 +* mv_verifyReady - validates that we're dealing with the device
3477 +* we think we're dealing with, and that it's ready.
3478 +*/
3479 +LOCAL void
3480 +mv_verifyReady(int ethUnit)
3481 +{
3482 + int phyUnit;
3483 + UINT16 globalStatus;
3484 + UINT32 phyBase = 0;
3485 + UINT32 phyAddr;
3486 + UINT32 switchPortAddr;
3487 + UINT16 phyID1;
3488 + UINT16 phyID2;
3489 + UINT16 switchID;
3490 +
3491 + /*
3492 + * The first read to the Phy port registers always fails and
3493 + * returns 0. So get things started with a bogus read.
3494 + */
3495 + for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
3496 + if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
3497 + continue;
3498 + }
3499 + phyBase = MV_PHYBASE(phyUnit);
3500 + phyAddr = MV_PHYADDR(phyUnit);
3501 +
3502 + (void)phyRegRead(phyBase, phyAddr, MV_PHY_ID1); /* returns 0 */
3503 + break;
3504 + }
3505 +
3506 + for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
3507 + if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
3508 + continue;
3509 + }
3510 +
3511 + /*******************/
3512 + /* Verify phy port */
3513 + /*******************/
3514 + phyBase = MV_PHYBASE(phyUnit);
3515 + phyAddr = MV_PHYADDR(phyUnit);
3516 +
3517 + phyID1 = phyRegRead(phyBase, phyAddr, MV_PHY_ID1);
3518 + if (phyID1 != MV_PHY_ID1_EXPECTATION) {
3519 + MV_PRINT(MV_DEBUG_PHYSETUP,
3520 + ("Invalid PHY ID1 for ethmac%d port%d. Expected 0x%04x, read 0x%04x\n",
3521 + ethUnit,
3522 + phyUnit,
3523 + MV_PHY_ID1_EXPECTATION,
3524 + phyID1));
3525 + return;
3526 + }
3527 +
3528 + phyID2 = phyRegRead(phyBase, phyAddr, MV_PHY_ID2);
3529 + if ((phyID2 & MV_OUI_LSB_MASK) != MV_OUI_LSB_EXPECTATION) {
3530 + MV_PRINT(MV_DEBUG_PHYSETUP,
3531 + ("Invalid PHY ID2 for ethmac%d port %d. Expected 0x%04x, read 0x%04x\n",
3532 + ethUnit,
3533 + phyUnit,
3534 + MV_OUI_LSB_EXPECTATION,
3535 + phyID2));
3536 + return;
3537 + }
3538 +
3539 + MV_PRINT(MV_DEBUG_PHYSETUP,
3540 + ("Found PHY ethmac%d port%d: model 0x%x revision 0x%x\n",
3541 + ethUnit,
3542 + phyUnit,
3543 + (phyID2 & MV_MODEL_NUM_MASK) >> MV_MODEL_NUM_SHIFT,
3544 + (phyID2 & MV_REV_NUM_MASK) >> MV_REV_NUM_SHIFT));
3545 +
3546 +
3547 + /**********************/
3548 + /* Verify switch port */
3549 + /**********************/
3550 + switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
3551 +
3552 + switchID = phyRegRead(phyBase, switchPortAddr, MV_SWITCH_ID);
3553 + if ((switchID & MV_SWITCH_ID_DEV_MASK) !=
3554 + MV_SWITCH_ID_DEV_EXPECTATION) {
3555 +
3556 + MV_PRINT(MV_DEBUG_PHYSETUP,
3557 + ("Invalid switch ID for ethmac%d port %d. Expected 0x%04x, read 0x%04x\n",
3558 + ethUnit,
3559 + phyUnit,
3560 + MV_SWITCH_ID_DEV_EXPECTATION,
3561 + switchID));
3562 + return;
3563 + }
3564 +
3565 + MV_PRINT(MV_DEBUG_PHYSETUP,
3566 + ("Found PHY switch for enet %d port %d deviceID 0x%x revision 0x%x\n",
3567 + ethUnit,
3568 + phyUnit,
3569 + (switchID & MV_SWITCH_ID_DEV_MASK) >> MV_SWITCH_ID_DEV_SHIFT,
3570 + (switchID & MV_SWITCH_ID_REV_MASK) >> MV_SWITCH_ID_REV_SHIFT))
3571 + }
3572 +
3573 + /*******************************/
3574 + /* Verify that switch is ready */
3575 + /*******************************/
3576 + if (phyBase) {
3577 + globalStatus = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
3578 + MV_SWITCH_GLOBAL_STATUS);
3579 +
3580 + if (!(globalStatus & MV_SWITCH_STATUS_READY_MASK)) {
3581 + MV_PRINT(MV_DEBUG_PHYSETUP,
3582 + ("PHY switch for ethmac%d NOT ready!\n",
3583 + ethUnit));
3584 + }
3585 + } else {
3586 + MV_PRINT(MV_DEBUG_PHYSETUP,
3587 + ("No ports configured for ethmac%d\n", ethUnit));
3588 + }
3589 +}
3590 +
3591 +/******************************************************************************
3592 +*
3593 +* mv_phySetup - reset and setup the PHY switch.
3594 +*
3595 +* Resets each PHY port.
3596 +*
3597 +* RETURNS:
3598 +* TRUE --> at least 1 PHY with LINK
3599 +* FALSE --> no LINKs on this ethernet unit
3600 +*/
3601 +BOOL
3602 +mv_phySetup(int ethUnit, UINT32 phyBase)
3603 +{
3604 + int phyUnit;
3605 + int liveLinks = 0;
3606 + BOOL foundPhy = FALSE;
3607 + UINT32 phyAddr;
3608 + UINT16 atuControl;
3609 +
3610 + /*
3611 + * Allow platform-specific code to determine the default Ethernet MAC
3612 + * at run-time. If phyEthMacDefault returns a negative value, use the
3613 + * static mvPhyInfo table "as is". But if phyEthMacDefault returns a
3614 + * non-negative value, use it as the default ethernet unit.
3615 + */
3616 + {
3617 + int ethMacDefault = phyEthMacDefault();
3618 +
3619 + if (ethMacDefault >= 0) {
3620 + for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
3621 + MV_ETHUNIT(phyUnit)=ethMacDefault;
3622 + }
3623 + }
3624 + }
3625 +
3626 + /*
3627 + * See if there's any configuration data for this enet,
3628 + * and set up phyBase in table.
3629 + */
3630 + for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
3631 + if (MV_ETHUNIT(phyUnit) != ethUnit) {
3632 + continue;
3633 + }
3634 +
3635 + MV_PHYBASE(phyUnit) = phyBase;
3636 + foundPhy = TRUE;
3637 + }
3638 +
3639 + if (!foundPhy) {
3640 + return FALSE; /* No PHY's configured for this ethUnit */
3641 + }
3642 +
3643 + /* Verify that the switch is what we think it is, and that it's ready */
3644 + mv_verifyReady(ethUnit);
3645 +
3646 + /* Initialize global switch settings */
3647 + atuControl = MV_ATUCTRL_AGE_TIME_DEFAULT << MV_ATUCTRL_AGE_TIME_SHIFT;
3648 + atuControl |= MV_ATUCTRL_ATU_SIZE_DEFAULT << MV_ATUCTRL_ATU_SIZE_SHIFT;
3649 + // atuControl |= MV_ATUCTRL_ATU_LEARNDIS;
3650 + phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_CONTROL, atuControl);
3651 +
3652 + /* Reset PHYs and start autonegoation on each. */
3653 + for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
3654 + if (MV_ETHUNIT(phyUnit) != ethUnit) {
3655 + continue;
3656 + }
3657 +
3658 + phyBase = MV_PHYBASE(phyUnit);
3659 + phyAddr = MV_PHYADDR(phyUnit);
3660 +
3661 + phyRegWrite(phyBase, phyAddr, MV_PHY_CONTROL,
3662 + MV_CTRL_SOFTWARE_RESET | MV_CTRL_AUTONEGOTIATION_ENABLE);
3663 + }
3664 +
3665 + {
3666 + int timeout;
3667 + UINT16 phyHwStatus;
3668 +
3669 + /*
3670 + * Wait 5 seconds for ALL associated PHYs to finish autonegotiation.
3671 + */
3672 + timeout=50;
3673 + for (phyUnit=0; (phyUnit < MV_PHY_MAX) && (timeout > 0); phyUnit++) {
3674 + if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
3675 + continue;
3676 + }
3677 + for (;;) {
3678 + phyBase = MV_PHYBASE(phyUnit);
3679 + phyAddr = MV_PHYADDR(phyUnit);
3680 +
3681 + phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
3682 +
3683 + if (MV_AUTONEG_DONE(phyHwStatus)) {
3684 + break;
3685 + }
3686 +
3687 + if (--timeout == 0) {
3688 + break;
3689 + }
3690 +
3691 + sysMsDelay(100);
3692 + }
3693 + }
3694 + }
3695 +
3696 + /*
3697 + * All PHYs have had adequate time to autonegotiate.
3698 + * Now initialize software status.
3699 + *
3700 + * It's possible that some ports may take a bit longer
3701 + * to autonegotiate; but we can't wait forever. They'll
3702 + * get noticed by mv_phyCheckStatusChange during regular
3703 + * polling activities.
3704 + */
3705 + for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
3706 + if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
3707 + continue;
3708 + }
3709 +
3710 + if (mv_phyIsLinkAlive(phyUnit)) {
3711 + liveLinks++;
3712 + MV_IS_PHY_ALIVE(phyUnit) = TRUE;
3713 +#ifdef DEBUG
3714 + mv_phyShow(phyUnit);
3715 +#endif
3716 + } else {
3717 + MV_IS_PHY_ALIVE(phyUnit) = FALSE;
3718 + }
3719 +
3720 + MV_PRINT(MV_DEBUG_PHYSETUP,
3721 + ("ethmac%d: Phy Status=%4.4x\n",
3722 + ethUnit,
3723 + phyRegRead(MV_PHYBASE(phyUnit),
3724 + MV_PHYADDR(phyUnit),
3725 + MV_PHY_SPECIFIC_STATUS)));
3726 +
3727 + }
3728 +
3729 +#ifdef DEBUG
3730 + /* PHY 5 is the connection to the CPU */
3731 + mv_phyShow(5);
3732 +#endif
3733 +
3734 + mv_VLANInit(ethUnit);
3735 +
3736 + mv_enableConfiguredPorts(ethUnit);
3737 +
3738 + return (liveLinks > 0);
3739 +}
3740 +
3741 +
3742 +/******************************************************************************
3743 +*
3744 +* mv_phyIsDuplexFull - Determines whether the phy ports associated with the
3745 +* specified device are FULL or HALF duplex.
3746 +*
3747 +* RETURNS:
3748 +* TRUE --> at least one associated PHY in FULL DUPLEX
3749 +* FALSE --> all half duplex, or no links
3750 +*/
3751 +BOOL
3752 +mv_phyIsFullDuplex(int ethUnit)
3753 +{
3754 + int phyUnit;
3755 + UINT32 phyBase;
3756 + UINT32 phyAddr;
3757 + UINT16 phyHwStatus;
3758 +
3759 + for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
3760 +
3761 + if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
3762 + continue;
3763 + }
3764 +
3765 + if (mv_phyIsLinkAlive(phyUnit)) {
3766 +
3767 + phyBase = MV_PHYBASE(phyUnit);
3768 + phyAddr = MV_PHYADDR(phyUnit);
3769 +
3770 + phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
3771 +
3772 + if (phyHwStatus & MV_STATUS_RESOLVED_DUPLEX_FULL) {
3773 + return TRUE;
3774 + }
3775 + }
3776 + }
3777 +
3778 + return FALSE;
3779 +}
3780 +
3781 +/******************************************************************************
3782 +*
3783 +* mv_phyIsSpeed100 - Determines the speed of a phy port
3784 +*
3785 +* RETURNS:
3786 +* TRUE --> PHY operating at 100 Mbit
3787 +* FALSE --> link down, or not operating at 100 Mbit
3788 +*/
3789 +BOOL
3790 +mv_phyIsSpeed100(int phyUnit)
3791 +{
3792 + UINT16 phyHwStatus;
3793 + UINT32 phyBase;
3794 + UINT32 phyAddr;
3795 +
3796 + if (MV_IS_ENET_PORT(phyUnit)) {
3797 + if (mv_phyIsLinkAlive(phyUnit)) {
3798 +
3799 + phyBase = MV_PHYBASE(phyUnit);
3800 + phyAddr = MV_PHYADDR(phyUnit);
3801 +
3802 + phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
3803 +
3804 + if (phyHwStatus & MV_STATUS_RESOLVED_SPEED_100) {
3805 + return TRUE;
3806 + }
3807 + }
3808 + }
3809 +
3810 + return FALSE;
3811 +}
3812 +
3813 +#ifdef CONFIG_VENETDEV
3814 +/******************************************************************************
3815 +*
3816 +* mv_phyDetermineSource - Examine a received frame's Egress Trailer
3817 +* to determine whether it came from a LAN or WAN port.
3818 +*
3819 +* RETURNS:
3820 +* Returns 1-->LAN, 0-->WAN, -1-->ERROR
3821 +*/
3822 +int
3823 +mv_phyDetermineSource(char *data, int len)
3824 +{
3825 + unsigned char *phyTrailer;
3826 + unsigned char incomingPort;
3827 +
3828 + phyTrailer = &data[len - MV_PHY_TRAILER_SIZE];
3829 +
3830 + /* ASSERT(phyTrailer[0] == MV_EGRESS_TRAILER_VALID); */
3831 + if (phyTrailer[0] != MV_EGRESS_TRAILER_VALID) {
3832 + printk(KERN_ERR "PHY trailer invalid; got %#02x, expected %#02x\n",
3833 + phyTrailer[0], MV_EGRESS_TRAILER_VALID);
3834 + return -1;
3835 + }
3836 +
3837 + incomingPort = phyTrailer[1];
3838 + if (MV_IS_LAN_PORT(incomingPort)) {
3839 + return 1;
3840 + } else {
3841 + /* ASSERT(MV_IS_WAN_PORT(incomingPort)); */
3842 + if (!MV_IS_WAN_PORT(incomingPort)) {
3843 + printk(KERN_ERR "incoming port was %d; expected 0-4\n", incomingPort);
3844 + return -1;
3845 + }
3846 + return 0;
3847 + }
3848 +}
3849 +
3850 +
3851 +/******************************************************************************
3852 +*
3853 +* mv_phySetDestinationPort - Set the Ingress Trailer to force the
3854 +* frame to be sent to LAN or WAN, as specified.
3855 +*
3856 +*/
3857 +void
3858 +mv_phySetDestinationPort(char *data, int len, int fromLAN)
3859 +{
3860 + char *phyTrailer;
3861 +
3862 + phyTrailer = &data[len];
3863 + if (fromLAN) {
3864 + /* LAN ports: Use default settings, as per mvPhyInfo */
3865 + phyTrailer[0] = 0x00;
3866 + phyTrailer[1] = 0x00;
3867 + } else {
3868 + /* WAN port: Direct to WAN port */
3869 + phyTrailer[0] = MV_INGRESS_TRAILER_OVERRIDE;
3870 + phyTrailer[1] = 1 << MV_WAN_PORT;
3871 + }
3872 + phyTrailer[2] = 0x00;
3873 + phyTrailer[3] = 0x00;
3874 +}
3875 +#endif
3876 +
3877 +
3878 +/*****************************************************************************
3879 +*
3880 +* Validate that the specified PHY unit number is a valid PHY ID.
3881 +* Print a message if it is invalid.
3882 +* RETURNS
3883 +* TRUE --> valid
3884 +* FALSE --> invalid
3885 +*/
3886 +LOCAL BOOL
3887 +mv_validPhyId(int phyUnit)
3888 +{
3889 + if ((phyUnit >= MV_ID_MIN) && (phyUnit <= MV_ID_MAX)) {
3890 + return TRUE;
3891 + } else {
3892 + PRINTF("PHY unit number must be in the range [%d..%d]\n",
3893 + MV_ID_MIN, MV_ID_MAX);
3894 + return FALSE;
3895 + }
3896 +}
3897 +
3898 +
3899 +/*****************************************************************************
3900 +*
3901 +* mv_waitWhileATUBusy - spins until the ATU completes
3902 +* its previous operation.
3903 +*/
3904 +LOCAL void
3905 +mv_waitWhileATUBusy(UINT32 phyBase)
3906 +{
3907 + BOOL isBusy;
3908 + UINT16 ATUOperation;
3909 +
3910 + do {
3911 +
3912 + ATUOperation = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
3913 + MV_ATU_OPERATION);
3914 +
3915 + isBusy = (ATUOperation & MV_ATU_BUSY_MASK) == MV_ATU_IS_BUSY;
3916 +
3917 + } while(isBusy);
3918 +}
3919 +
3920 +/*****************************************************************************
3921 +*
3922 +* mv_flushATUDB - flushes ALL entries in the Address Translation Unit
3923 +* DataBase associated with phyUnit. [Since we use a single DB for
3924 +* all PHYs, this flushes the entire shared DataBase.]
3925 +*
3926 +* The current implementation flushes even more than absolutely needed --
3927 +* it flushes all entries for all phyUnits on the same ethernet as the
3928 +* specified phyUnit.
3929 +*
3930 +* It is called only when a link failure is detected on a port that was
3931 +* previously working. In other words, when the cable is unplugged.
3932 +*/
3933 +void
3934 +mv_flushATUDB(int phyUnit)
3935 +{
3936 + UINT32 phyBase;
3937 +
3938 + if (!mv_validPhyId(phyUnit)) {
3939 + PRINTF("Invalid port number: %d\n", phyUnit);
3940 + return;
3941 + }
3942 +
3943 + phyBase = MV_PHYBASE(phyUnit);
3944 +
3945 + /* Wait for previous operation (if any) to complete */
3946 + mv_waitWhileATUBusy(phyBase);
3947 +
3948 + /* Tell hardware to flush all entries */
3949 + phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_OPERATION,
3950 + MV_ATU_OP_FLUSH_ALL | MV_ATU_IS_BUSY);
3951 +
3952 + mv_waitWhileATUBusy(phyBase);
3953 +}
3954 +
3955 +/*****************************************************************************
3956 +*
3957 +* mv_phyCheckStatusChange -- checks for significant changes in PHY state.
3958 +*
3959 +* A "significant change" is:
3960 +* dropped link (e.g. ethernet cable unplugged) OR
3961 +* autonegotiation completed + link (e.g. ethernet cable plugged in)
3962 +*/
3963 +void
3964 +mv_phyCheckStatusChange(int ethUnit)
3965 +{
3966 + int phyUnit;
3967 + UINT16 phyHwStatus;
3968 + mvPhyInfo_t *lastStatus;
3969 + int linkCount = 0;
3970 + int lostLinks = 0;
3971 + int gainedLinks = 0;
3972 + UINT32 phyBase;
3973 + UINT32 phyAddr;
3974 +
3975 + for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
3976 + if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
3977 + continue;
3978 + }
3979 +
3980 + phyBase = MV_PHYBASE(phyUnit);
3981 + phyAddr = MV_PHYADDR(phyUnit);
3982 +
3983 + lastStatus = &mvPhyInfo[phyUnit];
3984 + phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
3985 +
3986 + if (lastStatus->isPhyAlive) { /* last known link status was ALIVE */
3987 + /* See if we've lost link */
3988 + if (phyHwStatus & MV_STATUS_REAL_TIME_LINK_UP) {
3989 + linkCount++;
3990 + } else {
3991 + lostLinks++;
3992 + mv_flushATUDB(phyUnit);
3993 + MV_PRINT(MV_DEBUG_PHYCHANGE,("\nethmac%d port%d down\n",
3994 + ethUnit, phyUnit));
3995 + lastStatus->isPhyAlive = FALSE;
3996 + }
3997 + } else { /* last known link status was DEAD */
3998 + /* Check for AutoNegotiation complete */
3999 + if (MV_AUTONEG_DONE(phyHwStatus)) {
4000 + gainedLinks++;
4001 + linkCount++;
4002 + MV_PRINT(MV_DEBUG_PHYCHANGE,("\nethmac%d port%d up\n",
4003 + ethUnit, phyUnit));
4004 + lastStatus->isPhyAlive = TRUE;
4005 + }
4006 + }
4007 + }
4008 +
4009 + if (linkCount == 0) {
4010 + if (lostLinks) {
4011 + /* We just lost the last link for this MAC */
4012 + phyLinkLost(ethUnit);
4013 + }
4014 + } else {
4015 + if (gainedLinks == linkCount) {
4016 + /* We just gained our first link(s) for this MAC */
4017 + phyLinkGained(ethUnit);
4018 + }
4019 + }
4020 +}
4021 +
4022 +#if DEBUG
4023 +
4024 +/* Define the registers of interest for a phyShow command */
4025 +typedef struct mvRegisterTableEntry_s {
4026 + UINT32 regNum;
4027 + char *regIdString;
4028 +} mvRegisterTableEntry_t;
4029 +
4030 +mvRegisterTableEntry_t mvPhyRegisterTable[] = {
4031 + {MV_PHY_CONTROL, "PHY Control "},
4032 + {MV_PHY_STATUS, "PHY Status "},
4033 + {MV_PHY_ID1, "PHY Identifier 1 "},
4034 + {MV_PHY_ID2, "PHY Identifier 2 "},
4035 + {MV_AUTONEG_ADVERT, "Auto-Negotiation Advertisement "},
4036 + {MV_LINK_PARTNER_ABILITY, "Link Partner Ability "},
4037 + {MV_AUTONEG_EXPANSION, "Auto-Negotiation Expansion "},
4038 + {MV_NEXT_PAGE_TRANSMIT, "Next Page Transmit "},
4039 + {MV_LINK_PARTNER_NEXT_PAGE, "Link Partner Next Page "},
4040 + {MV_PHY_SPECIFIC_CONTROL_1, "PHY-Specific Control Register 1 "},
4041 + {MV_PHY_SPECIFIC_STATUS, "PHY-Specific Status "},
4042 + {MV_PHY_INTERRUPT_ENABLE, "PHY Interrupt Enable "},
4043 + {MV_PHY_INTERRUPT_STATUS, "PHY Interrupt Status "},
4044 + {MV_PHY_INTERRUPT_PORT_SUMMARY, "PHY Interrupt Port Summary "},
4045 + {MV_RECEIVE_ERROR_COUNTER, "Receive Error Counter "},
4046 + {MV_LED_PARALLEL_SELECT, "LED Parallel Select "},
4047 + {MV_LED_STREAM_SELECT_LEDS, "LED Stream Select "},
4048 + {MV_PHY_LED_CONTROL, "PHY LED Control "},
4049 + {MV_PHY_MANUAL_LED_OVERRIDE, "PHY Manual LED Override "},
4050 + {MV_VCT_CONTROL, "VCT Control "},
4051 + {MV_VCT_STATUS, "VCT Status "},
4052 + {MV_PHY_SPECIFIC_CONTROL_2, "PHY-Specific Control Register 2 "},
4053 +};
4054 +int mvPhyNumRegs = sizeof(mvPhyRegisterTable) / sizeof(mvPhyRegisterTable[0]);
4055 +
4056 +
4057 +mvRegisterTableEntry_t mvSwitchPortRegisterTable[] = {
4058 + {MV_PORT_STATUS, "Port Status "},
4059 + {MV_SWITCH_ID, "Switch ID "},
4060 + {MV_PORT_CONTROL, "Port Control "},
4061 + {MV_PORT_BASED_VLAN_MAP, "Port-Based VLAN Map "},
4062 + {MV_PORT_ASSOCIATION_VECTOR, "Port Association Vector "},
4063 + {MV_RX_COUNTER, "RX Counter "},
4064 + {MV_TX_COUNTER, "TX Counter "},
4065 +};
4066 +int mvSwitchPortNumRegs =
4067 + sizeof(mvSwitchPortRegisterTable) / sizeof(mvSwitchPortRegisterTable[0]);
4068 +
4069 +
4070 +mvRegisterTableEntry_t mvSwitchGlobalRegisterTable[] = {
4071 + {MV_SWITCH_GLOBAL_STATUS, "Switch Global Status "},
4072 + {MV_SWITCH_MAC_ADDR0, "Switch MAC Addr 0 & 1 "},
4073 + {MV_SWITCH_MAC_ADDR2, "Switch MAC Addr 2 & 3 "},
4074 + {MV_SWITCH_MAC_ADDR4, "Switch MAC Addr 4 & 5 "},
4075 + {MV_SWITCH_GLOBAL_CONTROL, "Switch Global Control "},
4076 + {MV_ATU_CONTROL, "ATU Control "},
4077 + {MV_ATU_OPERATION, "ATU Operation "},
4078 + {MV_ATU_DATA, "ATU Data "},
4079 + {MV_ATU_MAC_ADDR0, "ATU MAC Addr 0 & 1 "},
4080 + {MV_ATU_MAC_ADDR2, "ATU MAC Addr 2 & 3 "},
4081 + {MV_ATU_MAC_ADDR4, "ATU MAC Addr 4 & 5 "},
4082 +};
4083 +int mvSwitchGlobalNumRegs =
4084 + sizeof(mvSwitchGlobalRegisterTable) / sizeof(mvSwitchGlobalRegisterTable[0]);
4085 +
4086 +
4087 +/*****************************************************************************
4088 +*
4089 +* mv_phyShow - Dump the state of a PHY.
4090 +* There are two sets of registers for each phy port:
4091 +* "phy registers" and
4092 +* "switch port registers"
4093 +* We dump 'em all, plus the switch global registers.
4094 +*/
4095 +void
4096 +mv_phyShow(int phyUnit)
4097 +{
4098 + int i;
4099 + UINT16 value;
4100 + UINT32 phyBase;
4101 + UINT32 phyAddr;
4102 + UINT32 switchPortAddr;
4103 +
4104 + if (!mv_validPhyId(phyUnit)) {
4105 + return;
4106 + }
4107 +
4108 + phyBase = MV_PHYBASE(phyUnit);
4109 + phyAddr = MV_PHYADDR(phyUnit);
4110 + switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
4111 +
4112 + PRINTF("PHY state for PHY%d (ethmac%d, phyBase 0x%8x, phyAddr 0x%x, switchAddr 0x%x)\n",
4113 + phyUnit,
4114 + MV_ETHUNIT(phyUnit),
4115 + MV_PHYBASE(phyUnit),
4116 + MV_PHYADDR(phyUnit),
4117 + MV_SWITCH_PORT_ADDR(phyUnit));
4118 +
4119 + PRINTF("PHY Registers:\n");
4120 + for (i=0; i < mvPhyNumRegs; i++) {
4121 +
4122 + value = phyRegRead(phyBase, phyAddr, mvPhyRegisterTable[i].regNum);
4123 +
4124 + PRINTF("Reg %02d (0x%02x) %s = 0x%08x\n",
4125 + mvPhyRegisterTable[i].regNum,
4126 + mvPhyRegisterTable[i].regNum,
4127 + mvPhyRegisterTable[i].regIdString,
4128 + value);
4129 + }
4130 +
4131 + PRINTF("Switch Port Registers:\n");
4132 + for (i=0; i < mvSwitchPortNumRegs; i++) {
4133 +
4134 + value = phyRegRead(phyBase, switchPortAddr,
4135 + mvSwitchPortRegisterTable[i].regNum);
4136 +
4137 + PRINTF("Reg %02d (0x%02x) %s = 0x%08x\n",
4138 + mvSwitchPortRegisterTable[i].regNum,
4139 + mvSwitchPortRegisterTable[i].regNum,
4140 + mvSwitchPortRegisterTable[i].regIdString,
4141 + value);
4142 + }
4143 +
4144 + PRINTF("Switch Global Registers:\n");
4145 + for (i=0; i < mvSwitchGlobalNumRegs; i++) {
4146 +
4147 + value = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
4148 + mvSwitchGlobalRegisterTable[i].regNum);
4149 +
4150 + PRINTF("Reg %02d (0x%02x) %s = 0x%08x\n",
4151 + mvSwitchGlobalRegisterTable[i].regNum,
4152 + mvSwitchGlobalRegisterTable[i].regNum,
4153 + mvSwitchGlobalRegisterTable[i].regIdString,
4154 + value);
4155 + }
4156 +}
4157 +
4158 +/*****************************************************************************
4159 +*
4160 +* mv_phySet - Modify the value of a PHY register (debug only).
4161 +*/
4162 +void
4163 +mv_phySet(int phyUnit, UINT32 regnum, UINT32 value)
4164 +{
4165 + UINT32 phyBase;
4166 + UINT32 phyAddr;
4167 +
4168 + if (mv_validPhyId(phyUnit)) {
4169 +
4170 + phyBase = MV_PHYBASE(phyUnit);
4171 + phyAddr = MV_PHYADDR(phyUnit);
4172 +
4173 + phyRegWrite(phyBase, phyAddr, regnum, value);
4174 + }
4175 +}
4176 +
4177 +
4178 +/*****************************************************************************
4179 +*
4180 +* mv_switchPortSet - Modify the value of a switch port register (debug only).
4181 +*/
4182 +void
4183 +mv_switchPortSet(int phyUnit, UINT32 regnum, UINT32 value)
4184 +{
4185 + UINT32 phyBase;
4186 + UINT32 switchPortAddr;
4187 +
4188 + if (mv_validPhyId(phyUnit)) {
4189 +
4190 + phyBase = MV_PHYBASE(phyUnit);
4191 + switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
4192 +
4193 + phyRegWrite(phyBase, switchPortAddr, regnum, value);
4194 + }
4195 +}
4196 +
4197 +/*****************************************************************************
4198 +*
4199 +* mv_switchGlobalSet - Modify the value of a switch global register
4200 +* (debug only).
4201 +*/
4202 +void
4203 +mv_switchGlobalSet(int phyUnit, UINT32 regnum, UINT32 value)
4204 +{
4205 + UINT32 phyBase;
4206 +
4207 + if (mv_validPhyId(phyUnit)) {
4208 +
4209 + phyBase = MV_PHYBASE(phyUnit);
4210 +
4211 + phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, regnum, value);
4212 + }
4213 +}
4214 +
4215 +/*****************************************************************************
4216 +*
4217 +* mv_showATUDB - Dump the contents of the Address Translation Unit DataBase
4218 +* for the PHY switch associated with the specified phy.
4219 +*/
4220 +void
4221 +mv_showATUDB(int phyUnit)
4222 +{
4223 + UINT32 phyBase;
4224 + UINT16 ATUData;
4225 + UINT16 ATUMac0;
4226 + UINT16 ATUMac2;
4227 + UINT16 ATUMac4;
4228 + int portVec;
4229 + int entryState;
4230 +
4231 + if (!mv_validPhyId(phyUnit)) {
4232 + PRINTF("Invalid port number: %d\n", phyUnit);
4233 + return;
4234 + }
4235 +
4236 + phyBase = MV_PHYBASE(phyUnit);
4237 +
4238 + /* Wait for previous operation (if any) to complete */
4239 + mv_waitWhileATUBusy(phyBase);
4240 +
4241 + /* Initialize ATU MAC to all 1's */
4242 + phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR0, 0xffff);
4243 + phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR2, 0xffff);
4244 + phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR4, 0xffff);
4245 +
4246 + PRINTF(" MAC ADDRESS EntryState PortVector\n");
4247 +
4248 + for(;;) {
4249 + /* Tell hardware to get next MAC info */
4250 + phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_OPERATION,
4251 + MV_ATU_OP_GET_NEXT | MV_ATU_IS_BUSY);
4252 +
4253 + mv_waitWhileATUBusy(phyBase);
4254 +
4255 + ATUData = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_DATA);
4256 + entryState = (ATUData & MV_ENTRYSTATE_MASK) >> MV_ENTRYSTATE_SHIFT;
4257 +
4258 + if (entryState == 0) {
4259 + /* We've hit the end of the list */
4260 + break;
4261 + }
4262 +
4263 + ATUMac0 = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR0);
4264 + ATUMac2 = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR2);
4265 + ATUMac4 = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR4);
4266 +
4267 + portVec = (ATUData & MV_PORTVEC_MASK) >> MV_PORTVEC_SHIFT;
4268 +
4269 + PRINTF("%02x:%02x:%02x:%02x:%02x:%02x 0x%02x 0x%02x\n",
4270 + ATUMac0 >> 8, /* MAC byte 0 */
4271 + ATUMac0 & 0xff, /* MAC byte 1 */
4272 + ATUMac2 >> 8, /* MAC byte 2 */
4273 + ATUMac2 & 0xff, /* MAC byte 3 */
4274 + ATUMac4 >> 8, /* MAC byte 4 */
4275 + ATUMac4 & 0xff, /* MAC byte 5 */
4276 + entryState,
4277 + portVec);
4278 + }
4279 +}
4280 +
4281 +LOCAL BOOL countingGoodFrames;
4282 +
4283 +/*****************************************************************************
4284 +*
4285 +* mv_countGoodFrames - starts counting GOOD RX/TX frames per port
4286 +*/
4287 +void
4288 +mv_countGoodFrames(int phyUnit)
4289 +{
4290 + UINT32 phyBase;
4291 + UINT16 globalControl;
4292 +
4293 + if (mv_validPhyId(phyUnit)) {
4294 + /*
4295 + * Guarantee that counters are cleared by
4296 + * forcing CtrMode to toggle and end on GOODFRAMES.
4297 + */
4298 +
4299 + phyBase = MV_PHYBASE(phyUnit);
4300 +
4301 + /* Read current Switch Global Control Register */
4302 + globalControl = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
4303 + MV_SWITCH_GLOBAL_CONTROL);
4304 +
4305 + /* Set CtrMode to count BAD frames */
4306 + globalControl = ((globalControl & ~MV_CTRMODE_MASK) |
4307 + MV_CTRMODE_BADFRAMES);
4308 +
4309 + /* Push new value out to hardware */
4310 + phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR,
4311 + MV_SWITCH_GLOBAL_CONTROL, globalControl);
4312 +
4313 + /* Now toggle CtrMode to count GOOD frames */
4314 + globalControl = ((globalControl & ~MV_CTRMODE_MASK) |
4315 + MV_CTRMODE_GOODFRAMES);
4316 +
4317 + /* Push new value out to hardware */
4318 + phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR,
4319 + MV_SWITCH_GLOBAL_CONTROL, globalControl);
4320 +
4321 + countingGoodFrames = TRUE;
4322 + }
4323 +}
4324 +
4325 +/*****************************************************************************
4326 +*
4327 +* mv_countBadFrames - starts counting BAD RX/TX frames per port
4328 +*/
4329 +void
4330 +mv_countBadFrames(int phyUnit)
4331 +{
4332 + UINT32 phyBase;
4333 + UINT16 globalControl;
4334 +
4335 + if (mv_validPhyId(phyUnit)) {
4336 + /*
4337 + * Guarantee that counters are cleared by
4338 + * forcing CtrMode to toggle and end on BADFRAMES.
4339 + */
4340 +
4341 + phyBase = MV_PHYBASE(phyUnit);
4342 +
4343 + /* Read current Switch Global Control Register */
4344 + globalControl = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
4345 + MV_SWITCH_GLOBAL_CONTROL);
4346 +
4347 + /* Set CtrMode to count GOOD frames */
4348 + globalControl = ((globalControl & ~MV_CTRMODE_MASK) |
4349 + MV_CTRMODE_GOODFRAMES);
4350 +
4351 + /* Push new value out to hardware */
4352 + phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR,
4353 + MV_SWITCH_GLOBAL_CONTROL, globalControl);
4354 +
4355 + /* Now toggle CtrMode to count BAD frames */
4356 + globalControl = ((globalControl & ~MV_CTRMODE_MASK) |
4357 + MV_CTRMODE_BADFRAMES);
4358 +
4359 + /* Push new value out to hardware */
4360 + phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR,
4361 + MV_SWITCH_GLOBAL_CONTROL, globalControl);
4362 +
4363 + countingGoodFrames = FALSE;
4364 + }
4365 +}
4366 +
4367 +/*****************************************************************************
4368 +*
4369 +* mv_showFrameCounts - shows current GOOD/BAD Frame counts
4370 +*/
4371 +void
4372 +mv_showFrameCounts(int phyUnit)
4373 +{
4374 + UINT16 rxCounter;
4375 + UINT16 txCounter;
4376 + UINT32 phyBase;
4377 + UINT32 switchPortAddr;
4378 +
4379 + if (!mv_validPhyId(phyUnit)) {
4380 + return;
4381 + }
4382 +
4383 + phyBase = MV_PHYBASE(phyUnit);
4384 + switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
4385 +
4386 + rxCounter = phyRegRead(phyBase, switchPortAddr, MV_RX_COUNTER);
4387 +
4388 + txCounter = phyRegRead(phyBase, switchPortAddr, MV_TX_COUNTER);
4389 +
4390 + PRINTF("port%d %s frames: receive: %05d transmit: %05d\n",
4391 + phyUnit,
4392 + (countingGoodFrames ? "good" : "error"),
4393 + rxCounter,
4394 + txCounter);
4395 +}
4396 +#endif
4397 diff -urN linux-2.4.32.new/arch/mips/ar531x/mvPhy.h linux-2.4.32.new-eth/arch/mips/ar531x/mvPhy.h
4398 --- linux-2.4.32.new/arch/mips/ar531x/mvPhy.h 1970-01-01 01:00:00.000000000 +0100
4399 +++ linux-2.4.32.new-eth/arch/mips/ar531x/mvPhy.h 2005-12-25 11:54:39.775382608 +0000
4400 @@ -0,0 +1,160 @@
4401 +/*
4402 + * This file is subject to the terms and conditions of the GNU General Public
4403 + * License. See the file "COPYING" in the main directory of this archive
4404 + * for more details.
4405 + *
4406 + * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
4407 + */
4408 +
4409 +/*
4410 + * mvPhy.h - definitions for the ethernet PHY -- Marvell 88E6060
4411 + * All definitions in this file are operating system independent!
4412 + */
4413 +
4414 +#ifndef MVPHY_H
4415 +#define MVPHY_H
4416 +
4417 +/*****************/
4418 +/* PHY Registers */
4419 +/*****************/
4420 +#define MV_PHY_CONTROL 0
4421 +#define MV_PHY_STATUS 1
4422 +#define MV_PHY_ID1 2
4423 +#define MV_PHY_ID2 3
4424 +#define MV_AUTONEG_ADVERT 4
4425 +#define MV_LINK_PARTNER_ABILITY 5
4426 +#define MV_AUTONEG_EXPANSION 6
4427 +#define MV_NEXT_PAGE_TRANSMIT 7
4428 +#define MV_LINK_PARTNER_NEXT_PAGE 8
4429 +#define MV_PHY_SPECIFIC_CONTROL_1 16
4430 +#define MV_PHY_SPECIFIC_STATUS 17
4431 +#define MV_PHY_INTERRUPT_ENABLE 18
4432 +#define MV_PHY_INTERRUPT_STATUS 19
4433 +#define MV_PHY_INTERRUPT_PORT_SUMMARY 20
4434 +#define MV_RECEIVE_ERROR_COUNTER 21
4435 +#define MV_LED_PARALLEL_SELECT 22
4436 +#define MV_LED_STREAM_SELECT_LEDS 23
4437 +#define MV_PHY_LED_CONTROL 24
4438 +#define MV_PHY_MANUAL_LED_OVERRIDE 25
4439 +#define MV_VCT_CONTROL 26
4440 +#define MV_VCT_STATUS 27
4441 +#define MV_PHY_SPECIFIC_CONTROL_2 28
4442 +
4443 +/* MV_PHY_CONTROL fields */
4444 +#define MV_CTRL_SOFTWARE_RESET 0x8000
4445 +#define MV_CTRL_AUTONEGOTIATION_ENABLE 0x1000
4446 +
4447 +/* MV_PHY_ID1 fields */
4448 +#define MV_PHY_ID1_EXPECTATION 0x0141 /* OUI >> 6 */
4449 +
4450 +/* MV_PHY_ID2 fields */
4451 +#define MV_OUI_LSB_MASK 0xfc00
4452 +#define MV_OUI_LSB_EXPECTATION 0x0c00
4453 +#define MV_OUI_LSB_SHIFT 10
4454 +#define MV_MODEL_NUM_MASK 0x03f0
4455 +#define MV_MODEL_NUM_SHIFT 4
4456 +#define MV_REV_NUM_MASK 0x000f
4457 +#define MV_REV_NUM_SHIFT 0
4458 +
4459 +/* MV_PHY_SPECIFIC_STATUS fields */
4460 +#define MV_STATUS_RESOLVED_SPEED_100 0x4000
4461 +#define MV_STATUS_RESOLVED_DUPLEX_FULL 0x2000
4462 +#define MV_STATUS_RESOLVED 0x0800
4463 +#define MV_STATUS_REAL_TIME_LINK_UP 0x0400
4464 +
4465 +/* Check if autonegotiation is complete and link is up */
4466 +#define MV_AUTONEG_DONE(mv_phy_specific_status) \
4467 + (((mv_phy_specific_status) & \
4468 + (MV_STATUS_RESOLVED | MV_STATUS_REAL_TIME_LINK_UP)) == \
4469 + (MV_STATUS_RESOLVED | MV_STATUS_REAL_TIME_LINK_UP))
4470 +
4471 +
4472 +/*************************/
4473 +/* Switch Port Registers */
4474 +/*************************/
4475 +#define MV_PORT_STATUS 0
4476 +#define MV_SWITCH_ID 3
4477 +#define MV_PORT_CONTROL 4
4478 +#define MV_PORT_BASED_VLAN_MAP 6
4479 +#define MV_PORT_ASSOCIATION_VECTOR 11
4480 +#define MV_RX_COUNTER 16
4481 +#define MV_TX_COUNTER 17
4482 +
4483 +/* MV_SWITCH_ID fields */
4484 +#define MV_SWITCH_ID_DEV_MASK 0xfff0
4485 +#define MV_SWITCH_ID_DEV_EXPECTATION 0x0600
4486 +#define MV_SWITCH_ID_DEV_SHIFT 4
4487 +#define MV_SWITCH_ID_REV_MASK 0x000f
4488 +#define MV_SWITCH_ID_REV_SHIFT 0
4489 +
4490 +/* MV_PORT_CONTROL fields */
4491 +#define MV_PORT_CONTROL_PORT_STATE_MASK 0x0003
4492 +#define MV_PORT_CONTROL_PORT_STATE_DISABLED 0x0000
4493 +#define MV_PORT_CONTROL_PORT_STATE_FORWARDING 0x0003
4494 +
4495 +#define MV_PORT_CONTROL_EGRESS_MODE 0x0100 /* Receive */
4496 +#define MV_PORT_CONTROL_INGRESS_TRAILER 0x4000 /* Transmit */
4497 +
4498 +#define MV_EGRESS_TRAILER_VALID 0x80
4499 +#define MV_INGRESS_TRAILER_OVERRIDE 0x80
4500 +
4501 +#define MV_PHY_TRAILER_SIZE 4
4502 +
4503 +
4504 +/***************************/
4505 +/* Switch Global Registers */
4506 +/***************************/
4507 +#define MV_SWITCH_GLOBAL_STATUS 0
4508 +#define MV_SWITCH_MAC_ADDR0 1
4509 +#define MV_SWITCH_MAC_ADDR2 2
4510 +#define MV_SWITCH_MAC_ADDR4 3
4511 +#define MV_SWITCH_GLOBAL_CONTROL 4
4512 +#define MV_ATU_CONTROL 10
4513 +#define MV_ATU_OPERATION 11
4514 +#define MV_ATU_DATA 12
4515 +#define MV_ATU_MAC_ADDR0 13
4516 +#define MV_ATU_MAC_ADDR2 14
4517 +#define MV_ATU_MAC_ADDR4 15
4518 +
4519 +/* MV_SWITCH_GLOBAL_STATUS fields */
4520 +#define MV_SWITCH_STATUS_READY_MASK 0x0800
4521 +
4522 +/* MV_SWITCH_GLOBAL_CONTROL fields */
4523 +#define MV_CTRMODE_MASK 0x0100
4524 +#define MV_CTRMODE_GOODFRAMES 0x0000
4525 +#define MV_CTRMODE_BADFRAMES 0x0100
4526 +
4527 +/* MV_ATU_CONTROL fields */
4528 +#define MV_ATUCTRL_ATU_LEARNDIS 0x4000
4529 +#define MV_ATUCTRL_ATU_SIZE_MASK 0x3000
4530 +#define MV_ATUCTRL_ATU_SIZE_SHIFT 12
4531 +#define MV_ATUCTRL_ATU_SIZE_DEFAULT 2 /* 1024 entry database */
4532 +#define MV_ATUCTRL_AGE_TIME_MASK 0x0ff0
4533 +#define MV_ATUCTRL_AGE_TIME_SHIFT 4
4534 +#define MV_ATUCTRL_AGE_TIME_DEFAULT 19 /* 19 * 16 = 304 seconds */
4535 +
4536 +/* MV_ATU_OPERATION fields */
4537 +#define MV_ATU_BUSY_MASK 0x8000
4538 +#define MV_ATU_IS_BUSY 0x8000
4539 +#define MV_ATU_IS_FREE 0x0000
4540 +#define MV_ATU_OP_MASK 0x7000
4541 +#define MV_ATU_OP_FLUSH_ALL 0x1000
4542 +#define MV_ATU_OP_GET_NEXT 0x4000
4543 +
4544 +/* MV_ATU_DATA fields */
4545 +#define MV_ENTRYPRI_MASK 0xc000
4546 +#define MV_ENTRYPRI_SHIFT 14
4547 +#define MV_PORTVEC_MASK 0x03f0
4548 +#define MV_PORTVEC_SHIFT 4
4549 +#define MV_ENTRYSTATE_MASK 0x000f
4550 +#define MV_ENTRYSTATE_SHIFT 0
4551 +
4552 +/* PHY Address for the switch itself */
4553 +#define MV_SWITCH_GLOBAL_ADDR 0x1f
4554 +
4555 +BOOL mv_phySetup(int ethUnit, UINT32 phyBase);
4556 +void mv_phyCheckStatusChange(int ethUnit);
4557 +BOOL mv_phyIsSpeed100(int ethUnit);
4558 +BOOL mv_phyIsFullDuplex(int ethUnit);
4559 +
4560 +#endif /* MVPHY_H */
4561 diff -urN linux-2.4.32.new/arch/mips/ar531x/rtPhy.c linux-2.4.32.new-eth/arch/mips/ar531x/rtPhy.c
4562 --- linux-2.4.32.new/arch/mips/ar531x/rtPhy.c 1970-01-01 01:00:00.000000000 +0100
4563 +++ linux-2.4.32.new-eth/arch/mips/ar531x/rtPhy.c 2005-12-25 11:54:46.086423184 +0000
4564 @@ -0,0 +1,272 @@
4565 +/*
4566 + * This file is subject to the terms and conditions of the GNU General Public
4567 + * License. See the file "COPYING" in the main directory of this archive
4568 + * for more details.
4569 + *
4570 + * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
4571 + */
4572 +
4573 +/*
4574 + * Manage the ethernet PHY.
4575 + * This code supports a simple 1-port ethernet phy, Realtek RTL8201BL,
4576 + * and compatible PHYs, such as the Kendin KS8721B.
4577 + * All definitions in this file are operating system independent!
4578 + */
4579 +
4580 +#if defined(linux)
4581 +#include <linux/config.h>
4582 +#include <linux/types.h>
4583 +#include <linux/netdevice.h>
4584 +#include <linux/etherdevice.h>
4585 +#include <linux/delay.h>
4586 +
4587 +#include "ar531xlnx.h"
4588 +#endif
4589 +
4590 +#if defined(__ECOS)
4591 +#include "ae531xecos.h"
4592 +#endif
4593 +
4594 +
4595 +#include "ae531xmac.h"
4596 +#include "ae531xreg.h"
4597 +#include "rtPhy.h"
4598 +
4599 +#if /* DEBUG */ 1
4600 +#define RT_DEBUG_ERROR 0x00000001
4601 +#define RT_DEBUG_PHYSETUP 0x00000002
4602 +#define RT_DEBUG_PHYCHANGE 0x00000004
4603 +
4604 +int rtPhyDebug = RT_DEBUG_ERROR;
4605 +
4606 +#define RT_PRINT(FLG, X) \
4607 +{ \
4608 + if (rtPhyDebug & (FLG)) { \
4609 + DEBUG_PRINTF X; \
4610 + } \
4611 +}
4612 +#else
4613 +#define RT_PRINT(FLG, X)
4614 +#endif
4615 +
4616 +/*
4617 + * Track per-PHY port information.
4618 + */
4619 +typedef struct {
4620 + BOOL phyAlive; /* last known state of link */
4621 + UINT32 phyBase;
4622 + UINT32 phyAddr;
4623 +} rtPhyInfo_t;
4624 +
4625 +#define ETH_PHY_ADDR 1
4626 +
4627 +/*
4628 + * This table defines the mapping from phy units to
4629 + * per-PHY information.
4630 + *
4631 + * This table is somewhat board-dependent.
4632 + */
4633 +rtPhyInfo_t rtPhyInfo[] = {
4634 + {phyAlive: FALSE, /* PHY 0 */
4635 + phyBase: 0, /* filled in by rt_phySetup */
4636 + phyAddr: ETH_PHY_ADDR},
4637 +
4638 + {phyAlive: FALSE, /* PHY 1 */
4639 + phyBase: 0, /* filled in by rt_phySetup */
4640 + phyAddr: ETH_PHY_ADDR}
4641 +};
4642 +
4643 +/* Convert from phy unit# to (phyBase, phyAddr) pair */
4644 +#define RT_PHYBASE(phyUnit) (rtPhyInfo[phyUnit].phyBase)
4645 +#define RT_PHYADDR(phyUnit) (rtPhyInfo[phyUnit].phyAddr)
4646 +
4647 +
4648 +/******************************************************************************
4649 +*
4650 +* rt_phySetup - reset and setup the PHY associated with
4651 +* the specified MAC unit number.
4652 +*
4653 +* Resets the associated PHY port.
4654 +*
4655 +* RETURNS:
4656 +* TRUE --> associated PHY is alive
4657 +* FALSE --> no LINKs on this ethernet unit
4658 +*/
4659 +
4660 +BOOL
4661 +rt_phySetup(int ethUnit, UINT32 phyBase)
4662 +{
4663 + BOOL linkAlive = FALSE;
4664 + UINT32 phyAddr;
4665 +
4666 + RT_PHYBASE(ethUnit) = phyBase;
4667 +
4668 + phyAddr = RT_PHYADDR(ethUnit);
4669 +
4670 + /* Reset phy */
4671 + phyRegWrite(phyBase, phyAddr, GEN_ctl, PHY_SW_RST | AUTONEGENA);
4672 +
4673 + sysMsDelay(1500);
4674 +
4675 + return linkAlive;
4676 +}
4677 +
4678 +/******************************************************************************
4679 +*
4680 +* rt_phyIsDuplexFull - Determines whether the phy ports associated with the
4681 +* specified device are FULL or HALF duplex.
4682 +*
4683 +* RETURNS:
4684 +* TRUE --> FULL
4685 +* FALSE --> HALF
4686 +*/
4687 +BOOL
4688 +rt_phyIsFullDuplex(int ethUnit)
4689 +{
4690 + UINT16 phyCtl;
4691 + UINT32 phyBase;
4692 + UINT32 phyAddr;
4693 +
4694 + phyBase = RT_PHYBASE(ethUnit);
4695 + phyAddr = RT_PHYADDR(ethUnit);
4696 +
4697 + phyCtl = phyRegRead(phyBase, phyAddr, GEN_ctl);
4698 +
4699 + if (phyCtl & DUPLEX) {
4700 + return TRUE;
4701 + } else {
4702 + return FALSE;
4703 + }
4704 +}
4705 +
4706 +/******************************************************************************
4707 +*
4708 +* rt_phyIsSpeed100 - Determines the speed of phy ports associated with the
4709 +* specified device.
4710 +*
4711 +* RETURNS:
4712 +* TRUE --> 100Mbit
4713 +* FALSE --> 10Mbit
4714 +*/
4715 +BOOL
4716 +rt_phyIsSpeed100(int phyUnit)
4717 +{
4718 + UINT16 phyLpa;
4719 + UINT32 phyBase;
4720 + UINT32 phyAddr;
4721 +
4722 + phyBase = RT_PHYBASE(phyUnit);
4723 + phyAddr = RT_PHYADDR(phyUnit);
4724 +
4725 + phyLpa = phyRegRead(phyBase, phyAddr, AN_lpa);
4726 +
4727 + if (phyLpa & (LPA_TXFD | LPA_TX)) {
4728 + return TRUE;
4729 + } else {
4730 + return FALSE;
4731 + }
4732 +}
4733 +
4734 +/*****************************************************************************
4735 +*
4736 +* rt_phyCheckStatusChange -- checks for significant changes in PHY state.
4737 +*
4738 +* A "significant change" is:
4739 +* dropped link (e.g. ethernet cable unplugged) OR
4740 +* autonegotiation completed + link (e.g. ethernet cable plugged in)
4741 +*
4742 +* On AR5311, there is a 1-to-1 mapping of ethernet units to PHYs.
4743 +* When a PHY is plugged in, phyLinkGained is called.
4744 +* When a PHY is unplugged, phyLinkLost is called.
4745 +*/
4746 +void
4747 +rt_phyCheckStatusChange(int ethUnit)
4748 +{
4749 + UINT16 phyHwStatus;
4750 + rtPhyInfo_t *lastStatus = &rtPhyInfo[ethUnit];
4751 + UINT32 phyBase;
4752 + UINT32 phyAddr;
4753 +
4754 + phyBase = RT_PHYBASE(ethUnit);
4755 + phyAddr = RT_PHYADDR(ethUnit);
4756 +
4757 + phyHwStatus = phyRegRead(phyBase, phyAddr, GEN_sts);
4758 +
4759 + if (lastStatus->phyAlive) { /* last known status was ALIVE */
4760 + /* See if we've lost link */
4761 + if (!(phyHwStatus & LINK)) {
4762 + RT_PRINT(RT_DEBUG_PHYCHANGE,("\nethmac%d link down\n", ethUnit));
4763 + lastStatus->phyAlive = FALSE;
4764 + phyLinkLost(ethUnit);
4765 + }
4766 + } else { /* last known status was DEAD */
4767 + /* Check for AN complete */
4768 + if ((phyHwStatus & (AUTOCMPLT | LINK)) == (AUTOCMPLT | LINK)) {
4769 + RT_PRINT(RT_DEBUG_PHYCHANGE,("\nethmac%d link up\n", ethUnit));
4770 + lastStatus->phyAlive = TRUE;
4771 + phyLinkGained(ethUnit);
4772 + }
4773 + }
4774 +}
4775 +
4776 +#if DEBUG
4777 +
4778 +/* Define the PHY registers of interest for a phyShow command */
4779 +struct rtRegisterTable_s {
4780 + UINT32 regNum;
4781 + char *regIdString;
4782 +} rtRegisterTable[] =
4783 +{
4784 + {GEN_ctl, "Basic Mode Control (GEN_ctl) "},
4785 + {GEN_sts, "Basic Mode Status (GEN_sts) "},
4786 + {GEN_id_hi, "PHY Identifier 1 (GET_id_hi) "},
4787 + {GEN_id_lo, "PHY Identifier 2 (GET_id_lo) "},
4788 + {AN_adv, "Auto-Neg Advertisement (AN_adv) "},
4789 + {AN_lpa, "Auto-Neg Link Partner Ability "},
4790 + {AN_exp, "Auto-Neg Expansion "},
4791 +};
4792 +
4793 +int rtNumRegs = sizeof(rtRegisterTable) / sizeof(rtRegisterTable[0]);
4794 +
4795 +/*
4796 + * Dump the state of a PHY.
4797 + */
4798 +void
4799 +rt_phyShow(int phyUnit)
4800 +{
4801 + int i;
4802 + UINT16 value;
4803 + UINT32 phyBase;
4804 + UINT32 phyAddr;
4805 +
4806 + phyBase = RT_PHYBASE(phyUnit);
4807 + phyAddr = RT_PHYADDR(phyUnit);
4808 +
4809 + printf("PHY state for ethphy%d\n", phyUnit);
4810 +
4811 + for (i=0; i<rtNumRegs; i++) {
4812 +
4813 + value = phyRegRead(phyBase, phyAddr, rtRegisterTable[i].regNum);
4814 +
4815 + printf("Reg %02d (0x%02x) %s = 0x%08x\n",
4816 + rtRegisterTable[i].regNum, rtRegisterTable[i].regNum,
4817 + rtRegisterTable[i].regIdString, value);
4818 + }
4819 +}
4820 +
4821 +/*
4822 + * Modify the value of a PHY register.
4823 + * This makes it a bit easier to modify PHY values during debug.
4824 + */
4825 +void
4826 +rt_phySet(int phyUnit, UINT32 regnum, UINT32 value)
4827 +{
4828 + UINT32 phyBase;
4829 + UINT32 phyAddr;
4830 +
4831 + phyBase = RT_PHYBASE(phyUnit);
4832 + phyAddr = RT_PHYADDR(phyUnit);
4833 +
4834 + phyRegWrite(phyBase, phyAddr, regnum, value);
4835 +}
4836 +#endif
4837 diff -urN linux-2.4.32.new/arch/mips/ar531x/rtPhy.h linux-2.4.32.new-eth/arch/mips/ar531x/rtPhy.h
4838 --- linux-2.4.32.new/arch/mips/ar531x/rtPhy.h 1970-01-01 01:00:00.000000000 +0100
4839 +++ linux-2.4.32.new-eth/arch/mips/ar531x/rtPhy.h 2005-12-25 11:54:46.089422728 +0000
4840 @@ -0,0 +1,50 @@
4841 +/*
4842 + * This file is subject to the terms and conditions of the GNU General Public
4843 + * License. See the file "COPYING" in the main directory of this archive
4844 + * for more details.
4845 + *
4846 + * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
4847 + */
4848 +
4849 +/*
4850 + * rtPhy.h - definitions for the ethernet PHY.
4851 + * This code supports a simple 1-port ethernet phy, Realtek RTL8201BL,
4852 + * and compatible PHYs, such as the Kendin KS8721B.
4853 + * All definitions in this file are operating system independent!
4854 + */
4855 +
4856 +#ifndef RTPHY_H
4857 +#define RTPHY_H
4858 +
4859 +/* MII Registers */
4860 +
4861 +#define GEN_ctl 00
4862 +#define GEN_sts 01
4863 +#define GEN_id_hi 02
4864 +#define GEN_id_lo 03
4865 +#define AN_adv 04
4866 +#define AN_lpa 05
4867 +#define AN_exp 06
4868 +
4869 +/* GEN_ctl */
4870 +#define PHY_SW_RST 0x8000
4871 +#define LOOPBACK 0x4000
4872 +#define SPEED 0x2000 /* 100 Mbit/s */
4873 +#define AUTONEGENA 0x1000
4874 +#define DUPLEX 0x0100 /* Duplex mode */
4875 +
4876 +
4877 +/* GEN_sts */
4878 +#define AUTOCMPLT 0x0020 /* Autonegotiation completed */
4879 +#define LINK 0x0004 /* Link status */
4880 +
4881 +/* GEN_ids */
4882 +#define RT_PHY_ID1_EXPECTATION 0x22
4883 +
4884 +/* AN_lpa */
4885 +#define LPA_TXFD 0x0100 /* Link partner supports 100 TX Full Duplex */
4886 +#define LPA_TX 0x0080 /* Link partner supports 100 TX Half Duplex */
4887 +#define LPA_10FD 0x0040 /* Link partner supports 10 BT Full Duplex */
4888 +#define LPA_10 0x0020 /* Link partner supports 10 BT Half Duplex */
4889 +
4890 +#endif /* RTPHY_H */