summaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
Diffstat (limited to 'target')
-rw-r--r--target/linux/Config.in11
-rw-r--r--target/linux/image/squashfs.mk9
-rw-r--r--target/linux/linux-2.4/config/ar531x11
-rw-r--r--target/linux/linux-2.4/patches/ar531x/000-atheros-support.patch14053
-rw-r--r--target/linux/linux-2.4/patches/ar531x/001-ar531x-ethernet.patch4890
-rw-r--r--target/linux/package/alsa/Config.in1
-rw-r--r--target/linux/package/madwifi/Makefile12
7 files changed, 11448 insertions, 7539 deletions
diff --git a/target/linux/Config.in b/target/linux/Config.in
index e56b2c82bd..893c8f56a2 100644
--- a/target/linux/Config.in
+++ b/target/linux/Config.in
@@ -364,6 +364,7 @@ config BR2_PACKAGE_KMOD_IDE
prompt "kmod-ide.......................... IDE support"
tristate
default m
+ depends BR2_LINUX_2_4_X86 || BR2_LINUX_2_4_BRCM || BR2_LINUX_2_6_X86 || BR2_LINUX_2_6_BRCM
help
Kernel modules for IDE support
useful for usb mass storage devices (e.g. on WL-HDD)
@@ -450,6 +451,7 @@ comment "Multimedia devices support"
config BR2_PACKAGE_KMOD_PWC
prompt "kmod-pwc.......................... Kernel driver for USB Philips Cameras"
tristate
+ default n if BR2_LINUX_2_4_AR531X
default m
config BR2_PACKAGE_KMOD_SOUNDCORE
@@ -519,6 +521,7 @@ comment "Network devices support"
config BR2_PACKAGE_KMOD_NET_3C59X
prompt "kmod-net-3c59x.................... 3Com 3c590/3c900 series (592/595/597) \"Vortex/Boomerang\" Ethernet kernel support"
tristate
+ default n if BR2_LINUX_2_4_AR531X
default m
help
This option enables driver support for a large number of 10mbps and
@@ -533,6 +536,7 @@ config BR2_PACKAGE_KMOD_NET_3C59X
config BR2_PACKAGE_KMOD_NET_8139TOO
prompt "kmod-net-8139too.................. RealTek RTL-8139 PCI Fast Ethernet Adapter kernel support"
tristate
+ default n if BR2_LINUX_2_4_AR531X
default m
help
This is a driver for the Fast Ethernet PCI network cards based on
@@ -541,6 +545,7 @@ config BR2_PACKAGE_KMOD_NET_8139TOO
config BR2_PACKAGE_KMOD_NET_AIRO
prompt "kmod-net-airo..................... Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards kernel support"
tristate
+ default n if BR2_LINUX_2_4_AR531X
default m
help
This is the standard Linux driver to support Cisco/Aironet ISA and
@@ -572,6 +577,7 @@ config BR2_PACKAGE_KMOD_NET_B44
config BR2_PACKAGE_KMOD_NET_HERMES
prompt "kmod-net-hermes................... Hermes chipset 802.11b support (Orinoco/Prism2/Symbol) kernel support"
tristate
+ default n if BR2_LINUX_2_4_AR531X
default m
help
A driver for 802.11b wireless cards based based on the "Hermes" or
@@ -612,6 +618,7 @@ config BR2_PACKAGE_KMOD_NET_HERMES_PLX
config BR2_PACKAGE_KMOD_NET_NATSEMI
prompt "kmod-net-natsemi.................. National Semiconductor DP8381x series PCI Ethernet kernel support"
tristate
+ default n if BR2_LINUX_2_4_AR531X
default m
help
This driver is for the National Semiconductor DP83810 series,
@@ -621,6 +628,7 @@ config BR2_PACKAGE_KMOD_NET_NATSEMI
config BR2_PACKAGE_KMOD_NET_PRISM54
prompt "kmod-net-prism54.................. Intersil Prism GT/Duette/Indigo PCI/PCMCIA cards kernel support"
tristate
+ default n if BR2_LINUX_2_4_AR531X
default m
help
Enable PCI and Cardbus support for the following chipset based cards:
@@ -662,6 +670,7 @@ config BR2_PACKAGE_KMOD_PCMCIA_CORE
prompt "kmod-pcmcia-core.................. PCMCIA/CardBus support"
depends BR2_LINUX_PCMCIA_SUPPORT
tristate
+ default n if BR2_LINUX_2_4_AR531X
default m
config BR2_PACKAGE_KMOD_PCMCIA_SERIAL
@@ -675,6 +684,7 @@ comment "USB support"
config BR2_PACKAGE_KMOD_USB
prompt "kmod-usb-core..................... USB support"
tristate
+ default n if BR2_LINUX_2_4_AR531X
default m
config BR2_PACKAGE_KMOD_USB_UHCI
@@ -785,6 +795,7 @@ config BR2_PACKAGE_KMOD_BLUETOOTH
prompt "kmod-bluetooth.................... Bluetooth drivers and network stack"
tristate
default m
+ default n if BR2_LINUX_2_4_AR531X
help
Bluetooth drivers and network stack
diff --git a/target/linux/image/squashfs.mk b/target/linux/image/squashfs.mk
index 63eba445a0..450718153c 100644
--- a/target/linux/image/squashfs.mk
+++ b/target/linux/image/squashfs.mk
@@ -1,3 +1,10 @@
+ifeq ($(BR2_LINUX_2_4_AR531X),)
+ endian := be
+else
+ endian := le
+endif
+
+
squashfs-prepare:
$(MAKE) -C squashfs prepare $(MAKE_TRACE)
@@ -10,7 +17,7 @@ squashfs-clean:
$(KDIR)/root.squashfs: install-prepare
@mkdir -p $(KDIR)/root/jffs
- $(STAGING_DIR)/bin/mksquashfs-lzma $(KDIR)/root $@ -nopad -noappend -root-owned -le $(MAKE_TRACE)
+ $(STAGING_DIR)/bin/mksquashfs-lzma $(KDIR)/root $@ -nopad -noappend -root-owned -$(endian) $(MAKE_TRACE)
ifeq ($(IB),)
squashfs-install: compile-targets $(BOARD)-compile
diff --git a/target/linux/linux-2.4/config/ar531x b/target/linux/linux-2.4/config/ar531x
index 4feca02dea..77c5beb3c2 100644
--- a/target/linux/linux-2.4/config/ar531x
+++ b/target/linux/linux-2.4/config/ar531x
@@ -88,6 +88,8 @@ CONFIG_NEW_IRQ=y
CONFIG_NEW_TIME_C=y
CONFIG_NONCOHERENT_IO=y
CONFIG_EARLY_PRINTK_HACK=y
+CONFIG_VENETDEV=y
+CONFIG_MARVELL_ENET_PHY=y
# CONFIG_SCSI is not set
#
@@ -126,7 +128,7 @@ CONFIG_CPU_VR41XX=y
CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
-# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_ADVANCED=y
# CONFIG_CPU_HAS_LLSC is not set
# CONFIG_CPU_HAS_LLDSCD is not set
# CONFIG_CPU_HAS_WB is not set
@@ -285,8 +287,9 @@ CONFIG_PARPORT=m
# CONFIG_BLK_DEV_SX8 is not set
CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_NBD=m
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=3072
+CONFIG_BLK_DEV_INITRD=y
# CONFIG_BLK_STATS is not set
#
@@ -596,8 +599,6 @@ CONFIG_NET_RANDOM=y
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
-# CONFIG_VENETDEV is not set
-CONFIG_MARVELL_ENET_PHY=y
# CONFIG_SUNLANCE is not set
# CONFIG_SUNBMAC is not set
# CONFIG_SUNQE is not set
diff --git a/target/linux/linux-2.4/patches/ar531x/000-atheros-support.patch b/target/linux/linux-2.4/patches/ar531x/000-atheros-support.patch
index 1ec012f630..de7115b46a 100644
--- a/target/linux/linux-2.4/patches/ar531x/000-atheros-support.patch
+++ b/target/linux/linux-2.4/patches/ar531x/000-atheros-support.patch
@@ -1,2642 +1,11411 @@
-diff -urN linux-2.4.32/arch/mips/ar531x/ar531xdbg_io.c linux-2.4.32.new/arch/mips/ar531x/ar531xdbg_io.c
---- linux-2.4.32/arch/mips/ar531x/ar531xdbg_io.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/ar531xdbg_io.c 2005-12-24 20:29:42.102311328 +0000
-@@ -0,0 +1,217 @@
-+/*
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file "COPYING" in the main directory of this archive
-+ * for more details.
-+ *
-+ * Copyright MontaVista Software Inc
-+ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
-+ */
-+
-+/*
-+ * Basic support for polled character input/output
-+ * using the AR531X's serial port.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/irq.h>
-+#include <linux/interrupt.h>
-+#include <linux/serial.h>
-+#include <linux/types.h>
-+#include <linux/string.h>
-+
-+#include <asm/reboot.h>
-+#include <asm/io.h>
-+#include <asm/time.h>
-+#include <asm/pgtable.h>
-+#include <asm/processor.h>
-+#include <asm/reboot.h>
-+#include <asm/system.h>
-+#include <asm/serial.h>
-+#include <asm/gdb-stub.h>
-+
-+#include "ar531xlnx.h"
-+
-+#if CONFIG_EARLY_PRINTK_HACK || CONFIG_KGDB
-+/* base addr of uart and clock timing */
-+#define BASE 0xbc000003
-+
-+/* distance in bytes between two serial registers */
-+#define REG_OFFSET 4
-+
-+/*
-+ * 0 - we need to do serial init
-+ * 1 - skip serial init
-+ */
-+static int serialPortInitialized = 0;
-+
-+/*
-+ * * the default baud rate *if* we do serial init
-+ * */
-+#define BAUD_DEFAULT UART16550_BAUD_9600
-+
-+/* === END OF CONFIG === */
-+
-+#define UART16550_BAUD_2400 2400
-+#define UART16550_BAUD_4800 4800
-+#define UART16550_BAUD_9600 9600
-+#define UART16550_BAUD_19200 19200
-+#define UART16550_BAUD_38400 38400
-+#define UART16550_BAUD_57600 57600
-+#define UART16550_BAUD_115200 115200
-+
-+#define UART16550_PARITY_NONE 0
-+#define UART16550_PARITY_ODD 0x08
-+#define UART16550_PARITY_EVEN 0x18
-+#define UART16550_PARITY_MARK 0x28
-+#define UART16550_PARITY_SPACE 0x38
-+
-+#define UART16550_DATA_5BIT 0x0
-+#define UART16550_DATA_6BIT 0x1
-+#define UART16550_DATA_7BIT 0x2
-+#define UART16550_DATA_8BIT 0x3
-+
-+#define UART16550_STOP_1BIT 0x0
-+#define UART16550_STOP_2BIT 0x4
-+
-+/* register offset */
-+#define OFS_RCV_BUFFER (0*REG_OFFSET)
-+#define OFS_TRANS_HOLD (0*REG_OFFSET)
-+#define OFS_SEND_BUFFER (0*REG_OFFSET)
-+#define OFS_INTR_ENABLE (1*REG_OFFSET)
-+#define OFS_INTR_ID (2*REG_OFFSET)
-+#define OFS_DATA_FORMAT (3*REG_OFFSET)
-+#define OFS_LINE_CONTROL (3*REG_OFFSET)
-+#define OFS_MODEM_CONTROL (4*REG_OFFSET)
-+#define OFS_RS232_OUTPUT (4*REG_OFFSET)
-+#define OFS_LINE_STATUS (5*REG_OFFSET)
-+#define OFS_MODEM_STATUS (6*REG_OFFSET)
-+#define OFS_RS232_INPUT (6*REG_OFFSET)
-+#define OFS_SCRATCH_PAD (7*REG_OFFSET)
-+
-+#define OFS_DIVISOR_LSB (0*REG_OFFSET)
-+#define OFS_DIVISOR_MSB (1*REG_OFFSET)
-+
-+
-+/* memory-mapped read/write of the port */
-+#define UART16550_READ(y) (*((volatile u8*)(BASE + y)))
-+#define UART16550_WRITE(y, z) ((*((volatile u8*)(BASE + y))) = z)
-+
-+void
-+debugPortInit(u32 baud, u8 data, u8 parity, u8 stop)
-+{
-+ /* Pull UART out of reset */
-+ sysRegWrite(AR531X_RESET,
-+ sysRegRead(AR531X_RESET) & ~(AR531X_RESET_UART0));
-+
-+ /* disable interrupts */
-+ UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
-+ UART16550_WRITE(OFS_INTR_ENABLE, 0);
-+
-+ /* set up buad rate */
-+ {
-+ u32 divisor;
-+ u32 uart_clock_rate = ar531x_cpu_frequency() / 4;
-+ u32 base_baud = uart_clock_rate / 16;
-+
-+ /* set DIAB bit */
-+ UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
-+
-+ /* set divisor */
-+ divisor = base_baud / baud;
-+ UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
-+ UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00)>>8);
-+
-+ /* clear DIAB bit */
-+ UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
-+ }
-+
-+ /* set data format */
-+ UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
-+}
-+
-+u8
-+getDebugChar(void)
-+{
-+ if (!serialPortInitialized) {
-+ serialPortInitialized = 1;
-+ debugPortInit(BAUD_DEFAULT,
-+ UART16550_DATA_8BIT,
-+ UART16550_PARITY_NONE, UART16550_STOP_1BIT);
-+ }
-+
-+ while((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
-+ return UART16550_READ(OFS_RCV_BUFFER);
-+}
-+
-+#if CONFIG_KGDB
-+/*
-+ * Peek at the most recently received character.
-+ * Don't wait for a new character to be received.
-+ */
-+u8
-+peekDebugChar(void)
-+{
-+ return UART16550_READ(OFS_RCV_BUFFER);
-+}
-+
-+static int kgdbInitialized = 0;
-+
-+void
-+kgdbInit(void)
-+{
-+ sysRegWrite(AR531X_WD_CTRL, AR531X_WD_CTRL_IGNORE_EXPIRATION);
-+
-+ if (!kgdbInitialized) {
-+ printk("Setting debug traps - please connect the remote debugger.\n");
-+ set_debug_traps();
-+ kgdbInitialized = 1;
-+ }
-+ breakpoint();
-+}
-+
-+int
-+kgdbEnabled(void)
-+{
-+ return kgdbInitialized;
-+}
-+
-+#define DEBUG_CHAR '\001';
-+
-+int
-+kgdbInterrupt(void)
-+{
-+ if (!kgdbInitialized) {
-+ return 0;
-+ }
-+
-+ /*
-+ * Try to avoid swallowing too much input: Only consume
-+ * a character if nothing new has arrived. Yes, there's
-+ * still a small hole here, and we may lose an input
-+ * character now and then.
-+ */
-+ if (UART16550_READ(OFS_LINE_STATUS) & 1) {
-+ return 0;
-+ } else {
-+ return UART16550_READ(OFS_RCV_BUFFER) == DEBUG_CHAR;
-+ }
-+}
-+#endif
-+
-+
-+void
-+putDebugChar(char byte)
-+{
-+ if (!serialPortInitialized) {
-+ serialPortInitialized = 1;
-+ debugPortInit(BAUD_DEFAULT,
-+ UART16550_DATA_8BIT,
-+ UART16550_PARITY_NONE, UART16550_STOP_1BIT);
-+ }
-+
-+ while ((UART16550_READ(OFS_LINE_STATUS) &0x20) == 0);
-+ UART16550_WRITE(OFS_SEND_BUFFER, byte);
-+ }
-+#endif /* CONFIG_EARLY_PRINTK_HACK || CONFIG_KGDB */
-diff -urN linux-2.4.32/arch/mips/ar531x/ar531xgpio.c linux-2.4.32.new/arch/mips/ar531x/ar531xgpio.c
---- linux-2.4.32/arch/mips/ar531x/ar531xgpio.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/ar531xgpio.c 2005-12-24 20:29:42.102311328 +0000
-@@ -0,0 +1,141 @@
-+/*
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file "COPYING" in the main directory of this archive
-+ * for more details.
-+ *
-+ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
-+ */
-+
-+/*
-+ * Support for GPIO -- General Purpose Input/Output Pins
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/kernel.h>
-+#include <linux/signal.h>
-+#include <linux/interrupt.h>
-+#include <linux/irq.h>
-+
-+#include "ar531xlnx.h"
-+
-+/* GPIO Interrupt Support */
-+
-+/* Turn on the specified AR531X_GPIO_IRQ interrupt */
-+static unsigned int
-+ar531x_gpio_intr_startup(unsigned int irq)
-+{
-+ ar531x_gpio_intr_enable(irq);
-+ return 0;
-+}
-+
-+/* Turn off the specified AR531X_GPIO_IRQ interrupt */
-+static void
-+ar531x_gpio_intr_shutdown(unsigned int irq)
-+{
-+ ar531x_gpio_intr_disable(irq);
-+}
-+
-+u32 gpioIntMask = 0;
-+
-+/* Enable the specified AR531X_GPIO_IRQ interrupt */
-+void
-+ar531x_gpio_intr_enable(unsigned int irq)
-+{
-+ u32 reg;
-+ int gpio;
-+
-+ gpio = irq - AR531X_GPIO_IRQ_BASE;
-+ gpioIntMask |= gpio;
-+
-+ reg = sysRegRead(AR531X_GPIO_CR);
-+ reg &= ~(GPIO_CR_M(gpio) | GPIO_CR_UART(gpio) | GPIO_CR_INT(gpio));
-+ reg |= GPIO_CR_I(gpio);
-+ reg |= GPIO_CR_INT(gpio);
-+
-+ sysRegWrite(AR531X_GPIO_CR, reg);
-+ (void)sysRegRead(AR531X_GPIO_CR); /* flush to hardware */
-+}
-+
-+/* Disable the specified AR531X_GPIO_IRQ interrupt */
-+void
-+ar531x_gpio_intr_disable(unsigned int irq)
-+{
-+ u32 reg;
-+ int gpio;
-+
-+ gpio = irq - AR531X_GPIO_IRQ_BASE;
-+
-+ reg = sysRegRead(AR531X_GPIO_CR);
-+ reg &= ~(GPIO_CR_M(gpio) | GPIO_CR_UART(gpio) | GPIO_CR_INT(gpio));
-+ reg |= GPIO_CR_I(gpio);
-+ /* No GPIO_CR_INT bit */
-+
-+ sysRegWrite(AR531X_GPIO_CR, reg);
-+ (void)sysRegRead(AR531X_GPIO_CR); /* flush to hardware */
-+
-+ gpioIntMask &= ~gpio;
-+}
-+
-+static void
-+ar531x_gpio_intr_ack(unsigned int irq)
-+{
-+ ar531x_gpio_intr_disable(irq);
-+}
-+
-+static void
-+ar531x_gpio_intr_end(unsigned int irq)
-+{
-+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-+ ar531x_gpio_intr_enable(irq);
-+}
-+
-+static void
-+ar531x_gpio_intr_set_affinity(unsigned int irq, unsigned long mask)
-+{
-+ /* Only 1 CPU; ignore affinity request */
-+}
-+
-+int ar531x_gpio_irq_base;
-+
-+struct hw_interrupt_type ar531x_gpio_intr_controller = {
-+ "AR531X GPIO",
-+ ar531x_gpio_intr_startup,
-+ ar531x_gpio_intr_shutdown,
-+ ar531x_gpio_intr_enable,
-+ ar531x_gpio_intr_disable,
-+ ar531x_gpio_intr_ack,
-+ ar531x_gpio_intr_end,
-+ ar531x_gpio_intr_set_affinity,
-+};
-+
-+void
-+ar531x_gpio_intr_init(int irq_base)
-+{
-+ int i;
-+
-+ for (i = irq_base; i < irq_base + AR531X_GPIO_IRQ_COUNT; i++) {
-+ irq_desc[i].status = IRQ_DISABLED;
-+ irq_desc[i].action = NULL;
-+ irq_desc[i].depth = 1;
-+ irq_desc[i].handler = &ar531x_gpio_intr_controller;
-+ }
-+
-+ ar531x_gpio_irq_base = irq_base;
-+}
-+
-+/* ARGSUSED */
-+void
-+spurious_gpio_handler(int cpl, void *dev_id, struct pt_regs *regs)
-+{
-+ u32 gpioDataIn;
-+
-+ gpioDataIn = sysRegRead(AR531X_GPIO_DI) & gpioIntMask;
-+
-+ printk("spurious_gpio_handler: 0x%x di=0x%8.8x gpioIntMask=0x%8.8x\n",
-+ cpl, gpioDataIn, gpioIntMask);
-+}
-+
-+struct irqaction spurious_gpio =
-+ {spurious_gpio_handler, SA_INTERRUPT, 0, "spurious_gpio",
-+ NULL, NULL};
-+
-diff -urN linux-2.4.32/arch/mips/ar531x/ar531x.h linux-2.4.32.new/arch/mips/ar531x/ar531x.h
---- linux-2.4.32/arch/mips/ar531x/ar531x.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/ar531x.h 2005-12-24 20:29:42.102311328 +0000
-@@ -0,0 +1,280 @@
-+/*
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file "COPYING" in the main directory of this archive
-+ * for more details.
-+ *
-+ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
-+ */
-+
-+#ifndef AR531X_H
-+#define AR531X_H 1
-+
-+#include <asm/addrspace.h>
-+
-+/* Address Map */
-+#define AR531X_WLAN0 0x18000000
-+#define AR531X_WLAN1 0x18500000
-+#define AR531X_ENET0 0x18100000
-+#define AR531X_ENET1 0x18200000
-+#define AR531X_SDRAMCTL 0x18300000
-+#define AR531X_FLASHCTL 0x18400000
-+#define AR531X_APBBASE 0x1c000000
-+#define AR531X_FLASH 0x1e000000
-+
-+/*
-+ * AR531X_NUM_ENET_MAC defines the number of ethernet MACs that
-+ * should be considered available. The AR5312 supports 2 enet MACS,
-+ * even though many reference boards only actually use 1 of them
-+ * (i.e. Only MAC 0 is actually connected to an enet PHY or PHY switch.
-+ * The AR2312 supports 1 enet MAC.
-+ */
-+#define AR531X_NUM_ENET_MAC 2
-+
-+/*
-+ * Need these defines to determine true number of ethernet MACs
-+ */
-+#define AR5212_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */
-+#define AR5212_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */
-+#define AR5212_AR2313_REV8 0x0058 /* AR2313 WMAC (AP43-030) */
-+#define AR531X_RADIO_MASK_OFF 0xc8
-+#define AR531X_RADIO0_MASK 0x0003
-+#define AR531X_RADIO1_MASK 0x000c
-+#define AR531X_RADIO1_S 2
-+
-+/*
-+ * AR531X_NUM_WMAC defines the number of Wireless MACs that\
-+ * should be considered available.
-+ */
-+#define AR531X_NUM_WMAC 2
-+
-+/* Reset/Timer Block Address Map */
-+#define AR531X_RESETTMR (AR531X_APBBASE + 0x3000)
-+#define AR531X_TIMER (AR531X_RESETTMR + 0x0000) /* countdown timer */
-+#define AR531X_WD_CTRL (AR531X_RESETTMR + 0x0008) /* watchdog cntrl */
-+#define AR531X_WD_TIMER (AR531X_RESETTMR + 0x000c) /* watchdog timer */
-+#define AR531X_ISR (AR531X_RESETTMR + 0x0010) /* Intr Status Reg */
-+#define AR531X_IMR (AR531X_RESETTMR + 0x0014) /* Intr Mask Reg */
-+#define AR531X_RESET (AR531X_RESETTMR + 0x0020)
-+#define AR5312_CLOCKCTL1 (AR531X_RESETTMR + 0x0064)
-+#define AR5312_SCRATCH (AR531X_RESETTMR + 0x006c)
-+#define AR531X_PROCADDR (AR531X_RESETTMR + 0x0070)
-+#define AR531X_PROC1 (AR531X_RESETTMR + 0x0074)
-+#define AR531X_DMAADDR (AR531X_RESETTMR + 0x0078)
-+#define AR531X_DMA1 (AR531X_RESETTMR + 0x007c)
-+#define AR531X_ENABLE (AR531X_RESETTMR + 0x0080) /* interface enb */
-+#define AR531X_REV (AR531X_RESETTMR + 0x0090) /* revision */
-+
-+/* AR531X_WD_CTRL register bit field definitions */
-+#define AR531X_WD_CTRL_IGNORE_EXPIRATION 0x0000
-+#define AR531X_WD_CTRL_NMI 0x0001
-+#define AR531X_WD_CTRL_RESET 0x0002
-+
-+/* AR531X_ISR register bit field definitions */
-+#define AR531X_ISR_NONE 0x0000
-+#define AR531X_ISR_TIMER 0x0001
-+#define AR531X_ISR_AHBPROC 0x0002
-+#define AR531X_ISR_AHBDMA 0x0004
-+#define AR531X_ISR_GPIO 0x0008
-+#define AR531X_ISR_UART0 0x0010
-+#define AR531X_ISR_UART0DMA 0x0020
-+#define AR531X_ISR_WD 0x0040
-+#define AR531X_ISR_LOCAL 0x0080
-+
-+/* AR531X_RESET register bit field definitions */
-+#define AR531X_RESET_SYSTEM 0x00000001 /* cold reset full system */
-+#define AR531X_RESET_PROC 0x00000002 /* cold reset MIPS core */
-+#define AR531X_RESET_WLAN0 0x00000004 /* cold reset WLAN MAC and BB */
-+#define AR531X_RESET_EPHY0 0x00000008 /* cold reset ENET0 phy */
-+#define AR531X_RESET_EPHY1 0x00000010 /* cold reset ENET1 phy */
-+#define AR531X_RESET_ENET0 0x00000020 /* cold reset ENET0 mac */
-+#define AR531X_RESET_ENET1 0x00000040 /* cold reset ENET1 mac */
-+#define AR531X_RESET_UART0 0x00000100 /* cold reset UART0 (high speed) */
-+#define AR531X_RESET_WLAN1 0x00000200 /* cold reset WLAN MAC/BB */
-+#define AR531X_RESET_APB 0x00000400 /* cold reset APB (ar5312) */
-+#define AR531X_RESET_WARM_PROC 0x00001000 /* warm reset MIPS core */
-+#define AR531X_RESET_WARM_WLAN0_MAC 0x00002000 /* warm reset WLAN0 MAC */
-+#define AR531X_RESET_WARM_WLAN0_BB 0x00004000 /* warm reset WLAN0 BaseBand */
-+#define AR531X_RESET_NMI 0x00010000 /* send an NMI to the processor */
-+#define AR531X_RESET_WARM_WLAN1_MAC 0x00020000 /* warm reset WLAN1 mac */
-+#define AR531X_RESET_WARM_WLAN1_BB 0x00040000 /* warm reset WLAN1 baseband */
-+#define AR531X_RESET_LOCAL_BUS 0x00080000 /* reset local bus */
-+#define AR531X_RESET_WDOG 0x00100000 /* last reset was a watchdog */
-+
-+#define AR531X_RESET_WMAC0_BITS \
-+ AR531X_RESET_WLAN0 |\
-+ AR531X_RESET_WARM_WLAN0_MAC |\
-+ AR531X_RESET_WARM_WLAN0_BB
-+
-+#define AR531X_RESERT_WMAC1_BITS \
-+ AR531X_RESET_WLAN1 |\
-+ AR531X_RESET_WARM_WLAN1_MAC |\
-+ AR531X_RESET_WARM_WLAN1_BB
-+
-+/* AR5312_CLOCKCTL1 register bit field definitions */
-+#define AR5312_CLOCKCTL1_PREDIVIDE_MASK 0x00000030
-+#define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT 4
-+#define AR5312_CLOCKCTL1_MULTIPLIER_MASK 0x00001f00
-+#define AR5312_CLOCKCTL1_MULTIPLIER_SHIFT 8
-+#define AR5312_CLOCKCTL1_DOUBLER_MASK 0x00010000
-+
-+/* Valid for AR5312 and AR2312 */
-+#define AR5312_CLOCKCTL1_PREDIVIDE_MASK 0x00000030
-+#define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT 4
-+#define AR5312_CLOCKCTL1_MULTIPLIER_MASK 0x00001f00
-+#define AR5312_CLOCKCTL1_MULTIPLIER_SHIFT 8
-+#define AR5312_CLOCKCTL1_DOUBLER_MASK 0x00010000
-+
-+/* Valid for AR2313 */
-+#define AR2313_CLOCKCTL1_PREDIVIDE_MASK 0x00003000
-+#define AR2313_CLOCKCTL1_PREDIVIDE_SHIFT 12
-+#define AR2313_CLOCKCTL1_MULTIPLIER_MASK 0x001f0000
-+#define AR2313_CLOCKCTL1_MULTIPLIER_SHIFT 16
-+#define AR2313_CLOCKCTL1_DOUBLER_MASK 0x00000000
-+
-+
-+/* AR531X_ENABLE register bit field definitions */
-+#define AR531X_ENABLE_WLAN0 0x0001
-+#define AR531X_ENABLE_ENET0 0x0002
-+#define AR531X_ENABLE_ENET1 0x0004
-+#define AR531X_ENABLE_UART_AND_WLAN1_PIO 0x0008 /* UART, and WLAN1 PIOs */
-+#define AR531X_ENABLE_WLAN1_DMA 0x0010 /* WLAN1 DMAs */
-+#define AR531X_ENABLE_WLAN1 \
-+ (AR531X_ENABLE_UART_AND_WLAN1_PIO | AR531X_ENABLE_WLAN1_DMA)
-+
-+/* AR531X_REV register bit field definitions */
-+#define AR531X_REV_WMAC_MAJ 0xf000
-+#define AR531X_REV_WMAC_MAJ_S 12
-+#define AR531X_REV_WMAC_MIN 0x0f00
-+#define AR531X_REV_WMAC_MIN_S 8
-+#define AR531X_REV_MAJ 0x00f0
-+#define AR531X_REV_MAJ_S 4
-+#define AR531X_REV_MIN 0x000f
-+#define AR531X_REV_MIN_S 0
-+#define AR531X_REV_CHIP (REV_MAJ|REV_MIN)
-+
-+/* Major revision numbers, bits 7..4 of Revision ID register */
-+#define AR531X_REV_MAJ_AR5312 0x4
-+#define AR531X_REV_MAJ_AR2313 0x5
-+
-+/* Minor revision numbers, bits 3..0 of Revision ID register */
-+#define AR5312_REV_MIN_DUAL 0x0 /* Dual WLAN version */
-+#define AR5312_REV_MIN_SINGLE 0x1 /* Single WLAN version */
-+
-+/* AR531X_FLASHCTL register bit field definitions */
-+#define FLASHCTL_IDCY 0x0000000f /* Idle cycle turn around time */
-+#define FLASHCTL_IDCY_S 0
-+#define FLASHCTL_WST1 0x000003e0 /* Wait state 1 */
-+#define FLASHCTL_WST1_S 5
-+#define FLASHCTL_RBLE 0x00000400 /* Read byte lane enable */
-+#define FLASHCTL_WST2 0x0000f800 /* Wait state 2 */
-+#define FLASHCTL_WST2_S 11
-+#define FLASHCTL_AC 0x00070000 /* Flash address check (added) */
-+#define FLASHCTL_AC_S 16
-+#define FLASHCTL_AC_128K 0x00000000
-+#define FLASHCTL_AC_256K 0x00010000
-+#define FLASHCTL_AC_512K 0x00020000
-+#define FLASHCTL_AC_1M 0x00030000
-+#define FLASHCTL_AC_2M 0x00040000
-+#define FLASHCTL_AC_4M 0x00050000
-+#define FLASHCTL_AC_8M 0x00060000
-+#define FLASHCTL_AC_RES 0x00070000 /* 16MB is not supported */
-+#define FLASHCTL_E 0x00080000 /* Flash bank enable (added) */
-+#define FLASHCTL_BUSERR 0x01000000 /* Bus transfer error status flag */
-+#define FLASHCTL_WPERR 0x02000000 /* Write protect error status flag */
-+#define FLASHCTL_WP 0x04000000 /* Write protect */
-+#define FLASHCTL_BM 0x08000000 /* Burst mode */
-+#define FLASHCTL_MW 0x30000000 /* Memory width */
-+#define FLASHCTL_MWx8 0x00000000 /* Memory width x8 */
-+#define FLASHCTL_MWx16 0x10000000 /* Memory width x16 */
-+#define FLASHCTL_MWx32 0x20000000 /* Memory width x32 (not supported) */
-+#define FLASHCTL_ATNR 0x00000000 /* Access type == no retry */
-+#define FLASHCTL_ATR 0x80000000 /* Access type == retry every */
-+#define FLASHCTL_ATR4 0xc0000000 /* Access type == retry every 4 */
-+
-+/* ARM Flash Controller -- 3 flash banks with either x8 or x16 devices. */
-+#define AR531X_FLASHCTL0 (AR531X_FLASHCTL + 0x00)
-+#define AR531X_FLASHCTL1 (AR531X_FLASHCTL + 0x04)
-+#define AR531X_FLASHCTL2 (AR531X_FLASHCTL + 0x08)
-+
-+/* ARM SDRAM Controller -- just enough to determine memory size */
-+#define AR531X_MEM_CFG1 (AR531X_SDRAMCTL + 0x04)
-+#define MEM_CFG1_AC0 0x00000700 /* bank 0: SDRAM addr check (added) */
-+#define MEM_CFG1_AC0_S 8
-+#define MEM_CFG1_AC1 0x00007000 /* bank 1: SDRAM addr check (added) */
-+#define MEM_CFG1_AC1_S 12
-+
-+/* GPIO Address Map */
-+#define AR531X_GPIO (AR531X_APBBASE + 0x2000)
-+#define AR531X_GPIO_DO (AR531X_GPIO + 0x00) /* output register */
-+#define AR531X_GPIO_DI (AR531X_GPIO + 0x04) /* intput register */
-+#define AR531X_GPIO_CR (AR531X_GPIO + 0x08) /* control register */
-+
-+/* GPIO Control Register bit field definitions */
-+#define GPIO_CR_M(x) (1 << (x)) /* mask for i/o */
-+#define GPIO_CR_O(x) (0 << (x)) /* mask for output */
-+#define GPIO_CR_I(x) (1 << (x)) /* mask for input */
-+#define GPIO_CR_INT(x) (1 << ((x)+8)) /* mask for interrupt */
-+#define GPIO_CR_UART(x) (1 << ((x)+16)) /* uart multiplex */
-+
-+
-+typedef unsigned int AR531X_REG;
-+
-+#define sysRegRead(phys) \
-+ (*(volatile AR531X_REG *)PHYS_TO_K1(phys))
-+
-+#define sysRegWrite(phys, val) \
-+ ((*(volatile AR531X_REG *)PHYS_TO_K1(phys)) = (val))
-+
-+
-+/*
-+ * This is board-specific data that is stored in a "fixed" location in flash.
-+ * It is shared across operating systems, so it should not be changed lightly.
-+ * The main reason we need it is in order to extract the ethernet MAC
-+ * address(es).
-+ */
-+struct ar531x_boarddata {
-+ u32 magic; /* board data is valid */
-+#define AR531X_BD_MAGIC 0x35333131 /* "5311", for all 531x platforms */
-+ u16 cksum; /* checksum (starting with BD_REV 2) */
-+ u16 rev; /* revision of this struct */
-+#define BD_REV 4
-+ char boardName[64]; /* Name of board */
-+ u16 major; /* Board major number */
-+ u16 minor; /* Board minor number */
-+ u32 config; /* Board configuration */
-+#define BD_ENET0 0x00000001 /* ENET0 is stuffed */
-+#define BD_ENET1 0x00000002 /* ENET1 is stuffed */
-+#define BD_UART1 0x00000004 /* UART1 is stuffed */
-+#define BD_UART0 0x00000008 /* UART0 is stuffed (dma) */
-+#define BD_RSTFACTORY 0x00000010 /* Reset factory defaults stuffed */
-+#define BD_SYSLED 0x00000020 /* System LED stuffed */
-+#define BD_EXTUARTCLK 0x00000040 /* External UART clock */
-+#define BD_CPUFREQ 0x00000080 /* cpu freq is valid in nvram */
-+#define BD_SYSFREQ 0x00000100 /* sys freq is set in nvram */
-+#define BD_WLAN0 0x00000200 /* Enable WLAN0 */
-+#define BD_MEMCAP 0x00000400 /* CAP SDRAM @ memCap for testing */
-+#define BD_DISWATCHDOG 0x00000800 /* disable system watchdog */
-+#define BD_WLAN1 0x00001000 /* Enable WLAN1 (ar5212) */
-+#define BD_ISCASPER 0x00002000 /* FLAG for AR2312 */
-+#define BD_WLAN0_2G_EN 0x00004000 /* FLAG for radio0_2G */
-+#define BD_WLAN0_5G_EN 0x00008000 /* FLAG for radio0_2G */
-+#define BD_WLAN1_2G_EN 0x00020000 /* FLAG for radio0_2G */
-+#define BD_WLAN1_5G_EN 0x00040000 /* FLAG for radio0_2G */
-+ u16 resetConfigGpio; /* Reset factory GPIO pin */
-+ u16 sysLedGpio; /* System LED GPIO pin */
-+
-+ u32 cpuFreq; /* CPU core frequency in Hz */
-+ u32 sysFreq; /* System frequency in Hz */
-+ u32 cntFreq; /* Calculated C0_COUNT frequency */
-+
-+ u8 wlan0Mac[6];
-+ u8 enet0Mac[6];
-+ u8 enet1Mac[6];
-+
-+ u16 pciId; /* Pseudo PCIID for common code */
-+ u16 memCap; /* cap bank1 in MB */
-+
-+ /* version 3 */
-+ u8 wlan1Mac[6]; /* (ar5212) */
-+};
-+#endif /* AR531X_H */
-diff -urN linux-2.4.32/arch/mips/ar531x/ar531xintr.S linux-2.4.32.new/arch/mips/ar531x/ar531xintr.S
---- linux-2.4.32/arch/mips/ar531x/ar531xintr.S 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/ar531xintr.S 2005-12-24 20:29:42.103311176 +0000
-@@ -0,0 +1,30 @@
-+/*
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file "COPYING" in the main directory of this archive
-+ * for more details.
-+ *
-+ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
-+ */
-+
-+#include <asm/asm.h>
-+#include <asm/mipsregs.h>
-+#include <asm/regdef.h>
-+#include <asm/stackframe.h>
-+
-+/*
-+ * Glue code to save registers and get us to the interrupt dispatcher
-+ */
-+ .text
-+ .set noat
-+ .align 5
-+NESTED(ar531x_interrupt_receive, PT_SIZE, sp)
-+ SAVE_ALL
-+ CLI
-+ .set at
-+
-+ move a0, sp
-+ jal ar531x_irq_dispatch
-+
-+ j ret_from_irq
-+
-+ END(ar531x_interrupt_receive)
-diff -urN linux-2.4.32/arch/mips/ar531x/ar531xirq.c linux-2.4.32.new/arch/mips/ar531x/ar531xirq.c
---- linux-2.4.32/arch/mips/ar531x/ar531xirq.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/ar531xirq.c 2005-12-24 20:29:42.132306768 +0000
-@@ -0,0 +1,292 @@
-+/*
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file "COPYING" in the main directory of this archive
-+ * for more details.
-+ *
-+ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
-+ */
-+
-+/*
-+ * Interrupt support for AR531X WiSOC.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/init.h>
-+#include <linux/kernel_stat.h>
-+#include <linux/signal.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/slab.h>
-+#include <linux/random.h>
-+#include <linux/pm.h>
-+#include <linux/delay.h>
-+#include <linux/reboot.h>
-+
-+#include <asm/irq.h>
-+#include <asm/mipsregs.h>
-+#include <asm/gdb-stub.h>
-+
-+#include "ar531xlnx.h"
-+#include <asm/irq_cpu.h>
-+
-+extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
-+
-+static void ar531x_misc_intr_enable(unsigned int irq);
-+static void ar531x_misc_intr_disable(unsigned int irq);
-+
-+/* Turn on the specified AR531X_MISC_IRQ interrupt */
-+static unsigned int
-+ar531x_misc_intr_startup(unsigned int irq)
-+{
-+ ar531x_misc_intr_enable(irq);
-+ return 0;
-+}
-+
-+/* Turn off the specified AR531X_MISC_IRQ interrupt */
-+static void
-+ar531x_misc_intr_shutdown(unsigned int irq)
-+{
-+ ar531x_misc_intr_disable(irq);
-+}
-+
-+/* Enable the specified AR531X_MISC_IRQ interrupt */
-+static void
-+ar531x_misc_intr_enable(unsigned int irq)
-+{
-+ unsigned int imr;
-+
-+ imr = sysRegRead(AR531X_IMR);
-+ imr |= (1 << (irq - AR531X_MISC_IRQ_BASE - 1));
-+ sysRegWrite(AR531X_IMR, imr);
-+ sysRegRead(AR531X_IMR); /* flush write buffer */
-+}
-+
-+/* Disable the specified AR531X_MISC_IRQ interrupt */
-+static void
-+ar531x_misc_intr_disable(unsigned int irq)
-+{
-+ unsigned int imr;
-+
-+ imr = sysRegRead(AR531X_IMR);
-+ imr &= ~(1 << (irq - AR531X_MISC_IRQ_BASE - 1));
-+ sysRegWrite(AR531X_IMR, imr);
-+ sysRegRead(AR531X_IMR); /* flush write buffer */
-+}
-+
-+static void
-+ar531x_misc_intr_ack(unsigned int irq)
-+{
-+ ar531x_misc_intr_disable(irq);
-+}
-+
-+static void
-+ar531x_misc_intr_end(unsigned int irq)
-+{
-+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-+ ar531x_misc_intr_enable(irq);
-+}
-+
-+static void
-+ar531x_misc_intr_set_affinity(unsigned int irq, unsigned long mask)
-+{
-+ /* Only 1 CPU; ignore affinity request */
-+}
-+
-+struct hw_interrupt_type ar531x_misc_intr_controller = {
-+ "AR531X MISC",
-+ ar531x_misc_intr_startup,
-+ ar531x_misc_intr_shutdown,
-+ ar531x_misc_intr_enable,
-+ ar531x_misc_intr_disable,
-+ ar531x_misc_intr_ack,
-+ ar531x_misc_intr_end,
-+ ar531x_misc_intr_set_affinity,
-+};
-+
-+int ar531x_misc_irq_base;
-+
-+/*
-+ * Determine interrupt source among interrupts that use IP6
-+ */
-+void
-+ar531x_misc_intr_init(int irq_base)
-+{
-+ int i;
-+
-+ for (i = irq_base; i < irq_base + AR531X_MISC_IRQ_COUNT; i++) {
-+ irq_desc[i].status = IRQ_DISABLED;
-+ irq_desc[i].action = NULL;
-+ irq_desc[i].depth = 1;
-+ irq_desc[i].handler = &ar531x_misc_intr_controller;
-+ }
-+
-+ ar531x_misc_irq_base = irq_base;
-+}
-+
-+/* ARGSUSED */
-+void
-+spurious_irq_handler(int cpl, void *dev_id, struct pt_regs *regs)
-+{
-+ /*
-+ printk("spurious_irq_handler: %d cause=0x%8.8x status=0x%8.8x\n",
-+ cpl, cause_intrs, status_intrs);
-+ */
-+}
-+
-+/* ARGSUSED */
-+void
-+spurious_misc_handler(int cpl, void *dev_id, struct pt_regs *regs)
-+{
-+ /*
-+ printk("spurious_misc_handler: 0x%x isr=0x%8.8x imr=0x%8.8x\n",
-+ cpl, ar531x_isr, ar531x_imr);
-+ */
-+}
-+
-+void
-+ar531x_timer_handler(int cpl, void *dev_id, struct pt_regs *regs)
-+{
-+ (void)sysRegRead(AR531X_TIMER); /* clear interrupt */
-+}
-+
-+void
-+ar531x_ahb_proc_handler(int cpl, void *dev_id, struct pt_regs *regs)
-+{
-+ u32 procAddr;
-+ u32 proc1;
-+ u32 dmaAddr;
-+ u32 dma1;
-+
-+ proc1 = sysRegRead(AR531X_PROC1);
-+ procAddr = sysRegRead(AR531X_PROCADDR); /* clears error state */
-+ dma1 = sysRegRead(AR531X_DMA1);
-+ dmaAddr = sysRegRead(AR531X_DMAADDR); /* clears error state */
-+
-+ printk("AHB interrupt: PROCADDR=0x%8.8x PROC1=0x%8.8x DMAADDR=0x%8.8x DMA1=0x%8.8x\n",
-+ procAddr, proc1, dmaAddr, dma1);
-+
-+ machine_restart("AHB error"); /* Catastrophic failure */
-+}
-+
-+static struct irqaction cascade =
-+ {no_action, SA_INTERRUPT, 0, "cascade",
-+ NULL, NULL};
-+
-+static struct irqaction spurious_irq =
-+ {spurious_irq_handler, SA_INTERRUPT, 0, "spurious_irq",
-+ NULL, NULL};
-+
-+static struct irqaction spurious_misc =
-+ {spurious_misc_handler, SA_INTERRUPT, 0, "spurious_misc",
-+ NULL, NULL};
-+
-+static struct irqaction ar531x_timer_interrupt =
-+ {ar531x_timer_handler, SA_INTERRUPT, 0, "ar531x_timer_interrupt",
-+ NULL, NULL};
-+
-+static struct irqaction ar531x_ahb_proc_interrupt =
-+ {ar531x_ahb_proc_handler, SA_INTERRUPT, 0, "ar531x_ahb_proc_interrupt",
-+ NULL, NULL};
-+
-+extern asmlinkage void ar531x_interrupt_receive(void);
-+
-+/*
-+ * Called when an interrupt is received, this function
-+ * determines exactly which interrupt it was, and it
-+ * invokes the appropriate handler.
-+ *
-+ * Implicitly, we also define interrupt priority by
-+ * choosing which to dispatch first.
-+ */
-+void
-+ar531x_irq_dispatch(struct pt_regs *regs)
-+{
-+ int cause_intrs = regs->cp0_cause;
-+ int status_intrs = regs->cp0_status;
-+ int pending = cause_intrs & status_intrs;
-+
-+ if (pending & CAUSEF_IP2) {
-+ do_IRQ(AR531X_IRQ_WLAN0_INTRS, regs);
-+ }
-+ else if (pending & CAUSEF_IP3) {
-+ do_IRQ(AR531X_IRQ_ENET0_INTRS, regs);
-+ }
-+ else if (pending & CAUSEF_IP4) {
-+ do_IRQ(AR531X_IRQ_ENET1_INTRS, regs);
-+ }
-+ else if (pending & CAUSEF_IP5) {
-+ do_IRQ(AR531X_IRQ_WLAN1_INTRS, regs);
-+ }
-+ else if (pending & CAUSEF_IP6) {
-+ AR531X_REG ar531x_isr = sysRegRead(AR531X_ISR);
-+ AR531X_REG ar531x_imr = sysRegRead(AR531X_IMR);
-+ unsigned int ar531x_misc_intrs = ar531x_isr & ar531x_imr;
-+
-+ if (ar531x_misc_intrs & AR531X_ISR_TIMER)
-+ do_IRQ(AR531X_MISC_IRQ_TIMER, regs);
-+ else if (ar531x_misc_intrs & AR531X_ISR_AHBPROC)
-+ do_IRQ(AR531X_MISC_IRQ_AHB_PROC, regs);
-+ else if (ar531x_misc_intrs & AR531X_ISR_AHBDMA)
-+ do_IRQ(AR531X_MISC_IRQ_AHB_DMA, regs);
-+ else if (ar531x_misc_intrs & AR531X_ISR_GPIO)
-+ {
-+ int i;
-+ u32 gpioIntPending;
-+
-+ gpioIntPending = sysRegRead(AR531X_GPIO_DI) & gpioIntMask;
-+ for (i=0; i<AR531X_GPIO_IRQ_COUNT; i++) {
-+ if (gpioIntPending & (1 << i))
-+ do_IRQ(AR531X_GPIO_IRQ(i), regs);
-+ }
-+ }
-+ else if ((ar531x_misc_intrs & AR531X_ISR_UART0) ||
-+ (ar531x_misc_intrs & AR531X_ISR_UART0DMA)) {
-+ do_IRQ(AR531X_MISC_IRQ_UART0, regs);
-+#if CONFIG_KGDB
-+ if (kgdbInterrupt()) {
-+ if (!user_mode(regs))
-+ set_async_breakpoint((unsigned long *)&regs->cp0_epc);
-+ }
-+#endif /* CONFIG_KGDB */
-+ }
-+ else if (ar531x_misc_intrs & AR531X_ISR_WD)
-+ do_IRQ(AR531X_MISC_IRQ_WATCHDOG, regs);
-+ else if (ar531x_misc_intrs & AR531X_ISR_LOCAL)
-+ do_IRQ(AR531X_MISC_IRQ_LOCAL, regs);
-+ else
-+ do_IRQ(AR531X_MISC_IRQ_NONE, regs);
-+ } else if (pending & CAUSEF_IP7)
-+ do_IRQ(AR531X_IRQ_CPU_CLOCK, regs);
-+ else
-+ do_IRQ(AR531X_IRQ_NONE, regs);
-+}
-+
-+void __init init_IRQ(void)
-+{
-+ init_generic_irq();
-+ set_except_vector(0, ar531x_interrupt_receive);
-+
-+ /* Initialize interrupt controllers */
-+ mips_cpu_irq_init(MIPS_CPU_IRQ_BASE);
-+ ar531x_misc_intr_init(AR531X_MISC_IRQ_BASE);
-+ ar531x_gpio_intr_init(AR531X_GPIO_IRQ_BASE);
-+ setup_irq(AR531X_IRQ_MISC_INTRS, &cascade);
-+ /*
-+ * AR531X_IRQ_CPU_CLOCK is setup by ar531x_timer_setup.
-+ */
-+
-+ /* Default "spurious interrupt" handlers */
-+ setup_irq(AR531X_IRQ_NONE, &spurious_irq);
-+ setup_irq(AR531X_MISC_IRQ_NONE, &spurious_misc);
-+ setup_irq(AR531X_GPIO_IRQ_NONE, &spurious_gpio);
-+
-+ setup_irq(AR531X_MISC_IRQ_TIMER, &ar531x_timer_interrupt);
-+ setup_irq(AR531X_MISC_IRQ_AHB_PROC, &ar531x_ahb_proc_interrupt);
-+ setup_irq(AR531X_MISC_IRQ_GPIO, &cascade);
-+
-+#ifdef CONFIG_KGDB
-+#if CONFIG_EARLY_STOP
-+ kgdbInit();
-+#endif
-+#endif
-+}
-diff -urN linux-2.4.32/arch/mips/ar531x/ar531xksyms.c linux-2.4.32.new/arch/mips/ar531x/ar531xksyms.c
---- linux-2.4.32/arch/mips/ar531x/ar531xksyms.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/ar531xksyms.c 2005-12-24 20:29:42.132306768 +0000
-@@ -0,0 +1,16 @@
-+/*
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file "COPYING" in the main directory of this archive
-+ * for more details.
-+ *
-+ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
-+ */
-+
-+#include <linux/module.h>
-+#include "asm/atheros/ar531xbsp.h"
-+
-+#if CONFIG_KGDB
-+EXPORT_SYMBOL(kgdbInit);
-+EXPORT_SYMBOL(kgdbEnabled);
-+#endif
-+EXPORT_SYMBOL(ar531x_sys_frequency);
-diff -urN linux-2.4.32/arch/mips/ar531x/ar531xlnx.h linux-2.4.32.new/arch/mips/ar531x/ar531xlnx.h
---- linux-2.4.32/arch/mips/ar531x/ar531xlnx.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/ar531xlnx.h 2005-12-24 20:29:42.133306616 +0000
-@@ -0,0 +1,122 @@
-+/*
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file "COPYING" in the main directory of this archive
-+ * for more details.
-+ *
-+ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
-+ */
-+
-+/*
-+ * This file contains definitions needed in order to compile
-+ * AR531X products for linux. Definitions that are largely
-+ * AR531X-specific and independent of operating system belong
-+ * in ar531x.h rather than this file.
-+ */
-+#include "ar531x.h"
-+
-+#define MIPS_CPU_IRQ_BASE 0x00
-+#define AR531X_HIGH_PRIO 0x10
-+#define AR531X_MISC_IRQ_BASE 0x20
-+#define AR531X_GPIO_IRQ_BASE 0x30
-+
-+/* Software's idea of interrupts handled by "CPU Interrupt Controller" */
-+#define AR531X_IRQ_NONE MIPS_CPU_IRQ_BASE+0
-+#define AR531X_IRQ_WLAN0_INTRS MIPS_CPU_IRQ_BASE+2 /* C0_CAUSE: 0x0400 */
-+#define AR531X_IRQ_ENET0_INTRS MIPS_CPU_IRQ_BASE+3 /* C0_CAUSE: 0x0800 */
-+#define AR531X_IRQ_ENET1_INTRS MIPS_CPU_IRQ_BASE+4 /* C0_CAUSE: 0x1000 */
-+#define AR531X_IRQ_WLAN1_INTRS MIPS_CPU_IRQ_BASE+5 /* C0_CAUSE: 0x2000 */
-+#define AR531X_IRQ_MISC_INTRS MIPS_CPU_IRQ_BASE+6 /* C0_CAUSE: 0x4000 */
-+#define AR531X_IRQ_CPU_CLOCK MIPS_CPU_IRQ_BASE+7 /* C0_CAUSE: 0x8000 */
-+
-+/* Miscellaneous interrupts, which share IP6 */
-+#define AR531X_MISC_IRQ_NONE AR531X_MISC_IRQ_BASE+0
-+#define AR531X_MISC_IRQ_TIMER AR531X_MISC_IRQ_BASE+1
-+#define AR531X_MISC_IRQ_AHB_PROC AR531X_MISC_IRQ_BASE+2
-+#define AR531X_MISC_IRQ_AHB_DMA AR531X_MISC_IRQ_BASE+3
-+#define AR531X_MISC_IRQ_GPIO AR531X_MISC_IRQ_BASE+4
-+#define AR531X_MISC_IRQ_UART0 AR531X_MISC_IRQ_BASE+5
-+#define AR531X_MISC_IRQ_UART0_DMA AR531X_MISC_IRQ_BASE+6
-+#define AR531X_MISC_IRQ_WATCHDOG AR531X_MISC_IRQ_BASE+7
-+#define AR531X_MISC_IRQ_LOCAL AR531X_MISC_IRQ_BASE+8
-+#define AR531X_MISC_IRQ_COUNT 9
-+
-+/* GPIO Interrupts [0..7], share AR531X_MISC_IRQ_GPIO */
-+#define AR531X_GPIO_IRQ_NONE AR531X_MISC_IRQ_BASE+0
-+#define AR531X_GPIO_IRQ(n) AR531X_MISC_IRQ_BASE+(n)+1
-+#define AR531X_GPIO_IRQ_COUNT 9
-+
-+#define PHYS_TO_K1(physaddr) KSEG1ADDR(physaddr)
-+#define PHYS_TO_K0(physaddr) KSEG0ADDR(physaddr)
-+#define UNMAPPED_TO_PHYS(vaddr) PHYSADDR(vaddr)
-+#define IS_UNMAPPED_VADDR(vaddr) \
-+ ((KSEGX(vaddr) == KSEG0) || (KSEGX(vaddr) == KSEG1))
-+
-+/* IOCTL commands for /proc/ar531x */
-+#define AR531X_CTRL_DO_BREAKPOINT 1
-+#define AR531X_CTRL_DO_MADWIFI 2
-+
-+/*
-+ * Definitions for operating system portability.
-+ * These are vxWorks-->Linux translations.
-+ */
-+#define LOCAL static
-+#define BOOL int
-+#define TRUE 1
-+#define FALSE 0
-+#define UINT8 u8
-+#define UINT16 u16
-+#define UINT32 u32
-+#define PRINTF printk
-+#if /* DEBUG */ 1
-+#define DEBUG_PRINTF printk
-+#define INLINE
-+#else
-+DEBUG_PRINTF while (0) printk
-+#define INLINE inline
-+#endif
-+#define sysUDelay(usecs) udelay(usecs)
-+#define sysMsDelay(msecs) mdelay(msecs)
-+typedef volatile UINT8 *VIRT_ADDR;
-+#define MALLOC(sz) kmalloc(sz, GFP_KERNEL)
-+#define MALLOC_NOSLEEP(sz) kmalloc(sz, GFP_ATOMIC)
-+#define FREE(ptr) kfree((void *)ptr)
-+#define BSP_BUG() do { printk("kernel BSP BUG at %s:%d!\n", __FILE__, __LINE__); *(int *)0=0; } while (0)
-+#define BSP_BUG_ON(condition) do { if (unlikely((condition)!=0)) BSP_BUG(); } while(0)
-+#define ASSERT(x) BSP_BUG_ON(!(x))
-+
-+extern struct ar531x_boarddata *ar531x_board_configuration;
-+extern char *ar531x_radio_configuration;
-+extern char *enet_mac_address_get(int MACUnit);
-+
-+extern void kgdbInit(void);
-+extern int kgdbEnabled(void);
-+extern void breakpoint(void);
-+extern int kgdbInterrupt(void);
-+extern unsigned int ar531x_cpu_frequency(void);
-+extern unsigned int ar531x_sys_frequency(void);
-+
-+/* GPIO support */
-+extern struct irqaction spurious_gpio;
-+extern unsigned int gpioIntMask;
-+extern void ar531x_gpio_intr_init(int irq_base);
-+extern void ar531x_gpio_ctrl_output(int gpio);
-+extern void ar531x_gpio_ctrl_input(int gpio);
-+extern void ar531x_gpio_set(int gpio, int val);
-+extern int ar531x_gpio_get(int gpio);
-+extern void ar531x_gpio_intr_enable(unsigned int irq);
-+extern void ar531x_gpio_intr_disable(unsigned int irq);
-+
-+/* Watchdog Timer support */
-+extern int watchdog_start(unsigned int milliseconds);
-+extern int watchdog_stop(void);
-+extern int watchdog_is_enabled(void);
-+extern unsigned int watchdog_min_timer_reached(void);
-+extern void watchdog_notify_alive(void);
-+
-+#define A_DATA_CACHE_INVAL(start, length) \
-+ dma_cache_inv((UINT32)(start),(length))
-+
-+#define sysWbFlush() mb()
-+
-+#define intDisable(x) cli()
-+#define intEnable(x) sti()
-diff -urN linux-2.4.32/arch/mips/ar531x/ar531xprom.c linux-2.4.32.new/arch/mips/ar531x/ar531xprom.c
---- linux-2.4.32/arch/mips/ar531x/ar531xprom.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/ar531xprom.c 2005-12-24 20:29:42.133306616 +0000
-@@ -0,0 +1,84 @@
-+/*
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file "COPYING" in the main directory of this archive
-+ * for more details.
-+ *
-+ * Copyright MontaVista Software Inc
-+ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
-+ */
-+
-+/*
-+ * Prom setup file for ar531x
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/config.h>
-+#include <linux/kernel.h>
-+#include <linux/string.h>
-+#include <linux/mm.h>
-+#include <linux/bootmem.h>
-+
-+#include <asm/bootinfo.h>
-+#include <asm/addrspace.h>
-+
-+#include "ar531xlnx.h"
-+
-+#define COMMAND_LINE_SIZE 512
-+
-+char arcs_cmdline[COMMAND_LINE_SIZE];
-+
-+void __init prom_init(int argc, char *argv[])
-+{
-+ int i;
-+ unsigned int memcfg1;
-+ int bank0AC, bank1AC;
-+ int memsz_in_mb;
-+
-+ strcpy(arcs_cmdline, "console=ttyS0,9600");
-+ for (i=0; i<argc; i++) {
-+ strcat(arcs_cmdline, " ");
-+ strcat(arcs_cmdline, argv[i]);
-+ }
-+
-+ mips_machgroup = MACH_GROUP_AR531X;
-+#ifdef CONFIG_APUNUSED
-+ mips_machtype = MACH_ATHEROS_UNUSED;
-+#endif
-+#ifdef CONFIG_AP30
-+ mips_machtype = MACH_ATHEROS_AP30;
-+#endif
-+#ifdef CONFIG_AP33
-+ mips_machtype = MACH_ATHEROS_AP33;
-+#endif
-+#ifdef CONFIG_AP38
-+ mips_machtype = MACH_ATHEROS_AP38;
-+#endif
-+#ifdef CONFIG_AP43
-+ mips_machtype = MACH_ATHEROS_AP43;
-+#endif
-+#ifdef CONFIG_AP48
-+ mips_machtype = MACH_ATHEROS_AP48;
-+#endif
-+#ifdef CONFIG_PB32
-+ mips_machtype = MACH_ATHEROS_PB32;
-+#endif
-+
-+
-+ /* Determine SDRAM size based on Address Checks done at startup */
-+ memcfg1 = sysRegRead(AR531X_MEM_CFG1);
-+ bank0AC = (memcfg1 & MEM_CFG1_AC0) >> MEM_CFG1_AC0_S;
-+ bank1AC = (memcfg1 & MEM_CFG1_AC1) >> MEM_CFG1_AC1_S;
-+ memsz_in_mb = (bank0AC ? (1 << (bank0AC+1)) : 0)
-+ + (bank1AC ? (1 << (bank1AC+1)) : 0);
-+
-+ /*
-+ * By default, use all available memory. You can override this
-+ * to use, say, 8MB by specifying "mem=8M" as an argument on the
-+ * linux bootup command line.
-+ */
-+ add_memory_region(0, memsz_in_mb << 20, BOOT_MEM_RAM);
-+}
-+
-+void __init prom_free_prom_memory(void)
-+{
-+}
-diff -urN linux-2.4.32/arch/mips/ar531x/ar531xsetup.c linux-2.4.32.new/arch/mips/ar531x/ar531xsetup.c
---- linux-2.4.32/arch/mips/ar531x/ar531xsetup.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/ar531xsetup.c 2005-12-24 20:29:42.133306616 +0000
-@@ -0,0 +1,240 @@
-+/*
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file "COPYING" in the main directory of this archive
-+ * for more details.
-+ *
-+ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
-+ */
-+
-+/*
-+ * Initialization for ar531x SOC.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/irq.h>
-+#include <linux/interrupt.h>
-+#include <linux/serial.h>
-+#include <linux/types.h>
-+#include <linux/string.h>
-+
-+#include <asm/reboot.h>
-+#include <asm/io.h>
-+#include <asm/time.h>
-+#include <asm/pgtable.h>
-+#include <asm/processor.h>
-+#include <asm/reboot.h>
-+#include <asm/system.h>
-+#include <asm/serial.h>
-+
-+#include "ar531xlnx.h"
-+
-+void
-+ar531x_restart(char *command)
-+{
-+ for(;;) {
-+ sysRegWrite(AR531X_RESET, AR531X_RESET_SYSTEM);
-+ }
-+}
-+
-+void
-+ar531x_halt(void)
-+{
-+ printk(KERN_NOTICE "\n** You can safely turn off the power\n");
-+ while (1);
-+}
-+
-+void
-+ar531x_power_off(void)
-+{
-+ ar531x_halt();
-+}
-+
-+const char *
-+get_system_type(void)
-+{
-+ return "Atheros AR531X";
-+}
-+
-+/*
-+ * This table is indexed by bits 5..4 of the CLOCKCTL1 register
-+ * to determine the predevisor value.
-+ */
-+static int CLOCKCTL1_PREDIVIDE_TABLE[4] = {
-+ 1,
-+ 2,
-+ 4,
-+ 5
-+};
-+
-+unsigned int
-+ar531x_cpu_frequency(void)
-+{
-+ static unsigned int ar531x_calculated_cpu_freq;
-+ unsigned int clockctl1_predivide_mask;
-+ unsigned int clockctl1_predivide_shift;
-+ unsigned int clockctl1_multiplier_mask;
-+ unsigned int clockctl1_multiplier_shift;
-+ unsigned int clockctl1_doubler_mask;
-+ int wisoc_revision;
-+
-+ /*
-+ * Trust the bootrom's idea of cpu frequency.
-+ */
-+ ar531x_calculated_cpu_freq = sysRegRead(AR5312_SCRATCH);
-+ if (ar531x_calculated_cpu_freq)
-+ return ar531x_calculated_cpu_freq;
-+
-+ wisoc_revision = (sysRegRead(AR531X_REV) & AR531X_REV_MAJ) >> AR531X_REV_MAJ_S;
-+ if (wisoc_revision == AR531X_REV_MAJ_AR2313) {
-+ clockctl1_predivide_mask = AR2313_CLOCKCTL1_PREDIVIDE_MASK;
-+ clockctl1_predivide_shift = AR2313_CLOCKCTL1_PREDIVIDE_SHIFT;
-+ clockctl1_multiplier_mask = AR2313_CLOCKCTL1_MULTIPLIER_MASK;
-+ clockctl1_multiplier_shift = AR2313_CLOCKCTL1_MULTIPLIER_SHIFT;
-+ clockctl1_doubler_mask = AR2313_CLOCKCTL1_DOUBLER_MASK;
-+ } else { /* AR5312 and AR2312 */
-+ clockctl1_predivide_mask = AR5312_CLOCKCTL1_PREDIVIDE_MASK;
-+ clockctl1_predivide_shift = AR5312_CLOCKCTL1_PREDIVIDE_SHIFT;
-+ clockctl1_multiplier_mask = AR5312_CLOCKCTL1_MULTIPLIER_MASK;
-+ clockctl1_multiplier_shift = AR5312_CLOCKCTL1_MULTIPLIER_SHIFT;
-+ clockctl1_doubler_mask = AR5312_CLOCKCTL1_DOUBLER_MASK;
-+ }
-+
-+ /*
-+ * Clocking is derived from a fixed 40MHz input clock.
-+ * cpuFreq = InputClock * MULT (where MULT is PLL multiplier)
-+ *
-+ * sysFreq = cpuFreq / 4 (used for APB clock, serial,
-+ * flash, Timer, Watchdog Timer)
-+ *
-+ * cntFreq = cpuFreq / 2 (use for CPU count/compare)
-+ *
-+ * So, for example, with a PLL multiplier of 5, we have
-+ * cpuFrez = 200MHz
-+ * sysFreq = 50MHz
-+ * cntFreq = 100MHz
-+ *
-+ * We compute the CPU frequency, based on PLL settings.
-+ */
-+ if (ar531x_calculated_cpu_freq == 0) {
-+ unsigned int clockCtl1 = sysRegRead(AR5312_CLOCKCTL1);
-+
-+ int preDivideSelect = (clockCtl1 & clockctl1_predivide_mask) >>
-+ clockctl1_predivide_shift;
-+
-+ int preDivisor = CLOCKCTL1_PREDIVIDE_TABLE[preDivideSelect];
-+
-+ int multiplier = (clockCtl1 & clockctl1_multiplier_mask) >>
-+ clockctl1_multiplier_shift;
-+
-+ if (clockCtl1 & clockctl1_doubler_mask) {
-+ multiplier = multiplier << 1;
-+ }
-+
-+ ar531x_calculated_cpu_freq = (40000000 / preDivisor) * multiplier;
-+ }
-+
-+ return ar531x_calculated_cpu_freq;
-+}
-+
-+unsigned int
-+ar531x_sys_frequency(void)
-+{
-+ static unsigned int ar531x_calculated_sys_freq = 0;
-+
-+ if (ar531x_calculated_sys_freq == 0) {
-+ ar531x_calculated_sys_freq = ar531x_cpu_frequency() / 4;
-+ }
-+
-+ return ar531x_calculated_sys_freq;
-+}
-+
-+static void __init
-+flash_setup(void)
-+{
-+ UINT32 flash_ctl;
-+
-+ /* Configure flash bank 0 */
-+ flash_ctl = FLASHCTL_E |
-+ FLASHCTL_AC_8M |
-+ FLASHCTL_RBLE |
-+ (0x01 << FLASHCTL_IDCY_S) |
-+ (0x07 << FLASHCTL_WST1_S) |
-+ (0x07 << FLASHCTL_WST2_S) |
-+ (sysRegRead(AR531X_FLASHCTL0) & FLASHCTL_MW);
-+
-+ sysRegWrite(AR531X_FLASHCTL0, flash_ctl);
-+
-+ /* Disable other flash banks */
-+ sysRegWrite(AR531X_FLASHCTL1,
-+ sysRegRead(AR531X_FLASHCTL1) & ~(FLASHCTL_E | FLASHCTL_AC));
-+
-+ sysRegWrite(AR531X_FLASHCTL2,
-+ sysRegRead(AR531X_FLASHCTL2) & ~(FLASHCTL_E | FLASHCTL_AC));
-+}
-+
-+
-+
-+void __init
-+serial_setup(void)
-+{
-+ struct serial_struct s;
-+
-+ memset(&s, 0, sizeof(s));
-+
-+ s.flags = STD_COM_FLAGS;
-+ s.io_type = SERIAL_IO_MEM;
-+ s.baud_base = ar531x_sys_frequency()/16;
-+ s.irq = AR531X_MISC_IRQ_UART0;
-+ s.iomem_reg_shift = 2;
-+ s.iomem_base = (u8 *)0xbc000003;
-+
-+ if (early_serial_setup(&s) != 0)
-+ printk(KERN_ERR "early_serial_setup failed\n");
-+}
-+
-+extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
-+static void __init
-+ar531x_timer_setup(struct irqaction *irq)
-+{
-+ unsigned int count;
-+
-+ /* Usually irq is timer_irqaction (timer_interrupt) */
-+ setup_irq(AR531X_IRQ_CPU_CLOCK, irq);
-+
-+ /* to generate the first CPU timer interrupt */
-+ count = read_c0_count();
-+ write_c0_compare(count + 1000);
-+}
-+
-+extern void (*board_time_init)(void);
-+
-+static void __init
-+ar531x_time_init(void)
-+{
-+ mips_hpt_frequency = ar531x_cpu_frequency() / 2;
-+}
-+
-+void __init
-+ar531x_setup(void)
-+{
-+ /* Clear any lingering AHB errors */
-+ sysRegRead(AR531X_PROCADDR);
-+ sysRegRead(AR531X_DMAADDR);
-+
-+ sysRegWrite(AR531X_WD_CTRL, AR531X_WD_CTRL_IGNORE_EXPIRATION);
-+
-+ /* Disable data watchpoints */
-+ write_c0_watchlo0(0);
-+
-+ board_time_init = ar531x_time_init;
-+ board_timer_setup = ar531x_timer_setup;
-+
-+ _machine_restart = ar531x_restart;
-+ _machine_halt = ar531x_halt;
-+ _machine_power_off = ar531x_power_off;
-+
-+ flash_setup();
-+ serial_setup();
-+}
-diff -urN linux-2.4.32/arch/mips/ar531x/Makefile linux-2.4.32.new/arch/mips/ar531x/Makefile
---- linux-2.4.32/arch/mips/ar531x/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/Makefile 2005-12-24 20:29:42.010325312 +0000
-@@ -0,0 +1,33 @@
-+#
-+# This file is subject to the terms and conditions of the GNU General Public
-+# License. See the file "COPYING" in the main directory of this archive
-+# for more details.
-+#
-+# Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
-+#
-+
-+# Makefile for Atheros ar531x boards
-+#
-+# Note! Dependencies are done automagically by 'make dep', which also
-+# removes any old dependencies. DON'T put your own dependencies here
-+# unless it's something special (ie not a .c file).
-+#
-+
-+.S.s:
-+ $(CPP) $(CFLAGS) $< -o $*.s
-+.S.o:
-+ $(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $*.o
-+
-+O_TARGET:= ar531x.o
-+
-+export-objs = ar531xksyms.o
-+
-+obj-y := ar531xdbg_io.o \
-+ ar531xsetup.o \
-+ ar531xprom.o \
-+ ar531xirq.o \
-+ ar531xintr.o \
-+ ar531xgpio.o \
-+ ar531xksyms.o
-+
-+include $(TOPDIR)/Rules.make
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/backup-busybox.links linux-2.4.32.new/arch/mips/ar531x/RAMDISK/backup-busybox.links
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/backup-busybox.links 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/backup-busybox.links 2005-12-24 20:29:42.011325160 +0000
-@@ -0,0 +1,33 @@
-+/usr/bin/[
-+/sbin/brctl
-+/bin/cat
-+/bin/chmod
-+/bin/cp
-+/bin/df
-+/bin/echo
-+/bin/false
-+/sbin/ifconfig
-+/sbin/init
-+/sbin/insmod
-+/bin/kill
-+/bin/ls
-+/sbin/lsmod
-+/bin/mkdir
-+/sbin/modprobe
-+/bin/mount
-+/bin/msh
-+/bin/mv
-+/bin/ping
-+/bin/ps
-+/bin/pwd
-+/sbin/reboot
-+/bin/rm
-+/bin/rmdir
-+/sbin/rmmod
-+/sbin/route
-+/bin/sh
-+/usr/bin/test
-+/usr/bin/top
-+/bin/true
-+/bin/umount
-+/usr/bin/wget
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/busybox.links linux-2.4.32.new/arch/mips/ar531x/RAMDISK/busybox.links
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/busybox.links 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/busybox.links 2005-12-24 20:29:42.011325160 +0000
-@@ -0,0 +1,33 @@
-+/usr/bin/[
-+/sbin/brctl
-+/bin/cat
-+/bin/chmod
-+/bin/cp
-+/bin/df
-+/bin/echo
-+/bin/false
-+/sbin/ifconfig
-+/sbin/init
-+/sbin/insmod
-+/bin/kill
-+/bin/ls
-+/sbin/lsmod
-+/bin/mkdir
-+/sbin/modprobe
-+/bin/mount
-+/bin/msh
-+/bin/mv
-+/bin/ping
-+/bin/ps
-+/bin/pwd
-+/sbin/reboot
-+/bin/rm
-+/bin/rmdir
-+/sbin/rmmod
-+/sbin/route
-+/bin/sh
-+/usr/bin/test
-+/bin/true
-+/bin/umount
-+/bin/uname
-+/usr/bin/wget
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/Makefile linux-2.4.32.new/arch/mips/ar531x/RAMDISK/Makefile
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/Makefile 2005-12-24 20:29:42.011325160 +0000
-@@ -0,0 +1,53 @@
-+KERNEL_SOURCE=../../../..
-+
-+# The value for INITRDSIZE is extracted from linux/.config,
-+# if it exists; otherwise, a default value is used.
-+
-+CONFIG_FILE = $(KERNEL_SOURCE)/.config
-+
-+ifeq ($(CONFIG_FILE),$(wildcard $(CONFIG_FILE)))
-+
-+include $(CONFIG_FILE)
-+ifdef CONFIG_BLK_DEV_RAM_SIZE
-+INITRDSIZE := $(shell echo $(CONFIG_BLK_DEV_RAM_SIZE))
-+else
-+INITRDSIZE := 8192
-+endif
-+
-+else
-+INITRDSIZE := 8192
-+endif
-+
-+MOUNTPT = /mnt/xtmp
-+
-+ramdisk.gz: ramdisk
-+ gzip -f ramdisk
-+
-+ramdisk:
-+ ./makelinks
-+ @echo "CREATING RAMDISK OF SIZE $(INITRDSIZE) on $@"
-+ dd if=/dev/zero of=$@ bs=1k count=$(INITRDSIZE)
-+ /sbin/mke2fs -vFm0 $@ $(INITRDSIZE)
-+ if [ \! -e $(MOUNTPT) ]; then mkdir -p $(MOUNTPT) ; fi
-+ mount -o loop $@ $(MOUNTPT)
-+ @df $(MOUNTPT)
-+ (cd rootdir; tar cf - . ) | (cd $(MOUNTPT) && tar xf - )
-+ (cd $(MOUNTPT) ; chown -R root.root . )
-+ @df $(MOUNTPT)
-+ umount $(MOUNTPT)
-+
-+install:
-+ @(if [ -d $(KERNEL_SOURCE)/arch/mips/ramdisk ]; \
-+ then \
-+ if [ -f ramdisk.gz ]; \
-+ then \
-+ cp ramdisk.gz $(KERNEL_SOURCE)/arch/mips/ramdisk/; \
-+ else \
-+ echo "No ramdisk.gz image"; \
-+ fi; \
-+ else \
-+ echo "No ramdisk directory. Check KERNEL_SOURCE variable."; \
-+ fi)
-+
-+clean:
-+ rm -f ramdisk.gz ramdisk
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/makelinks linux-2.4.32.new/arch/mips/ar531x/RAMDISK/makelinks
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/makelinks 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/makelinks 2005-12-24 20:29:42.012325008 +0000
-@@ -0,0 +1,65 @@
-+#!/bin/sh
-+
-+if [ -f busybox.links ]
-+then
-+ cat busybox.links | sed 's/\//ln -s -f \/bin\/busybox rootdir\//' | /bin/sh
-+fi
-+
-+cons=" root tty 622"
-+disk=" root disk 660"
-+mtd=" root root 640"
-+makedev () { # usage: makedev name [bcu] major minor owner group mode
-+ if [ "$opt_v" ]
-+ then if [ "$opt_d" ]
-+ then echo "rm -f $1"
-+ else echo "$1 = $2 $3 $4 $5:$6 $7"
-+ fi
-+ fi
-+ [ ! "$opt_n" ] && rm -f $1 &&
-+ [ ! "$opt_d" ] && mknod $1 $2 $3 $4 &&
-+ chown $5:$6 $1 &&
-+ chmod $7 $1
-+}
-+
-+makedev rootdir/dev/console c 5 1 $cons
-+makedev rootdir/dev/ram b 1 1 $disk
-+makedev rootdir/dev/ram0 b 1 0 $disk
-+makedev rootdir/dev/ram1 b 1 1 $disk
-+makedev rootdir/dev/ram2 b 1 2 $disk
-+makedev rootdir/dev/ram3 b 1 3 $disk
-+makedev rootdir/dev/ram4 b 1 4 $disk
-+makedev rootdir/dev/ram5 b 1 5 $disk
-+makedev rootdir/dev/ram6 b 1 6 $disk
-+makedev rootdir/dev/ram7 b 1 7 $disk
-+makedev rootdir/dev/ram8 b 1 8 $disk
-+makedev rootdir/dev/ram9 b 1 9 $disk
-+makedev rootdir/dev/ram10 b 1 10 $disk
-+makedev rootdir/dev/ram11 b 1 11 $disk
-+makedev rootdir/dev/ram12 b 1 12 $disk
-+makedev rootdir/dev/ram13 b 1 13 $disk
-+makedev rootdir/dev/ram14 b 1 14 $disk
-+makedev rootdir/dev/ram15 b 1 15 $disk
-+
-+makedev rootdir/dev/mtd0 c 90 0 $mtd
-+makedev rootdir/dev/mtd1 c 90 2 $mtd
-+makedev rootdir/dev/mtd2 c 90 4 $mtd
-+makedev rootdir/dev/mtd3 c 90 6 $mtd
-+makedev rootdir/dev/mtd4 c 90 8 $mtd
-+makedev rootdir/dev/mtd5 c 90 10 $mtd
-+makedev rootdir/dev/mtd6 c 90 12 $mtd
-+makedev rootdir/dev/mtdblock0 b 31 0 $mtd
-+makedev rootdir/dev/mtdblock1 b 31 1 $mtd
-+makedev rootdir/dev/mtdblock2 b 31 2 $mtd
-+makedev rootdir/dev/mtdblock3 b 31 3 $mtd
-+makedev rootdir/dev/mtdblock4 b 31 4 $mtd
-+makedev rootdir/dev/mtdblock5 b 31 5 $mtd
-+makedev rootdir/dev/mtdblock6 b 31 6 $mtd
-+makedev rootdir/dev/mtdr0 c 90 1 $mtd
-+makedev rootdir/dev/mtdr1 c 90 3 $mtd
-+makedev rootdir/dev/mtdr2 c 90 5 $mtd
-+makedev rootdir/dev/mtdr3 c 90 7 $mtd
-+makedev rootdir/dev/mtdr4 c 90 9 $mtd
-+makedev rootdir/dev/mtdr5 c 90 11 $mtd
-+makedev rootdir/dev/mtdr6 c 90 13 $mtd
-+
-+cd rootdir/dev;ln -sf ram1 ram
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/README linux-2.4.32.new/arch/mips/ar531x/RAMDISK/README
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/README 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/README 2005-12-24 20:29:42.011325160 +0000
-@@ -0,0 +1,40 @@
-+How to build a ramdisk image for use as a root filesystem with AR531X
-+
-+Overview:
-+In order to boot from a ramdisk root file system image, you will
-+first create a root directory structure in the "rootdir" directory.
-+Then run "make" to create a compressed root file system image in
-+ramdisk.gz. Finally, copy this image into your kernel source tree
-+and remake the kernel. The ramdisk image is then built into the
-+kernel. When the kernel starts, it is uncompressed into RAM, and
-+used as a root file system.
-+
-+If you'd like to use a pre-built ramdisk.gz rather than build
-+one yourself:
-+ cp arch/mips/ar531x/RAMDISK/ramdisk.gz arch/mips/ramdisk/ramdisk.gz
-+
-+Here are the detailed steps to build your own:
-+
-+1) Modify Makefile to point KERNEL_SOURCE at your linux source tree.
-+
-+2) Copy whatever additional files/directories/links you'd like to
-+ under rootdir. Note that you're limited to CONFIG_BLK_DEV_RAM_SIZE
-+ 1KB blocks, as specified in your linux/.config file.
-+ Examples:
-+ Copy busybox to rootdir/bin/
-+ [NOTE: Copy busybox.links to this directory to
-+ cause the makelinks script to automatically
-+ set up all of the necessary busybox command links
-+ in the rootdir/bin directory].
-+
-+ Copy any wireless driver modules into rootdir tree
-+
-+ You might want to make a copy of the rootdir directory
-+ before you modify it, just in case you want to get back
-+ to the original.
-+
-+3) LOGIN AS ROOT (e.g. "su") and type "make"
-+
-+4) Copy the resulting ramdisk.gz to your linux source tree under
-+ arch/mips/ramdisk/ramdisk.gz
-+ (or "make install" will do this step for you)
-Binary files linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/bin/busybox and linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/bin/busybox differ
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/fstab linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/fstab
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/fstab 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/fstab 2005-12-24 20:29:42.063317256 +0000
-@@ -0,0 +1 @@
-+/proc /proc proc defaults 0 0
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/group linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/group
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/group 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/group 2005-12-24 20:29:42.064317104 +0000
-@@ -0,0 +1,18 @@
-+root:x:0:
-+wheel:x:10:
-+bin:x:1:bin,daemon
-+daemon:x:2:bin,daemon
-+sys:x:3:bin,adm
-+adm:x:4:adm,daemon
-+tty:x:5:
-+disk:x:6:
-+lp:x:7:daemon,lp
-+mem:x:8:
-+kmem:x:9:
-+operator:x:11:
-+uucp:x:14:uucp
-+dip:x:40:
-+utmp:x:45:
-+www:x:63:
-+nobody:x:65534:
-+users:x:100:
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/host.conf linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/host.conf
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/host.conf 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/host.conf 2005-12-24 20:29:42.064317104 +0000
-@@ -0,0 +1,2 @@
-+order hosts,bind
-+multi on
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/inittab linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/inittab
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/inittab 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/inittab 2005-12-24 20:29:42.064317104 +0000
-@@ -0,0 +1,2 @@
-+::sysinit:/etc/rc.d/rcS
-+::respawn:/bin/sh
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/nsswitch.conf linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/nsswitch.conf
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/nsswitch.conf 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/nsswitch.conf 2005-12-24 20:29:42.065316952 +0000
-@@ -0,0 +1,16 @@
-+# /etc/nsswitch.conf
-+#
-+# Name Service Switch configuration file.
-+#
-+
-+passwd: compat
-+shadow: compat
-+group: compat
-+
-+hosts: files dns
-+networks: files dns
-+
-+ethers: files
-+protocols: files
-+rpc: files
-+services: files
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/passwd linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/passwd
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/passwd 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/passwd 2005-12-24 20:29:42.065316952 +0000
-@@ -0,0 +1,11 @@
-+root:x:0:0:root:/root:/bin/ash
-+bin:x:1:1:bin:/bin:/bin/sh
-+daemon:x:2:2:daemon:/usr/sbin:/bin/sh
-+adm:x:3:4:adm:/adm:/bin/sh
-+lp:x:4:7:lp:/var/spool/lpd:/bin/sh
-+sync:x:5:0:sync:/bin:/bin/sync
-+shutdown:x:6:11:shutdown:/sbin:/sbin/shutdown
-+halt:x:7:0:halt:/sbin:/sbin/halt
-+uucp:x:10:14:uucp:/var/spool/uucp:/bin/sh
-+operator:x:11:0:Operator:/var:/bin/sh
-+nobody:x:65534:65534:nobody:/home:/bin/sh
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/rc.d/rcS linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/rc.d/rcS
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/rc.d/rcS 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/rc.d/rcS 2005-12-24 20:29:42.066316800 +0000
-@@ -0,0 +1,17 @@
-+#!/bin/sh
-+
-+mount -a
-+mount -t jffs2 -o remount +w /
-+# mount -t ramfs /dev/ram /ramdisk
-+
-+echo Load MADWiFi wlan module
-+insmod ../../lib/modules/2.4.25/net/wlan.o
-+
-+echo Load MADWiFi Atheros HAL module
-+insmod ../../lib/modules/2.4.25/net/ath_hal.o
-+
-+echo Load MADWiFi Atheros Driver module
-+insmod ../../lib/modules/2.4.25/net/ath_lbus.o
-+
-+exit
-+
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/resolv.conf linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/resolv.conf
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/resolv.conf 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/resolv.conf 2005-12-24 20:29:42.066316800 +0000
-@@ -0,0 +1,18 @@
-+# /etc/resolv.conf - DNS setup file
-+#
-+# possible entries are:
-+#
-+# domain <domain> Local domain name. If not present, the
-+# gethostbyname syscall is used to
-+# determine the local domain name.
-+#
-+# search <list_of_domains> Search list for hostname lookup.
-+# The search list is normally determined
-+# from the local domain name but it
-+# can be set to a list of domains.
-+#
-+# nameserver <ip_addr> Define which server to contact
-+# for DNS lookups. If there are
-+# multiple nameserver lines (Max=3),
-+# they are queried in the listed order.
-+#
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/securetty linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/securetty
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/securetty 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/securetty 2005-12-24 20:29:42.066316800 +0000
-@@ -0,0 +1,12 @@
-+tty1
-+tty2
-+tty3
-+tty4
-+tty5
-+tty6
-+tty7
-+tty8
-+ttyS0
-+ttyS1
-+ttyS2
-+ttyS3
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/services linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/services
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/services 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/services 2005-12-24 20:29:42.066316800 +0000
-@@ -0,0 +1,193 @@
-+# $NetBSD: services,v 1.18 1996/03/26 00:07:58 mrg Exp $
-+#
-+# Network services, Internet style
-+#
-+# Note that it is presently the policy of IANA to assign a single well-known
-+# port number for both TCP and UDP; hence, most entries here have two entries
-+# even if the protocol doesn't support UDP operations.
-+# Updated from RFC 1340, ``Assigned Numbers'' (July 1992). Not all ports
-+# are included, only the more common ones.
-+#
-+# from: @(#)services 5.8 (Berkeley) 5/9/91
-+#
-+tcpmux 1/tcp # TCP port service multiplexer
-+echo 7/tcp
-+echo 7/udp
-+discard 9/tcp sink null
-+discard 9/udp sink null
-+systat 11/tcp users
-+daytime 13/tcp
-+daytime 13/udp
-+netstat 15/tcp
-+qotd 17/tcp quote
-+msp 18/tcp # message send protocol
-+msp 18/udp # message send protocol
-+chargen 19/tcp ttytst source
-+chargen 19/udp ttytst source
-+ftp-data 20/tcp # default ftp data port
-+ftp 21/tcp
-+ssh 22/tcp
-+ssh 22/udp
-+telnet 23/tcp
-+# 24 - private
-+smtp 25/tcp mail
-+# 26 - unassigned
-+time 37/tcp timserver
-+time 37/udp timserver
-+rlp 39/udp resource # resource location
-+nameserver 42/tcp name # IEN 116
-+whois 43/tcp nicname
-+domain 53/tcp nameserver # name-domain server
-+domain 53/udp nameserver
-+mtp 57/tcp # deprecated
-+bootps 67/tcp # BOOTP server
-+bootps 67/udp
-+bootpc 68/tcp # BOOTP client
-+bootpc 68/udp
-+tftp 69/udp
-+gopher 70/tcp # Internet Gopher
-+gopher 70/udp
-+rje 77/tcp netrjs
-+finger 79/tcp
-+www 80/tcp http # WorldWideWeb HTTP
-+www 80/udp # HyperText Transfer Protocol
-+link 87/tcp ttylink
-+kerberos 88/tcp krb5 # Kerberos v5
-+kerberos 88/udp
-+supdup 95/tcp
-+# 100 - reserved
-+hostnames 101/tcp hostname # usually from sri-nic
-+iso-tsap 102/tcp tsap # part of ISODE.
-+csnet-ns 105/tcp cso-ns # also used by CSO name server
-+csnet-ns 105/udp cso-ns
-+rtelnet 107/tcp # Remote Telnet
-+rtelnet 107/udp
-+pop2 109/tcp pop-2 postoffice # POP version 2
-+pop2 109/udp
-+pop3 110/tcp pop-3 # POP version 3
-+pop3 110/udp
-+sunrpc 111/tcp
-+sunrpc 111/udp
-+auth 113/tcp authentication tap ident
-+sftp 115/tcp
-+uucp-path 117/tcp
-+nntp 119/tcp readnews untp # USENET News Transfer Protocol
-+ntp 123/tcp
-+ntp 123/udp # Network Time Protocol
-+netbios-ns 137/tcp # NETBIOS Name Service
-+netbios-ns 137/udp
-+netbios-dgm 138/tcp # NETBIOS Datagram Service
-+netbios-dgm 138/udp
-+netbios-ssn 139/tcp # NETBIOS session service
-+netbios-ssn 139/udp
-+imap2 143/tcp imap # Interim Mail Access Proto v2
-+imap2 143/udp
-+snmp 161/udp # Simple Net Mgmt Proto
-+snmp-trap 162/udp snmptrap # Traps for SNMP
-+cmip-man 163/tcp # ISO mgmt over IP (CMOT)
-+cmip-man 163/udp
-+cmip-agent 164/tcp
-+cmip-agent 164/udp
-+xdmcp 177/tcp # X Display Mgr. Control Proto
-+xdmcp 177/udp
-+nextstep 178/tcp NeXTStep NextStep # NeXTStep window
-+nextstep 178/udp NeXTStep NextStep # server
-+bgp 179/tcp # Border Gateway Proto.
-+bgp 179/udp
-+prospero 191/tcp # Cliff Neuman's Prospero
-+prospero 191/udp
-+irc 194/tcp # Internet Relay Chat
-+irc 194/udp
-+smux 199/tcp # SNMP Unix Multiplexer
-+smux 199/udp
-+at-rtmp 201/tcp # AppleTalk routing
-+at-rtmp 201/udp
-+at-nbp 202/tcp # AppleTalk name binding
-+at-nbp 202/udp
-+at-echo 204/tcp # AppleTalk echo
-+at-echo 204/udp
-+at-zis 206/tcp # AppleTalk zone information
-+at-zis 206/udp
-+z3950 210/tcp wais # NISO Z39.50 database
-+z3950 210/udp wais
-+ipx 213/tcp # IPX
-+ipx 213/udp
-+imap3 220/tcp # Interactive Mail Access
-+imap3 220/udp # Protocol v3
-+ulistserv 372/tcp # UNIX Listserv
-+ulistserv 372/udp
-+#
-+# UNIX specific services
-+#
-+exec 512/tcp
-+biff 512/udp comsat
-+login 513/tcp
-+who 513/udp whod
-+shell 514/tcp cmd # no passwords used
-+syslog 514/udp
-+printer 515/tcp spooler # line printer spooler
-+talk 517/udp
-+ntalk 518/udp
-+route 520/udp router routed # RIP
-+timed 525/udp timeserver
-+tempo 526/tcp newdate
-+courier 530/tcp rpc
-+conference 531/tcp chat
-+netnews 532/tcp readnews
-+netwall 533/udp # -for emergency broadcasts
-+uucp 540/tcp uucpd # uucp daemon
-+remotefs 556/tcp rfs_server rfs # Brunhoff remote filesystem
-+#
-+webster 765/tcp # Network dictionary
-+webster 765/udp
-+# temporary entry (not officially registered by the Samba Team!)
-+swat 901/tcp # Samba Web Administration Tool
-+#
-+# From ``Assigned Numbers'':
-+#
-+#> The Registered Ports are not controlled by the IANA and on most systems
-+#> can be used by ordinary user processes or programs executed by ordinary
-+#> users.
-+#
-+#> Ports are used in the TCP [45,106] to name the ends of logical
-+#> connections which carry long term conversations. For the purpose of
-+#> providing services to unknown callers, a service contact port is
-+#> defined. This list specifies the port used by the server process as its
-+#> contact port. While the IANA can not control uses of these ports it
-+#> does register or list uses of these ports as a convienence to the
-+#> community.
-+#
-+ingreslock 1524/tcp
-+ingreslock 1524/udp
-+prospero-np 1525/tcp # Prospero non-privileged
-+prospero-np 1525/udp
-+rfe 5002/tcp # Radio Free Ethernet
-+rfe 5002/udp # Actually uses UDP only
-+#
-+#
-+# Kerberos (Project Athena/MIT) services
-+# Note that these are for Kerberos v4, and are unofficial.
-+#
-+klogin 543/tcp # Kerberos `rlogin'
-+kshell 544/tcp krcmd # Kerberos `rsh'
-+kerberos-adm 749/tcp # Kerberos `kadmin' (v5)
-+kerberos4 750/udp kdc # Kerberos (server) udp
-+kerberos4 750/tcp kdc # Kerberos (server) tcp
-+kerberos-master 751/udp # Kerberos admin server udp
-+kerberos-master 751/tcp # Kerberos admin server tcp
-+krbupdate 760/tcp kreg # BSD Kerberos registration
-+kpasswd 761/tcp kpwd # BSD Kerberos `passwd'
-+eklogin 2105/tcp # Kerberos encrypted `rlogin'
-+#
-+# Unofficial but necessary (for NetBSD) services
-+#
-+supfilesrv 871/tcp # SUP server
-+supfiledbg 1127/tcp # SUP debugging
-+#
-+# AppleTalk DDP entries (DDP: Datagram Delivery Protocol)
-+#
-+rtmp 1/ddp # Routing Table Maintenance Protocol
-+nbp 2/ddp # Name Binding Protocol
-+echo 4/ddp # AppleTalk Echo Protocol
-+zip 6/ddp # Zone Information Protocol
-+
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/shadow linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/shadow
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/shadow 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/shadow 2005-12-24 20:29:42.067316648 +0000
-@@ -0,0 +1,11 @@
-+root::10933:0:99999:7:::
-+bin:*:10933:0:99999:7:::
-+daemon:*:10933:0:99999:7:::
-+adm:*:10933:0:99999:7:::
-+lp:*:10933:0:99999:7:::
-+sync:*:10933:0:99999:7:::
-+shutdown:*:10933:0:99999:7:::
-+halt:*:10933:0:99999:7:::
-+uucp:*:10933:0:99999:7:::
-+operator:*:10933:0:99999:7:::
-+nobody:*:10933:0:99999:7:::
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.generic_string linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.generic_string
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.generic_string 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.generic_string 2005-12-24 20:29:42.071316040 +0000
-@@ -0,0 +1 @@
-+# module id=string
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.ieee1394map linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.ieee1394map
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.ieee1394map 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.ieee1394map 2005-12-24 20:29:42.071316040 +0000
-@@ -0,0 +1 @@
-+# ieee1394 module match_flags vendor_id model_id specifier_id version
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.isapnpmap linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.isapnpmap
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.isapnpmap 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.isapnpmap 2005-12-24 20:29:42.079314824 +0000
-@@ -0,0 +1 @@
-+# isapnp module cardvendor carddevice driver_data vendor function ...
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.parportmap linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.parportmap
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.parportmap 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.parportmap 2005-12-24 20:29:42.079314824 +0000
-@@ -0,0 +1 @@
-+# module pattern
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.pcimap linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.pcimap
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.pcimap 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.pcimap 2005-12-24 20:29:42.080314672 +0000
-@@ -0,0 +1 @@
-+# pci module vendor device subvendor subdevice class class_mask driver_data
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.pnpbiosmap linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.pnpbiosmap
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.pnpbiosmap 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.pnpbiosmap 2005-12-24 20:29:42.080314672 +0000
-@@ -0,0 +1 @@
-+# module id
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.usbmap linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.usbmap
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.usbmap 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.usbmap 2005-12-24 20:29:42.080314672 +0000
-@@ -0,0 +1 @@
-+# usb module match_flags idVendor idProduct bcdDevice_lo bcdDevice_hi bDeviceClass bDeviceSubClass bDeviceProtocol bInterfaceClass bInterfaceSubClass bInterfaceProtocol driver_info
-Binary files linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/sbin/iwconfig and linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/sbin/iwconfig differ
-Binary files linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/sbin/iwpriv and linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/sbin/iwpriv differ
-diff -urN linux-2.4.32/arch/mips/ar531x/README linux-2.4.32.new/arch/mips/ar531x/README
---- linux-2.4.32/arch/mips/ar531x/README 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/README 2005-12-24 20:29:42.101311480 +0000
-@@ -0,0 +1,68 @@
-+Basic information for the AR531X Board Support Package
-+
-+This directory contains the "LBSP" -- Linux Board Support Package --
-+for Linux on the Atheros AR531X Wireless System-On-a-Chip. It is intended
-+primarily as a building block for wireless products. At this time, the
-+AR531X Linux BSP is experimental code, and is actively UNDER CONSTRUCTION.
-+
-+Some components that are supported by this LBSP along with a standard 2.4
-+Linux MIPS kernel include
-+ R4Kc CPU
-+ instruction and data caches
-+ SDRAM
-+ flash (Macronix, AMD, STS, etc.)
-+ 16550 serial port
-+ ethernet MACs
-+ ethernet PHY or PHY Switch (RealTek, Kendin, Marvell)
-+ General-Purpose I/O pins
-+ kernel debugging with kgdb
-+
-+This LBSP code does NOT include drivers for the wireless components of the
-+chip/boards! Drivers for those components may be distributed separately.
-+In particular, the MADWiFi project under SourceForge supports (not yet!)
-+wireless functions on the AR531X chipset. See
-+ http://www.sourceforge.net/projects/madwifi
-+
-+Files included in this BSP:
-+ae531xlnx.c - Linux-specific portions of the ethernet driver
-+ae531xmac.c - OS-independent AR531X ethernet MAC code
-+ae531xmac.h - OS-independent AR531X ethernet MAC software definitions
-+ae531xreg.h - OS-independent AR531X ethernet MAC hardware definitions
-+ar531x.h - OS-independent AR531X system hardware definitions
-+ar531xlnx.h - Linux-specific AR531X system definitions and externs
-+defconfig-ar531x - Default Linux configuration file
-+intr_recv.S - Linux interrupt "glue" code
-+ar531xirq.c - Linux Interrupt Request management
-+Makefile - Linux makefile
-+mvPhy.c - OS-independent ethernet PHY code for Marvell Switch
-+mvPhy.h - OS-independent ethernet PHY definitions for Marvell Switch
-+ar531xprom.c - Linux prom "glue" code
-+ar531xsetup.c - Linux startup code
-+ar531xdbg_io.c - Support for kgdb-based debugging and for EARLY_PRINTK_HACK
-+ar531xproc.c - Pseudo-device driver for /proc/ar531x device
-+ar531xgpio.c - Support for General Purpose I/O pins
-+ar531xwmacsl.c - Wireless MAC Support Layer
-+
-+Additional files, distributed with the BSP:
-+README - This file
-+README.BUILD - Instructions for building a linux kernel from source
-+README.EXECUTE - Instructions for testing your linux kernel
-+README.RAMDISK - Instructions for building a root ramdisk image
-+
-+ramdisk.gz - A binary ramdisk image, suitable for use with AR531X.
-+DIFFS - Directory that contains "patch" files (See README.BUILD)
-+
-+
-+There are several ways to boot a vmlinux image on an AR531X board:
-+ -You can boot in over ethernet from the vxWorks bootrom, which is preloaded
-+ on all Atheros boards
-+ -You can use an ICE (e.g. VisionICE) to load the vmlinux image. You will
-+ need appropriate register initialization (e.g. AP30.ini file)
-+ -You can use the eCos RedBoot bootrom loader. This is a full-featured
-+ bootrom which as been ported to AR531x. It can boot vmlinux over ethernet
-+ or from flash. Source code is available from Atheros.
-+
-+Please send comments, corrections, complaints, criticisms, suggestions,
-+enhancements, requests, or any other reasonable communications regarding
-+this effort, to "linux@atheros.com". Your email will be received by a
-+couple of engineers, and redirected as appropriate.
-diff -urN linux-2.4.32/arch/mips/ar531x/README.BUILD linux-2.4.32.new/arch/mips/ar531x/README.BUILD
---- linux-2.4.32/arch/mips/ar531x/README.BUILD 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/README.BUILD 2005-12-24 20:29:42.101311480 +0000
-@@ -0,0 +1,47 @@
-+ How to BUILD a linux kernel for an AR531X system
-+
-+It is expected that you will build Linux on an existing Linux system, which
-+has all of the standard Linux tools.
-+
-+01) Obtain a MIPS BigEndian ELF gcc-compatible toolchain. For example,
-+ if you're cross-compiling on a x86 Linux system, you could use:
-+ ftp://ftp.mips.com/pub/tools/software/sde-for-linux/sdelinux-5.01-4eb.i386.rpm
-+
-+02) Obtain the latest working MIPS Linux kernel
-+ cvs -d :pserver:cvs@ftp.linux-mips.org:/home/cvs login (password "cvs")
-+ cvs -d :pserver:cvs@ftp.linux-mips.org:/home/cvs co -r linux_2_4 linux
-+
-+ Now "cd linux". The remainder of these instructions assume
-+ that you are in the linux directory.
-+
-+03) Place the contents of this directory at arch/mips/ar531x.
-+
-+04) Use the patch command to patch generic linux files according
-+ to the DIFFS directory
-+ for i in arch/mips/ar531x/DIFFS/*.diff
-+ do
-+ patch -p1 < $i
-+ done
-+ NOTE: This version of the AR531X Linux BSP was tested with
-+ MIPS Linux 2.4.22 as of 11/14/03. If you use a different
-+ (e.g. more recent) version of Linux source, you may need to
-+ resolve some minor patch and compilation issues.
-+
-+05) Set up a RAMDISK image.
-+ See the instructions in README.RAMDISK.
-+
-+06) Set up a linux configuration using ar531x/defconfig-ar531x.
-+ cp arch/mips/ar531x/defconfig-ar531x .config
-+ make oldconfig (answer all questions that are asked)
-+ NOTE: For development/debug purposes, you may want to
-+ enable CONFIG_RUNTIME_DEBUG and CONFIG_KGDB.
-+
-+07) Make dependencies.
-+ make dep
-+
-+08) Build the linux kernel
-+ make
-+
-+09) The linux image you just built is in vmlinux.
-+ See instructions in README.EXECUTE to run your vmlinux
-+ image on an AP531X-based board.
-diff -urN linux-2.4.32/arch/mips/ar531x/README.EXECUTE linux-2.4.32.new/arch/mips/ar531x/README.EXECUTE
---- linux-2.4.32/arch/mips/ar531x/README.EXECUTE 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/README.EXECUTE 2005-12-24 20:29:42.101311480 +0000
-@@ -0,0 +1,23 @@
-+ How to EXECUTE a linux image on an AR531X system
-+
-+There are currently three ways to run you vmlinux image:
-+ 1) Load it using the vxWorks bootrom that is supplied with the board.
-+ You can load it over ethernet or from the TFFS file system, if you
-+ have sufficient flash to store the image.
-+ 2) Load it using an ICE (e.g. VisionICE).
-+ 3) Use a bootrom loader, such as eCos RedBoot.
-+
-+After you have booted linux:
-+ By default, the root filesystem on ramdisk is read-only.
-+ To make it writable, use "mount -o remount w /".
-+
-+ The user-level commands are slightly non-standard, as they
-+ are based on "busybox".
-+
-+ The "wget" command is included. You can use wget to fetch
-+ files from any ftp server. So, for instance, you can fetch
-+ a kernel module and then "insmod" it.
-+
-+Note that the standard source-level kernel debugger, kgdb, works well
-+over the serial line with this port. We use kgdb and the kgdb_demux perl
-+script -- available over the www -- for debugging.
-diff -urN linux-2.4.32/arch/mips/ar531x/README.VERSION linux-2.4.32.new/arch/mips/ar531x/README.VERSION
---- linux-2.4.32/arch/mips/ar531x/README.VERSION 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/arch/mips/ar531x/README.VERSION 2005-12-24 20:29:42.101311480 +0000
-@@ -0,0 +1 @@
-+Source release last modified: 12/16/03
-diff -urN linux-2.4.32/arch/mips/config-shared.in linux-2.4.32.new/arch/mips/config-shared.in
---- linux-2.4.32/arch/mips/config-shared.in 2005-12-24 16:11:21.000000000 +0000
-+++ linux-2.4.32.new/arch/mips/config-shared.in 2005-12-24 21:33:42.804435856 +0000
-@@ -31,6 +31,7 @@
- dep_bool 'Support for Alchemy PB1000 board' CONFIG_MIPS_PB1000 $CONFIG_MIPS32
- dep_bool 'Support for Alchemy PB1100 board' CONFIG_MIPS_PB1100 $CONFIG_MIPS32
- dep_bool 'Support for Alchemy PB1500 board' CONFIG_MIPS_PB1500 $CONFIG_MIPS32
-+dep_bool 'Support for Atheros AR5312/AR2312 WiSoC (EXPERIMENTAL)' CONFIG_AR531X $CONFIG_AR531X $CONFIG_EXPERIMENTAL
- dep_bool 'Support for Alchemy PB1550 board' CONFIG_MIPS_PB1550 $CONFIG_MIPS32
- dep_bool 'Support for Alchemy PB1200 board' CONFIG_MIPS_PB1200 $CONFIG_MIPS32
- dep_bool 'Support for Alchemy Hydrogen3 board' CONFIG_MIPS_HYDROGEN3 $CONFIG_MIPS32
-@@ -196,7 +197,7 @@
- bool ' Support for ZBbus profiling' CONFIG_SIBYTE_TBPROF
-
- if [ "$CONFIG_SIBYTE_SWARM" = "y" -o \
-- "$CONFIG_SIBYTE_LITTLESUR" = "y" -o \
-+O5B "$CONFIG_SIBYTE_LITTLESUR" = "y" -o \
- "$CONFIG_SIBYTE_PTSWARM" = "y" -o \
- "$CONFIG_SIBYTE_CARMEL" = "y" ]; then
- define_bool CONFIG_SIBYTE_GENBUS_IDE y
-@@ -239,6 +240,43 @@
- define_bool CONFIG_NONCOHERENT_IO y
- define_bool CONFIG_PC_KEYB y
- fi
-+if [ "$CONFIG_AR531X" = "y" ]; then
-+ define_bool CONFIG_IRQ_CPU y
-+ define_bool CONFIG_CPU_VR4100 y
-+ define_bool CONFIG_SERIAL y
-+ define_bool CONFIG_NEW_IRQ y
-+ define_bool CONFIG_NEW_TIME_C y
-+ define_bool CONFIG_AR5312
-+ define_bool CONFIG_NONCOHERENT_IO y
-+ bool 'Enable early printk hack' CONFIG_EARLY_PRINTK_HACK
-+ define_bool CONFIG_SCSI n
-+ mainmenu_option next_comment
-+ comment 'Board selection'
-+ choice 'Board type' \
-+ "UNKNOWN CONFIG_APUNKNOWN \
-+ AP30 CONFIG_AP30 \
-+ AP31 CONFIG_AP31 \
-+ AP33 CONFIG_AP33 \
-+ AP38 CONFIG_AP38 \
-+ AP43 CONFIG_AP43 \
-+ AP48 CONFIG_AP48" AP30
-+ if [ "$CONFIG_AP30" = "y" ]; then
-+ define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 2
-+ fi
-+ if [ "$CONFIG_AP33" = "y" ]; then
-+ define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 1
-+ fi
-+ if [ "$CONFIG_AP38" = "y" ]; then
-+ define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 1
-+ fi
-+ if [ "$CONFIG_AP43" = "y" ]; then
-+ define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 1
-+ fi
-+ if [ "$CONFIG_AP48" = "y" ]; then
-+ define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 1
-+ fi
-+ endmenu
-+fi
- if [ "$CONFIG_CASIO_E55" = "y" ]; then
- define_bool CONFIG_IRQ_CPU y
- define_bool CONFIG_NONCOHERENT_IO y
-diff -urN linux-2.4.32/arch/mips/kernel/setup.c linux-2.4.32.new/arch/mips/kernel/setup.c
---- linux-2.4.32/arch/mips/kernel/setup.c 2005-12-24 16:08:53.000000000 +0000
-+++ linux-2.4.32.new/arch/mips/kernel/setup.c 2005-12-24 21:28:51.779678344 +0000
-@@ -494,6 +494,7 @@
- void hp_setup(void);
- void au1x00_setup(void);
- void frame_info_init(void);
-+ void ar531x_setup(void);
-
- frame_info_init();
- #if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE)
-@@ -691,6 +692,12 @@
- pmc_yosemite_setup();
- break;
- #endif
-+
-+#ifdef CONFIG_AR531X
-+ case MACH_GROUP_AR531X:
-+ ar531x_setup();
-+ break;
-+#endif
- default:
- panic("Unsupported architecture");
- }
-diff -urN linux-2.4.32/arch/mips/Makefile linux-2.4.32.new/arch/mips/Makefile
---- linux-2.4.32/arch/mips/Makefile 2005-12-24 16:09:51.000000000 +0000
-+++ linux-2.4.32.new/arch/mips/Makefile 2005-12-24 21:28:51.780678192 +0000
-@@ -725,6 +725,12 @@
- LOADADDR += 0x80020000
- endif
-
-+ifdef CONFIG_AR531X
-+SUBDIRS += arch/mips/ar531x
-+LIBS += arch/mips/ar531x/ar531x.o
-+LOADADDR += 0x80002000
-+endif
-+
- #
- # Choosing incompatible machines durings configuration will result in
- # error messages during linking. Select a default linkscript if
-diff -urN linux-2.4.32/drivers/mtd/chips/cfi_cmdset_0002.c linux-2.4.32.new/drivers/mtd/chips/cfi_cmdset_0002.c
---- linux-2.4.32/drivers/mtd/chips/cfi_cmdset_0002.c 2004-11-17 11:54:21.000000000 +0000
-+++ linux-2.4.32.new/drivers/mtd/chips/cfi_cmdset_0002.c 2005-12-24 21:28:51.795675912 +0000
-@@ -510,7 +510,7 @@
- or tells us why it failed. */
- dq6 = CMD(1<<6);
- dq5 = CMD(1<<5);
-- timeo = jiffies + (HZ/1000); /* setting timeout to 1ms for now */
-+ timeo = jiffies + (HZ/1000) + 1; /* setting timeout to 1ms for now */
-
- oldstatus = cfi_read(map, adr);
- status = cfi_read(map, adr);
-@@ -535,12 +535,14 @@
- if( (status & dq5) == dq5 ) {
- /* When DQ5 raises, we must check once again
- if DQ6 is toggling. If not, the erase has been
-- completed OK. If not, reset chip. */
-+ completed OK. But if so, reset chip. */
- oldstatus = cfi_read(map, adr);
- status = cfi_read(map, adr);
-
- if ( (oldstatus & 0x00FF) == (status & 0x00FF) ) {
-+#if 0
- printk(KERN_WARNING "Warning: DQ5 raised while program operation was in progress, however operation completed OK\n" );
-+#endif
- } else {
- /* DQ5 is active so we can do a reset and stop the erase */
- cfi_write(map, CMD(0xF0), chip->start);
-diff -urN linux-2.4.32/drivers/mtd/chips/jedec_probe.c linux-2.4.32.new/drivers/mtd/chips/jedec_probe.c
---- linux-2.4.32/drivers/mtd/chips/jedec_probe.c 2003-06-13 15:51:34.000000000 +0100
-+++ linux-2.4.32.new/drivers/mtd/chips/jedec_probe.c 2005-12-24 21:28:51.797675608 +0000
-@@ -900,7 +900,16 @@
- NumEraseRegions: 1,
- regions: {ERASEINFO(0x01000,256),
- }
-- }
-+ }, {
-+ mfr_id: MANUFACTURER_SST,
-+ dev_id: SST39LF160,
-+ name: "SST 39LF160",
-+ DevSize: SIZE_2MiB,
-+ CmdSet: P_ID_AMD_STD,
-+ NumEraseRegions: 1,
-+ regions: {ERASEINFO(0x01000,512),
-+ }
-+ }
- };
-
-
-diff -urN linux-2.4.32/drivers/mtd/Config.in linux-2.4.32.new/drivers/mtd/Config.in
---- linux-2.4.32/drivers/mtd/Config.in 2003-06-13 15:51:34.000000000 +0100
-+++ linux-2.4.32.new/drivers/mtd/Config.in 2005-12-24 21:28:51.803674696 +0000
-@@ -14,6 +14,9 @@
- dep_tristate ' MTD partitioning support' CONFIG_MTD_PARTITIONS $CONFIG_MTD
- dep_tristate ' MTD concatenating support' CONFIG_MTD_CONCAT $CONFIG_MTD
- dep_tristate ' RedBoot partition table parsing' CONFIG_MTD_REDBOOT_PARTS $CONFIG_MTD_PARTITIONS
-+ if [ "$CONFIG_MTD_END_RESERVED" != "" ]; then
-+ define_int CONFIG_MTD_END_RESERVED $CONFIG_MTD_END_RESERVED
-+ fi
- dep_tristate ' Command line partition table parsing' CONFIG_MTD_CMDLINE_PARTS $CONFIG_MTD_PARTITIONS
- if [ "$CONFIG_ARM" = "y" ]; then
- dep_tristate ' ARM Firmware Suite partition parsing' CONFIG_MTD_AFS_PARTS $CONFIG_MTD_PARTITIONS
-diff -urN linux-2.4.32/drivers/mtd/maps/physmap.c linux-2.4.32.new/drivers/mtd/maps/physmap.c
---- linux-2.4.32/drivers/mtd/maps/physmap.c 2003-06-13 15:51:34.000000000 +0100
-+++ linux-2.4.32.new/drivers/mtd/maps/physmap.c 2005-12-24 21:28:51.811673480 +0000
-@@ -80,12 +80,18 @@
- };
-
- #ifdef CONFIG_MTD_PARTITIONS
--#ifdef CONFIG_MTD_CMDLINE_PARTS
-+#if defined(CONFIG_MTD_CMDLINE_PARTS) || defined(CONFIG_MTD_REDBOOT_PARTS)
- static struct mtd_partition *mtd_parts = 0;
- static int mtd_parts_nb = 0;
- #else
- static struct mtd_partition physmap_partitions[] = {
- /* Put your own partition definitions here */
-+ {
-+ name: "rootfs",
-+ size: 0x000e0000,
-+ offset: 0x000f0000,
-+ /* Allow file system to be mounted for writing */
-+ }
- #if 0
- {
- name: "bootROM",
-@@ -138,6 +144,22 @@
-
- add_mtd_device(mymtd);
- #ifdef CONFIG_MTD_PARTITIONS
-+#ifdef CONFIG_MTD_REDBOOT_PARTS
-+ {
-+ extern int parse_redboot_partitions(struct mtd_info *master,
-+ struct mtd_partition **pparts);
-+
-+ struct mtd_partition *rb_parts = 0;
-+ int rb_parts_nb = 0;
-+
-+ rb_parts_nb = parse_redboot_partitions(mymtd, &rb_parts);
-+ if (rb_parts_nb > 0) {
-+ printk(KERN_NOTICE
-+ "Using redboot flash partitioning");
-+ add_mtd_partitions (mymtd, rb_parts, rb_parts_nb);
-+ }
-+ }
-+#endif
- #ifdef CONFIG_MTD_CMDLINE_PARTS
- mtd_parts_nb = parse_cmdline_partitions(mymtd, &mtd_parts,
- "phys");
-@@ -147,7 +169,8 @@
- "Using command line partition definition\n");
- add_mtd_partitions (mymtd, mtd_parts, mtd_parts_nb);
- }
--#else
-+#endif
-+#if !defined(CONFIG_MTD_CMDLINE_PARTS) && !defined(CONFIG_MTD_REDBOOT_PARTS)
- if (NUM_PARTITIONS != 0)
- {
- printk(KERN_NOTICE
-diff -urN linux-2.4.32/drivers/mtd/redboot.c linux-2.4.32.new/drivers/mtd/redboot.c
---- linux-2.4.32/drivers/mtd/redboot.c 2001-11-09 22:01:22.000000000 +0000
-+++ linux-2.4.32.new/drivers/mtd/redboot.c 2005-12-24 21:28:51.821671960 +0000
-@@ -51,8 +51,14 @@
- return -ENOMEM;
-
- /* Read the start of the last erase block */
-- ret = master->read(master, master->size - master->erasesize,
-+ {
-+ u_int32_t part_table_start = master->size - master->erasesize;
-+#if defined(CONFIG_MTD_END_RESERVED)
-+ part_table_start -= CONFIG_MTD_END_RESERVED;
-+#endif
-+ ret = master->read(master, part_table_start,
- PAGE_SIZE, &retlen, (void *)buf);
-+ }
-
- if (ret)
- goto out;
-diff -urN linux-2.4.32/drivers/net/Config.in linux-2.4.32.new/drivers/net/Config.in
---- linux-2.4.32/drivers/net/Config.in 2005-12-24 16:16:53.000000000 +0000
-+++ linux-2.4.32.new/drivers/net/Config.in 2005-12-24 21:28:51.856666640 +0000
-@@ -30,6 +30,8 @@
- comment 'Ethernet (10 or 100Mbit)'
- bool 'Ethernet (10 or 100Mbit)' CONFIG_NET_ETHERNET
- if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
-+ define_bool CONFIG_VENETDEV n
-+ define_bool CONFIG_MARVELL_ENET_PHY y
- if [ "$CONFIG_ARM" = "y" ]; then
- dep_bool ' ARM EBSA110 AM79C961A support' CONFIG_ARM_AM79C961A $CONFIG_ARCH_EBSA110
- tristate ' Cirrus Logic CS8900A support' CONFIG_ARM_CIRRUS
-diff -urN linux-2.4.32/drivers/net/wireless/Config.in linux-2.4.32.new/drivers/net/wireless/Config.in
---- linux-2.4.32/drivers/net/wireless/Config.in 2004-11-17 11:54:21.000000000 +0000
-+++ linux-2.4.32.new/drivers/net/wireless/Config.in 2005-12-24 21:28:51.898660256 +0000
-@@ -38,7 +38,8 @@
-
- # yes, this works even when no drivers are selected
- if [ "$CONFIG_ISA" = "y" -o "$CONFIG_PCI" = "y" -o \
-- "$CONFIG_ALL_PPC" = "y" -o "$CONFIG_PCMCIA" != "n" ]; then
-+ "$CONFIG_ALL_PPC" = "y" -o "$CONFIG_PCMCIA" != "n" -o \
-+ "$CONFIG_NET_WIRELESS" = "y" ]; then
- define_bool CONFIG_NET_WIRELESS y
- else
- define_bool CONFIG_NET_WIRELESS n
-diff -urN linux-2.4.32/include/asm-mips/atheros/ar531xbsp.h linux-2.4.32.new/include/asm-mips/atheros/ar531xbsp.h
---- linux-2.4.32/include/asm-mips/atheros/ar531xbsp.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/include/asm-mips/atheros/ar531xbsp.h 2005-12-24 20:29:06.898663096 +0000
-@@ -0,0 +1,16 @@
-+#ifndef __ASM_ATHEROS_BSP_SUPPORT_H
-+#define __ASM_ATHEROS_BSP_SUPPORT_H
-+/*
-+ * These are definitions and functions provided by the bsp to support the
-+ * AR5312 WiSoC running LSDK. For different BSP implementations, different
-+ * BSP functions will be needed.
-+ */
-+
-+extern unsigned int ar531x_sys_frequency(void);
-+
-+#ifdef CONFIG_KGDB
-+extern void kgdbInit(void);
-+extern int kgdbEnabled(void);
-+#endif
-+
-+#endif /* __ASM_ATHEROS_BSP_SUPPORT_H */
-diff -urN linux-2.4.32/include/asm-mips/bootinfo.h linux-2.4.32.new/include/asm-mips/bootinfo.h
---- linux-2.4.32/include/asm-mips/bootinfo.h 2005-12-24 16:08:53.000000000 +0000
-+++ linux-2.4.32.new/include/asm-mips/bootinfo.h 2005-12-24 21:28:51.899660104 +0000
-@@ -37,6 +37,7 @@
- #define MACH_GROUP_HP_LJ 20 /* Hewlett Packard LaserJet */
- #define MACH_GROUP_LASAT 21
- #define MACH_GROUP_TITAN 22 /* PMC-Sierra Titan */
-+#define MACH_GROUP_AR531X 23 /* Atheros AR531X */
-
- /*
- * Valid machtype values for group unknown (low order halfword of mips_machtype)
-@@ -201,6 +202,17 @@
- */
- #define MACH_TITAN_YOSEMITE 1 /* PMC-Sierra Yosemite */
-
-+/*
-+ * Valid machtype for group MACH_GROUP_AR5312
-+ */
-+#define MACH_ATHEROS_UNUSED 0
-+#define MACH_ATHEROS_AP30 1 /* AP30 */
-+#define MACH_ATHEROS_AP33 2 /* AP33 */
-+#define MACH_ATHEROS_AP38 3 /* AP38 */
-+#define MACH_ATHEROS_AP43 4 /* AP43 */
-+#define MACH_ATHEROS_AP48 5 /* AP48 */
-+#define MACH_ATHEROS_PB32 6 /* PB32 */
-+
- #define CL_SIZE (256)
-
- const char *get_system_type(void);
-diff -urN linux-2.4.32/include/asm-mips/serial.h linux-2.4.32.new/include/asm-mips/serial.h
---- linux-2.4.32/include/asm-mips/serial.h 2005-01-19 14:10:12.000000000 +0000
-+++ linux-2.4.32.new/include/asm-mips/serial.h 2005-12-24 21:28:51.901659800 +0000
-@@ -467,6 +467,11 @@
- #define DDB5477_SERIAL_PORT_DEFNS
- #endif
-
-+#if defined(CONFIG_AR531X)
-+#undef RS_TABLE_SIZE
-+#define RS_TABLE_SIZE 1
-+#endif
-+
- #define SERIAL_PORT_DFNS \
- ATLAS_SERIAL_PORT_DEFNS \
- AU1000_SERIAL_PORT_DEFNS \
-diff -urN linux-2.4.32/kernel/printk.c linux-2.4.32.new/kernel/printk.c
---- linux-2.4.32/kernel/printk.c 2004-11-17 11:54:22.000000000 +0000
-+++ linux-2.4.32.new/kernel/printk.c 2005-12-24 21:28:51.929655544 +0000
-@@ -384,6 +384,18 @@
- _call_console_drivers(start_print, end, msg_level);
- }
-
-+#if CONFIG_EARLY_PRINTK_HACK
-+void putDebugChar(char byte);
-+static void emit_log_char(char c)
-+{
-+ if (c == '\n') {
-+ putDebugChar('\r');
-+ putDebugChar('\n');
-+ } else {
-+ putDebugChar(c);
-+ }
-+}
-+#else
- static void emit_log_char(char c)
- {
- LOG_BUF(log_end) = c;
-@@ -395,6 +407,7 @@
- if (logged_chars < LOG_BUF_LEN)
- logged_chars++;
- }
-+#endif
-
- /*
- * This is printk. It can be called from any context. We want it to work.
-@@ -700,3 +713,4 @@
- tty->driver.write(tty, 0, msg, strlen(msg));
- return;
- }
-+
+diff -urN linux-mips/arch/mips/ar531x/ar531xdbg_io.c mips-linux-2.4.25/arch/mips/ar531x/ar531xdbg_io.c
+--- linux-mips/arch/mips/ar531x/ar531xdbg_io.c 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/ar531xdbg_io.c 2005-12-30 17:26:30.606883840 +0000
+@@ -0,0 +1,234 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright MontaVista Software Inc
++ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++ */
++
++/*
++ * Basic support for polled character input/output
++ * using the AR531X's serial port.
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/serial.h>
++#include <linux/types.h>
++#include <linux/string.h>
++
++#include <asm/reboot.h>
++#include <asm/io.h>
++#include <asm/time.h>
++#include <asm/pgtable.h>
++#include <asm/processor.h>
++#include <asm/reboot.h>
++#include <asm/system.h>
++#include <asm/serial.h>
++#include <asm/gdb-stub.h>
++
++#include "ar531xlnx.h"
++
++#if CONFIG_EARLY_PRINTK_HACK || CONFIG_KGDB
++/* base addr of uart and clock timing */
++#if CONFIG_AR5315
++#define BASE AR5315_UART0
++#else
++#define BASE AR531X_UART0
++#endif
++
++/* distance in bytes between two serial registers */
++#define REG_OFFSET 4
++
++/*
++ * 0 - we need to do serial init
++ * 1 - skip serial init
++ */
++static int serialPortInitialized = 0;
++
++/*
++ * * the default baud rate *if* we do serial init
++ * */
++#define BAUD_DEFAULT UART16550_BAUD_9600
++
++/* === END OF CONFIG === */
++
++#define UART16550_BAUD_2400 2400
++#define UART16550_BAUD_4800 4800
++#define UART16550_BAUD_9600 9600
++#define UART16550_BAUD_19200 19200
++#define UART16550_BAUD_38400 38400
++#define UART16550_BAUD_57600 57600
++#define UART16550_BAUD_115200 115200
++
++#define UART16550_PARITY_NONE 0
++#define UART16550_PARITY_ODD 0x08
++#define UART16550_PARITY_EVEN 0x18
++#define UART16550_PARITY_MARK 0x28
++#define UART16550_PARITY_SPACE 0x38
++
++#define UART16550_DATA_5BIT 0x0
++#define UART16550_DATA_6BIT 0x1
++#define UART16550_DATA_7BIT 0x2
++#define UART16550_DATA_8BIT 0x3
++
++#define UART16550_STOP_1BIT 0x0
++#define UART16550_STOP_2BIT 0x4
++
++/* register offset */
++#define OFS_RCV_BUFFER (0*REG_OFFSET)
++#define OFS_TRANS_HOLD (0*REG_OFFSET)
++#define OFS_SEND_BUFFER (0*REG_OFFSET)
++#define OFS_INTR_ENABLE (1*REG_OFFSET)
++#define OFS_INTR_ID (2*REG_OFFSET)
++#define OFS_DATA_FORMAT (3*REG_OFFSET)
++#define OFS_LINE_CONTROL (3*REG_OFFSET)
++#define OFS_MODEM_CONTROL (4*REG_OFFSET)
++#define OFS_RS232_OUTPUT (4*REG_OFFSET)
++#define OFS_LINE_STATUS (5*REG_OFFSET)
++#define OFS_MODEM_STATUS (6*REG_OFFSET)
++#define OFS_RS232_INPUT (6*REG_OFFSET)
++#define OFS_SCRATCH_PAD (7*REG_OFFSET)
++
++#define OFS_DIVISOR_LSB (0*REG_OFFSET)
++#define OFS_DIVISOR_MSB (1*REG_OFFSET)
++
++
++/* memory-mapped read/write of the port */
++#define UART16550_READ(y) (*((volatile u8*)(BASE + y)))
++#define UART16550_WRITE(y, z) ((*((volatile u8*)(BASE + y))) = z)
++
++void
++debugPortInit(u32 baud, u8 data, u8 parity, u8 stop)
++{
++ /* Pull UART out of reset */
++#if CONFIG_AR5315
++ sysRegWrite(AR5315_RESET,
++ sysRegRead(AR5315_RESET) & ~(RESET_UART0));
++#else
++ sysRegWrite(AR531X_RESET,
++ sysRegRead(AR531X_RESET) & ~(AR531X_RESET_UART0));
++#endif
++
++ /* disable interrupts */
++ UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
++ UART16550_WRITE(OFS_INTR_ENABLE, 0);
++
++ /* set up buad rate */
++ {
++ u32 divisor;
++#if CONFIG_AR5315
++ u32 uart_clock_rate = ar531x_apb_frequency();
++#else
++ u32 uart_clock_rate = ar531x_cpu_frequency() / 4;
++#endif
++ u32 base_baud = uart_clock_rate / 16;
++
++ /* set DIAB bit */
++ UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
++
++ /* set divisor */
++ divisor = base_baud / baud;
++ UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
++ UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00)>>8);
++
++ /* clear DIAB bit */
++ UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
++ }
++
++ /* set data format */
++ UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
++}
++
++u8
++getDebugChar(void)
++{
++ if (!serialPortInitialized) {
++ serialPortInitialized = 1;
++ debugPortInit(BAUD_DEFAULT,
++ UART16550_DATA_8BIT,
++ UART16550_PARITY_NONE, UART16550_STOP_1BIT);
++ }
++
++ while((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
++ return UART16550_READ(OFS_RCV_BUFFER);
++}
++
++#if CONFIG_KGDB
++/*
++ * Peek at the most recently received character.
++ * Don't wait for a new character to be received.
++ */
++u8
++peekDebugChar(void)
++{
++ return UART16550_READ(OFS_RCV_BUFFER);
++}
++
++static int kgdbInitialized = 0;
++
++void
++kgdbInit(void)
++{
++#if CONFIG_AR5315
++ sysRegWrite(AR5315_WDC, WDC_IGNORE_EXPIRATION);
++#else
++ sysRegWrite(AR531X_WD_CTRL, AR531X_WD_CTRL_IGNORE_EXPIRATION);
++#endif
++
++ if (!kgdbInitialized) {
++ printk("Setting debug traps - please connect the remote debugger.\n");
++ set_debug_traps();
++ kgdbInitialized = 1;
++ }
++ breakpoint();
++}
++
++int
++kgdbEnabled(void)
++{
++ return kgdbInitialized;
++}
++
++#define DEBUG_CHAR '\001';
++
++int
++kgdbInterrupt(void)
++{
++ if (!kgdbInitialized) {
++ return 0;
++ }
++
++ /*
++ * Try to avoid swallowing too much input: Only consume
++ * a character if nothing new has arrived. Yes, there's
++ * still a small hole here, and we may lose an input
++ * character now and then.
++ */
++ if (UART16550_READ(OFS_LINE_STATUS) & 1) {
++ return 0;
++ } else {
++ return UART16550_READ(OFS_RCV_BUFFER) == DEBUG_CHAR;
++ }
++}
++#endif
++
++
++void
++putDebugChar(char byte)
++{
++ if (!serialPortInitialized) {
++ serialPortInitialized = 1;
++ debugPortInit(BAUD_DEFAULT,
++ UART16550_DATA_8BIT,
++ UART16550_PARITY_NONE, UART16550_STOP_1BIT);
++ }
++
++ while ((UART16550_READ(OFS_LINE_STATUS) &0x20) == 0);
++ UART16550_WRITE(OFS_SEND_BUFFER, byte);
++ }
++#endif /* CONFIG_EARLY_PRINTK_HACK || CONFIG_KGDB */
+diff -urN linux-mips/arch/mips/ar531x/ar531xgpio.c mips-linux-2.4.25/arch/mips/ar531x/ar531xgpio.c
+--- linux-mips/arch/mips/ar531x/ar531xgpio.c 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/ar531xgpio.c 2005-12-30 17:26:30.606883840 +0000
+@@ -0,0 +1,147 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++ */
++
++/*
++ * Support for GPIO -- General Purpose Input/Output Pins
++ */
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/signal.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++
++#include "ar531xlnx.h"
++
++/* GPIO Interrupt Support */
++
++/* Turn on the specified AR531X_GPIO_IRQ interrupt */
++static unsigned int
++ar531x_gpio_intr_startup(unsigned int irq)
++{
++ ar531x_gpio_intr_enable(irq);
++ return 0;
++}
++
++/* Turn off the specified AR531X_GPIO_IRQ interrupt */
++static void
++ar531x_gpio_intr_shutdown(unsigned int irq)
++{
++ ar531x_gpio_intr_disable(irq);
++}
++
++u32 gpioIntMask = 0;
++
++/* Enable the specified AR531X_GPIO_IRQ interrupt */
++void
++ar531x_gpio_intr_enable(unsigned int irq)
++{
++ u32 reg;
++ int gpio;
++
++#ifndef CONFIG_AR5315
++ gpio = irq - AR531X_GPIO_IRQ_BASE;
++ gpioIntMask |= gpio;
++
++ reg = sysRegRead(AR531X_GPIO_CR);
++ reg &= ~(GPIO_CR_M(gpio) | GPIO_CR_UART(gpio) | GPIO_CR_INT(gpio));
++ reg |= GPIO_CR_I(gpio);
++ reg |= GPIO_CR_INT(gpio);
++
++ sysRegWrite(AR531X_GPIO_CR, reg);
++ (void)sysRegRead(AR531X_GPIO_CR); /* flush to hardware */
++#endif
++}
++
++/* Disable the specified AR531X_GPIO_IRQ interrupt */
++void
++ar531x_gpio_intr_disable(unsigned int irq)
++{
++ u32 reg;
++ int gpio;
++
++#ifndef CONFIG_AR5315
++ gpio = irq - AR531X_GPIO_IRQ_BASE;
++ reg = sysRegRead(AR531X_GPIO_CR);
++ reg &= ~(GPIO_CR_M(gpio) | GPIO_CR_UART(gpio) | GPIO_CR_INT(gpio));
++ reg |= GPIO_CR_I(gpio);
++ /* No GPIO_CR_INT bit */
++
++ sysRegWrite(AR531X_GPIO_CR, reg);
++ (void)sysRegRead(AR531X_GPIO_CR); /* flush to hardware */
++
++ gpioIntMask &= ~gpio;
++#endif
++}
++
++static void
++ar531x_gpio_intr_ack(unsigned int irq)
++{
++ ar531x_gpio_intr_disable(irq);
++}
++
++static void
++ar531x_gpio_intr_end(unsigned int irq)
++{
++ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
++ ar531x_gpio_intr_enable(irq);
++}
++
++static void
++ar531x_gpio_intr_set_affinity(unsigned int irq, unsigned long mask)
++{
++ /* Only 1 CPU; ignore affinity request */
++}
++
++int ar531x_gpio_irq_base;
++
++struct hw_interrupt_type ar531x_gpio_intr_controller = {
++ "AR531X GPIO",
++ ar531x_gpio_intr_startup,
++ ar531x_gpio_intr_shutdown,
++ ar531x_gpio_intr_enable,
++ ar531x_gpio_intr_disable,
++ ar531x_gpio_intr_ack,
++ ar531x_gpio_intr_end,
++ ar531x_gpio_intr_set_affinity,
++};
++
++void
++ar531x_gpio_intr_init(int irq_base)
++{
++ int i;
++
++ for (i = irq_base; i < irq_base + AR531X_GPIO_IRQ_COUNT; i++) {
++ irq_desc[i].status = IRQ_DISABLED;
++ irq_desc[i].action = NULL;
++ irq_desc[i].depth = 1;
++ irq_desc[i].handler = &ar531x_gpio_intr_controller;
++ }
++
++ ar531x_gpio_irq_base = irq_base;
++}
++
++/* ARGSUSED */
++void
++spurious_gpio_handler(int cpl, void *dev_id, struct pt_regs *regs)
++{
++ u32 gpioDataIn;
++#if CONFIG_AR5315
++ gpioDataIn = sysRegRead(AR5315_GPIO_DI) & gpioIntMask;
++#else
++ gpioDataIn = sysRegRead(AR531X_GPIO_DI) & gpioIntMask;
++#endif
++
++ printk("spurious_gpio_handler: 0x%x di=0x%8.8x gpioIntMask=0x%8.8x\n",
++ cpl, gpioDataIn, gpioIntMask);
++}
++
++struct irqaction spurious_gpio =
++ {spurious_gpio_handler, SA_INTERRUPT, 0, "spurious_gpio",
++ NULL, NULL};
++
+diff -urN linux-mips/arch/mips/ar531x/ar531x.h mips-linux-2.4.25/arch/mips/ar531x/ar531x.h
+--- linux-mips/arch/mips/ar531x/ar531x.h 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/ar531x.h 2005-12-30 17:26:30.605883992 +0000
+@@ -0,0 +1,1018 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++ */
++
++#ifndef AR531X_H
++#define AR531X_H 1
++
++#ifndef CONFIG_AR5315
++
++#include <asm/addrspace.h>
++
++/* Address Map */
++#define AR531X_WLAN0 0x18000000
++#define AR531X_WLAN1 0x18500000
++#define AR531X_ENET0 0x18100000
++#define AR531X_ENET1 0x18200000
++#define AR531X_SDRAMCTL 0x18300000
++#define AR531X_FLASHCTL 0x18400000
++#define AR531X_APBBASE 0x1c000000
++#define AR531X_FLASH 0x1e000000
++#define AR531X_UART0 0xbc000003 /* UART MMR */
++
++/*
++ * AR531X_NUM_ENET_MAC defines the number of ethernet MACs that
++ * should be considered available. The AR5312 supports 2 enet MACS,
++ * even though many reference boards only actually use 1 of them
++ * (i.e. Only MAC 0 is actually connected to an enet PHY or PHY switch.
++ * The AR2312 supports 1 enet MAC.
++ */
++#define AR531X_NUM_ENET_MAC 2
++
++/*
++ * Need these defines to determine true number of ethernet MACs
++ */
++#define AR5212_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */
++#define AR5212_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */
++#define AR5212_AR2313_REV8 0x0058 /* AR2313 WMAC (AP43-030) */
++#define AR531X_RADIO_MASK_OFF 0xc8
++#define AR531X_RADIO0_MASK 0x0003
++#define AR531X_RADIO1_MASK 0x000c
++#define AR531X_RADIO1_S 2
++
++/*
++ * AR531X_NUM_WMAC defines the number of Wireless MACs that\
++ * should be considered available.
++ */
++#define AR531X_NUM_WMAC 2
++
++/* Reset/Timer Block Address Map */
++#define AR531X_RESETTMR (AR531X_APBBASE + 0x3000)
++#define AR531X_TIMER (AR531X_RESETTMR + 0x0000) /* countdown timer */
++#define AR531X_WD_CTRL (AR531X_RESETTMR + 0x0008) /* watchdog cntrl */
++#define AR531X_WD_TIMER (AR531X_RESETTMR + 0x000c) /* watchdog timer */
++#define AR531X_ISR (AR531X_RESETTMR + 0x0010) /* Intr Status Reg */
++#define AR531X_IMR (AR531X_RESETTMR + 0x0014) /* Intr Mask Reg */
++#define AR531X_RESET (AR531X_RESETTMR + 0x0020)
++#define AR5312_CLOCKCTL1 (AR531X_RESETTMR + 0x0064)
++#define AR5312_SCRATCH (AR531X_RESETTMR + 0x006c)
++#define AR531X_PROCADDR (AR531X_RESETTMR + 0x0070)
++#define AR531X_PROC1 (AR531X_RESETTMR + 0x0074)
++#define AR531X_DMAADDR (AR531X_RESETTMR + 0x0078)
++#define AR531X_DMA1 (AR531X_RESETTMR + 0x007c)
++#define AR531X_ENABLE (AR531X_RESETTMR + 0x0080) /* interface enb */
++#define AR531X_REV (AR531X_RESETTMR + 0x0090) /* revision */
++
++/* AR531X_WD_CTRL register bit field definitions */
++#define AR531X_WD_CTRL_IGNORE_EXPIRATION 0x0000
++#define AR531X_WD_CTRL_NMI 0x0001
++#define AR531X_WD_CTRL_RESET 0x0002
++
++/* AR531X_ISR register bit field definitions */
++#define AR531X_ISR_NONE 0x0000
++#define AR531X_ISR_TIMER 0x0001
++#define AR531X_ISR_AHBPROC 0x0002
++#define AR531X_ISR_AHBDMA 0x0004
++#define AR531X_ISR_GPIO 0x0008
++#define AR531X_ISR_UART0 0x0010
++#define AR531X_ISR_UART0DMA 0x0020
++#define AR531X_ISR_WD 0x0040
++#define AR531X_ISR_LOCAL 0x0080
++
++/* AR531X_RESET register bit field definitions */
++#define AR531X_RESET_SYSTEM 0x00000001 /* cold reset full system */
++#define AR531X_RESET_PROC 0x00000002 /* cold reset MIPS core */
++#define AR531X_RESET_WLAN0 0x00000004 /* cold reset WLAN MAC and BB */
++#define AR531X_RESET_EPHY0 0x00000008 /* cold reset ENET0 phy */
++#define AR531X_RESET_EPHY1 0x00000010 /* cold reset ENET1 phy */
++#define AR531X_RESET_ENET0 0x00000020 /* cold reset ENET0 mac */
++#define AR531X_RESET_ENET1 0x00000040 /* cold reset ENET1 mac */
++#define AR531X_RESET_UART0 0x00000100 /* cold reset UART0 (high speed) */
++#define AR531X_RESET_WLAN1 0x00000200 /* cold reset WLAN MAC/BB */
++#define AR531X_RESET_APB 0x00000400 /* cold reset APB (ar5312) */
++#define AR531X_RESET_WARM_PROC 0x00001000 /* warm reset MIPS core */
++#define AR531X_RESET_WARM_WLAN0_MAC 0x00002000 /* warm reset WLAN0 MAC */
++#define AR531X_RESET_WARM_WLAN0_BB 0x00004000 /* warm reset WLAN0 BaseBand */
++#define AR531X_RESET_NMI 0x00010000 /* send an NMI to the processor */
++#define AR531X_RESET_WARM_WLAN1_MAC 0x00020000 /* warm reset WLAN1 mac */
++#define AR531X_RESET_WARM_WLAN1_BB 0x00040000 /* warm reset WLAN1 baseband */
++#define AR531X_RESET_LOCAL_BUS 0x00080000 /* reset local bus */
++#define AR531X_RESET_WDOG 0x00100000 /* last reset was a watchdog */
++
++#define AR531X_RESET_WMAC0_BITS \
++ AR531X_RESET_WLAN0 |\
++ AR531X_RESET_WARM_WLAN0_MAC |\
++ AR531X_RESET_WARM_WLAN0_BB
++
++#define AR531X_RESERT_WMAC1_BITS \
++ AR531X_RESET_WLAN1 |\
++ AR531X_RESET_WARM_WLAN1_MAC |\
++ AR531X_RESET_WARM_WLAN1_BB
++
++/* AR5312_CLOCKCTL1 register bit field definitions */
++#define AR5312_CLOCKCTL1_PREDIVIDE_MASK 0x00000030
++#define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT 4
++#define AR5312_CLOCKCTL1_MULTIPLIER_MASK 0x00001f00
++#define AR5312_CLOCKCTL1_MULTIPLIER_SHIFT 8
++#define AR5312_CLOCKCTL1_DOUBLER_MASK 0x00010000
++
++/* Valid for AR5312 and AR2312 */
++#define AR5312_CLOCKCTL1_PREDIVIDE_MASK 0x00000030
++#define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT 4
++#define AR5312_CLOCKCTL1_MULTIPLIER_MASK 0x00001f00
++#define AR5312_CLOCKCTL1_MULTIPLIER_SHIFT 8
++#define AR5312_CLOCKCTL1_DOUBLER_MASK 0x00010000
++
++/* Valid for AR2313 */
++#define AR2313_CLOCKCTL1_PREDIVIDE_MASK 0x00003000
++#define AR2313_CLOCKCTL1_PREDIVIDE_SHIFT 12
++#define AR2313_CLOCKCTL1_MULTIPLIER_MASK 0x001f0000
++#define AR2313_CLOCKCTL1_MULTIPLIER_SHIFT 16
++#define AR2313_CLOCKCTL1_DOUBLER_MASK 0x00000000
++
++
++/* AR531X_ENABLE register bit field definitions */
++#define AR531X_ENABLE_WLAN0 0x0001
++#define AR531X_ENABLE_ENET0 0x0002
++#define AR531X_ENABLE_ENET1 0x0004
++#define AR531X_ENABLE_UART_AND_WLAN1_PIO 0x0008 /* UART, and WLAN1 PIOs */
++#define AR531X_ENABLE_WLAN1_DMA 0x0010 /* WLAN1 DMAs */
++#define AR531X_ENABLE_WLAN1 \
++ (AR531X_ENABLE_UART_AND_WLAN1_PIO | AR531X_ENABLE_WLAN1_DMA)
++
++/* AR531X_REV register bit field definitions */
++#define AR531X_REV_WMAC_MAJ 0xf000
++#define AR531X_REV_WMAC_MAJ_S 12
++#define AR531X_REV_WMAC_MIN 0x0f00
++#define AR531X_REV_WMAC_MIN_S 8
++#define AR531X_REV_MAJ 0x00f0
++#define AR531X_REV_MAJ_S 4
++#define AR531X_REV_MIN 0x000f
++#define AR531X_REV_MIN_S 0
++#define AR531X_REV_CHIP (REV_MAJ|REV_MIN)
++
++/* Major revision numbers, bits 7..4 of Revision ID register */
++#define AR531X_REV_MAJ_AR5312 0x4
++#define AR531X_REV_MAJ_AR2313 0x5
++
++/* Minor revision numbers, bits 3..0 of Revision ID register */
++#define AR5312_REV_MIN_DUAL 0x0 /* Dual WLAN version */
++#define AR5312_REV_MIN_SINGLE 0x1 /* Single WLAN version */
++
++/* AR531X_FLASHCTL register bit field definitions */
++#define FLASHCTL_IDCY 0x0000000f /* Idle cycle turn around time */
++#define FLASHCTL_IDCY_S 0
++#define FLASHCTL_WST1 0x000003e0 /* Wait state 1 */
++#define FLASHCTL_WST1_S 5
++#define FLASHCTL_RBLE 0x00000400 /* Read byte lane enable */
++#define FLASHCTL_WST2 0x0000f800 /* Wait state 2 */
++#define FLASHCTL_WST2_S 11
++#define FLASHCTL_AC 0x00070000 /* Flash address check (added) */
++#define FLASHCTL_AC_S 16
++#define FLASHCTL_AC_128K 0x00000000
++#define FLASHCTL_AC_256K 0x00010000
++#define FLASHCTL_AC_512K 0x00020000
++#define FLASHCTL_AC_1M 0x00030000
++#define FLASHCTL_AC_2M 0x00040000
++#define FLASHCTL_AC_4M 0x00050000
++#define FLASHCTL_AC_8M 0x00060000
++#define FLASHCTL_AC_RES 0x00070000 /* 16MB is not supported */
++#define FLASHCTL_E 0x00080000 /* Flash bank enable (added) */
++#define FLASHCTL_BUSERR 0x01000000 /* Bus transfer error status flag */
++#define FLASHCTL_WPERR 0x02000000 /* Write protect error status flag */
++#define FLASHCTL_WP 0x04000000 /* Write protect */
++#define FLASHCTL_BM 0x08000000 /* Burst mode */
++#define FLASHCTL_MW 0x30000000 /* Memory width */
++#define FLASHCTL_MWx8 0x00000000 /* Memory width x8 */
++#define FLASHCTL_MWx16 0x10000000 /* Memory width x16 */
++#define FLASHCTL_MWx32 0x20000000 /* Memory width x32 (not supported) */
++#define FLASHCTL_ATNR 0x00000000 /* Access type == no retry */
++#define FLASHCTL_ATR 0x80000000 /* Access type == retry every */
++#define FLASHCTL_ATR4 0xc0000000 /* Access type == retry every 4 */
++
++/* ARM Flash Controller -- 3 flash banks with either x8 or x16 devices. */
++#define AR531X_FLASHCTL0 (AR531X_FLASHCTL + 0x00)
++#define AR531X_FLASHCTL1 (AR531X_FLASHCTL + 0x04)
++#define AR531X_FLASHCTL2 (AR531X_FLASHCTL + 0x08)
++
++/* ARM SDRAM Controller -- just enough to determine memory size */
++#define AR531X_MEM_CFG1 (AR531X_SDRAMCTL + 0x04)
++#define MEM_CFG1_AC0 0x00000700 /* bank 0: SDRAM addr check (added) */
++#define MEM_CFG1_AC0_S 8
++#define MEM_CFG1_AC1 0x00007000 /* bank 1: SDRAM addr check (added) */
++#define MEM_CFG1_AC1_S 12
++
++/* GPIO Address Map */
++#define AR531X_GPIO (AR531X_APBBASE + 0x2000)
++#define AR531X_GPIO_DO (AR531X_GPIO + 0x00) /* output register */
++#define AR531X_GPIO_DI (AR531X_GPIO + 0x04) /* intput register */
++#define AR531X_GPIO_CR (AR531X_GPIO + 0x08) /* control register */
++
++/* GPIO Control Register bit field definitions */
++#define GPIO_CR_M(x) (1 << (x)) /* mask for i/o */
++#define GPIO_CR_O(x) (0 << (x)) /* mask for output */
++#define GPIO_CR_I(x) (1 << (x)) /* mask for input */
++#define GPIO_CR_INT(x) (1 << ((x)+8)) /* mask for interrupt */
++#define GPIO_CR_UART(x) (1 << ((x)+16)) /* uart multiplex */
++
++
++typedef unsigned int AR531X_REG;
++
++#define sysRegRead(phys) \
++ (*(volatile AR531X_REG *)PHYS_TO_K1(phys))
++
++#define sysRegWrite(phys, val) \
++ ((*(volatile AR531X_REG *)PHYS_TO_K1(phys)) = (val))
++
++
++/*
++ * This is board-specific data that is stored in a "fixed" location in flash.
++ * It is shared across operating systems, so it should not be changed lightly.
++ * The main reason we need it is in order to extract the ethernet MAC
++ * address(es).
++ */
++struct ar531x_boarddata {
++ u32 magic; /* board data is valid */
++#define AR531X_BD_MAGIC 0x35333131 /* "5311", for all 531x platforms */
++ u16 cksum; /* checksum (starting with BD_REV 2) */
++ u16 rev; /* revision of this struct */
++#define BD_REV 4
++ char boardName[64]; /* Name of board */
++ u16 major; /* Board major number */
++ u16 minor; /* Board minor number */
++ u32 config; /* Board configuration */
++#define BD_ENET0 0x00000001 /* ENET0 is stuffed */
++#define BD_ENET1 0x00000002 /* ENET1 is stuffed */
++#define BD_UART1 0x00000004 /* UART1 is stuffed */
++#define BD_UART0 0x00000008 /* UART0 is stuffed (dma) */
++#define BD_RSTFACTORY 0x00000010 /* Reset factory defaults stuffed */
++#define BD_SYSLED 0x00000020 /* System LED stuffed */
++#define BD_EXTUARTCLK 0x00000040 /* External UART clock */
++#define BD_CPUFREQ 0x00000080 /* cpu freq is valid in nvram */
++#define BD_SYSFREQ 0x00000100 /* sys freq is set in nvram */
++#define BD_WLAN0 0x00000200 /* Enable WLAN0 */
++#define BD_MEMCAP 0x00000400 /* CAP SDRAM @ memCap for testing */
++#define BD_DISWATCHDOG 0x00000800 /* disable system watchdog */
++#define BD_WLAN1 0x00001000 /* Enable WLAN1 (ar5212) */
++#define BD_ISCASPER 0x00002000 /* FLAG for AR2312 */
++#define BD_WLAN0_2G_EN 0x00004000 /* FLAG for radio0_2G */
++#define BD_WLAN0_5G_EN 0x00008000 /* FLAG for radio0_2G */
++#define BD_WLAN1_2G_EN 0x00020000 /* FLAG for radio0_2G */
++#define BD_WLAN1_5G_EN 0x00040000 /* FLAG for radio0_2G */
++ u16 resetConfigGpio; /* Reset factory GPIO pin */
++ u16 sysLedGpio; /* System LED GPIO pin */
++
++ u32 cpuFreq; /* CPU core frequency in Hz */
++ u32 sysFreq; /* System frequency in Hz */
++ u32 cntFreq; /* Calculated C0_COUNT frequency */
++
++ u8 wlan0Mac[6];
++ u8 enet0Mac[6];
++ u8 enet1Mac[6];
++
++ u16 pciId; /* Pseudo PCIID for common code */
++ u16 memCap; /* cap bank1 in MB */
++
++ /* version 3 */
++ u8 wlan1Mac[6]; /* (ar5212) */
++};
++
++#else
++
++/*
++ * Address map
++ */
++#define AR5315_SDRAM0 0x00000000 /* DRAM */
++#define AR5315_SPI_READ 0x08000000 /* SPI FLASH */
++#define AR5315_WLAN0 0xB0000000 /* Wireless MMR */
++#define AR5315_PCI 0xB0100000 /* PCI MMR */
++#define AR5315_SDRAMCTL 0xB0300000 /* SDRAM MMR */
++#define AR5315_LOCAL 0xB0400000 /* LOCAL BUS MMR */
++#define AR5315_ENET0 0xB0500000 /* ETHERNET MMR */
++#define AR5315_DSLBASE 0xB1000000 /* RESET CONTROL MMR */
++#define AR5315_UART0 0xB1100003 /* UART MMR */
++#define AR5315_SPI 0xB1300000 /* SPI FLASH MMR */
++#define AR5315_FLASHBT 0xBfc00000 /* ro boot alias to FLASH */
++#define AR5315_RAM1 0x40000000 /* ram alias */
++#define AR5315_PCIEXT 0x80000000 /* pci external */
++#define AR5315_RAM2 0xc0000000 /* ram alias */
++#define AR5315_RAM3 0xe0000000 /* ram alias */
++
++/*
++ * Reset Register
++ */
++#define AR5315_COLD_RESET (AR5315_DSLBASE + 0x0000)
++
++/* Cold Reset */
++#define RESET_COLD_AHB 0x00000001
++#define RESET_COLD_APB 0x00000002
++#define RESET_COLD_CPU 0x00000004
++#define RESET_COLD_CPUWARM 0x00000008
++#define RESET_SYSTEM (RESET_COLD_CPU | RESET_COLD_APB | RESET_COLD_AHB) /* full system */
++
++/* Warm Reset */
++
++#define AR5315_RESET (AR5315_DSLBASE + 0x0004)
++
++#define RESET_WARM_WLAN0_MAC 0x00000001 /* warm reset WLAN0 MAC */
++#define RESET_WARM_WLAN0_BB 0x00000002 /* warm reset WLAN0 BaseBand */
++#define RESET_MPEGTS_RSVD 0x00000004 /* warm reset MPEG-TS */
++#define RESET_PCIDMA 0x00000008 /* warm reset PCI ahb/dma */
++#define RESET_MEMCTL 0x00000010 /* warm reset memory controller */
++#define RESET_LOCAL 0x00000020 /* warm reset local bus */
++#define RESET_I2C_RSVD 0x00000040 /* warm reset I2C bus */
++#define RESET_SPI 0x00000080 /* warm reset SPI interface */
++#define RESET_UART0 0x00000100 /* warm reset UART0 */
++#define RESET_IR_RSVD 0x00000200 /* warm reset IR interface */
++#define RESET_EPHY0 0x00000400 /* cold reset ENET0 phy */
++#define RESET_ENET0 0x00000800 /* cold reset ENET0 mac */
++
++/*
++ * AHB master arbitration control
++ */
++#define AR5315_AHB_ARB_CTL (AR5315_DSLBASE + 0x0008)
++
++#define ARB_CPU 0x00000001 /* CPU, default */
++#define ARB_WLAN 0x00000002 /* WLAN */
++#define ARB_MPEGTS_RSVD 0x00000004 /* MPEG-TS */
++#define ARB_LOCAL 0x00000008 /* LOCAL */
++#define ARB_PCI 0x00000010 /* PCI */
++#define ARB_ETHERNET 0x00000020 /* Ethernet */
++#define ARB_RETRY 0x00000100 /* retry policy, debug only */
++
++/*
++ * Config Register
++ */
++#define AR5315_ENDIAN_CTL (AR5315_DSLBASE + 0x000c)
++
++#define CONFIG_AHB 0x00000001 /* EC - AHB bridge endianess */
++#define CONFIG_WLAN 0x00000002 /* WLAN byteswap */
++#define CONFIG_MPEGTS_RSVD 0x00000004 /* MPEG-TS byteswap */
++#define CONFIG_PCI 0x00000008 /* PCI byteswap */
++#define CONFIG_MEMCTL 0x00000010 /* Memory controller endianess */
++#define CONFIG_LOCAL 0x00000020 /* Local bus byteswap */
++#define CONFIG_ETHERNET 0x00000040 /* Ethernet byteswap */
++
++#define CONFIG_MERGE 0x00000200 /* CPU write buffer merge */
++#define CONFIG_CPU 0x00000400 /* CPU big endian */
++#define CONFIG_PCIAHB 0x00000800
++#define CONFIG_PCIAHB_BRIDGE 0x00001000
++#define CONFIG_SPI 0x00008000 /* SPI byteswap */
++#define CONFIG_CPU_DRAM 0x00010000
++#define CONFIG_CPU_PCI 0x00020000
++#define CONFIG_CPU_MMR 0x00040000
++#define CONFIG_BIG 0x00000400
++
++
++/*
++ * NMI control
++ */
++#define AR5315_NMI_CTL (AR5315_DSLBASE + 0x0010)
++
++#define NMI_EN 1
++
++/*
++ * Revision Register - Initial value is 0x3010 (WMAC 3.0, AR531X 1.0).
++ */
++#define AR5315_SREV (AR5315_DSLBASE + 0x0014)
++
++#define REV_MAJ 0x00f0
++#define REV_MAJ_S 4
++#define REV_MIN 0x000f
++#define REV_MIN_S 0
++#define REV_CHIP (REV_MAJ|REV_MIN)
++
++/*
++ * Interface Enable
++ */
++#define AR5315_IF_CTL (AR5315_DSLBASE + 0x0018)
++
++#define IF_MASK 0x00000007
++#define IF_DISABLED 0
++#define IF_PCI 1
++#define IF_TS_LOCAL 2
++#define IF_ALL 3 /* only for emulation with separate pins */
++#define IF_LOCAL_HOST 0x00000008
++#define IF_PCI_HOST 0x00000010
++#define IF_PCI_INTR 0x00000020
++#define IF_PCI_CLK_MASK 0x00030000
++#define IF_PCI_CLK_INPUT 0
++#define IF_PCI_CLK_OUTPUT_LOW 1
++#define IF_PCI_CLK_OUTPUT_CLK 2
++#define IF_PCI_CLK_OUTPUT_HIGH 3
++#define IF_PCI_CLK_SHIFT 16
++
++
++/* Major revision numbers, bits 7..4 of Revision ID register */
++#define REV_MAJ_AR5311 0x01
++#define REV_MAJ_AR5312 0x04
++#define REV_MAJ_AR5315 0x0B
++
++/*
++ * APB Interrupt control
++ */
++
++#define AR5315_ISR (AR5315_DSLBASE + 0x0020)
++#define AR5315_IMR (AR5315_DSLBASE + 0x0024)
++#define AR5315_GISR (AR5315_DSLBASE + 0x0028)
++
++#define ISR_UART0 0x0001 /* high speed UART */
++#define ISR_I2C_RSVD 0x0002 /* I2C bus */
++#define ISR_SPI 0x0004 /* SPI bus */
++#define ISR_AHB 0x0008 /* AHB error */
++#define ISR_APB 0x0010 /* APB error */
++#define ISR_TIMER 0x0020 /* timer */
++#define ISR_GPIO 0x0040 /* GPIO */
++#define ISR_WD 0x0080 /* watchdog */
++#define ISR_IR_RSVD 0x0100 /* IR */
++
++#define IMR_UART0 ISR_UART0
++#define IMR_I2C_RSVD ISR_I2C_RSVD
++#define IMR_SPI ISR_SPI
++#define IMR_AHB ISR_AHB
++#define IMR_APB ISR_APB
++#define IMR_TIMER ISR_TIMER
++#define IMR_GPIO ISR_GPIO
++#define IMR_WD ISR_WD
++#define IMR_IR_RSVD ISR_IR_RSVD
++
++#define GISR_MISC 0x0001
++#define GISR_WLAN0 0x0002
++#define GISR_MPEGTS_RSVD 0x0004
++#define GISR_LOCALPCI 0x0008
++#define GISR_WMACPOLL 0x0010
++#define GISR_TIMER 0x0020
++#define GISR_ETHERNET 0x0040
++
++/*
++ * Interrupt routing from IO to the processor IP bits
++ * Define our inter mask and level
++ */
++#define AR5315_INTR_MISCIO SR_IBIT3
++#define AR5315_INTR_WLAN0 SR_IBIT4
++#define AR5315_INTR_ENET0 SR_IBIT5
++#define AR5315_INTR_LOCALPCI SR_IBIT6
++#define AR5315_INTR_WMACPOLL SR_IBIT7
++#define AR5315_INTR_COMPARE SR_IBIT8
++
++/*
++ * Timers
++ */
++#define AR5315_TIMER (AR5315_DSLBASE + 0x0030)
++#define AR5315_RELOAD (AR5315_DSLBASE + 0x0034)
++#define AR5315_WD (AR5315_DSLBASE + 0x0038)
++#define AR5315_WDC (AR5315_DSLBASE + 0x003c)
++
++#define WDC_RESET 0x00000002 /* reset on watchdog */
++#define WDC_NMI 0x00000001 /* NMI on watchdog */
++#define WDC_IGNORE_EXPIRATION 0x00000000
++
++/*
++ * Interface Debug
++ */
++#define AR531X_FLASHDBG (AR531X_RESETTMR + 0x0040)
++#define AR531X_MIIDBG (AR531X_RESETTMR + 0x0044)
++
++
++/*
++ * CPU Performance Counters
++ */
++#define AR5315_PERFCNT0 (AR5315_DSLBASE + 0x0048)
++#define AR5315_PERFCNT1 (AR5315_DSLBASE + 0x004c)
++
++#define PERF_DATAHIT 0x0001 /* Count Data Cache Hits */
++#define PERF_DATAMISS 0x0002 /* Count Data Cache Misses */
++#define PERF_INSTHIT 0x0004 /* Count Instruction Cache Hits */
++#define PERF_INSTMISS 0x0008 /* Count Instruction Cache Misses */
++#define PERF_ACTIVE 0x0010 /* Count Active Processor Cycles */
++#define PERF_WBHIT 0x0020 /* Count CPU Write Buffer Hits */
++#define PERF_WBMISS 0x0040 /* Count CPU Write Buffer Misses */
++
++#define PERF_EB_ARDY 0x0001 /* Count EB_ARdy signal */
++#define PERF_EB_AVALID 0x0002 /* Count EB_AValid signal */
++#define PERF_EB_WDRDY 0x0004 /* Count EB_WDRdy signal */
++#define PERF_EB_RDVAL 0x0008 /* Count EB_RdVal signal */
++#define PERF_VRADDR 0x0010 /* Count valid read address cycles */
++#define PERF_VWADDR 0x0020 /* Count valid write address cycles */
++#define PERF_VWDATA 0x0040 /* Count valid write data cycles */
++
++/*
++ * AHB Error Reporting.
++ */
++#define AR5315_AHB_ERR0 (AR5315_DSLBASE + 0x0050) /* error */
++#define AR5315_AHB_ERR1 (AR5315_DSLBASE + 0x0054) /* haddr */
++#define AR5315_AHB_ERR2 (AR5315_DSLBASE + 0x0058) /* hwdata */
++#define AR5315_AHB_ERR3 (AR5315_DSLBASE + 0x005c) /* hrdata */
++#define AR5315_AHB_ERR4 (AR5315_DSLBASE + 0x0060) /* status */
++
++#define AHB_ERROR_DET 1 /* AHB Error has been detected, */
++ /* write 1 to clear all bits in ERR0 */
++#define AHB_ERROR_OVR 2 /* AHB Error overflow has been detected */
++#define AHB_ERROR_WDT 4 /* AHB Error due to wdt instead of hresp */
++
++#define PROCERR_HMAST 0x0000000f
++#define PROCERR_HMAST_DFLT 0
++#define PROCERR_HMAST_WMAC 1
++#define PROCERR_HMAST_ENET 2
++#define PROCERR_HMAST_PCIENDPT 3
++#define PROCERR_HMAST_LOCAL 4
++#define PROCERR_HMAST_CPU 5
++#define PROCERR_HMAST_PCITGT 6
++
++#define PROCERR_HMAST_S 0
++#define PROCERR_HWRITE 0x00000010
++#define PROCERR_HSIZE 0x00000060
++#define PROCERR_HSIZE_S 5
++#define PROCERR_HTRANS 0x00000180
++#define PROCERR_HTRANS_S 7
++#define PROCERR_HBURST 0x00000e00
++#define PROCERR_HBURST_S 9
++
++
++
++/*
++ * Clock Control
++ */
++#define AR5315_PLLC_CTL (AR5315_DSLBASE + 0x0064)
++#define AR5315_PLLV_CTL (AR5315_DSLBASE + 0x0068)
++#define AR5315_CPUCLK (AR5315_DSLBASE + 0x006c)
++#define AR5315_AMBACLK (AR5315_DSLBASE + 0x0070)
++#define AR5315_SYNCCLK (AR5315_DSLBASE + 0x0074)
++#define AR5315_DSL_SLEEP_CTL (AR5315_DSLBASE + 0x0080)
++#define AR5315_DSL_SLEEP_DUR (AR5315_DSLBASE + 0x0084)
++
++/* PLLc Control fields */
++#define PLLC_REF_DIV_M 0x00000003
++#define PLLC_REF_DIV_S 0
++#define PLLC_FDBACK_DIV_M 0x0000007C
++#define PLLC_FDBACK_DIV_S 2
++#define PLLC_ADD_FDBACK_DIV_M 0x00000080
++#define PLLC_ADD_FDBACK_DIV_S 7
++#define PLLC_CLKC_DIV_M 0x0001c000
++#define PLLC_CLKC_DIV_S 14
++#define PLLC_CLKM_DIV_M 0x00700000
++#define PLLC_CLKM_DIV_S 20
++
++/* CPU CLK Control fields */
++#define CPUCLK_CLK_SEL_M 0x00000003
++#define CPUCLK_CLK_SEL_S 0
++#define CPUCLK_CLK_DIV_M 0x0000000c
++#define CPUCLK_CLK_DIV_S 2
++
++/* AMBA CLK Control fields */
++#define AMBACLK_CLK_SEL_M 0x00000003
++#define AMBACLK_CLK_SEL_S 0
++#define AMBACLK_CLK_DIV_M 0x0000000c
++#define AMBACLK_CLK_DIV_S 2
++
++#if defined(COBRA_EMUL)
++#define AR5315_AMBA_CLOCK_RATE 20000000
++#define AR5315_CPU_CLOCK_RATE 40000000
++#else
++#if defined(DEFAULT_PLL)
++#define AR5315_AMBA_CLOCK_RATE 40000000
++#define AR5315_CPU_CLOCK_RATE 40000000
++#else
++#define AR5315_AMBA_CLOCK_RATE 92000000
++#define AR5315_CPU_CLOCK_RATE 184000000
++#endif /* ! DEFAULT_PLL */
++#endif /* ! COBRA_EMUL */
++
++#define AR5315_UART_CLOCK_RATE AR5315_AMBA_CLOCK_RATE
++#define AR5315_SDRAM_CLOCK_RATE AR5315_AMBA_CLOCK_RATE
++
++/*
++ * The UART computes baud rate as:
++ * baud = clock / (16 * divisor)
++ * where divisor is specified as a High Byte (DLM) and a Low Byte (DLL).
++ */
++#define DESIRED_BAUD_RATE 38400
++
++/*
++ * The WATCHDOG value is computed as
++ * 10 seconds * AR531X_WATCHDOG_CLOCK_RATE
++ */
++#define DESIRED_WATCHDOG_SECONDS 10
++#define AR531X_WATCHDOG_TIME \
++ (DESIRED_WATCHDOG_SECONDS * AR531X_WATCHDOG_CLOCK_RATE)
++
++
++#define CLOCKCTL_UART0 0x0010 /* enable UART0 external clock */
++
++
++ /*
++ * Applicable "PCICFG" bits for WLAN(s). Assoc status and LED mode.
++ */
++#define AR531X_PCICFG (AR531X_RESETTMR + 0x00b0)
++#define ASSOC_STATUS_M 0x00000003
++#define ASSOC_STATUS_NONE 0
++#define ASSOC_STATUS_PENDING 1
++#define ASSOC_STATUS_ASSOCIATED 2
++#define LED_MODE_M 0x0000001c
++#define LED_BLINK_THRESHOLD_M 0x000000e0
++#define LED_SLOW_BLINK_MODE 0x00000100
++
++/*
++ * GPIO
++ */
++
++#define AR5315_GPIO_DI (AR5315_DSLBASE + 0x0088)
++#define AR5315_GPIO_DO (AR5315_DSLBASE + 0x0090)
++#define AR5315_GPIO_CR (AR5315_DSLBASE + 0x0098)
++#define AR5315_GPIO_INT (AR5315_DSLBASE + 0x00a0)
++
++#define GPIO_CR_M(x) (1 << (x)) /* mask for i/o */
++#define GPIO_CR_O(x) (1 << (x)) /* output */
++#define GPIO_CR_I(x) (0 << (x)) /* input */
++
++#define GPIO_INT(x,Y) ((x) << (8 * (Y))) /* interrupt enable */
++#define GPIO_INT_M(Y) ((0x3F) << (8 * (Y))) /* mask for int */
++#define GPIO_INT_LVL(x,Y) ((x) << (8 * (Y) + 6)) /* interrupt level */
++#define GPIO_INT_LVL_M(Y) ((0x3) << (8 * (Y) + 6)) /* mask for int level */
++
++#define AR5315_RESET_GPIO 5
++#define AR5315_NUM_GPIO 22
++
++
++/*
++ * PCI Clock Control
++ */
++
++#define AR5315_PCICLK (AR5315_DSLBASE + 0x00a4)
++
++#define PCICLK_INPUT_M 0x3
++#define PCICLK_INPUT_S 0
++
++#define PCICLK_PLLC_CLKM 0
++#define PCICLK_PLLC_CLKM1 1
++#define PCICLK_PLLC_CLKC 2
++#define PCICLK_REF_CLK 3
++
++#define PCICLK_DIV_M 0xc
++#define PCICLK_DIV_S 2
++
++#define PCICLK_IN_FREQ 0
++#define PCICLK_IN_FREQ_DIV_6 1
++#define PCICLK_IN_FREQ_DIV_8 2
++#define PCICLK_IN_FREQ_DIV_10 3
++
++/*
++ * Observation Control Register
++ */
++#define AR5315_OCR (AR5315_DSLBASE + 0x00b0)
++#define OCR_GPIO0_IRIN 0x0040
++#define OCR_GPIO1_IROUT 0x0080
++#define OCR_GPIO3_RXCLR 0x0200
++
++/*
++ * General Clock Control
++ */
++
++#define AR5315_MISCCLK (AR5315_DSLBASE + 0x00b4)
++#define MISCCLK_PLLBYPASS_EN 0x00000001
++#define MISCCLK_PROCREFCLK 0x00000002
++
++/*
++ * SDRAM Controller
++ * - No read or write buffers are included.
++ */
++#define AR5315_MEM_CFG (AR5315_SDRAMCTL + 0x00)
++#define AR5315_MEM_CTRL (AR5315_SDRAMCTL + 0x0c)
++#define AR5315_MEM_REF (AR5315_SDRAMCTL + 0x10)
++
++#define SDRAM_DATA_WIDTH_M 0x00006000
++#define SDRAM_DATA_WIDTH_S 13
++
++#define SDRAM_COL_WIDTH_M 0x00001E00
++#define SDRAM_COL_WIDTH_S 9
++
++#define SDRAM_ROW_WIDTH_M 0x000001E0
++#define SDRAM_ROW_WIDTH_S 5
++
++#define SDRAM_BANKADDR_BITS_M 0x00000018
++#define SDRAM_BANKADDR_BITS_S 3
++
++
++/*
++ * SDRAM Memory Refresh (MEM_REF) value is computed as:
++ * MEMCTL_SREFR = (Tr * hclk_freq) / R
++ * where Tr is max. time of refresh of any single row
++ * R is number of rows in the DRAM
++ * For most 133MHz SDRAM parts, Tr=64ms, R=4096 or 8192
++ */
++#if defined(COBRA_EMUL)
++#define AR5315_SDRAM_MEMORY_REFRESH_VALUE 0x96
++#else
++#if defined(DEFAULT_PLL)
++#define AR5315_SDRAM_MEMORY_REFRESH_VALUE 0x200
++#else
++#define AR5315_SDRAM_MEMORY_REFRESH_VALUE 0x61a
++#endif /* ! DEFAULT_PLL */
++#endif
++
++#if defined(AR5315)
++
++#define AR5315_SDRAM_DDR_SDRAM 0 /* Not DDR SDRAM */
++#define AR5315_SDRAM_DATA_WIDTH 16 /* bits */
++#define AR5315_SDRAM_COL_WIDTH 8
++#define AR5315_SDRAM_ROW_WIDTH 12
++
++#else
++
++#define AR5315_SDRAM_DDR_SDRAM 0 /* Not DDR SDRAM */
++#define AR5315_SDRAM_DATA_WIDTH 16
++#define AR5315_SDRAM_COL_WIDTH 8
++#define AR5315_SDRAM_ROW_WIDTH 12
++
++#endif /* ! AR5315 */
++
++/*
++ * SPI Flash Interface Registers
++ */
++
++#define AR5315_SPI_CTL (AR5315_SPI + 0x00)
++#define AR5315_SPI_OPCODE (AR5315_SPI + 0x04)
++#define AR5315_SPI_DATA (AR5315_SPI + 0x08)
++
++#define SPI_CTL_START 0x00000100
++#define SPI_CTL_BUSY 0x00010000
++#define SPI_CTL_TXCNT_MASK 0x0000000f
++#define SPI_CTL_RXCNT_MASK 0x000000f0
++#define SPI_CTL_TX_RX_CNT_MASK 0x000000ff
++#define SPI_CTL_SIZE_MASK 0x00060000
++
++#define SPI_CTL_CLK_SEL_MASK 0x03000000
++#define SPI_OPCODE_MASK 0x000000ff
++
++/*
++ * PCI-MAC Configuration registers
++ */
++#define PCI_MAC_RC (AR5315_PCI + 0x4000)
++#define PCI_MAC_SCR (AR5315_PCI + 0x4004)
++#define PCI_MAC_INTPEND (AR5315_PCI + 0x4008)
++#define PCI_MAC_SFR (AR5315_PCI + 0x400C)
++#define PCI_MAC_PCICFG (AR5315_PCI + 0x4010)
++#define PCI_MAC_SREV (AR5315_PCI + 0x4020)
++
++#define PCI_MAC_RC_MAC 0x00000001
++#define PCI_MAC_RC_BB 0x00000002
++
++#define PCI_MAC_SCR_SLMODE_M 0x00030000
++#define PCI_MAC_SCR_SLMODE_S 16
++#define PCI_MAC_SCR_SLM_FWAKE 0
++#define PCI_MAC_SCR_SLM_FSLEEP 1
++#define PCI_MAC_SCR_SLM_NORMAL 2
++
++#define PCI_MAC_SFR_SLEEP 0x00000001
++
++#define PCI_MAC_PCICFG_SPWR_DN 0x00010000
++
++
++
++
++/*
++ * PCI Bus Interface Registers
++ */
++#define AR5315_PCI_1MS_REG (AR5315_PCI + 0x0008)
++#define AR5315_PCI_1MS_MASK 0x3FFFF /* # of AHB clk cycles in 1ms */
++
++#define AR5315_PCI_MISC_CONFIG (AR5315_PCI + 0x000c)
++#define AR5315_PCIMISC_TXD_EN 0x00000001 /* Enable TXD for fragments */
++#define AR5315_PCIMISC_CFG_SEL 0x00000002 /* mem or config cycles */
++#define AR5315_PCIMISC_GIG_MASK 0x0000000C /* bits 31-30 for pci req */
++#define AR5315_PCIMISC_RST_MODE 0x00000030
++#define AR5315_PCIRST_INPUT 0x00000000 /* 4:5=0 rst is input */
++#define AR5315_PCIRST_LOW 0x00000010 /* 4:5=1 rst to GND */
++#define AR5315_PCIRST_HIGH 0x00000020 /* 4:5=2 rst to VDD */
++#define AR5315_PCIGRANT_EN 0x00000000 /* 6:7=0 early grant en */
++#define AR5315_PCIGRANT_FRAME 0x00000040 /* 6:7=1 grant waits 4 frame */
++#define AR5315_PCIGRANT_IDLE 0x00000080 /* 6:7=2 grant waits 4 idle */
++#define AR5315_PCIGRANT_GAP 0x00000000 /* 6:7=2 grant waits 4 idle */
++#define AR5315_PCICACHE_DIS 0x00001000 /* PCI external access cache disable */
++
++#define AR5315_PCI_OUT_TSTAMP (AR5315_PCI + 0x0010)
++
++#define AR5315_PCI_UNCACHE_CFG (AR5315_PCI + 0x0014)
++
++#define AR5315_PCI_IN_EN (AR5315_PCI + 0x0100)
++#define AR5315_PCI_IN_EN0 0x01 /* Enable chain 0 */
++#define AR5315_PCI_IN_EN1 0x02 /* Enable chain 1 */
++#define AR5315_PCI_IN_EN2 0x04 /* Enable chain 2 */
++#define AR5315_PCI_IN_EN3 0x08 /* Enable chain 3 */
++
++#define AR5315_PCI_IN_DIS (AR5315_PCI + 0x0104)
++#define AR5315_PCI_IN_DIS0 0x01 /* Disable chain 0 */
++#define AR5315_PCI_IN_DIS1 0x02 /* Disable chain 1 */
++#define AR5315_PCI_IN_DIS2 0x04 /* Disable chain 2 */
++#define AR5315_PCI_IN_DIS3 0x08 /* Disable chain 3 */
++
++#define AR5315_PCI_IN_PTR (AR5315_PCI + 0x0200)
++
++#define AR5315_PCI_OUT_EN (AR5315_PCI + 0x0400)
++#define AR5315_PCI_OUT_EN0 0x01 /* Enable chain 0 */
++
++#define AR5315_PCI_OUT_DIS (AR5315_PCI + 0x0404)
++#define AR5315_PCI_OUT_DIS0 0x01 /* Disable chain 0 */
++
++#define AR5315_PCI_OUT_PTR (AR5315_PCI + 0x0408)
++
++#define AR5315_PCI_INT_STATUS (AR5315_PCI + 0x0500) /* write one to clr */
++#define AR5315_PCI_TXINT 0x00000001 /* Desc In Completed */
++#define AR5315_PCI_TXOK 0x00000002 /* Desc In OK */
++#define AR5315_PCI_TXERR 0x00000004 /* Desc In ERR */
++#define AR5315_PCI_TXEOL 0x00000008 /* Desc In End-of-List */
++#define AR5315_PCI_RXINT 0x00000010 /* Desc Out Completed */
++#define AR5315_PCI_RXOK 0x00000020 /* Desc Out OK */
++#define AR5315_PCI_RXERR 0x00000040 /* Desc Out ERR */
++#define AR5315_PCI_RXEOL 0x00000080 /* Desc Out EOL */
++#define AR5315_PCI_TXOOD 0x00000200 /* Desc In Out-of-Desc */
++#define AR5315_PCI_MASK 0x0000FFFF /* Desc Mask */
++#define AR5315_PCI_EXT_INT 0x02000000
++#define AR5315_PCI_ABORT_INT 0x04000000
++
++#define AR5315_PCI_INT_MASK (AR5315_PCI + 0x0504) /* same as INT_STATUS */
++
++#define AR5315_PCI_INTEN_REG (AR5315_PCI + 0x0508)
++#define AR5315_PCI_INT_DISABLE 0x00 /* disable pci interrupts */
++#define AR5315_PCI_INT_ENABLE 0x01 /* enable pci interrupts */
++
++#define AR5315_PCI_HOST_IN_EN (AR5315_PCI + 0x0800)
++#define AR5315_PCI_HOST_IN_DIS (AR5315_PCI + 0x0804)
++#define AR5315_PCI_HOST_IN_PTR (AR5315_PCI + 0x0810)
++#define AR5315_PCI_HOST_OUT_EN (AR5315_PCI + 0x0900)
++#define AR5315_PCI_HOST_OUT_DIS (AR5315_PCI + 0x0904)
++#define AR5315_PCI_HOST_OUT_PTR (AR5315_PCI + 0x0908)
++
++
++/*
++ * Local Bus Interface Registers
++ */
++#define AR5315_LB_CONFIG (AR5315_LOCAL + 0x0000)
++#define AR5315_LBCONF_OE 0x00000001 /* =1 OE is low-true */
++#define AR5315_LBCONF_CS0 0x00000002 /* =1 first CS is low-true */
++#define AR5315_LBCONF_CS1 0x00000004 /* =1 2nd CS is low-true */
++#define AR5315_LBCONF_RDY 0x00000008 /* =1 RDY is low-true */
++#define AR5315_LBCONF_WE 0x00000010 /* =1 Write En is low-true */
++#define AR5315_LBCONF_WAIT 0x00000020 /* =1 WAIT is low-true */
++#define AR5315_LBCONF_ADS 0x00000040 /* =1 Adr Strobe is low-true */
++#define AR5315_LBCONF_MOT 0x00000080 /* =0 Intel, =1 Motorola */
++#define AR5315_LBCONF_8CS 0x00000100 /* =1 8 bits CS, 0= 16bits */
++#define AR5315_LBCONF_8DS 0x00000200 /* =1 8 bits Data S, 0=16bits */
++#define AR5315_LBCONF_ADS_EN 0x00000400 /* =1 Enable ADS */
++#define AR5315_LBCONF_ADR_OE 0x00000800 /* =1 Adr cap on OE, WE or DS */
++#define AR5315_LBCONF_ADDT_MUX 0x00001000 /* =1 Adr and Data share bus */
++#define AR5315_LBCONF_DATA_OE 0x00002000 /* =1 Data cap on OE, WE, DS */
++#define AR5315_LBCONF_16DATA 0x00004000 /* =1 Data is 16 bits wide */
++#define AR5315_LBCONF_SWAPDT 0x00008000 /* =1 Byte swap data */
++#define AR5315_LBCONF_SYNC 0x00010000 /* =1 Bus synchronous to clk */
++#define AR5315_LBCONF_INT 0x00020000 /* =1 Intr is low true */
++#define AR5315_LBCONF_INT_CTR0 0x00000000 /* GND high-Z, Vdd is high-Z */
++#define AR5315_LBCONF_INT_CTR1 0x00040000 /* GND drive, Vdd is high-Z */
++#define AR5315_LBCONF_INT_CTR2 0x00080000 /* GND high-Z, Vdd drive */
++#define AR5315_LBCONF_INT_CTR3 0x000C0000 /* GND drive, Vdd drive */
++#define AR5315_LBCONF_RDY_WAIT 0x00100000 /* =1 RDY is negative of WAIT */
++#define AR5315_LBCONF_INT_PULSE 0x00200000 /* =1 Interrupt is a pulse */
++#define AR5315_LBCONF_ENABLE 0x00400000 /* =1 Falcon respond to LB */
++
++#define AR5315_LB_CLKSEL (AR5315_LOCAL + 0x0004)
++#define AR5315_LBCLK_EXT 0x0001 /* use external clk for lb */
++
++#define AR5315_LB_1MS (AR5315_LOCAL + 0x0008)
++#define AR5315_LB1MS_MASK 0x3FFFF /* # of AHB clk cycles in 1ms */
++
++#define AR5315_LB_MISCCFG (AR5315_LOCAL + 0x000C)
++#define AR5315_LBM_TXD_EN 0x00000001 /* Enable TXD for fragments */
++#define AR5315_LBM_RX_INTEN 0x00000002 /* Enable LB ints on RX ready */
++#define AR5315_LBM_MBOXWR_INTEN 0x00000004 /* Enable LB ints on mbox wr */
++#define AR5315_LBM_MBOXRD_INTEN 0x00000008 /* Enable LB ints on mbox rd */
++#define AR5315_LMB_DESCSWAP_EN 0x00000010 /* Byte swap desc enable */
++#define AR5315_LBM_TIMEOUT_MASK 0x00FFFF80
++#define AR5315_LBM_TIMEOUT_SHFT 7
++#define AR5315_LBM_PORTMUX 0x07000000
++
++
++#define AR5315_LB_RXTSOFF (AR5315_LOCAL + 0x0010)
++
++#define AR5315_LB_TX_CHAIN_EN (AR5315_LOCAL + 0x0100)
++#define AR5315_LB_TXEN_0 0x01
++#define AR5315_LB_TXEN_1 0x02
++#define AR5315_LB_TXEN_2 0x04
++#define AR5315_LB_TXEN_3 0x08
++
++#define AR5315_LB_TX_CHAIN_DIS (AR5315_LOCAL + 0x0104)
++#define AR5315_LB_TX_DESC_PTR (AR5315_LOCAL + 0x0200)
++
++#define AR5315_LB_RX_CHAIN_EN (AR5315_LOCAL + 0x0400)
++#define AR5315_LB_RXEN 0x01
++
++#define AR5315_LB_RX_CHAIN_DIS (AR5315_LOCAL + 0x0404)
++#define AR5315_LB_RX_DESC_PTR (AR5315_LOCAL + 0x0408)
++
++#define AR5315_LB_INT_STATUS (AR5315_LOCAL + 0x0500)
++#define AR5315_INT_TX_DESC 0x0001
++#define AR5315_INT_TX_OK 0x0002
++#define AR5315_INT_TX_ERR 0x0004
++#define AR5315_INT_TX_EOF 0x0008
++#define AR5315_INT_RX_DESC 0x0010
++#define AR5315_INT_RX_OK 0x0020
++#define AR5315_INT_RX_ERR 0x0040
++#define AR5315_INT_RX_EOF 0x0080
++#define AR5315_INT_TX_TRUNC 0x0100
++#define AR5315_INT_TX_STARVE 0x0200
++#define AR5315_INT_LB_TIMEOUT 0x0400
++#define AR5315_INT_LB_ERR 0x0800
++#define AR5315_INT_MBOX_WR 0x1000
++#define AR5315_INT_MBOX_RD 0x2000
++
++/* Bit definitions for INT MASK are the same as INT_STATUS */
++#define AR5315_LB_INT_MASK (AR5315_LOCAL + 0x0504)
++
++#define AR5315_LB_INT_EN (AR5315_LOCAL + 0x0508)
++#define AR5315_LB_MBOX (AR5315_LOCAL + 0x0600)
++
++
++
++/*
++ * IR Interface Registers
++ */
++#define AR5315_IR_PKTDATA (AR5315_IR + 0x0000)
++
++#define AR5315_IR_PKTLEN (AR5315_IR + 0x07fc) /* 0 - 63 */
++
++#define AR5315_IR_CONTROL (AR5315_IR + 0x0800)
++#define AR5315_IRCTL_TX 0x00000000 /* use as tranmitter */
++#define AR5315_IRCTL_RX 0x00000001 /* use as receiver */
++#define AR5315_IRCTL_SAMPLECLK_MASK 0x00003ffe /* Sample clk divisor mask */
++#define AR5315_IRCTL_SAMPLECLK_SHFT 1
++#define AR5315_IRCTL_OUTPUTCLK_MASK 0x03ffc000 /* Output clk divisor mask */
++#define AR5315_IRCTL_OUTPUTCLK_SHFT 14
++
++#define AR5315_IR_STATUS (AR5315_IR + 0x0804)
++#define AR5315_IRSTS_RX 0x00000001 /* receive in progress */
++#define AR5315_IRSTS_TX 0x00000002 /* transmit in progress */
++
++#define AR5315_IR_CONFIG (AR5315_IR + 0x0808)
++#define AR5315_IRCFG_INVIN 0x00000001 /* invert input polarity */
++#define AR5315_IRCFG_INVOUT 0x00000002 /* invert output polarity */
++#define AR5315_IRCFG_SEQ_START_WIN_SEL 0x00000004 /* 1 => 28, 0 => 7 */
++#define AR5315_IRCFG_SEQ_START_THRESH 0x000000f0 /* */
++#define AR5315_IRCFG_SEQ_END_UNIT_SEL 0x00000100 /* */
++#define AR5315_IRCFG_SEQ_END_UNIT_THRESH 0x00007e00 /* */
++#define AR5315_IRCFG_SEQ_END_WIN_SEL 0x00008000 /* */
++#define AR5315_IRCFG_SEQ_END_WIN_THRESH 0x001f0000 /* */
++#define AR5315_IRCFG_NUM_BACKOFF_WORDS 0x01e00000 /* */
++
++/*
++ * PCI memory constants: Memory area 1 and 2 are the same size -
++ * (twice the PCI_TLB_PAGE_SIZE). The definition of
++ * CPU_TO_PCI_MEM_SIZE is coupled with the TLB setup routine
++ * sysLib.c/sysTlbInit(), in that it assumes that 2 pages of size
++ * PCI_TLB_PAGE_SIZE are set up in the TLB for each PCI memory space.
++ */
++
++#define CPU_TO_PCI_MEM_BASE1 0xE0000000
++#define CPU_TO_PCI_MEM_SIZE1 (2*PCI_TLB_PAGE_SIZE)
++
++
++/* TLB attributes for PCI transactions */
++
++#define PCI_MMU_PAGEMASK 0x00003FFF
++#define MMU_PAGE_UNCACHED 0x00000010
++#define MMU_PAGE_DIRTY 0x00000004
++#define MMU_PAGE_VALID 0x00000002
++#define MMU_PAGE_GLOBAL 0x00000001
++#define PCI_MMU_PAGEATTRIB (MMU_PAGE_UNCACHED|MMU_PAGE_DIRTY|\
++ MMU_PAGE_VALID|MMU_PAGE_GLOBAL)
++#define PCI_MEMORY_SPACE1_VIRT 0xE0000000 /* Used for non-prefet mem */
++#define PCI_MEMORY_SPACE1_PHYS 0x80000000
++#define PCI_TLB_PAGE_SIZE 0x01000000
++#define TLB_HI_MASK 0xFFFFE000
++#define TLB_LO_MASK 0x3FFFFFFF
++#define PAGEMASK_SHIFT 11
++#define TLB_LO_SHIFT 6
++
++#define PCI_MAX_LATENCY 0xFFF /* Max PCI latency */
++
++#define HOST_PCI_DEV_ID 3
++#define HOST_PCI_MBAR0 0x10000000
++#define HOST_PCI_MBAR1 0x20000000
++#define HOST_PCI_MBAR2 0x30000000
++
++#define HOST_PCI_SDRAM_BASEADDR HOST_PCI_MBAR1
++#define PCI_DEVICE_MEM_SPACE 0x800000
++
++
++typedef unsigned int AR531X_REG;
++
++#define sysRegRead(phys) \
++ (*(volatile AR531X_REG *)PHYS_TO_K1(phys))
++
++#define sysRegWrite(phys, val) \
++ ((*(volatile AR531X_REG *)PHYS_TO_K1(phys)) = (val))
++#endif
++
++#endif
+diff -urN linux-mips/arch/mips/ar531x/ar531xintr.S mips-linux-2.4.25/arch/mips/ar531x/ar531xintr.S
+--- linux-mips/arch/mips/ar531x/ar531xintr.S 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/ar531xintr.S 2005-12-30 17:26:31.000823952 +0000
+@@ -0,0 +1,30 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++ */
++
++#include <asm/asm.h>
++#include <asm/mipsregs.h>
++#include <asm/regdef.h>
++#include <asm/stackframe.h>
++
++/*
++ * Glue code to save registers and get us to the interrupt dispatcher
++ */
++ .text
++ .set noat
++ .align 5
++NESTED(ar531x_interrupt_receive, PT_SIZE, sp)
++ SAVE_ALL
++ CLI
++ .set at
++
++ move a0, sp
++ jal ar531x_irq_dispatch
++
++ j ret_from_irq
++
++ END(ar531x_interrupt_receive)
+diff -urN linux-mips/arch/mips/ar531x/ar531xirq.c mips-linux-2.4.25/arch/mips/ar531x/ar531xirq.c
+--- linux-mips/arch/mips/ar531x/ar531xirq.c 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/ar531xirq.c 2005-12-30 17:26:31.000823952 +0000
+@@ -0,0 +1,442 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++ */
++
++/*
++ * Interrupt support for AR531X WiSOC.
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/kernel_stat.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/interrupt.h>
++#include <linux/slab.h>
++#include <linux/random.h>
++#include <linux/pm.h>
++#include <linux/delay.h>
++#include <linux/reboot.h>
++
++#include <asm/irq.h>
++#include <asm/mipsregs.h>
++#include <asm/gdb-stub.h>
++
++#include "ar531xlnx.h"
++#include <asm/irq_cpu.h>
++
++extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
++
++static void ar531x_misc_intr_enable(unsigned int irq);
++static void ar531x_misc_intr_disable(unsigned int irq);
++
++/* Turn on the specified AR531X_MISC_IRQ interrupt */
++static unsigned int
++ar531x_misc_intr_startup(unsigned int irq)
++{
++ ar531x_misc_intr_enable(irq);
++ return 0;
++}
++
++/* Turn off the specified AR531X_MISC_IRQ interrupt */
++static void
++ar531x_misc_intr_shutdown(unsigned int irq)
++{
++ ar531x_misc_intr_disable(irq);
++}
++
++/* Enable the specified AR531X_MISC_IRQ interrupt */
++static void
++ar531x_misc_intr_enable(unsigned int irq)
++{
++ unsigned int imr;
++
++#if CONFIG_AR5315
++ imr = sysRegRead(AR5315_IMR);
++ switch(irq)
++ {
++ case AR531X_MISC_IRQ_TIMER:
++ imr |= IMR_TIMER;
++ break;
++
++ case AR531X_MISC_IRQ_AHB_PROC:
++ imr |= IMR_AHB;
++ break;
++
++ case AR531X_MISC_IRQ_AHB_DMA:
++ imr |= 0/* ?? */;
++ break;
++ /*
++ case AR531X_ISR_GPIO:
++ imr |= IMR_GPIO;
++ break;
++ */
++
++ case AR531X_MISC_IRQ_UART0:
++ imr |= IMR_UART0;
++ break;
++
++
++ case AR531X_MISC_IRQ_WATCHDOG:
++ imr |= IMR_WD;
++ break;
++
++ case AR531X_MISC_IRQ_LOCAL:
++ imr |= 0/* ?? */;
++ break;
++
++ }
++ sysRegWrite(AR5315_IMR, imr);
++ imr=sysRegRead(AR5315_IMR); /* flush write buffer */
++ //printk("enable Interrupt irq 0x%x imr 0x%x \n",irq,imr);
++
++#else
++ imr = sysRegRead(AR531X_IMR);
++ imr |= (1 << (irq - AR531X_MISC_IRQ_BASE - 1));
++ sysRegWrite(AR531X_IMR, imr);
++ sysRegRead(AR531X_IMR); /* flush write buffer */
++#endif
++}
++
++/* Disable the specified AR531X_MISC_IRQ interrupt */
++static void
++ar531x_misc_intr_disable(unsigned int irq)
++{
++ unsigned int imr;
++
++#if CONFIG_AR5315
++ imr = sysRegRead(AR5315_IMR);
++ switch(irq)
++ {
++ case AR531X_MISC_IRQ_TIMER:
++ imr &= (~IMR_TIMER);
++ break;
++
++ case AR531X_MISC_IRQ_AHB_PROC:
++ imr &= (~IMR_AHB);
++ break;
++
++ case AR531X_MISC_IRQ_AHB_DMA:
++ imr &= 0/* ?? */;
++ break;
++ /*
++ case AR531X_ISR_GPIO:
++ imr &= ~IMR_GPIO;
++ break;
++ */
++
++ case AR531X_MISC_IRQ_UART0:
++ imr &= (~IMR_UART0);
++ break;
++
++ case AR531X_MISC_IRQ_WATCHDOG:
++ imr &= (~IMR_WD);
++ break;
++
++ case AR531X_MISC_IRQ_LOCAL:
++ imr &= ~0/* ?? */;
++ break;
++
++ }
++ sysRegWrite(AR5315_IMR, imr);
++ sysRegRead(AR5315_IMR); /* flush write buffer */
++#else
++ imr = sysRegRead(AR531X_IMR);
++ imr &= ~(1 << (irq - AR531X_MISC_IRQ_BASE - 1));
++ sysRegWrite(AR531X_IMR, imr);
++ sysRegRead(AR531X_IMR); /* flush write buffer */
++#endif
++}
++
++static void
++ar531x_misc_intr_ack(unsigned int irq)
++{
++ ar531x_misc_intr_disable(irq);
++}
++
++static void
++ar531x_misc_intr_end(unsigned int irq)
++{
++ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
++ ar531x_misc_intr_enable(irq);
++}
++
++static void
++ar531x_misc_intr_set_affinity(unsigned int irq, unsigned long mask)
++{
++ /* Only 1 CPU; ignore affinity request */
++}
++
++struct hw_interrupt_type ar531x_misc_intr_controller = {
++ "AR531X MISC",
++ ar531x_misc_intr_startup,
++ ar531x_misc_intr_shutdown,
++ ar531x_misc_intr_enable,
++ ar531x_misc_intr_disable,
++ ar531x_misc_intr_ack,
++ ar531x_misc_intr_end,
++ ar531x_misc_intr_set_affinity,
++};
++
++int ar531x_misc_irq_base;
++
++/*
++ * Determine interrupt source among interrupts that use IP6
++ */
++void
++ar531x_misc_intr_init(int irq_base)
++{
++ int i;
++
++ for (i = irq_base; i < irq_base + AR531X_MISC_IRQ_COUNT; i++) {
++ irq_desc[i].status = IRQ_DISABLED;
++ irq_desc[i].action = NULL;
++ irq_desc[i].depth = 1;
++ irq_desc[i].handler = &ar531x_misc_intr_controller;
++ }
++
++ ar531x_misc_irq_base = irq_base;
++}
++
++/* ARGSUSED */
++void
++spurious_irq_handler(int cpl, void *dev_id, struct pt_regs *regs)
++{
++ /*
++ printk("spurious_irq_handler: %d cause=0x%8.8x status=0x%8.8x\n",
++ cpl, cause_intrs, status_intrs);
++ */
++}
++
++/* ARGSUSED */
++void
++spurious_misc_handler(int cpl, void *dev_id, struct pt_regs *regs)
++{
++ /*
++ printk("spurious_misc_handler: 0x%x isr=0x%8.8x imr=0x%8.8x\n",
++ cpl, ar531x_isr, ar531x_imr);
++ */
++}
++
++void
++ar531x_timer_handler(int cpl, void *dev_id, struct pt_regs *regs)
++{
++#if CONFIG_AR5315
++ (void)sysRegRead(AR5315_TIMER); /* clear interrupt */
++#else
++ (void)sysRegRead(AR531X_TIMER); /* clear interrupt */
++#endif
++}
++
++void
++ar531x_ahb_proc_handler(int cpl, void *dev_id, struct pt_regs *regs)
++{
++ u32 procAddr;
++ u32 proc1;
++ u32 dmaAddr;
++ u32 dma1;
++#if CONFIG_AR5315
++ sysRegWrite(AR5315_AHB_ERR0,AHB_ERROR_DET);
++ sysRegRead(AR5315_AHB_ERR1);
++#else
++ proc1 = sysRegRead(AR531X_PROC1);
++ procAddr = sysRegRead(AR531X_PROCADDR); /* clears error state */
++ dma1 = sysRegRead(AR531X_DMA1);
++ dmaAddr = sysRegRead(AR531X_DMAADDR); /* clears error state */
++#endif
++
++ printk("AHB interrupt: PROCADDR=0x%8.8x PROC1=0x%8.8x DMAADDR=0x%8.8x DMA1=0x%8.8x\n",
++ procAddr, proc1, dmaAddr, dma1);
++
++ machine_restart("AHB error"); /* Catastrophic failure */
++}
++
++static struct irqaction cascade =
++ {no_action, SA_INTERRUPT, 0, "cascade",
++ NULL, NULL};
++
++static struct irqaction spurious_irq =
++ {spurious_irq_handler, SA_INTERRUPT, 0, "spurious_irq",
++ NULL, NULL};
++
++static struct irqaction spurious_misc =
++ {spurious_misc_handler, SA_INTERRUPT, 0, "spurious_misc",
++ NULL, NULL};
++
++static struct irqaction ar531x_timer_interrupt =
++ {ar531x_timer_handler, SA_INTERRUPT, 0, "ar531x_timer_interrupt",
++ NULL, NULL};
++
++static struct irqaction ar531x_ahb_proc_interrupt =
++ {ar531x_ahb_proc_handler, SA_INTERRUPT, 0, "ar531x_ahb_proc_interrupt",
++ NULL, NULL};
++
++extern asmlinkage void ar531x_interrupt_receive(void);
++
++/*
++ * Called when an interrupt is received, this function
++ * determines exactly which interrupt it was, and it
++ * invokes the appropriate handler.
++ *
++ * Implicitly, we also define interrupt priority by
++ * choosing which to dispatch first.
++ */
++extern void dump_uart(void *);
++
++#if CONFIG_AR5315
++
++void
++ar531x_irq_dispatch(struct pt_regs *regs)
++{
++ int cause_intrs = regs->cp0_cause;
++ int status_intrs = regs->cp0_status;
++ int pending = cause_intrs & status_intrs;
++
++ if (pending & CAUSEF_IP3) {
++ do_IRQ(AR531X_IRQ_WLAN0_INTRS, regs);
++ }
++ else if (pending & CAUSEF_IP4) {
++ do_IRQ(AR531X_IRQ_ENET0_INTRS, regs);
++ }
++ else if (pending & CAUSEF_IP2) {
++ AR531X_REG ar531x_isr = sysRegRead(AR5315_ISR);
++ AR531X_REG ar531x_imr = sysRegRead(AR5315_IMR);
++ unsigned int ar531x_misc_intrs = ar531x_isr & ar531x_imr;
++
++ if (ar531x_misc_intrs & ISR_TIMER)
++ do_IRQ(AR531X_MISC_IRQ_TIMER, regs);
++ else if (ar531x_misc_intrs & ISR_AHB)
++ do_IRQ(AR531X_MISC_IRQ_AHB_PROC, regs);
++ else if (ar531x_misc_intrs & ISR_GPIO)
++ {
++ int i;
++ u32 gpioIntPending;
++
++ gpioIntPending = sysRegRead(AR5315_GPIO_DI) & gpioIntMask;
++ for (i=0; i<AR531X_GPIO_IRQ_COUNT; i++) {
++ if (gpioIntPending & (1 << i))
++ do_IRQ(AR531X_GPIO_IRQ(i), regs);
++ }
++ }
++ else if (ar531x_misc_intrs & ISR_UART0) {
++ do_IRQ(AR531X_MISC_IRQ_UART0, regs);
++#if CONFIG_KGDB
++ if (kgdbInterrupt()) {
++ if (!user_mode(regs))
++ set_async_breakpoint((unsigned long *)&regs->cp0_epc);
++ }
++#endif /* CONFIG_KGDB */
++ }
++ else if (ar531x_misc_intrs & ISR_WD)
++ do_IRQ(AR531X_MISC_IRQ_WATCHDOG, regs);
++ else
++ do_IRQ(AR531X_MISC_IRQ_NONE, regs);
++ } else if (pending & CAUSEF_IP7) {
++ do_IRQ(AR531X_IRQ_CPU_CLOCK, regs);
++ }
++ else {
++ do_IRQ(AR531X_IRQ_NONE, regs);
++ }
++}
++
++#else
++
++void
++ar531x_irq_dispatch(struct pt_regs *regs)
++{
++ int cause_intrs = regs->cp0_cause;
++ int status_intrs = regs->cp0_status;
++ int pending = cause_intrs & status_intrs;
++
++ if (pending & CAUSEF_IP2) {
++ do_IRQ(AR531X_IRQ_WLAN0_INTRS, regs);
++ }
++ else if (pending & CAUSEF_IP3) {
++ do_IRQ(AR531X_IRQ_ENET0_INTRS, regs);
++ }
++ else if (pending & CAUSEF_IP4) {
++ do_IRQ(AR531X_IRQ_ENET1_INTRS, regs);
++ }
++ else if (pending & CAUSEF_IP5) {
++ do_IRQ(AR531X_IRQ_WLAN1_INTRS, regs);
++ }
++ else if (pending & CAUSEF_IP6) {
++ AR531X_REG ar531x_isr = sysRegRead(AR531X_ISR);
++ AR531X_REG ar531x_imr = sysRegRead(AR531X_IMR);
++ unsigned int ar531x_misc_intrs = ar531x_isr & ar531x_imr;
++
++ if (ar531x_misc_intrs & AR531X_ISR_TIMER)
++ do_IRQ(AR531X_MISC_IRQ_TIMER, regs);
++ else if (ar531x_misc_intrs & AR531X_ISR_AHBPROC)
++ do_IRQ(AR531X_MISC_IRQ_AHB_PROC, regs);
++ else if (ar531x_misc_intrs & AR531X_ISR_AHBDMA)
++ do_IRQ(AR531X_MISC_IRQ_AHB_DMA, regs);
++ else if (ar531x_misc_intrs & AR531X_ISR_GPIO)
++ {
++ int i;
++ u32 gpioIntPending;
++
++ gpioIntPending = sysRegRead(AR531X_GPIO_DI) & gpioIntMask;
++ for (i=0; i<AR531X_GPIO_IRQ_COUNT; i++) {
++ if (gpioIntPending & (1 << i))
++ do_IRQ(AR531X_GPIO_IRQ(i), regs);
++ }
++ }
++ else if ((ar531x_misc_intrs & AR531X_ISR_UART0) ||
++ (ar531x_misc_intrs & AR531X_ISR_UART0DMA)) {
++ do_IRQ(AR531X_MISC_IRQ_UART0, regs);
++#if CONFIG_KGDB
++ if (kgdbInterrupt()) {
++ if (!user_mode(regs))
++ set_async_breakpoint((unsigned long *)&regs->cp0_epc);
++ }
++#endif /* CONFIG_KGDB */
++ }
++ else if (ar531x_misc_intrs & AR531X_ISR_WD)
++ do_IRQ(AR531X_MISC_IRQ_WATCHDOG, regs);
++ else if (ar531x_misc_intrs & AR531X_ISR_LOCAL)
++ do_IRQ(AR531X_MISC_IRQ_LOCAL, regs);
++ else
++ do_IRQ(AR531X_MISC_IRQ_NONE, regs);
++ } else if (pending & CAUSEF_IP7) {
++ do_IRQ(AR531X_IRQ_CPU_CLOCK, regs);
++ } else
++ do_IRQ(AR531X_IRQ_NONE, regs);
++}
++
++#endif
++
++void __init init_IRQ(void)
++{
++ init_generic_irq();
++ set_except_vector(0, ar531x_interrupt_receive);
++
++ /* Initialize interrupt controllers */
++ mips_cpu_irq_init(MIPS_CPU_IRQ_BASE);
++ ar531x_misc_intr_init(AR531X_MISC_IRQ_BASE);
++ ar531x_gpio_intr_init(AR531X_GPIO_IRQ_BASE);
++ setup_irq(AR531X_IRQ_MISC_INTRS, &cascade);
++ /*
++ * AR531X_IRQ_CPU_CLOCK is setup by ar531x_timer_setup.
++ */
++
++ /* Default "spurious interrupt" handlers */
++ setup_irq(AR531X_IRQ_NONE, &spurious_irq);
++ setup_irq(AR531X_MISC_IRQ_NONE, &spurious_misc);
++ setup_irq(AR531X_GPIO_IRQ_NONE, &spurious_gpio);
++#ifndef CONFIG_AR5315
++ setup_irq(AR531X_MISC_IRQ_TIMER, &ar531x_timer_interrupt);
++#endif
++ setup_irq(AR531X_MISC_IRQ_AHB_PROC, &ar531x_ahb_proc_interrupt);
++ setup_irq(AR531X_MISC_IRQ_GPIO, &cascade);
++
++#ifdef CONFIG_KGDB
++#if CONFIG_EARLY_STOP
++ kgdbInit();
++#endif
++#endif
++}
+diff -urN linux-mips/arch/mips/ar531x/ar531xksyms.c mips-linux-2.4.25/arch/mips/ar531x/ar531xksyms.c
+--- linux-mips/arch/mips/ar531x/ar531xksyms.c 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/ar531xksyms.c 2005-12-30 17:26:31.001823800 +0000
+@@ -0,0 +1,17 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++ */
++
++#include <linux/module.h>
++#include "asm/atheros/ar531xbsp.h"
++
++#ifdef CONFIG_KGDB
++EXPORT_SYMBOL(kgdbInit);
++EXPORT_SYMBOL(kgdbEnabled);
++#endif
++EXPORT_SYMBOL(ar531x_sys_frequency);
++EXPORT_SYMBOL(get_system_type);
+diff -urN linux-mips/arch/mips/ar531x/ar531xlnx.h mips-linux-2.4.25/arch/mips/ar531x/ar531xlnx.h
+--- linux-mips/arch/mips/ar531x/ar531xlnx.h 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/ar531xlnx.h 2005-12-30 17:26:31.001823800 +0000
+@@ -0,0 +1,135 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++ */
++
++/*
++ * This file contains definitions needed in order to compile
++ * AR531X products for linux. Definitions that are largely
++ * AR531X-specific and independent of operating system belong
++ * in ar531x.h rather than this file.
++ */
++#include "ar531x.h"
++
++#define MIPS_CPU_IRQ_BASE 0x00
++#define AR531X_HIGH_PRIO 0x10
++#define AR531X_MISC_IRQ_BASE 0x20
++#define AR531X_GPIO_IRQ_BASE 0x30
++
++/* Software's idea of interrupts handled by "CPU Interrupt Controller" */
++#if CONFIG_AR5315
++#define AR531X_IRQ_NONE MIPS_CPU_IRQ_BASE+0
++#define AR531X_IRQ_MISC_INTRS MIPS_CPU_IRQ_BASE+2 /* C0_CAUSE: 0x0400 */
++#define AR531X_IRQ_WLAN0_INTRS MIPS_CPU_IRQ_BASE+3 /* C0_CAUSE: 0x0800 */
++#define AR531X_IRQ_ENET0_INTRS MIPS_CPU_IRQ_BASE+4 /* C0_CAUSE: 0x1000 */
++#define AR531X_IRQ_LCBUS_PCI MIPS_CPU_IRQ_BASE+6 /* C0_CAUSE: 0x4000 */
++#define AR531X_IRQ_WLAN0_POLL MIPS_CPU_IRQ_BASE+6 /* C0_CAUSE: 0x4000 */
++#define AR531X_IRQ_CPU_CLOCK MIPS_CPU_IRQ_BASE+7 /* C0_CAUSE: 0x8000 */
++#else
++#define AR531X_IRQ_NONE MIPS_CPU_IRQ_BASE+0
++#define AR531X_IRQ_WLAN0_INTRS MIPS_CPU_IRQ_BASE+2 /* C0_CAUSE: 0x0400 */
++#define AR531X_IRQ_ENET0_INTRS MIPS_CPU_IRQ_BASE+3 /* C0_CAUSE: 0x0800 */
++#define AR531X_IRQ_ENET1_INTRS MIPS_CPU_IRQ_BASE+4 /* C0_CAUSE: 0x1000 */
++#define AR531X_IRQ_WLAN1_INTRS MIPS_CPU_IRQ_BASE+5 /* C0_CAUSE: 0x2000 */
++#define AR531X_IRQ_MISC_INTRS MIPS_CPU_IRQ_BASE+6 /* C0_CAUSE: 0x4000 */
++#define AR531X_IRQ_CPU_CLOCK MIPS_CPU_IRQ_BASE+7 /* C0_CAUSE: 0x8000 */
++#endif
++/* Miscellaneous interrupts, which share IP6 */
++#define AR531X_MISC_IRQ_NONE AR531X_MISC_IRQ_BASE+0
++#define AR531X_MISC_IRQ_TIMER AR531X_MISC_IRQ_BASE+1
++#define AR531X_MISC_IRQ_AHB_PROC AR531X_MISC_IRQ_BASE+2
++#define AR531X_MISC_IRQ_AHB_DMA AR531X_MISC_IRQ_BASE+3
++#define AR531X_MISC_IRQ_GPIO AR531X_MISC_IRQ_BASE+4
++#define AR531X_MISC_IRQ_UART0 AR531X_MISC_IRQ_BASE+5
++#define AR531X_MISC_IRQ_UART0_DMA AR531X_MISC_IRQ_BASE+6
++#define AR531X_MISC_IRQ_WATCHDOG AR531X_MISC_IRQ_BASE+7
++#define AR531X_MISC_IRQ_LOCAL AR531X_MISC_IRQ_BASE+8
++#define AR531X_MISC_IRQ_COUNT 9
++
++/* GPIO Interrupts [0..7], share AR531X_MISC_IRQ_GPIO */
++#define AR531X_GPIO_IRQ_NONE AR531X_MISC_IRQ_BASE+0
++#define AR531X_GPIO_IRQ(n) AR531X_MISC_IRQ_BASE+(n)+1
++#ifdef CONFIG_AR5315
++#define AR531X_GPIO_IRQ_COUNT 2
++#else
++#define AR531X_GPIO_IRQ_COUNT 9
++#endif
++
++#define PHYS_TO_K1(physaddr) KSEG1ADDR(physaddr)
++#define PHYS_TO_K0(physaddr) KSEG0ADDR(physaddr)
++#define UNMAPPED_TO_PHYS(vaddr) PHYSADDR(vaddr)
++#define IS_UNMAPPED_VADDR(vaddr) \
++ ((KSEGX(vaddr) == KSEG0) || (KSEGX(vaddr) == KSEG1))
++
++/* IOCTL commands for /proc/ar531x */
++#define AR531X_CTRL_DO_BREAKPOINT 1
++#define AR531X_CTRL_DO_MADWIFI 2
++
++/*
++ * Definitions for operating system portability.
++ * These are vxWorks-->Linux translations.
++ */
++#define LOCAL static
++#define BOOL int
++#define TRUE 1
++#define FALSE 0
++#define UINT8 u8
++#define UINT16 u16
++#define UINT32 u32
++#define PRINTF printk
++#if /* DEBUG */ 1
++#define DEBUG_PRINTF printk
++#define INLINE
++#else
++DEBUG_PRINTF while (0) printk
++#define INLINE inline
++#endif
++#define sysUDelay(usecs) udelay(usecs)
++#define sysMsDelay(msecs) mdelay(msecs)
++typedef volatile UINT8 *VIRT_ADDR;
++#define MALLOC(sz) kmalloc(sz, GFP_KERNEL)
++#define MALLOC_NOSLEEP(sz) kmalloc(sz, GFP_ATOMIC)
++#define FREE(ptr) kfree((void *)ptr)
++#define BSP_BUG() do { printk("kernel BSP BUG at %s:%d!\n", __FILE__, __LINE__); *(int *)0=0; } while (0)
++#define BSP_BUG_ON(condition) do { if (unlikely((condition)!=0)) BSP_BUG(); } while(0)
++#define ASSERT(x) BSP_BUG_ON(!(x))
++
++extern struct ar531x_boarddata *ar531x_board_configuration;
++extern char *ar531x_radio_configuration;
++extern char *enet_mac_address_get(int MACUnit);
++
++extern void kgdbInit(void);
++extern int kgdbEnabled(void);
++extern void breakpoint(void);
++extern int kgdbInterrupt(void);
++extern unsigned int ar531x_cpu_frequency(void);
++extern unsigned int ar531x_sys_frequency(void);
++
++/* GPIO support */
++extern struct irqaction spurious_gpio;
++extern unsigned int gpioIntMask;
++extern void ar531x_gpio_intr_init(int irq_base);
++extern void ar531x_gpio_ctrl_output(int gpio);
++extern void ar531x_gpio_ctrl_input(int gpio);
++extern void ar531x_gpio_set(int gpio, int val);
++extern int ar531x_gpio_get(int gpio);
++extern void ar531x_gpio_intr_enable(unsigned int irq);
++extern void ar531x_gpio_intr_disable(unsigned int irq);
++
++/* Watchdog Timer support */
++extern int watchdog_start(unsigned int milliseconds);
++extern int watchdog_stop(void);
++extern int watchdog_is_enabled(void);
++extern unsigned int watchdog_min_timer_reached(void);
++extern void watchdog_notify_alive(void);
++
++#define A_DATA_CACHE_INVAL(start, length) \
++ dma_cache_inv((UINT32)(start),(length))
++
++#define sysWbFlush() mb()
++
++#define intDisable(x) cli()
++#define intEnable(x) sti()
+diff -urN linux-mips/arch/mips/ar531x/ar531xprom.c mips-linux-2.4.25/arch/mips/ar531x/ar531xprom.c
+--- linux-mips/arch/mips/ar531x/ar531xprom.c 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/ar531xprom.c 2005-12-30 17:26:31.001823800 +0000
+@@ -0,0 +1,88 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright MontaVista Software Inc
++ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++ */
++
++/*
++ * Prom setup file for ar531x
++ */
++
++#include <linux/init.h>
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/bootmem.h>
++
++#include <asm/bootinfo.h>
++#include <asm/addrspace.h>
++
++#include "ar531xlnx.h"
++
++#define COMMAND_LINE_SIZE 512
++
++char arcs_cmdline[COMMAND_LINE_SIZE];
++
++void __init prom_init(int argc, char *argv[])
++{
++ int i;
++ unsigned int memcfg1;
++ int bank0AC, bank1AC;
++ int memsz_in_mb;
++ strcpy(arcs_cmdline, "console=ttyS0,9600");
++ for (i=0; i<argc; i++) {
++ strcat(arcs_cmdline, " ");
++ strcat(arcs_cmdline, argv[i]);
++ }
++
++ mips_machgroup = MACH_GROUP_AR531X;
++#ifdef CONFIG_APUNUSED
++ mips_machtype = MACH_ATHEROS_UNUSED;
++#endif
++#ifdef CONFIG_AP30
++ mips_machtype = MACH_ATHEROS_AP30;
++#endif
++#ifdef CONFIG_AP33
++ mips_machtype = MACH_ATHEROS_AP33;
++#endif
++#ifdef CONFIG_AP38
++ mips_machtype = MACH_ATHEROS_AP38;
++#endif
++#ifdef CONFIG_AP43
++ mips_machtype = MACH_ATHEROS_AP43;
++#endif
++#ifdef CONFIG_AP48
++ mips_machtype = MACH_ATHEROS_AP48;
++#endif
++#ifdef CONFIG_PB32
++ mips_machtype = MACH_ATHEROS_PB32;
++#endif
++
++
++ /* Determine SDRAM size based on Address Checks done at startup */
++#if CONFIG_AR5315
++ /* TO-DO : compute the SDRAM size */
++ memsz_in_mb=8;
++#else
++ memcfg1 = sysRegRead(AR531X_MEM_CFG1);
++ bank0AC = (memcfg1 & MEM_CFG1_AC0) >> MEM_CFG1_AC0_S;
++ bank1AC = (memcfg1 & MEM_CFG1_AC1) >> MEM_CFG1_AC1_S;
++ memsz_in_mb = (bank0AC ? (1 << (bank0AC+1)) : 0)
++ + (bank1AC ? (1 << (bank1AC+1)) : 0);
++#endif
++
++ /*
++ * By default, use all available memory. You can override this
++ * to use, say, 8MB by specifying "mem=8M" as an argument on the
++ * linux bootup command line.
++ */
++ add_memory_region(0, memsz_in_mb << 20, BOOT_MEM_RAM);
++}
++
++void __init prom_free_prom_memory(void)
++{
++}
+diff -urN linux-mips/arch/mips/ar531x/ar531xsetup.c mips-linux-2.4.25/arch/mips/ar531x/ar531xsetup.c
+--- linux-mips/arch/mips/ar531x/ar531xsetup.c 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/ar531xsetup.c 2005-12-30 17:26:31.002823648 +0000
+@@ -0,0 +1,406 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++ */
++
++/*
++ * Initialization for ar531x SOC.
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/serial.h>
++#include <linux/types.h>
++#include <linux/string.h>
++
++#include <asm/reboot.h>
++#include <asm/io.h>
++#include <asm/time.h>
++#include <asm/pgtable.h>
++#include <asm/processor.h>
++#include <asm/reboot.h>
++#include <asm/system.h>
++#include <asm/serial.h>
++
++#include "ar531xlnx.h"
++
++void
++ar531x_restart(char *command)
++{
++ for(;;) {
++#if CONFIG_AR5315
++ /*
++ ** Cold reset does not work,work around is to use the GPIO reset bit.
++ */
++ unsigned int reg;
++ reg = sysRegRead(AR5315_GPIO_DO);
++ reg &= ~(1 << AR5315_RESET_GPIO);
++ sysRegWrite(AR5315_GPIO_DO, reg);
++ (void)sysRegRead(AR5315_GPIO_DO); /* flush write to hardware */
++
++#else
++ sysRegWrite(AR531X_RESET, AR531X_RESET_SYSTEM);
++#endif
++ }
++}
++
++void
++ar531x_halt(void)
++{
++ printk(KERN_NOTICE "\n** You can safely turn off the power\n");
++ while (1);
++}
++
++void
++ar531x_power_off(void)
++{
++ ar531x_halt();
++}
++
++const char *
++get_system_type(void)
++{
++#if CONFIG_AR5315
++ return "Atheros AR5315";
++#else
++ return "Atheros AR531X";
++#endif
++}
++
++/*
++ * This table is indexed by bits 5..4 of the CLOCKCTL1 register
++ * to determine the predevisor value.
++ */
++static int CLOCKCTL1_PREDIVIDE_TABLE[4] = {
++ 1,
++ 2,
++ 4,
++ 5
++};
++
++#if CONFIG_AR5315
++static int PLLC_DIVIDE_TABLE[5] = {
++ 2,
++ 3,
++ 4,
++ 6,
++ 3
++};
++
++unsigned int
++ar531x_cpu_frequency(void)
++{
++ static unsigned int ar531x_calculated_cpu_freq=0;
++ unsigned int clockCtl,pllcCtrl,cpuDiv;
++ unsigned int pllcOut,refdiv,fdiv,divby2;
++
++ if(ar531x_calculated_cpu_freq)
++ return ar531x_calculated_cpu_freq;
++
++
++ pllcCtrl = sysRegRead(AR5315_PLLC_CTL);
++ refdiv = (pllcCtrl & PLLC_REF_DIV_M) >> PLLC_REF_DIV_S;
++ refdiv = CLOCKCTL1_PREDIVIDE_TABLE[refdiv];
++ fdiv = (pllcCtrl & PLLC_FDBACK_DIV_M) >> PLLC_FDBACK_DIV_S;
++ divby2 = (pllcCtrl & PLLC_ADD_FDBACK_DIV_M) >> PLLC_ADD_FDBACK_DIV_S;
++ divby2 += 1;
++ pllcOut = (40000000/refdiv)*(2*divby2)*fdiv;
++
++ clockCtl = sysRegRead(AR5315_CPUCLK);
++
++ /* clkm input selected */
++ if((clockCtl & CPUCLK_CLK_SEL_M) == 0 || (clockCtl & CPUCLK_CLK_SEL_M) == 1 ) {
++ unsigned int clkMdiv;
++ clkMdiv = (pllcCtrl & PLLC_CLKM_DIV_M) >> PLLC_CLKM_DIV_S;
++ clkMdiv = PLLC_DIVIDE_TABLE[clkMdiv];
++
++ cpuDiv = (clockCtl & CPUCLK_CLK_DIV_M) >> CPUCLK_CLK_DIV_S;
++ if(cpuDiv) cpuDiv *= 2;
++ else cpuDiv=1;
++
++ ar531x_calculated_cpu_freq= (pllcOut/(clkMdiv * cpuDiv)) ;
++
++ return ar531x_calculated_cpu_freq;
++ }
++
++ /* clkc input selected */
++ if((clockCtl & CPUCLK_CLK_SEL_M) == 2 ) {
++ unsigned int clkCdiv;
++ clkCdiv = (pllcCtrl & PLLC_CLKC_DIV_M) >> PLLC_CLKC_DIV_S;
++ clkCdiv = PLLC_DIVIDE_TABLE[clkCdiv];
++
++ cpuDiv = (clockCtl & CPUCLK_CLK_DIV_M) >> CPUCLK_CLK_DIV_S;
++ if(cpuDiv) cpuDiv *= 2;
++ else cpuDiv=1;
++
++ ar531x_calculated_cpu_freq= (pllcOut/(clkCdiv * cpuDiv)) ;
++
++ return ar531x_calculated_cpu_freq;
++ } else { /* ref_clk selected */
++
++ cpuDiv = (clockCtl & CPUCLK_CLK_DIV_M) >> CPUCLK_CLK_DIV_S;
++ if(cpuDiv) cpuDiv *= 2;
++ else cpuDiv=1;
++
++ ar531x_calculated_cpu_freq= (40000000/(cpuDiv)) ;
++ return ar531x_calculated_cpu_freq;
++ }
++}
++
++unsigned int
++ar531x_apb_frequency(void)
++{
++ static unsigned int ar531x_calculated_cpu_freq=0;
++ unsigned int clockCtl,pllcCtrl,cpuDiv;
++ unsigned int pllcOut,refdiv,fdiv,divby2;
++
++ if(ar531x_calculated_cpu_freq)
++ return ar531x_calculated_cpu_freq;
++
++
++ pllcCtrl = sysRegRead(AR5315_PLLC_CTL);
++ refdiv = (pllcCtrl & PLLC_REF_DIV_M) >> PLLC_REF_DIV_S;
++ refdiv = CLOCKCTL1_PREDIVIDE_TABLE[refdiv];
++ fdiv = (pllcCtrl & PLLC_FDBACK_DIV_M) >> PLLC_FDBACK_DIV_S;
++ divby2 = (pllcCtrl & PLLC_ADD_FDBACK_DIV_M) >> PLLC_ADD_FDBACK_DIV_S;
++ divby2 += 1;
++ pllcOut = (40000000/refdiv)*(2*divby2)*fdiv;
++
++ clockCtl = sysRegRead(AR5315_AMBACLK);
++
++ /* clkm input selected */
++ if((clockCtl & CPUCLK_CLK_SEL_M) == 0 || (clockCtl & CPUCLK_CLK_SEL_M) == 1 ) {
++ unsigned int clkMdiv;
++ clkMdiv = (pllcCtrl & PLLC_CLKM_DIV_M) >> PLLC_CLKM_DIV_S;
++ clkMdiv = PLLC_DIVIDE_TABLE[clkMdiv];
++
++ cpuDiv = (clockCtl & CPUCLK_CLK_DIV_M) >> CPUCLK_CLK_DIV_S;
++ if(cpuDiv) cpuDiv *= 2;
++ else cpuDiv=1;
++
++ ar531x_calculated_cpu_freq= (pllcOut/(clkMdiv * cpuDiv)) ;
++
++ return ar531x_calculated_cpu_freq;
++ }
++
++ /* clkc input selected */
++ if((clockCtl & CPUCLK_CLK_SEL_M) == 2 ) {
++ unsigned int clkCdiv;
++ clkCdiv = (pllcCtrl & PLLC_CLKC_DIV_M) >> PLLC_CLKC_DIV_S;
++ clkCdiv = PLLC_DIVIDE_TABLE[clkCdiv];
++
++ cpuDiv = (clockCtl & CPUCLK_CLK_DIV_M) >> CPUCLK_CLK_DIV_S;
++ if(cpuDiv) cpuDiv *= 2;
++ else cpuDiv=1;
++
++ ar531x_calculated_cpu_freq= (pllcOut/(clkCdiv * cpuDiv)) ;
++
++ return ar531x_calculated_cpu_freq;
++ } else { /* ref_clk selected */
++
++ cpuDiv = (clockCtl & CPUCLK_CLK_DIV_M) >> CPUCLK_CLK_DIV_S;
++ if(cpuDiv) cpuDiv *= 2;
++ else cpuDiv=1;
++
++ ar531x_calculated_cpu_freq= (40000000/(cpuDiv)) ;
++ return ar531x_calculated_cpu_freq;
++ }
++}
++
++#else
++unsigned int
++ar531x_cpu_frequency(void)
++{
++ static unsigned int ar531x_calculated_cpu_freq;
++ unsigned int clockctl1_predivide_mask;
++ unsigned int clockctl1_predivide_shift;
++ unsigned int clockctl1_multiplier_mask;
++ unsigned int clockctl1_multiplier_shift;
++ unsigned int clockctl1_doubler_mask;
++ int wisoc_revision;
++
++ /*
++ * Trust the bootrom's idea of cpu frequency.
++ */
++ ar531x_calculated_cpu_freq = sysRegRead(AR5312_SCRATCH);
++ if (ar531x_calculated_cpu_freq)
++ return ar531x_calculated_cpu_freq;
++
++ wisoc_revision = (sysRegRead(AR531X_REV) & AR531X_REV_MAJ) >> AR531X_REV_MAJ_S;
++
++ if (wisoc_revision == AR531X_REV_MAJ_AR2313) {
++ clockctl1_predivide_mask = AR2313_CLOCKCTL1_PREDIVIDE_MASK;
++ clockctl1_predivide_shift = AR2313_CLOCKCTL1_PREDIVIDE_SHIFT;
++ clockctl1_multiplier_mask = AR2313_CLOCKCTL1_MULTIPLIER_MASK;
++ clockctl1_multiplier_shift = AR2313_CLOCKCTL1_MULTIPLIER_SHIFT;
++ clockctl1_doubler_mask = AR2313_CLOCKCTL1_DOUBLER_MASK;
++ } else { /* AR5312 and AR2312 */
++ clockctl1_predivide_mask = AR5312_CLOCKCTL1_PREDIVIDE_MASK;
++ clockctl1_predivide_shift = AR5312_CLOCKCTL1_PREDIVIDE_SHIFT;
++ clockctl1_multiplier_mask = AR5312_CLOCKCTL1_MULTIPLIER_MASK;
++ clockctl1_multiplier_shift = AR5312_CLOCKCTL1_MULTIPLIER_SHIFT;
++ clockctl1_doubler_mask = AR5312_CLOCKCTL1_DOUBLER_MASK;
++ }
++
++ /*
++ * Clocking is derived from a fixed 40MHz input clock.
++ * cpuFreq = InputClock * MULT (where MULT is PLL multiplier)
++ *
++ * sysFreq = cpuFreq / 4 (used for APB clock, serial,
++ * flash, Timer, Watchdog Timer)
++ *
++ * cntFreq = cpuFreq / 2 (use for CPU count/compare)
++ *
++ * So, for example, with a PLL multiplier of 5, we have
++ * cpuFrez = 200MHz
++ * sysFreq = 50MHz
++ * cntFreq = 100MHz
++ *
++ * We compute the CPU frequency, based on PLL settings.
++ */
++ if (ar531x_calculated_cpu_freq == 0) {
++ unsigned int clockCtl1 = sysRegRead(AR5312_CLOCKCTL1);
++
++ int preDivideSelect = (clockCtl1 & clockctl1_predivide_mask) >>
++ clockctl1_predivide_shift;
++
++ int preDivisor = CLOCKCTL1_PREDIVIDE_TABLE[preDivideSelect];
++
++ int multiplier = (clockCtl1 & clockctl1_multiplier_mask) >>
++ clockctl1_multiplier_shift;
++
++ if (clockCtl1 & clockctl1_doubler_mask) {
++ multiplier = multiplier << 1;
++ }
++
++ ar531x_calculated_cpu_freq = (40000000 / preDivisor) * multiplier;
++ }
++
++ return ar531x_calculated_cpu_freq;
++}
++#endif
++
++unsigned int
++ar531x_sys_frequency(void)
++{
++ static unsigned int ar531x_calculated_sys_freq = 0;
++
++ if (ar531x_calculated_sys_freq == 0) {
++ ar531x_calculated_sys_freq = ar531x_cpu_frequency() / 4;
++ }
++
++ return ar531x_calculated_sys_freq;
++}
++
++static void __init
++flash_setup(void)
++{
++ UINT32 flash_ctl;
++#ifndef CONFIG_AR5315
++ /* Configure flash bank 0 */
++ flash_ctl = FLASHCTL_E |
++ FLASHCTL_AC_8M |
++ FLASHCTL_RBLE |
++ (0x01 << FLASHCTL_IDCY_S) |
++ (0x07 << FLASHCTL_WST1_S) |
++ (0x07 << FLASHCTL_WST2_S) |
++ (sysRegRead(AR531X_FLASHCTL0) & FLASHCTL_MW);
++
++ sysRegWrite(AR531X_FLASHCTL0, flash_ctl);
++
++ /* Disable other flash banks */
++ sysRegWrite(AR531X_FLASHCTL1,
++ sysRegRead(AR531X_FLASHCTL1) & ~(FLASHCTL_E | FLASHCTL_AC));
++
++ sysRegWrite(AR531X_FLASHCTL2,
++ sysRegRead(AR531X_FLASHCTL2) & ~(FLASHCTL_E | FLASHCTL_AC));
++#endif
++}
++
++
++
++void __init
++serial_setup(void)
++{
++ struct serial_struct s;
++
++ memset(&s, 0, sizeof(s));
++
++ s.flags = STD_COM_FLAGS;
++ s.io_type = SERIAL_IO_MEM;
++#if CONFIG_AR5315
++ s.baud_base = ar531x_apb_frequency()/16;
++#else
++ s.baud_base = ar531x_sys_frequency()/16;
++#endif
++ s.irq = AR531X_MISC_IRQ_UART0;
++ s.iomem_reg_shift = 2;
++#if CONFIG_AR5315
++ s.iomem_base = (u8 *)AR5315_UART0;
++#else
++ s.iomem_base = (u8 *)AR531X_UART0;
++#endif
++
++ if (early_serial_setup(&s) != 0)
++ printk(KERN_ERR "early_serial_setup failed\n");
++}
++
++extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
++static void __init
++ar531x_timer_setup(struct irqaction *irq)
++{
++ unsigned int count;
++
++ /* Usually irq is timer_irqaction (timer_interrupt) */
++ setup_irq(AR531X_IRQ_CPU_CLOCK, irq);
++
++ /* to generate the first CPU timer interrupt */
++ count = read_c0_count();
++ write_c0_compare(count + 1000);
++}
++
++extern void (*board_time_init)(void);
++
++static void __init
++ar531x_time_init(void)
++{
++ mips_hpt_frequency = ar531x_cpu_frequency() / 2;
++}
++
++void __init
++ar531x_setup(void)
++{
++ /* Clear any lingering AHB errors */
++#if CONFIG_AR5315
++ unsigned int config = read_c0_config();
++ write_c0_config(config & ~0x3);
++ sysRegWrite(AR5315_AHB_ERR0,AHB_ERROR_DET);
++ sysRegRead(AR5315_AHB_ERR1);
++ sysRegWrite(AR5315_WDC, WDC_IGNORE_EXPIRATION);
++#else
++ sysRegRead(AR531X_PROCADDR);
++ sysRegRead(AR531X_DMAADDR);
++
++ sysRegWrite(AR531X_WD_CTRL, AR531X_WD_CTRL_IGNORE_EXPIRATION);
++
++#endif
++
++ /* Disable data watchpoints */
++ write_c0_watchlo0(0);
++
++ board_time_init = ar531x_time_init;
++ board_timer_setup = ar531x_timer_setup;
++
++ _machine_restart = ar531x_restart;
++ _machine_halt = ar531x_halt;
++ _machine_power_off = ar531x_power_off;
++
++ flash_setup();
++ serial_setup();
++}
+diff -urN linux-mips/arch/mips/ar531x/Makefile mips-linux-2.4.25/arch/mips/ar531x/Makefile
+--- linux-mips/arch/mips/ar531x/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/Makefile 2005-12-30 17:26:29.912989328 +0000
+@@ -0,0 +1,33 @@
++#
++# This file is subject to the terms and conditions of the GNU General Public
++# License. See the file "COPYING" in the main directory of this archive
++# for more details.
++#
++# Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++#
++
++# Makefile for Atheros ar531x boards
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++
++.S.s:
++ $(CPP) $(CFLAGS) $< -o $*.s
++.S.o:
++ $(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $*.o
++
++O_TARGET:= ar531x.o
++
++export-objs = ar531xksyms.o
++
++obj-y := ar531xdbg_io.o \
++ ar531xsetup.o \
++ ar531xprom.o \
++ ar531xirq.o \
++ ar531xintr.o \
++ ar531xgpio.o \
++ ar531xksyms.o
++
++include $(TOPDIR)/Rules.make
+diff -urN linux-mips/arch/mips/ar531x/README mips-linux-2.4.25/arch/mips/ar531x/README
+--- linux-mips/arch/mips/ar531x/README 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/README 2005-12-30 17:26:30.478903296 +0000
+@@ -0,0 +1,68 @@
++Basic information for the AR531X Board Support Package
++
++This directory contains the "LBSP" -- Linux Board Support Package --
++for Linux on the Atheros AR531X Wireless System-On-a-Chip. It is intended
++primarily as a building block for wireless products. At this time, the
++AR531X Linux BSP is experimental code, and is actively UNDER CONSTRUCTION.
++
++Some components that are supported by this LBSP along with a standard 2.4
++Linux MIPS kernel include
++ R4Kc CPU
++ instruction and data caches
++ SDRAM
++ flash (Macronix, AMD, STS, etc.)
++ 16550 serial port
++ ethernet MACs
++ ethernet PHY or PHY Switch (RealTek, Kendin, Marvell)
++ General-Purpose I/O pins
++ kernel debugging with kgdb
++
++This LBSP code does NOT include drivers for the wireless components of the
++chip/boards! Drivers for those components may be distributed separately.
++In particular, the MADWiFi project under SourceForge supports (not yet!)
++wireless functions on the AR531X chipset. See
++ http://www.sourceforge.net/projects/madwifi
++
++Files included in this BSP:
++ae531xlnx.c - Linux-specific portions of the ethernet driver
++ae531xmac.c - OS-independent AR531X ethernet MAC code
++ae531xmac.h - OS-independent AR531X ethernet MAC software definitions
++ae531xreg.h - OS-independent AR531X ethernet MAC hardware definitions
++ar531x.h - OS-independent AR531X system hardware definitions
++ar531xlnx.h - Linux-specific AR531X system definitions and externs
++defconfig-ar531x - Default Linux configuration file
++intr_recv.S - Linux interrupt "glue" code
++ar531xirq.c - Linux Interrupt Request management
++Makefile - Linux makefile
++mvPhy.c - OS-independent ethernet PHY code for Marvell Switch
++mvPhy.h - OS-independent ethernet PHY definitions for Marvell Switch
++ar531xprom.c - Linux prom "glue" code
++ar531xsetup.c - Linux startup code
++ar531xdbg_io.c - Support for kgdb-based debugging and for EARLY_PRINTK_HACK
++ar531xproc.c - Pseudo-device driver for /proc/ar531x device
++ar531xgpio.c - Support for General Purpose I/O pins
++ar531xwmacsl.c - Wireless MAC Support Layer
++
++Additional files, distributed with the BSP:
++README - This file
++README.BUILD - Instructions for building a linux kernel from source
++README.EXECUTE - Instructions for testing your linux kernel
++README.RAMDISK - Instructions for building a root ramdisk image
++
++ramdisk.gz - A binary ramdisk image, suitable for use with AR531X.
++DIFFS - Directory that contains "patch" files (See README.BUILD)
++
++
++There are several ways to boot a vmlinux image on an AR531X board:
++ -You can boot in over ethernet from the vxWorks bootrom, which is preloaded
++ on all Atheros boards
++ -You can use an ICE (e.g. VisionICE) to load the vmlinux image. You will
++ need appropriate register initialization (e.g. AP30.ini file)
++ -You can use the eCos RedBoot bootrom loader. This is a full-featured
++ bootrom which as been ported to AR531x. It can boot vmlinux over ethernet
++ or from flash. Source code is available from Atheros.
++
++Please send comments, corrections, complaints, criticisms, suggestions,
++enhancements, requests, or any other reasonable communications regarding
++this effort, to "linux@atheros.com". Your email will be received by a
++couple of engineers, and redirected as appropriate.
+diff -urN linux-mips/arch/mips/ar531x/README.BUILD mips-linux-2.4.25/arch/mips/ar531x/README.BUILD
+--- linux-mips/arch/mips/ar531x/README.BUILD 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/README.BUILD 2005-12-30 17:26:30.478903296 +0000
+@@ -0,0 +1,47 @@
++ How to BUILD a linux kernel for an AR531X system
++
++It is expected that you will build Linux on an existing Linux system, which
++has all of the standard Linux tools.
++
++01) Obtain a MIPS BigEndian ELF gcc-compatible toolchain. For example,
++ if you're cross-compiling on a x86 Linux system, you could use:
++ ftp://ftp.mips.com/pub/tools/software/sde-for-linux/sdelinux-5.01-4eb.i386.rpm
++
++02) Obtain the latest working MIPS Linux kernel
++ cvs -d :pserver:cvs@ftp.linux-mips.org:/home/cvs login (password "cvs")
++ cvs -d :pserver:cvs@ftp.linux-mips.org:/home/cvs co -r linux_2_4 linux
++
++ Now "cd linux". The remainder of these instructions assume
++ that you are in the linux directory.
++
++03) Place the contents of this directory at arch/mips/ar531x.
++
++04) Use the patch command to patch generic linux files according
++ to the DIFFS directory
++ for i in arch/mips/ar531x/DIFFS/*.diff
++ do
++ patch -p1 < $i
++ done
++ NOTE: This version of the AR531X Linux BSP was tested with
++ MIPS Linux 2.4.22 as of 11/14/03. If you use a different
++ (e.g. more recent) version of Linux source, you may need to
++ resolve some minor patch and compilation issues.
++
++05) Set up a RAMDISK image.
++ See the instructions in README.RAMDISK.
++
++06) Set up a linux configuration using ar531x/defconfig-ar531x.
++ cp arch/mips/ar531x/defconfig-ar531x .config
++ make oldconfig (answer all questions that are asked)
++ NOTE: For development/debug purposes, you may want to
++ enable CONFIG_RUNTIME_DEBUG and CONFIG_KGDB.
++
++07) Make dependencies.
++ make dep
++
++08) Build the linux kernel
++ make
++
++09) The linux image you just built is in vmlinux.
++ See instructions in README.EXECUTE to run your vmlinux
++ image on an AP531X-based board.
+diff -urN linux-mips/arch/mips/ar531x/README.EXECUTE mips-linux-2.4.25/arch/mips/ar531x/README.EXECUTE
+--- linux-mips/arch/mips/ar531x/README.EXECUTE 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/README.EXECUTE 2005-12-30 17:26:30.479903144 +0000
+@@ -0,0 +1,23 @@
++ How to EXECUTE a linux image on an AR531X system
++
++There are currently three ways to run you vmlinux image:
++ 1) Load it using the vxWorks bootrom that is supplied with the board.
++ You can load it over ethernet or from the TFFS file system, if you
++ have sufficient flash to store the image.
++ 2) Load it using an ICE (e.g. VisionICE).
++ 3) Use a bootrom loader, such as eCos RedBoot.
++
++After you have booted linux:
++ By default, the root filesystem on ramdisk is read-only.
++ To make it writable, use "mount -o remount w /".
++
++ The user-level commands are slightly non-standard, as they
++ are based on "busybox".
++
++ The "wget" command is included. You can use wget to fetch
++ files from any ftp server. So, for instance, you can fetch
++ a kernel module and then "insmod" it.
++
++Note that the standard source-level kernel debugger, kgdb, works well
++over the serial line with this port. We use kgdb and the kgdb_demux perl
++script -- available over the www -- for debugging.
+diff -urN linux-mips/arch/mips/ar531x/README.VERSION mips-linux-2.4.25/arch/mips/ar531x/README.VERSION
+--- linux-mips/arch/mips/ar531x/README.VERSION 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/arch/mips/ar531x/README.VERSION 2005-12-30 17:26:30.479903144 +0000
+@@ -0,0 +1 @@
++Source release last modified: 12/16/03
+diff -urN linux-mips/arch/mips/config-shared.in mips-linux-2.4.25/arch/mips/config-shared.in
+--- linux-mips/arch/mips/config-shared.in 2005-12-24 15:11:15.963885864 +0000
++++ mips-linux-2.4.25/arch/mips/config-shared.in 2005-12-30 17:26:31.611731080 +0000
+@@ -34,6 +34,7 @@
+ dep_bool 'Support for Alchemy PB1550 board' CONFIG_MIPS_PB1550 $CONFIG_MIPS32
+ dep_bool 'Support for Alchemy PB1200 board' CONFIG_MIPS_PB1200 $CONFIG_MIPS32
+ dep_bool 'Support for Alchemy Hydrogen3 board' CONFIG_MIPS_HYDROGEN3 $CONFIG_MIPS32
++dep_bool 'Support for Atheros AR5312/AR2312 WiSoC (EXPERIMENTAL)' CONFIG_AR531X $CONFIG_AR531X $CONFIG_EXPERIMENTAL
+ dep_bool 'Support for MyCable XXS1500 board' CONFIG_MIPS_XXS1500 $CONFIG_MIPS32
+ dep_bool 'Support for 4G Systems MTX-1 board' CONFIG_MIPS_MTX1 $CONFIG_MIPS32
+ dep_bool 'Support for Cogent CSB250 board' CONFIG_COGENT_CSB250 $CONFIG_MIPS32
+@@ -238,6 +239,63 @@
+ define_bool CONFIG_PC_KEYB y
+ define_bool CONFIG_OLD_TIME_C y
+ fi
++if [ "$CONFIG_AR531X" = "y" ]; then
++ define_bool CONFIG_IRQ_CPU y
++ define_bool CONFIG_CPU_R4X00 y
++ define_bool CONFIG_SERIAL y
++ define_bool CONFIG_NEW_IRQ y
++ define_bool CONFIG_NEW_TIME_C y
++ define_bool CONFIG_AR5312
++ define_bool CONFIG_NONCOHERENT_IO y
++ bool 'Enable early printk hack' CONFIG_EARLY_PRINTK_HACK
++ define_bool CONFIG_SCSI n
++ mainmenu_option next_comment
++ comment 'Board selection'
++ choice 'Board type' \
++ "UNKNOWN CONFIG_APUNKNOWN \
++ AP30 CONFIG_AP30 \
++ AP31 CONFIG_AP31 \
++ AP33 CONFIG_AP33 \
++ AP38 CONFIG_AP38 \
++ AP43 CONFIG_AP43 \
++ AP48 CONFIG_AP48 \
++ AP51 CONFIG_AP51 \
++ AP30-ASK CONFIG_AP30ASK" AP30
++ if [ "$CONFIG_AP30" = "y" -o "$CONFIG_AP30ASK" = "y" ]; then
++ define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 2
++ fi
++ if [ "$CONFIG_AP33" = "y" ]; then
++ define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 1
++ fi
++ if [ "$CONFIG_AP38" = "y" ]; then
++ define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 1
++ fi
++ if [ "$CONFIG_AP43" = "y" ]; then
++ define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 1
++ fi
++ if [ "$CONFIG_AP48" = "y" ]; then
++ define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 1
++ fi
++ if [ "$CONFIG_AP51" = "y" ]; then
++ define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 1
++ define_bool CONFIG_MTD_REDBOOT_PARTS y
++ define_bool CONFIG_AR5315 y
++ define_bool CONFIG_MTD_SPIFLASH y
++ define_bool CONFIG_MTD_CFI n
++ define_bool CONFIG_MTD_JEDECPROBE n
++ define_bool CONFIG_MTD_CFI_INTELEXT n
++ define_bool CONFIG_MTD_CFI_AMDSTD n
++ define_bool CONFIG_MTD_OBSOLETE_CHIPS n
++ define_bool CONFIG_MTD_AMDSTD n
++ define_bool CONFIG_MTD_JEDEC n
++ define_bool CONFIG_MTD_PHYSMAP n
++ fi
++ mainmenu_option next_comment
++ comment 'Flash Selection'
++ choice 'Flash Size' \
++ "2MB CONFIG_FLASH_2MB \
++ 4MB CONFIG_FLASH_4MB" 2MB
++fi
+ if [ "$CONFIG_CASIO_E55" = "y" ]; then
+ define_bool CONFIG_IRQ_CPU y
+ define_bool CONFIG_NEW_TIME_C y
+
+diff -urN linux-mips/arch/mips/kernel/setup.c mips-linux-2.4.25/arch/mips/kernel/setup.c
+--- linux-mips/arch/mips/kernel/setup.c 2005-12-24 15:11:16.188851664 +0000
++++ mips-linux-2.4.25/arch/mips/kernel/setup.c 2005-12-30 17:26:33.536438480 +0000
+@@ -496,6 +496,7 @@
+ void hp_setup(void);
+ void au1x00_setup(void);
+ void frame_info_init(void);
++ void ar531x_setup(void);
+
+ frame_info_init();
+ #if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE)
+@@ -693,6 +694,12 @@
+ pmc_yosemite_setup();
+ break;
+ #endif
++
++#ifdef CONFIG_AR531X
++ case MACH_GROUP_AR531X:
++ ar531x_setup();
++ break;
++#endif
+ default:
+ panic("Unsupported architecture");
+ }
+diff -urN linux-mips/arch/mips/Makefile mips-linux-2.4.25/arch/mips/Makefile
+--- linux-mips/arch/mips/Makefile 2005-12-24 15:11:15.903894984 +0000
++++ mips-linux-2.4.25/arch/mips/Makefile 2005-12-30 17:26:29.911989480 +0000
+@@ -701,6 +701,17 @@
+ LOADADDR += 0x80020000
+ endif
+
++ifdef CONFIG_AR531X
++SUBDIRS += arch/mips/ar531x
++LIBS += arch/mips/ar531x/ar531x.o
++ifdef CONFIG_AP51
++LOADADDR += 0x80041000
++else
++LOADADDR += 0x80002000
++endif
++
++endif
++
+ #
+ # Choosing incompatible machines durings configuration will result in
+ # error messages during linking. Select a default linkscript if
+diff -urN linux-mips/ath_version.mk mips-linux-2.4.25/ath_version.mk
+--- linux-mips/ath_version.mk 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/ath_version.mk 2005-12-30 17:27:00.579327336 +0000
+@@ -0,0 +1 @@
++EXTRAVERSION=-LSDK-5.0.0-RC5
+diff -urN linux-mips/drivers/char/serial.c mips-linux-2.4.25/drivers/char/serial.c
+--- linux-mips/drivers/char/serial.c 2005-12-24 15:11:21.796999096 +0000
++++ mips-linux-2.4.25/drivers/char/serial.c 2005-12-30 17:27:10.815771160 +0000
+@@ -3441,7 +3441,7 @@
+
+ static _INLINE_ void show_serial_version(void)
+ {
+- printk(KERN_INFO "%s version %s%s (%s) with%s", serial_name,
++ printk(KERN_INFO "%s version %s%s (%s) with%s\n", serial_name,
+ serial_version, LOCAL_VERSTRING, serial_revdate,
+ serial_options);
+ }
+@@ -5567,7 +5567,7 @@
+ printk(KERN_INFO"ttyS%02d%s at 0x%p (irq = %d) is a %s\n",
+ state->line + SERIAL_DEV_OFFSET,
+ (state->flags & ASYNC_FOURPORT) ? " FourPort" : "",
+- state->iomem_base, state->irq,
++ (void *)state->iomem_base, state->irq,
+ uart_config[state->type].name);
+ }
+ else {
+diff -urN linux-mips/drivers/mtd/chips/cfi_cmdset_0002.c mips-linux-2.4.25/drivers/mtd/chips/cfi_cmdset_0002.c
+--- linux-mips/drivers/mtd/chips/cfi_cmdset_0002.c 2005-12-24 15:11:25.102496584 +0000
++++ mips-linux-2.4.25/drivers/mtd/chips/cfi_cmdset_0002.c 2005-12-30 17:27:21.333172272 +0000
+@@ -511,7 +511,7 @@
+ or tells us why it failed. */
+ dq6 = CMD(1<<6);
+ dq5 = CMD(1<<5);
+- timeo = jiffies + (HZ/1000); /* setting timeout to 1ms for now */
++ timeo = jiffies + (HZ/1000) + 1; /* setting timeout to 1ms for now */
+
+ oldstatus = cfi_read(map, adr);
+ status = cfi_read(map, adr);
+@@ -536,16 +536,18 @@
+ if( (status & dq5) == dq5 ) {
+ /* When DQ5 raises, we must check once again
+ if DQ6 is toggling. If not, the erase has been
+- completed OK. If not, reset chip. */
++ completed OK. But if so, reset chip. */
+ oldstatus = cfi_read(map, adr);
+ status = cfi_read(map, adr);
+
+ if ( (oldstatus & 0x00FF) == (status & 0x00FF) ) {
++#if 0
+ printk(KERN_WARNING "Warning: DQ5 raised while program operation was in progress, however operation completed OK\n" );
++#endif
+ } else {
+ /* DQ5 is active so we can do a reset and stop the erase */
+ cfi_write(map, CMD(0xF0), chip->start);
+- printk(KERN_WARNING "Internal flash device timeout occurred or write operation was performed while flash was programming.\n" );
++ printk(KERN_WARNING "Internal flash device timeout pt A occurred or write operation was performed while flash was programming. timeout=%d\n",chip->word_write_time );
+ }
+ } else {
+ printk(KERN_WARNING "Waiting for write to complete timed out in do_write_oneword.");
+@@ -959,7 +961,7 @@
+ {
+ /* DQ5 is active so we can do a reset and stop the erase */
+ cfi_write(map, CMD(0xF0), chip->start);
+- printk( KERN_WARNING "Internal flash device timeout occured or write operation was performed while flash was erasing\n" );
++ printk( KERN_WARNING "Internal flash device timeout pt B occured or write operation was performed while flash was erasing\n" );
+ }
+ }
+ else
+diff -urN linux-mips/drivers/mtd/chips/cfi_probe.c mips-linux-2.4.25/drivers/mtd/chips/cfi_probe.c
+--- linux-mips/drivers/mtd/chips/cfi_probe.c 2005-12-24 15:11:25.103496432 +0000
++++ mips-linux-2.4.25/drivers/mtd/chips/cfi_probe.c 2005-12-30 17:27:21.507145824 +0000
+@@ -51,7 +51,7 @@
+ struct flchip *chips, struct cfi_private *cfi)
+ {
+ int i;
+-
++
+ if ((base + 0) >= map->size) {
+ printk(KERN_NOTICE
+ "Probe at base[0x00](0x%08lx) past the end of the map(0x%08lx)\n",
+@@ -221,12 +221,10 @@
+
+ static void print_cfi_ident(struct cfi_ident *cfip)
+ {
+-#if 0
+ if (cfip->qry[0] != 'Q' || cfip->qry[1] != 'R' || cfip->qry[2] != 'Y') {
+ printk("Invalid CFI ident structure.\n");
+ return;
+ }
+-#endif
+ printk("Primary Vendor Command Set: %4.4X (%s)\n", cfip->P_ID, vendorname(cfip->P_ID));
+ if (cfip->P_ADR)
+ printk("Primary Algorithm Table at %4.4X\n", cfip->P_ADR);
+diff -urN linux-mips/drivers/mtd/chips/jedec_probe.c mips-linux-2.4.25/drivers/mtd/chips/jedec_probe.c
+--- linux-mips/drivers/mtd/chips/jedec_probe.c 2005-12-24 15:11:25.126492936 +0000
++++ mips-linux-2.4.25/drivers/mtd/chips/jedec_probe.c 2005-12-30 17:27:21.532142024 +0000
+@@ -104,6 +104,7 @@
+ #define SST29LE512 0x003d
+ #define SST39LF800 0x2781
+ #define SST39LF160 0x2782
++#define SST39LF1601 0x234b
+ #define SST39LF512 0x00D4
+ #define SST39LF010 0x00D5
+ #define SST39LF020 0x00D6
+@@ -113,6 +114,8 @@
+ #define SST49LF030A 0x001C
+ #define SST49LF040A 0x0051
+ #define SST49LF080A 0x005B
++#define SST39VF3201 0x235B
++#define SST39VF3202 0x235A
+
+ /* Toshiba */
+ #define TC58FVT160 0x00C2
+@@ -900,7 +903,43 @@
+ NumEraseRegions: 1,
+ regions: {ERASEINFO(0x01000,256),
+ }
+- }
++ }, {
++ mfr_id: MANUFACTURER_SST,
++ dev_id: SST39LF160,
++ name: "SST 39LF160",
++ DevSize: SIZE_2MiB,
++ CmdSet: P_ID_AMD_STD,
++ NumEraseRegions: 1,
++ regions: {ERASEINFO(0x01000,512),
++ }
++ }, {
++ mfr_id: MANUFACTURER_SST,
++ dev_id: SST39LF1601,
++ name: "SST 39LF1601",
++ DevSize: SIZE_2MiB,
++ CmdSet: P_ID_AMD_STD,
++ NumEraseRegions: 1,
++ regions: {ERASEINFO(0x01000,512),
++ }
++ }, {
++ mfr_id: MANUFACTURER_SST,
++ dev_id: SST39VF3201,
++ name: "SST 39VF3201",
++ DevSize: SIZE_4MiB,
++ CmdSet: P_ID_AMD_STD,
++ NumEraseRegions: 1,
++ regions: {ERASEINFO(0x01000,1024),
++ }
++ }, {
++ mfr_id: MANUFACTURER_SST,
++ dev_id: SST39VF3202,
++ name: "SST 39VF3202",
++ DevSize: SIZE_4MiB,
++ CmdSet: P_ID_AMD_STD,
++ NumEraseRegions: 1,
++ regions: {ERASEINFO(0x01000,1024),
++ }
++ }
+ };
+
+
+@@ -967,6 +1006,35 @@
+ p_cfi->cfiq->DevSize = jedec_table[index].DevSize;
+ p_cfi->cfi_mode = CFI_MODE_JEDEC;
+
++ /*
++ * Add the following code to set the flash timing parameters.
++ * Maybe this is done in a table somwehere else? I can't find it.
++ */
++
++
++ switch(jedec_table[index].dev_id) {
++ case SST39VF3201:
++ case SST39VF3202:
++ p_cfi->cfiq->WordWriteTimeoutTyp = 3; /* 8 us */
++ p_cfi->cfiq->WordWriteTimeoutMax = 4; /* 16 us */
++ p_cfi->cfiq->BlockEraseTimeoutTyp = 15; /* Actually 18ms, max 25 */
++ p_cfi->cfiq->BlockEraseTimeoutMax = 15; /* Actually 25ms */
++ p_cfi->cfiq->ChipEraseTimeoutTyp = 16; /* Max is 50ms, typical is 40ms */
++ p_cfi->cfiq->ChipEraseTimeoutMax = 16;
++ break;
++ case SST39LF160:
++ case SST39LF1601:
++ p_cfi->cfiq->WordWriteTimeoutTyp = 4; /* 14 us */
++ p_cfi->cfiq->WordWriteTimeoutMax = 5; /* 20 us */
++ p_cfi->cfiq->BlockEraseTimeoutTyp = 15; /* Actually 18ms, max 25 */
++ p_cfi->cfiq->BlockEraseTimeoutMax = 15; /* Actually 25ms */
++ p_cfi->cfiq->ChipEraseTimeoutTyp = 17; /* Max is 70ms, typical is 40ms */
++ p_cfi->cfiq->ChipEraseTimeoutMax = 17;
++ break;
++ }
++
++
++
+ for (i=0; i<num_erase_regions; i++){
+ p_cfi->cfiq->EraseRegionInfo[i] = jedec_table[index].regions[i];
+ }
+diff -urN linux-mips/drivers/mtd/Config.in mips-linux-2.4.25/drivers/mtd/Config.in
+--- linux-mips/drivers/mtd/Config.in 2005-12-24 15:11:25.091498256 +0000
++++ mips-linux-2.4.25/drivers/mtd/Config.in 2005-12-30 17:27:21.182195224 +0000
+@@ -14,6 +14,9 @@
+ dep_tristate ' MTD partitioning support' CONFIG_MTD_PARTITIONS $CONFIG_MTD
+ dep_tristate ' MTD concatenating support' CONFIG_MTD_CONCAT $CONFIG_MTD
+ dep_tristate ' RedBoot partition table parsing' CONFIG_MTD_REDBOOT_PARTS $CONFIG_MTD_PARTITIONS
++ if [ "$CONFIG_MTD_END_RESERVED" != "" ]; then
++ define_int CONFIG_MTD_END_RESERVED $CONFIG_MTD_END_RESERVED
++ fi
+ dep_tristate ' Command line partition table parsing' CONFIG_MTD_CMDLINE_PARTS $CONFIG_MTD_PARTITIONS
+ if [ "$CONFIG_ARM" = "y" ]; then
+ dep_tristate ' ARM Firmware Suite partition parsing' CONFIG_MTD_AFS_PARTS $CONFIG_MTD_PARTITIONS
+diff -urN linux-mips/drivers/mtd/devices/Makefile mips-linux-2.4.25/drivers/mtd/devices/Makefile
+--- linux-mips/drivers/mtd/devices/Makefile 2005-12-24 15:11:25.128492632 +0000
++++ mips-linux-2.4.25/drivers/mtd/devices/Makefile 2005-12-30 17:27:21.561137616 +0000
+@@ -22,5 +22,6 @@
+ obj-$(CONFIG_MTD_MTDRAM) += mtdram.o
+ obj-$(CONFIG_MTD_LART) += lart.o
+ obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o
++obj-$(CONFIG_MTD_SPIFLASH) += spiflash.o
+
+ include $(TOPDIR)/Rules.make
+diff -urN linux-mips/drivers/mtd/devices/spiflash.c mips-linux-2.4.25/drivers/mtd/devices/spiflash.c
+--- linux-mips/drivers/mtd/devices/spiflash.c 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/drivers/mtd/devices/spiflash.c 2005-12-30 17:27:21.652123784 +0000
+@@ -0,0 +1,506 @@
++
++/*
++ * MTD driver for the SPI Flash Memory support.
++ *
++ * $Id: //depot/sw/releases/linuxsrc/src/kernels/mips-linux-2.4.25/drivers/mtd/devices/spiflash.c#3 $
++ *
++ *
++ * Copyright (c) 2005-2006 Atheros Communications Inc.
++ *
++ * This code is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++
++/*===========================================================================
++** !!!! VERY IMPORTANT NOTICE !!!! FLASH DATA STORED IN LITTLE ENDIAN FORMAT
++**
++** This module contains the Serial Flash access routines for the Atheros SOC.
++** The Atheros SOC integrates a SPI flash controller that is used to access
++** serial flash parts. The SPI flash controller executes in "Little Endian"
++** mode. THEREFORE, all WRITES and READS from the MIPS CPU must be
++** BYTESWAPPED! The SPI Flash controller hardware by default performs READ
++** ONLY byteswapping when accessed via the SPI Flash Alias memory region
++** (Physical Address 0x0800_0000 - 0x0fff_ffff). The data stored in the
++** flash sectors is stored in "Little Endian" format.
++**
++** The spiflash_write() routine performs byteswapping on all write
++** operations.
++**===========================================================================*/
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/version.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#include <asm/delay.h>
++#include <asm/io.h>
++#include "spiflash.h"
++
++/* debugging */
++/* #define SPIFLASH_DEBUG */
++
++#ifndef __BIG_ENDIAN
++#error This driver currently only works with big endian CPU.
++#endif
++
++static char module_name[] = "spiflash";
++
++#define MIN(a,b) ((a) < (b) ? (a) : (b))
++#define FALSE 0
++#define TRUE 1
++
++#define ROOTFS_NAME "rootfs"
++
++static __u32 spiflash_regread32(int reg);
++static void spiflash_regwrite32(int reg, __u32 data);
++static __u32 spiflash_sendcmd (int op);
++
++int __init spiflash_init (void);
++void __exit spiflash_exit (void);
++static int spiflash_probe (void);
++static int spiflash_erase (struct mtd_info *mtd,struct erase_info *instr);
++static int spiflash_read (struct mtd_info *mtd, loff_t from,size_t len,size_t *retlen,u_char *buf);
++static int spiflash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen,const u_char *buf);
++
++/* Flash configuration table */
++struct flashconfig {
++ __u32 byte_cnt;
++ __u32 sector_cnt;
++ __u32 sector_size;
++ __u32 cs_addrmask;
++} flashconfig_tbl[MAX_FLASH] =
++ {
++ { 0, 0, 0, 0},
++ { STM_1MB_BYTE_COUNT, STM_1MB_SECTOR_COUNT, STM_1MB_SECTOR_SIZE, 0x0},
++ { STM_2MB_BYTE_COUNT, STM_2MB_SECTOR_COUNT, STM_2MB_SECTOR_SIZE, 0x0},
++ { STM_4MB_BYTE_COUNT, STM_4MB_SECTOR_COUNT, STM_4MB_SECTOR_SIZE, 0x0}
++ };
++
++/* Mapping of generic opcodes to STM serial flash opcodes */
++struct opcodes {
++ __u16 code;
++ __s8 tx_cnt;
++ __s8 rx_cnt;
++} stm_opcodes[] = {
++ {STM_OP_WR_ENABLE, 1, 0},
++ {STM_OP_WR_DISABLE, 1, 0},
++ {STM_OP_RD_STATUS, 1, 1},
++ {STM_OP_WR_STATUS, 1, 0},
++ {STM_OP_RD_DATA, 4, 4},
++ {STM_OP_FAST_RD_DATA, 1, 0},
++ {STM_OP_PAGE_PGRM, 8, 0},
++ {STM_OP_SECTOR_ERASE, 4, 0},
++ {STM_OP_BULK_ERASE, 1, 0},
++ {STM_OP_DEEP_PWRDOWN, 1, 0},
++ {STM_OP_RD_SIG, 4, 1}
++};
++
++/* Driver private data structure */
++struct spiflash_data {
++ struct mtd_info *mtd;
++ struct mtd_partition *parsed_parts; /* parsed partitions */
++ void *spiflash_readaddr; /* memory mapped data for read */
++ void *spiflash_mmraddr; /* memory mapped register space */
++};
++
++static struct spiflash_data *spidata;
++
++extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
++
++/***************************************************************************************************/
++
++static __u32
++spiflash_regread32(int reg)
++{
++ volatile __u32 *data = (__u32 *)(spidata->spiflash_mmraddr + reg);
++
++ return (*data);
++}
++
++static void
++spiflash_regwrite32(int reg, __u32 data)
++{
++ volatile __u32 *addr = (__u32 *)(spidata->spiflash_mmraddr + reg);
++
++ *addr = data;
++ return;
++}
++
++static __u32
++spiflash_sendcmd (int op)
++{
++ __u32 reg;
++ __u32 mask;
++ struct opcodes *ptr_opcode;
++
++ ptr_opcode = &stm_opcodes[op];
++
++ do {
++ reg = spiflash_regread32(SPI_FLASH_CTL);
++ } while (reg & SPI_CTL_BUSY);
++
++ spiflash_regwrite32(SPI_FLASH_OPCODE, ptr_opcode->code);
++
++ reg = (reg & ~SPI_CTL_TX_RX_CNT_MASK) | ptr_opcode->tx_cnt |
++ (ptr_opcode->rx_cnt << 4) | SPI_CTL_START;
++
++ spiflash_regwrite32(SPI_FLASH_CTL, reg);
++
++ if (ptr_opcode->rx_cnt > 0) {
++ do {
++ reg = spiflash_regread32(SPI_FLASH_CTL);
++ } while (reg & SPI_CTL_BUSY);
++
++ reg = (__u32) spiflash_regread32(SPI_FLASH_DATA);
++
++ switch (ptr_opcode->rx_cnt) {
++ case 1:
++ mask = 0x000000ff;
++ break;
++ case 2:
++ mask = 0x0000ffff;
++ break;
++ case 3:
++ mask = 0x00ffffff;
++ break;
++ default:
++ mask = 0xffffffff;
++ break;
++ }
++
++ reg &= mask;
++ }
++ else {
++ reg = 0;
++ }
++
++ return reg;
++}
++
++/* Probe SPI flash device
++ * Function returns 0 for failure.
++ * and flashconfig_tbl array index for success.
++ */
++static int
++spiflash_probe (void)
++{
++ __u32 sig;
++ int flash_size;
++
++ /* Read the signature on the flash device */
++ sig = spiflash_sendcmd(SPI_RD_SIG);
++
++ switch (sig) {
++ case STM_8MBIT_SIGNATURE:
++ flash_size = FLASH_1MB;
++ break;
++ case STM_16MBIT_SIGNATURE:
++ flash_size = FLASH_2MB;
++ break;
++ case STM_32MBIT_SIGNATURE:
++ flash_size = FLASH_4MB;
++ break;
++ default:
++ printk (KERN_WARNING "%s: Read of flash device signature failed!\n", module_name);
++ return (0);
++ }
++
++ return (flash_size);
++}
++
++
++static int
++spiflash_erase (struct mtd_info *mtd,struct erase_info *instr)
++{
++ struct opcodes *ptr_opcode;
++ __u32 temp, reg;
++ int finished = FALSE;
++
++#ifdef SPIFLASH_DEBUG
++ printk (KERN_DEBUG "%s(addr = 0x%.8x, len = %d)\n",__FUNCTION__,instr->addr,instr->len);
++#endif
++
++ /* sanity checks */
++ if (instr->addr + instr->len > mtd->size) return (-EINVAL);
++
++ ptr_opcode = &stm_opcodes[SPI_SECTOR_ERASE];
++
++ temp = ((__u32)instr->addr << 8) | (__u32)(ptr_opcode->code);
++ spiflash_sendcmd(SPI_WRITE_ENABLE);
++ do {
++ reg = spiflash_regread32(SPI_FLASH_CTL);
++ } while (reg & SPI_CTL_BUSY);
++
++ spiflash_regwrite32(SPI_FLASH_OPCODE, temp);
++
++ reg = (reg & ~SPI_CTL_TX_RX_CNT_MASK) | ptr_opcode->tx_cnt | SPI_CTL_START;
++ spiflash_regwrite32(SPI_FLASH_CTL, reg);
++
++ do {
++ reg = spiflash_sendcmd(SPI_RD_STATUS);
++ if (!(reg & SPI_STATUS_WIP)) {
++ finished = TRUE;
++ }
++ } while (!finished);
++
++ instr->state = MTD_ERASE_DONE;
++ if (instr->callback) instr->callback (instr);
++
++#ifdef SPIFLASH_DEBUG
++ printk (KERN_DEBUG "%s return\n",__FUNCTION__);
++#endif
++ return (0);
++}
++
++static int
++spiflash_read (struct mtd_info *mtd, loff_t from,size_t len,size_t *retlen,u_char *buf)
++{
++ u_char *read_addr;
++
++#ifdef SPIFLASH_DEBUG
++ printk (KERN_DEBUG "%s(from = 0x%.8x, len = %d)\n",__FUNCTION__,(__u32) from,(int)len);
++#endif
++
++ /* sanity checks */
++ if (!len) return (0);
++ if (from + len > mtd->size) return (-EINVAL);
++
++
++ /* we always read len bytes */
++ *retlen = len;
++
++ read_addr = (u_char *)(spidata->spiflash_readaddr + from);
++ memcpy(buf, read_addr, len);
++
++ return (0);
++}
++
++static int
++spiflash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen,const u_char *buf)
++{
++ int done = FALSE, page_offset, bytes_left, finished;
++ __u32 xact_len, spi_data = 0, opcode, reg;
++
++#ifdef SPIFLASH_DEBUG
++ printk (KERN_DEBUG "%s(to = 0x%.8x, len = %d)\n",__FUNCTION__,(__u32) to,len);
++#endif
++
++ *retlen = 0;
++
++ /* sanity checks */
++ if (!len) return (0);
++ if (to + len > mtd->size) return (-EINVAL);
++
++ opcode = stm_opcodes[SPI_PAGE_PROGRAM].code;
++ bytes_left = len;
++
++ while (done == FALSE) {
++ xact_len = MIN(bytes_left, sizeof(__u32));
++
++ /* 32-bit writes cannot span across a page boundary
++ * (256 bytes). This types of writes require two page
++ * program operations to handle it correctly. The STM part
++ * will write the overflow data to the beginning of the
++ * current page as opposed to the subsequent page.
++ */
++ page_offset = (to & (STM_PAGE_SIZE - 1)) + xact_len;
++
++ if (page_offset > STM_PAGE_SIZE) {
++ xact_len -= (page_offset - STM_PAGE_SIZE);
++ }
++
++ spiflash_sendcmd(SPI_WRITE_ENABLE);
++
++ do {
++ reg = spiflash_regread32(SPI_FLASH_CTL);
++ } while (reg & SPI_CTL_BUSY);
++
++ switch (xact_len) {
++ case 1:
++ (__u8)spi_data = *buf;
++ break;
++ case 2:
++ spi_data = (buf[1] << 8) | buf[0];
++ break;
++ case 3:
++ spi_data = (buf[2] << 16) | (buf[1] << 8) | buf[0];
++ break;
++ case 4:
++ spi_data = (buf[3] << 24) | (buf[2] << 16) |
++ (buf[1] << 8) | buf[0];
++ break;
++ default:
++ printk("spiflash_write: default case\n");
++ break;
++ }
++
++ spiflash_regwrite32(SPI_FLASH_DATA, spi_data);
++ opcode = (opcode & SPI_OPCODE_MASK) | ((__u32)to << 8);
++ spiflash_regwrite32(SPI_FLASH_OPCODE, opcode);
++
++ reg = (reg & ~SPI_CTL_TX_RX_CNT_MASK) | (xact_len + 4) | SPI_CTL_START;
++ spiflash_regwrite32(SPI_FLASH_CTL, reg);
++ finished = FALSE;
++
++ do {
++ udelay(1);
++ reg = spiflash_sendcmd(SPI_RD_STATUS);
++ if (!(reg & SPI_STATUS_WIP)) {
++ finished = TRUE;
++ }
++ } while (!finished);
++
++ bytes_left -= xact_len;
++ to += xact_len;
++ buf += xact_len;
++
++ *retlen += xact_len;
++
++ if (bytes_left == 0) {
++ done = TRUE;
++ }
++ }
++
++ return (0);
++}
++
++
++int __init
++spiflash_init (void)
++{
++ int result, i;
++ int index, num_parts;
++ struct mtd_info *mtd;
++ struct mtd_partition *mtd_parts;
++
++ spidata = kmalloc(sizeof(struct spiflash_data), GFP_KERNEL);
++ if (!spidata)
++ return (-ENXIO);
++
++ spidata->spiflash_mmraddr = ioremap_nocache(SPI_FLASH_MMR, SPI_FLASH_MMR_SIZE);
++ if (!spidata->spiflash_mmraddr) {
++ printk (KERN_WARNING "%s: Failed to map flash device\n", module_name);
++ kfree(spidata);
++ return (-ENXIO);
++ }
++
++ mtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
++ if (!mtd) {
++ kfree(spidata);
++ return (-ENXIO);
++ }
++
++ memset (mtd,0,sizeof (*mtd));
++
++ printk ("MTD driver for SPI flash.\n");
++ printk ("%s: Probing for Serial flash ...\n", module_name);
++ if (!(index = spiflash_probe ())) {
++ printk (KERN_WARNING "%s: Found no serial flash device\n", module_name);
++ kfree(mtd);
++ kfree(spidata);
++ return (-ENXIO);
++ }
++ printk ("%s: Found SPI serial Flash.\n", module_name);
++ printk ("%d: size\n", flashconfig_tbl[index].byte_cnt);
++
++ spidata->spiflash_readaddr = ioremap_nocache(SPI_FLASH_READ, flashconfig_tbl[index].byte_cnt);
++ if (!spidata->spiflash_readaddr) {
++ printk (KERN_WARNING "%s: Failed to map flash device\n", module_name);
++ kfree(mtd);
++ kfree(spidata);
++ return (-ENXIO);
++ }
++
++ mtd->name = module_name;
++ mtd->type = MTD_NORFLASH;
++ mtd->flags = (MTD_CAP_NORFLASH|MTD_WRITEABLE);
++ mtd->size = flashconfig_tbl[index].byte_cnt;
++ mtd->erasesize = flashconfig_tbl[index].sector_size;
++ mtd->numeraseregions = 0;
++ mtd->eraseregions = NULL;
++ mtd->module = THIS_MODULE;
++ mtd->erase = spiflash_erase;
++ mtd->read = spiflash_read;
++ mtd->write = spiflash_write;
++
++#ifdef SPIFLASH_DEBUG
++ printk (KERN_DEBUG
++ "mtd->name = %s\n"
++ "mtd->size = 0x%.8x (%uM)\n"
++ "mtd->erasesize = 0x%.8x (%uK)\n"
++ "mtd->numeraseregions = %d\n",
++ mtd->name,
++ mtd->size, mtd->size / (1024*1024),
++ mtd->erasesize, mtd->erasesize / 1024,
++ mtd->numeraseregions);
++
++ if (mtd->numeraseregions) {
++ for (result = 0; result < mtd->numeraseregions; result++) {
++ printk (KERN_DEBUG
++ "\n\n"
++ "mtd->eraseregions[%d].offset = 0x%.8x\n"
++ "mtd->eraseregions[%d].erasesize = 0x%.8x (%uK)\n"
++ "mtd->eraseregions[%d].numblocks = %d\n",
++ result,mtd->eraseregions[result].offset,
++ result,mtd->eraseregions[result].erasesize,mtd->eraseregions[result].erasesize / 1024,
++ result,mtd->eraseregions[result].numblocks);
++ }
++ }
++#endif
++
++#ifndef CONFIG_BLK_DEV_INITRD
++ /* parse redboot partitions */
++ num_parts = parse_redboot_partitions(mtd, &spidata->parsed_parts);
++
++#ifdef SPIFLASH_DEBUG
++ printk (KERN_DEBUG "Found %d redboot partitions\n", num_parts);
++#endif
++
++ if (num_parts) {
++ result = add_mtd_partitions(mtd, spidata->parsed_parts, num_parts);
++ /* Find root partition */
++ mtd_parts = spidata->parsed_parts;
++ for (i=0; i < num_parts; i++) {
++ if (!strcmp(mtd_parts[i].name, ROOTFS_NAME)) {
++ /* Create root device */
++ ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, i);
++ break;
++ }
++ }
++ } else {
++#ifdef SPIFLASH_DEBUG
++ printk (KERN_DEBUG "Did not find any redboot partitions\n");
++#endif
++ kfree(mtd);
++ kfree(spidata);
++ return (-ENXIO);
++ }
++#endif
++
++ spidata->mtd = mtd;
++
++ return (result);
++}
++
++void __exit
++spiflash_exit (void)
++{
++ if (spidata && spidata->parsed_parts) {
++ del_mtd_partitions (spidata->mtd);
++ kfree(spidata->mtd);
++ kfree(spidata);
++ }
++}
++
++module_init (spiflash_init);
++module_exit (spiflash_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Atheros Communications Inc");
++MODULE_DESCRIPTION("MTD driver for SPI Flash on Atheros SOC");
++
+diff -urN linux-mips/drivers/mtd/devices/spiflash.h mips-linux-2.4.25/drivers/mtd/devices/spiflash.h
+--- linux-mips/drivers/mtd/devices/spiflash.h 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/drivers/mtd/devices/spiflash.h 2005-12-30 17:27:21.652123784 +0000
+@@ -0,0 +1,113 @@
++/*
++ * SPI Flash Memory support header file.
++ *
++ * $Id: //depot/sw/releases/linuxsrc/src/kernels/mips-linux-2.4.25/drivers/mtd/devices/spiflash.h#3 $
++ *
++ *
++ * Copyright (c) 2005, Atheros Communications Inc.
++ *
++ * This code is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++#define FLASH_1MB 1
++#define FLASH_2MB 2
++#define FLASH_4MB 3
++#define MAX_FLASH 4
++
++#define STM_PAGE_SIZE 256
++
++#define STM_8MBIT_SIGNATURE 0x13
++#define STM_M25P80_BYTE_COUNT 1048576
++#define STM_M25P80_SECTOR_COUNT 16
++#define STM_M25P80_SECTOR_SIZE 0x10000
++
++#define STM_16MBIT_SIGNATURE 0x14
++#define STM_M25P16_BYTE_COUNT 2097152
++#define STM_M25P16_SECTOR_COUNT 32
++#define STM_M25P16_SECTOR_SIZE 0x10000
++
++#define STM_32MBIT_SIGNATURE 0x15
++#define STM_M25P32_BYTE_COUNT 4194304
++#define STM_M25P32_SECTOR_COUNT 64
++#define STM_M25P32_SECTOR_SIZE 0x10000
++
++#define STM_1MB_BYTE_COUNT STM_M25P80_BYTE_COUNT
++#define STM_1MB_SECTOR_COUNT STM_M25P80_SECTOR_COUNT
++#define STM_1MB_SECTOR_SIZE STM_M25P80_SECTOR_SIZE
++#define STM_2MB_BYTE_COUNT STM_M25P16_BYTE_COUNT
++#define STM_2MB_SECTOR_COUNT STM_M25P16_SECTOR_COUNT
++#define STM_2MB_SECTOR_SIZE STM_M25P16_SECTOR_SIZE
++#define STM_4MB_BYTE_COUNT STM_M25P32_BYTE_COUNT
++#define STM_4MB_SECTOR_COUNT STM_M25P32_SECTOR_COUNT
++#define STM_4MB_SECTOR_SIZE STM_M25P32_SECTOR_SIZE
++
++#define SPI_WRITE_ENABLE 0
++#define SPI_WRITE_DISABLE 1
++#define SPI_RD_STATUS 2
++#define SPI_WR_STATUS 3
++#define SPI_RD_DATA 4
++#define SPI_FAST_RD_DATA 5
++#define SPI_PAGE_PROGRAM 6
++#define SPI_SECTOR_ERASE 7
++#define SPI_BULK_ERASE 8
++#define SPI_DEEP_PWRDOWN 9
++#define SPI_RD_SIG 10
++#define SPI_MAX_OPCODES 11
++
++#define SFI_WRITE_BUFFER_SIZE 4
++#define SFI_FLASH_ADDR_MASK 0x00ffffff
++
++/*
++ * ST Microelectronics Opcodes for Serial Flash
++ */
++
++#define STM_OP_WR_ENABLE 0x06 /* Write Enable */
++#define STM_OP_WR_DISABLE 0x04 /* Write Disable */
++#define STM_OP_RD_STATUS 0x05 /* Read Status */
++#define STM_OP_WR_STATUS 0x01 /* Write Status */
++#define STM_OP_RD_DATA 0x03 /* Read Data */
++#define STM_OP_FAST_RD_DATA 0x0b /* Fast Read Data */
++#define STM_OP_PAGE_PGRM 0x02 /* Page Program */
++#define STM_OP_SECTOR_ERASE 0xd8 /* Sector Erase */
++#define STM_OP_BULK_ERASE 0xc7 /* Bulk Erase */
++#define STM_OP_DEEP_PWRDOWN 0xb9 /* Deep Power-Down Mode */
++#define STM_OP_RD_SIG 0xab /* Read Electronic Signature */
++
++#define STM_STATUS_WIP 0x01 /* Write-In-Progress */
++#define STM_STATUS_WEL 0x02 /* Write Enable Latch */
++#define STM_STATUS_BP0 0x04 /* Block Protect 0 */
++#define STM_STATUS_BP1 0x08 /* Block Protect 1 */
++#define STM_STATUS_BP2 0x10 /* Block Protect 2 */
++#define STM_STATUS_SRWD 0x80 /* Status Register Write Disable */
++
++/*
++ * SPI Flash Interface Registers
++ */
++#define AR531XPLUS_SPI_READ 0x1fc00000
++#define AR531XPLUS_SPI_MMR 0x11300000
++#define AR531XPLUS_SPI_MMR_SIZE 12
++
++#define AR531XPLUS_SPI_CTL 0x00
++#define AR531XPLUS_SPI_OPCODE 0x04
++#define AR531XPLUS_SPI_DATA 0x08
++
++#define SPI_FLASH_READ AR531XPLUS_SPI_READ
++#define SPI_FLASH_MMR AR531XPLUS_SPI_MMR
++#define SPI_FLASH_MMR_SIZE AR531XPLUS_SPI_MMR_SIZE
++#define SPI_FLASH_CTL AR531XPLUS_SPI_CTL
++#define SPI_FLASH_OPCODE AR531XPLUS_SPI_OPCODE
++#define SPI_FLASH_DATA AR531XPLUS_SPI_DATA
++
++#define SPI_CTL_START 0x00000100
++#define SPI_CTL_BUSY 0x00010000
++#define SPI_CTL_TXCNT_MASK 0x0000000f
++#define SPI_CTL_RXCNT_MASK 0x000000f0
++#define SPI_CTL_TX_RX_CNT_MASK 0x000000ff
++#define SPI_CTL_SIZE_MASK 0x00060000
++
++#define SPI_CTL_CLK_SEL_MASK 0x03000000
++#define SPI_OPCODE_MASK 0x000000ff
++
++#define SPI_STATUS_WIP STM_STATUS_WIP
+diff -urN linux-mips/drivers/mtd/maps/Config.in mips-linux-2.4.25/drivers/mtd/maps/Config.in
+--- linux-mips/drivers/mtd/maps/Config.in 2005-12-24 15:11:25.158488072 +0000
++++ mips-linux-2.4.25/drivers/mtd/maps/Config.in 2005-12-30 17:27:21.660122568 +0000
+@@ -9,7 +9,14 @@
+ dep_tristate ' CFI Flash device in physical memory map' CONFIG_MTD_PHYSMAP $CONFIG_MTD_GEN_PROBE
+ if [ "$CONFIG_MTD_PHYSMAP" = "y" -o "$CONFIG_MTD_PHYSMAP" = "m" ]; then
+ hex ' Physical start address of flash mapping' CONFIG_MTD_PHYSMAP_START 0x8000000
+- hex ' Physical length of flash mapping' CONFIG_MTD_PHYSMAP_LEN 0x4000000
++ if [ "$CONFIG_FLASH_2MB" = "y" ]; then
++ define_hex CONFIG_MTD_PHYSMAP_LEN 200000
++ fi
++ if [ "$CONFIG_FLASH_4MB" = "y" ]; then
++ define_hex CONFIG_MTD_PHYSMAP_LEN 400000
++ fi
++
++# hex ' Physical length of flash mapping' CONFIG_MTD_PHYSMAP_LEN 0x4000000
+ int ' Bus width in octets' CONFIG_MTD_PHYSMAP_BUSWIDTH 2
+ fi
+
+diff -urN linux-mips/drivers/mtd/maps/physmap.c mips-linux-2.4.25/drivers/mtd/maps/physmap.c
+--- linux-mips/drivers/mtd/maps/physmap.c 2005-12-24 15:11:25.217479104 +0000
++++ mips-linux-2.4.25/drivers/mtd/maps/physmap.c 2005-12-30 17:27:22.044064200 +0000
+@@ -80,12 +80,25 @@
+ };
+
+ #ifdef CONFIG_MTD_PARTITIONS
+-#ifdef CONFIG_MTD_CMDLINE_PARTS
++#if defined(CONFIG_MTD_CMDLINE_PARTS) || defined(CONFIG_MTD_REDBOOT_PARTS)
+ static struct mtd_partition *mtd_parts = 0;
+ static int mtd_parts_nb = 0;
+ #else
+ static struct mtd_partition physmap_partitions[] = {
+ /* Put your own partition definitions here */
++ {
++ name: "rootfs",
++#ifdef CONFIG_FLASH_2MB
++ size: 0x000e0000,
++ offset: 0x000f0000,
++#endif
++#ifdef CONFIG_FLASH_4MB
++ size: 0x002dd000,
++ offset: 0x00100000,
++#endif
++
++ /* Allow file system to be mounted for writing */
++ }
+ #if 0
+ {
+ name: "bootROM",
+@@ -138,6 +151,22 @@
+
+ add_mtd_device(mymtd);
+ #ifdef CONFIG_MTD_PARTITIONS
++#ifdef CONFIG_MTD_REDBOOT_PARTS
++ {
++ extern int parse_redboot_partitions(struct mtd_info *master,
++ struct mtd_partition **pparts);
++
++ struct mtd_partition *rb_parts = 0;
++ int rb_parts_nb = 0;
++
++ rb_parts_nb = parse_redboot_partitions(mymtd, &rb_parts);
++ if (rb_parts_nb > 0) {
++ printk(KERN_NOTICE
++ "Using redboot flash partitioning");
++ add_mtd_partitions (mymtd, rb_parts, rb_parts_nb);
++ }
++ }
++#endif
+ #ifdef CONFIG_MTD_CMDLINE_PARTS
+ mtd_parts_nb = parse_cmdline_partitions(mymtd, &mtd_parts,
+ "phys");
+@@ -147,7 +176,8 @@
+ "Using command line partition definition\n");
+ add_mtd_partitions (mymtd, mtd_parts, mtd_parts_nb);
+ }
+-#else
++#endif
++#if !defined(CONFIG_MTD_CMDLINE_PARTS) && !defined(CONFIG_MTD_REDBOOT_PARTS)
+ if (NUM_PARTITIONS != 0)
+ {
+ printk(KERN_NOTICE
+diff -urN linux-mips/drivers/mtd/redboot.c mips-linux-2.4.25/drivers/mtd/redboot.c
+--- linux-mips/drivers/mtd/redboot.c 2005-12-24 15:11:25.249474240 +0000
++++ mips-linux-2.4.25/drivers/mtd/redboot.c 2005-12-30 17:27:22.517992152 +0000
+@@ -51,8 +51,14 @@
+ return -ENOMEM;
+
+ /* Read the start of the last erase block */
+- ret = master->read(master, master->size - master->erasesize,
++ {
++ u_int32_t part_table_start = master->size - master->erasesize;
++#if defined(CONFIG_MTD_END_RESERVED)
++ part_table_start -= CONFIG_MTD_END_RESERVED;
++#endif
++ ret = master->read(master, part_table_start,
+ PAGE_SIZE, &retlen, (void *)buf);
++ }
+
+ if (ret)
+ goto out;
+diff -urN linux-mips/drivers/net/Config.in mips-linux-2.4.25/drivers/net/Config.in
+--- linux-mips/drivers/net/Config.in 2005-12-24 15:11:25.725401888 +0000
++++ mips-linux-2.4.25/drivers/net/Config.in 2005-12-30 17:27:22.684966768 +0000
+@@ -24,6 +24,18 @@
+ comment 'Ethernet (10 or 100Mbit)'
+ bool 'Ethernet (10 or 100Mbit)' CONFIG_NET_ETHERNET
+ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
++ define_bool CONFIG_VENETDEV n
++ tristate ' BUILT-IN ATHEROS ENET DRIVER' CONFIG_NET_ATHEROS_ETHER
++ if [ "$CONFIG_AP38" = "y" -o "$CONFIG_AP48" = "y" ]; then
++ define_bool CONFIG_KENDIN_ENET_PHY y
++ elif [ "$CONFIG_AP30ASK" = "y" ]; then
++ define_bool CONFIG_KENDIN_KS8995XA_ENET_PHY y
++ bool 'Multiple Ethernet address hack ' CONFIG_ASK_MULT_MAC_HACK
++ elif [ "$CONFIG_AP51" = "y" ]; then
++ define_bool CONFIG_ICPLUS_ENET_PHY y
++ else
++ define_bool CONFIG_MARVELL_ENET_PHY y
++ fi
+ if [ "$CONFIG_ARM" = "y" ]; then
+ dep_bool ' ARM EBSA110 AM79C961A support' CONFIG_ARM_AM79C961A $CONFIG_ARCH_EBSA110
+ tristate ' Cirrus Logic CS8900A support' CONFIG_ARM_CIRRUS
+diff -urN linux-mips/drivers/net/Makefile mips-linux-2.4.25/drivers/net/Makefile
+--- linux-mips/drivers/net/Makefile 2005-12-24 15:11:25.726401736 +0000
++++ mips-linux-2.4.25/drivers/net/Makefile 2005-12-30 17:27:22.709962968 +0000
+@@ -31,6 +31,10 @@
+ obj-y += e1000/e1000.o
+ endif
+
++ifeq ($(CONFIG_NET_ATHEROS_ETHER),y)
++ obj-y += ath/ae531x.o
++endif
++
+ ifeq ($(CONFIG_BONDING),y)
+ obj-y += bonding/bonding.o
+ endif
+@@ -53,8 +57,13 @@
+ subdir-$(CONFIG_SKFP) += skfp
+ subdir-$(CONFIG_E100) += e100
+ subdir-$(CONFIG_E1000) += e1000
++subdir-$(CONFIG_NET_ATHEROS_ETHER) += ath
+ subdir-$(CONFIG_BONDING) += bonding
+
++ifeq ($(CONFIG_ATHAP33),y)
++subdir-$(CONFIG_ATHAP33) += athap33
++endif
++
+ #
+ # link order important here
+ #
+@@ -242,6 +251,10 @@
+ obj-$(CONFIG_R8169) += r8169.o
+ obj-$(CONFIG_AMD8111_ETH) += amd8111e.o mii.o
+
++ifeq ($(CONFIG_ATHAP33),y)
++obj-$(CONFIG_ATHAP33) += athap33/ath_ap_mips.o
++endif
++
+ # non-drivers/net drivers who want mii lib
+ obj-$(CONFIG_PCMCIA_SMC91C92) += mii.o
+ obj-$(CONFIG_USB_USBNET) += mii.o
+diff -urN linux-mips/fs/jffs2/nodelist.h mips-linux-2.4.25/fs/jffs2/nodelist.h
+--- linux-mips/fs/jffs2/nodelist.h 2005-12-24 15:11:50.407649616 +0000
++++ mips-linux-2.4.25/fs/jffs2/nodelist.h 2005-12-30 17:27:51.289618200 +0000
+@@ -31,7 +31,7 @@
+ * provisions above, a recipient may use your version of this file
+ * under either the RHEPL or the GPL.
+ *
+- * $Id: nodelist.h,v 1.46.2.5 2003/11/02 13:54:20 dwmw2 Exp $
++ * $Id: //depot/sw/releases/linuxsrc/src/kernels/mips-linux-2.4.25/fs/jffs2/nodelist.h#3 $
+ *
+ */
+
+@@ -222,8 +222,8 @@
+ #define ALLOC_DELETION 1 /* Deletion node. Best to allow it */
+ #define ALLOC_GC 2 /* Space requested for GC. Give it or die */
+
+-#define JFFS2_RESERVED_BLOCKS_BASE 3 /* Number of free blocks there must be before we... */
+-#define JFFS2_RESERVED_BLOCKS_WRITE (JFFS2_RESERVED_BLOCKS_BASE + 2) /* ... allow a normal filesystem write */
++#define JFFS2_RESERVED_BLOCKS_BASE 2 /* Number of free blocks there must be before we... */
++#define JFFS2_RESERVED_BLOCKS_WRITE (JFFS2_RESERVED_BLOCKS_BASE + 1) /* ... allow a normal filesystem write */
+ #define JFFS2_RESERVED_BLOCKS_DELETION (JFFS2_RESERVED_BLOCKS_BASE + 1) /* ... allow a normal filesystem deletion */
+ #define JFFS2_RESERVED_BLOCKS_GCTRIGGER (JFFS2_RESERVED_BLOCKS_BASE + 3) /* ... wake up the GC thread */
+ #define JFFS2_RESERVED_BLOCKS_GCBAD (JFFS2_RESERVED_BLOCKS_BASE + 1) /* ... pick a block from the bad_list to GC */
+diff -urN linux-mips/fs/partitions/Config.in mips-linux-2.4.25/fs/partitions/Config.in
+--- linux-mips/fs/partitions/Config.in 2005-12-24 15:11:52.366351848 +0000
++++ mips-linux-2.4.25/fs/partitions/Config.in 2005-12-30 17:27:52.279467720 +0000
+@@ -39,7 +39,7 @@
+ fi
+ if [ "$CONFIG_AMIGA" != "y" -a "$CONFIG_ATARI" != "y" -a \
+ "$CONFIG_MAC" != "y" -a "$CONFIG_SGI_IP22" != "y" -a \
+- "$CONFIG_SGI_IP27" != "y" ]; then
++ "$CONFIG_SGI_IP27" != "y" -a "$CONFIG_AR531X" != "y" ]; then
+ define_bool CONFIG_MSDOS_PARTITION y
+ fi
+ if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_AFFS_FS" = "y" ]; then
+diff -urN linux-mips/include/asm-mips/atheros/ar531xbsp.h mips-linux-2.4.25/include/asm-mips/atheros/ar531xbsp.h
+--- linux-mips/include/asm-mips/atheros/ar531xbsp.h 1970-01-01 01:00:00.000000000 +0100
++++ mips-linux-2.4.25/include/asm-mips/atheros/ar531xbsp.h 2005-12-30 17:28:01.523062480 +0000
+@@ -0,0 +1,17 @@
++#ifndef __ASM_ATHEROS_BSP_SUPPORT_H
++#define __ASM_ATHEROS_BSP_SUPPORT_H
++/*
++ * These are definitions and functions provided by the bsp to support the
++ * AR5312 WiSoC running LSDK. For different BSP implementations, different
++ * BSP functions will be needed.
++ */
++
++extern unsigned int ar531x_sys_frequency(void);
++extern const char* get_system_type(void);
++
++#ifdef CONFIG_KGDB
++extern void kgdbInit(void);
++extern int kgdbEnabled(void);
++#endif
++
++#endif /* __ASM_ATHEROS_BSP_SUPPORT_H */
+diff -urN linux-mips/include/asm-mips/bootinfo.h mips-linux-2.4.25/include/asm-mips/bootinfo.h
+--- linux-mips/include/asm-mips/bootinfo.h 2005-12-24 15:12:00.645093288 +0000
++++ mips-linux-2.4.25/include/asm-mips/bootinfo.h 2005-12-30 17:28:01.534060808 +0000
+@@ -37,6 +37,7 @@
+ #define MACH_GROUP_HP_LJ 20 /* Hewlett Packard LaserJet */
+ #define MACH_GROUP_LASAT 21
+ #define MACH_GROUP_TITAN 22 /* PMC-Sierra Titan */
++#define MACH_GROUP_AR531X 23 /* Atheros AR531X */
+
+ /*
+ * Valid machtype values for group unknown (low order halfword of mips_machtype)
+@@ -198,6 +199,17 @@
+ */
+ #define MACH_TITAN_YOSEMITE 1 /* PMC-Sierra Yosemite */
+
++/*
++ * Valid machtype for group MACH_GROUP_AR5312
++ */
++#define MACH_ATHEROS_UNUSED 0
++#define MACH_ATHEROS_AP30 1 /* AP30 */
++#define MACH_ATHEROS_AP33 2 /* AP33 */
++#define MACH_ATHEROS_AP38 3 /* AP38 */
++#define MACH_ATHEROS_AP43 4 /* AP43 */
++#define MACH_ATHEROS_AP48 5 /* AP48 */
++#define MACH_ATHEROS_PB32 6 /* PB32 */
++
+ #define CL_SIZE (256)
+
+ const char *get_system_type(void);
+diff -urN linux-mips/include/asm-mips/page.h mips-linux-2.4.25/include/asm-mips/page.h
+--- linux-mips/include/asm-mips/page.h 2005-12-24 15:12:01.097024584 +0000
++++ mips-linux-2.4.25/include/asm-mips/page.h 2005-12-30 17:28:01.898005480 +0000
+@@ -13,7 +13,6 @@
+ #include <linux/config.h>
+ #include <asm/break.h>
+
+-#ifdef __KERNEL__
+
+ /*
+ * PAGE_SHIFT determines the page size
+@@ -30,6 +29,7 @@
+ #define PAGE_SIZE (1L << PAGE_SHIFT)
+ #define PAGE_MASK (~(PAGE_SIZE-1))
+
++#ifdef __KERNEL__
+ #ifndef __ASSEMBLY__
+
+ #include <asm/cacheflush.h>
+diff -urN linux-mips/include/asm-mips/serial.h mips-linux-2.4.25/include/asm-mips/serial.h
+--- linux-mips/include/asm-mips/serial.h 2005-12-24 15:12:01.130019568 +0000
++++ mips-linux-2.4.25/include/asm-mips/serial.h 2005-12-30 17:28:02.143968088 +0000
+@@ -410,6 +410,11 @@
+ #define DDB5477_SERIAL_PORT_DEFNS
+ #endif
+
++#if defined(CONFIG_AR531X)
++#undef RS_TABLE_SIZE
++#define RS_TABLE_SIZE 1
++#endif
++
+ #define SERIAL_PORT_DFNS \
+ ATLAS_SERIAL_PORT_DEFNS \
+ AU1000_SERIAL_PORT_DEFNS \
+diff -urN linux-mips/kernel/printk.c mips-linux-2.4.25/kernel/printk.c
+--- linux-mips/kernel/printk.c 2005-12-24 15:12:09.361768152 +0000
++++ mips-linux-2.4.25/kernel/printk.c 2005-12-30 17:28:11.943478336 +0000
+@@ -383,6 +383,18 @@
+ _call_console_drivers(start_print, end, msg_level);
+ }
+
++#if CONFIG_EARLY_PRINTK_HACK
++void putDebugChar(char byte);
++static void emit_log_char(char c)
++{
++ if (c == '\n') {
++ putDebugChar('\r');
++ putDebugChar('\n');
++ } else {
++ putDebugChar(c);
++ }
++}
++#else
+ static void emit_log_char(char c)
+ {
+ LOG_BUF(log_end) = c;
+@@ -394,6 +406,7 @@
+ if (logged_chars < LOG_BUF_LEN)
+ logged_chars++;
+ }
++#endif
+
+ /*
+ * This is printk. It can be called from any context. We want it to work.
+@@ -696,3 +709,4 @@
+ tty->driver.write(tty, 0, msg, strlen(msg));
+ return;
+ }
++
+diff -urN linux-mips-orig/drivers/net/ath/ae531x.h linux-mips-new/drivers/net/ath/ae531x.h
+--- linux-mips-orig/drivers/net/ath/ae531x.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/ae531x.h 2005-12-31 12:33:57.672538976 +0000
+@@ -0,0 +1,43 @@
++#ifndef __AE531X_H
++#define __AE531X_H
++
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/delay.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/init.h>
++#include <linux/skbuff.h>
++#include <asm/io.h>
++
++#include "ar531xlnx.h"
++#include "ae531xreg.h"
++#include "ae531xmac.h"
++
++extern void *ae531x_rxbuf_alloc(ae531x_MAC_t *MACInfo, char **rxBuffp,
++ int *rxBuffSizep);
++extern void ae531x_swptr_free(VIRT_ADDR desc);
++extern BOOL ae531x_twisted_enet(void);
++extern void ae531x_MiiWrite(UINT32 phyBase, UINT32 phyAddr, UINT8 reg,
++ UINT16 data);
++extern UINT16 ae531x_MiiRead(UINT32 phyBase, UINT32 phyAddr, UINT8 reg);
++extern void ae531x_unitLinkGained(int ethUnit);
++extern void ae531x_unitLinkLost(int ethUnit);
++extern void ae531x_WriteDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data);
++extern void ae531x_MACReset(ae531x_MAC_t *MACInfo);
++extern void ae531x_DisableComm(ae531x_MAC_t *MACInfo);
++extern void ae531x_FreeQueues(ae531x_MAC_t *MACInfo);
++extern void ae531x_reset(ae531x_MAC_t *MACInfo);
++extern int ae531x_AllocateQueues(ae531x_MAC_t *MACInfo);
++extern void ae531x_EnableComm(ae531x_MAC_t *MACInfo);
++extern void ae531x_DmaIntEnable(ae531x_MAC_t *MACInfo);
++extern void ae531x_DmaIntDisable(ae531x_MAC_t *MACInfo);
++extern void ae531x_DmaReset(ae531x_MAC_t *MACInfo);
++extern void ae531x_BeginResetMode(ae531x_MAC_t *MACInfo);
++extern void ae531x_AckIntr(ae531x_MAC_t *MACInfo, UINT32 data);
++extern void ae531x_SetDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
++extern BOOL ae531x_IsInResetMode(ae531x_MAC_t *MACInfo);
++extern UINT32 ae531x_ReadDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg);
++extern void ae531x_ClearDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
++
++#endif /* __AE531X_H */
+diff -urN linux-mips-orig/drivers/net/ath/ae531xlnx.c linux-mips-new/drivers/net/ath/ae531xlnx.c
+--- linux-mips-orig/drivers/net/ath/ae531xlnx.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/ae531xlnx.c 2005-12-31 12:33:57.673538824 +0000
+@@ -0,0 +1,1303 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++ */
++
++/*
++ * Ethernet driver for Atheros' ae531x ethernet MAC.
++ * This is a fairly generic driver, but it's intended
++ * for use in typical Atheros products.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/delay.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/init.h>
++#include <linux/skbuff.h>
++#include <asm/io.h>
++
++#include "ar531xlnx.h"
++#include "ae531xreg.h"
++#include "ae531xmac.h"
++#include "ae531x.h"
++
++#ifndef EXPORT_SYMTAB
++#define EXPORT_SYMTAB
++#endif
++
++#ifdef DEBUG
++void my_mvPhyShow(int ethUnit);
++#endif
++
++static struct ar531x_boarddata *ar531x_boardConfig=NULL;
++
++static char *radioConfig=NULL;
++
++#define AE531X_LAN_PORT 0
++#define AE531X_DEV_PER_MAC 1
++
++/*
++ * ae531x_MAC_state contains driver-specific linux-specific per-MAC information.
++ * The OSinfo member of ae531x_MAC_t points to one of these.
++ */
++typedef struct ae531x_MAC_state {
++ int irq;
++ struct tq_struct restart_task;
++ struct net_device_stats stats;
++ struct ae531x_dev_sw_state *dev_sw_state[AE531X_DEV_PER_MAC];
++ int primary_dev;
++ ae531x_MAC_t MACInfo; /* hardware state */
++} ae531x_MAC_state_t;
++
++/*
++ * ae531x_dev_sw_state contains driver-specific linux-specific per-device
++ * information. The net_device priv member points to one of these, and
++ * this structure contains a pointer to the associated MAC information.
++ */
++
++typedef struct ae531x_dev_sw_state {
++ int enetUnit; /* system unit number "eth%d" */
++ int unit_on_MAC; /* MAC-relative unit number */
++ struct net_device *dev;
++ ae531x_MAC_state_t *MAC_state; /* underlying MAC hw/sw state */
++} ae531x_dev_sw_state_t;
++
++/*
++ * Driver-independent linux-specific per-ethernet device software information.
++ */
++static struct net_device *ae531x_MAC_dev[AR531X_NUM_ENET_MAC * AE531X_DEV_PER_MAC];
++
++/* Driver-dependent per-MAC information */
++static ae531x_MAC_state_t per_MAC_info[AR531X_NUM_ENET_MAC];
++
++/*
++ * Receive buffers need enough room to hold the following:
++ * 1) a max MTU-sized packet.
++ * 2) space for an ethernet header
++ * 3) room at the beginning of the receive buffer in order
++ * to facilitate cooperating drivers that need to PREpend
++ * data.
++ * 4) Depending on configuration, we may need some additional
++ * room at the END of the rx buffer for phy-supplied
++ * trailers (if any). (c.f. CONFIG_VENETDEV)
++ *
++ * The DMA engine insists on 32-bit aligned RX buffers.
++ * TBDXXX: With current code, the IP stack ends up looking
++ * at misaligned headers with word operations. The misaligned
++ * reads are software-emulated via handle_adel_int. We'd
++ * rather align the buffers on a 16-bit boundary, but the
++ * DMA engine doesn't permit it???
++ */
++#define ETH_MAX_MTU 1518
++#define AE531X_RX_BUF_SIZE \
++ (((RXBUFF_RESERVE + ETH_HLEN + ETH_MAX_MTU + PHY_TRAILER_SIZE) + 3) & ~3)
++
++/* Forward references to local functions */
++static void ae531x_TxReap(ae531x_MAC_state_t *MAC_state);
++static int ae531x_phy_poll(void *data);
++static int ae531x_MAC_stop(struct net_device *dev);
++static int ae531x_MAC_open(struct net_device *dev);
++
++/*******************************************************************************
++* ae531x_MAC_poll checks for received packets, and sends data
++* up the stack.
++*/
++int
++ae531x_MAC_poll(struct net_device *dev, int *budget)
++{
++ struct sk_buff *skb;
++ struct sk_buff *newskb;
++ char *rxBufp;
++ int unused_length;
++ VIRT_ADDR rxDesc;
++ int length;
++ ae531x_dev_sw_state_t *dev_sw_state;
++ ae531x_MAC_state_t *MAC_state;
++ ae531x_MAC_t *MACInfo;
++ u32 cmdsts;
++ int rx_limit;
++ int rx_received;
++ int rxDescCount;
++ struct net_device *rxdev;
++ int early_stop;
++ int retval;
++#ifdef DEBUG
++ static int rxDescCountMax = 0;
++#endif
++
++ ARRIVE();
++
++ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
++ MAC_state = dev_sw_state->MAC_state;
++ MACInfo = &MAC_state->MACInfo;
++ rx_limit = MAC_state->dev_sw_state[MAC_state->primary_dev]->dev->quota;
++ rx_received = 0;
++
++ rxDescCount = 0;
++
++ early_stop = 0;
++ do {
++ ae531x_AckIntr(MACInfo, DmaIntRxCompleted);
++
++ for(;!early_stop;) {
++ rxDesc = MACInfo->rxQueue.curDescAddr;
++ cmdsts = AE531X_DESC_STATUS_GET(KSEG1ADDR(rxDesc));
++
++ AE531X_PRINT(AE531X_DEBUG_RX,
++ ("examine rxDesc %p with cmdsts=0x%x\n",
++ (void *)rxDesc, cmdsts));
++
++ if (cmdsts & DescOwnByDma) {
++ /* There's nothing left to process in the RX ring */
++ goto rx_all_done;
++ }
++
++ rxDescCount++;
++
++ AE531X_CONSUME_DESC((&MACInfo->rxQueue));
++
++ A_DATA_CACHE_INVAL(rxDesc, AE531X_DESC_SIZE);
++
++ /* Process a packet */
++ length = AE531X_DESC_STATUS_RX_SIZE(cmdsts) - ETH_CRC_LEN;
++ if ( (cmdsts & (DescRxFirst |DescRxLast | DescRxErrors)) ==
++ (DescRxFirst | DescRxLast) ) {
++ /* Descriptor status indicates "NO errors" */
++ skb = AE531X_DESC_SWPTR_GET(rxDesc);
++
++ /*
++ * Allocate a replacement skb.
++ * We want to get another buffer ready for Rx ASAP.
++ */
++ newskb = (struct sk_buff *)ae531x_rxbuf_alloc(MACInfo, &rxBufp, &unused_length);
++ if(newskb == NULL ) {
++ /*
++ * Give this descriptor back to the DMA engine,
++ * and drop the received packet.
++ */
++ MAC_state->stats.rx_dropped++;
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("Can't allocate new skb\n"));
++ } else {
++ AE531X_DESC_BUFPTR_SET(rxDesc, virt_to_bus(rxBufp));
++ AE531X_DESC_SWPTR_SET(rxDesc, newskb);
++ }
++
++ AE531X_DESC_STATUS_SET(rxDesc, DescOwnByDma);
++ rxDesc = NULL; /* sanity -- cannot use rxDesc now */
++ sysWbFlush();
++
++ if (newskb == NULL) {
++ retval = 1;
++ goto rx_no_skbs;
++ } else {
++ /* Sync data cache w.r.t. DMA */
++ A_DATA_CACHE_INVAL(skb->data, length);
++
++ rxdev = dev_sw_state->dev;
++
++ if (rxdev == NULL) {
++ /*
++ * We received a packet for a virtual enet device
++ * that is no longer up. Ignore it.
++ */
++ kfree_skb(skb);
++ continue;
++ }
++
++ /* Advance data pointer to show that there's data here */
++ skb_put(skb, length);
++ skb->protocol = eth_type_trans(skb, rxdev);
++ skb->dev = rxdev;
++ rxdev->last_rx = jiffies;
++ rxdev->quota--;
++
++ if (rx_limit-- < 0) {
++ early_stop=1;
++ /* We've done enough for now -- more later */
++ AE531X_PRINT(AE531X_DEBUG_RX_STOP,
++ ("Enet%d RX early stop. Quota=%d rxDescCount=%d budget=%d\n",
++ MACInfo->unit, dev->quota, rxDescCount, *budget));
++ }
++ rx_received++;
++
++ /* Send the data up the stack */
++ AE531X_PRINT(AE531X_DEBUG_RX,
++ ("Send data up stack: skb=%p data=%p length=%d\n",
++ (void *)skb, (void *)skb->data, length));
++
++ netif_receive_skb(skb);
++
++ MAC_state->stats.rx_packets++;
++ MAC_state->stats.rx_bytes += length;
++ }
++ } else {
++ /* Descriptor status indicates ERRORS */
++ MAC_state->stats.rx_errors++;
++
++ if (cmdsts & (DescRxRunt | DescRxLateColl)) {
++ MAC_state->stats.collisions++;
++ }
++
++ if (cmdsts & DescRxLengthError) {
++ MAC_state->stats.rx_length_errors++;
++ }
++
++ if (cmdsts & DescRxCrc) {
++ MAC_state->stats.rx_crc_errors++;
++ }
++
++ if (cmdsts & DescRxDribbling) {
++ MAC_state->stats.rx_frame_errors++;
++ }
++
++ AE531X_DESC_STATUS_SET(rxDesc, DescOwnByDma);
++
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("Bad receive. rxDesc=%p cmdsts=0x%8.8x\n",
++ (void *)rxDesc, cmdsts));
++ }
++ }
++ } while ((!early_stop) &&
++ ae531x_ReadDmaReg(MACInfo, DmaStatus) & DmaIntRxCompleted);
++
++rx_all_done:
++ AE531X_PRINT(AE531X_DEBUG_RX,
++ ("rx done (%d)\n", rxDescCount));
++ *budget -= rxDescCount;
++
++ if (!early_stop) {
++ netif_rx_complete(dev);
++
++ ae531x_SetDmaReg(MACInfo, DmaIntrEnb,
++ DmaIeRxCompleted | DmaIeRxNoBuffer);
++ ae531x_WriteDmaReg(MACInfo, DmaRxPollDemand, 0);
++ }
++
++ retval = early_stop;
++
++rx_no_skbs:
++
++ LEAVE();
++
++#ifdef DEBUG
++ if (rxDescCount > rxDescCountMax) {
++ printk("max rx %d\n", rxDescCount);
++ rxDescCountMax = rxDescCount;
++ }
++#endif
++
++ return retval;
++}
++
++/*******************************************************************************
++* ae531x_restart stops all ethernet devices associated with a physical MAC,
++* then shuts down the MAC. Then it re-opens all devices that were in use.
++* TBDXXX: needs testing!
++*/
++static void
++ae531x_restart(void *data)
++{
++ ae531x_MAC_t *MACInfo = (ae531x_MAC_t *)data;
++ ae531x_MAC_state_t *MAC_state = (ae531x_MAC_state_t *)MACInfo->OSinfo;
++ struct net_device *saved_dev[AE531X_DEV_PER_MAC];
++ int i;
++
++ for (i=0; i<AE531X_DEV_PER_MAC; i++) {
++ if ((saved_dev[i] = MAC_state->dev_sw_state[i]->dev) != NULL) {
++ ae531x_MAC_stop(saved_dev[i]);
++ }
++ }
++
++ for (i=0; i<AE531X_DEV_PER_MAC; i++) {
++ if (saved_dev[i])
++ ae531x_MAC_open(saved_dev[i]);
++ }
++}
++
++/*******************************************************************************
++* ae531x_MAC_intr handle interrupts from an ethernet MAC.
++* It checks MAC status registers, and dispatches as appropriate.
++*/
++void
++ae531x_MAC_intr(int cpl, void *dev_id, struct pt_regs *regs)
++{
++ ae531x_MAC_state_t *MAC_state;
++ ae531x_MAC_t *MACInfo;
++ u32 regIsr;
++ u32 regImr;
++ u32 pendIntrs;
++
++ ARRIVE();
++ MACInfo = (ae531x_MAC_t *)dev_id;
++ MAC_state = (ae531x_MAC_state_t *)MACInfo->OSinfo;
++ for(;;) {
++ /* Clear any unhandled intr causes. */
++ ae531x_WriteDmaReg(MACInfo, DmaStatus, UnhandledIntrMask);
++
++ regIsr = ae531x_ReadDmaReg(MACInfo, DmaStatus);
++ regImr = ae531x_ReadDmaReg(MACInfo, DmaIntrEnb);
++ pendIntrs = regIsr & regImr;
++
++ AE531X_PRINT(AE531X_DEBUG_INT,
++ ("ethmac%d: intIsr=0x%8.8x intImr=0x%8.8x pendIntrs=0x%8.8x\n",
++ MACInfo->unit, regIsr, regImr, pendIntrs ));
++
++ if ((pendIntrs & DmaAllIntCauseMask) == 0)
++ break;
++
++ if ((pendIntrs & DmaIntRxCompleted) ||
++ (pendIntrs & DmaIntRxNoBuffer)) {
++ if (netif_rx_schedule_prep(MAC_state->dev_sw_state[MAC_state->primary_dev]->dev)) {
++ ae531x_ClearDmaReg(MACInfo,
++ DmaIntrEnb,
++ DmaIeRxCompleted | DmaIeRxNoBuffer);
++ ae531x_AckIntr(MACInfo,
++ DmaIntRxCompleted | DmaIntRxNoBuffer);
++ (void)ae531x_ReadDmaReg(MACInfo, DmaIntrEnb);
++ __netif_rx_schedule(MAC_state->dev_sw_state[MAC_state->primary_dev]->dev);
++ } else {
++#if 0
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("%s: Interrupt (0x%8.8x/0x%8.8x) while in poll. regs@%p, pc=%p, ra=%p\n",
++ __FILE__,
++ regIsr,
++ ae531x_ReadDmaReg(MACInfo, DmaIntrEnb),
++ (void *)regs,
++ (void *)regs->cp0_epc,
++ (void *)regs->regs[31]));
++#endif
++ ae531x_AckIntr(MACInfo,
++ DmaIntRxCompleted | DmaIntRxNoBuffer);
++ }
++ }
++
++ if (pendIntrs &
++ (DmaIntTxStopped | DmaIntTxJabber | DmaIntTxUnderflow)) {
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("ethmac%d: TX Error Intr (0x%x)\n",
++ MACInfo->unit, pendIntrs));
++ ae531x_AckIntr(MACInfo,
++ (DmaIntTxStopped | DmaIntTxJabber | DmaIntTxUnderflow));
++ }
++
++ if (pendIntrs & DmaIntBusError) {
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("ethmac%d: DMA Bus Error Intr (0x%x)\n",
++ MACInfo->unit, pendIntrs));
++ ae531x_AckIntr(MACInfo, DmaIntBusError);
++ /* Reset the chip, if it's not already being done */
++ if (ae531x_IsInResetMode(MACInfo)) {
++ goto intr_done;
++ }
++ ae531x_BeginResetMode(MACInfo);
++ schedule_task(&MAC_state->restart_task);
++ }
++
++ if (pendIntrs & DmaIntRxStopped) {
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("ethmac%d: RX Stopped Intr (0x%x)\n",
++ MACInfo->unit, pendIntrs));
++ ae531x_AckIntr(MACInfo, DmaIntRxStopped);
++ }
++ }
++
++ intr_done:
++ LEAVE();
++}
++
++/*******************************************************************************
++* ae531x_MAC_get_stats returns statistics for a specified device
++*/
++static struct net_device_stats*
++ae531x_MAC_get_stats(struct net_device *dev)
++{
++ ae531x_dev_sw_state_t *dev_sw_state;
++ ae531x_MAC_state_t *MAC_state;
++
++ ARRIVE();
++ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
++ MAC_state = dev_sw_state->MAC_state;
++
++ LEAVE();
++ return &MAC_state->stats;
++}
++
++#define AE531X_PHY_POLL_SECONDS 2
++
++#if CONFIG_AR5315
++
++/*******************************************************************************
++* ae531x_getMACInfo returns the MACInfo of the interface given by unit
++*/
++ae531x_MAC_t *ae531x_getMAcInfo(int ethUnit)
++{
++ int i,j;
++ for(i=0;i<AR531X_NUM_ENET_MAC;++i) {
++ if(per_MAC_info[i].dev_sw_state) {
++ for(j=0;j<AE531X_DEV_PER_MAC;++j) {
++ if(per_MAC_info[i].dev_sw_state[j]
++ && per_MAC_info[i].dev_sw_state[j]->enetUnit == ethUnit)
++ return (&(per_MAC_info[i].MACInfo));
++ }
++ }
++ }
++ return NULL;
++}
++
++
++#endif
++
++/*******************************************************************************
++* ae531x_phy_poll periodically checks for changes in phy status
++* (e.g. dropped link).
++*/
++static int
++ae531x_phy_poll(void *data)
++{
++ ae531x_dev_sw_state_t *dev_sw_state = (ae531x_dev_sw_state_t *)data;
++ ae531x_MAC_t *MACInfo = &dev_sw_state->MAC_state->MACInfo;
++ int unit = dev_sw_state->enetUnit;
++
++ while(dev_sw_state->dev!=NULL) {
++ if (MACInfo->port_is_up) {
++ phyCheckStatusChange(unit);
++ }
++
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ schedule_timeout(AE531X_PHY_POLL_SECONDS * HZ);
++ }
++
++ return 0;
++}
++
++
++static char invalid_enet_MAC_addr[] = {0, 0, 0, 0, 0, 0};
++
++/*
++ * Fetch a pointer to an ethernet's MAC address
++ * in the Board Configuration data (in flash).
++ */
++char *
++ae531x_enet_mac_address_get(int MACUnit)
++{
++ /* XXX: Hack for poorly configured boards.
++ * Cannot setup bridging properly (brctl) when both enet
++ * interfaces share the same MAC address.
++ *
++ */
++
++#ifdef CONFIG_ASK_MULT_MAC_HACK
++ static u8 enet0Mac[6] = {0x00, 0x0d, 0x0b, 0x13, 0x6b, 0x16};
++ static u8 enet1Mac[6] = {0x00, 0x0d, 0x0b, 0x13, 0x6b, 0x17};
++#endif
++
++ if (!ar531x_boardConfig)
++ return invalid_enet_MAC_addr;
++ if (MACUnit == 0) {
++#ifndef CONFIG_ASK_MULT_MAC_HACK
++ return ar531x_boardConfig->enet0Mac;
++#else
++ return enet0Mac;
++#endif
++ }
++ if (MACUnit == 1) {
++#ifndef CONFIG_ASK_MULT_MAC_HACK
++ return ar531x_boardConfig->enet1Mac;
++#else
++ return enet1Mac;
++#endif
++ }
++ printk("Invalid ethernet MAC unit number (%d)!\n", MACUnit);
++ return invalid_enet_MAC_addr;
++}
++
++
++
++/*******************************************************************************
++* ae531x_MAC_open is the standard Linux open function. It puts
++* hardware into a known good state, allocates queues, starts
++* the phy polling task, and arranges for interrupts to be handled.
++*/
++static int
++ae531x_MAC_open(struct net_device *dev)
++{
++ ae531x_dev_sw_state_t *dev_sw_state;
++ ae531x_MAC_state_t *MAC_state;
++ ae531x_MAC_t *MACInfo;
++ u8 *MACAddr;
++ int rv;
++ struct tq_struct *restart_task;
++ pid_t phy_poll_pid;
++ ARRIVE();
++
++ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
++ dev_sw_state->dev = dev;
++ MAC_state = dev_sw_state->MAC_state;
++ MACInfo = &MAC_state->MACInfo;
++
++ restart_task = &MAC_state->restart_task;
++ restart_task->routine = ae531x_restart;
++ restart_task->data = (void *)MACInfo;
++
++ AE531X_PRINT(AE531X_DEBUG_RESET,
++ ("ae531x_MAC_open eth%d ethmac%d macBase=0x%x dmaBase=0x%x irq=0x%x\n",
++ dev_sw_state->enetUnit,
++ MACInfo->unit,
++ MACInfo->macBase,
++ MACInfo->dmaBase,
++ MAC_state->irq));
++
++ /* Default MAC address */
++ MACAddr = ae531x_enet_mac_address_get(MACInfo->unit);
++ memcpy(dev->dev_addr, MACAddr, dev->addr_len );
++
++ if (!MACInfo->port_is_up) {
++ /* Bring MAC and PHY out of reset */
++ ae531x_reset(MACInfo);
++
++ /* Attach interrupt handler */
++ rv = request_irq(MAC_state->irq, ae531x_MAC_intr, SA_INTERRUPT,
++ "ae531x_MAC_intr", (void *)MACInfo);
++ if (rv < 0) {
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("request_irq(0x%x) failed (%d)\n",
++ MAC_state->irq, rv));
++ goto open_failure;
++ }
++
++ /* Initialize PHY */
++ AE531X_PRINT(AE531X_DEBUG_RESET, ("\n --- phyBase: %08x\n", MACInfo->phyBase));
++ phySetup(MACInfo->unit, MACInfo->phyBase);
++
++ /* Start thread to poll for phy link status changes */
++ phy_poll_pid = kernel_thread(ae531x_phy_poll, dev_sw_state, 0);
++ if (phy_poll_pid < 0) {
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("ethmac%d unable to start Phy Poll thread\n",
++ MACInfo->unit));
++ }
++
++ /* Allocate RX/TX Queues */
++ if (ae531x_AllocateQueues(MACInfo) < 0) {
++ AE531X_PRINT(AE531X_DEBUG_RESET, ("Queue allocation failed"));
++ free_irq(MAC_state->irq, (void *)MACInfo);
++ goto open_failure;
++ }
++
++ /* Initialize DMA and descriptors */
++ ae531x_DmaReset(MACInfo);
++
++ /* Initialize MAC */
++ ae531x_MACReset(MACInfo);
++
++ /* Enable Receive/Transmit */
++ ae531x_EnableComm(MACInfo);
++
++ MAC_state->primary_dev = dev_sw_state->unit_on_MAC;
++ MACInfo->port_is_up = TRUE;
++ }
++
++ dev->trans_start = jiffies;
++ SET_MODULE_OWNER(dev);
++
++ LEAVE();
++ return 0;
++
++open_failure:
++ LEAVE();
++ return -1;
++}
++
++/*
++ * Shut down MAC hardware.
++ */
++static void
++ae531x_MAC_shutdown(ae531x_MAC_state_t *MAC_state)
++{
++ ae531x_MAC_t *MACInfo;
++
++ MACInfo = &MAC_state->MACInfo;
++ MACInfo->port_is_up = FALSE;
++
++ /* Disable Receive/Transmit */
++ ae531x_DisableComm(MACInfo);
++
++ /* Disable Interrupts */
++ ae531x_DmaIntDisable(MACInfo);
++ sysWbFlush();
++ free_irq(MAC_state->irq, (void *)MACInfo);
++
++ /* Free Transmit & Receive skb's/descriptors */
++ ae531x_TxReap(MAC_state); /* one last time */
++ ae531x_FreeQueues(MACInfo);
++}
++
++/*******************************************************************************
++* ae531x_MAC_stop is the standard Linux stop function. It undoes
++* everything set up by ae531x_MAC_open.
++*/
++static int
++ae531x_MAC_stop(struct net_device *dev)
++{
++ ae531x_dev_sw_state_t *dev_sw_state;
++ ae531x_MAC_state_t *MAC_state;
++ ae531x_MAC_t *MACInfo;
++ int i;
++
++ ARRIVE();
++
++ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
++ MAC_state = dev_sw_state->MAC_state;
++ MACInfo = &MAC_state->MACInfo;
++
++ for (i=0; i<AE531X_DEV_PER_MAC; i++) {
++ if ((MAC_state->dev_sw_state[i]->dev) &&
++ (MAC_state->dev_sw_state[i]->dev != dev_sw_state->dev)) {
++ break;
++ }
++ }
++
++ if (i < AE531X_DEV_PER_MAC) {
++ /* Physical MAC is still in use */
++ if (MAC_state->primary_dev == dev_sw_state->unit_on_MAC) {
++ /*
++ * If the primary_dev is being stopped
++ * then we need to assign a new one.
++ */
++ MAC_state->primary_dev = i;
++ }
++ } else {
++ /* Physical MAC is no longer in use */
++ ae531x_MAC_shutdown(MAC_state);
++ }
++
++ dev_sw_state->dev = NULL;
++ LEAVE();
++ return 0;
++}
++
++/*******************************************************************************
++* ae531x_rxbuf_alloc - Allocate an skb to be associated with an RX descriptor.
++*
++* RETURNS: A pointer to the skb. Also returns a pointer to the underlying
++* buffer and the size of that buffer.
++*/
++void *
++ae531x_rxbuf_alloc(ae531x_MAC_t *MACInfo, char **rxBuffp, int *rxBuffSizep)
++{
++ int buf_size;
++ struct sk_buff *skb;
++ char *rxBuff;
++ int rxBuffSize;
++
++ buf_size = AE531X_RX_BUF_SIZE;
++
++ skb = dev_alloc_skb(buf_size);
++ if (skb) {
++ /* skb->dev = dev; */
++ skb_reserve(skb, RXBUFF_RESERVE);
++
++ rxBuffSize = skb_tailroom(skb);
++ rxBuff = skb->tail;
++
++ *rxBuffp = rxBuff;
++ *rxBuffSizep = rxBuffSize;
++ }
++
++ return skb;
++}
++
++/*******************************************************************************
++* ae531x_swptr_free - Free the skb, if any, associated with a descriptor.
++*/
++void
++ae531x_swptr_free(VIRT_ADDR desc)
++{
++ struct sk_buff *skb;
++
++ skb = (struct sk_buff *)AE531X_DESC_SWPTR_GET(desc);
++ if (skb) {
++ AE531X_DESC_SWPTR_SET(desc, NULL);
++ kfree_skb(skb);
++ }
++}
++
++/*******************************************************************************
++*
++* ae531x_TxReap - the driver Tx completion routine.
++*
++* This routine reaps sk_buffs which have already been transmitted.
++*
++*/
++static void
++ae531x_TxReap(ae531x_MAC_state_t *MAC_state)
++{
++ AE531X_QUEUE *txq;
++ VIRT_ADDR txDesc;
++ UINT32 cmdsts;
++ struct sk_buff *skb;
++ int reaped;
++ ae531x_MAC_t *MACInfo;
++ static int aeUselessReap = 0;
++#ifdef DEBUG
++ static int aeMaxReap = 0;
++#endif
++ ARRIVE();
++
++ MACInfo = &MAC_state->MACInfo;
++ txq = &MACInfo->txQueue;
++ reaped = 0;
++
++ while (1) {
++
++ txDesc = AE531X_QUEUE_ELE_NEXT_GET(txq, txq->reapDescAddr);
++ if (txDesc == txq->curDescAddr) {
++ break;
++ }
++
++ cmdsts = AE531X_DESC_STATUS_GET(KSEG1ADDR(txDesc));
++ if (cmdsts & DescOwnByDma) {
++ break;
++ }
++
++ /* Release sk_buff associated with completed transmit */
++ skb = (struct sk_buff *)AE531X_DESC_SWPTR_GET(txDesc);
++ if (skb) {
++ kfree_skb(skb);
++ AE531X_DESC_SWPTR_SET(txDesc, NULL);
++ }
++
++ /* Update statistics according to completed transmit desc */
++ if (cmdsts & DescTxErrors) {
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("enetmac%d Tx prior error: 0x%8.8x <0x%8.8x> 0x%8.8x\n",
++ MACInfo->unit,
++ cmdsts,
++ DescTxErrors,
++ (int)txDesc));
++#ifdef DEBUG
++ //my_mvPhyShow(MACInfo->unit);
++ printk ("ae531xMacControl: 0x%08x\tMacFlowControl: 0x%08x\n",
++ ae531x_ReadMacReg(MACInfo, MacControl),
++ ae531x_ReadMacReg(MACInfo, MacFlowControl));
++#endif
++ MAC_state->stats.tx_errors++;
++ if (cmdsts & (DescTxLateCollision | DescTxExcCollisions)) {
++ MAC_state->stats.tx_aborted_errors++;
++ }
++ if (cmdsts & (DescTxLostCarrier | DescTxNoCarrier)) {
++ MAC_state->stats.tx_carrier_errors++;
++ }
++ } else {
++ MAC_state->stats.tx_bytes += AE531X_DESC_STATUS_RX_SIZE(cmdsts);
++ MAC_state->stats.tx_packets++;
++ }
++
++ MAC_state->stats.collisions +=
++ ((cmdsts & DescTxCollMask) >> DescTxCollShift);
++
++ txq->reapDescAddr = txDesc;
++ reaped++;
++ }
++
++ if (reaped > 0) {
++ int i;
++
++#ifdef DEBUG
++ if (reaped > aeMaxReap) {
++ aeMaxReap = reaped;
++ printk("max reaped = %d\n", reaped);
++ }
++#endif
++ AE531X_PRINT(AE531X_DEBUG_TX_REAP,
++ ("reaped %d\n", reaped));
++
++ /*
++ * Re-start transmit queues for all ethernet devices
++ * associated with this MAC.
++ */
++ for (i=0; i<AE531X_DEV_PER_MAC; i++) {
++ if (MAC_state->dev_sw_state[i]->dev)
++ netif_start_queue(MAC_state->dev_sw_state[i]->dev);
++ }
++ } else {
++ aeUselessReap++;
++ }
++
++ LEAVE();
++}
++
++
++/*******************************************************************************
++* ae531x_MAC_start_xmit sends a packet.
++*/
++static int
++ae531x_MAC_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++ ae531x_dev_sw_state_t *dev_sw_state;
++ ae531x_MAC_state_t *MAC_state;
++ ae531x_MAC_t *MACInfo;
++ u32 buf;
++ u32 ctrlen;
++ u32 length;
++ int mtu;
++ int max_buf_size;
++ VIRT_ADDR txDesc;
++
++ ARRIVE();
++
++ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
++ MAC_state = dev_sw_state->MAC_state;
++ MACInfo = &MAC_state->MACInfo;
++
++ length = skb->len;
++
++ /* Check if this port is up, else toss packet */
++ if (!MACInfo->port_is_up) {
++ buf = virt_to_bus(skb->data);
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("eth%d Tx Down, dropping buf=0x%8.8x, length=0x%8.8x, skb=%p\n",
++ dev_sw_state->enetUnit, buf, length, (void *)skb));
++
++ MAC_state->stats.tx_dropped++;
++ MAC_state->stats.tx_carrier_errors++;
++ goto dropFrame;
++ }
++
++ if (ae531x_IsInResetMode(MACInfo)) {
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("eth%d Tx: In Chip reset - drop frame\n",
++ dev_sw_state->enetUnit));
++
++ MAC_state->stats.tx_dropped++;
++ MAC_state->stats.tx_aborted_errors++;
++ goto dropFrame;
++ }
++
++ /* Check if we can transport this packet */
++ length = max((u32)60, length); /* total length */
++ mtu = dev->mtu;
++ max_buf_size = mtu + ETH_HLEN;
++ if (length > max_buf_size) {
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("eth%d Tx: length %d too long. mtu=%d, trailer=%d\n",
++ dev_sw_state->enetUnit, length, mtu, PHY_TRAILER_SIZE));
++
++ MAC_state->stats.tx_errors++;
++ MAC_state->stats.tx_aborted_errors++;
++
++ goto dropFrame;
++ }
++
++ /* Reap any old, completed Tx descriptors */
++ ae531x_TxReap(MAC_state);
++
++ txDesc = MACInfo->txQueue.curDescAddr;
++ if (txDesc == MACInfo->txQueue.reapDescAddr) {
++ int i;
++
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("eth%d Tx: cannot get txDesc\n",
++ dev_sw_state->enetUnit));
++
++ MAC_state->stats.tx_dropped++;
++ MAC_state->stats.tx_fifo_errors++;
++
++ /*
++ * Stop transmit queues for any ethernet devices
++ * associated with this MAC.
++ */
++#if 0 /* XXX: no way to recover from queue stop until ae531x_MAC_tx_timeout()
++ * is rewritten to avoid calls to shedule().
++ */
++ for (i=0; i<AE531X_DEV_PER_MAC; i++) {
++ if (MAC_state->dev_sw_state[i]->dev)
++ netif_stop_queue(MAC_state->dev_sw_state[i]->dev);
++ }
++#endif
++ goto dropFrame;
++ }
++
++ /* We won't fail now; so consume this descriptor */
++ AE531X_CONSUME_DESC((&MACInfo->txQueue));
++
++ /* Update the descriptor */
++ buf = virt_to_bus(skb->data);
++ AE531X_DESC_BUFPTR_SET(txDesc, buf);
++ AE531X_DESC_SWPTR_SET(txDesc, skb);
++ ctrlen = AE531X_DESC_CTRLEN_GET(txDesc);
++ ctrlen = (ctrlen & (DescEndOfRing)) |
++ DescTxFirst |
++ DescTxLast |
++ DescTxIntEnable;
++
++ ctrlen |= ((length << DescSize1Shift) & DescSize1Mask);
++
++ AE531X_DESC_CTRLEN_SET(txDesc, ctrlen);
++ AE531X_DESC_STATUS_SET(txDesc, DescOwnByDma);
++
++ /* Alert DMA engine to resume Tx */
++ ae531x_WriteDmaReg(MACInfo, DmaTxPollDemand, 0);
++ sysWbFlush();
++
++ AE531X_PRINT(AE531X_DEBUG_TX,
++ ("eth%d Tx: Desc=0x%8.8x, L=0x%8.8x, D=0x%8.8x, d=0x%8.8x, length=0x%8.8x\n",
++ dev_sw_state->enetUnit,
++ (UINT32)txDesc,
++ AE531X_DESC_CTRLEN_GET(txDesc),
++ buf,
++ AE531X_DESC_LNKBUF_GET(txDesc),
++ length));
++
++ /* Tell upper layers to keep it coming */
++ dev->trans_start = jiffies;
++
++ LEAVE();
++
++ return 0;
++
++dropFrame:
++ kfree_skb(skb);
++ LEAVE();
++ return 0;
++}
++
++
++/*******************************************************************************
++* ae531x_MAC_tx_timeout handles transmit timeouts
++*/
++static void
++ae531x_MAC_tx_timeout(struct net_device *dev)
++{
++ ae531x_dev_sw_state_t *dev_sw_state;
++ ae531x_MAC_state_t *MAC_state;
++ ae531x_MAC_t *MACInfo;
++
++ ARRIVE();
++
++ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
++ MAC_state = dev_sw_state->MAC_state;
++ MACInfo = &MAC_state->MACInfo;
++
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("enet%d: Tx timeout\n", dev_sw_state->enetUnit));
++
++ ae531x_restart(MACInfo);
++
++ LEAVE();
++}
++
++
++/*******************************************************************************
++* ae531x_MAC_do_ioctl is a placeholder for future ioctls.
++*/
++static int
++ae531x_MAC_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
++{
++ int rv;
++ ae531x_MAC_t *MACInfo;
++ struct ioctl_data {
++ u32 unit;
++ u32 addr;
++ u32 data;
++ } *req;
++ ae531x_dev_sw_state_t *dev_sw_state;
++ ae531x_MAC_state_t *MAC_state;
++
++ ARRIVE();
++
++ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
++ MAC_state = dev_sw_state->MAC_state;
++ MACInfo = &MAC_state->MACInfo;
++
++ req = (struct ioctl_data *)ifr->ifr_data;
++
++ switch( cmd ) {
++ default:
++ AE531X_PRINT(AE531X_DEBUG_ERROR,
++ ("Unsupported ioctl: 0x%x\n", cmd));
++ rv = -EOPNOTSUPP;
++ }
++
++ LEAVE();
++ return rv;
++}
++
++static void
++ae531x_MAC_setup_fntable(struct net_device *dev)
++{
++ ARRIVE();
++
++ dev->get_stats = ae531x_MAC_get_stats;
++ dev->open = ae531x_MAC_open;
++ dev->stop = ae531x_MAC_stop;
++ dev->hard_start_xmit = ae531x_MAC_start_xmit;
++ dev->do_ioctl = ae531x_MAC_do_ioctl;
++ dev->poll = ae531x_MAC_poll;
++ dev->weight = 16;
++#if 0 /* XXX: currently, ae531x_MAC_tx_timeout() will call functions
++ * that in turn call schedule(). this is BAD, since the
++ * timeout call runs at interrupt time. until ae531x_MAC_tx_timeout
++ * is rewritten to avoid schedule() calls, we do not use it.
++ */
++ dev->tx_timeout = ae531x_MAC_tx_timeout;
++#else
++ dev->tx_timeout = NULL;
++#endif
++ dev->features = NETIF_F_HW_CSUM |\
++ NETIF_F_HIGHDMA;
++
++ LEAVE();
++}
++
++static void
++ar5312EepromRead(char *EepromAddr, u_int16_t id, unsigned int off,
++ unsigned int nbytes, char *data)
++{
++ int i;
++
++ for (i=0; i<nbytes; i++, off++) {
++ data[i] = EepromAddr[off];
++ }
++}
++
++int
++ae531x_get_numMACs(void)
++{
++ int devid;
++ u16 radioMask;
++
++ /* Probe to find out the silicon revision and enable the
++ correct number of macs */
++ devid = ((u_int16_t) ((sysRegRead(AR531X_REV) >>8) &
++ (AR531X_REV_MAJ | AR531X_REV_MIN)));
++ switch (devid) {
++ case AR5212_AR5312_REV2:
++ case AR5212_AR5312_REV7:
++ /* Need to determine if we have a 5312 or a 2312 since they
++ have the same Silicon Rev ID*/
++ ar5312EepromRead(radioConfig,0,2*AR531X_RADIO_MASK_OFF,2,
++ (char *) &radioMask);
++ if ((radioMask & AR531X_RADIO0_MASK) != 0) {
++ return 2;
++ }
++ return 1;
++ case AR5212_AR2313_REV8:
++ return 1;
++ }
++
++ /* default to 1 */
++ return 1;
++}
++
++BOOL
++ae531x_twisted_enet(void)
++{
++ int wisoc_revision;
++
++ wisoc_revision = (sysRegRead(AR531X_REV) & AR531X_REV_MAJ) >> AR531X_REV_MAJ_S;
++ if ( (wisoc_revision == AR531X_REV_MAJ_AR2313) ||
++ /* next clause is used to determine AR2312, based on number of MACs.
++ * must do this since revision is same for 5312 and 2312.
++ */
++ (wisoc_revision == AR531X_REV_MAJ_AR5312 && ae531x_get_numMACs() == 1) ) {
++ return TRUE;
++ } else {
++ return FALSE;
++ }
++}
++
++int
++ae531x_get_board_config(void)
++{
++ int dataFound;
++ char *bd_config;
++
++ /*
++ * Find start of Board Configuration data, using heuristics:
++ * Search back from the (aliased) end of flash by 0x1000 bytes
++ * at a time until we find the string "5311", which marks the
++ * start of Board Configuration. Give up if we've searched
++ * more than 500KB.
++ */
++ dataFound = 0;
++ for (bd_config = (char *)0xbffff000;
++ bd_config > (char *)0xbff80000;
++ bd_config -= 0x1000)
++ {
++ if ( *(int *)bd_config == AR531X_BD_MAGIC) {
++ dataFound = 1;
++ break;
++ }
++ }
++
++ if (!dataFound) {
++ printk("Could not find Board Configuration Data\n");
++ bd_config = NULL;
++ }
++
++ ar531x_boardConfig = (struct ar531x_boarddata *) bd_config;
++
++ return(dataFound);
++}
++
++int
++ae531x_get_radio_config(void)
++{
++ int dataFound;
++ char *radio_config;
++
++ /*
++ * Now find the start of Radio Configuration data, using heuristics:
++ * Search forward from Board Configuration data by 0x1000 bytes
++ * at a time until we find non-0xffffffff.
++ */
++ dataFound = 0;
++ for (radio_config = ((char *) ar531x_boardConfig) + 0x1000;
++ radio_config < (char *)0xbffff000;
++ radio_config += 0x1000)
++ {
++ if (*(int *)radio_config != 0xffffffff) {
++ dataFound = 1;
++ break;
++ }
++ }
++
++ if (!dataFound) { /* AR2316 relocates radio config to new location */
++ dataFound = 0;
++ for (radio_config = ((char *) ar531x_boardConfig) + 0xf8;
++ radio_config < (char *)0xbffff0f8;
++ radio_config += 0x1000)
++ {
++ if (*(int *)radio_config != 0xffffffff) {
++ dataFound = 1;
++ break;
++ }
++ }
++ }
++
++ if (!dataFound) {
++ printk("Could not find Radio Configuration data\n");
++ radio_config = NULL;
++ }
++ radioConfig = radio_config;
++ return(dataFound);
++}
++
++static int __init
++ae531x_MAC_setup(void)
++{
++ int next_dev, i;
++ struct net_device *dev;
++ ae531x_dev_sw_state_t *dev_sw_state;
++ ae531x_MAC_state_t *MAC_state;
++ ae531x_MAC_t *MACInfo;
++ char *addr;
++
++ ARRIVE();
++
++ MOD_INC_USE_COUNT;
++ for (i=0;i<AR531X_NUM_ENET_MAC * AE531X_DEV_PER_MAC; i++) {
++ ae531x_MAC_dev[i] = NULL;
++ }
++
++ if (!ae531x_get_board_config()) {
++ LEAVE();
++ return -1;
++ }
++ if (!ae531x_get_radio_config()) {
++ LEAVE();
++ return(-1);
++ }
++ for(i=0, next_dev = AR531X_NUM_ENET_MAC-1;
++ i<ae531x_get_numMACs() && next_dev>=0;
++ i++, next_dev--){
++
++ /* if MAC is bogus in config data, skip */
++ addr = ae531x_enet_mac_address_get(next_dev);
++ if((*(u32 *)addr == 0xffffffff) && (*(u16 *)(addr+4)==0xffff)){
++ /* bogus MAC config data */
++ continue;
++ }
++
++ dev = ae531x_MAC_dev[next_dev] =
++ init_etherdev(NULL, sizeof(ae531x_dev_sw_state_t));
++
++ if (dev == NULL) {
++ LEAVE();
++ return -1;
++ }
++
++ ae531x_MAC_setup_fntable(dev);
++
++ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
++ dev_sw_state->enetUnit = next_dev;
++ dev_sw_state->unit_on_MAC = 0;
++ MAC_state = &per_MAC_info[next_dev];
++ dev_sw_state->MAC_state = MAC_state;
++ MAC_state->dev_sw_state[AE531X_LAN_PORT] = dev_sw_state;
++ MAC_state->primary_dev = -1;
++
++ /* Initialize per-MAC information */
++ MACInfo = &MAC_state->MACInfo;
++
++ MACInfo->unit = next_dev;
++
++ if (MACInfo->unit == 0) {
++ MACInfo->macBase = (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_MAC_OFFSET);
++ MACInfo->dmaBase = (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_DMA_OFFSET);
++ MACInfo->phyBase = (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET);
++ MAC_state->irq = AR531X_IRQ_ENET0_INTRS;
++ } else {
++#ifndef CONFIG_AR5315
++ MACInfo->macBase = (u32) (PHYS_TO_K1(AR531X_ENET1)+AE531X_MAC_OFFSET);
++ MACInfo->dmaBase = (u32) (PHYS_TO_K1(AR531X_ENET1)+AE531X_DMA_OFFSET);
++ if (ae531x_twisted_enet()) {
++ MACInfo->phyBase = (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET);
++ } else {
++ MACInfo->phyBase = (u32)(PHYS_TO_K1(AR531X_ENET1)+AE531X_PHY_OFFSET);
++ }
++ MAC_state->irq = AR531X_IRQ_ENET1_INTRS;
++#endif
++ }
++
++ MACInfo->OSinfo = (void *)MAC_state;
++
++ }
++
++ LEAVE();
++ return 0;
++}
++module_init(ae531x_MAC_setup);
++
++/*******************************************************************************
++* ae531x_MAC_unload is the module unload function
++*/
++static void __exit
++ae531x_MAC_unload(void)
++{
++ int i;
++
++ for (i=0;i<AR531X_NUM_ENET_MAC * AE531X_DEV_PER_MAC; i++) {
++ if (ae531x_MAC_dev[i] != NULL) {
++ if( (((ae531x_dev_sw_state_t *)ae531x_MAC_dev[i]->priv)->dev) != NULL)
++ ae531x_MAC_stop(ae531x_MAC_dev[i]);
++ ae531x_MAC_dev[i] = NULL;
++ }
++ }
++ MOD_DEC_USE_COUNT;
++}
++
++MODULE_AUTHOR("Atheros Communications, Inc.");
++MODULE_DESCRIPTION("Support for Atheros WiSoC Ethernet device");
++#ifdef MODULE_LICENSE
++MODULE_LICENSE("Atheros");
++#endif
++module_exit(ae531x_MAC_unload);
+diff -urN linux-mips-orig/drivers/net/ath/ae531xmac.c linux-mips-new/drivers/net/ath/ae531xmac.c
+--- linux-mips-orig/drivers/net/ath/ae531xmac.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/ae531xmac.c 2005-12-31 12:33:57.673538824 +0000
+@@ -0,0 +1,951 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++ */
++
++
++/*
++ * Ethernet driver for Atheros' ae531x ethernet MAC.
++ */
++
++#if linux
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/delay.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/init.h>
++#include <asm/io.h>
++
++#include "ar531xlnx.h"
++#endif /* linux */
++
++#include "ae531xreg.h"
++#include "ae531xmac.h"
++
++#ifdef DEBUG
++int ae531x_MAC_debug = AE531X_DEBUG_ERROR;
++#else
++int ae531x_MAC_debug = 0;
++#endif
++
++extern char *ae531x_enet_mac_address_get(int);
++
++/* Forward references to local functions */
++static void ae531x_QueueDestroy(AE531X_QUEUE *q);
++
++
++/******************************************************************************
++*
++* ae531x_ReadMacReg - read AE MAC register
++*
++* RETURNS: register value
++*/
++UINT32
++ae531x_ReadMacReg(ae531x_MAC_t *MACInfo, UINT32 reg)
++{
++ UINT32 addr = MACInfo->macBase+reg;
++ UINT32 data;
++
++ data = RegRead(addr);
++ return data;
++}
++
++
++/******************************************************************************
++*
++* ae531x_WriteMacReg - write AE MAC register
++*
++* RETURNS: N/A
++*/
++void
++ae531x_WriteMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data)
++{
++ UINT32 addr = MACInfo->macBase+reg;
++
++ RegWrite(data, addr);
++}
++
++
++/******************************************************************************
++*
++* ae531x_SetMacReg - set bits in AE MAC register
++*
++* RETURNS: N/A
++*/
++void
++ae531x_SetMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val)
++{
++ UINT32 addr = MACInfo->macBase+reg;
++ UINT32 data = RegRead(addr);
++
++ data |= val;
++ RegWrite(data, addr);
++}
++
++
++/******************************************************************************
++*
++* ae531x_ClearMacReg - clear bits in AE MAC register
++*
++* RETURNS: N/A
++*/
++void
++ae531x_ClearMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val)
++{
++ UINT32 addr = MACInfo->macBase+reg;
++ UINT32 data = RegRead(addr);
++
++ data &= ~val;
++ RegWrite(data, addr);
++}
++
++
++/******************************************************************************
++*
++* ae531x_ReadDmaReg - read AE DMA register
++*
++* RETURNS: register value
++*/
++UINT32
++ae531x_ReadDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg)
++{
++ UINT32 addr = MACInfo->dmaBase+reg;
++ UINT32 data = RegRead(addr);
++
++ return data;
++}
++
++
++/******************************************************************************
++*
++* ae531x_WriteDmaReg - write AE DMA register
++*
++* RETURNS: N/A
++*/
++void
++ae531x_WriteDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data)
++{
++ UINT32 addr = MACInfo->dmaBase+reg;
++
++ RegWrite(data, addr);
++}
++
++
++/******************************************************************************
++ *
++ * ae531x_AckIntr - clear interrupt bits in the status register.
++ * Note: Interrupt bits are *cleared* by writing a 1.
++ */
++void
++ae531x_AckIntr(ae531x_MAC_t *MACInfo, UINT32 data)
++{
++ ae531x_WriteDmaReg(MACInfo, DmaStatus, data);
++}
++
++
++/******************************************************************************
++*
++* ae531x_SetDmaReg - set bits in an AE DMA register
++*
++* RETURNS: N/A
++*/
++void
++ae531x_SetDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val)
++{
++ UINT32 addr = MACInfo->dmaBase+reg;
++ UINT32 data = RegRead(addr);
++
++ data |= val;
++ RegWrite(data, addr);
++}
++
++
++/******************************************************************************
++*
++* ae531x_ClearDmaReg - clear bits in an AE DMA register
++*
++* RETURNS: N/A
++*/
++void
++ae531x_ClearDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val)
++{
++ UINT32 addr = MACInfo->dmaBase+reg;
++ UINT32 data = RegRead(addr);
++
++ data &= ~val;
++ RegWrite(data, addr);
++}
++
++
++/******************************************************************************
++*
++* ae531x_ReadMiiReg - read PHY registers via AE MAC Mii addr/data registers
++*
++* RETURNS: register value
++*/
++UINT32
++ae531x_ReadMiiReg(UINT32 phyBase, UINT32 reg)
++{
++ UINT32 data;
++ UINT32 addr = phyBase+reg;
++
++ data = RegRead(addr);
++ return data;
++}
++
++
++/******************************************************************************
++*
++* ae531x_WriteMiiReg - write PHY registers via AE MAC Mii addr/data registers
++*
++* RETURNS: N/A
++*/
++void
++ae531x_WriteMiiReg(UINT32 phyBase, UINT32 reg, UINT32 data)
++{
++ UINT32 addr = phyBase+reg;
++
++ RegWrite(data, addr);
++}
++
++
++/******************************************************************************
++*
++* ae531x_MiiRead - read AE Mii register
++*
++* RETURNS: register value
++*/
++UINT16
++ae531x_MiiRead(UINT32 phyBase, UINT32 phyAddr, UINT8 reg)
++{
++ UINT32 addr;
++ UINT16 data;
++
++ addr = ((phyAddr << MiiDevShift) & MiiDevMask) | ((reg << MiiRegShift) & MiiRegMask);
++
++ ae531x_WriteMiiReg(phyBase, MacMiiAddr, addr );
++ do {
++ /* nop */
++ } while ((ae531x_ReadMiiReg(phyBase, MacMiiAddr ) & MiiBusy) == MiiBusy);
++
++ data = ae531x_ReadMiiReg(phyBase, MacMiiData) & 0xFFFF;
++
++ return data;
++}
++
++
++/******************************************************************************
++*
++* ae531x_MiiWrite - write AE Mii register
++*
++* RETURNS: N/A
++*/
++void
++ae531x_MiiWrite(UINT32 phyBase, UINT32 phyAddr, UINT8 reg, UINT16 data)
++{
++ UINT32 addr;
++
++ ae531x_WriteMiiReg(phyBase, MacMiiData, data );
++
++ addr = ((phyAddr << MiiDevShift) & MiiDevMask) |
++ ((reg << MiiRegShift) & MiiRegMask) | MiiWrite;
++ ae531x_WriteMiiReg(phyBase, MacMiiAddr, addr );
++
++ do {
++ /* nop */
++ } while ((ae531x_ReadMiiReg(phyBase, MacMiiAddr ) & MiiBusy) == MiiBusy);
++}
++
++
++/*******************************************************************************
++* ae531x_BeginResetMode - enter a special "reset mode" in which
++* -no interrupts are expected from the device
++* -the device will not transmit nor receive
++* -attempts to send or receive will return with an error and
++* -the device will be reset at the next convenient opportunity.
++*/
++void
++ae531x_BeginResetMode(ae531x_MAC_t *MACInfo)
++{
++ /* Set the reset flag */
++ MACInfo->aeProcessRst = 1;
++}
++
++
++/*******************************************************************************
++* ae531x_EndResetMode - exit the special "reset mode" entered
++* earlier via a call to ae531x_BeginResetMode.
++*/
++void
++ae531x_EndResetMode(ae531x_MAC_t *MACInfo)
++{
++ MACInfo->aeProcessRst = 0;
++}
++
++
++/*******************************************************************************
++* ae531x_IsInResetMode - determine whether or not the device is
++* currently in "reset mode" (i.e. that a device reset is pending)
++*/
++BOOL
++ae531x_IsInResetMode(ae531x_MAC_t *MACInfo)
++{
++ return MACInfo->aeProcessRst;
++}
++
++
++/******************************************************************************
++*
++* ae531x_DmaRxStart - Start Rx
++*
++* RETURNS: N/A
++*/
++static void
++ae531x_DmaRxStart(ae531x_MAC_t *MACInfo)
++{
++ ae531x_SetDmaReg(MACInfo, DmaControl, DmaRxStart);
++ sysWbFlush();
++}
++
++
++/******************************************************************************
++*
++* ae531x_DmaRxStop - Stop Rx
++*
++* RETURNS: N/A
++*/
++void
++ae531x_DmaRxStop(ae531x_MAC_t *MACInfo)
++{
++ ae531x_ClearDmaReg(MACInfo, DmaControl, DmaRxStart);
++ sysWbFlush();
++}
++
++
++/******************************************************************************
++*
++* ae531x_DmaTxStart - Start Tx
++*
++* RETURNS: N/A
++*/
++void
++ae531x_DmaTxStart(ae531x_MAC_t *MACInfo)
++{
++ ae531x_SetDmaReg(MACInfo, DmaControl, DmaTxStart);
++ sysWbFlush();
++}
++
++
++/******************************************************************************
++*
++* ae531x_DmaTxStop - Stop Tx
++*
++* RETURNS: N/A
++*/
++void
++ae531x_DmaTxStop(ae531x_MAC_t *MACInfo)
++{
++ ae531x_ClearDmaReg(MACInfo, DmaControl, DmaTxStart);
++ sysWbFlush();
++}
++
++
++/******************************************************************************
++*
++* ae531x_DmaIntEnable - Enable DMA interrupts
++*
++* RETURNS: N/A
++*/
++void
++ae531x_DmaIntEnable(ae531x_MAC_t *MACInfo)
++{
++ ae531x_WriteDmaReg(MACInfo, DmaIntrEnb, DmaIntEnable);
++}
++
++
++/******************************************************************************
++*
++* ae531x_DmaIntDisable - Disable DMA interrupts
++*
++* RETURNS: N/A
++*/
++void
++ae531x_DmaIntDisable(ae531x_MAC_t *MACInfo)
++{
++ ae531x_WriteDmaReg(MACInfo, DmaIntrEnb, DmaIntDisable);
++}
++
++
++/******************************************************************************
++*
++* ae531x_DmaIntClear - Clear DMA interrupts
++*
++* RETURNS: N/A
++*/
++static void
++ae531x_DmaIntClear(ae531x_MAC_t *MACInfo)
++{
++ /* clear all interrupt requests */
++ ae531x_WriteDmaReg(MACInfo, DmaStatus,
++ ae531x_ReadDmaReg(MACInfo, DmaStatus));
++}
++
++
++/******************************************************************************
++* Initialize generic queue data
++*/
++void
++ae531x_QueueInit(AE531X_QUEUE *q, char *pMem, int count)
++{
++ ARRIVE();
++ q->firstDescAddr = pMem;
++ q->lastDescAddr = (VIRT_ADDR)((UINT32)q->firstDescAddr +
++ (count - 1) * AE531X_QUEUE_ELE_SIZE);
++ q->curDescAddr = q->firstDescAddr;
++ q->count = count;
++ LEAVE();
++}
++
++
++/******************************************************************************
++* ae531x_TxQueueCreate - create a circular queue of descriptors for Transmit
++*/
++static int
++ae531x_TxQueueCreate(ae531x_MAC_t *MACInfo,
++ AE531X_QUEUE *q,
++ char *pMem,
++ int count)
++{
++ int i;
++ VIRT_ADDR descAddr;
++
++ ARRIVE();
++
++ ae531x_QueueInit(q, pMem, count);
++ q->reapDescAddr = q->lastDescAddr;
++
++ /* Initialize Tx buffer descriptors. */
++ for (i=0, descAddr=q->firstDescAddr;
++ i<count;
++ i++, descAddr=(VIRT_ADDR)((UINT32)descAddr + AE531X_QUEUE_ELE_SIZE))
++ {
++ /* Update the size, BUFPTR, and SWPTR fields */
++
++ AE531X_DESC_STATUS_SET(descAddr, 0);
++ AE531X_DESC_CTRLEN_SET(descAddr, 0);
++
++ AE531X_DESC_BUFPTR_SET(descAddr, (UINT32)0);
++ AE531X_DESC_LNKBUF_SET(descAddr, (UINT32)0);
++ AE531X_DESC_SWPTR_SET(descAddr, (void *)0);
++ } /* for each desc */
++
++ /* Make the queue circular */
++ AE531X_DESC_CTRLEN_SET(q->lastDescAddr,
++ DescEndOfRing|AE531X_DESC_CTRLEN_GET(q->lastDescAddr));
++
++ AE531X_PRINT(AE531X_DEBUG_RESET,
++ ("ethmac%d Txbuf begin = %x, end = %x\n",
++ MACInfo->unit,
++ (UINT32)q->firstDescAddr,
++ (UINT32)q->lastDescAddr));
++
++ LEAVE();
++ return 0;
++}
++
++
++/******************************************************************************
++* ae531x_RxQueueCreate - create a circular queue of Rx descriptors
++*/
++int
++ae531x_RxQueueCreate(ae531x_MAC_t *MACInfo,
++ AE531X_QUEUE *q,
++ char *pMem,
++ int count)
++{
++ int i;
++ VIRT_ADDR descAddr;
++
++ ARRIVE();
++
++ ae531x_QueueInit(q, pMem, count);
++ q->reapDescAddr = NULL;
++
++
++ /* Initialize Rx buffer descriptors */
++ for (i=0, descAddr=q->firstDescAddr;
++ i<count;
++ i++, descAddr=(VIRT_ADDR)((UINT32)descAddr + AE531X_QUEUE_ELE_SIZE))
++ {
++ void *swptr;
++ char *rxBuffer;
++ int rxBufferSize;
++
++ swptr = ae531x_rxbuf_alloc(MACInfo, &rxBuffer, &rxBufferSize);
++ if (swptr == NULL) {
++ AE531X_PRINT(AE531X_DEBUG_RESET,
++ ("ethmac%d RX queue: ae531x_rxbuf_alloc failed\n",
++ MACInfo->unit));
++ ae531x_QueueDestroy(q);
++ return -1;
++ }
++ AE531X_DESC_SWPTR_SET(descAddr, swptr);
++
++ AE531X_DESC_STATUS_SET(descAddr, DescOwnByDma);
++ AE531X_DESC_CTRLEN_SET(descAddr, rxBufferSize);
++ AE531X_DESC_BUFPTR_SET(descAddr, virt_to_bus(rxBuffer));
++ AE531X_DESC_LNKBUF_SET(descAddr, (UINT32)0);
++ } /* for each desc */
++
++ /* Make the queue circular */
++ AE531X_DESC_CTRLEN_SET(q->lastDescAddr,
++ DescEndOfRing|AE531X_DESC_CTRLEN_GET(q->lastDescAddr));
++
++ AE531X_PRINT(AE531X_DEBUG_RESET,
++ ("ethmac%d Rxbuf begin = %x, end = %x\n",
++ MACInfo->unit,
++ (UINT32)q->firstDescAddr,
++ (UINT32)q->lastDescAddr));
++
++ LEAVE();
++ return 0;
++}
++
++
++/******************************************************************************
++* ae531x_QueueDestroy -- Free all buffers and descriptors associated
++* with a queue.
++*/
++static void
++ae531x_QueueDestroy(AE531X_QUEUE *q)
++{
++ int i;
++ int count;
++ VIRT_ADDR descAddr;
++
++ ARRIVE();
++
++ count = q->count;
++
++ for (i=0, descAddr=q->firstDescAddr;
++ i<count;
++ i++, descAddr=(VIRT_ADDR)((UINT32)descAddr + AE531X_QUEUE_ELE_SIZE)) {
++
++ AE531X_DESC_STATUS_SET(descAddr, 0);
++ AE531X_DESC_CTRLEN_SET(descAddr, 0);
++ AE531X_DESC_BUFPTR_SET(descAddr, (UINT32)0);
++ AE531X_DESC_LNKBUF_SET(descAddr, (UINT32)0);
++
++ ae531x_swptr_free(descAddr); /* Free OS-specific software pointer */
++ }
++
++ LEAVE();
++}
++
++static void
++ae531x_TxQueueDestroy(ae531x_MAC_t *MACInfo)
++{
++ ae531x_QueueDestroy(&MACInfo->txQueue);
++}
++
++static void
++ae531x_RxQueueDestroy(ae531x_MAC_t *MACInfo)
++{
++ ae531x_QueueDestroy(&MACInfo->rxQueue);
++}
++
++
++/******************************************************************************
++* ae531x_AllocateQueues - Allocate receive and transmit queues
++*/
++int
++ae531x_AllocateQueues(ae531x_MAC_t *MACInfo)
++{
++ size_t QMemSize;
++ char *pTxBuf = NULL;
++ char *pRxBuf = NULL;
++
++ ARRIVE();
++
++ MACInfo->txDescCount = AE531X_TX_DESC_COUNT_DEFAULT;
++ QMemSize = AE531X_QUEUE_ELE_SIZE * MACInfo->txDescCount;
++ pTxBuf = MALLOC(QMemSize);
++ if (pTxBuf == NULL) {
++ AE531X_PRINT(AE531X_DEBUG_RESET,
++ ("ethmac%d Failed to allocate TX queue\n", MACInfo->unit));
++ goto AllocQFail;
++ }
++
++ if (ae531x_TxQueueCreate(MACInfo, &MACInfo->txQueue, pTxBuf,
++ MACInfo->txDescCount) < 0)
++ {
++ AE531X_PRINT(AE531X_DEBUG_RESET,
++ ("ethmac%d Failed to create TX queue\n", MACInfo->unit));
++ goto AllocQFail;
++ }
++
++ MACInfo->rxDescCount = AE531X_RX_DESC_COUNT_DEFAULT;
++ QMemSize = AE531X_QUEUE_ELE_SIZE * MACInfo->rxDescCount;
++ pRxBuf = MALLOC(QMemSize);
++ if (pRxBuf == NULL) {
++ AE531X_PRINT(AE531X_DEBUG_RESET,
++ ("ethmac%d Failed to allocate RX queue\n", MACInfo->unit));
++ goto AllocQFail;
++ }
++
++ if (ae531x_RxQueueCreate(MACInfo, &MACInfo->rxQueue, pRxBuf,
++ MACInfo->rxDescCount) < 0)
++ {
++ AE531X_PRINT(AE531X_DEBUG_RESET,
++ ("ethmac%d Failed to create RX queue\n", MACInfo->unit));
++ goto AllocQFail;
++ }
++
++ AE531X_PRINT(AE531X_DEBUG_RESET,
++ ("ethmac%d Memory setup complete.\n", MACInfo->unit));
++
++ LEAVE();
++ return 0;
++
++AllocQFail:
++ MACInfo->txDescCount = 0; /* sanity */
++ MACInfo->rxDescCount = 0; /* sanity */
++
++ if (pTxBuf) {
++ FREE(pTxBuf);
++ }
++ if (pRxBuf) {
++ FREE(pRxBuf);
++ }
++
++ LEAVE();
++ return -1;
++}
++
++
++/******************************************************************************
++*
++* ae531x_FreeQueues - Free Transmit & Receive queues
++*/
++void
++ae531x_FreeQueues(ae531x_MAC_t *MACInfo)
++{
++ ae531x_TxQueueDestroy(MACInfo);
++ FREE(MACInfo->txQueue.firstDescAddr);
++
++ ae531x_RxQueueDestroy(MACInfo);
++ FREE(MACInfo->rxQueue.firstDescAddr);
++}
++
++/******************************************************************************
++*
++* ae531x_DmaReset - Reset DMA and TLI controllers
++*
++* RETURNS: N/A
++*/
++void
++ae531x_DmaReset(ae531x_MAC_t *MACInfo)
++{
++ int i;
++ UINT32 descAddr;
++
++ ARRIVE();
++
++ /* Disable device interrupts prior to any errors during stop */
++ intDisable(MACInfo->ilevel);
++
++ /* Disable MAC rx and tx */
++ ae531x_ClearMacReg(MACInfo, MacControl, (MacRxEnable | MacTxEnable));
++
++ udelay(1);
++
++ /* Reset dma controller */
++
++ ae531x_WriteDmaReg(MACInfo, DmaBusMode, DmaResetOn);
++
++ /* Delay 2 usec */
++ sysUDelay(2);
++
++ /* Flush the rx queue */
++ descAddr = (UINT32)MACInfo->rxQueue.firstDescAddr;
++ MACInfo->rxQueue.curDescAddr = MACInfo->rxQueue.firstDescAddr;
++ for (i=0;
++ i<(MACInfo->rxDescCount);
++ i++, descAddr += AE531X_QUEUE_ELE_SIZE) {
++ AE531X_DESC_STATUS_SET(descAddr, DescOwnByDma);
++ }
++
++ /* Flush the tx queue */
++ descAddr = (UINT32)MACInfo->txQueue.firstDescAddr;
++ MACInfo->txQueue.curDescAddr = MACInfo->txQueue.firstDescAddr;
++ MACInfo->txQueue.reapDescAddr = MACInfo->txQueue.lastDescAddr;
++ for (i=0;
++ i<(MACInfo->txDescCount);
++ i++, descAddr += AE531X_QUEUE_ELE_SIZE) {
++ AE531X_DESC_STATUS_SET (descAddr, 0);
++ }
++
++ /* Set init register values */
++ ae531x_WriteDmaReg(MACInfo, DmaBusMode, DmaBusModeInit);
++
++ /* Install the first Tx and Rx queues on the device */
++ ae531x_WriteDmaReg(MACInfo, DmaRxBaseAddr,
++ virt_to_bus(MACInfo->rxQueue.firstDescAddr));
++ ae531x_WriteDmaReg(MACInfo, DmaTxBaseAddr,
++ virt_to_bus(MACInfo->txQueue.firstDescAddr));
++
++
++ ae531x_WriteDmaReg(MACInfo, DmaControl, DmaStoreAndForward);
++
++ ae531x_WriteDmaReg(MACInfo, DmaIntrEnb, DmaIntDisable);
++
++ AE531X_PRINT(AE531X_DEBUG_RESET,
++ ("ethmac%d: DMA RESET!\n", MACInfo->unit));
++
++ /* Turn on device interrupts -- enable most errors */
++ ae531x_DmaIntClear(MACInfo); /* clear interrupt requests */
++ ae531x_DmaIntEnable(MACInfo); /* enable interrupts */
++
++ ae531x_EndResetMode(MACInfo);
++
++ intEnable(MACInfo->ilevel);
++
++ LEAVE();
++}
++
++
++/******************************************************************************
++*
++* ae531x_MACAddressSet - Set the ethernet address
++*
++* Sets the ethernet address according to settings in flash.
++*
++* RETURNS: void
++*/
++static void
++ae531x_MACAddressSet(ae531x_MAC_t *MACInfo)
++{
++ unsigned int data;
++ UINT8 *macAddr;
++
++ ARRIVE();
++
++ macAddr = ae531x_enet_mac_address_get(MACInfo->unit);
++
++ /* set our MAC address */
++ data = (macAddr[5]<<8) | macAddr[4];
++ ae531x_WriteMacReg(MACInfo, MacAddrHigh, data );
++
++ data = (macAddr[3]<<24) | (macAddr[2]<<16) | (macAddr[1]<<8) | macAddr[0];
++ ae531x_WriteMacReg(MACInfo, MacAddrLow, data );
++
++ AE531X_PRINT(AE531X_DEBUG_RESET,
++ ("ethmac%d Verify MAC address %8.8X %8.8X \n",
++ MACInfo->unit,
++ ae531x_ReadMacReg(MACInfo, MacAddrLow),
++ ae531x_ReadMacReg(MACInfo, MacAddrHigh)));
++
++ AE531X_PRINT(AE531X_DEBUG_RESET,
++ (" sb = %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
++ 0xff&macAddr[0],
++ 0xff&macAddr[1],
++ 0xff&macAddr[2],
++ 0xff&macAddr[3],
++ 0xff&macAddr[4],
++ 0xff&macAddr[5]));
++ LEAVE();
++}
++
++
++/******************************************************************************
++*
++* ae_SetMACFromPhy - read Phy settings and update Mac
++* with current duplex and speed.
++*
++* RETURNS:
++*/
++static void
++ae531x_SetMACFromPhy(ae531x_MAC_t *MACInfo)
++{
++ UINT32 macCtl;
++ BOOL fullDuplex;
++ UINT32 timeout;
++
++ ARRIVE();
++
++ timeout = jiffies+(HZ/1000)*AE531X_NEGOT_TIMEOUT;
++
++ /* Get duplex mode from Phy */
++ while (((fullDuplex = phyIsFullDuplex(MACInfo->unit)) == -1) &&
++ (jiffies <= timeout));
++
++ /* Flag is set for full duplex mode, else cleared */
++ macCtl = ae531x_ReadMacReg(MACInfo, MacControl);
++
++ if (fullDuplex) {
++ /* set values of control registers */
++ macCtl &= ~MacDisableRxOwn;
++ macCtl |= MacFullDuplex;
++ ae531x_WriteMacReg(MACInfo, MacControl, macCtl);
++ ae531x_WriteMacReg(MACInfo, MacFlowControl, MacFlowControlInitFdx);
++ } else {
++ /* set values of control registers */
++ ae531x_WriteMacReg(MACInfo, MacFlowControl, MacFlowControlInitHdx);
++ macCtl |= MacDisableRxOwn;
++ macCtl &= ~MacFullDuplex;
++ ae531x_WriteMacReg(MACInfo, MacControl, macCtl);
++ }
++
++ LEAVE();
++}
++
++
++/******************************************************************************
++* ae531x_MACReset -- sets MAC address and duplex.
++*/
++void
++ae531x_MACReset(ae531x_MAC_t *MACInfo)
++{
++ ae531x_MACAddressSet(MACInfo);
++#ifndef CONFIG_AR5315
++ ae531x_SetMACFromPhy(MACInfo);
++#endif
++}
++
++
++/******************************************************************************
++* ae531x_EnableComm -- enable Transmit and Receive
++*/
++void
++ae531x_EnableComm(ae531x_MAC_t *MACInfo)
++{
++ ae531x_SetMacReg(MACInfo, MacControl, (MacRxEnable | MacTxEnable));
++ ae531x_DmaRxStart(MACInfo); /* start receiver */
++ ae531x_DmaTxStart(MACInfo); /* start transmitter */
++}
++
++
++/******************************************************************************
++* ae531x_DisableComm -- disable Transmit and Receive
++*/
++void
++ae531x_DisableComm(ae531x_MAC_t *MACInfo)
++{
++ ae531x_ClearMacReg(MACInfo, MacControl, (MacRxEnable | MacTxEnable));
++}
++
++
++/******************************************************************************
++* ae531x_reset -- Cold reset ethernet interface
++*/
++void
++ae531x_reset(ae531x_MAC_t *MACInfo)
++{
++ UINT32 mask = 0;
++ UINT32 regtmp;
++#ifndef CONFIG_AR5315
++
++ if (MACInfo->unit == 0) {
++ mask = AR531X_RESET_ENET0 | AR531X_RESET_EPHY0;
++ } else {
++ mask = AR531X_RESET_ENET1 | AR531X_RESET_EPHY1;
++ }
++
++ /* Put into reset */
++ regtmp = sysRegRead(AR531X_RESET);
++ sysRegWrite(AR531X_RESET, regtmp | mask);
++ sysMsDelay(15);
++
++ /* Pull out of reset */
++ regtmp = sysRegRead(AR531X_RESET);
++ sysRegWrite(AR531X_RESET, regtmp & ~mask);
++ sysUDelay(25);
++
++ /* Enable */
++ if (MACInfo->unit == 0) {
++ mask = AR531X_ENABLE_ENET0;
++ } else {
++ mask = AR531X_ENABLE_ENET1;
++ }
++ regtmp = sysRegRead(AR531X_ENABLE);
++ sysRegWrite(AR531X_ENABLE, regtmp | mask);
++#else
++ if (MACInfo->unit == 0) {
++ mask = AR531X_RESET_ENET0 | AR531X_RESET_EPHY0;
++ }
++ /* Enable Arbitration for Ethernet bus */
++ regtmp = sysRegRead(AR531XPLUS_AHB_ARB_CTL);
++ regtmp |= ARB_ETHERNET;
++ sysRegWrite(AR531XPLUS_AHB_ARB_CTL, regtmp);
++
++ /* Put into reset */
++ regtmp = sysRegRead(AR531X_RESET);
++ sysRegWrite(AR531X_RESET, regtmp | mask);
++ sysMsDelay(10);
++
++ /* Pull out of reset */
++ regtmp = sysRegRead(AR531X_RESET);
++ sysRegWrite(AR531X_RESET, regtmp & ~mask);
++ sysMsDelay(10);
++
++ regtmp = sysRegRead(AR531XPLUS_IF_CTL);
++ regtmp |= IF_TS_LOCAL;
++ sysRegWrite(AR531XPLUS_IF_CTL, regtmp);
++#endif
++}
++
++
++/******************************************************************************
++* ae531x_unitLinkLost -- Called from PHY layer to notify the MAC layer
++* that there are no longer any live links associated with a MAC.
++*/
++void
++ae531x_unitLinkLost(int ethUnit)
++{
++ AE531X_PRINT(AE531X_DEBUG_LINK_CHANGE,
++ ("enetmac%d link down\n", ethUnit));
++}
++
++
++/******************************************************************************
++* ae531x_unitLinkGained -- Called from PHY layer to notify the MAC layer
++* that there are 1 or more live links associated with a MAC.
++*/
++void
++ae531x_unitLinkGained(int ethUnit)
++{
++#if CONFIG_AR5315
++#define AE531X_POLL_MILLI_SECONDS 200
++ ae531x_MAC_t *MACInfo = ae531x_getMAcInfo(ethUnit);
++ while(!MACInfo || !MACInfo->port_is_up)
++ {
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ schedule_timeout((AE531X_POLL_MILLI_SECONDS * HZ)/1000);
++ MACInfo = ae531x_getMAcInfo(ethUnit);
++ }
++ ae531x_SetMACFromPhy(MACInfo);
++#endif
++ AE531X_PRINT(AE531X_DEBUG_LINK_CHANGE,
++ ("enet%d link up\n", ethUnit));
++}
++
++/******************************************************************************
++* ae531x_ethMacDefault -- Called from PHY layer to determine the default
++* ethernet MAC. On some "twisted" platforms, the only usable MAC is 1,
++* while on others the usable MAC is 0. Future boards may allow both MACs
++* to be used; in this case, return -1 to indicate that there IS NO default
++* MAC.
++*/
++int
++ae531x_ethMacDefault(void)
++{
++ if (ae531x_twisted_enet())
++ return 1;
++
++ return 0;
++
++}
+diff -urN linux-mips-orig/drivers/net/ath/ae531xmac.h linux-mips-new/drivers/net/ath/ae531xmac.h
+--- linux-mips-orig/drivers/net/ath/ae531xmac.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/ae531xmac.h 2005-12-31 12:33:57.674538672 +0000
+@@ -0,0 +1,229 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++ */
++
++/*
++ * See README to understand the decomposition of the ethernet driver.
++ *
++ * This file contains OS-independent pure software definitions for
++ * ethernet support on the AR531X platform.
++ */
++
++#ifndef _AE531XMAC_H_
++#define _AE531XMAC_H_
++
++#include <linux/config.h>
++#include <linux/module.h>
++
++/*
++ * DEBUG switches to control verbosity.
++ * Just modify the value of ae531x_MAC_debug.
++ */
++#define AE531X_DEBUG_ALL 0xffffffff
++#define AE531X_DEBUG_ERROR 0x00000001 /* Unusual conditions and Errors */
++#define AE531X_DEBUG_ARRIVE 0x00000002 /* Arrive into a function */
++#define AE531X_DEBUG_LEAVE 0x00000004 /* Leave a function */
++#define AE531X_DEBUG_RESET 0x00000008 /* Reset */
++#define AE531X_DEBUG_TX 0x00000010 /* Transmit */
++#define AE531X_DEBUG_TX_REAP 0x00000020 /* Transmit Descriptor Reaping */
++#define AE531X_DEBUG_RX 0x00000040 /* Receive */
++#define AE531X_DEBUG_RX_STOP 0x00000080 /* Receive Early Stop */
++#define AE531X_DEBUG_INT 0x00000100 /* Interrupts */
++#define AE531X_DEBUG_LINK_CHANGE 0x00000200 /* PHY Link status changed */
++
++#define AE531X_NEGOT_TIMEOUT 500 /* ms to wait for autonegotiation */
++
++extern int ae531x_MAC_debug;
++
++#define AE531X_PRINT(FLG, X) \
++{ \
++ if (ae531x_MAC_debug & (FLG)) { \
++ DEBUG_PRINTF("%s#%d:%s ", \
++ __FILE__, \
++ __LINE__, \
++ __FUNCTION__); \
++ DEBUG_PRINTF X; \
++ } \
++}
++
++#define ARRIVE() AE531X_PRINT(AE531X_DEBUG_ARRIVE, ("Arrive{\n"))
++#define LEAVE() AE531X_PRINT(AE531X_DEBUG_LEAVE, ("}Leave\n"))
++
++#define RegRead(addr) \
++ (*(volatile unsigned int *)(addr))
++
++#define RegWrite(val,addr) \
++ ((*(volatile unsigned int *)(addr)) = (val))
++
++/*****************************************************************
++ * Phy code is broken out into a separate layer, so that different
++ * PHY hardware can easily be supported.
++ *
++ * These functions are provided by the PHY layer for use by the MAC layer.
++ * phySetup -- Set phy hardware appropriately for a MAC unit
++ *
++ * phyCheckStatusChange -- Look for dropped/initiated links on any
++ * phy port associated with a MAC unit
++ *
++ * phyIsSpeed100 -- Determines whether or not a PHY is up and
++ * running at 100Mbit
++ *
++ * phyIsFullDuplex -- Determines whether or not a PHY is up and
++ * running in Full Duplex mode
++ *
++ */
++#if CONFIG_MARVELL_ENET_PHY
++/*
++ * Mapping of generic phy APIs to Marvell Ethernet Switch phy functions.
++ */
++#include "mvPhy.h"
++#define phySetup(ethUnit, phyBase) mv_phySetup((ethUnit), (phyBase))
++#define phyCheckStatusChange(ethUnit) mv_phyCheckStatusChange(ethUnit)
++#define phyIsSpeed100(ethUnit) mv_phyIsSpeed100(ethUnit)
++#define phyIsFullDuplex(ethUnit) mv_phyIsFullDuplex(ethUnit)
++
++#if CONFIG_VENETDEV
++#define PHY_TRAILER_SIZE MV_PHY_TRAILER_SIZE
++extern void mv_phyDetermineSource(char *data, int len, int *pFromLAN);
++extern void mv_phySetDestinationPort(char *data, int len, int fromLAN);
++#define phyDetermineSource(data, len, pFromLAN) mv_phyDetermineSource((data), (len), (pFromLAN))
++#define phySetDestinationPort(data, len, fromLAN) mv_phySetDestinationPort((data), (len), (fromLAN))
++#else
++#define PHY_TRAILER_SIZE 0
++#endif
++#endif /* CONFIG_MARVELL_ENET_PHY */
++
++#if CONFIG_KENDIN_ENET_PHY || CONFIG_REALTEK_ENET_PHY || CONFIG_KENDIN_KS8995XA_ENET_PHY
++/*
++ * Mapping of generic phy APIs to Kendin KS8721B and RealTek RTL8201BL phys.
++ */
++#include "rtPhy.h"
++#define phySetup(ethUnit, phyBase) rt_phySetup((ethUnit), (phyBase))
++#define phyCheckStatusChange(ethUnit) rt_phyCheckStatusChange(ethUnit)
++#define phyIsSpeed100(ethUnit) rt_phyIsSpeed100(ethUnit)
++#define phyIsFullDuplex(ethUnit) rt_phyIsFullDuplex(ethUnit)
++#endif
++
++#if CONFIG_ICPLUS_ENET_PHY
++/*
++ * Mapping of generic phy APIs to Icplus phys.
++ */
++#include "ipPhy.h"
++#define phySetup(ethUnit, phyBase) ip_phySetup((ethUnit), (phyBase))
++#define phyCheckStatusChange(ethUnit) ip_phyCheckStatusChange(ethUnit)
++#define phyIsSpeed100(ethUnit) ip_phyIsSpeed100(ethUnit)
++#define phyIsFullDuplex(ethUnit) ip_phyIsFullDuplex(ethUnit)
++#endif
++
++#if !defined(PHY_TRAILER_SIZE)
++#define PHY_TRAILER_SIZE 0
++#endif
++
++/*****************************************************************
++ * MAC-independent interface to be used by PHY code
++ *
++ * These functions are provided by the MAC layer for use by the PHY layer.
++ */
++#define phyRegRead ae531x_MiiRead
++#define phyRegWrite ae531x_MiiWrite
++#define phyLinkLost(ethUnit) ae531x_unitLinkLost(ethUnit)
++#define phyLinkGained(ethUnit) ae531x_unitLinkGained(ethUnit)
++#define phyEthMacDefault() ae531x_ethMacDefault()
++
++void ae531x_unitLinkLost(int unit);
++void ae531x_unitLinkGained(int unit);
++int ae531x_ethMacDefault(void);
++
++
++/*
++ * RXBUFF_RESERVE enables building header on WLAN-side in place
++ * NB: Divisible by 2 but NOT 4. Otherwise handle_adel_int() will
++ * be used by the ip layer for misaligned word accesses and
++ * performance will suffer - a lot.
++ */
++#define ETH_CRC_LEN 4
++#define RXBUFF_RESERVE 98
++// #define RXBUFF_RESERVE 98
++
++/*****************************************************************
++ * Descriptor queue
++ */
++typedef struct ae531x_queue {
++ VIRT_ADDR firstDescAddr; /* descriptor array address */
++ VIRT_ADDR lastDescAddr; /* last descriptor address */
++ VIRT_ADDR curDescAddr; /* current descriptor address */
++ VIRT_ADDR reapDescAddr; /* current tail of tx descriptors reaped */
++ UINT16 count; /* number of elements */
++} AE531X_QUEUE;
++
++/* Given a descriptor, return the next one in a circular list */
++#define AE531X_QUEUE_ELE_NEXT_GET(q, descAddr) \
++ ((descAddr) == (q)->lastDescAddr) ? (q)->firstDescAddr : \
++ (VIRT_ADDR)((UINT32)(descAddr) + AE531X_QUEUE_ELE_SIZE)
++
++/* Move the "current descriptor" forward to the next one */
++#define AE531X_CONSUME_DESC(q) \
++ q->curDescAddr = AE531X_QUEUE_ELE_NEXT_GET(q, q->curDescAddr)
++
++/*****************************************************************
++ * Per-ethernet-MAC OS-independent information
++ */
++typedef struct ae531x_MAC_s {
++ u32 unit; /* MAC unit ID */
++ u32 macBase; /* MAC base address */
++ u32 dmaBase; /* DMA base address */
++ u32 phyBase; /* PHY base address */
++ AE531X_QUEUE txQueue; /* Transmit descriptor queue */
++ AE531X_QUEUE rxQueue; /* Receive descriptor queue */
++ UINT16 txDescCount; /* Transmit descriptor count */
++ UINT16 rxDescCount; /* Receive descriptor count */
++ BOOL aeProcessRst; /* flag to indicate reset in progress */
++ BOOL port_is_up; /* flag to indicate port is up */
++ void *OSinfo; /* OS-dependent data */
++} ae531x_MAC_t;
++
++#define AE531X_TX_DESC_COUNT_DEFAULT 128 /* Transmit descriptors */
++#define AE531X_RX_DESC_COUNT_DEFAULT 128 /* Receive descriptors */
++
++
++/*****************************************************************
++ * Interfaces exported by the OS-independent MAC layer
++ */
++void ae531x_BeginResetMode(ae531x_MAC_t *MACInfo);
++void ae531x_EndResetMode(ae531x_MAC_t *MACInfo);
++BOOL ae531x_IsInResetMode(ae531x_MAC_t *MACInfo);
++int ae531x_RxQueueCreate(ae531x_MAC_t *MACInfo, AE531X_QUEUE *q,
++ char *pMem, int count);
++int ae531x_QueueDelete(struct ae531x_queue *q);
++void ae531x_DmaReset(ae531x_MAC_t *MACInfo);
++void ae531x_MACReset(ae531x_MAC_t *MACInfo);
++void ae531x_EnableComm(ae531x_MAC_t *MACInfo);
++void ae531x_DisableComm(ae531x_MAC_t *MACInfo);
++void ae531x_reset(ae531x_MAC_t *MACInfo);
++int ae531x_AllocateQueues(ae531x_MAC_t *MACInfo);
++void ae531x_FreeQueues(ae531x_MAC_t *MACInfo);
++void ae531x_QueueInit(AE531X_QUEUE *q, char *pMem, int count);
++UINT32 ae531x_ReadMacReg(ae531x_MAC_t *MACInfo, UINT32 reg);
++void ae531x_WriteMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data);
++void ae531x_SetMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
++void ae531x_ClearMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
++void ae531x_SetDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
++void ae531x_ClearDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
++UINT32 ae531x_ReadDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg);
++void ae531x_WriteDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data);
++UINT32 ae531x_ReadMiiReg(UINT32 phyBase, UINT32 reg);
++void ae531x_WriteMiiReg(UINT32 phyBase, UINT32 reg, UINT32 data);
++UINT16 ae531x_MiiRead(UINT32 phyBase, UINT32 phyAddr, UINT8 reg);
++void ae531x_MiiWrite(UINT32 phyBase, UINT32 phyAddr, UINT8 reg, UINT16 data);
++void ae531x_DmaIntEnable(ae531x_MAC_t *MACInfo);
++void ae531x_DmaIntDisable(ae531x_MAC_t *MACInfo);
++void ae531x_AckIntr(ae531x_MAC_t *MACInfo, UINT32 val);
++void *ae531x_rxbuf_alloc(ae531x_MAC_t *MACInfo, char **rxBptr, int *rxBSize);
++void ae531x_swptr_free(VIRT_ADDR txDesc);
++BOOL ae531x_twisted_enet(void);
++
++#endif /* _AE531XMAC_H_ */
+diff -urN linux-mips-orig/drivers/net/ath/ae531xreg.h linux-mips-new/drivers/net/ath/ae531xreg.h
+--- linux-mips-orig/drivers/net/ath/ae531xreg.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/ae531xreg.h 2005-12-31 12:33:57.675538520 +0000
+@@ -0,0 +1,439 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++ */
++
++/*
++ * See README to understand the decomposition of the ethernet driver.
++ *
++ * Register definitions for Atheros AR531X Ethernet MAC.
++ */
++
++#ifndef _AE531XREG_H_
++#define _AE531XREG_H_
++
++#define AE531X_MAC_OFFSET 0x0000
++#define AE531X_PHY_OFFSET 0x0000 /* Same as MAC offset */
++#define AE531X_DMA_OFFSET 0x1000
++
++/***********************************************************/
++/* MAC110 registers, base address is BAR+AE531X_MAC_OFFSET */
++/***********************************************************/
++#define MacControl 0x00 /* control */
++#define MacAddrHigh 0x04 /* address high */
++#define MacAddrLow 0x08 /* address low */
++#define MacMultiHashHigh 0x0C /* multicast hash table high */
++#define MacMultiHashLow 0x10 /* multicast hash table low */
++#define MacMiiAddr 0x14 /* MII address */
++#define MacMiiData 0x18 /* MII data */
++#define MacFlowControl 0x1C /* Flow control */
++#define MacVlan1Tag 0x4C /* VLAN1 tag */
++#define MacVlan2Tag 0x50 /* VLAN2 tag */
++
++
++/***************************************************************/
++/* DMA engine registers, base address is BAR+AE531X_DMA_OFFSET */
++/***************************************************************/
++#define DmaBusMode 0x00 /* CSR0 - Bus Mode */
++#define DmaTxPollDemand 0x04 /* CSR1 - Transmit Poll Demand */
++#define DmaRxPollDemand 0x08 /* CSR2 - Receive Poll Demand */
++#define DmaRxBaseAddr 0x0C /* CSR3 - Receive list base address */
++#define DmaTxBaseAddr 0x10 /* CSR4 - Transmit list base address */
++#define DmaStatus 0x14 /* CSR5 - Dma status */
++#define DmaControl 0x18 /* CSR6 - Dma control */
++#define DmaIntrEnb 0x1C /* CSR7 - Interrupt enable */
++#define DmaOverflowCnt 0x20 /* CSR8 - Missed Frame and Buff Overflow counter */
++#define DmaTxCurrAddr 0x50 /* CSR20 - Current host transmit buffer address */
++#define DmaRxCurrAddr 0x54 /* CSR21 - Current host receive buffer address */
++
++/**********************************************************/
++/* MAC Control register layout */
++/**********************************************************/
++#define MacFilterOff 0x80000000 /* Receive all incoming packets RW */
++#define MacFilterOn 0 /* Receive filtered packets only 0 */
++#define MacBigEndian 0x40000000 /* Big endian mode RW */
++#define MacLittleEndian 0 /* Little endian 0 */
++#define MacHeartBeatOff 0x10000000 /* Heartbeat signal qual disable RW*/
++#define MacHeartBeatOn 0 /* Heartbeat signal qual enable 0 */
++#define MacSelectSrl 0x08000000 /* Select SRL port RW */
++#define MacSelectMii 0 /* Select MII port 0 */
++#define MacDisableRxOwn 0x00800000 /* Disable receive own packets RW */
++#define MacEnableRxOwn 0 /* Enable receive own packets 0 */
++#define MacLoopbackExt 0x00400000 /* External loopback RW */
++#define MacLoopbackInt 0x00200000 /* Internal loopback */
++#define MacLoopbackOff 0 /* Normal mode 00 */
++#define MacFullDuplex 0x00100000 /* Full duplex mode RW */
++#define MacHalfDuplex 0 /* Half duplex mode 0 */
++#define MacMulticastFilterOff 0x00080000 /* Pass all multicast packets RW */
++#define MacMulticastFilterOn 0 /* Pass filtered mcast packets 0 */
++#define MacPromiscuousModeOn 0x00040000 /* Receive all valid packets RW 1 */
++#define MacPromiscuousModeOff 0 /* Receive filtered packets only */
++#define MacFilterInverse 0x00020000 /* Inverse filtering RW */
++#define MacFilterNormal 0 /* Normal filtering 0 */
++#define MacBadFramesEnable 0x00010000 /* Pass bad frames RW */
++#define MacBadFramesDisable 0 /* Do not pass bad frames 0 */
++#define MacPerfectFilterOff 0x00008000 /* Hash filtering only RW */
++#define MacPerfectFilterOn 0 /* Both perfect and hash filtering 0 */
++#define MacHashFilterOn 0x00002000 /* perform hash filtering RW */
++#define MacHashFilterOff 0 /* perfect filtering only 0 */
++#define MacLateCollisionOn 0x00001000 /* Enable late collision control RW */
++#define MacLateCollisionOff 0 /* Disable late collision control 0 */
++#define MacBroadcastDisable 0x00000800 /* Disable reception of bcast frames RW */
++#define MacBroadcastEnable 0 /* Enable broadcast frames 0 */
++#define MacRetryDisable 0x00000400 /* Disable retransmission RW */
++#define MacRetryEnable 0 /* Enable retransmission 0 */
++#define MacPadStripEnable 0x00000100 /* Pad stripping enable RW */
++#define MacPadStripDisable 0 /* Pad stripping disable 0 */
++#define MacBackoff 0 /* Backoff Limit RW 00 */
++#define MacDeferralCheckEnable 0x00000020 /* Deferral check enable RW */
++#define MacDeferralCheckDisable 0 /* Deferral check disable 0 */
++#define MacTxEnable 0x00000008 /* Transmitter enable RW */
++#define MacTxDisable 0 /* Transmitter disable 0 */
++#define MacRxEnable 0x00000004 /* Receiver enable RW */
++#define MacRxDisable 0 /* Receiver disable 0 */
++
++
++/**********************************************************/
++/* MII address register layout */
++/**********************************************************/
++#define MiiDevMask 0x0000F800 /* MII device address */
++#define MiiDevShift 11
++#define MiiRegMask 0x000007C0 /* MII register */
++#define MiiRegShift 6
++#define MiiWrite 0x00000002 /* Write to register */
++#define MiiRead 0 /* Read from register */
++#define MiiBusy 0x00000001 /* MII interface is busy */
++
++/**********************************************************/
++/* MII Data register layout */
++/**********************************************************/
++#define MiiDataMask 0x0000FFFF /* MII Data */
++
++/**********************************************************/
++/* MAC flow control register layout */
++/**********************************************************/
++#define MacPauseTimeMask 0xFFFF0000 /* PAUSE TIME field in ctrl frame */
++#define MacPauseTimeShift 15
++#define MacControlFrameEnable 0x00000004 /* Enable pass ctrl frames to host */
++#define MacControlFrameDisable 0 /* Do not pass ctrl frames to host */
++#define MacFlowControlEnable 0x00000002 /* Enable flow control */
++#define MacFlowControlDisable 0 /* Disable flow control */
++#define MacSendPauseFrame 0x00000001 /* send pause frame */
++
++/**********************************************************/
++/* DMA bus mode register layout */
++/**********************************************************/
++#define DmaRxAlign16 0x01000000 /* Force all rx buffers to align on odd hw bndry */
++#define DmaBigEndianDes 0x00100000 /* Big endian data buffer descriptors RW */
++#define DmaLittleEndianDesc 0 /* Little endian data descriptors */
++#define DmaBurstLength32 0x00002000 /* Dma burst length 32 RW */
++#define DmaBurstLength16 0x00001000 /* Dma burst length 16 */
++#define DmaBurstLength8 0x00000800 /* Dma burst length 8 */
++#define DmaBurstLength4 0x00000400 /* Dma burst length 4 */
++#define DmaBurstLength2 0x00000200 /* Dma burst length 2 */
++#define DmaBurstLength1 0x00000100 /* Dma burst length 1 */
++#define DmaBurstLength0 0x00000000 /* Dma burst length 0 */
++#define DmaBigEndianData 0x00000080 /* Big endian data buffers RW */
++#define DmaLittleEndianData 0 /* Little endian data buffers 0 */
++#define DmaDescriptorSkip16 0x00000040 /* number of dwords to skip RW */
++#define DmaDescriptorSkip8 0x00000020 /* between two unchained descriptors */
++#define DmaDescriptorSkip4 0x00000010
++#define DmaDescriptorSkip2 0x00000008
++#define DmaDescriptorSkip1 0x00000004
++#define DmaDescriptorSkip0 0
++#define DmaReceivePriorityOff 0x00000002 /* equal rx and tx priorities RW */
++#define DmaReceivePriorityOn 0 /* Rx has prioryty over Tx 0 */
++#define DmaResetOn 0x00000001 /* Reset DMA engine RW */
++#define DmaResetOff 0
++
++/**********************************************************/
++/* DMA Status register layout */
++/**********************************************************/
++#define DmaRxAbort 0x01000000 /* receiver bus abort R 0 */
++#define DmaTxAbort 0x00800000 /* transmitter bus abort R 0 */
++#define DmaTxState 0x00700000 /* Transmit process state R 000 */
++#define DmaTxStopped 0x00000000 /* Stopped */
++#define DmaTxFetching 0x00100000 /* Running - fetching the descriptor */
++#define DmaTxWaiting 0x00200000 /* Running - waiting for end of transmission */
++#define DmaTxReading 0x00300000 /* Running - reading the data from memory */
++#define DmaTxSuspended 0x00600000 /* Suspended */
++#define DmaTxClosing 0x00700000 /* Running - closing descriptor */
++#define DmaRxState 0x000E0000 /* Receive process state 000 */
++#define DmaRxStopped 0x00000000 /* Stopped */
++#define DmaRxFetching 0x00020000 /* Running - fetching the descriptor */
++#define DmaRxChecking 0x00040000 /* Running - checking for end of packet */
++#define DmaRxWaiting 0x00060000 /* Running - waiting for packet */
++#define DmaRxSuspended 0x00080000 /* Suspended */
++#define DmaRxClosing 0x000A0000 /* Running - closing descriptor */
++#define DmaRxFlushing 0x000C0000 /* Running - flushing the current frame */
++#define DmaRxQueuing 0x000E0000 /* Running - queuing the recieve frame into host memory */
++#define DmaIntNormal 0x00010000 /* Normal interrupt summary RW 0 */
++#define DmaIntAbnormal 0x00008000 /* Abnormal interrupt summary RW 0 */
++#define DmaIntEarlyRx 0x00004000 /* Early receive interrupt (Normal) RW 0 */
++#define DmaIntBusError 0x00002000 /* Fatal bus error (Abnormal) RW 0 */
++#define DmaIntEarlyTx 0x00000400 /* Early transmit interrupt RW 0 */
++#define DmaIntRxStopped 0x00000100 /* Receive process stopped (Abnormal) RW 0 */
++#define DmaIntRxNoBuffer 0x00000080 /* Receive buffer unavailable (Abnormal) RW 0*/
++#define DmaIntRxCompleted 0x00000040 /* Completion of frame reception(Normal) RW 0*/
++#define DmaIntTxUnderflow 0x00000020 /* Transmit underflow (Abnormal) RW 0 */
++#define DmaIntTxJabber 0x00000008 /* Transmit Jabber Timeout (Abnormal) RW 0 */
++#define DmaIntTxNoBuffer 0x00000004 /* Transmit buffer unavailable (Normal) RW 0*/
++#define DmaIntTxStopped 0x00000002 /* Transmit process stopped (Abnormal) RW 0 */
++#define DmaIntTxCompleted 0x00000001 /* Transmit completed (Normal) RW 0 */
++
++/**********************************************************/
++/* DMA control register layout */
++/**********************************************************/
++#define DmaStoreAndForward 0x00000000 /* Store and forward RW 0 */
++#define DmaTxThreshCtl256 0x0000c000 /* Non-SF threshold is 256 words */
++#define DmaTxThreshCtl128 0x00008000 /* Non-SF threshold is 128 words */
++#define DmaTxThreshCtl064 0x00004000 /* Non-SF threshold is 64 words */
++#define DmaTxThreshCtl032 0x00000000 /* Non-SF threshold is 32 words */
++#define DmaTxStart 0x00002000 /* Start/Stop transmission RW 0 */
++#define DmaTxSecondFrame 0x00000004 /* Operate on second frame RW 0 */
++#define DmaRxStart 0x00000002 /* Start/Stop reception RW 0 */
++
++/**********************************************************/
++/* DMA interrupt enable register layout */
++/**********************************************************/
++#define DmaIeNormal DmaIntNormal /* Normal interrupt enable RW 0 */
++#define DmaIeAbnormal DmaIntAbnormal /* Abnormal interrupt enable RW 0 */
++#define DmaIeEarlyRx DmaIntEarlyRx /* Early receive interrupt enable RW 0 */
++#define DmaIeBusError DmaIntBusError /* Fatal bus error enable RW 0 */
++#define DmaIeEarlyTx DmaIntEarlyTx /* Early transmit interrupt enable RW 0 */
++#define DmaIeRxStopped DmaIntRxStopped /* Receive process stopped enable RW 0 */
++#define DmaIeRxNoBuffer DmaIntRxNoBuffer /* Receive buffer unavailable enable RW 0 */
++#define DmaIeRxCompleted DmaIntRxCompleted /* Completion of frame reception enable RW 0 */
++#define DmaIeTxUnderflow DmaIntTxUnderflow /* Transmit underflow enable RW 0 */
++#define DmaIeTxJabber DmaIntTxJabber /* Transmit jabber timeout RW 0 */
++#define DmaIeTxNoBuffer DmaIntTxNoBuffer /* Transmit buffer unavailable enable RW 0 */
++#define DmaIeTxStopped DmaIntTxStopped /* Transmit process stopped enable RW 0 */
++#define DmaIeTxCompleted DmaIntTxCompleted /* Transmit completed enable RW 0 */
++
++/****************************************************************/
++/* DMA Missed Frame and Buffer Overflow Counter register layout */
++/****************************************************************/
++#define DmaRxBufferMissedFrame 0xffff0000 /* cleared on read */
++#define DmaMissedFrameShift 16
++#define DmaRxBufferOverflowCnt 0x0000ffff /* cleared on read */
++#define DmaMissedFrameCountMask 0x0000ffff
++
++/**********************************************************/
++/* DMA Engine descriptor layout */
++/**********************************************************/
++/* status word of DMA descriptor */
++#define DescOwnByDma 0x80000000 /* Descriptor is owned by DMA engine */
++#define DescFrameLengthMask 0x3FFF0000 /* Receive descriptor frame length */
++#define DescFrameLengthShift 16
++#define DescError 0x00008000 /* Error summary bit OR of following bits */
++#define DescRxTruncated 0x00004000 /* Rx - no more descs for receive frame */
++#define DescRxLengthError 0x00001000 /* Rx - frame size not matching with length field */
++#define DescRxRunt 0x00000800 /* Rx - runt frame, damaged by a
++ collision or term before 64 bytes */
++#define DescRxMulticast 0x00000400 /* Rx - received frame is multicast */
++#define DescRxFirst 0x00000200 /* Rx - first descriptor of the frame */
++#define DescRxLast 0x00000100 /* Rx - last descriptor of the frame */
++#define DescRxLongFrame 0x00000080 /* Rx - frame is longer than 1518 bytes */
++#define DescRxLateColl 0x00000040 /* Rx - frame was damaged by a late collision */
++#define DescRxFrameEther 0x00000020 /* Rx - Frame type Ethernet 802.3*/
++#define DescRxMiiError 0x00000008 /* Rx - error reported by MII interface */
++#define DescRxDribbling 0x00000004 /* Rx - frame contains noninteger multiple of 8 bits */
++#define DescRxCrc 0x00000002 /* Rx - CRC error */
++#define DescTxTimeout 0x00004000 /* Tx - Transmit jabber timeout */
++#define DescTxLostCarrier 0x00000800 /* Tx - carrier lost during tramsmission */
++#define DescTxNoCarrier 0x00000400 /* Tx - no carrier signal from tranceiver */
++#define DescTxLateCollision 0x00000200 /* Tx - transmission aborted due to collision */
++#define DescTxExcCollisions 0x00000100 /* Tx - transmission aborted after 16 collisions */
++#define DescTxHeartbeatFail 0x00000080 /* Tx - heartbeat collision check failure */
++#define DescTxCollMask 0x00000078 /* Tx - Collision count */
++#define DescTxCollShift 3
++#define DescTxExcDeferral 0x00000004 /* Tx - excessive deferral */
++#define DescTxUnderflow 0x00000002 /* Tx - late data arrival from memory */
++#define DescTxDeferred 0x00000001 /* Tx - frame transmision deferred */
++
++/* length word of DMA descriptor */
++#define DescTxIntEnable 0x80000000 /* Tx - interrupt on completion */
++#define DescTxLast 0x40000000 /* Tx - Last segment of the frame */
++#define DescTxFirst 0x20000000 /* Tx - First segment of the frame */
++#define DescTxDisableCrc 0x04000000 /* Tx - Add CRC disabled (first segment only) */
++#define DescEndOfRing 0x02000000 /* End of descriptors ring */
++#define DescChain 0x01000000 /* Second buffer address is chain address */
++#define DescTxDisablePadd 0x00800000 /* disable padding */
++#define DescSize2Mask 0x003FF800 /* Buffer 2 size */
++#define DescSize2Shift 11
++#define DescSize1Mask 0x000007FF /* Buffer 1 size */
++#define DescSize1Shift 0
++
++/**********************************************************/
++/* Initial register values */
++/**********************************************************/
++/* Full-duplex mode with perfect filter on */
++#define MacControlInitFdx \
++ ( MacFilterOn \
++ | MacLittleEndian \
++ | MacHeartBeatOn \
++ | MacSelectMii \
++ | MacEnableRxOwn \
++ | MacLoopbackOff \
++ | MacFullDuplex \
++ | MacMulticastFilterOn \
++ | MacPromiscuousModeOff \
++ | MacFilterNormal \
++ | MacBadFramesDisable \
++ | MacPerfectFilterOn \
++ | MacHashFilterOff \
++ | MacLateCollisionOff \
++ | MacBroadcastEnable \
++ | MacRetryEnable \
++ | MacPadStripDisable \
++ | MacDeferralCheckDisable \
++ | MacTxEnable \
++ | MacRxEnable)
++
++/* Full-duplex mode */
++#define MacFlowControlInitFdx \
++ ( MacControlFrameDisable \
++ | MacFlowControlEnable)
++
++/* Half-duplex mode with perfect filter on */
++#define MacControlInitHdx \
++ ( MacFilterOn \
++ | MacLittleEndian \
++ | MacHeartBeatOn \
++ | MacSelectMii \
++ | MacDisableRxOwn \
++ | MacLoopbackOff \
++ | MacHalfDuplex \
++ | MacMulticastFilterOn \
++ | MacPromiscuousModeOff \
++ | MacFilterNormal \
++ | MacBadFramesDisable \
++ | MacPerfectFilterOn \
++ | MacHashFilterOff \
++ | MacLateCollisionOff \
++ | MacBroadcastEnable \
++ | MacRetryEnable \
++ | MacPadStripDisable \
++ | MacDeferralCheckDisable \
++ | MacTxEnable \
++ | MacRxEnable)
++
++/* Half-duplex mode */
++#define MacFlowControlInitHdx \
++ ( MacControlFrameDisable \
++ | MacFlowControlDisable)
++
++/* Bus Mode Rx odd half word align */
++#define DmaBusModeInit \
++ ( DmaLittleEndianDesc \
++ | DmaRxAlign16 \
++ | DmaBurstLength32 \
++ | DmaBigEndianData \
++ | DmaDescriptorSkip1 \
++ | DmaReceivePriorityOn \
++ | DmaResetOff)
++
++#define DmaControlInit (DmaStoreAndForward)
++
++/* Interrupt groups */
++#define DmaIntEnable \
++ ( DmaIeNormal \
++ | DmaIeAbnormal \
++ | DmaIntBusError \
++ | DmaIntRxStopped \
++ | DmaIntRxNoBuffer \
++ | DmaIntRxCompleted \
++ | DmaIntTxUnderflow \
++ | DmaIntTxStopped)
++
++#define DmaIntDisable 0
++
++#define DmaAllIntCauseMask \
++ ( DmaIeNormal \
++ | DmaIeAbnormal \
++ | DmaIntEarlyRx \
++ | DmaIntBusError \
++ | DmaIntEarlyTx \
++ | DmaIntRxStopped \
++ | DmaIntRxNoBuffer \
++ | DmaIntRxCompleted \
++ | DmaIntTxUnderflow \
++ | DmaIntTxJabber \
++ | DmaIntTxNoBuffer \
++ | DmaIntTxStopped \
++ | DmaIntTxCompleted)
++
++#define UnhandledIntrMask \
++ (DmaAllIntCauseMask \
++ & ~(DmaIntRxNoBuffer \
++ | DmaIntTxStopped \
++ | DmaIntTxJabber \
++ | DmaIntTxUnderflow \
++ | DmaIntBusError \
++ | DmaIntRxCompleted ))
++
++#define DescRxErrors \
++ (DescRxTruncated \
++ | DescRxRunt \
++ | DescRxLateColl \
++ | DescRxMiiError \
++ | DescRxCrc)
++
++#define DescTxErrors \
++ ( DescTxTimeout \
++ | DescTxLateCollision \
++ | DescTxExcCollisions \
++ | DescTxExcDeferral \
++ | DescTxUnderflow)
++
++/**********************************************************/
++/* Descriptor Layout */
++/**********************************************************/
++#define AE531X_DESC_STATUS 0x00 /* Status offset */
++#define AE531X_DESC_CTRLEN 0x04 /* Control and Length offset */
++#define AE531X_DESC_BUFPTR 0x08 /* Buffer pointer offset */
++#define AE531X_DESC_LNKBUF 0x0c /* Link field offset, or ptr to 2nd buf */
++#define AE531X_DESC_SWPTR 0x10 /* OS-Dependent software pointer */
++
++#define AE531X_DESC_SIZE 0x10 /* 4 words, 16 bytes */
++#define AE531X_QUEUE_ELE_SIZE 0x14 /* with software pointer extension */
++
++/* Accessors to the dma descriptor fields */
++#define AE531X_DESC_STATUS_GET(ptr) \
++ *(volatile UINT32 *)((UINT32)(ptr) + AE531X_DESC_STATUS)
++
++#define AE531X_DESC_STATUS_SET(ptr, val) \
++ AE531X_DESC_STATUS_GET(ptr) = (val)
++
++#define AE531X_DESC_CTRLEN_GET(ptr) \
++ *(volatile UINT32 *)((UINT32)ptr + AE531X_DESC_CTRLEN)
++
++#define AE531X_DESC_CTRLEN_SET(ptr, val) \
++ AE531X_DESC_CTRLEN_GET(ptr) = (val)
++
++#define AE531X_DESC_BUFPTR_GET(ptr) \
++ *(volatile UINT32 *)((UINT32)ptr + AE531X_DESC_BUFPTR)
++
++#define AE531X_DESC_BUFPTR_SET(ptr,val) \
++ AE531X_DESC_BUFPTR_GET(ptr) = (UINT32)(val)
++
++#define AE531X_DESC_LNKBUF_GET(ptr) \
++ *(volatile UINT32 *)((UINT32)ptr + AE531X_DESC_LNKBUF)
++
++#define AE531X_DESC_LNKBUF_SET(ptr, val) \
++ AE531X_DESC_LNKBUF_GET(ptr) = (val)
++
++#define AE531X_DESC_SWPTR_GET(ptr) \
++ (void *)(*(volatile UINT32 *) ((UINT32)ptr + AE531X_DESC_SWPTR))
++
++#define AE531X_DESC_SWPTR_SET(ptr,val) \
++ AE531X_DESC_SWPTR_GET(ptr) = (void *)(val)
++
++/* Get size of Rx data from desc, in bytes */
++#define AE531X_DESC_STATUS_RX_SIZE(x) \
++ (((x) & DescFrameLengthMask) >> DescFrameLengthShift)
++
++#endif /* _AE531XREG_H_ */
+diff -urN linux-mips-orig/drivers/net/ath/ar531x.h linux-mips-new/drivers/net/ath/ar531x.h
+--- linux-mips-orig/drivers/net/ath/ar531x.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/ar531x.h 2005-12-31 12:33:57.676538368 +0000
+@@ -0,0 +1,1124 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++ */
++
++#ifndef AR531X_H
++#define AR531X_H 1
++
++
++#ifndef CONFIG_AR5315
++
++#include <asm/addrspace.h>
++
++/* Address Map */
++#define AR531X_WLAN0 0x18000000
++#define AR531X_WLAN1 0x18500000
++#define AR531X_ENET0 0x18100000
++#define AR531X_ENET1 0x18200000
++#define AR531X_SDRAMCTL 0x18300000
++#define AR531X_FLASHCTL 0x18400000
++#define AR531X_APBBASE 0x1c000000
++#define AR531X_FLASH 0x1e000000
++
++/*
++ * AR531X_NUM_ENET_MAC defines the number of ethernet MACs that
++ * should be considered available. The AR5312 supports 2 enet MACS,
++ * even though many reference boards only actually use 1 of them
++ * (i.e. Only MAC 0 is actually connected to an enet PHY or PHY switch.
++ * The AR2312 supports 1 enet MAC.
++ */
++#define AR531X_NUM_ENET_MAC 2
++
++/*
++ * Need these defines to determine true number of ethernet MACs
++ */
++#define AR5212_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */
++#define AR5212_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */
++#define AR5212_AR2313_REV8 0x0058 /* AR2313 WMAC (AP43-030) */
++#define AR531X_RADIO_MASK_OFF 0xc8
++#define AR531X_RADIO0_MASK 0x0003
++#define AR531X_RADIO1_MASK 0x000c
++#define AR531X_RADIO1_S 2
++
++/*
++ * AR531X_NUM_WMAC defines the number of Wireless MACs that\
++ * should be considered available.
++ */
++#define AR531X_NUM_WMAC 2
++
++/* Reset/Timer Block Address Map */
++#define AR531X_RESETTMR (AR531X_APBBASE + 0x3000)
++#define AR531X_TIMER (AR531X_RESETTMR + 0x0000) /* countdown timer */
++#define AR531X_WD_CTRL (AR531X_RESETTMR + 0x0008) /* watchdog cntrl */
++#define AR531X_WD_TIMER (AR531X_RESETTMR + 0x000c) /* watchdog timer */
++#define AR531X_ISR (AR531X_RESETTMR + 0x0010) /* Intr Status Reg */
++#define AR531X_IMR (AR531X_RESETTMR + 0x0014) /* Intr Mask Reg */
++#define AR531X_RESET (AR531X_RESETTMR + 0x0020)
++#define AR5312_CLOCKCTL1 (AR531X_RESETTMR + 0x0064)
++#define AR5312_SCRATCH (AR531X_RESETTMR + 0x006c)
++#define AR531X_PROCADDR (AR531X_RESETTMR + 0x0070)
++#define AR531X_PROC1 (AR531X_RESETTMR + 0x0074)
++#define AR531X_DMAADDR (AR531X_RESETTMR + 0x0078)
++#define AR531X_DMA1 (AR531X_RESETTMR + 0x007c)
++#define AR531X_ENABLE (AR531X_RESETTMR + 0x0080) /* interface enb */
++#define AR531X_REV (AR531X_RESETTMR + 0x0090) /* revision */
++
++/* AR531X_WD_CTRL register bit field definitions */
++#define AR531X_WD_CTRL_IGNORE_EXPIRATION 0x0000
++#define AR531X_WD_CTRL_NMI 0x0001
++#define AR531X_WD_CTRL_RESET 0x0002
++
++/* AR531X_ISR register bit field definitions */
++#define AR531X_ISR_NONE 0x0000
++#define AR531X_ISR_TIMER 0x0001
++#define AR531X_ISR_AHBPROC 0x0002
++#define AR531X_ISR_AHBDMA 0x0004
++#define AR531X_ISR_GPIO 0x0008
++#define AR531X_ISR_UART0 0x0010
++#define AR531X_ISR_UART0DMA 0x0020
++#define AR531X_ISR_WD 0x0040
++#define AR531X_ISR_LOCAL 0x0080
++
++/* AR531X_RESET register bit field definitions */
++#define AR531X_RESET_SYSTEM 0x00000001 /* cold reset full system */
++#define AR531X_RESET_PROC 0x00000002 /* cold reset MIPS core */
++#define AR531X_RESET_WLAN0 0x00000004 /* cold reset WLAN MAC and BB */
++#define AR531X_RESET_EPHY0 0x00000008 /* cold reset ENET0 phy */
++#define AR531X_RESET_EPHY1 0x00000010 /* cold reset ENET1 phy */
++#define AR531X_RESET_ENET0 0x00000020 /* cold reset ENET0 mac */
++#define AR531X_RESET_ENET1 0x00000040 /* cold reset ENET1 mac */
++#define AR531X_RESET_UART0 0x00000100 /* cold reset UART0 (high speed) */
++#define AR531X_RESET_WLAN1 0x00000200 /* cold reset WLAN MAC/BB */
++#define AR531X_RESET_APB 0x00000400 /* cold reset APB (ar5312) */
++#define AR531X_RESET_WARM_PROC 0x00001000 /* warm reset MIPS core */
++#define AR531X_RESET_WARM_WLAN0_MAC 0x00002000 /* warm reset WLAN0 MAC */
++#define AR531X_RESET_WARM_WLAN0_BB 0x00004000 /* warm reset WLAN0 BaseBand */
++#define AR531X_RESET_NMI 0x00010000 /* send an NMI to the processor */
++#define AR531X_RESET_WARM_WLAN1_MAC 0x00020000 /* warm reset WLAN1 mac */
++#define AR531X_RESET_WARM_WLAN1_BB 0x00040000 /* warm reset WLAN1 baseband */
++#define AR531X_RESET_LOCAL_BUS 0x00080000 /* reset local bus */
++#define AR531X_RESET_WDOG 0x00100000 /* last reset was a watchdog */
++
++#define AR531X_RESET_WMAC0_BITS \
++ AR531X_RESET_WLAN0 |\
++ AR531X_RESET_WARM_WLAN0_MAC |\
++ AR531X_RESET_WARM_WLAN0_BB
++
++#define AR531X_RESERT_WMAC1_BITS \
++ AR531X_RESET_WLAN1 |\
++ AR531X_RESET_WARM_WLAN1_MAC |\
++ AR531X_RESET_WARM_WLAN1_BB
++
++/* AR5312_CLOCKCTL1 register bit field definitions */
++#define AR5312_CLOCKCTL1_PREDIVIDE_MASK 0x00000030
++#define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT 4
++#define AR5312_CLOCKCTL1_MULTIPLIER_MASK 0x00001f00
++#define AR5312_CLOCKCTL1_MULTIPLIER_SHIFT 8
++#define AR5312_CLOCKCTL1_DOUBLER_MASK 0x00010000
++
++/* Valid for AR5312 and AR2312 */
++#define AR5312_CLOCKCTL1_PREDIVIDE_MASK 0x00000030
++#define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT 4
++#define AR5312_CLOCKCTL1_MULTIPLIER_MASK 0x00001f00
++#define AR5312_CLOCKCTL1_MULTIPLIER_SHIFT 8
++#define AR5312_CLOCKCTL1_DOUBLER_MASK 0x00010000
++
++/* Valid for AR2313 */
++#define AR2313_CLOCKCTL1_PREDIVIDE_MASK 0x00003000
++#define AR2313_CLOCKCTL1_PREDIVIDE_SHIFT 12
++#define AR2313_CLOCKCTL1_MULTIPLIER_MASK 0x001f0000
++#define AR2313_CLOCKCTL1_MULTIPLIER_SHIFT 16
++#define AR2313_CLOCKCTL1_DOUBLER_MASK 0x00000000
++
++
++/* AR531X_ENABLE register bit field definitions */
++#define AR531X_ENABLE_WLAN0 0x0001
++#define AR531X_ENABLE_ENET0 0x0002
++#define AR531X_ENABLE_ENET1 0x0004
++#define AR531X_ENABLE_UART_AND_WLAN1_PIO 0x0008 /* UART, and WLAN1 PIOs */
++#define AR531X_ENABLE_WLAN1_DMA 0x0010 /* WLAN1 DMAs */
++#define AR531X_ENABLE_WLAN1 \
++ (AR531X_ENABLE_UART_AND_WLAN1_PIO | AR531X_ENABLE_WLAN1_DMA)
++
++/* AR531X_REV register bit field definitions */
++#define AR531X_REV_WMAC_MAJ 0xf000
++#define AR531X_REV_WMAC_MAJ_S 12
++#define AR531X_REV_WMAC_MIN 0x0f00
++#define AR531X_REV_WMAC_MIN_S 8
++#define AR531X_REV_MAJ 0x00f0
++#define AR531X_REV_MAJ_S 4
++#define AR531X_REV_MIN 0x000f
++#define AR531X_REV_MIN_S 0
++#define AR531X_REV_CHIP (REV_MAJ|REV_MIN)
++
++/* Major revision numbers, bits 7..4 of Revision ID register */
++#define AR531X_REV_MAJ_AR5312 0x4
++#define AR531X_REV_MAJ_AR2313 0x5
++
++/* Minor revision numbers, bits 3..0 of Revision ID register */
++#define AR5312_REV_MIN_DUAL 0x0 /* Dual WLAN version */
++#define AR5312_REV_MIN_SINGLE 0x1 /* Single WLAN version */
++
++/* AR531X_FLASHCTL register bit field definitions */
++#define FLASHCTL_IDCY 0x0000000f /* Idle cycle turn around time */
++#define FLASHCTL_IDCY_S 0
++#define FLASHCTL_WST1 0x000003e0 /* Wait state 1 */
++#define FLASHCTL_WST1_S 5
++#define FLASHCTL_RBLE 0x00000400 /* Read byte lane enable */
++#define FLASHCTL_WST2 0x0000f800 /* Wait state 2 */
++#define FLASHCTL_WST2_S 11
++#define FLASHCTL_AC 0x00070000 /* Flash address check (added) */
++#define FLASHCTL_AC_S 16
++#define FLASHCTL_AC_128K 0x00000000
++#define FLASHCTL_AC_256K 0x00010000
++#define FLASHCTL_AC_512K 0x00020000
++#define FLASHCTL_AC_1M 0x00030000
++#define FLASHCTL_AC_2M 0x00040000
++#define FLASHCTL_AC_4M 0x00050000
++#define FLASHCTL_AC_8M 0x00060000
++#define FLASHCTL_AC_RES 0x00070000 /* 16MB is not supported */
++#define FLASHCTL_E 0x00080000 /* Flash bank enable (added) */
++#define FLASHCTL_BUSERR 0x01000000 /* Bus transfer error status flag */
++#define FLASHCTL_WPERR 0x02000000 /* Write protect error status flag */
++#define FLASHCTL_WP 0x04000000 /* Write protect */
++#define FLASHCTL_BM 0x08000000 /* Burst mode */
++#define FLASHCTL_MW 0x30000000 /* Memory width */
++#define FLASHCTL_MWx8 0x00000000 /* Memory width x8 */
++#define FLASHCTL_MWx16 0x10000000 /* Memory width x16 */
++#define FLASHCTL_MWx32 0x20000000 /* Memory width x32 (not supported) */
++#define FLASHCTL_ATNR 0x00000000 /* Access type == no retry */
++#define FLASHCTL_ATR 0x80000000 /* Access type == retry every */
++#define FLASHCTL_ATR4 0xc0000000 /* Access type == retry every 4 */
++
++/* ARM Flash Controller -- 3 flash banks with either x8 or x16 devices. */
++#define AR531X_FLASHCTL0 (AR531X_FLASHCTL + 0x00)
++#define AR531X_FLASHCTL1 (AR531X_FLASHCTL + 0x04)
++#define AR531X_FLASHCTL2 (AR531X_FLASHCTL + 0x08)
++
++/* ARM SDRAM Controller -- just enough to determine memory size */
++#define AR531X_MEM_CFG1 (AR531X_SDRAMCTL + 0x04)
++#define MEM_CFG1_AC0 0x00000700 /* bank 0: SDRAM addr check (added) */
++#define MEM_CFG1_AC0_S 8
++#define MEM_CFG1_AC1 0x00007000 /* bank 1: SDRAM addr check (added) */
++#define MEM_CFG1_AC1_S 12
++
++/* GPIO Address Map */
++#define AR531X_GPIO (AR531X_APBBASE + 0x2000)
++#define AR531X_GPIO_DO (AR531X_GPIO + 0x00) /* output register */
++#define AR531X_GPIO_DI (AR531X_GPIO + 0x04) /* intput register */
++#define AR531X_GPIO_CR (AR531X_GPIO + 0x08) /* control register */
++
++/* GPIO Control Register bit field definitions */
++#define GPIO_CR_M(x) (1 << (x)) /* mask for i/o */
++#define GPIO_CR_O(x) (0 << (x)) /* mask for output */
++#define GPIO_CR_I(x) (1 << (x)) /* mask for input */
++#define GPIO_CR_INT(x) (1 << ((x)+8)) /* mask for interrupt */
++#define GPIO_CR_UART(x) (1 << ((x)+16)) /* uart multiplex */
++
++
++typedef unsigned int AR531X_REG;
++
++#define sysRegRead(phys) \
++ (*(volatile AR531X_REG *)PHYS_TO_K1(phys))
++
++#define sysRegWrite(phys, val) \
++ ((*(volatile AR531X_REG *)PHYS_TO_K1(phys)) = (val))
++
++
++/*
++ * This is board-specific data that is stored in a "fixed" location in flash.
++ * It is shared across operating systems, so it should not be changed lightly.
++ * The main reason we need it is in order to extract the ethernet MAC
++ * address(es).
++ */
++struct ar531x_boarddata {
++ u32 magic; /* board data is valid */
++#define AR531X_BD_MAGIC 0x35333131 /* "5311", for all 531x platforms */
++ u16 cksum; /* checksum (starting with BD_REV 2) */
++ u16 rev; /* revision of this struct */
++#define BD_REV 4
++ char boardName[64]; /* Name of board */
++ u16 major; /* Board major number */
++ u16 minor; /* Board minor number */
++ u32 config; /* Board configuration */
++#define BD_ENET0 0x00000001 /* ENET0 is stuffed */
++#define BD_ENET1 0x00000002 /* ENET1 is stuffed */
++#define BD_UART1 0x00000004 /* UART1 is stuffed */
++#define BD_UART0 0x00000008 /* UART0 is stuffed (dma) */
++#define BD_RSTFACTORY 0x00000010 /* Reset factory defaults stuffed */
++#define BD_SYSLED 0x00000020 /* System LED stuffed */
++#define BD_EXTUARTCLK 0x00000040 /* External UART clock */
++#define BD_CPUFREQ 0x00000080 /* cpu freq is valid in nvram */
++#define BD_SYSFREQ 0x00000100 /* sys freq is set in nvram */
++#define BD_WLAN0 0x00000200 /* Enable WLAN0 */
++#define BD_MEMCAP 0x00000400 /* CAP SDRAM @ memCap for testing */
++#define BD_DISWATCHDOG 0x00000800 /* disable system watchdog */
++#define BD_WLAN1 0x00001000 /* Enable WLAN1 (ar5212) */
++#define BD_ISCASPER 0x00002000 /* FLAG for AR2312 */
++#define BD_WLAN0_2G_EN 0x00004000 /* FLAG for radio0_2G */
++#define BD_WLAN0_5G_EN 0x00008000 /* FLAG for radio0_2G */
++#define BD_WLAN1_2G_EN 0x00020000 /* FLAG for radio0_2G */
++#define BD_WLAN1_5G_EN 0x00040000 /* FLAG for radio0_2G */
++ u16 resetConfigGpio; /* Reset factory GPIO pin */
++ u16 sysLedGpio; /* System LED GPIO pin */
++
++ u32 cpuFreq; /* CPU core frequency in Hz */
++ u32 sysFreq; /* System frequency in Hz */
++ u32 cntFreq; /* Calculated C0_COUNT frequency */
++
++ u8 wlan0Mac[6];
++ u8 enet0Mac[6];
++ u8 enet1Mac[6];
++
++ u16 pciId; /* Pseudo PCIID for common code */
++ u16 memCap; /* cap bank1 in MB */
++
++ /* version 3 */
++ u8 wlan1Mac[6]; /* (ar5212) */
++};
++
++#else
++
++/*
++ * Add support for Cobra
++ *
++ * AR531XPLUSreg.h Register definitions for Atheros AR5311 and AR5312 chipsets.
++ * - WLAN registers are listed in
++ * hal/ar5211/ar5211Reg.h
++ * hal/ar5212/ar5212Reg.h
++ * - Ethernet registers are listed in ar531xenet.h
++ * - Standard UART is 16550 compatible.
++ */
++
++
++/*
++ * Address map
++ */
++#define AR531XPLUS_SDRAM0 0x00000000 /* DRAM */
++#define AR531XPLUS_SPI_READ 0x08000000 /* SPI FLASH */
++#define AR531XPLUS_WLAN0 0xB0000000 /* Wireless MMR */
++#define AR531XPLUS_PCI 0xB0100000 /* PCI MMR */
++#define AR531XPLUS_SDRAMCTL 0xB0300000 /* SDRAM MMR */
++#define AR531XPLUS_LOCAL 0xB0400000 /* LOCAL BUS MMR */
++#define AR531XPLUS_ENET0 0xB0500000 /* ETHERNET MMR */
++#define AR531XPLUS_DSLBASE 0xB1000000 /* RESET CONTROL MMR */
++#define AR531XPLUS_UART0 0xB1100003 /* UART MMR */
++#define AR531XPLUS_SPI 0xB1300000 /* SPI FLASH MMR */
++#define AR531XPLUS_FLASHBT 0xBfc00000 /* ro boot alias to FLASH */
++#define AR531XPLUS_RAM1 0x40000000 /* ram alias */
++#define AR531XPLUS_PCIEXT 0x80000000 /* pci external */
++#define AR531XPLUS_RAM2 0xc0000000 /* ram alias */
++#define AR531XPLUS_RAM3 0xe0000000 /* ram alias */
++
++#define AR531X_ENET0 AR531XPLUS_ENET0
++#define AR531X_ENET1 0
++/*
++ * Reset Register
++ */
++#define AR531XPLUS_COLD_RESET (AR531XPLUS_DSLBASE + 0x0000)
++
++/* Cold Reset */
++#define RESET_COLD_AHB 0x00000001
++#define RESET_COLD_APB 0x00000002
++#define RESET_COLD_CPU 0x00000004
++#define RESET_COLD_CPUWARM 0x00000008
++#define RESET_SYSTEM (RESET_COLD_CPU | RESET_COLD_APB | RESET_COLD_AHB) /* full system */
++
++/* Warm Reset */
++
++#define AR531XPLUS_RESET (AR531XPLUS_DSLBASE + 0x0004)
++#define AR531X_RESET AR531XPLUS_RESET
++
++#define RESET_WARM_WLAN0_MAC 0x00000001 /* warm reset WLAN0 MAC */
++#define RESET_WARM_WLAN0_BB 0x00000002 /* warm reset WLAN0 BaseBand */
++#define RESET_MPEGTS_RSVD 0x00000004 /* warm reset MPEG-TS */
++#define RESET_PCIDMA 0x00000008 /* warm reset PCI ahb/dma */
++#define RESET_MEMCTL 0x00000010 /* warm reset memory controller */
++#define RESET_LOCAL 0x00000020 /* warm reset local bus */
++#define RESET_I2C_RSVD 0x00000040 /* warm reset I2C bus */
++#define RESET_SPI 0x00000080 /* warm reset SPI interface */
++#define RESET_UART0 0x00000100 /* warm reset UART0 */
++#define RESET_IR_RSVD 0x00000200 /* warm reset IR interface */
++#define RESET_EPHY0 0x00000400 /* cold reset ENET0 phy */
++#define RESET_ENET0 0x00000800 /* cold reset ENET0 mac */
++
++#define AR531X_RESET_ENET0 RESET_ENET0
++#define AR531X_RESET_EPHY0 RESET_EPHY0
++#define AR531X_RESET_ENET1 0
++#define AR531X_RESET_EPHY1 0
++
++/*
++ * AHB master arbitration control
++ */
++#define AR531XPLUS_AHB_ARB_CTL (AR531XPLUS_DSLBASE + 0x0008)
++
++#define ARB_CPU 0x00000001 /* CPU, default */
++#define ARB_WLAN 0x00000002 /* WLAN */
++#define ARB_MPEGTS_RSVD 0x00000004 /* MPEG-TS */
++#define ARB_LOCAL 0x00000008 /* LOCAL */
++#define ARB_PCI 0x00000010 /* PCI */
++#define ARB_ETHERNET 0x00000020 /* Ethernet */
++#define ARB_RETRY 0x00000100 /* retry policy, debug only */
++
++/*
++ * Config Register
++ */
++#define AR531XPLUS_ENDIAN_CTL (AR531XPLUS_DSLBASE + 0x000c)
++
++#define CONFIG_AHB 0x00000001 /* EC - AHB bridge endianess */
++#define CONFIG_WLAN 0x00000002 /* WLAN byteswap */
++#define CONFIG_MPEGTS_RSVD 0x00000004 /* MPEG-TS byteswap */
++#define CONFIG_PCI 0x00000008 /* PCI byteswap */
++#define CONFIG_MEMCTL 0x00000010 /* Memory controller endianess */
++#define CONFIG_LOCAL 0x00000020 /* Local bus byteswap */
++#define CONFIG_ETHERNET 0x00000040 /* Ethernet byteswap */
++
++#define CONFIG_MERGE 0x00000200 /* CPU write buffer merge */
++#define CONFIG_CPU 0x00000400 /* CPU big endian */
++#define CONFIG_PCIAHB 0x00000800
++#define CONFIG_PCIAHB_BRIDGE 0x00001000
++#define CONFIG_SPI 0x00008000 /* SPI byteswap */
++#define CONFIG_CPU_DRAM 0x00010000
++#define CONFIG_CPU_PCI 0x00020000
++#define CONFIG_CPU_MMR 0x00040000
++#define CONFIG_BIG 0x00000400
++
++
++/*
++ * NMI control
++ */
++#define AR531XPLUS_NMI_CTL (AR531XPLUS_DSLBASE + 0x0010)
++
++#define NMI_EN 1
++
++/*
++ * Revision Register - Initial value is 0x3010 (WMAC 3.0, AR531X 1.0).
++ */
++#define AR531XPLUS_SREV (AR531XPLUS_DSLBASE + 0x0014)
++
++#define AR531X_REV AR531XPLUS_SREV
++
++#define REV_MAJ 0x00f0
++#define REV_MAJ_S 4
++#define REV_MIN 0x000f
++#define REV_MIN_S 0
++#define REV_CHIP (REV_MAJ|REV_MIN)
++
++#define AR531X_REV_MAJ REV_MAJ
++#define AR531X_REV_MAJ_S REV_MAJ_S
++#define AR531X_REV_MIN REV_MIN
++#define AR531X_REV_MIN_S REV_MIN_S
++#define REV_CHIP (REV_MAJ|REV_MIN)
++/*
++ * Need these defines to determine true number of ethernet MACs
++ */
++#define AR5212_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */
++#define AR5212_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */
++#define AR5212_AR2313_REV8 0x0058 /* AR2313 WMAC (AP43-030) */
++#define AR531X_RADIO_MASK_OFF 0xc8
++#define AR531X_RADIO0_MASK 0x0003
++#define AR531X_RADIO1_MASK 0x000c
++#define AR531X_RADIO1_S 2
++
++/* Major revision numbers, bits 7..4 of Revision ID register */
++#define AR531X_REV_MAJ_AR5312 0x4
++#define AR531X_REV_MAJ_AR2313 0x5
++
++/*
++ * AR531X_NUM_ENET_MAC defines the number of ethernet MACs that
++ * should be considered available. The AR5312 supports 2 enet MACS,
++ * even though many reference boards only actually use 1 of them
++ * (i.e. Only MAC 0 is actually connected to an enet PHY or PHY switch.
++ * The AR2312 supports 1 enet MAC.
++ */
++#define AR531X_NUM_ENET_MAC 1
++
++/*
++ * Interface Enable
++ */
++#define AR531XPLUS_IF_CTL (AR531XPLUS_DSLBASE + 0x0018)
++
++#define IF_MASK 0x00000007
++#define IF_DISABLED 0
++#define IF_PCI 1
++#define IF_TS_LOCAL 2
++#define IF_ALL 3 /* only for emulation with separate pins */
++#define IF_LOCAL_HOST 0x00000008
++#define IF_PCI_HOST 0x00000010
++#define IF_PCI_INTR 0x00000020
++#define IF_PCI_CLK_MASK 0x00030000
++#define IF_PCI_CLK_INPUT 0
++#define IF_PCI_CLK_OUTPUT_LOW 1
++#define IF_PCI_CLK_OUTPUT_CLK 2
++#define IF_PCI_CLK_OUTPUT_HIGH 3
++#define IF_PCI_CLK_SHIFT 16
++
++
++/* Major revision numbers, bits 7..4 of Revision ID register */
++#define REV_MAJ_AR5311 0x01
++#define REV_MAJ_AR5312 0x04
++#define REV_MAJ_AR5315 0x0B
++
++/*
++ * APB Interrupt control
++ */
++
++#define AR531XPLUS_ISR (AR531XPLUS_DSLBASE + 0x0020)
++#define AR531XPLUS_IMR (AR531XPLUS_DSLBASE + 0x0024)
++#define AR531XPLUS_GISR (AR531XPLUS_DSLBASE + 0x0028)
++
++#define ISR_UART0 0x0001 /* high speed UART */
++#define ISR_I2C_RSVD 0x0002 /* I2C bus */
++#define ISR_SPI 0x0004 /* SPI bus */
++#define ISR_AHB 0x0008 /* AHB error */
++#define ISR_APB 0x0010 /* APB error */
++#define ISR_TIMER 0x0020 /* timer */
++#define ISR_GPIO 0x0040 /* GPIO */
++#define ISR_WD 0x0080 /* watchdog */
++#define ISR_IR_RSVD 0x0100 /* IR */
++
++#define IMR_UART0 ISR_UART0
++#define IMR_I2C_RSVD ISR_I2C_RSVD
++#define IMR_SPI ISR_SPI
++#define IMR_AHB ISR_AHB
++#define IMR_APB ISR_APB
++#define IMR_TIMER ISR_TIMER
++#define IMR_GPIO ISR_GPIO
++#define IMR_WD ISR_WD
++#define IMR_IR_RSVD ISR_IR_RSVD
++
++#define GISR_MISC 0x0001
++#define GISR_WLAN0 0x0002
++#define GISR_MPEGTS_RSVD 0x0004
++#define GISR_LOCALPCI 0x0008
++#define GISR_WMACPOLL 0x0010
++#define GISR_TIMER 0x0020
++#define GISR_ETHERNET 0x0040
++
++/*
++ * Interrupt routing from IO to the processor IP bits
++ * Define our inter mask and level
++ */
++#define AR531XPLUS_INTR_MISCIO SR_IBIT3
++#define AR531XPLUS_INTR_WLAN0 SR_IBIT4
++#define AR531XPLUS_INTR_ENET0 SR_IBIT5
++#define AR531XPLUS_INTR_LOCALPCI SR_IBIT6
++#define AR531XPLUS_INTR_WMACPOLL SR_IBIT7
++#define AR531XPLUS_INTR_COMPARE SR_IBIT8
++
++/*
++ * Timers
++ */
++#define AR531XPLUS_TIMER (AR531XPLUS_DSLBASE + 0x0030)
++#define AR531XPLUS_RELOAD (AR531XPLUS_DSLBASE + 0x0034)
++#define AR531XPLUS_WD (AR531XPLUS_DSLBASE + 0x0038)
++#define AR531XPLUS_WDC (AR531XPLUS_DSLBASE + 0x003c)
++
++#define WDC_RESET 0x00000002 /* reset on watchdog */
++#define WDC_NMI 0x00000001 /* NMI on watchdog */
++#define WDC_IGNORE_EXPIRATION 0x00000000
++
++/*
++ * Interface Debug
++ */
++#define AR531X_FLASHDBG (AR531X_RESETTMR + 0x0040)
++#define AR531X_MIIDBG (AR531X_RESETTMR + 0x0044)
++
++
++/*
++ * CPU Performance Counters
++ */
++#define AR531XPLUS_PERFCNT0 (AR531XPLUS_DSLBASE + 0x0048)
++#define AR531XPLUS_PERFCNT1 (AR531XPLUS_DSLBASE + 0x004c)
++
++#define PERF_DATAHIT 0x0001 /* Count Data Cache Hits */
++#define PERF_DATAMISS 0x0002 /* Count Data Cache Misses */
++#define PERF_INSTHIT 0x0004 /* Count Instruction Cache Hits */
++#define PERF_INSTMISS 0x0008 /* Count Instruction Cache Misses */
++#define PERF_ACTIVE 0x0010 /* Count Active Processor Cycles */
++#define PERF_WBHIT 0x0020 /* Count CPU Write Buffer Hits */
++#define PERF_WBMISS 0x0040 /* Count CPU Write Buffer Misses */
++
++#define PERF_EB_ARDY 0x0001 /* Count EB_ARdy signal */
++#define PERF_EB_AVALID 0x0002 /* Count EB_AValid signal */
++#define PERF_EB_WDRDY 0x0004 /* Count EB_WDRdy signal */
++#define PERF_EB_RDVAL 0x0008 /* Count EB_RdVal signal */
++#define PERF_VRADDR 0x0010 /* Count valid read address cycles */
++#define PERF_VWADDR 0x0020 /* Count valid write address cycles */
++#define PERF_VWDATA 0x0040 /* Count valid write data cycles */
++
++/*
++ * AHB Error Reporting.
++ */
++#define AR531XPLUS_AHB_ERR0 (AR531XPLUS_DSLBASE + 0x0050) /* error */
++#define AR531XPLUS_AHB_ERR1 (AR531XPLUS_DSLBASE + 0x0054) /* haddr */
++#define AR531XPLUS_AHB_ERR2 (AR531XPLUS_DSLBASE + 0x0058) /* hwdata */
++#define AR531XPLUS_AHB_ERR3 (AR531XPLUS_DSLBASE + 0x005c) /* hrdata */
++#define AR531XPLUS_AHB_ERR4 (AR531XPLUS_DSLBASE + 0x0060) /* status */
++
++#define AHB_ERROR_DET 1 /* AHB Error has been detected, */
++ /* write 1 to clear all bits in ERR0 */
++#define AHB_ERROR_OVR 2 /* AHB Error overflow has been detected */
++#define AHB_ERROR_WDT 4 /* AHB Error due to wdt instead of hresp */
++
++#define PROCERR_HMAST 0x0000000f
++#define PROCERR_HMAST_DFLT 0
++#define PROCERR_HMAST_WMAC 1
++#define PROCERR_HMAST_ENET 2
++#define PROCERR_HMAST_PCIENDPT 3
++#define PROCERR_HMAST_LOCAL 4
++#define PROCERR_HMAST_CPU 5
++#define PROCERR_HMAST_PCITGT 6
++
++#define PROCERR_HMAST_S 0
++#define PROCERR_HWRITE 0x00000010
++#define PROCERR_HSIZE 0x00000060
++#define PROCERR_HSIZE_S 5
++#define PROCERR_HTRANS 0x00000180
++#define PROCERR_HTRANS_S 7
++#define PROCERR_HBURST 0x00000e00
++#define PROCERR_HBURST_S 9
++
++
++
++/*
++ * Clock Control
++ */
++#define AR531XPLUS_PLLC_CTL (AR531XPLUS_DSLBASE + 0x0064)
++#define AR531XPLUS_PLLV_CTL (AR531XPLUS_DSLBASE + 0x0068)
++#define AR531XPLUS_CPUCLK (AR531XPLUS_DSLBASE + 0x006c)
++#define AR531XPLUS_AMBACLK (AR531XPLUS_DSLBASE + 0x0070)
++#define AR531XPLUS_SYNCCLK (AR531XPLUS_DSLBASE + 0x0074)
++#define AR531XPLUS_DSL_SLEEP_CTL (AR531XPLUS_DSLBASE + 0x0080)
++#define AR531XPLUS_DSL_SLEEP_DUR (AR531XPLUS_DSLBASE + 0x0084)
++
++/* PLLc Control fields */
++#define PLLC_REF_DIV_M 0x00000003
++#define PLLC_REF_DIV_S 0
++#define PLLC_FDBACK_DIV_M 0x0000007C
++#define PLLC_FDBACK_DIV_S 2
++#define PLLC_ADD_FDBACK_DIV_M 0x00000080
++#define PLLC_ADD_FDBACK_DIV_S 7
++#define PLLC_CLKC_DIV_M 0x0001c000
++#define PLLC_CLKC_DIV_S 14
++#define PLLC_CLKM_DIV_M 0x00700000
++#define PLLC_CLKM_DIV_S 20
++
++/* CPU CLK Control fields */
++#define CPUCLK_CLK_SEL_M 0x00000003
++#define CPUCLK_CLK_SEL_S 0
++#define CPUCLK_CLK_DIV_M 0x0000000c
++#define CPUCLK_CLK_DIV_S 2
++
++/* AMBA CLK Control fields */
++#define AMBACLK_CLK_SEL_M 0x00000003
++#define AMBACLK_CLK_SEL_S 0
++#define AMBACLK_CLK_DIV_M 0x0000000c
++#define AMBACLK_CLK_DIV_S 2
++
++#if defined(COBRA_EMUL)
++#define AR531XPLUS_AMBA_CLOCK_RATE 20000000
++#define AR531XPLUS_CPU_CLOCK_RATE 40000000
++#else
++#if defined(DEFAULT_PLL)
++#define AR531XPLUS_AMBA_CLOCK_RATE 40000000
++#define AR531XPLUS_CPU_CLOCK_RATE 40000000
++#else
++#define AR531XPLUS_AMBA_CLOCK_RATE 92000000
++#define AR531XPLUS_CPU_CLOCK_RATE 184000000
++#endif /* ! DEFAULT_PLL */
++#endif /* ! COBRA_EMUL */
++
++#define AR531XPLUS_UART_CLOCK_RATE AR531XPLUS_AMBA_CLOCK_RATE
++#define AR531XPLUS_SDRAM_CLOCK_RATE AR531XPLUS_AMBA_CLOCK_RATE
++
++/*
++ * The UART computes baud rate as:
++ * baud = clock / (16 * divisor)
++ * where divisor is specified as a High Byte (DLM) and a Low Byte (DLL).
++ */
++#define DESIRED_BAUD_RATE 38400
++
++/*
++ * The WATCHDOG value is computed as
++ * 10 seconds * AR531X_WATCHDOG_CLOCK_RATE
++ */
++#define DESIRED_WATCHDOG_SECONDS 10
++#define AR531X_WATCHDOG_TIME \
++ (DESIRED_WATCHDOG_SECONDS * AR531X_WATCHDOG_CLOCK_RATE)
++
++
++#define CLOCKCTL_UART0 0x0010 /* enable UART0 external clock */
++
++
++ /*
++ * Applicable "PCICFG" bits for WLAN(s). Assoc status and LED mode.
++ */
++#define AR531X_PCICFG (AR531X_RESETTMR + 0x00b0)
++#define ASSOC_STATUS_M 0x00000003
++#define ASSOC_STATUS_NONE 0
++#define ASSOC_STATUS_PENDING 1
++#define ASSOC_STATUS_ASSOCIATED 2
++#define LED_MODE_M 0x0000001c
++#define LED_BLINK_THRESHOLD_M 0x000000e0
++#define LED_SLOW_BLINK_MODE 0x00000100
++
++/*
++ * GPIO
++ */
++
++#define AR531XPLUS_GPIO_DI (AR531XPLUS_DSLBASE + 0x0088)
++#define AR531XPLUS_GPIO_DO (AR531XPLUS_DSLBASE + 0x0090)
++#define AR531XPLUS_GPIO_CR (AR531XPLUS_DSLBASE + 0x0098)
++#define AR531XPLUS_GPIO_INT (AR531XPLUS_DSLBASE + 0x00a0)
++
++#define GPIO_CR_M(x) (1 << (x)) /* mask for i/o */
++#define GPIO_CR_O(x) (1 << (x)) /* output */
++#define GPIO_CR_I(x) (0 << (x)) /* input */
++
++#define GPIO_INT(x,Y) ((x) << (8 * (Y))) /* interrupt enable */
++#define GPIO_INT_M(Y) ((0x3F) << (8 * (Y))) /* mask for int */
++#define GPIO_INT_LVL(x,Y) ((x) << (8 * (Y) + 6)) /* interrupt level */
++#define GPIO_INT_LVL_M(Y) ((0x3) << (8 * (Y) + 6)) /* mask for int level */
++
++#define AR531XPLUS_RESET_GPIO 5
++#define AR531XPLUS_NUM_GPIO 22
++
++
++/*
++ * PCI Clock Control
++ */
++
++#define AR531XPLUS_PCICLK (AR531XPLUS_DSLBASE + 0x00a4)
++
++#define PCICLK_INPUT_M 0x3
++#define PCICLK_INPUT_S 0
++
++#define PCICLK_PLLC_CLKM 0
++#define PCICLK_PLLC_CLKM1 1
++#define PCICLK_PLLC_CLKC 2
++#define PCICLK_REF_CLK 3
++
++#define PCICLK_DIV_M 0xc
++#define PCICLK_DIV_S 2
++
++#define PCICLK_IN_FREQ 0
++#define PCICLK_IN_FREQ_DIV_6 1
++#define PCICLK_IN_FREQ_DIV_8 2
++#define PCICLK_IN_FREQ_DIV_10 3
++
++/*
++ * Observation Control Register
++ */
++#define AR531XPLUS_OCR (AR531XPLUS_DSLBASE + 0x00b0)
++#define OCR_GPIO0_IRIN 0x0040
++#define OCR_GPIO1_IROUT 0x0080
++#define OCR_GPIO3_RXCLR 0x0200
++
++/*
++ * General Clock Control
++ */
++
++#define AR531XPLUS_MISCCLK (AR531XPLUS_DSLBASE + 0x00b4)
++#define MISCCLK_PLLBYPASS_EN 0x00000001
++#define MISCCLK_PROCREFCLK 0x00000002
++
++/*
++ * SDRAM Controller
++ * - No read or write buffers are included.
++ */
++#define AR531XPLUS_MEM_CFG (AR531XPLUS_SDRAMCTL + 0x00)
++#define AR531XPLUS_MEM_CTRL (AR531XPLUS_SDRAMCTL + 0x0c)
++#define AR531XPLUS_MEM_REF (AR531XPLUS_SDRAMCTL + 0x10)
++
++#define SDRAM_DATA_WIDTH_M 0x00006000
++#define SDRAM_DATA_WIDTH_S 13
++
++#define SDRAM_COL_WIDTH_M 0x00001E00
++#define SDRAM_COL_WIDTH_S 9
++
++#define SDRAM_ROW_WIDTH_M 0x000001E0
++#define SDRAM_ROW_WIDTH_S 5
++
++#define SDRAM_BANKADDR_BITS_M 0x00000018
++#define SDRAM_BANKADDR_BITS_S 3
++
++
++/*
++ * SDRAM Memory Refresh (MEM_REF) value is computed as:
++ * MEMCTL_SREFR = (Tr * hclk_freq) / R
++ * where Tr is max. time of refresh of any single row
++ * R is number of rows in the DRAM
++ * For most 133MHz SDRAM parts, Tr=64ms, R=4096 or 8192
++ */
++#if defined(COBRA_EMUL)
++#define AR531XPLUS_SDRAM_MEMORY_REFRESH_VALUE 0x96
++#else
++#if defined(DEFAULT_PLL)
++#define AR531XPLUS_SDRAM_MEMORY_REFRESH_VALUE 0x200
++#else
++#define AR531XPLUS_SDRAM_MEMORY_REFRESH_VALUE 0x61a
++#endif /* ! DEFAULT_PLL */
++#endif
++
++#if defined(AR531XPLUS)
++
++#define AR531XPLUS_SDRAM_DDR_SDRAM 0 /* Not DDR SDRAM */
++#define AR531XPLUS_SDRAM_DATA_WIDTH 16 /* bits */
++#define AR531XPLUS_SDRAM_COL_WIDTH 8
++#define AR531XPLUS_SDRAM_ROW_WIDTH 12
++
++#else
++
++#define AR531XPLUS_SDRAM_DDR_SDRAM 0 /* Not DDR SDRAM */
++#define AR531XPLUS_SDRAM_DATA_WIDTH 16
++#define AR531XPLUS_SDRAM_COL_WIDTH 8
++#define AR531XPLUS_SDRAM_ROW_WIDTH 12
++
++#endif /* ! AR531XPLUS */
++
++/*
++ * SPI Flash Interface Registers
++ */
++
++#define AR531XPLUS_SPI_CTL (AR531XPLUS_SPI + 0x00)
++#define AR531XPLUS_SPI_OPCODE (AR531XPLUS_SPI + 0x04)
++#define AR531XPLUS_SPI_DATA (AR531XPLUS_SPI + 0x08)
++
++#define SPI_CTL_START 0x00000100
++#define SPI_CTL_BUSY 0x00010000
++#define SPI_CTL_TXCNT_MASK 0x0000000f
++#define SPI_CTL_RXCNT_MASK 0x000000f0
++#define SPI_CTL_TX_RX_CNT_MASK 0x000000ff
++#define SPI_CTL_SIZE_MASK 0x00060000
++
++#define SPI_CTL_CLK_SEL_MASK 0x03000000
++#define SPI_OPCODE_MASK 0x000000ff
++
++/*
++ * PCI-MAC Configuration registers
++ */
++#define PCI_MAC_RC (AR531XPLUS_PCI + 0x4000)
++#define PCI_MAC_SCR (AR531XPLUS_PCI + 0x4004)
++#define PCI_MAC_INTPEND (AR531XPLUS_PCI + 0x4008)
++#define PCI_MAC_SFR (AR531XPLUS_PCI + 0x400C)
++#define PCI_MAC_PCICFG (AR531XPLUS_PCI + 0x4010)
++#define PCI_MAC_SREV (AR531XPLUS_PCI + 0x4020)
++
++#define PCI_MAC_RC_MAC 0x00000001
++#define PCI_MAC_RC_BB 0x00000002
++
++#define PCI_MAC_SCR_SLMODE_M 0x00030000
++#define PCI_MAC_SCR_SLMODE_S 16
++#define PCI_MAC_SCR_SLM_FWAKE 0
++#define PCI_MAC_SCR_SLM_FSLEEP 1
++#define PCI_MAC_SCR_SLM_NORMAL 2
++
++#define PCI_MAC_SFR_SLEEP 0x00000001
++
++#define PCI_MAC_PCICFG_SPWR_DN 0x00010000
++
++
++
++
++/*
++ * PCI Bus Interface Registers
++ */
++#define AR531XPLUS_PCI_1MS_REG (AR531XPLUS_PCI + 0x0008)
++#define AR531XPLUS_PCI_1MS_MASK 0x3FFFF /* # of AHB clk cycles in 1ms */
++
++#define AR531XPLUS_PCI_MISC_CONFIG (AR531XPLUS_PCI + 0x000c)
++#define AR531XPLUS_PCIMISC_TXD_EN 0x00000001 /* Enable TXD for fragments */
++#define AR531XPLUS_PCIMISC_CFG_SEL 0x00000002 /* mem or config cycles */
++#define AR531XPLUS_PCIMISC_GIG_MASK 0x0000000C /* bits 31-30 for pci req */
++#define AR531XPLUS_PCIMISC_RST_MODE 0x00000030
++#define AR531XPLUS_PCIRST_INPUT 0x00000000 /* 4:5=0 rst is input */
++#define AR531XPLUS_PCIRST_LOW 0x00000010 /* 4:5=1 rst to GND */
++#define AR531XPLUS_PCIRST_HIGH 0x00000020 /* 4:5=2 rst to VDD */
++#define AR531XPLUS_PCIGRANT_EN 0x00000000 /* 6:7=0 early grant en */
++#define AR531XPLUS_PCIGRANT_FRAME 0x00000040 /* 6:7=1 grant waits 4 frame */
++#define AR531XPLUS_PCIGRANT_IDLE 0x00000080 /* 6:7=2 grant waits 4 idle */
++#define AR531XPLUS_PCIGRANT_GAP 0x00000000 /* 6:7=2 grant waits 4 idle */
++#define AR531XPLUS_PCICACHE_DIS 0x00001000 /* PCI external access cache disable */
++
++#define AR531XPLUS_PCI_OUT_TSTAMP (AR531XPLUS_PCI + 0x0010)
++
++#define AR531XPLUS_PCI_UNCACHE_CFG (AR531XPLUS_PCI + 0x0014)
++
++#define AR531XPLUS_PCI_IN_EN (AR531XPLUS_PCI + 0x0100)
++#define AR531XPLUS_PCI_IN_EN0 0x01 /* Enable chain 0 */
++#define AR531XPLUS_PCI_IN_EN1 0x02 /* Enable chain 1 */
++#define AR531XPLUS_PCI_IN_EN2 0x04 /* Enable chain 2 */
++#define AR531XPLUS_PCI_IN_EN3 0x08 /* Enable chain 3 */
++
++#define AR531XPLUS_PCI_IN_DIS (AR531XPLUS_PCI + 0x0104)
++#define AR531XPLUS_PCI_IN_DIS0 0x01 /* Disable chain 0 */
++#define AR531XPLUS_PCI_IN_DIS1 0x02 /* Disable chain 1 */
++#define AR531XPLUS_PCI_IN_DIS2 0x04 /* Disable chain 2 */
++#define AR531XPLUS_PCI_IN_DIS3 0x08 /* Disable chain 3 */
++
++#define AR531XPLUS_PCI_IN_PTR (AR531XPLUS_PCI + 0x0200)
++
++#define AR531XPLUS_PCI_OUT_EN (AR531XPLUS_PCI + 0x0400)
++#define AR531XPLUS_PCI_OUT_EN0 0x01 /* Enable chain 0 */
++
++#define AR531XPLUS_PCI_OUT_DIS (AR531XPLUS_PCI + 0x0404)
++#define AR531XPLUS_PCI_OUT_DIS0 0x01 /* Disable chain 0 */
++
++#define AR531XPLUS_PCI_OUT_PTR (AR531XPLUS_PCI + 0x0408)
++
++#define AR531XPLUS_PCI_INT_STATUS (AR531XPLUS_PCI + 0x0500) /* write one to clr */
++#define AR531XPLUS_PCI_TXINT 0x00000001 /* Desc In Completed */
++#define AR531XPLUS_PCI_TXOK 0x00000002 /* Desc In OK */
++#define AR531XPLUS_PCI_TXERR 0x00000004 /* Desc In ERR */
++#define AR531XPLUS_PCI_TXEOL 0x00000008 /* Desc In End-of-List */
++#define AR531XPLUS_PCI_RXINT 0x00000010 /* Desc Out Completed */
++#define AR531XPLUS_PCI_RXOK 0x00000020 /* Desc Out OK */
++#define AR531XPLUS_PCI_RXERR 0x00000040 /* Desc Out ERR */
++#define AR531XPLUS_PCI_RXEOL 0x00000080 /* Desc Out EOL */
++#define AR531XPLUS_PCI_TXOOD 0x00000200 /* Desc In Out-of-Desc */
++#define AR531XPLUS_PCI_MASK 0x0000FFFF /* Desc Mask */
++#define AR531XPLUS_PCI_EXT_INT 0x02000000
++#define AR531XPLUS_PCI_ABORT_INT 0x04000000
++
++#define AR531XPLUS_PCI_INT_MASK (AR531XPLUS_PCI + 0x0504) /* same as INT_STATUS */
++
++#define AR531XPLUS_PCI_INTEN_REG (AR531XPLUS_PCI + 0x0508)
++#define AR531XPLUS_PCI_INT_DISABLE 0x00 /* disable pci interrupts */
++#define AR531XPLUS_PCI_INT_ENABLE 0x01 /* enable pci interrupts */
++
++#define AR531XPLUS_PCI_HOST_IN_EN (AR531XPLUS_PCI + 0x0800)
++#define AR531XPLUS_PCI_HOST_IN_DIS (AR531XPLUS_PCI + 0x0804)
++#define AR531XPLUS_PCI_HOST_IN_PTR (AR531XPLUS_PCI + 0x0810)
++#define AR531XPLUS_PCI_HOST_OUT_EN (AR531XPLUS_PCI + 0x0900)
++#define AR531XPLUS_PCI_HOST_OUT_DIS (AR531XPLUS_PCI + 0x0904)
++#define AR531XPLUS_PCI_HOST_OUT_PTR (AR531XPLUS_PCI + 0x0908)
++
++
++/*
++ * Local Bus Interface Registers
++ */
++#define AR531XPLUS_LB_CONFIG (AR531XPLUS_LOCAL + 0x0000)
++#define AR531XPLUS_LBCONF_OE 0x00000001 /* =1 OE is low-true */
++#define AR531XPLUS_LBCONF_CS0 0x00000002 /* =1 first CS is low-true */
++#define AR531XPLUS_LBCONF_CS1 0x00000004 /* =1 2nd CS is low-true */
++#define AR531XPLUS_LBCONF_RDY 0x00000008 /* =1 RDY is low-true */
++#define AR531XPLUS_LBCONF_WE 0x00000010 /* =1 Write En is low-true */
++#define AR531XPLUS_LBCONF_WAIT 0x00000020 /* =1 WAIT is low-true */
++#define AR531XPLUS_LBCONF_ADS 0x00000040 /* =1 Adr Strobe is low-true */
++#define AR531XPLUS_LBCONF_MOT 0x00000080 /* =0 Intel, =1 Motorola */
++#define AR531XPLUS_LBCONF_8CS 0x00000100 /* =1 8 bits CS, 0= 16bits */
++#define AR531XPLUS_LBCONF_8DS 0x00000200 /* =1 8 bits Data S, 0=16bits */
++#define AR531XPLUS_LBCONF_ADS_EN 0x00000400 /* =1 Enable ADS */
++#define AR531XPLUS_LBCONF_ADR_OE 0x00000800 /* =1 Adr cap on OE, WE or DS */
++#define AR531XPLUS_LBCONF_ADDT_MUX 0x00001000 /* =1 Adr and Data share bus */
++#define AR531XPLUS_LBCONF_DATA_OE 0x00002000 /* =1 Data cap on OE, WE, DS */
++#define AR531XPLUS_LBCONF_16DATA 0x00004000 /* =1 Data is 16 bits wide */
++#define AR531XPLUS_LBCONF_SWAPDT 0x00008000 /* =1 Byte swap data */
++#define AR531XPLUS_LBCONF_SYNC 0x00010000 /* =1 Bus synchronous to clk */
++#define AR531XPLUS_LBCONF_INT 0x00020000 /* =1 Intr is low true */
++#define AR531XPLUS_LBCONF_INT_CTR0 0x00000000 /* GND high-Z, Vdd is high-Z */
++#define AR531XPLUS_LBCONF_INT_CTR1 0x00040000 /* GND drive, Vdd is high-Z */
++#define AR531XPLUS_LBCONF_INT_CTR2 0x00080000 /* GND high-Z, Vdd drive */
++#define AR531XPLUS_LBCONF_INT_CTR3 0x000C0000 /* GND drive, Vdd drive */
++#define AR531XPLUS_LBCONF_RDY_WAIT 0x00100000 /* =1 RDY is negative of WAIT */
++#define AR531XPLUS_LBCONF_INT_PULSE 0x00200000 /* =1 Interrupt is a pulse */
++#define AR531XPLUS_LBCONF_ENABLE 0x00400000 /* =1 Falcon respond to LB */
++
++#define AR531XPLUS_LB_CLKSEL (AR531XPLUS_LOCAL + 0x0004)
++#define AR531XPLUS_LBCLK_EXT 0x0001 /* use external clk for lb */
++
++#define AR531XPLUS_LB_1MS (AR531XPLUS_LOCAL + 0x0008)
++#define AR531XPLUS_LB1MS_MASK 0x3FFFF /* # of AHB clk cycles in 1ms */
++
++#define AR531XPLUS_LB_MISCCFG (AR531XPLUS_LOCAL + 0x000C)
++#define AR531XPLUS_LBM_TXD_EN 0x00000001 /* Enable TXD for fragments */
++#define AR531XPLUS_LBM_RX_INTEN 0x00000002 /* Enable LB ints on RX ready */
++#define AR531XPLUS_LBM_MBOXWR_INTEN 0x00000004 /* Enable LB ints on mbox wr */
++#define AR531XPLUS_LBM_MBOXRD_INTEN 0x00000008 /* Enable LB ints on mbox rd */
++#define AR531XPLUS_LMB_DESCSWAP_EN 0x00000010 /* Byte swap desc enable */
++#define AR531XPLUS_LBM_TIMEOUT_MASK 0x00FFFF80
++#define AR531XPLUS_LBM_TIMEOUT_SHFT 7
++#define AR531XPLUS_LBM_PORTMUX 0x07000000
++
++
++#define AR531XPLUS_LB_RXTSOFF (AR531XPLUS_LOCAL + 0x0010)
++
++#define AR531XPLUS_LB_TX_CHAIN_EN (AR531XPLUS_LOCAL + 0x0100)
++#define AR531XPLUS_LB_TXEN_0 0x01
++#define AR531XPLUS_LB_TXEN_1 0x02
++#define AR531XPLUS_LB_TXEN_2 0x04
++#define AR531XPLUS_LB_TXEN_3 0x08
++
++#define AR531XPLUS_LB_TX_CHAIN_DIS (AR531XPLUS_LOCAL + 0x0104)
++#define AR531XPLUS_LB_TX_DESC_PTR (AR531XPLUS_LOCAL + 0x0200)
++
++#define AR531XPLUS_LB_RX_CHAIN_EN (AR531XPLUS_LOCAL + 0x0400)
++#define AR531XPLUS_LB_RXEN 0x01
++
++#define AR531XPLUS_LB_RX_CHAIN_DIS (AR531XPLUS_LOCAL + 0x0404)
++#define AR531XPLUS_LB_RX_DESC_PTR (AR531XPLUS_LOCAL + 0x0408)
++
++#define AR531XPLUS_LB_INT_STATUS (AR531XPLUS_LOCAL + 0x0500)
++#define AR531XPLUS_INT_TX_DESC 0x0001
++#define AR531XPLUS_INT_TX_OK 0x0002
++#define AR531XPLUS_INT_TX_ERR 0x0004
++#define AR531XPLUS_INT_TX_EOF 0x0008
++#define AR531XPLUS_INT_RX_DESC 0x0010
++#define AR531XPLUS_INT_RX_OK 0x0020
++#define AR531XPLUS_INT_RX_ERR 0x0040
++#define AR531XPLUS_INT_RX_EOF 0x0080
++#define AR531XPLUS_INT_TX_TRUNC 0x0100
++#define AR531XPLUS_INT_TX_STARVE 0x0200
++#define AR531XPLUS_INT_LB_TIMEOUT 0x0400
++#define AR531XPLUS_INT_LB_ERR 0x0800
++#define AR531XPLUS_INT_MBOX_WR 0x1000
++#define AR531XPLUS_INT_MBOX_RD 0x2000
++
++/* Bit definitions for INT MASK are the same as INT_STATUS */
++#define AR531XPLUS_LB_INT_MASK (AR531XPLUS_LOCAL + 0x0504)
++
++#define AR531XPLUS_LB_INT_EN (AR531XPLUS_LOCAL + 0x0508)
++#define AR531XPLUS_LB_MBOX (AR531XPLUS_LOCAL + 0x0600)
++
++
++
++/*
++ * IR Interface Registers
++ */
++#define AR531XPLUS_IR_PKTDATA (AR531XPLUS_IR + 0x0000)
++
++#define AR531XPLUS_IR_PKTLEN (AR531XPLUS_IR + 0x07fc) /* 0 - 63 */
++
++#define AR531XPLUS_IR_CONTROL (AR531XPLUS_IR + 0x0800)
++#define AR531XPLUS_IRCTL_TX 0x00000000 /* use as tranmitter */
++#define AR531XPLUS_IRCTL_RX 0x00000001 /* use as receiver */
++#define AR531XPLUS_IRCTL_SAMPLECLK_MASK 0x00003ffe /* Sample clk divisor mask */
++#define AR531XPLUS_IRCTL_SAMPLECLK_SHFT 1
++#define AR531XPLUS_IRCTL_OUTPUTCLK_MASK 0x03ffc000 /* Output clk divisor mask */
++#define AR531XPLUS_IRCTL_OUTPUTCLK_SHFT 14
++
++#define AR531XPLUS_IR_STATUS (AR531XPLUS_IR + 0x0804)
++#define AR531XPLUS_IRSTS_RX 0x00000001 /* receive in progress */
++#define AR531XPLUS_IRSTS_TX 0x00000002 /* transmit in progress */
++
++#define AR531XPLUS_IR_CONFIG (AR531XPLUS_IR + 0x0808)
++#define AR531XPLUS_IRCFG_INVIN 0x00000001 /* invert input polarity */
++#define AR531XPLUS_IRCFG_INVOUT 0x00000002 /* invert output polarity */
++#define AR531XPLUS_IRCFG_SEQ_START_WIN_SEL 0x00000004 /* 1 => 28, 0 => 7 */
++#define AR531XPLUS_IRCFG_SEQ_START_THRESH 0x000000f0 /* */
++#define AR531XPLUS_IRCFG_SEQ_END_UNIT_SEL 0x00000100 /* */
++#define AR531XPLUS_IRCFG_SEQ_END_UNIT_THRESH 0x00007e00 /* */
++#define AR531XPLUS_IRCFG_SEQ_END_WIN_SEL 0x00008000 /* */
++#define AR531XPLUS_IRCFG_SEQ_END_WIN_THRESH 0x001f0000 /* */
++#define AR531XPLUS_IRCFG_NUM_BACKOFF_WORDS 0x01e00000 /* */
++
++/*
++ * PCI memory constants: Memory area 1 and 2 are the same size -
++ * (twice the PCI_TLB_PAGE_SIZE). The definition of
++ * CPU_TO_PCI_MEM_SIZE is coupled with the TLB setup routine
++ * sysLib.c/sysTlbInit(), in that it assumes that 2 pages of size
++ * PCI_TLB_PAGE_SIZE are set up in the TLB for each PCI memory space.
++ */
++
++#define CPU_TO_PCI_MEM_BASE1 0xE0000000
++#define CPU_TO_PCI_MEM_SIZE1 (2*PCI_TLB_PAGE_SIZE)
++
++
++/* TLB attributes for PCI transactions */
++
++#define PCI_MMU_PAGEMASK 0x00003FFF
++#define MMU_PAGE_UNCACHED 0x00000010
++#define MMU_PAGE_DIRTY 0x00000004
++#define MMU_PAGE_VALID 0x00000002
++#define MMU_PAGE_GLOBAL 0x00000001
++#define PCI_MMU_PAGEATTRIB (MMU_PAGE_UNCACHED|MMU_PAGE_DIRTY|\
++ MMU_PAGE_VALID|MMU_PAGE_GLOBAL)
++#define PCI_MEMORY_SPACE1_VIRT 0xE0000000 /* Used for non-prefet mem */
++#define PCI_MEMORY_SPACE1_PHYS 0x80000000
++#define PCI_TLB_PAGE_SIZE 0x01000000
++#define TLB_HI_MASK 0xFFFFE000
++#define TLB_LO_MASK 0x3FFFFFFF
++#define PAGEMASK_SHIFT 11
++#define TLB_LO_SHIFT 6
++
++#define PCI_MAX_LATENCY 0xFFF /* Max PCI latency */
++
++#define HOST_PCI_DEV_ID 3
++#define HOST_PCI_MBAR0 0x10000000
++#define HOST_PCI_MBAR1 0x20000000
++#define HOST_PCI_MBAR2 0x30000000
++
++#define HOST_PCI_SDRAM_BASEADDR HOST_PCI_MBAR1
++#define PCI_DEVICE_MEM_SPACE 0x800000
++
++
++typedef unsigned int AR531X_REG;
++
++#define sysRegRead(phys) \
++ (*(volatile AR531X_REG *)PHYS_TO_K1(phys))
++
++#define sysRegWrite(phys, val) \
++ ((*(volatile AR531X_REG *)PHYS_TO_K1(phys)) = (val))
++
++
++
++/*
++ * This is board-specific data that is stored in a "fixed" location in flash.
++ * It is shared across operating systems, so it should not be changed lightly.
++ * The main reason we need it is in order to extract the ethernet MAC
++ * address(es).
++ */
++struct ar531x_boarddata {
++ u32 magic; /* board data is valid */
++#define AR531X_BD_MAGIC 0x35333131 /* "5311", for all 531x platforms */
++ u16 cksum; /* checksum (starting with BD_REV 2) */
++ u16 rev; /* revision of this struct */
++#define BD_REV 4
++ char boardName[64]; /* Name of board */
++ u16 major; /* Board major number */
++ u16 minor; /* Board minor number */
++ u32 config; /* Board configuration */
++#define BD_ENET0 0x00000001 /* ENET0 is stuffed */
++#define BD_ENET1 0x00000002 /* ENET1 is stuffed */
++#define BD_UART1 0x00000004 /* UART1 is stuffed */
++#define BD_UART0 0x00000008 /* UART0 is stuffed (dma) */
++#define BD_RSTFACTORY 0x00000010 /* Reset factory defaults stuffed */
++#define BD_SYSLED 0x00000020 /* System LED stuffed */
++#define BD_EXTUARTCLK 0x00000040 /* External UART clock */
++#define BD_CPUFREQ 0x00000080 /* cpu freq is valid in nvram */
++#define BD_SYSFREQ 0x00000100 /* sys freq is set in nvram */
++#define BD_WLAN0 0x00000200 /* Enable WLAN0 */
++#define BD_MEMCAP 0x00000400 /* CAP SDRAM @ memCap for testing */
++#define BD_DISWATCHDOG 0x00000800 /* disable system watchdog */
++#define BD_WLAN1 0x00001000 /* Enable WLAN1 (ar5212) */
++#define BD_ISCASPER 0x00002000 /* FLAG for AR2312 */
++#define BD_WLAN0_2G_EN 0x00004000 /* FLAG for radio0_2G */
++#define BD_WLAN0_5G_EN 0x00008000 /* FLAG for radio0_2G */
++#define BD_WLAN1_2G_EN 0x00020000 /* FLAG for radio0_2G */
++#define BD_WLAN1_5G_EN 0x00040000 /* FLAG for radio0_2G */
++ u16 resetConfigGpio; /* Reset factory GPIO pin */
++ u16 sysLedGpio; /* System LED GPIO pin */
++
++ u32 cpuFreq; /* CPU core frequency in Hz */
++ u32 sysFreq; /* System frequency in Hz */
++ u32 cntFreq; /* Calculated C0_COUNT frequency */
++
++ u8 wlan0Mac[6];
++ u8 enet0Mac[6];
++ u8 enet1Mac[6];
++
++ u16 pciId; /* Pseudo PCIID for common code */
++ u16 memCap; /* cap bank1 in MB */
++
++ /* version 3 */
++ u8 wlan1Mac[6]; /* (ar5212) */
++};
++
++#endif
++
++#endif /* AR531X_H */
+diff -urN linux-mips-orig/drivers/net/ath/ar531xlnx.h linux-mips-new/drivers/net/ath/ar531xlnx.h
+--- linux-mips-orig/drivers/net/ath/ar531xlnx.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/ar531xlnx.h 2005-12-31 12:33:57.676538368 +0000
+@@ -0,0 +1,137 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++ */
++
++/*
++ * This file contains definitions needed in order to compile
++ * AR531X products for linux. Definitions that are largely
++ * AR531X-specific and independent of operating system belong
++ * in ar531x.h rather than this file.
++ */
++#ifndef __AR531XLNX_H
++#define __AR531XLNX_H
++#include "ar531x.h"
++
++#define MIPS_CPU_IRQ_BASE 0x00
++#define AR531X_HIGH_PRIO 0x10
++#define AR531X_MISC_IRQ_BASE 0x20
++#define AR531X_GPIO_IRQ_BASE 0x30
++
++/* Software's idea of interrupts handled by "CPU Interrupt Controller" */
++#if CONFIG_AR5315
++#define AR531X_IRQ_NONE MIPS_CPU_IRQ_BASE+0
++#define AR531X_IRQ_MISC_INTRS MIPS_CPU_IRQ_BASE+2 /* C0_CAUSE: 0x0400 */
++#define AR531X_IRQ_WLAN0_INTRS MIPS_CPU_IRQ_BASE+3 /* C0_CAUSE: 0x0800 */
++#define AR531X_IRQ_ENET0_INTRS MIPS_CPU_IRQ_BASE+4 /* C0_CAUSE: 0x1000 */
++#define AR531X_IRQ_LCBUS_PCI MIPS_CPU_IRQ_BASE+6 /* C0_CAUSE: 0x4000 */
++#define AR531X_IRQ_WLAN0_POLL MIPS_CPU_IRQ_BASE+6 /* C0_CAUSE: 0x4000 */
++#define AR531X_IRQ_CPU_CLOCK MIPS_CPU_IRQ_BASE+7 /* C0_CAUSE: 0x8000 */
++#else
++#define AR531X_IRQ_NONE MIPS_CPU_IRQ_BASE+0
++#define AR531X_IRQ_WLAN0_INTRS MIPS_CPU_IRQ_BASE+2 /* C0_CAUSE: 0x0400 */
++#define AR531X_IRQ_ENET0_INTRS MIPS_CPU_IRQ_BASE+3 /* C0_CAUSE: 0x0800 */
++#define AR531X_IRQ_ENET1_INTRS MIPS_CPU_IRQ_BASE+4 /* C0_CAUSE: 0x1000 */
++#define AR531X_IRQ_WLAN1_INTRS MIPS_CPU_IRQ_BASE+5 /* C0_CAUSE: 0x2000 */
++#define AR531X_IRQ_MISC_INTRS MIPS_CPU_IRQ_BASE+6 /* C0_CAUSE: 0x4000 */
++#define AR531X_IRQ_CPU_CLOCK MIPS_CPU_IRQ_BASE+7 /* C0_CAUSE: 0x8000 */
++#endif
++
++/* Miscellaneous interrupts, which share IP6 or IP2 */
++#define AR531X_MISC_IRQ_NONE AR531X_MISC_IRQ_BASE+0
++#define AR531X_MISC_IRQ_TIMER AR531X_MISC_IRQ_BASE+1
++#define AR531X_MISC_IRQ_AHB_PROC AR531X_MISC_IRQ_BASE+2
++#define AR531X_MISC_IRQ_AHB_DMA AR531X_MISC_IRQ_BASE+3
++#define AR531X_MISC_IRQ_GPIO AR531X_MISC_IRQ_BASE+4
++#define AR531X_MISC_IRQ_UART0 AR531X_MISC_IRQ_BASE+5
++#define AR531X_MISC_IRQ_UART0_DMA AR531X_MISC_IRQ_BASE+6
++#define AR531X_MISC_IRQ_WATCHDOG AR531X_MISC_IRQ_BASE+7
++#define AR531X_MISC_IRQ_LOCAL AR531X_MISC_IRQ_BASE+8
++#define AR531X_MISC_IRQ_COUNT 9
++
++/* GPIO Interrupts [0..7], share AR531X_MISC_IRQ_GPIO */
++#define AR531X_GPIO_IRQ_NONE AR531X_MISC_IRQ_BASE+0
++#define AR531X_GPIO_IRQ(n) AR531X_MISC_IRQ_BASE+(n)+1
++#define AR531X_GPIO_IRQ_COUNT 9
++
++#define PHYS_TO_K1(physaddr) KSEG1ADDR(physaddr)
++#define PHYS_TO_K0(physaddr) KSEG0ADDR(physaddr)
++#define UNMAPPED_TO_PHYS(vaddr) PHYSADDR(vaddr)
++#define IS_UNMAPPED_VADDR(vaddr) \
++ ((KSEGX(vaddr) == KSEG0) || (KSEGX(vaddr) == KSEG1))
++
++/* IOCTL commands for /proc/ar531x */
++#define AR531X_CTRL_DO_BREAKPOINT 1
++#define AR531X_CTRL_DO_MADWIFI 2
++
++/*
++ * Definitions for operating system portability.
++ * These are vxWorks-->Linux translations.
++ */
++#define LOCAL static
++#define BOOL int
++#define TRUE 1
++#define FALSE 0
++#define UINT8 u8
++#define UINT16 u16
++#define UINT32 u32
++#define PRINTF printk
++#if /* DEBUG */ 1
++#define DEBUG_PRINTF printk
++#define printf printk
++#define INLINE
++#else
++DEBUG_PRINTF while (0) printk
++#define INLINE inline
++#endif
++#define sysUDelay(usecs) udelay(usecs)
++#define sysMsDelay(msecs) mdelay(msecs)
++typedef volatile UINT8 *VIRT_ADDR;
++#define MALLOC(sz) kmalloc(sz, GFP_KERNEL)
++#define MALLOC_NOSLEEP(sz) kmalloc(sz, GFP_ATOMIC)
++#define FREE(ptr) kfree((void *)ptr)
++#define BSP_BUG() do { printk("kernel BSP BUG at %s:%d!\n", __FILE__, __LINE__); *(int *)0=0; } while (0)
++#define BSP_BUG_ON(condition) do { if (unlikely((condition)!=0)) BSP_BUG(); } while(0)
++#define ASSERT(x) BSP_BUG_ON(!(x))
++
++extern struct ar531x_boarddata *ar531x_board_configuration;
++extern char *ar531x_radio_configuration;
++extern char *enet_mac_address_get(int MACUnit);
++
++extern void kgdbInit(void);
++extern int kgdbEnabled(void);
++extern void breakpoint(void);
++extern int kgdbInterrupt(void);
++extern unsigned int ar531x_cpu_frequency(void);
++extern unsigned int ar531x_sys_frequency(void);
++
++/* GPIO support */
++extern struct irqaction spurious_gpio;
++extern unsigned int gpioIntMask;
++extern void ar531x_gpio_intr_init(int irq_base);
++extern void ar531x_gpio_ctrl_output(int gpio);
++extern void ar531x_gpio_ctrl_input(int gpio);
++extern void ar531x_gpio_set(int gpio, int val);
++extern int ar531x_gpio_get(int gpio);
++extern void ar531x_gpio_intr_enable(unsigned int irq);
++extern void ar531x_gpio_intr_disable(unsigned int irq);
++
++/* Watchdog Timer support */
++extern int watchdog_start(unsigned int milliseconds);
++extern int watchdog_stop(void);
++extern int watchdog_is_enabled(void);
++extern unsigned int watchdog_min_timer_reached(void);
++extern void watchdog_notify_alive(void);
++
++#define A_DATA_CACHE_INVAL(start, length) \
++ dma_cache_inv((UINT32)(start),(length))
++
++#define sysWbFlush() mb()
++
++#define intDisable(x) cli()
++#define intEnable(x) sti()
++
++#endif /* __AR531XLNX_H */
+diff -urN linux-mips-orig/drivers/net/ath/ipPhy.c linux-mips-new/drivers/net/ath/ipPhy.c
+--- linux-mips-orig/drivers/net/ath/ipPhy.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/ipPhy.c 2005-12-31 12:33:57.677538216 +0000
+@@ -0,0 +1,833 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++ */
++
++/*
++ * Manage the ICPLUS ethernet PHY.
++ *
++ * All definitions in this file are operating system independent!
++ */
++
++#if defined(linux)
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/delay.h>
++
++#include "ar531xlnx.h"
++#endif
++
++#include "ae531xmac.h"
++#include "ae531xreg.h"
++#include "ipPhy.h"
++
++/* PHY selections and access functions */
++
++typedef enum {
++ PHY_SRCPORT_INFO,
++ PHY_PORTINFO_SIZE,
++} PHY_CAP_TYPE;
++
++typedef enum {
++ PHY_SRCPORT_NONE,
++ PHY_SRCPORT_VLANTAG,
++ PHY_SRCPORT_TRAILER,
++} PHY_SRCPORT_TYPE;
++
++#ifdef DEBUG
++#define DRV_DEBUG 1
++#endif
++#define DRV_DEBUG 1
++
++#if DRV_DEBUG
++#define DRV_DEBUG_PHYERROR 0x00000001
++#define DRV_DEBUG_PHYCHANGE 0x00000002
++#define DRV_DEBUG_PHYSETUP 0x00000004
++
++int ipPhyDebug = DRV_DEBUG_PHYERROR;
++
++#define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6) \
++{ \
++ if (ipPhyDebug & (FLG)) { \
++ logMsg(X0, X1, X2, X3, X4, X5, X6); \
++ } \
++}
++
++#define DRV_MSG(x,a,b,c,d,e,f) \
++ logMsg(x,a,b,c,d,e,f)
++
++#define DRV_PRINT(FLG, X) \
++{ \
++ if (ipPhyDebug & (FLG)) { \
++ printf X; \
++ } \
++}
++
++#else /* !DRV_DEBUG */
++#define DRV_LOG(DBG_SW, X0, X1, X2, X3, X4, X5, X6)
++#define DRV_MSG(x,a,b,c,d,e,f)
++#define DRV_PRINT(DBG_SW,X)
++#endif
++
++#define IP_LAN_PORT_VLAN 1
++#define IP_WAN_PORT_VLAN 2
++
++#define ENET_UNIT_DEFAULT 0
++
++/*
++ * Track per-PHY port information.
++ */
++typedef struct {
++ BOOL isEnetPort; /* normal enet port */
++ BOOL isPhyAlive; /* last known state of link */
++ int ethUnit; /* MAC associated with this phy port */
++ UINT32 phyBase;
++ UINT32 phyAddr; /* PHY registers associated with this phy port */
++ UINT32 VLANTableSetting; /* Value to be written to VLAN table */
++} ipPhyInfo_t;
++
++/*
++ * Per-PHY information, indexed by PHY unit number.
++ */
++ipPhyInfo_t ipPhyInfo[] = {
++ /*
++ * On AP30/AR5312, all PHYs are associated with MAC0.
++ * AP30/AR5312's MAC1 isn't used for anything.
++ * CONFIG_VENETDEV==1 (router) configuration:
++ * Ports 0,1,2, and 3 are "LAN ports"
++ * Port 4 is a WAN port
++ * Port 5 connects to MAC0 in the AR5312
++ * CONFIG_VENETDEV==0 (bridge) configuration:
++ * Ports 0,1,2,3,4 are "LAN ports"
++ * Port 5 connects to the MAC0 in the AR5312
++ */
++ {TRUE, /* phy port 0 -- LAN port 0 */
++ FALSE,
++ ENET_UNIT_DEFAULT,
++ (UINT32) (PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET),
++ IP_PHY0_ADDR,
++ IP_LAN_PORT_VLAN
++ },
++
++ {TRUE, /* phy port 1 -- LAN port 1 */
++ FALSE,
++ ENET_UNIT_DEFAULT,
++ (UINT32) (PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET),
++ IP_PHY1_ADDR,
++ IP_LAN_PORT_VLAN
++ },
++
++ {TRUE, /* phy port 2 -- LAN port 2 */
++ FALSE,
++ ENET_UNIT_DEFAULT,
++ (UINT32) (PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET),
++ IP_PHY2_ADDR,
++ IP_LAN_PORT_VLAN
++ },
++
++ {TRUE, /* phy port 3 -- LAN port 3 */
++ FALSE,
++ ENET_UNIT_DEFAULT,
++ (UINT32) (PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET),
++ IP_PHY3_ADDR,
++ IP_LAN_PORT_VLAN
++ },
++
++ {TRUE, /* phy port 4 -- WAN port or LAN port 4 */
++ FALSE,
++ ENET_UNIT_DEFAULT,
++ (UINT32) (PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET),
++ IP_PHY4_ADDR,
++ IP_LAN_PORT_VLAN /* Send to all ports */
++ },
++
++ {FALSE, /* phy port 5 -- CPU port (no RJ45 connector) */
++ TRUE,
++ ENET_UNIT_DEFAULT,
++ (UINT32) (PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET),
++ 0x00,
++ IP_LAN_PORT_VLAN /* Send to all ports */
++ },
++};
++
++#define IP_GLOBALREGBASE ((UINT32) (PHYS_TO_K1(AR531X_ENET0)))
++
++#define IP_PHY_MAX (sizeof(ipPhyInfo) / sizeof(ipPhyInfo[0]))
++
++/* Range of valid PHY IDs is [MIN..MAX] */
++#define IP_ID_MIN 0
++#define IP_ID_MAX (IP_PHY_MAX-1)
++
++/* Convenience macros to access myPhyInfo */
++#define IP_IS_ENET_PORT(phyUnit) (ipPhyInfo[phyUnit].isEnetPort)
++#define IP_IS_PHY_ALIVE(phyUnit) (ipPhyInfo[phyUnit].isPhyAlive)
++#define IP_ETHUNIT(phyUnit) (ipPhyInfo[phyUnit].ethUnit)
++#define IP_PHYBASE(phyUnit) (ipPhyInfo[phyUnit].phyBase)
++#define IP_PHYADDR(phyUnit) (ipPhyInfo[phyUnit].phyAddr)
++#define IP_VLAN_TABLE_SETTING(phyUnit) (ipPhyInfo[phyUnit].VLANTableSetting)
++
++
++#define IP_IS_ETHUNIT(phyUnit, ethUnit) \
++ (IP_IS_ENET_PORT(phyUnit) && \
++ IP_ETHUNIT(phyUnit) == (ethUnit))
++
++/* Forward references */
++BOOL ip_phyIsLinkAlive(int phyUnit);
++LOCAL void ip_VLANInit(int ethUnit);
++LOCAL void ip_verifyReady(int ethUnit);
++#if DEBUG
++void ip_phyShow(int phyUnit);
++void ip_phySet(int phyUnit, UINT32 regnum, UINT32 value);
++void ip_globalSet(UINT32 phyAddr, UINT32 regnum, UINT32 value);
++#endif
++
++/******************************************************************************
++*
++* ip_phyIsLinkAlive - test to see if the specified link is alive
++*
++* RETURNS:
++* TRUE --> link is alive
++* FALSE --> link is down
++*/
++BOOL
++ip_phyIsLinkAlive(int phyUnit)
++{
++ UINT16 phyHwStatus;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ phyBase = IP_PHYBASE(phyUnit);
++ phyAddr = IP_PHYADDR(phyUnit);
++
++ phyHwStatus = phyRegRead(phyBase, phyAddr, IP_PHY_STATUS);
++
++ if (phyHwStatus & IP_STATUS_LINK_PASS) {
++ return TRUE;
++ } else {
++ return FALSE;
++ }
++}
++
++/******************************************************************************
++*
++* ip_VLANInit - initialize "port-based VLANs" for the specified enet unit.
++*/
++LOCAL void
++ip_VLANInit(int ethUnit)
++{
++ int phyUnit;
++ UINT32 phyBase;
++ UINT32 phyReg;
++
++ phyBase = IP_GLOBALREGBASE;
++
++ for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
++ if (IP_ETHUNIT(phyUnit) != ethUnit) {
++ continue;
++ }
++ phyRegWrite(phyBase, IP_GLOBAL_PHY29_ADDR,
++ IP_GLOBAL_PHY29_24_REG + ((phyUnit == 5) ? (phyUnit + 1) : phyUnit),
++ IP_VLAN_TABLE_SETTING(phyUnit));
++
++ /* Send all packets to all ports */
++ phyReg = phyRegRead(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_1_REG);
++ phyReg = phyReg | ((1 << phyUnit) << IP_VLAN1_OUTPUT_PORT_MASK_S);
++ phyRegWrite(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_1_REG, phyReg);
++ }
++ phyReg = phyRegRead(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_9_REG);
++ phyReg = phyReg | TAG_VLAN_ENABLE;
++ phyReg = phyReg & ~VID_INDX_SEL_M;
++ phyRegWrite(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_9_REG, phyReg);
++
++}
++
++
++LOCAL void
++ip_verifyReady(int ethUnit)
++{
++ int phyUnit;
++ UINT32 phyBase = 0;
++ UINT32 phyAddr;
++ UINT16 phyID1;
++ UINT16 phyID2;
++
++ /*
++ * The first read to the Phy port registers always fails and
++ * returns 0. So get things started with a bogus read.
++ */
++ for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
++ if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++
++ phyBase = IP_PHYBASE(phyUnit);
++ phyAddr = IP_PHYADDR(phyUnit);
++
++ phyID1 = phyRegRead(phyBase, phyAddr, IP_PHY_ID1); /* returns 0 */
++ break;
++ }
++
++ for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
++ if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++
++ /*******************/
++ /* Verify phy port */
++ /*******************/
++ phyBase = IP_PHYBASE(phyUnit);
++ phyAddr = IP_PHYADDR(phyUnit);
++
++ phyID1 = phyRegRead(phyBase, phyAddr, IP_PHY_ID1);
++ if (phyID1 != IP_PHY_ID1_EXPECTATION) {
++ DRV_PRINT(DRV_DEBUG_PHYERROR,
++ ("Invalid PHY ID1 for enet%d port%d. Expected 0x%04x, read 0x%04x\n",
++ ethUnit,
++ phyUnit,
++ IP_PHY_ID1_EXPECTATION,
++ phyID1));
++ return;
++ }
++
++ phyID2 = phyRegRead(phyBase, phyAddr, IP_PHY_ID2);
++ if ((phyID2 & IP_OUI_LSB_MASK) != IP_OUI_LSB_EXPECTATION) {
++ DRV_PRINT(DRV_DEBUG_PHYERROR,
++ ("Invalid PHY ID2 for enet%d port %d. Expected 0x%04x, read 0x%04x\n",
++ ethUnit,
++ phyUnit,
++ IP_OUI_LSB_EXPECTATION,
++ phyID2));
++ return;
++ }
++
++ DRV_PRINT(DRV_DEBUG_PHYSETUP,
++ ("Found PHY enet%d port%d: model 0x%x revision 0x%x\n",
++ ethUnit,
++ phyUnit,
++ (phyID2 & IP_MODEL_NUM_MASK) >> IP_MODEL_NUM_SHIFT,
++ (phyID2 & IP_REV_NUM_MASK) >> IP_REV_NUM_SHIFT));
++
++ }
++}
++
++
++/******************************************************************************
++*
++* ip_phySetup - reset and setup the PHY associated with
++* the specified MAC unit number.
++*
++* Resets the associated PHY port.
++*
++* RETURNS:
++* TRUE --> associated PHY is alive
++* FALSE --> no LINKs on this ethernet unit
++*/
++
++BOOL
++ip_phySetup(int ethUnit, UINT32 _phyBase)
++{
++ int phyUnit;
++ UINT16 phyHwStatus;
++ UINT16 timeout;
++ int liveLinks = 0;
++ UINT32 phyBase = 0;
++ BOOL foundPhy = FALSE;
++ UINT32 phyAddr;
++
++ /* Reset PHYs*/
++ for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
++ if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++
++ phyBase = IP_PHYBASE(phyUnit);
++ phyAddr = IP_PHYADDR(phyUnit);
++
++ phyRegWrite(phyBase, phyAddr, IP_PHY_CONTROL,
++ IP_CTRL_SOFTWARE_RESET);
++ }
++ /*
++ * After the phy is reset, it takes a little while before
++ * it can respond properly.
++ */
++ sysMsDelay(300);
++ /* Verify that the switch is what we think it is, and that it's ready */
++ ip_verifyReady(ethUnit);
++
++ /* See if there's any configuration data for this enet */
++ for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
++ if (IP_ETHUNIT(phyUnit) != ethUnit) {
++ continue;
++ }
++
++ phyBase = IP_PHYBASE(phyUnit);
++ foundPhy = TRUE;
++ break;
++ }
++
++ if (!foundPhy) {
++ return FALSE; /* No PHY's configured for this ethUnit */
++ }
++
++#ifdef COBRA_TODO
++ /* Initialize global switch settings */
++
++ /* Initialize the aging time */
++
++ /* Set the learning properties */
++#endif
++
++ /* start auto negogiation on each phy */
++ for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
++ if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++
++ phyBase = IP_PHYBASE(phyUnit);
++ phyAddr = IP_PHYADDR(phyUnit);
++
++ phyRegWrite(phyBase, phyAddr, IP_AUTONEG_ADVERT,
++ IP_ADVERTISE_ALL);
++ phyRegWrite(phyBase, phyAddr, IP_PHY_CONTROL,
++ IP_CTRL_AUTONEGOTIATION_ENABLE | IP_CTRL_START_AUTONEGOTIATION);
++ }
++
++ /*
++ * Wait up to .75 seconds for ALL associated PHYs to finish
++ * autonegotiation. The only way we get out of here sooner is
++ * if ALL PHYs are connected AND finish autonegotiation.
++ */
++ timeout=5;
++ for (phyUnit=0; (phyUnit < IP_PHY_MAX) /*&& (timeout > 0) */; phyUnit++) {
++ if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++ for (;;) {
++ phyBase = IP_PHYBASE(phyUnit);
++ phyAddr = IP_PHYADDR(phyUnit);
++
++ phyHwStatus = phyRegRead(phyBase, phyAddr, IP_PHY_STATUS);
++
++ if (IP_AUTONEG_DONE(phyHwStatus)) {
++ DRV_PRINT(DRV_DEBUG_PHYSETUP,
++ ("Port %d, Neg Success\n", phyUnit));
++ break;
++ }
++ if (timeout == 0) {
++ DRV_PRINT(DRV_DEBUG_PHYSETUP,
++ ("Port %d, Negogiation timeout\n", phyUnit));
++ break;
++ }
++ if (--timeout == 0) {
++ DRV_PRINT(DRV_DEBUG_PHYSETUP,
++ ("Port %d, Negogiation timeout\n", phyUnit));
++ break;
++ }
++
++ sysMsDelay(150);
++ }
++ }
++
++ /*
++ * All PHYs have had adequate time to autonegotiate.
++ * Now initialize software status.
++ *
++ * It's possible that some ports may take a bit longer
++ * to autonegotiate; but we can't wait forever. They'll
++ * get noticed by mv_phyCheckStatusChange during regular
++ * polling activities.
++ */
++ for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
++ if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++
++ if (ip_phyIsLinkAlive(phyUnit)) {
++ liveLinks++;
++ IP_IS_PHY_ALIVE(phyUnit) = TRUE;
++ } else {
++ IP_IS_PHY_ALIVE(phyUnit) = FALSE;
++ }
++
++ DRV_PRINT(DRV_DEBUG_PHYSETUP,
++ ("eth%d: Phy Status=%4.4x\n",
++ ethUnit,
++ phyRegRead(IP_PHYBASE(phyUnit),
++ IP_PHYADDR(phyUnit),
++ IP_PHY_STATUS)));
++ }
++#if 0
++ /* XXX Divy. Disable WAN/LAN seggregation. See bug 17866 */
++ ip_VLANInit(ethUnit);
++#endif
++ return (liveLinks > 0);
++}
++
++/******************************************************************************
++*
++* ip_phyIsDuplexFull - Determines whether the phy ports associated with the
++* specified device are FULL or HALF duplex.
++*
++* RETURNS:
++* 1 --> FULL
++* 0 --> HALF
++*/
++int
++ip_phyIsFullDuplex(int ethUnit)
++{
++ int phyUnit;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++ UINT16 phyHwStatus;
++
++ for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
++ if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++
++ if (ip_phyIsLinkAlive(phyUnit)) {
++
++ phyBase = IP_PHYBASE(phyUnit);
++ phyAddr = IP_PHYADDR(phyUnit);
++
++ phyHwStatus = phyRegRead(phyBase, phyAddr, IP_LINK_PARTNER_ABILITY);
++ printk("ipPhy.c: phyHwStatus 0x%x\n",phyHwStatus);
++ if ((phyHwStatus & IP_LINK_100BASETX_FULL_DUPLEX) ||
++ (phyHwStatus & IP_LINK_10BASETX_FULL_DUPLEX)) {
++ return TRUE;
++ }
++ }
++ return -1;
++ }
++
++ return FALSE;
++
++}
++
++
++/******************************************************************************
++*
++* ip_phyIsSpeed100 - Determines the speed of phy ports associated with the
++* specified device.
++*
++* RETURNS:
++* TRUE --> 100Mbit
++* FALSE --> 10Mbit
++*/
++
++BOOL
++ip_phyIsSpeed100(int ethUnit)
++{
++ int phyUnit;
++ UINT16 phyHwStatus;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
++ if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++
++ if (ip_phyIsLinkAlive(phyUnit)) {
++
++ phyBase = IP_PHYBASE(phyUnit);
++ phyAddr = IP_PHYADDR(phyUnit);
++
++ phyHwStatus = phyRegRead(phyBase, phyAddr, IP_LINK_PARTNER_ABILITY);
++
++ if (phyHwStatus & IP_LINK_100BASETX) {
++ return TRUE;
++ }
++ }
++ }
++
++ return FALSE;
++}
++
++/*****************************************************************************
++*
++* ip_phyCheckStatusChange -- checks for significant changes in PHY state.
++*
++* A "significant change" is:
++* dropped link (e.g. ethernet cable unplugged) OR
++* autonegotiation completed + link (e.g. ethernet cable plugged in)
++*
++* When a PHY is plugged in, phyLinkGained is called.
++* When a PHY is unplugged, phyLinkLost is called.
++*/
++
++void
++ip_phyCheckStatusChange(int ethUnit)
++{
++
++ int phyUnit;
++ UINT16 phyHwStatus;
++ ipPhyInfo_t *lastStatus;
++ int linkCount = 0;
++ int lostLinks = 0;
++ int gainedLinks = 0;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
++ if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++
++ phyBase = IP_PHYBASE(phyUnit);
++ phyAddr = IP_PHYADDR(phyUnit);
++
++ lastStatus = &ipPhyInfo[phyUnit];
++ phyHwStatus = phyRegRead(phyBase, phyAddr, IP_PHY_STATUS);
++
++ if (lastStatus->isPhyAlive) { /* last known link status was ALIVE */
++ /* See if we've lost link */
++ if (phyHwStatus & IP_STATUS_LINK_PASS) {
++ linkCount++;
++ } else {
++ lostLinks++;
++#ifdef COBRA_TODO
++ mv_flushATUDB(phyUnit);
++#endif
++ DRV_PRINT(DRV_DEBUG_PHYCHANGE,("\nenet%d port%d down\n",
++ ethUnit, phyUnit));
++ lastStatus->isPhyAlive = FALSE;
++ }
++ } else { /* last known link status was DEAD */
++ /* Check for AutoNegotiation complete */
++ if (IP_AUTONEG_DONE(phyHwStatus)) {
++ gainedLinks++;
++ linkCount++;
++ DRV_PRINT(DRV_DEBUG_PHYCHANGE,("\nenet%d port%d up\n",
++ ethUnit, phyUnit));
++ lastStatus->isPhyAlive = TRUE;
++ }
++ }
++ }
++
++ if (linkCount == 0) {
++ if (lostLinks) {
++ /* We just lost the last link for this MAC */
++ phyLinkLost(ethUnit);
++ }
++ } else {
++ if (gainedLinks == linkCount) {
++ /* We just gained our first link(s) for this MAC */
++ phyLinkGained(ethUnit);
++ }
++ }
++
++}
++
++#if DEBUG
++
++/* Define the registers of interest for a phyShow command */
++typedef struct ipRegisterTableEntry_s {
++ UINT32 regNum;
++ char *regIdString;
++} ipRegisterTableEntry_t;
++
++ipRegisterTableEntry_t ipPhyRegisterTable[] = {
++ {IP_PHY_CONTROL, "PHY Control "},
++ {IP_PHY_STATUS, "PHY Status "},
++ {IP_PHY_ID1, "PHY Identifier 1 "},
++ {IP_PHY_ID2, "PHY Identifier 2 "},
++ {IP_AUTONEG_ADVERT, "Auto-Negotiation Advertisement "},
++ {IP_LINK_PARTNER_ABILITY, "Link Partner Ability "},
++ {IP_AUTONEG_EXPANSION, "Auto-Negotiation Expansion "},
++};
++int ipPhyNumRegs = sizeof(ipPhyRegisterTable) / sizeof(ipPhyRegisterTable[0]);
++
++
++ipRegisterTableEntry_t ipPhy29GlobalRegisterTable[] = {
++ {IP_GLOBAL_PHY29_18_REG, "29_18_REG "},
++ {IP_GLOBAL_PHY29_19_REG, "29_19_REG "},
++ {IP_GLOBAL_PHY29_20_REG, "29_20_REG "},
++ {IP_GLOBAL_PHY29_21_REG, "29_21_REG "},
++ {IP_GLOBAL_PHY29_22_REG, "29_22_REG "},
++ {IP_GLOBAL_PHY29_23_REG, "29_23_REG "},
++ {IP_GLOBAL_PHY29_24_REG, "29_24_REG "},
++ {IP_GLOBAL_PHY29_25_REG, "29_25_REG "},
++ {IP_GLOBAL_PHY29_26_REG, "29_26_REG "},
++ {IP_GLOBAL_PHY29_27_REG, "29_27_REG "},
++ {IP_GLOBAL_PHY29_28_REG, "29_28_REG "},
++ {IP_GLOBAL_PHY29_29_REG, "29_29_REG "},
++ {IP_GLOBAL_PHY29_30_REG, "29_30_REG "},
++ {IP_GLOBAL_PHY29_31_REG, "29_31_REG "},
++};
++int ipPhy29GlobalNumRegs =
++ sizeof(ipPhy29GlobalRegisterTable) / sizeof(ipPhy29GlobalRegisterTable[0]);
++
++
++ipRegisterTableEntry_t ipPhy30GlobalRegisterTable[] = {
++ {IP_GLOBAL_PHY30_0_REG, "30_0_REG "},
++ {IP_GLOBAL_PHY30_1_REG, "30_1_REG "},
++ {IP_GLOBAL_PHY30_2_REG, "30_2_REG "},
++ {IP_GLOBAL_PHY30_3_REG, "30_3_REG "},
++ {IP_GLOBAL_PHY30_4_REG, "30_4_REG "},
++ {IP_GLOBAL_PHY30_5_REG, "30_5_REG "},
++ {IP_GLOBAL_PHY30_6_REG, "30_6_REG "},
++ {IP_GLOBAL_PHY30_7_REG, "30_7_REG "},
++ {IP_GLOBAL_PHY30_8_REG, "30_8_REG "},
++ {IP_GLOBAL_PHY30_9_REG, "30_9_REG "},
++ {IP_GLOBAL_PHY30_10_REG, "30_10_REG "},
++ {IP_GLOBAL_PHY30_11_REG, "30_11_REG "},
++ {IP_GLOBAL_PHY30_12_REG, "30_12_REG "},
++ {IP_GLOBAL_PHY30_13_REG, "30_13_REG "},
++ {IP_GLOBAL_PHY30_16_REG, "30_16_REG "},
++ {IP_GLOBAL_PHY30_17_REG, "30_17_REG "},
++ {IP_GLOBAL_PHY30_18_REG, "30_18_REG "},
++ {IP_GLOBAL_PHY30_20_REG, "30_20_REG "},
++ {IP_GLOBAL_PHY30_21_REG, "30_21_REG "},
++ {IP_GLOBAL_PHY30_22_REG, "30_22_REG "},
++ {IP_GLOBAL_PHY30_23_REG, "30_23_REG "},
++ {IP_GLOBAL_PHY30_24_REG, "30_24_REG "},
++ {IP_GLOBAL_PHY30_25_REG, "30_25_REG "},
++ {IP_GLOBAL_PHY30_26_REG, "30_26_REG "},
++ {IP_GLOBAL_PHY30_27_REG, "30_27_REG "},
++ {IP_GLOBAL_PHY30_28_REG, "30_28_REG "},
++ {IP_GLOBAL_PHY30_29_REG, "30_29_REG "},
++ {IP_GLOBAL_PHY30_30_REG, "30_30_REG "},
++ {IP_GLOBAL_PHY30_31_REG, "30_31_REG "},
++};
++int ipPhy30GlobalNumRegs =
++ sizeof(ipPhy30GlobalRegisterTable) / sizeof(ipPhy30GlobalRegisterTable[0]);
++
++ipRegisterTableEntry_t ipPhy31GlobalRegisterTable[] = {
++ {IP_GLOBAL_PHY31_0_REG, "31_0_REG "},
++ {IP_GLOBAL_PHY31_1_REG, "31_1_REG "},
++ {IP_GLOBAL_PHY31_2_REG, "31_2_REG "},
++ {IP_GLOBAL_PHY31_3_REG, "31_3_REG "},
++ {IP_GLOBAL_PHY31_4_REG, "31_4_REG "},
++ {IP_GLOBAL_PHY31_5_REG, "31_5_REG "},
++ {IP_GLOBAL_PHY31_6_REG, "31_6_REG "},
++};
++
++int ipPhy31GlobalNumRegs =
++ sizeof(ipPhy31GlobalRegisterTable) / sizeof(ipPhy31GlobalRegisterTable[0]);
++
++
++/*****************************************************************************
++*
++* ip_phyShow - Dump the state of a PHY.
++* There are two sets of registers for each phy port:
++* "phy registers" and
++* "switch port registers"
++* We dump 'em all, plus the switch global registers.
++*/
++void
++ip_phyShow(int phyUnit)
++{
++ int i;
++ UINT16 value;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ if (!ip_validPhyId(phyUnit)) {
++ return;
++ }
++
++ phyBase = IP_PHYBASE(phyUnit);
++ phyAddr = IP_PHYADDR(phyUnit);
++
++ printf("PHY state for PHY%d (enet%d, phyBase 0x%8x, phyAddr 0x%x)\n",
++ phyUnit,
++ IP_ETHUNIT(phyUnit),
++ IP_PHYBASE(phyUnit),
++ IP_PHYADDR(phyUnit));
++
++ printf("PHY Registers:\n");
++ for (i=0; i < ipPhyNumRegs; i++) {
++
++ value = phyRegRead(phyBase, phyAddr, ipPhyRegisterTable[i].regNum);
++
++ printf("Reg %02d (0x%02x) %s = 0x%08x\n",
++ ipPhyRegisterTable[i].regNum,
++ ipPhyRegisterTable[i].regNum,
++ ipPhyRegisterTable[i].regIdString,
++ value);
++ }
++
++ phyBase = IP_GLOBALREGBASE;
++
++ printf("Switch Global Registers:\n");
++ printf("Phy29 Registers:\n");
++ for (i=0; i < ipPhy29GlobalNumRegs; i++) {
++
++ value = phyRegRead(phyBase, IP_GLOBAL_PHY29_ADDR,
++ ipPhy29GlobalRegisterTable[i].regNum);
++
++ printf("Reg %02d (0x%02x) %s = 0x%08x\n",
++ ipPhy29GlobalRegisterTable[i].regNum,
++ ipPhy29GlobalRegisterTable[i].regNum,
++ ipPhy29GlobalRegisterTable[i].regIdString,
++ value);
++ }
++
++ printf("Phy30 Registers:\n");
++ for (i=0; i < ipPhy30GlobalNumRegs; i++) {
++
++ value = phyRegRead(phyBase, IP_GLOBAL_PHY30_ADDR,
++ ipPhy30GlobalRegisterTable[i].regNum);
++
++ printf("Reg %02d (0x%02x) %s = 0x%08x\n",
++ ipPhy30GlobalRegisterTable[i].regNum,
++ ipPhy30GlobalRegisterTable[i].regNum,
++ ipPhy30GlobalRegisterTable[i].regIdString,
++ value);
++ }
++ printf("Phy31 Registers:\n");
++ for (i=0; i < ipPhy31GlobalNumRegs; i++) {
++
++ value = phyRegRead(phyBase, IP_GLOBAL_PHY31_ADDR,
++ ipPhy31GlobalRegisterTable[i].regNum);
++
++ printf("Reg %02d (0x%02x) %s = 0x%08x\n",
++ ipPhy31GlobalRegisterTable[i].regNum,
++ ipPhy31GlobalRegisterTable[i].regNum,
++ ipPhy31GlobalRegisterTable[i].regIdString,
++ value);
++ }
++}
++
++/*****************************************************************************
++*
++* ip_phySet - Modify the value of a PHY register (debug only).
++*/
++void
++ip_phySet(int phyUnit, UINT32 regnum, UINT32 value)
++{
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ if (ip_validPhyId(phyUnit)) {
++
++ phyBase = IP_PHYBASE(phyUnit);
++ phyAddr = IP_PHYADDR(phyUnit);
++
++ phyRegWrite(phyBase, phyAddr, regnum, value);
++ }
++}
++
++/*****************************************************************************
++*
++* ip_globalSet - Modify the value of a global register
++* (debug only).
++*/
++void
++ip_globalSet(UINT32 phyAddr, UINT32 regnum, UINT32 value)
++{
++ UINT32 phyBase;
++
++ phyBase = IP_GLOBALREGBASE;
++
++ phyRegWrite(phyBase, phyAddr, regnum, value);
++}
++
++
++#endif
+diff -urN linux-mips-orig/drivers/net/ath/ipPhy.h linux-mips-new/drivers/net/ath/ipPhy.h
+--- linux-mips-orig/drivers/net/ath/ipPhy.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/ipPhy.h 2005-12-31 12:33:57.678538064 +0000
+@@ -0,0 +1,172 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++ */
++
++/*
++ * icPhy.h - definitions for the ethernet PHY.
++ * This code supports a simple 1-port ethernet phy, ICPLUS,
++ * All definitions in this file are operating system independent!
++ */
++
++#ifndef IPPHY_H
++#define IPPHY_H
++
++/*****************/
++/* PHY Registers */
++/*****************/
++#define IP_PHY_CONTROL 0
++#define IP_PHY_STATUS 1
++#define IP_PHY_ID1 2
++#define IP_PHY_ID2 3
++#define IP_AUTONEG_ADVERT 4
++#define IP_LINK_PARTNER_ABILITY 5
++#define IP_AUTONEG_EXPANSION 6
++
++
++/* IP_PHY_CONTROL fields */
++#define IP_CTRL_SOFTWARE_RESET 0x8000
++#define IP_CTRL_SPEED_100 0x2000
++#define IP_CTRL_AUTONEGOTIATION_ENABLE 0x1000
++#define IP_CTRL_START_AUTONEGOTIATION 0x0200
++#define IP_CTRL_SPEED_FULL_DUPLEX 0x0100
++
++/* Phy status fields */
++#define IP_STATUS_AUTO_NEG_DONE 0x0020
++#define IP_STATUS_LINK_PASS 0x0004
++
++#define IP_AUTONEG_DONE(ip_phy_status) \
++ (((ip_phy_status) & \
++ (IP_STATUS_AUTO_NEG_DONE)) == \
++ (IP_STATUS_AUTO_NEG_DONE))
++
++/* ICPLUS_PHY_ID1 fields */
++#define IP_PHY_ID1_EXPECTATION 0x0243 /* OUI >> 6 */
++
++/* ICPLUS_PHY_ID2 fields */
++#define IP_OUI_LSB_MASK 0xfc00
++#define IP_OUI_LSB_EXPECTATION 0x0c00
++#define IP_OUI_LSB_SHIFT 10
++#define IP_MODEL_NUM_MASK 0x03f0
++#define IP_MODEL_NUM_SHIFT 4
++#define IP_REV_NUM_MASK 0x000f
++#define IP_REV_NUM_SHIFT 0
++
++/* Link Partner ability */
++#define IP_LINK_100BASETX_FULL_DUPLEX 0x0100
++#define IP_LINK_100BASETX 0x0080
++#define IP_LINK_10BASETX_FULL_DUPLEX 0x0040
++#define IP_LINK_10BASETX 0x0020
++
++/* Advertisement register. */
++#define IP_ADVERTISE_100FULL 0x0100
++#define IP_ADVERTISE_100HALF 0x0080
++#define IP_ADVERTISE_10FULL 0x0040
++#define IP_ADVERTISE_10HALF 0x0020
++
++#define IP_ADVERTISE_ALL (IP_ADVERTISE_10HALF | IP_ADVERTISE_10FULL | \
++ IP_ADVERTISE_100HALF | IP_ADVERTISE_100FULL)
++
++
++#define IP_VLAN_TAG_VALID 0x81
++#define IP_VLAN_TAG_SIZE 4
++#define IP_VLAN_TAG_OFFSET 12 /* After DA & SA */
++#define IP_SPECIAL_TAG_VALID 0x81
++
++/****************************/
++/* Global Control Registers */
++/****************************/
++/* IP Global register doesn't have names based on functionality
++ * hence has to live with this names for now */
++#define IP_GLOBAL_PHY29_18_REG 18
++#define IP_GLOBAL_PHY29_19_REG 19
++#define IP_GLOBAL_PHY29_20_REG 20
++#define IP_GLOBAL_PHY29_21_REG 21
++#define IP_GLOBAL_PHY29_22_REG 22
++#define IP_GLOBAL_PHY29_23_REG 23
++#define IP_GLOBAL_PHY29_24_REG 24
++#define IP_GLOBAL_PHY29_25_REG 25
++#define IP_GLOBAL_PHY29_26_REG 26
++#define IP_GLOBAL_PHY29_27_REG 27
++#define IP_GLOBAL_PHY29_28_REG 28
++#define IP_GLOBAL_PHY29_29_REG 29
++#define IP_GLOBAL_PHY29_30_REG 30
++#define IP_GLOBAL_PHY29_31_REG 31
++
++
++#define IP_GLOBAL_PHY30_0_REG 0
++#define IP_GLOBAL_PHY30_1_REG 1
++#define IP_GLOBAL_PHY30_2_REG 2
++#define IP_GLOBAL_PHY30_3_REG 3
++#define IP_GLOBAL_PHY30_4_REG 4
++#define IP_GLOBAL_PHY30_5_REG 5
++#define IP_GLOBAL_PHY30_6_REG 6
++#define IP_GLOBAL_PHY30_7_REG 7
++#define IP_GLOBAL_PHY30_8_REG 8
++#define IP_GLOBAL_PHY30_9_REG 9
++#define IP_GLOBAL_PHY30_10_REG 10
++#define IP_GLOBAL_PHY30_11_REG 11
++#define IP_GLOBAL_PHY30_12_REG 12
++#define IP_GLOBAL_PHY30_13_REG 13
++#define IP_GLOBAL_PHY30_16_REG 16
++#define IP_GLOBAL_PHY30_17_REG 17
++#define IP_GLOBAL_PHY30_18_REG 18
++#define IP_GLOBAL_PHY30_20_REG 20
++#define IP_GLOBAL_PHY30_21_REG 21
++#define IP_GLOBAL_PHY30_22_REG 22
++#define IP_GLOBAL_PHY30_23_REG 23
++#define IP_GLOBAL_PHY30_24_REG 24
++#define IP_GLOBAL_PHY30_25_REG 25
++#define IP_GLOBAL_PHY30_26_REG 26
++#define IP_GLOBAL_PHY30_27_REG 27
++#define IP_GLOBAL_PHY30_28_REG 28
++#define IP_GLOBAL_PHY30_29_REG 29
++#define IP_GLOBAL_PHY30_30_REG 30
++#define IP_GLOBAL_PHY30_31_REG 31
++
++#define IP_GLOBAL_PHY31_0_REG 0
++#define IP_GLOBAL_PHY31_1_REG 1
++#define IP_GLOBAL_PHY31_2_REG 2
++#define IP_GLOBAL_PHY31_3_REG 3
++#define IP_GLOBAL_PHY31_4_REG 4
++#define IP_GLOBAL_PHY31_5_REG 5
++#define IP_GLOBAL_PHY31_6_REG 6
++
++#define IP_GLOBAL_PHY29_31_REG 31
++
++
++#define IP_VLAN0_OUTPUT_PORT_MASK_S 0
++#define IP_VLAN1_OUTPUT_PORT_MASK_S 8
++#define IP_VLAN2_OUTPUT_PORT_MASK_S 0
++#define IP_VLAN3_OUTPUT_PORT_MASK_S 8
++
++/* Masks and shifts for 29.23 register */
++#define IP_PORTX_ADD_TAG_S 11
++#define IP_PORTX_REMOVE_TAG_S 6
++#define IP_PORT5_ADD_TAG_S 1
++#define IP_PORT5_REMOVE_TAG_S 0
++
++/*
++ * 30.9 Definitions
++ */
++#define TAG_VLAN_ENABLE 0x0080
++#define VID_INDX_SEL_M 0x0070
++#define VID_INDX_SEL_S 4
++
++
++/* PHY Addresses */
++#define IP_PHY0_ADDR 0
++#define IP_PHY1_ADDR 1
++#define IP_PHY2_ADDR 2
++#define IP_PHY3_ADDR 3
++#define IP_PHY4_ADDR 4
++
++#define IP_GLOBAL_PHY29_ADDR 29
++#define IP_GLOBAL_PHY30_ADDR 30
++#define IP_GLOBAL_PHY31_ADDR 31
++
++
++#endif
+diff -urN linux-mips-orig/drivers/net/ath/kendSwitchPhy.c linux-mips-new/drivers/net/ath/kendSwitchPhy.c
+--- linux-mips-orig/drivers/net/ath/kendSwitchPhy.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/kendSwitchPhy.c 2005-12-31 12:33:57.678538064 +0000
+@@ -0,0 +1,286 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++ */
++
++/*
++ * Manage the ethernet PHY.
++ * This code supports a simple 1-port ethernet phy, Realtek RTL8201BL,
++ * and compatible PHYs, such as the Kendin KS8721B.
++ * All definitions in this file are operating system independent!
++ */
++
++#if defined(linux)
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/delay.h>
++
++#include "ar531xlnx.h"
++#endif
++
++#if defined(__ECOS)
++#include "ae531xecos.h"
++#endif
++
++
++#include "ae531xmac.h"
++#include "ae531xreg.h"
++#include "rtPhy.h"
++
++#define RT_MAX_PORTS 5 /* max addressable ports per MIIM */
++
++#if /* DEBUG */ 1
++#define RT_DEBUG_ERROR 0x00000001
++#define RT_DEBUG_PHYSETUP 0x00000002
++#define RT_DEBUG_PHYCHANGE 0x00000004
++
++/* XXX: must hardcode this since same MIIM for all ethUnits */
++const UINT32 phyBase = 0xb8100000;
++
++int rtPhyDebug = RT_DEBUG_ERROR;
++
++#define RT_PRINT(FLG, X) \
++{ \
++ if (rtPhyDebug & (FLG)) { \
++ DEBUG_PRINTF X; \
++ } \
++}
++#else
++#define RT_PRINT(FLG, X)
++#endif
++
++/*
++ * Track per-PHY state.
++ */
++static BOOL rtPhyAlive[RT_MAX_PORTS];
++
++
++/******************************************************************************
++*
++* rt_phySetup - reset and setup the PHY associated with
++* the specified MAC unit number.
++*
++* Resets the associated PHY port.
++*
++* RETURNS:
++* TRUE --> associated PHY is alive
++* FALSE --> no LINKs on this ethernet unit
++*/
++
++BOOL
++rt_phySetup(int ethUnit, UINT32 phyBaseIgnored)
++{
++ BOOL linkAlive = FALSE;
++
++ /* Reset phy */
++ if (ethUnit == 0) {
++ int i;
++ for (i=1; i<5; i++) {
++ phyRegWrite(phyBase, i, GEN_ctl, AUTONEGENA);
++ sysMsDelay(200);
++ if (phyRegRead(phyBase, i, GEN_sts) & (AUTOCMPLT | LINK)) {
++ rtPhyAlive[i] = TRUE;
++ }
++ else {
++ rtPhyAlive[i] = FALSE;
++ }
++ }
++ }
++ else {
++ phyRegWrite(phyBase, 5, GEN_ctl, AUTONEGENA);
++ sysMsDelay(200);
++ if (phyRegRead(phyBase, 5, GEN_sts) & (AUTOCMPLT | LINK)) {
++ rtPhyAlive[5] = TRUE;
++ }
++ else {
++ rtPhyAlive[5] = FALSE;
++ }
++ }
++
++ return linkAlive;
++}
++
++/******************************************************************************
++*
++* rt_phyIsDuplexFull - Determines whether the phy ports associated with the
++* specified device are FULL or HALF duplex.
++*
++* RETURNS:
++* 1 --> FULL
++* 0 --> HALF
++*/
++int
++rt_phyIsFullDuplex(int ethUnit)
++{
++ UINT16 phyLpa = 0;
++
++ if (ethUnit == 0) {
++ int i;
++ /* 4 ports connected. If any are half-duplex report half. */
++ for (i=1; i<5; i++) {
++ phyLpa = phyRegRead(phyBase, i, AN_lpa);
++ if ( (!(phyLpa & (LPA_TXFD | LPA_10FD))) &&
++ (phyLpa & (LPA_TX | LPA_10)) ) {
++ return 0;
++ }
++ }
++ return 1;
++ }
++ else {
++ phyLpa = phyRegRead(phyBase, 5, AN_lpa);
++ if (phyLpa & (LPA_TXFD | LPA_10FD) ) {
++ return 1;
++ }
++ else {
++ return 0;
++ }
++ }
++}
++
++/******************************************************************************
++*
++* rt_phyIsSpeed100 - Determines the speed of phy ports associated with the
++* specified device.
++*
++* RETURNS:
++* TRUE --> 100Mbit
++* FALSE --> 10Mbit
++*/
++BOOL
++rt_phyIsSpeed100(int ethUnit)
++{
++ UINT16 phyLpa;
++
++ if (ethUnit == 0) {
++ int i;
++ /* 4 ports connected. If any are not 100 report 10. */
++ for (i=1; i<5; i++) {
++ phyLpa = phyRegRead(phyBase, i, AN_lpa);
++ if ( (!(phyLpa & (LPA_TXFD | LPA_TX))) &&
++ (phyLpa & (LPA_10FD | LPA_10)) ) {
++ printk("10\n");
++ return FALSE;
++ }
++ }
++ printk("100\n");
++ return TRUE;
++ }
++ else {
++ phyLpa = phyRegRead(phyBase, 5, AN_lpa);
++ if (phyLpa & (LPA_TXFD | LPA_TX) ) {
++ printk("100\n");
++ return TRUE;
++ }
++ else {
++ printk("10\n");
++ return FALSE;
++ }
++ }
++}
++
++/*****************************************************************************
++*
++* rt_phyCheckStatusChange -- checks for significant changes in PHY state.
++*
++* A "significant change" is:
++* dropped link (e.g. ethernet cable unplugged) OR
++* autonegotiation completed + link (e.g. ethernet cable plugged in)
++*
++* When a PHY is plugged in, phyLinkGained is called.
++* When a PHY is unplugged, phyLinkLost is called.
++*/
++void
++rt_phyCheckStatusChange(int ethUnit)
++{
++ UINT16 phyHwStatus;
++ int i, loopLower, loopUpper;
++
++ if (ethUnit == 0) {
++ loopLower = 1;
++ loopUpper = 4;
++ }
++ else {
++ loopLower = 5;
++ loopUpper = 5;
++ }
++
++ for (i=loopLower; i<=loopUpper; i++) {
++ phyHwStatus = phyRegRead(phyBase, i, GEN_sts);
++
++ if (rtPhyAlive[i]) { /* last known status was ALIVE */
++ /* See if we've lost link */
++ if (!(phyHwStatus & LINK)) {
++ RT_PRINT(RT_DEBUG_PHYCHANGE,("\nethmac%d link down\n", ethUnit));
++ rtPhyAlive[i] = FALSE;
++ phyLinkLost(ethUnit);
++ }
++ } else { /* last known status was DEAD */
++ /* Check for AN complete */
++ if ((phyHwStatus & (AUTOCMPLT | LINK)) == (AUTOCMPLT | LINK)) {
++ RT_PRINT(RT_DEBUG_PHYCHANGE,("\nethmac%d link up\n", ethUnit));
++ rtPhyAlive[i] = TRUE;
++ phyLinkGained(ethUnit);
++ }
++ }
++ }
++}
++
++#if DEBUG
++
++/* Define the PHY registers of interest for a phyShow command */
++struct rtRegisterTable_s {
++ UINT32 regNum;
++ char *regIdString;
++} rtRegisterTable[] =
++{
++ {GEN_ctl, "Basic Mode Control (GEN_ctl) "},
++ {GEN_sts, "Basic Mode Status (GEN_sts) "},
++ {GEN_id_hi, "PHY Identifier 1 (GET_id_hi) "},
++ {GEN_id_lo, "PHY Identifier 2 (GET_id_lo) "},
++ {AN_adv, "Auto-Neg Advertisement (AN_adv) "},
++ {AN_lpa, "Auto-Neg Link Partner Ability "},
++ {AN_exp, "Auto-Neg Expansion "},
++};
++
++int rtNumRegs = sizeof(rtRegisterTable) / sizeof(rtRegisterTable[0]);
++
++/*
++ * Dump the state of a PHY.
++ */
++void
++rt_phyShow(int phyUnit)
++{
++ int i;
++ UINT16 value;
++ int j, loopLower, loopUpper;
++
++ printf("PHY state for ethphy%d\n", phyUnit);
++
++ if (phyUnit == 0) {
++ loopLower = 1;
++ loopUpper = 4;
++ }
++ else {
++ loopLower = 5;
++ loopUpper = 5;
++ }
++
++ for (j=loopLower; j<=loopUpper; j++) {
++ printk("PHY port %d:\n", j);
++ for (i=0; i<rtNumRegs; i++) {
++
++ value = phyRegRead(phyBase, j, rtRegisterTable[i].regNum);
++
++ printf("Reg %02d (0x%02x) %s = 0x%08x\n",
++ rtRegisterTable[i].regNum, rtRegisterTable[i].regNum,
++ rtRegisterTable[i].regIdString, value);
++ }
++ }
++}
++
++#endif
+diff -urN linux-mips-orig/drivers/net/ath/Makefile linux-mips-new/drivers/net/ath/Makefile
+--- linux-mips-orig/drivers/net/ath/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/Makefile 2005-12-31 12:33:57.678538064 +0000
+@@ -0,0 +1,78 @@
++################################################################################
++#
++# This file is subject to the terms and conditions of the GNU General Public
++# License. See the file "COPYING" in the main directory of this archive
++# for more details.
++#
++# Copyright © 2004 Atheros Communications, Inc., All Rights Reserved.
++#
++# Makefile for Atheros ar531x ethernet driver
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++################################################################################
++
++#
++# Makefile for the Atheros ar531x ethernet driver
++#
++
++obj= .
++
++obj-m += ae531x.o
++ae531x-objs := ae531xlnx.o ae531xmac.o
++export-objs := ae531xlnx.o
++list-multi := ae531x.o
++
++ifeq ($(CONFIG_KENDIN_ENET_PHY),y)
++ ae531x-objs += rtPhy.o
++endif
++ifeq ($(CONFIG_KENDIN_KS8995XA_ENET_PHY),y)
++ ae531x-objs += kendSwitchPhy.o
++endif
++ifeq ($(CONFIG_MARVELL_ENET_PHY),y)
++ ae531x-objs += mvPhy.o
++endif
++ifeq ($(CONFIG_ICPLUS_ENET_PHY),y)
++ ae531x-objs += ipPhy.o
++endif
++
++#
++# If building directly into kernel
++#
++ifneq ($(MAKING_MODULES),1)
++obj-$(CONFIG_NET_ATHEROS_ETHER) := ae531x.o $(ae531x-objs)
++O_TARGET := ae531x.o
++endif
++
++INCS += -I.
++
++EXTRA_CFLAGS+=$(INCS) ${COPTS} -g
++ifeq ($(DEBUG_BUILD),1)
++EXTRA_CFLAGS+=-DDEBUG
++endif
++
++# release tag versioning
++-include $(KERNELPATH)/ath_version.mk
++
++-include $(TOPDIR)/Rules.make
++STRIP= ${TOOLPREFIX}strip
++
++ifndef MODPATH
++MODPATH = ${KERNELPATH}/arch/mips/ar531x/ROOTDISK/rootdir/lib/modules/${KERNELRELEASE}/
++endif
++
++all:
++ $(MAKE) -C ${KERNELPATH} SUBDIRS=$(shell pwd) modules
++
++install: all
++ $(STRIP) -S ae531x.o
++ cp ae531x.o ${KERNELPATH}/arch/mips/ar531x/ROOTDISK/rootdir/lib/modules/$(strip $(shell head -n 1 $(KERNELPATH)/Makefile | cut -f 2 -d'=')).$(strip $(shell head -n 2 $(KERNELPATH)/Makefile | tail -1 | cut -f 2 -d'=')).$(strip $(shell head -n 3 $(KERNELPATH)/Makefile | tail -1 | cut -f 2 -d'='))${EXTRAVERSION}/net/.
++
++clean:
++ -rm -f *~ *.o *.ko *.mod.c
++ -rm -f .version .*.o.flags .*.o.d .*.o.cmd .*.ko.cmd
++
++ae531x.o : $(ae531x-objs)
++ $(LD) -o ae531x.o -r $(ae531x-objs)
+diff -urN linux-mips-orig/drivers/net/ath/mvPhy.c linux-mips-new/drivers/net/ath/mvPhy.c
+--- linux-mips-orig/drivers/net/ath/mvPhy.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/mvPhy.c 2005-12-31 12:33:57.726530768 +0000
+@@ -0,0 +1,1230 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++ */
++
++/*
++* Manage the ethernet PHY switch, Marvell 88E6060.
++*
++* This module is intended to be largely OS and platform-independent.
++*/
++
++#if defined(linux)
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/delay.h>
++
++#include "ar531xlnx.h"
++#endif
++
++#if defined(__ECOS)
++#include "ae531xecos.h"
++#endif
++
++
++#include "ae531xmac.h"
++#include "ae531xreg.h"
++#include "mvPhy.h"
++
++#if /* DEBUG */ 1
++#define MV_DEBUG_ERROR 0x00000001
++#define MV_DEBUG_PHYSETUP 0x00000002
++#define MV_DEBUG_PHYCHANGE 0x00000004
++
++int mvPhyDebug = MV_DEBUG_ERROR;
++
++#define MV_PRINT(FLG, X) \
++{ \
++ if (mvPhyDebug & (FLG)) { \
++ DEBUG_PRINTF X; \
++ } \
++}
++#else
++#define MV_PRINT(FLG, X)
++#endif
++
++#if CONFIG_VENETDEV
++/*
++ * On AR5312 with CONFIG_VENETDEV==1,
++ * ports 0..3 are LAN ports (accessed through ae0)
++ * port 4 is the WAN port. (accessed through ae1)
++ *
++ * The phy switch settings in the mvPhyInfo table are set accordingly.
++ */
++#define MV_WAN_PORT 4
++#define MV_IS_LAN_PORT(port) ((port) < MV_WAN_PORT)
++#define MV_IS_WAN_PORT(port) ((port) == MV_WAN_PORT)
++#endif
++
++/*
++ * Track per-PHY port information.
++ */
++typedef struct {
++ BOOL isEnetPort; /* normal enet port */
++ BOOL isPhyAlive; /* last known state of link */
++ int ethUnit; /* MAC associated with this phy port */
++ UINT32 phyBase;
++ UINT32 phyAddr; /* PHY registers associated with this phy port */
++ UINT32 switchPortAddr; /* switch port regs assoc'ed with this phy port */
++ UINT32 VLANTableSetting; /* Value to be written to VLAN table */
++} mvPhyInfo_t;
++
++/******************************************************************************
++ * Per-PHY information, indexed by PHY unit number.
++ *
++ * This table is board-dependent. It includes information
++ * about which enet MAC controls which PHY port.
++ */
++mvPhyInfo_t mvPhyInfo[] = {
++ /*
++ * On AP30/AR5312, all PHYs are associated with MAC0.
++ * AP30/AR5312's MAC1 isn't used for anything.
++ * CONFIG_VENETDEV==1 (router) configuration:
++ * Ports 0,1,2, and 3 are "LAN ports"
++ * Port 4 is a WAN port
++ * Port 5 connects to MAC0 in the AR5312
++ * CONFIG_VENETDEV==0 (bridge) configuration:
++ * Ports 0,1,2,3,4 are "LAN ports"
++ * Port 5 connects to the MAC0 in the AR5312
++ */
++ {isEnetPort: TRUE, /* phy port 0 -- LAN port 0 */
++ isPhyAlive: FALSE,
++ ethUnit: 0,
++ phyBase: 0,
++ phyAddr: 0x10,
++ switchPortAddr: 0x18,
++#if CONFIG_VENETDEV
++ VLANTableSetting: 0x2e
++#else
++ VLANTableSetting: 0x3e
++#endif
++ },
++
++ {isEnetPort: TRUE, /* phy port 1 -- LAN port 1 */
++ isPhyAlive: FALSE,
++ ethUnit: 0,
++ phyBase: 0,
++ phyAddr: 0x11,
++ switchPortAddr: 0x19,
++#if CONFIG_VENETDEV
++ VLANTableSetting: 0x2d
++#else
++ VLANTableSetting: 0x3d
++#endif
++ },
++
++ {isEnetPort: TRUE, /* phy port 2 -- LAN port 2 */
++ isPhyAlive: FALSE,
++ ethUnit: 0,
++ phyBase: 0,
++ phyAddr: 0x12,
++ switchPortAddr: 0x1a,
++#if CONFIG_VENETDEV
++ VLANTableSetting: 0x2b
++#else
++ VLANTableSetting: 0x3b
++#endif
++ },
++
++ {isEnetPort: TRUE, /* phy port 3 -- LAN port 3 */
++ isPhyAlive: FALSE,
++ ethUnit: 0,
++ phyBase: 0,
++ phyAddr: 0x13,
++ switchPortAddr: 0x1b,
++#if CONFIG_VENETDEV
++ VLANTableSetting: 0x27
++#else
++ VLANTableSetting: 0x37
++#endif
++ },
++
++ {isEnetPort: TRUE, /* phy port 4 -- WAN port or LAN port 4 */
++ isPhyAlive: FALSE,
++ ethUnit: 0,
++ phyBase: 0,
++ phyAddr: 0x14,
++ switchPortAddr: 0x1c,
++#if CONFIG_VENETDEV
++ VLANTableSetting: 0x1020 /* WAN port */
++#else
++ VLANTableSetting: 0x2f /* LAN port 4 */
++#endif
++ },
++
++ {isEnetPort: FALSE, /* phy port 5 -- CPU port (no RJ45 connector) */
++ isPhyAlive: TRUE,
++ ethUnit: 0,
++ phyBase: 0,
++ phyAddr: 0x15,
++ switchPortAddr: 0x1d,
++#if CONFIG_VENETDEV
++ VLANTableSetting: 0x0f /* Send only to LAN ports */
++#else
++ VLANTableSetting: 0x1f /* Send to all ports */
++#endif
++ },
++};
++
++#define MV_PHY_MAX (sizeof(mvPhyInfo) / sizeof(mvPhyInfo[0]))
++
++/* Range of valid PHY IDs is [MIN..MAX] */
++#define MV_ID_MIN 0
++#define MV_ID_MAX (MV_PHY_MAX-1)
++
++/* Convenience macros to access myPhyInfo */
++#define MV_IS_ENET_PORT(phyUnit) (mvPhyInfo[phyUnit].isEnetPort)
++#define MV_IS_PHY_ALIVE(phyUnit) (mvPhyInfo[phyUnit].isPhyAlive)
++#define MV_ETHUNIT(phyUnit) (mvPhyInfo[phyUnit].ethUnit)
++#define MV_PHYBASE(phyUnit) (mvPhyInfo[phyUnit].phyBase)
++#define MV_PHYADDR(phyUnit) (mvPhyInfo[phyUnit].phyAddr)
++#define MV_SWITCH_PORT_ADDR(phyUnit) (mvPhyInfo[phyUnit].switchPortAddr)
++#define MV_VLAN_TABLE_SETTING(phyUnit) (mvPhyInfo[phyUnit].VLANTableSetting)
++
++#define MV_IS_ETHUNIT(phyUnit, ethUnit) \
++ (MV_IS_ENET_PORT(phyUnit) && \
++ MV_ETHUNIT(phyUnit) == (ethUnit))
++
++
++/* Forward references */
++BOOL mv_phyIsLinkAlive(int phyUnit);
++LOCAL void mv_VLANInit(int ethUnit);
++LOCAL void mv_enableConfiguredPorts(int ethUnit);
++LOCAL void mv_verifyReady(int ethUnit);
++BOOL mv_phySetup(int ethUnit, UINT32 phyBase);
++int mv_phyIsFullDuplex(int ethUnit);
++BOOL mv_phyIsSpeed100(int phyUnit);
++LOCAL BOOL mv_validPhyId(int phyUnit);
++void mv_flushATUDB(int phyUnit);
++void mv_phyCheckStatusChange(int ethUnit);
++#if DEBUG
++void mv_phyShow(int phyUnit);
++void mv_phySet(int phyUnit, UINT32 regnum, UINT32 value);
++void mv_switchPortSet(int phyUnit, UINT32 regnum, UINT32 value);
++void mv_switchGlobalSet(int phyUnit, UINT32 regnum, UINT32 value);
++void mv_showATUDB(int phyUnit);
++void mv_countGoodFrames(int phyUnit);
++void mv_countBadFrames(int phyUnit);
++void mv_showFrameCounts(int phyUnit);
++#endif
++
++
++/******************************************************************************
++*
++* mv_phyIsLinkAlive - test to see if the specified link is alive
++*
++* RETURNS:
++* TRUE --> link is alive
++* FALSE --> link is down
++*/
++BOOL
++mv_phyIsLinkAlive(int phyUnit)
++{
++ UINT16 phyHwStatus;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ phyBase = MV_PHYBASE(phyUnit);
++ phyAddr = MV_PHYADDR(phyUnit);
++
++ phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
++
++ if (phyHwStatus & MV_STATUS_REAL_TIME_LINK_UP) {
++ return TRUE;
++ } else {
++ return FALSE;
++ }
++}
++
++/******************************************************************************
++*
++* mv_VLANInit - initialize "port-based VLANs" for the specified enet unit.
++*/
++LOCAL void
++mv_VLANInit(int ethUnit)
++{
++ int phyUnit;
++ UINT32 phyBase;
++ UINT32 switchPortAddr;
++
++ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
++ if (MV_ETHUNIT(phyUnit) != ethUnit) {
++ continue;
++ }
++
++ phyBase = MV_PHYBASE(phyUnit);
++ switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
++
++ phyRegWrite(phyBase, switchPortAddr, MV_PORT_BASED_VLAN_MAP,
++ MV_VLAN_TABLE_SETTING(phyUnit));
++ }
++}
++
++#define phyPortConfigured(phyUnit) TRUE /* TBDFREEDOM2 */
++
++/******************************************************************************
++*
++* mv_enableConfiguredPorts - enable whichever PHY ports are supposed
++* to be enabled according to administrative configuration.
++*/
++LOCAL void
++mv_enableConfiguredPorts(int ethUnit)
++{
++ int phyUnit;
++ UINT32 phyBase;
++ UINT32 switchPortAddr;
++ UINT16 portControl;
++ UINT16 portAssociationVector;
++
++ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
++ if (MV_ETHUNIT(phyUnit) != ethUnit) {
++ continue;
++ }
++
++ phyBase = MV_PHYBASE(phyUnit);
++ switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
++
++ if (phyPortConfigured(phyUnit)) {
++
++ portControl = MV_PORT_CONTROL_PORT_STATE_FORWARDING;
++#if CONFIG_VENETDEV
++ if (!MV_IS_ENET_PORT(phyUnit)) { /* CPU port */
++ portControl |= MV_PORT_CONTROL_INGRESS_TRAILER
++ | MV_PORT_CONTROL_EGRESS_MODE;
++ }
++#endif
++ phyRegWrite(phyBase, switchPortAddr, MV_PORT_CONTROL, portControl);
++
++ portAssociationVector = 1 << phyUnit;
++
++ phyRegWrite(phyBase, switchPortAddr,
++ MV_PORT_ASSOCIATION_VECTOR, portAssociationVector);
++ }
++ }
++}
++
++/******************************************************************************
++*
++* mv_verifyReady - validates that we're dealing with the device
++* we think we're dealing with, and that it's ready.
++*/
++LOCAL void
++mv_verifyReady(int ethUnit)
++{
++ int phyUnit;
++ UINT16 globalStatus;
++ UINT32 phyBase = 0;
++ UINT32 phyAddr;
++ UINT32 switchPortAddr;
++ UINT16 phyID1;
++ UINT16 phyID2;
++ UINT16 switchID;
++
++ /*
++ * The first read to the Phy port registers always fails and
++ * returns 0. So get things started with a bogus read.
++ */
++ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
++ if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++ phyBase = MV_PHYBASE(phyUnit);
++ phyAddr = MV_PHYADDR(phyUnit);
++
++ (void)phyRegRead(phyBase, phyAddr, MV_PHY_ID1); /* returns 0 */
++ break;
++ }
++
++ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
++ if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++
++ /*******************/
++ /* Verify phy port */
++ /*******************/
++ phyBase = MV_PHYBASE(phyUnit);
++ phyAddr = MV_PHYADDR(phyUnit);
++
++ phyID1 = phyRegRead(phyBase, phyAddr, MV_PHY_ID1);
++ if (phyID1 != MV_PHY_ID1_EXPECTATION) {
++ MV_PRINT(MV_DEBUG_PHYSETUP,
++ ("Invalid PHY ID1 for ethmac%d port%d. Expected 0x%04x, read 0x%04x\n",
++ ethUnit,
++ phyUnit,
++ MV_PHY_ID1_EXPECTATION,
++ phyID1));
++ return;
++ }
++
++ phyID2 = phyRegRead(phyBase, phyAddr, MV_PHY_ID2);
++ if ((phyID2 & MV_OUI_LSB_MASK) != MV_OUI_LSB_EXPECTATION) {
++ MV_PRINT(MV_DEBUG_PHYSETUP,
++ ("Invalid PHY ID2 for ethmac%d port %d. Expected 0x%04x, read 0x%04x\n",
++ ethUnit,
++ phyUnit,
++ MV_OUI_LSB_EXPECTATION,
++ phyID2));
++ return;
++ }
++
++ MV_PRINT(MV_DEBUG_PHYSETUP,
++ ("Found PHY ethmac%d port%d: model 0x%x revision 0x%x\n",
++ ethUnit,
++ phyUnit,
++ (phyID2 & MV_MODEL_NUM_MASK) >> MV_MODEL_NUM_SHIFT,
++ (phyID2 & MV_REV_NUM_MASK) >> MV_REV_NUM_SHIFT));
++
++
++ /**********************/
++ /* Verify switch port */
++ /**********************/
++ switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
++
++ switchID = phyRegRead(phyBase, switchPortAddr, MV_SWITCH_ID);
++ if ((switchID & MV_SWITCH_ID_DEV_MASK) !=
++ MV_SWITCH_ID_DEV_EXPECTATION) {
++
++ MV_PRINT(MV_DEBUG_PHYSETUP,
++ ("Invalid switch ID for ethmac%d port %d. Expected 0x%04x, read 0x%04x\n",
++ ethUnit,
++ phyUnit,
++ MV_SWITCH_ID_DEV_EXPECTATION,
++ switchID));
++ return;
++ }
++
++ MV_PRINT(MV_DEBUG_PHYSETUP,
++ ("Found PHY switch for enet %d port %d deviceID 0x%x revision 0x%x\n",
++ ethUnit,
++ phyUnit,
++ (switchID & MV_SWITCH_ID_DEV_MASK) >> MV_SWITCH_ID_DEV_SHIFT,
++ (switchID & MV_SWITCH_ID_REV_MASK) >> MV_SWITCH_ID_REV_SHIFT))
++ }
++
++ /*******************************/
++ /* Verify that switch is ready */
++ /*******************************/
++ if (phyBase) {
++ globalStatus = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
++ MV_SWITCH_GLOBAL_STATUS);
++
++ if (!(globalStatus & MV_SWITCH_STATUS_READY_MASK)) {
++ MV_PRINT(MV_DEBUG_PHYSETUP,
++ ("PHY switch for ethmac%d NOT ready!\n",
++ ethUnit));
++ }
++ } else {
++ MV_PRINT(MV_DEBUG_PHYSETUP,
++ ("No ports configured for ethmac%d\n", ethUnit));
++ }
++}
++
++/******************************************************************************
++*
++* mv_phySetup - reset and setup the PHY switch.
++*
++* Resets each PHY port.
++*
++* RETURNS:
++* TRUE --> at least 1 PHY with LINK
++* FALSE --> no LINKs on this ethernet unit
++*/
++BOOL
++mv_phySetup(int ethUnit, UINT32 phyBase)
++{
++ int phyUnit;
++ int liveLinks = 0;
++ BOOL foundPhy = FALSE;
++ UINT32 phyAddr;
++ UINT16 atuControl;
++
++ /*
++ * Allow platform-specific code to determine the default Ethernet MAC
++ * at run-time. If phyEthMacDefault returns a negative value, use the
++ * static mvPhyInfo table "as is". But if phyEthMacDefault returns a
++ * non-negative value, use it as the default ethernet unit.
++ */
++ {
++ int ethMacDefault = phyEthMacDefault();
++
++ if (ethMacDefault >= 0) {
++ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
++ MV_ETHUNIT(phyUnit)=ethMacDefault;
++ }
++ }
++ }
++
++ /*
++ * See if there's any configuration data for this enet,
++ * and set up phyBase in table.
++ */
++ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
++ if (MV_ETHUNIT(phyUnit) != ethUnit) {
++ continue;
++ }
++
++ MV_PHYBASE(phyUnit) = phyBase;
++ foundPhy = TRUE;
++ }
++
++ if (!foundPhy) {
++ return FALSE; /* No PHY's configured for this ethUnit */
++ }
++
++ /* Verify that the switch is what we think it is, and that it's ready */
++ mv_verifyReady(ethUnit);
++
++ /* Initialize global switch settings */
++ atuControl = MV_ATUCTRL_AGE_TIME_DEFAULT << MV_ATUCTRL_AGE_TIME_SHIFT;
++ atuControl |= MV_ATUCTRL_ATU_SIZE_DEFAULT << MV_ATUCTRL_ATU_SIZE_SHIFT;
++ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_CONTROL, atuControl);
++
++ /* Reset PHYs and start autonegoation on each. */
++ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
++ if (MV_ETHUNIT(phyUnit) != ethUnit) {
++ continue;
++ }
++
++ phyBase = MV_PHYBASE(phyUnit);
++ phyAddr = MV_PHYADDR(phyUnit);
++
++ phyRegWrite(phyBase, phyAddr, MV_PHY_CONTROL,
++ MV_CTRL_SOFTWARE_RESET | MV_CTRL_AUTONEGOTIATION_ENABLE);
++ }
++
++#if 0 /* Don't wait -- we'll detect shortly after the link comes up */
++{
++ int timeout;
++ UINT16 phyHwStatus;
++
++ /*
++ * Wait 5 seconds for ALL associated PHYs to finish autonegotiation.
++ */
++ timeout=50;
++ for (phyUnit=0; (phyUnit < MV_PHY_MAX) && (timeout > 0); phyUnit++) {
++ if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++ for (;;) {
++ phyBase = MV_PHYBASE(phyUnit);
++ phyAddr = MV_PHYADDR(phyUnit);
++
++ phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
++
++ if (MV_AUTONEG_DONE(phyHwStatus)) {
++ break;
++ }
++
++ if (--timeout == 0) {
++ break;
++ }
++
++ sysMsDelay(100);
++ }
++ }
++}
++#endif
++
++ /*
++ * All PHYs have had adequate time to autonegotiate.
++ * Now initialize software status.
++ *
++ * It's possible that some ports may take a bit longer
++ * to autonegotiate; but we can't wait forever. They'll
++ * get noticed by mv_phyCheckStatusChange during regular
++ * polling activities.
++ */
++ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
++ if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++
++ if (mv_phyIsLinkAlive(phyUnit)) {
++ liveLinks++;
++ MV_IS_PHY_ALIVE(phyUnit) = TRUE;
++ } else {
++ MV_IS_PHY_ALIVE(phyUnit) = FALSE;
++ }
++
++ MV_PRINT(MV_DEBUG_PHYSETUP,
++ ("ethmac%d: Phy Status=%4.4x\n",
++ ethUnit,
++ phyRegRead(MV_PHYBASE(phyUnit),
++ MV_PHYADDR(phyUnit),
++ MV_PHY_SPECIFIC_STATUS)));
++ }
++
++ mv_VLANInit(ethUnit);
++
++ mv_enableConfiguredPorts(ethUnit);
++
++ return (liveLinks > 0);
++}
++
++
++/******************************************************************************
++*
++* mv_phyIsDuplexFull - Determines whether the phy ports associated with the
++* specified device are FULL or HALF duplex.
++*
++* RETURNS:
++* 1 --> at least one associated PHY in FULL DUPLEX
++* 0 --> all half duplex
++* -1 --> No links
++*/
++int
++mv_phyIsFullDuplex(int ethUnit)
++{
++ int phyUnit;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++ UINT16 phyHwStatus;
++ int oneIsReady=0;
++
++ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
++ if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++
++ if (mv_phyIsLinkAlive(phyUnit)) {
++ oneIsReady = 1;
++
++ phyBase = MV_PHYBASE(phyUnit);
++ phyAddr = MV_PHYADDR(phyUnit);
++
++ phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
++
++ if (phyHwStatus & MV_STATUS_RESOLVED_DUPLEX_FULL) {
++ return 1;
++ }
++ }
++ }
++ if (oneIsReady)
++ return 0;
++ else
++ return -1;
++}
++
++/******************************************************************************
++*
++* mv_phyIsSpeed100 - Determines the speed of a phy port
++*
++* RETURNS:
++* TRUE --> PHY operating at 100 Mbit
++* FALSE --> link down, or not operating at 100 Mbit
++*/
++BOOL
++mv_phyIsSpeed100(int phyUnit)
++{
++ UINT16 phyHwStatus;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ if (MV_IS_ENET_PORT(phyUnit)) {
++ if (mv_phyIsLinkAlive(phyUnit)) {
++
++ phyBase = MV_PHYBASE(phyUnit);
++ phyAddr = MV_PHYADDR(phyUnit);
++
++ phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
++
++ if (phyHwStatus & MV_STATUS_RESOLVED_SPEED_100) {
++ return TRUE;
++ }
++ }
++ }
++
++ return FALSE;
++}
++
++#if CONFIG_VENETDEV
++/******************************************************************************
++*
++* mv_phyDetermineSource - Examine a received frame's Egress Trailer
++* to determine whether it came from a LAN or WAN port.
++*
++* RETURNS:
++* Sets *pFromLAN: 1-->LAN, 0-->WAN
++* Modifies *pLen to remove PHY trailer from frame
++*/
++void
++mv_phyDetermineSource(char *data, int len, int *pFromLAN)
++{
++ unsigned char *phyTrailer;
++ unsigned char incomingPort;
++
++ phyTrailer = &data[len - MV_PHY_TRAILER_SIZE];
++ ASSERT(phyTrailer[0] == MV_EGRESS_TRAILER_VALID);
++
++ incomingPort = phyTrailer[1];
++ if (MV_IS_LAN_PORT(incomingPort)) {
++ *pFromLAN = 1;
++ } else {
++ ASSERT(MV_IS_WAN_PORT(incomingPort));
++ *pFromLAN = 0;
++ }
++}
++
++
++/******************************************************************************
++*
++* mv_phySetDestinationPort - Set the Ingress Trailer to force the
++* frame to be sent to LAN or WAN, as specified.
++*
++*/
++void
++mv_phySetDestinationPort(char *data, int len, int fromLAN)
++{
++ char *phyTrailer;
++
++ phyTrailer = &data[len];
++ if (fromLAN) {
++ /* LAN ports: Use default settings, as per mvPhyInfo */
++ phyTrailer[0] = 0x00;
++ phyTrailer[1] = 0x00;
++ } else {
++ /* WAN port: Direct to WAN port */
++ phyTrailer[0] = MV_INGRESS_TRAILER_OVERRIDE;
++ phyTrailer[1] = 1 << MV_WAN_PORT;
++ }
++ phyTrailer[2] = 0x00;
++ phyTrailer[3] = 0x00;
++}
++#endif
++
++
++/*****************************************************************************
++*
++* Validate that the specified PHY unit number is a valid PHY ID.
++* Print a message if it is invalid.
++* RETURNS
++* TRUE --> valid
++* FALSE --> invalid
++*/
++LOCAL BOOL
++mv_validPhyId(int phyUnit)
++{
++ if ((phyUnit >= MV_ID_MIN) && (phyUnit <= MV_ID_MAX)) {
++ return TRUE;
++ } else {
++ PRINTF("PHY unit number must be in the range [%d..%d]\n",
++ MV_ID_MIN, MV_ID_MAX);
++ return FALSE;
++ }
++}
++
++
++/*****************************************************************************
++*
++* mv_waitWhileATUBusy - spins until the ATU completes
++* its previous operation.
++*/
++LOCAL void
++mv_waitWhileATUBusy(UINT32 phyBase)
++{
++ BOOL isBusy;
++ UINT16 ATUOperation;
++
++ do {
++
++ ATUOperation = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
++ MV_ATU_OPERATION);
++
++ isBusy = (ATUOperation & MV_ATU_BUSY_MASK) == MV_ATU_IS_BUSY;
++
++ } while(isBusy);
++}
++
++/*****************************************************************************
++*
++* mv_flushATUDB - flushes ALL entries in the Address Translation Unit
++* DataBase associated with phyUnit. [Since we use a single DB for
++* all PHYs, this flushes the entire shared DataBase.]
++*
++* The current implementation flushes even more than absolutely needed --
++* it flushes all entries for all phyUnits on the same ethernet as the
++* specified phyUnit.
++*
++* It is called only when a link failure is detected on a port that was
++* previously working. In other words, when the cable is unplugged.
++*/
++void
++mv_flushATUDB(int phyUnit)
++{
++ UINT32 phyBase;
++
++ if (!mv_validPhyId(phyUnit)) {
++ PRINTF("Invalid port number: %d\n", phyUnit);
++ return;
++ }
++
++ phyBase = MV_PHYBASE(phyUnit);
++
++ /* Wait for previous operation (if any) to complete */
++ mv_waitWhileATUBusy(phyBase);
++
++ /* Tell hardware to flush all entries */
++ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_OPERATION,
++ MV_ATU_OP_FLUSH_ALL | MV_ATU_IS_BUSY);
++
++ mv_waitWhileATUBusy(phyBase);
++}
++
++/*****************************************************************************
++*
++* mv_phyCheckStatusChange -- checks for significant changes in PHY state.
++*
++* A "significant change" is:
++* dropped link (e.g. ethernet cable unplugged) OR
++* autonegotiation completed + link (e.g. ethernet cable plugged in)
++*/
++void
++mv_phyCheckStatusChange(int ethUnit)
++{
++ int phyUnit;
++ UINT16 phyHwStatus;
++ mvPhyInfo_t *lastStatus;
++ int linkCount = 0;
++ int lostLinks = 0;
++ int gainedLinks = 0;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
++ if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++
++ phyBase = MV_PHYBASE(phyUnit);
++ phyAddr = MV_PHYADDR(phyUnit);
++
++ lastStatus = &mvPhyInfo[phyUnit];
++ phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
++
++ if (lastStatus->isPhyAlive) { /* last known link status was ALIVE */
++ /* See if we've lost link */
++ if (phyHwStatus & MV_STATUS_REAL_TIME_LINK_UP) {
++ linkCount++;
++ } else {
++ lostLinks++;
++ mv_flushATUDB(phyUnit);
++ MV_PRINT(MV_DEBUG_PHYCHANGE,("\nethmac%d port%d down\n",
++ ethUnit, phyUnit));
++ lastStatus->isPhyAlive = FALSE;
++ }
++ } else { /* last known link status was DEAD */
++ /* Check for AutoNegotiation complete */
++ if (MV_AUTONEG_DONE(phyHwStatus)) {
++ gainedLinks++;
++ linkCount++;
++ MV_PRINT(MV_DEBUG_PHYCHANGE,("\nethmac%d port%d up\n",
++ ethUnit, phyUnit));
++ lastStatus->isPhyAlive = TRUE;
++ }
++ }
++ }
++
++ if (linkCount == 0) {
++ if (lostLinks) {
++ /* We just lost the last link for this MAC */
++ phyLinkLost(ethUnit);
++ }
++ } else {
++ if (gainedLinks == linkCount) {
++ /* We just gained our first link(s) for this MAC */
++ phyLinkGained(ethUnit);
++ }
++ }
++}
++
++#if DEBUG
++
++/* Define the registers of interest for a phyShow command */
++typedef struct mvRegisterTableEntry_s {
++ UINT32 regNum;
++ char *regIdString;
++} mvRegisterTableEntry_t;
++
++mvRegisterTableEntry_t mvPhyRegisterTable[] = {
++ {MV_PHY_CONTROL, "PHY Control "},
++ {MV_PHY_STATUS, "PHY Status "},
++ {MV_PHY_ID1, "PHY Identifier 1 "},
++ {MV_PHY_ID2, "PHY Identifier 2 "},
++ {MV_AUTONEG_ADVERT, "Auto-Negotiation Advertisement "},
++ {MV_LINK_PARTNER_ABILITY, "Link Partner Ability "},
++ {MV_AUTONEG_EXPANSION, "Auto-Negotiation Expansion "},
++ {MV_NEXT_PAGE_TRANSMIT, "Next Page Transmit "},
++ {MV_LINK_PARTNER_NEXT_PAGE, "Link Partner Next Page "},
++ {MV_PHY_SPECIFIC_CONTROL_1, "PHY-Specific Control Register 1 "},
++ {MV_PHY_SPECIFIC_STATUS, "PHY-Specific Status "},
++ {MV_PHY_INTERRUPT_ENABLE, "PHY Interrupt Enable "},
++ {MV_PHY_INTERRUPT_STATUS, "PHY Interrupt Status "},
++ {MV_PHY_INTERRUPT_PORT_SUMMARY, "PHY Interrupt Port Summary "},
++ {MV_RECEIVE_ERROR_COUNTER, "Receive Error Counter "},
++ {MV_LED_PARALLEL_SELECT, "LED Parallel Select "},
++ {MV_LED_STREAM_SELECT_LEDS, "LED Stream Select "},
++ {MV_PHY_LED_CONTROL, "PHY LED Control "},
++ {MV_PHY_MANUAL_LED_OVERRIDE, "PHY Manual LED Override "},
++ {MV_VCT_CONTROL, "VCT Control "},
++ {MV_VCT_STATUS, "VCT Status "},
++ {MV_PHY_SPECIFIC_CONTROL_2, "PHY-Specific Control Register 2 "},
++};
++int mvPhyNumRegs = sizeof(mvPhyRegisterTable) / sizeof(mvPhyRegisterTable[0]);
++
++
++mvRegisterTableEntry_t mvSwitchPortRegisterTable[] = {
++ {MV_PORT_STATUS, "Port Status "},
++ {MV_SWITCH_ID, "Switch ID "},
++ {MV_PORT_CONTROL, "Port Control "},
++ {MV_PORT_BASED_VLAN_MAP, "Port-Based VLAN Map "},
++ {MV_PORT_ASSOCIATION_VECTOR, "Port Association Vector "},
++ {MV_RX_COUNTER, "RX Counter "},
++ {MV_TX_COUNTER, "TX Counter "},
++};
++int mvSwitchPortNumRegs =
++ sizeof(mvSwitchPortRegisterTable) / sizeof(mvSwitchPortRegisterTable[0]);
++
++
++mvRegisterTableEntry_t mvSwitchGlobalRegisterTable[] = {
++ {MV_SWITCH_GLOBAL_STATUS, "Switch Global Status "},
++ {MV_SWITCH_MAC_ADDR0, "Switch MAC Addr 0 & 1 "},
++ {MV_SWITCH_MAC_ADDR2, "Switch MAC Addr 2 & 3 "},
++ {MV_SWITCH_MAC_ADDR4, "Switch MAC Addr 4 & 5 "},
++ {MV_SWITCH_GLOBAL_CONTROL, "Switch Global Control "},
++ {MV_ATU_CONTROL, "ATU Control "},
++ {MV_ATU_OPERATION, "ATU Operation "},
++ {MV_ATU_DATA, "ATU Data "},
++ {MV_ATU_MAC_ADDR0, "ATU MAC Addr 0 & 1 "},
++ {MV_ATU_MAC_ADDR2, "ATU MAC Addr 2 & 3 "},
++ {MV_ATU_MAC_ADDR4, "ATU MAC Addr 4 & 5 "},
++};
++int mvSwitchGlobalNumRegs =
++ sizeof(mvSwitchGlobalRegisterTable) / sizeof(mvSwitchGlobalRegisterTable[0]);
++
++void my_mvPhyShow(int ethUnit)
++{
++ int phyUnit;
++ for (phyUnit=0; (phyUnit < MV_PHY_MAX); phyUnit++) {
++ if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
++ continue;
++ }
++ mv_phyShow(phyUnit);
++ }
++}
++
++/*****************************************************************************
++*
++* mv_phyShow - Dump the state of a PHY.
++* There are two sets of registers for each phy port:
++* "phy registers" and
++* "switch port registers"
++* We dump 'em all, plus the switch global registers.
++*/
++void
++mv_phyShow(int phyUnit)
++{
++ int i;
++ UINT16 value;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++ UINT32 switchPortAddr;
++
++ if (!mv_validPhyId(phyUnit)) {
++ return;
++ }
++
++ phyBase = MV_PHYBASE(phyUnit);
++ phyAddr = MV_PHYADDR(phyUnit);
++ switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
++
++ printk("PHY state for PHY%d (ethmac%d, phyBase 0x%8x, phyAddr 0x%x, switchAddr 0x%x)\n",
++ phyUnit,
++ MV_ETHUNIT(phyUnit),
++ MV_PHYBASE(phyUnit),
++ MV_PHYADDR(phyUnit),
++ MV_SWITCH_PORT_ADDR(phyUnit));
++
++ printk("PHY Registers:\n");
++ for (i=0; i < mvPhyNumRegs; i++) {
++
++ value = phyRegRead(phyBase, phyAddr, mvPhyRegisterTable[i].regNum);
++
++ printk("Reg %02d (0x%02x) %s = 0x%08x\n",
++ mvPhyRegisterTable[i].regNum,
++ mvPhyRegisterTable[i].regNum,
++ mvPhyRegisterTable[i].regIdString,
++ value);
++ }
++
++ printk("Switch Port Registers:\n");
++ for (i=0; i < mvSwitchPortNumRegs; i++) {
++
++ value = phyRegRead(phyBase, switchPortAddr,
++ mvSwitchPortRegisterTable[i].regNum);
++
++ printk("Reg %02d (0x%02x) %s = 0x%08x\n",
++ mvSwitchPortRegisterTable[i].regNum,
++ mvSwitchPortRegisterTable[i].regNum,
++ mvSwitchPortRegisterTable[i].regIdString,
++ value);
++ }
++
++ printk("Switch Global Registers:\n");
++ for (i=0; i < mvSwitchGlobalNumRegs; i++) {
++
++ value = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
++ mvSwitchGlobalRegisterTable[i].regNum);
++
++ printk("Reg %02d (0x%02x) %s = 0x%08x\n",
++ mvSwitchGlobalRegisterTable[i].regNum,
++ mvSwitchGlobalRegisterTable[i].regNum,
++ mvSwitchGlobalRegisterTable[i].regIdString,
++ value);
++ }
++}
++
++/*****************************************************************************
++*
++* mv_phySet - Modify the value of a PHY register (debug only).
++*/
++void
++mv_phySet(int phyUnit, UINT32 regnum, UINT32 value)
++{
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ if (mv_validPhyId(phyUnit)) {
++
++ phyBase = MV_PHYBASE(phyUnit);
++ phyAddr = MV_PHYADDR(phyUnit);
++
++ phyRegWrite(phyBase, phyAddr, regnum, value);
++ }
++}
++
++
++/*****************************************************************************
++*
++* mv_switchPortSet - Modify the value of a switch port register (debug only).
++*/
++void
++mv_switchPortSet(int phyUnit, UINT32 regnum, UINT32 value)
++{
++ UINT32 phyBase;
++ UINT32 switchPortAddr;
++
++ if (mv_validPhyId(phyUnit)) {
++
++ phyBase = MV_PHYBASE(phyUnit);
++ switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
++
++ phyRegWrite(phyBase, switchPortAddr, regnum, value);
++ }
++}
++
++/*****************************************************************************
++*
++* mv_switchGlobalSet - Modify the value of a switch global register
++* (debug only).
++*/
++void
++mv_switchGlobalSet(int phyUnit, UINT32 regnum, UINT32 value)
++{
++ UINT32 phyBase;
++
++ if (mv_validPhyId(phyUnit)) {
++
++ phyBase = MV_PHYBASE(phyUnit);
++
++ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, regnum, value);
++ }
++}
++
++/*****************************************************************************
++*
++* mv_showATUDB - Dump the contents of the Address Translation Unit DataBase
++* for the PHY switch associated with the specified phy.
++*/
++void
++mv_showATUDB(int phyUnit)
++{
++ UINT32 phyBase;
++ UINT16 ATUData;
++ UINT16 ATUMac0;
++ UINT16 ATUMac2;
++ UINT16 ATUMac4;
++ int portVec;
++ int entryState;
++
++ if (!mv_validPhyId(phyUnit)) {
++ printk("Invalid port number: %d\n", phyUnit);
++ return;
++ }
++
++ phyBase = MV_PHYBASE(phyUnit);
++
++ /* Wait for previous operation (if any) to complete */
++ mv_waitWhileATUBusy(phyBase);
++
++ /* Initialize ATU MAC to all 1's */
++ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR0, 0xffff);
++ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR2, 0xffff);
++ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR4, 0xffff);
++
++ printk(" MAC ADDRESS EntryState PortVector\n");
++
++ for(;;) {
++ /* Tell hardware to get next MAC info */
++ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_OPERATION,
++ MV_ATU_OP_GET_NEXT | MV_ATU_IS_BUSY);
++
++ mv_waitWhileATUBusy(phyBase);
++
++ ATUData = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_DATA);
++ entryState = (ATUData & MV_ENTRYSTATE_MASK) >> MV_ENTRYSTATE_SHIFT;
++
++ if (entryState == 0) {
++ /* We've hit the end of the list */
++ break;
++ }
++
++ ATUMac0 = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR0);
++ ATUMac2 = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR2);
++ ATUMac4 = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR4);
++
++ portVec = (ATUData & MV_PORTVEC_MASK) >> MV_PORTVEC_SHIFT;
++
++ printk("%02x:%02x:%02x:%02x:%02x:%02x 0x%02x 0x%02x\n",
++ ATUMac0 >> 8, /* MAC byte 0 */
++ ATUMac0 & 0xff, /* MAC byte 1 */
++ ATUMac2 >> 8, /* MAC byte 2 */
++ ATUMac2 & 0xff, /* MAC byte 3 */
++ ATUMac4 >> 8, /* MAC byte 4 */
++ ATUMac4 & 0xff, /* MAC byte 5 */
++ entryState,
++ portVec);
++ }
++}
++
++LOCAL BOOL countingGoodFrames;
++
++/*****************************************************************************
++*
++* mv_countGoodFrames - starts counting GOOD RX/TX frames per port
++*/
++void
++mv_countGoodFrames(int phyUnit)
++{
++ UINT32 phyBase;
++ UINT16 globalControl;
++
++ if (mv_validPhyId(phyUnit)) {
++ /*
++ * Guarantee that counters are cleared by
++ * forcing CtrMode to toggle and end on GOODFRAMES.
++ */
++
++ phyBase = MV_PHYBASE(phyUnit);
++
++ /* Read current Switch Global Control Register */
++ globalControl = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
++ MV_SWITCH_GLOBAL_CONTROL);
++
++ /* Set CtrMode to count BAD frames */
++ globalControl = ((globalControl & ~MV_CTRMODE_MASK) |
++ MV_CTRMODE_BADFRAMES);
++
++ /* Push new value out to hardware */
++ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR,
++ MV_SWITCH_GLOBAL_CONTROL, globalControl);
++
++ /* Now toggle CtrMode to count GOOD frames */
++ globalControl = ((globalControl & ~MV_CTRMODE_MASK) |
++ MV_CTRMODE_GOODFRAMES);
++
++ /* Push new value out to hardware */
++ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR,
++ MV_SWITCH_GLOBAL_CONTROL, globalControl);
++
++ countingGoodFrames = TRUE;
++ }
++}
++
++/*****************************************************************************
++*
++* mv_countBadFrames - starts counting BAD RX/TX frames per port
++*/
++void
++mv_countBadFrames(int phyUnit)
++{
++ UINT32 phyBase;
++ UINT16 globalControl;
++
++ if (mv_validPhyId(phyUnit)) {
++ /*
++ * Guarantee that counters are cleared by
++ * forcing CtrMode to toggle and end on BADFRAMES.
++ */
++
++ phyBase = MV_PHYBASE(phyUnit);
++
++ /* Read current Switch Global Control Register */
++ globalControl = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
++ MV_SWITCH_GLOBAL_CONTROL);
++
++ /* Set CtrMode to count GOOD frames */
++ globalControl = ((globalControl & ~MV_CTRMODE_MASK) |
++ MV_CTRMODE_GOODFRAMES);
++
++ /* Push new value out to hardware */
++ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR,
++ MV_SWITCH_GLOBAL_CONTROL, globalControl);
++
++ /* Now toggle CtrMode to count BAD frames */
++ globalControl = ((globalControl & ~MV_CTRMODE_MASK) |
++ MV_CTRMODE_BADFRAMES);
++
++ /* Push new value out to hardware */
++ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR,
++ MV_SWITCH_GLOBAL_CONTROL, globalControl);
++
++ countingGoodFrames = FALSE;
++ }
++}
++
++/*****************************************************************************
++*
++* mv_showFrameCounts - shows current GOOD/BAD Frame counts
++*/
++void
++mv_showFrameCounts(int phyUnit)
++{
++ UINT16 rxCounter;
++ UINT16 txCounter;
++ UINT32 phyBase;
++ UINT32 switchPortAddr;
++
++ if (!mv_validPhyId(phyUnit)) {
++ return;
++ }
++
++ phyBase = MV_PHYBASE(phyUnit);
++ switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
++
++ rxCounter = phyRegRead(phyBase, switchPortAddr, MV_RX_COUNTER);
++
++ txCounter = phyRegRead(phyBase, switchPortAddr, MV_TX_COUNTER);
++
++ printk("port%d %s frames: receive: %05d transmit: %05d\n",
++ phyUnit,
++ (countingGoodFrames ? "good" : "error"),
++ rxCounter,
++ txCounter);
++}
++#endif
+diff -urN linux-mips-orig/drivers/net/ath/mvPhy.h linux-mips-new/drivers/net/ath/mvPhy.h
+--- linux-mips-orig/drivers/net/ath/mvPhy.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/mvPhy.h 2005-12-31 12:33:57.727530616 +0000
+@@ -0,0 +1,162 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++ */
++
++/*
++ * mvPhy.h - definitions for the ethernet PHY -- Marvell 88E6060
++ * All definitions in this file are operating system independent!
++ */
++
++#ifndef MVPHY_H
++#define MVPHY_H
++
++/*****************/
++/* PHY Registers */
++/*****************/
++#define MV_PHY_CONTROL 0
++#define MV_PHY_STATUS 1
++#define MV_PHY_ID1 2
++#define MV_PHY_ID2 3
++#define MV_AUTONEG_ADVERT 4
++#define MV_LINK_PARTNER_ABILITY 5
++#define MV_AUTONEG_EXPANSION 6
++#define MV_NEXT_PAGE_TRANSMIT 7
++#define MV_LINK_PARTNER_NEXT_PAGE 8
++#define MV_PHY_SPECIFIC_CONTROL_1 16
++#define MV_PHY_SPECIFIC_STATUS 17
++#define MV_PHY_INTERRUPT_ENABLE 18
++#define MV_PHY_INTERRUPT_STATUS 19
++#define MV_PHY_INTERRUPT_PORT_SUMMARY 20
++#define MV_RECEIVE_ERROR_COUNTER 21
++#define MV_LED_PARALLEL_SELECT 22
++#define MV_LED_STREAM_SELECT_LEDS 23
++#define MV_PHY_LED_CONTROL 24
++#define MV_PHY_MANUAL_LED_OVERRIDE 25
++
++#define MV_VCT_CONTROL 26
++#define MV_VCT_STATUS 27
++#define MV_PHY_SPECIFIC_CONTROL_2 28
++
++/* MV_PHY_CONTROL fields */
++#define MV_CTRL_SOFTWARE_RESET 0x8000
++#define MV_CTRL_AUTONEGOTIATION_ENABLE 0x1000
++#define MV_CTRL_FULL_DUPLEX 0x0100
++#define MV_CTRL_100_MBPS 0x2000
++
++/* MV_PHY_ID1 fields */
++#define MV_PHY_ID1_EXPECTATION 0x0141 /* OUI >> 6 */
++
++/* MV_PHY_ID2 fields */
++#define MV_OUI_LSB_MASK 0xfc00
++#define MV_OUI_LSB_EXPECTATION 0x0c00
++#define MV_OUI_LSB_SHIFT 10
++#define MV_MODEL_NUM_MASK 0x03f0
++#define MV_MODEL_NUM_SHIFT 4
++#define MV_REV_NUM_MASK 0x000f
++#define MV_REV_NUM_SHIFT 0
++
++/* MV_PHY_SPECIFIC_STATUS fields */
++#define MV_STATUS_RESOLVED_SPEED_100 0x4000
++#define MV_STATUS_RESOLVED_DUPLEX_FULL 0x2000
++#define MV_STATUS_RESOLVED 0x0800
++#define MV_STATUS_REAL_TIME_LINK_UP 0x0400
++
++/* Check if autonegotiation is complete and link is up */
++#define MV_AUTONEG_DONE(mv_phy_specific_status) \
++ (((mv_phy_specific_status) & \
++ (MV_STATUS_RESOLVED | MV_STATUS_REAL_TIME_LINK_UP)) == \
++ (MV_STATUS_RESOLVED | MV_STATUS_REAL_TIME_LINK_UP))
++
++
++/*************************/
++/* Switch Port Registers */
++/*************************/
++#define MV_PORT_STATUS 0
++#define MV_SWITCH_ID 3
++#define MV_PORT_CONTROL 4
++#define MV_PORT_BASED_VLAN_MAP 6
++#define MV_PORT_ASSOCIATION_VECTOR 11
++#define MV_RX_COUNTER 16
++#define MV_TX_COUNTER 17
++
++/* MV_SWITCH_ID fields */
++#define MV_SWITCH_ID_DEV_MASK 0xfff0
++#define MV_SWITCH_ID_DEV_EXPECTATION 0x0600
++#define MV_SWITCH_ID_DEV_SHIFT 4
++#define MV_SWITCH_ID_REV_MASK 0x000f
++#define MV_SWITCH_ID_REV_SHIFT 0
++
++/* MV_PORT_CONTROL fields */
++#define MV_PORT_CONTROL_PORT_STATE_MASK 0x0003
++#define MV_PORT_CONTROL_PORT_STATE_DISABLED 0x0000
++#define MV_PORT_CONTROL_PORT_STATE_FORWARDING 0x0003
++
++#define MV_PORT_CONTROL_EGRESS_MODE 0x0100 /* Receive */
++#define MV_PORT_CONTROL_INGRESS_TRAILER 0x4000 /* Transmit */
++
++#define MV_EGRESS_TRAILER_VALID 0x80
++#define MV_INGRESS_TRAILER_OVERRIDE 0x80
++
++#define MV_PHY_TRAILER_SIZE 4
++
++
++/***************************/
++/* Switch Global Registers */
++/***************************/
++#define MV_SWITCH_GLOBAL_STATUS 0
++#define MV_SWITCH_MAC_ADDR0 1
++#define MV_SWITCH_MAC_ADDR2 2
++#define MV_SWITCH_MAC_ADDR4 3
++#define MV_SWITCH_GLOBAL_CONTROL 4
++#define MV_ATU_CONTROL 10
++#define MV_ATU_OPERATION 11
++#define MV_ATU_DATA 12
++#define MV_ATU_MAC_ADDR0 13
++#define MV_ATU_MAC_ADDR2 14
++#define MV_ATU_MAC_ADDR4 15
++
++/* MV_SWITCH_GLOBAL_STATUS fields */
++#define MV_SWITCH_STATUS_READY_MASK 0x0800
++
++/* MV_SWITCH_GLOBAL_CONTROL fields */
++#define MV_CTRMODE_MASK 0x0100
++#define MV_CTRMODE_GOODFRAMES 0x0000
++#define MV_CTRMODE_BADFRAMES 0x0100
++
++/* MV_ATU_CONTROL fields */
++#define MV_ATUCTRL_ATU_SIZE_MASK 0x3000
++#define MV_ATUCTRL_ATU_SIZE_SHIFT 12
++#define MV_ATUCTRL_ATU_SIZE_DEFAULT 2 /* 1024 entry database */
++#define MV_ATUCTRL_AGE_TIME_MASK 0x0ff0
++#define MV_ATUCTRL_AGE_TIME_SHIFT 4
++#define MV_ATUCTRL_AGE_TIME_DEFAULT 19 /* 19 * 16 = 304 seconds */
++
++/* MV_ATU_OPERATION fields */
++#define MV_ATU_BUSY_MASK 0x8000
++#define MV_ATU_IS_BUSY 0x8000
++#define MV_ATU_IS_FREE 0x0000
++#define MV_ATU_OP_MASK 0x7000
++#define MV_ATU_OP_FLUSH_ALL 0x1000
++#define MV_ATU_OP_GET_NEXT 0x4000
++
++/* MV_ATU_DATA fields */
++#define MV_ENTRYPRI_MASK 0xc000
++#define MV_ENTRYPRI_SHIFT 14
++#define MV_PORTVEC_MASK 0x03f0
++#define MV_PORTVEC_SHIFT 4
++#define MV_ENTRYSTATE_MASK 0x000f
++#define MV_ENTRYSTATE_SHIFT 0
++
++/* PHY Address for the switch itself */
++#define MV_SWITCH_GLOBAL_ADDR 0x1f
++
++BOOL mv_phySetup(int ethUnit, UINT32 phyBase);
++void mv_phyCheckStatusChange(int ethUnit);
++BOOL mv_phyIsSpeed100(int ethUnit);
++int mv_phyIsFullDuplex(int ethUnit);
++
++#endif /* MVPHY_H */
+diff -urN linux-mips-orig/drivers/net/ath/rtPhy.c linux-mips-new/drivers/net/ath/rtPhy.c
+--- linux-mips-orig/drivers/net/ath/rtPhy.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/rtPhy.c 2005-12-31 12:33:57.727530616 +0000
+@@ -0,0 +1,272 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++ */
++
++/*
++ * Manage the ethernet PHY.
++ * This code supports a simple 1-port ethernet phy, Realtek RTL8201BL,
++ * and compatible PHYs, such as the Kendin KS8721B.
++ * All definitions in this file are operating system independent!
++ */
++
++#if defined(linux)
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/delay.h>
++
++#include "ar531xlnx.h"
++#endif
++
++#if defined(__ECOS)
++#include "ae531xecos.h"
++#endif
++
++
++#include "ae531xmac.h"
++#include "ae531xreg.h"
++#include "rtPhy.h"
++
++#if /* DEBUG */ 1
++#define RT_DEBUG_ERROR 0x00000001
++#define RT_DEBUG_PHYSETUP 0x00000002
++#define RT_DEBUG_PHYCHANGE 0x00000004
++
++int rtPhyDebug = RT_DEBUG_ERROR;
++
++#define RT_PRINT(FLG, X) \
++{ \
++ if (rtPhyDebug & (FLG)) { \
++ DEBUG_PRINTF X; \
++ } \
++}
++#else
++#define RT_PRINT(FLG, X)
++#endif
++
++/*
++ * Track per-PHY port information.
++ */
++typedef struct {
++ BOOL phyAlive; /* last known state of link */
++ UINT32 phyBase;
++ UINT32 phyAddr;
++} rtPhyInfo_t;
++
++#define ETH_PHY_ADDR 1
++
++/*
++ * This table defines the mapping from phy units to
++ * per-PHY information.
++ *
++ * This table is somewhat board-dependent.
++ */
++rtPhyInfo_t rtPhyInfo[] = {
++ {phyAlive: FALSE, /* PHY 0 */
++ phyBase: 0, /* filled in by rt_phySetup */
++ phyAddr: ETH_PHY_ADDR},
++
++ {phyAlive: FALSE, /* PHY 1 */
++ phyBase: 0, /* filled in by rt_phySetup */
++ phyAddr: ETH_PHY_ADDR}
++};
++
++/* Convert from phy unit# to (phyBase, phyAddr) pair */
++#define RT_PHYBASE(phyUnit) (rtPhyInfo[phyUnit].phyBase)
++#define RT_PHYADDR(phyUnit) (rtPhyInfo[phyUnit].phyAddr)
++
++
++/******************************************************************************
++*
++* rt_phySetup - reset and setup the PHY associated with
++* the specified MAC unit number.
++*
++* Resets the associated PHY port.
++*
++* RETURNS:
++* TRUE --> associated PHY is alive
++* FALSE --> no LINKs on this ethernet unit
++*/
++
++BOOL
++rt_phySetup(int ethUnit, UINT32 phyBase)
++{
++ BOOL linkAlive = FALSE;
++ UINT32 phyAddr;
++
++ RT_PHYBASE(ethUnit) = phyBase;
++
++ phyAddr = RT_PHYADDR(ethUnit);
++
++ /* Reset phy */
++ phyRegWrite(phyBase, phyAddr, GEN_ctl, PHY_SW_RST | AUTONEGENA);
++
++ sysMsDelay(1500);
++
++ return linkAlive;
++}
++
++/******************************************************************************
++*
++* rt_phyIsDuplexFull - Determines whether the phy ports associated with the
++* specified device are FULL or HALF duplex.
++*
++* RETURNS:
++* 1 --> FULL
++* 0 --> HALF
++*/
++int
++rt_phyIsFullDuplex(int ethUnit)
++{
++ UINT16 phyCtl;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ phyBase = RT_PHYBASE(ethUnit);
++ phyAddr = RT_PHYADDR(ethUnit);
++
++ phyCtl = phyRegRead(phyBase, phyAddr, GEN_ctl);
++
++ if (phyCtl & DUPLEX) {
++ return 1;
++ } else {
++ return 0;
++ }
++}
++
++/******************************************************************************
++*
++* rt_phyIsSpeed100 - Determines the speed of phy ports associated with the
++* specified device.
++*
++* RETURNS:
++* TRUE --> 100Mbit
++* FALSE --> 10Mbit
++*/
++BOOL
++rt_phyIsSpeed100(int phyUnit)
++{
++ UINT16 phyLpa;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ phyBase = RT_PHYBASE(phyUnit);
++ phyAddr = RT_PHYADDR(phyUnit);
++
++ phyLpa = phyRegRead(phyBase, phyAddr, AN_lpa);
++
++ if (phyLpa & (LPA_TXFD | LPA_TX)) {
++ return TRUE;
++ } else {
++ return FALSE;
++ }
++}
++
++/*****************************************************************************
++*
++* rt_phyCheckStatusChange -- checks for significant changes in PHY state.
++*
++* A "significant change" is:
++* dropped link (e.g. ethernet cable unplugged) OR
++* autonegotiation completed + link (e.g. ethernet cable plugged in)
++*
++* On AR5311, there is a 1-to-1 mapping of ethernet units to PHYs.
++* When a PHY is plugged in, phyLinkGained is called.
++* When a PHY is unplugged, phyLinkLost is called.
++*/
++void
++rt_phyCheckStatusChange(int ethUnit)
++{
++ UINT16 phyHwStatus;
++ rtPhyInfo_t *lastStatus = &rtPhyInfo[ethUnit];
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ phyBase = RT_PHYBASE(ethUnit);
++ phyAddr = RT_PHYADDR(ethUnit);
++
++ phyHwStatus = phyRegRead(phyBase, phyAddr, GEN_sts);
++
++ if (lastStatus->phyAlive) { /* last known status was ALIVE */
++ /* See if we've lost link */
++ if (!(phyHwStatus & LINK)) {
++ RT_PRINT(RT_DEBUG_PHYCHANGE,("\nethmac%d link down\n", ethUnit));
++ lastStatus->phyAlive = FALSE;
++ phyLinkLost(ethUnit);
++ }
++ } else { /* last known status was DEAD */
++ /* Check for AN complete */
++ if ((phyHwStatus & (AUTOCMPLT | LINK)) == (AUTOCMPLT | LINK)) {
++ RT_PRINT(RT_DEBUG_PHYCHANGE,("\nethmac%d link up\n", ethUnit));
++ lastStatus->phyAlive = TRUE;
++ phyLinkGained(ethUnit);
++ }
++ }
++}
++
++#if DEBUG
++
++/* Define the PHY registers of interest for a phyShow command */
++struct rtRegisterTable_s {
++ UINT32 regNum;
++ char *regIdString;
++} rtRegisterTable[] =
++{
++ {GEN_ctl, "Basic Mode Control (GEN_ctl) "},
++ {GEN_sts, "Basic Mode Status (GEN_sts) "},
++ {GEN_id_hi, "PHY Identifier 1 (GET_id_hi) "},
++ {GEN_id_lo, "PHY Identifier 2 (GET_id_lo) "},
++ {AN_adv, "Auto-Neg Advertisement (AN_adv) "},
++ {AN_lpa, "Auto-Neg Link Partner Ability "},
++ {AN_exp, "Auto-Neg Expansion "},
++};
++
++int rtNumRegs = sizeof(rtRegisterTable) / sizeof(rtRegisterTable[0]);
++
++/*
++ * Dump the state of a PHY.
++ */
++void
++rt_phyShow(int phyUnit)
++{
++ int i;
++ UINT16 value;
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ phyBase = RT_PHYBASE(phyUnit);
++ phyAddr = RT_PHYADDR(phyUnit);
++
++ printf("PHY state for ethphy%d\n", phyUnit);
++
++ for (i=0; i<rtNumRegs; i++) {
++
++ value = phyRegRead(phyBase, phyAddr, rtRegisterTable[i].regNum);
++
++ printf("Reg %02d (0x%02x) %s = 0x%08x\n",
++ rtRegisterTable[i].regNum, rtRegisterTable[i].regNum,
++ rtRegisterTable[i].regIdString, value);
++ }
++}
++
++/*
++ * Modify the value of a PHY register.
++ * This makes it a bit easier to modify PHY values during debug.
++ */
++void
++rt_phySet(int phyUnit, UINT32 regnum, UINT32 value)
++{
++ UINT32 phyBase;
++ UINT32 phyAddr;
++
++ phyBase = RT_PHYBASE(phyUnit);
++ phyAddr = RT_PHYADDR(phyUnit);
++
++ phyRegWrite(phyBase, phyAddr, regnum, value);
++}
++#endif
+diff -urN linux-mips-orig/drivers/net/ath/rtPhy.h linux-mips-new/drivers/net/ath/rtPhy.h
+--- linux-mips-orig/drivers/net/ath/rtPhy.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-mips-new/drivers/net/ath/rtPhy.h 2005-12-31 12:33:57.727530616 +0000
+@@ -0,0 +1,50 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
++ */
++
++/*
++ * rtPhy.h - definitions for the ethernet PHY.
++ * This code supports a simple 1-port ethernet phy, Realtek RTL8201BL,
++ * and compatible PHYs, such as the Kendin KS8721B.
++ * All definitions in this file are operating system independent!
++ */
++
++#ifndef RTPHY_H
++#define RTPHY_H
++
++/* MII Registers */
++
++#define GEN_ctl 00
++#define GEN_sts 01
++#define GEN_id_hi 02
++#define GEN_id_lo 03
++#define AN_adv 04
++#define AN_lpa 05
++#define AN_exp 06
++
++/* GEN_ctl */
++#define PHY_SW_RST 0x8000
++#define LOOPBACK 0x4000
++#define SPEED 0x2000 /* 100 Mbit/s */
++#define AUTONEGENA 0x1000
++#define DUPLEX 0x0100 /* Duplex mode */
++
++
++/* GEN_sts */
++#define AUTOCMPLT 0x0020 /* Autonegotiation completed */
++#define LINK 0x0004 /* Link status */
++
++/* GEN_ids */
++#define RT_PHY_ID1_EXPECTATION 0x22
++
++/* AN_lpa */
++#define LPA_TXFD 0x0100 /* Link partner supports 100 TX Full Duplex */
++#define LPA_TX 0x0080 /* Link partner supports 100 TX Half Duplex */
++#define LPA_10FD 0x0040 /* Link partner supports 10 BT Full Duplex */
++#define LPA_10 0x0020 /* Link partner supports 10 BT Half Duplex */
++
++#endif /* RTPHY_H */
+diff -urN linux-mips/include/linux/raid/md_p.h mips-linux-2.4.25/include/linux/raid/md_p.h
+--- linux-mips/include/linux/raid/md_p.h 2005-12-24 15:12:07.189098448 +0000
++++ mips-linux-2.4.25/include/linux/raid/md_p.h 2005-12-30 17:28:10.345721232 +0000
+@@ -151,10 +151,12 @@
+ */
+ mdp_disk_t disks[MD_SB_DISKS];
+
++#if MD_SB_RESERVED_WORDS
+ /*
+ * Reserved
+ */
+ __u32 reserved[MD_SB_RESERVED_WORDS];
++#endif
+
+ /*
+ * Active descriptor
diff --git a/target/linux/linux-2.4/patches/ar531x/001-ar531x-ethernet.patch b/target/linux/linux-2.4/patches/ar531x/001-ar531x-ethernet.patch
deleted file mode 100644
index 15dd777ec4..0000000000
--- a/target/linux/linux-2.4/patches/ar531x/001-ar531x-ethernet.patch
+++ /dev/null
@@ -1,4890 +0,0 @@
-diff -urN linux-2.4.32.new/arch/mips/ar531x/ae531xlnx.c linux-2.4.32.new-eth/arch/mips/ar531x/ae531xlnx.c
---- linux-2.4.32.new/arch/mips/ar531x/ae531xlnx.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new-eth/arch/mips/ar531x/ae531xlnx.c 2005-12-25 11:54:20.756273952 +0000
-@@ -0,0 +1,1534 @@
-+/*
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file "COPYING" in the main directory of this archive
-+ * for more details.
-+ *
-+ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
-+ */
-+
-+/*
-+ * Ethernet driver for Atheros' ae531x ethernet MAC.
-+ * This is a fairly generic driver, but it's intended
-+ * for use in typical Atheros products.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/types.h>
-+#include <linux/delay.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/init.h>
-+#include <linux/skbuff.h>
-+#include <asm/io.h>
-+
-+#include "ar531xlnx.h"
-+#include "ae531xreg.h"
-+#include "ae531xmac.h"
-+
-+/*
-+ * A word about CONFIG_VENETDEV: It's intended to support two
-+ * "virtualized ethernet devices" that share a single underlying MAC.
-+ * To upper layers, it appears that the hardware supports two MACs,
-+ * with enet0 used for LAN ports and enet1 used for a WAN port. This
-+ * is useful, for instance, when building a 5-port router on hardware
-+ * that uses only one of the AR5312's ethernet MACs.
-+ *
-+ * Virtualization is accomplished through trickery at the ethernet
-+ * PHY layer. We use PHY hardware to determine which port a packet
-+ * was received on, and in order to direct a packet to a particular
-+ * port or set of ports.
-+ *
-+ * The code is mostly written to be generalized to more than two
-+ * virtual devices; but it's intended for one multi-port LAN enet
-+ * device and one single-port WAN enet device.
-+ */
-+
-+#define AE531X_LAN_PORT 0
-+#ifdef CONFIG_VENETDEV
-+#define AE531X_DEV_PER_MAC 2
-+#define AE531X_WAN_PORT 1
-+#else
-+#define AE531X_DEV_PER_MAC 1
-+#endif
-+
-+
-+/*
-+ * ae531x_MAC_state contains driver-specific linux-specific per-MAC information.
-+ * The OSinfo member of ae531x_MAC_t points to one of these.
-+ */
-+typedef struct ae531x_MAC_state {
-+ int irq;
-+ struct tq_struct restart_task;
-+ struct net_device_stats stats;
-+ struct ae531x_dev_sw_state *dev_sw_state[AE531X_DEV_PER_MAC];
-+ int primary_dev;
-+ ae531x_MAC_t MACInfo; /* hardware state */
-+} ae531x_MAC_state_t;
-+
-+/*
-+ * ae531x_dev_sw_state contains driver-specific linux-specific per-device
-+ * information. The net_device priv member points to one of these, and
-+ * this structure contains a pointer to the associated MAC information.
-+ * In the case of CONFIG_VENETDEV, each virtual device has its own
-+ * ae531x_dev_sw_state, and virtual devices that share a physical MAC
-+ * point to the same ae531x_MAC_state.
-+ */
-+typedef struct ae531x_dev_sw_state {
-+ int enetUnit; /* system unit number "eth%d" */
-+ int unit_on_MAC; /* MAC-relative unit number */
-+ struct net_device *dev;
-+ ae531x_MAC_state_t *MAC_state; /* underlying MAC hw/sw state */
-+#ifdef CONFIG_VENETDEV
-+ BOOL isLAN; /* 0-->WAN; 1-->LAN */
-+#endif
-+} ae531x_dev_sw_state_t;
-+
-+/*
-+ * Driver-independent linux-specific per-ethernet device software information.
-+ * Regarding CONFIG_VENETDEV: If a system has 2 physical MACs, and each
-+ * physical MAC has 2 virtual ethernet devices (one for LAN and one for WAN),
-+ * then there are a total of 4 ethernet devices.
-+ */
-+static struct net_device *ae531x_MAC_dev[AR531X_NUM_ENET_MAC * AE531X_DEV_PER_MAC];
-+
-+/* Driver-dependent per-MAC information */
-+static ae531x_MAC_state_t per_MAC_info[AR531X_NUM_ENET_MAC];
-+
-+/*
-+ * Receive buffers need enough room to hold the following:
-+ * 1) a max MTU-sized packet.
-+ * 2) space for an ethernet header
-+ * 3) room at the beginning of the receive buffer in order
-+ * to facilitate cooperating drivers that need to PREpend
-+ * data.
-+ * 4) Depending on configuration, we may need some additional
-+ * room at the END of the rx buffer for phy-supplied
-+ * trailers (if any). (c.f. CONFIG_VENETDEV)
-+ *
-+ * The DMA engine insists on 32-bit aligned RX buffers.
-+ * TBDXXX: With current code, the IP stack ends up looking
-+ * at misaligned headers with word operations. The misaligned
-+ * reads are software-emulated via handle_adel_int. We'd
-+ * rather align the buffers on a 16-bit boundary, but the
-+ * DMA engine doesn't permit it???
-+ */
-+
-+#ifdef CONFIG_VLAN_8021Q
-+#define ETH_MAX_MTU 1522
-+#define HLEN 18
-+#else
-+#define ETH_MAX_MTU 1518
-+#define HLEN ETH_HLEN
-+#endif
-+
-+#define AE531X_RX_BUF_SIZE \
-+ (((2 + RXBUFF_RESERVE + HLEN + ETH_MAX_MTU + PHY_TRAILER_SIZE) + 3) & ~3)
-+
-+/* Forward references to local functions */
-+static void ae531x_TxReap(ae531x_MAC_state_t *MAC_state);
-+static int ae531x_phy_poll(void *data);
-+static int ae531x_MAC_stop(struct net_device *dev);
-+static int ae531x_MAC_open(struct net_device *dev);
-+
-+/* Global to track number of MACs */
-+
-+int ar531x_num_enet_macs;
-+
-+#undef DEBUG_VENETDEV
-+#define AR531X_NAPI
-+
-+#if defined(CONFIG_VENETDEV) && defined(DEBUG_VENETDEV)
-+static int cloned_counter;
-+static int expand_counter;
-+static int both_counter;
-+#endif
-+
-+#ifdef AR531X_NAPI
-+/*******************************************************************************
-+* ae531x_MAC_poll checks for received packets, and sends data
-+* up the stack.
-+*/
-+int
-+ae531x_MAC_poll(struct net_device *dev, int *budget)
-+{
-+ struct sk_buff *skb;
-+ struct sk_buff *newskb;
-+ char *rxBufp;
-+ int unused_length;
-+ VIRT_ADDR rxDesc;
-+ int length;
-+ ae531x_dev_sw_state_t *dev_sw_state;
-+ ae531x_MAC_state_t *MAC_state;
-+ ae531x_MAC_t *MACInfo;
-+ u32 cmdsts;
-+ int rx_limit;
-+ int rx_received;
-+ int rxDescCount;
-+ struct net_device *rxdev;
-+ int early_stop;
-+ int retval;
-+#ifdef CONFIG_VENETDEV
-+ int i;
-+#endif
-+
-+ ARRIVE();
-+
-+ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
-+ MAC_state = dev_sw_state->MAC_state;
-+ MACInfo = &MAC_state->MACInfo;
-+ rx_limit = MAC_state->dev_sw_state[MAC_state->primary_dev]->dev->quota;
-+ rx_received = 0;
-+
-+#ifdef CONFIG_VENETDEV
-+ /*
-+ * Non-primary devs don't explicitly get polled by the upper layers;
-+ * rather, they rely on primary_dev polling to feed packets. But in
-+ * order to keep netif_receive_skb happy, we need to temporarily put the
-+ * net_devices into "polling mode". We pull them back out before
-+ * leaving this function.
-+ */
-+ for (i=0; i<AE531X_DEV_PER_MAC; i++) {
-+ if ((MAC_state->dev_sw_state[i]->dev) &&
-+ (MAC_state->dev_sw_state[i]->unit_on_MAC != MAC_state->primary_dev)) {
-+ netif_rx_schedule(MAC_state->dev_sw_state[i]->dev);
-+ }
-+ }
-+#endif
-+ rxDescCount = 0;
-+
-+ early_stop = 0;
-+ do {
-+ for(;;) {
-+ // ae531x_AckIntr(MACInfo, (DmaIntRxCompleted | DmaIntRxNoBuffer));
-+
-+ rxDesc = MACInfo->rxQueue.curDescAddr;
-+ cmdsts = AE531X_DESC_STATUS_GET(KSEG1ADDR(rxDesc));
-+
-+ AE531X_PRINT(AE531X_DEBUG_RX,
-+ ("examine rxDesc %p with cmdsts=0x%x\n",
-+ (void *)rxDesc, cmdsts));
-+
-+ if (cmdsts & DescOwnByDma) {
-+ /* There's nothing left to process in the RX ring */
-+ goto rx_all_done;
-+ }
-+
-+ rxDescCount++;
-+
-+ AE531X_CONSUME_DESC((&MACInfo->rxQueue));
-+
-+ // A_DATA_CACHE_INVAL(rxDesc, AE531X_DESC_SIZE);
-+
-+ /* Process a packet */
-+ length = AE531X_DESC_STATUS_RX_SIZE(cmdsts) - ETH_CRC_LEN;
-+ if ( (cmdsts & (DescRxFirst |DescRxLast | DescRxErrors)) ==
-+ (DescRxFirst | DescRxLast) ) {
-+ /* Descriptor status indicates "NO errors" */
-+ skb = AE531X_DESC_SWPTR_GET(rxDesc);
-+
-+ /*
-+ * Allocate a replacement skb.
-+ * We want to get another buffer ready for Rx ASAP.
-+ */
-+ newskb = (struct sk_buff *)ae531x_rxbuf_alloc(MACInfo, &rxBufp, &unused_length);
-+ if(newskb == NULL ) {
-+ /*
-+ * Give this descriptor back to the DMA engine,
-+ * and drop the received packet.
-+ */
-+ MAC_state->stats.rx_dropped++;
-+ AE531X_PRINT(AE531X_DEBUG_ERROR,
-+ ("Can't allocate new skb\n"));
-+ } else {
-+ AE531X_DESC_BUFPTR_SET(rxDesc, rxBufp);
-+ AE531X_DESC_SWPTR_SET(rxDesc, newskb);
-+ }
-+
-+ AE531X_DESC_STATUS_SET(rxDesc, DescOwnByDma);
-+ A_DATA_CACHE_FLUSH_INVAL(rxDesc, AE531X_DESC_SIZE);
-+ // rxDesc = NULL; /* sanity -- cannot use rxDesc now */
-+ sysWbFlush();
-+
-+ if (newskb == NULL) {
-+ retval = 1;
-+ goto rx_no_skbs;
-+ } else {
-+ /* Sync data cache w.r.t. DMA */
-+ // A_DATA_CACHE_INVAL(skb->data, length);
-+
-+#ifdef CONFIG_VENETDEV
-+ /* Determine which associated device owns this rx buffer */
-+ {
-+ int fromLAN;
-+
-+ fromLAN = phyDetermineSource(skb->data, length);
-+
-+ if (fromLAN == -1) {
-+ /*
-+ * Could not determine source, so drop the packet
-+ */
-+ dev_kfree_skb(skb);
-+ continue;
-+ }
-+
-+ length -= PHY_TRAILER_SIZE;
-+ if (fromLAN) {
-+ dev_sw_state = MAC_state->dev_sw_state[AE531X_LAN_PORT];
-+ } else {
-+ dev_sw_state = MAC_state->dev_sw_state[AE531X_WAN_PORT];
-+ }
-+ }
-+#endif
-+ rxdev = dev_sw_state->dev;
-+
-+ if (rxdev == NULL) {
-+ /*
-+ * We received a packet for a virtual enet device
-+ * that is no longer up. Ignore it.
-+ */
-+ dev_kfree_skb(skb);
-+ continue;
-+ }
-+
-+ /* Advance data pointer to show that there's data here */
-+ skb_put(skb, length);
-+ skb->protocol = eth_type_trans(skb, rxdev);
-+ skb->dev = rxdev;
-+ rxdev->last_rx = jiffies;
-+ rxdev->quota--;
-+
-+ if (rx_limit-- < 0) {
-+ early_stop=1;
-+ /* We've done enough for now -- more later */
-+ AE531X_PRINT(AE531X_DEBUG_RX_STOP,
-+ ("Enet%d RX early stop. Quota=%d rxDescCount=%d budget=%d\n",
-+ MACInfo->unit, dev->quota, rxDescCount, *budget));
-+ }
-+ rx_received++;
-+
-+ /* Send the data up the stack */
-+ AE531X_PRINT(AE531X_DEBUG_RX,
-+ ("Send data up stack: skb=%p data=%p length=%d\n",
-+ (void *)skb, (void *)skb->data, length));
-+
-+ netif_receive_skb(skb);
-+
-+ MAC_state->stats.rx_packets++;
-+ MAC_state->stats.rx_bytes += length;
-+ }
-+ } else {
-+ /* Descriptor status indicates ERRORS */
-+ MAC_state->stats.rx_errors++;
-+
-+ if (cmdsts & (DescRxRunt | DescRxLateColl)) {
-+ AE531X_PRINT(AE531X_DEBUG_ERROR,
-+ ("Runt | RX Late Collision Error\n"));
-+ MAC_state->stats.collisions++;
-+ }
-+
-+ if (cmdsts & DescRxLengthError) {
-+ AE531X_PRINT(AE531X_DEBUG_ERROR,
-+ ("RX Length Error\n"));
-+ MAC_state->stats.rx_length_errors++;
-+ }
-+
-+ if (cmdsts & DescRxCrc) {
-+ AE531X_PRINT(AE531X_DEBUG_ERROR,
-+ ("RX CRC Error\n"));
-+ MAC_state->stats.rx_crc_errors++;
-+ }
-+
-+ if (cmdsts & DescRxDribbling) {
-+ AE531X_PRINT(AE531X_DEBUG_ERROR,
-+ ("Dribbling Error\n"));
-+ MAC_state->stats.rx_frame_errors++;
-+ }
-+
-+ AE531X_PRINT(AE531X_DEBUG_ERROR,
-+ ("Bad receive. rxDesc=%p cmdsts=0x%8.8x\n",
-+ (void *)rxDesc, cmdsts));
-+
-+ /* Give this one back */
-+ AE531X_DESC_STATUS_SET(rxDesc, DescOwnByDma);
-+ A_DATA_CACHE_FLUSH_INVAL(rxDesc, AE531X_DESC_SIZE);
-+ sysWbFlush();
-+ }
-+ }
-+ } while ((!early_stop) &&
-+ ae531x_ReadDmaReg(MACInfo, DmaStatus) & DmaIntRxCompleted);
-+
-+rx_all_done:
-+ AE531X_PRINT(AE531X_DEBUG_RX,
-+ ("rx done (%d)\n", rxDescCount));
-+ *budget -= rxDescCount;
-+
-+ if (!early_stop) {
-+ netif_rx_complete(dev);
-+
-+ ae531x_SetDmaReg(MACInfo, DmaIntrEnb,
-+ DmaIeRxCompleted | DmaIeRxNoBuffer);
-+ ae531x_WriteDmaReg(MACInfo, DmaRxPollDemand, 0);
-+ }
-+
-+ retval = early_stop;
-+
-+rx_no_skbs:
-+
-+#ifdef CONFIG_VENETDEV
-+ for (i=0; i<AE531X_DEV_PER_MAC; i++) {
-+ if ((MAC_state->dev_sw_state[i]->dev) &&
-+ (MAC_state->dev_sw_state[i]->unit_on_MAC !=
-+ MAC_state->primary_dev)) {
-+ netif_rx_complete(MAC_state->dev_sw_state[i]->dev);
-+ }
-+ }
-+#endif
-+
-+ LEAVE();
-+ return retval;
-+}
-+#endif
-+
-+#ifndef AR531X_NAPI
-+/*******************************************************************************
-+* ae531x_MAC_recv checks for received packets, and sends data
-+* up the stack.
-+*/
-+static void
-+ae531x_MAC_recv(struct net_device *dev)
-+{
-+ struct sk_buff *skb;
-+ struct sk_buff *newskb;
-+ char *rxBufp;
-+ int unused_length;
-+ VIRT_ADDR rxDesc;
-+ int length;
-+ ae531x_dev_sw_state_t *dev_sw_state;
-+ ae531x_MAC_state_t *MAC_state;
-+ ae531x_MAC_t *MACInfo;
-+ u32 cmdsts;
-+ int rx_limit;
-+ int rx_received;
-+ struct net_device *rxdev;
-+ int retval;
-+
-+ ARRIVE();
-+
-+ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
-+ MAC_state = dev_sw_state->MAC_state;
-+ MACInfo = &MAC_state->MACInfo;
-+ rx_limit = MAC_state->dev_sw_state[MAC_state->primary_dev]->dev->quota;
-+ rx_received = 0;
-+
-+ for(;;) {
-+ rxDesc = MACInfo->rxQueue.curDescAddr;
-+ cmdsts = AE531X_DESC_STATUS_GET(KSEG1ADDR(rxDesc));
-+
-+ AE531X_PRINT(AE531X_DEBUG_RX,
-+ ("examine rxDesc %p with cmdsts=0x%x\n",
-+ (void *)rxDesc, cmdsts));
-+
-+ if (cmdsts & DescOwnByDma) {
-+ /* There's nothing left to process in the RX ring */
-+ break;
-+ }
-+
-+ AE531X_CONSUME_DESC((&MACInfo->rxQueue));
-+
-+ // A_DATA_CACHE_INVAL(rxDesc, AE531X_DESC_SIZE);
-+
-+ /* Process a packet */
-+ length = AE531X_DESC_STATUS_RX_SIZE(cmdsts) - ETH_CRC_LEN;
-+ if ( (cmdsts & (DescRxFirst |DescRxLast | DescRxErrors)) ==
-+ (DescRxFirst | DescRxLast) ) {
-+ /* Descriptor status indicates "NO errors" */
-+ skb = AE531X_DESC_SWPTR_GET(rxDesc);
-+
-+ /*
-+ * Allocate a replacement skb.
-+ * We want to get another buffer ready for Rx ASAP.
-+ */
-+ newskb = (struct sk_buff *)ae531x_rxbuf_alloc(MACInfo,
-+ &rxBufp,
-+ &unused_length);
-+ if(newskb == NULL ) {
-+ /*
-+ * Give this descriptor back to the DMA engine,
-+ * and drop the received packet.
-+ */
-+ MAC_state->stats.rx_dropped++;
-+ AE531X_PRINT(AE531X_DEBUG_ERROR,
-+ ("Can't allocate new skb\n"));
-+ } else {
-+ AE531X_DESC_BUFPTR_SET(rxDesc, rxBufp);
-+ AE531X_DESC_SWPTR_SET(rxDesc, newskb);
-+ }
-+
-+ AE531X_DESC_STATUS_SET(rxDesc, DescOwnByDma);
-+ A_DATA_CACHE_FLUSH_INVAL(rxDesc, AE531X_DESC_SIZE);
-+ sysWbFlush();
-+
-+ if (newskb == NULL) {
-+ break;
-+ } else {
-+#ifdef CONFIG_VENETDEV
-+ /* Determine which associated device owns this rx buffer */
-+ {
-+ int fromLAN;
-+
-+ fromLAN = phyDetermineSource(skb->data, length);
-+
-+ if (fromLAN == -1) {
-+ /*
-+ * Could not determine source, so drop the packet
-+ */
-+ dev_kfree_skb(skb);
-+ continue;
-+ }
-+
-+ length -= PHY_TRAILER_SIZE;
-+ if (fromLAN) {
-+ dev_sw_state =
-+ MAC_state->dev_sw_state[AE531X_LAN_PORT];
-+ } else {
-+ dev_sw_state =
-+ MAC_state->dev_sw_state[AE531X_WAN_PORT];
-+ }
-+ }
-+#endif
-+ rxdev = dev_sw_state->dev;
-+
-+ if (rxdev == NULL) {
-+ /*
-+ * We received a packet for a virtual enet device
-+ * that is no longer up. Ignore it.
-+ */
-+ dev_kfree_skb(skb);
-+ continue;
-+ }
-+
-+ /* Advance data pointer to show that there's data here */
-+ skb_put(skb, length);
-+ skb->protocol = eth_type_trans(skb, rxdev);
-+ skb->dev = rxdev;
-+ rxdev->last_rx = jiffies;
-+ rxdev->quota--;
-+
-+ rx_received++;
-+
-+ /* Send the data up the stack */
-+ AE531X_PRINT(AE531X_DEBUG_RX,
-+ ("Send data up stack: skb=%p data=%p length=%d\n",
-+ (void *)skb, (void *)skb->data, length));
-+
-+ netif_rx(skb);
-+
-+ MAC_state->stats.rx_packets++;
-+ MAC_state->stats.rx_bytes += length;
-+ }
-+ } else {
-+ /* Descriptor status indicates ERRORS */
-+ MAC_state->stats.rx_errors++;
-+
-+ if (cmdsts & (DescRxRunt | DescRxLateColl)) {
-+ MAC_state->stats.collisions++;
-+ }
-+
-+ if (cmdsts & DescRxLengthError) {
-+ MAC_state->stats.rx_length_errors++;
-+ }
-+
-+ if (cmdsts & DescRxCrc) {
-+ MAC_state->stats.rx_crc_errors++;
-+ }
-+
-+ if (cmdsts & DescRxDribbling) {
-+ MAC_state->stats.rx_frame_errors++;
-+ }
-+
-+ AE531X_PRINT(AE531X_DEBUG_ERROR,
-+ ("Bad receive. rxDesc=%p cmdsts=0x%8.8x\n",
-+ (void *)rxDesc, cmdsts));
-+ }
-+ }
-+
-+ LEAVE();
-+ return;
-+}
-+#endif
-+
-+/*******************************************************************************
-+* ae531x_restart stops all ethernet devices associated with a physical MAC,
-+* then shuts down the MAC. Then it re-opens all devices that were in use.
-+* TBDXXX: needs testing!
-+*/
-+static void
-+ae531x_restart(void *data)
-+{
-+ ae531x_MAC_t *MACInfo = (ae531x_MAC_t *)data;
-+ ae531x_MAC_state_t *MAC_state = (ae531x_MAC_state_t *)MACInfo->OSinfo;
-+ struct net_device *saved_dev[AE531X_DEV_PER_MAC];
-+ int i;
-+
-+ for (i=0; i<AE531X_DEV_PER_MAC; i++) {
-+ if ((saved_dev[i] = MAC_state->dev_sw_state[i]->dev) != NULL) {
-+ ae531x_MAC_stop(saved_dev[i]);
-+ }
-+ }
-+
-+ for (i=0; i<AE531X_DEV_PER_MAC; i++) {
-+ if (saved_dev[i])
-+ ae531x_MAC_open(saved_dev[i]);
-+ }
-+}
-+
-+/*******************************************************************************
-+* ae531x_MAC_intr handle interrupts from an ethernet MAC.
-+* It checks MAC status registers, and dispatches as appropriate.
-+*/
-+void
-+ae531x_MAC_intr(int cpl, void *dev_id, struct pt_regs *regs)
-+{
-+ ae531x_MAC_state_t *MAC_state;
-+ ae531x_MAC_t *MACInfo;
-+ u32 regIsr;
-+ u32 regImr;
-+ u32 pendIntrs;
-+ struct net_device * primary_dev;
-+
-+ ARRIVE();
-+
-+ MACInfo = (ae531x_MAC_t *)dev_id;
-+ MAC_state = (ae531x_MAC_state_t *)MACInfo->OSinfo;
-+ primary_dev = MAC_state->dev_sw_state[MAC_state->primary_dev]->dev;
-+
-+ for(;;) {
-+ /* Clear any unhandled intr causes. */
-+ ae531x_WriteDmaReg(MACInfo, DmaStatus, UnhandledIntrMask);
-+
-+ regIsr = ae531x_ReadDmaReg(MACInfo, DmaStatus);
-+
-+ regImr = ae531x_ReadDmaReg(MACInfo, DmaIntrEnb);
-+ pendIntrs = regIsr & regImr;
-+
-+ AE531X_PRINT(AE531X_DEBUG_INT,
-+ ("ethmac%d: intIsr=0x%8.8x intImr=0x%8.8x\n",
-+ MACInfo->unit, regIsr, regImr));
-+
-+ if ((pendIntrs & DmaAllIntCauseMask) == 0)
-+ break;
-+
-+ if ((pendIntrs & DmaIntRxCompleted) ||
-+ (pendIntrs & DmaIntRxNoBuffer)) {
-+#ifdef AR531X_NAPI
-+ if (netif_rx_schedule_prep(primary_dev)) {
-+ ae531x_ClearDmaReg(MACInfo,
-+ DmaIntrEnb,
-+ DmaIeRxCompleted | DmaIeRxNoBuffer);
-+ ae531x_AckIntr(MACInfo,
-+ DmaIntRxCompleted | DmaIntRxNoBuffer);
-+ (void)ae531x_ReadDmaReg(MACInfo, DmaIntrEnb);
-+ __netif_rx_schedule(primary_dev);
-+ } else {
-+ AE531X_PRINT(AE531X_DEBUG_ERROR,
-+ ("%s: Interrupt (0x%8.8x/0x%8.8x) while in poll. regs@%p, pc=%p, ra=%p\n",
-+ __FILE__,
-+ regIsr,
-+ ae531x_ReadDmaReg(MACInfo, DmaIntrEnb),
-+ (void *)regs,
-+ (void *)regs->cp0_epc,
-+ (void *)regs->regs[31]));
-+ ae531x_ClearDmaReg(MACInfo,
-+ DmaIntrEnb,
-+ DmaIeRxCompleted | DmaIeRxNoBuffer);
-+ ae531x_AckIntr(MACInfo,
-+ DmaIntRxCompleted | DmaIntRxNoBuffer);
-+ }
-+#else
-+ ae531x_MAC_recv(primary_dev);
-+ ae531x_AckIntr(MACInfo,
-+ DmaIntRxCompleted | DmaIntRxNoBuffer);
-+#endif
-+ }
-+
-+ if (pendIntrs &
-+ (DmaIntTxStopped | DmaIntTxJabber | DmaIntTxUnderflow)) {
-+ AE531X_PRINT(AE531X_DEBUG_ERROR,
-+ ("ethmac%d: TX Error Intr (0x%x)\n",
-+ MACInfo->unit, pendIntrs));
-+ ae531x_AckIntr(MACInfo,
-+ (DmaIntTxStopped | DmaIntTxJabber | DmaIntTxUnderflow));
-+ }
-+
-+ if (pendIntrs & DmaIntBusError) {
-+ AE531X_PRINT(AE531X_DEBUG_ERROR,
-+ ("ethmac%d: DMA Bus Error Intr (0x%x)\n",
-+ MACInfo->unit, pendIntrs));
-+ ae531x_AckIntr(MACInfo, DmaIntBusError);
-+ /* Reset the chip, if it's not already being done */
-+ if (ae531x_IsInResetMode(MACInfo)) {
-+ goto intr_done;
-+ }
-+ ae531x_BeginResetMode(MACInfo);
-+ schedule_task(&MAC_state->restart_task);
-+ }
-+
-+ if (pendIntrs & DmaIntRxStopped) {
-+ AE531X_PRINT(AE531X_DEBUG_ERROR,
-+ ("ethmac%d: RX Stopped Intr (0x%x)\n",
-+ MACInfo->unit, pendIntrs));
-+ ae531x_AckIntr(MACInfo, DmaIntRxStopped);
-+ }
-+ }
-+
-+ ae531x_DmaIntEnable(MACInfo);
-+
-+intr_done:
-+ LEAVE();
-+}
-+
-+/*******************************************************************************
-+* ae531x_MAC_get_stats returns statistics for a specified device
-+*/
-+static struct net_device_stats*
-+ae531x_MAC_get_stats(struct net_device *dev)
-+{
-+ ae531x_dev_sw_state_t *dev_sw_state;
-+ ae531x_MAC_state_t *MAC_state;
-+
-+ ARRIVE();
-+ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
-+ MAC_state = dev_sw_state->MAC_state;
-+
-+ LEAVE();
-+ return &MAC_state->stats;
-+}
-+
-+#define AE531X_PHY_POLL_SECONDS 2
-+
-+/*******************************************************************************
-+* ae531x_phy_poll periodically checks for changes in phy status
-+* (e.g. dropped link).
-+*/
-+static int
-+ae531x_phy_poll(void *data)
-+{
-+ ae531x_dev_sw_state_t *dev_sw_state = (ae531x_dev_sw_state_t *)data;
-+ ae531x_MAC_t *MACInfo = &dev_sw_state->MAC_state->MACInfo;
-+ int unit = dev_sw_state->enetUnit;
-+
-+#if defined(CONFIG_VENETDEV) && defined(DEBUG_VENETDEV)
-+ int previous_cloned = 0;
-+ int previous_expand = 0;
-+ int previous_both = 0;
-+#endif
-+
-+ daemonize();
-+ reparent_to_init();
-+ spin_lock_irq(&current->sigmask_lock);
-+ sigemptyset(&current->blocked);
-+ recalc_sigpending(current);
-+ spin_unlock_irq(&current->sigmask_lock);
-+
-+ snprintf(current->comm, sizeof(current->comm), "%s",
-+ dev_sw_state->dev->name);
-+
-+ for(;;) {
-+ if (MACInfo->port_is_up) {
-+ phyCheckStatusChange(unit);
-+ }
-+
-+#if defined(CONFIG_VENETDEV) && defined(DEBUG_VENETDEV)
-+ if (cloned_counter != previous_cloned) {
-+ printk("Cloned Counter: %d (delta %d)\n",
-+ cloned_counter, cloned_counter - previous_cloned);
-+ previous_cloned = cloned_counter;
-+ }
-+ if (expand_counter != previous_expand) {
-+ printk("Expand Counter: %d (delta %d)\n",
-+ expand_counter, expand_counter - previous_expand);
-+ previous_expand = expand_counter;
-+ }
-+ if (both_counter != previous_both) {
-+ printk("Expand & Cloned Counter: %d (delta %d)\n",
-+ both_counter, both_counter - previous_both);
-+ previous_both = both_counter;
-+ }
-+#endif
-+
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(AE531X_PHY_POLL_SECONDS * HZ);
-+ }
-+
-+ return 0;
-+}
-+
-+
-+/*******************************************************************************
-+* ae531x_MAC_set_rx_mode is used to set the RX mode options, such as
-+* promiscuous or multicast.
-+*/
-+static void
-+ae531x_MAC_set_rx_mode(struct net_device *dev)
-+{
-+ ae531x_dev_sw_state_t *dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
-+ ae531x_MAC_state_t *MAC_state=dev_sw_state->MAC_state;
-+ ae531x_MAC_t *MACInfo = &MAC_state->MACInfo;
-+
-+ if (dev->flags & IFF_PROMISC) {
-+ ae531x_SetMacReg(MACInfo, MacControl, MacPromiscuousModeOn);
-+ } else {
-+ ae531x_ClearMacReg(MACInfo, MacControl, MacPromiscuousModeOn);
-+ }
-+
-+ if (dev->flags & IFF_MULTICAST) {
-+ ae531x_SetMacReg(MACInfo, MacControl, MacMulticastFilterOff);
-+ } else {
-+ ae531x_ClearMacReg(MACInfo, MacControl, MacMulticastFilterOff);
-+ }
-+}
-+
-+/*******************************************************************************
-+* ae531x_MAC_open is the standard Linux open function. It puts
-+* hardware into a known good state, allocates queues, starts
-+* the phy polling task, and arranges for interrupts to be handled.
-+*/
-+static int
-+ae531x_MAC_open(struct net_device *dev)
-+{
-+ ae531x_dev_sw_state_t *dev_sw_state;
-+ ae531x_MAC_state_t *MAC_state;
-+ ae531x_MAC_t *MACInfo;
-+ int rv;
-+ struct tq_struct *restart_task;
-+ pid_t phy_poll_pid;
-+
-+ ARRIVE();
-+
-+ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
-+ dev_sw_state->dev = dev;
-+ MAC_state = dev_sw_state->MAC_state;
-+ MACInfo = &MAC_state->MACInfo;
-+
-+ restart_task = &MAC_state->restart_task;
-+ restart_task->routine = ae531x_restart;
-+ restart_task->data = (void *)MACInfo;
-+
-+ AE531X_PRINT(AE531X_DEBUG_RESET,
-+ ("ae531x_MAC_open eth%d ethmac%d macBase=0x%x dmaBase=0x%x irq=0x%x\n",
-+ dev_sw_state->enetUnit,
-+ MACInfo->unit,
-+ MACInfo->macBase,
-+ MACInfo->dmaBase,
-+ MAC_state->irq));
-+
-+ if (!MACInfo->port_is_up) {
-+ /* Bring MAC and PHY out of reset */
-+ ae531x_reset(MACInfo);
-+
-+ /* Attach interrupt handler */
-+ rv = request_irq(MAC_state->irq, ae531x_MAC_intr, SA_INTERRUPT,
-+ "ae531x_MAC_intr", (void *)MACInfo);
-+ if (rv < 0) {
-+ AE531X_PRINT(AE531X_DEBUG_ERROR,
-+ ("request_irq(0x%x) failed (%d)\n",
-+ MAC_state->irq, rv));
-+ goto open_failure;
-+ }
-+
-+ /* Initialize PHY */
-+ phySetup(MACInfo->unit, MACInfo->phyBase);
-+
-+ /* Start thread to poll for phy link status changes */
-+ phy_poll_pid = kernel_thread(ae531x_phy_poll,
-+ dev_sw_state,
-+ CLONE_FS | CLONE_FILES);
-+ if (phy_poll_pid < 0) {
-+ AE531X_PRINT(AE531X_DEBUG_ERROR,
-+ ("ethmac%d unable to start Phy Poll thread\n",
-+ MACInfo->unit));
-+ }
-+
-+ /* Allocate RX/TX Queues */
-+ if (ae531x_AllocateQueues(MACInfo) < 0) {
-+ AE531X_PRINT(AE531X_DEBUG_RESET, ("Queue allocation failed"));
-+ free_irq(MAC_state->irq, (void *)MACInfo);
-+ goto open_failure;
-+ }
-+
-+ /* Initialize DMA and descriptors */
-+ ae531x_DmaReset(MACInfo);
-+
-+ /* Initialize MAC */
-+ ae531x_MACReset(MACInfo);
-+
-+ /* Set RX mode */
-+ ae531x_MAC_set_rx_mode(dev);
-+
-+ /* Enable Receive/Transmit */
-+ ae531x_EnableComm(MACInfo);
-+
-+ MAC_state->primary_dev = dev_sw_state->unit_on_MAC;
-+ MACInfo->port_is_up = TRUE;
-+ }
-+
-+ dev->trans_start = jiffies;
-+
-+ LEAVE();
-+ return 0;
-+
-+open_failure:
-+ LEAVE();
-+ return -1;
-+}
-+
-+/*
-+ * Shut down MAC hardware.
-+ */
-+static void
-+ae531x_MAC_shutdown(ae531x_MAC_state_t *MAC_state)
-+{
-+ ae531x_MAC_t *MACInfo;
-+
-+ MACInfo = &MAC_state->MACInfo;
-+ MACInfo->port_is_up = FALSE;
-+
-+ /* Disable Receive/Transmit */
-+ ae531x_DisableComm(MACInfo);
-+
-+ /* Disable Interrupts */
-+ ae531x_DmaIntDisable(MACInfo);
-+ sysWbFlush();
-+ free_irq(MAC_state->irq, (void *)MACInfo);
-+
-+ /* Free Transmit & Receive skb's/descriptors */
-+ ae531x_TxReap(MAC_state); /* one last time */
-+ ae531x_FreeQueues(MACInfo);
-+}
-+
-+/*******************************************************************************
-+* ae531x_MAC_stop is the standard Linux stop function. It undoes
-+* everything set up by ae531x_MAC_open.
-+*/
-+static int
-+ae531x_MAC_stop(struct net_device *dev)
-+{
-+ ae531x_dev_sw_state_t *dev_sw_state;
-+ ae531x_MAC_state_t *MAC_state;
-+ ae531x_MAC_t *MACInfo;
-+ int i;
-+
-+ ARRIVE();
-+
-+ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
-+ MAC_state = dev_sw_state->MAC_state;
-+ MACInfo = &MAC_state->MACInfo;
-+
-+ for (i=0; i<AE531X_DEV_PER_MAC; i++) {
-+ if ((MAC_state->dev_sw_state[i]->dev) &&
-+ (MAC_state->dev_sw_state[i]->dev != dev_sw_state->dev)) {
-+ break;
-+ }
-+ }
-+
-+ if (i < AE531X_DEV_PER_MAC) {
-+ /* Physical MAC is still in use */
-+ if (MAC_state->primary_dev == dev_sw_state->unit_on_MAC) {
-+ /*
-+ * If the primary_dev is being stopped
-+ * then we need to assign a new one.
-+ */
-+ MAC_state->primary_dev = i;
-+ }
-+ } else {
-+ /* Physical MAC is no longer in use */
-+ ae531x_MAC_shutdown(MAC_state);
-+ }
-+
-+ dev_sw_state->dev = NULL;
-+
-+ LEAVE();
-+ return 0;
-+}
-+
-+/*******************************************************************************
-+* ae531x_rxbuf_alloc - Allocate an skb to be associated with an RX descriptor.
-+*
-+* RETURNS: A pointer to the skb. Also returns a pointer to the underlying
-+* buffer and the size of that buffer.
-+*/
-+void *
-+ae531x_rxbuf_alloc(ae531x_MAC_t *MACInfo, char **rxBuffp, int *rxBuffSizep)
-+{
-+ struct sk_buff *skb;
-+ char *rxBuff;
-+ int rxBuffSize;
-+
-+ skb = dev_alloc_skb(AE531X_RX_BUF_SIZE);
-+ if (skb) {
-+ /* Add 2 to align the IP header on a DWORD boundary */
-+ skb_reserve(skb, RXBUFF_RESERVE + 2);
-+
-+ rxBuffSize = skb_tailroom(skb);
-+ rxBuff = skb->tail;
-+
-+ *rxBuffp = rxBuff;
-+ *rxBuffSizep = rxBuffSize;
-+
-+ A_DATA_CACHE_INVAL(rxBuff, rxBuffSize);
-+ }
-+
-+ return skb;
-+}
-+
-+/*******************************************************************************
-+* ae531x_swptr_free - Free the skb, if any, associated with a descriptor.
-+*/
-+void
-+ae531x_swptr_free(VIRT_ADDR desc)
-+{
-+ struct sk_buff *skb;
-+
-+ skb = (struct sk_buff *)AE531X_DESC_SWPTR_GET(desc);
-+ if (skb) {
-+ AE531X_DESC_SWPTR_SET(desc, NULL);
-+ kfree_skb(skb);
-+ }
-+}
-+
-+/*******************************************************************************
-+*
-+* ae531x_TxReap - the driver Tx completion routine.
-+*
-+* This routine reaps sk_buffs which have already been transmitted.
-+*
-+*/
-+static void
-+ae531x_TxReap(ae531x_MAC_state_t *MAC_state)
-+{
-+ AE531X_QUEUE *txq;
-+ VIRT_ADDR txDesc;
-+ UINT32 cmdsts;
-+ struct sk_buff *skb;
-+ int reaped;
-+ ae531x_MAC_t *MACInfo;
-+ static int aeUselessReap = 0;
-+
-+ ARRIVE();
-+
-+ MACInfo = &MAC_state->MACInfo;
-+ txq = &MACInfo->txQueue;
-+ reaped = 0;
-+
-+ while (1) {
-+ txDesc = AE531X_QUEUE_ELE_NEXT_GET(txq, txq->reapDescAddr);
-+ if (txDesc == txq->curDescAddr) {
-+ break;
-+ }
-+
-+ cmdsts = AE531X_DESC_STATUS_GET(KSEG1ADDR(txDesc));
-+ if (cmdsts & DescOwnByDma) {
-+ break;
-+ }
-+
-+ /* Release sk_buff associated with completed transmit */
-+ skb = (struct sk_buff *)AE531X_DESC_SWPTR_GET(txDesc);
-+
-+ if (skb) {
-+ kfree_skb(skb);
-+ AE531X_DESC_SWPTR_SET(txDesc, NULL);
-+ }
-+
-+ /* Update statistics according to completed transmit desc */
-+ if (cmdsts & DescTxErrors) {
-+ AE531X_PRINT(AE531X_DEBUG_ERROR,
-+ ("enetmac%d Tx prior error: 0x%8.8x <0x%8.8x> 0x%8.8x\n",
-+ MACInfo->unit,
-+ cmdsts,
-+ DescTxErrors,
-+ (int)txDesc));
-+ MAC_state->stats.tx_errors++;
-+ if (cmdsts & (DescTxLateCollision | DescTxExcCollisions)) {
-+ MAC_state->stats.tx_aborted_errors++;
-+ }
-+ if (cmdsts & (DescTxLostCarrier | DescTxNoCarrier)) {
-+ MAC_state->stats.tx_carrier_errors++;
-+ }
-+ } else {
-+ MAC_state->stats.tx_bytes += AE531X_DESC_STATUS_RX_SIZE(cmdsts);
-+ MAC_state->stats.tx_packets++;
-+ }
-+
-+ MAC_state->stats.collisions +=
-+ ((cmdsts & DescTxCollMask) >> DescTxCollShift);
-+
-+ txq->reapDescAddr = txDesc;
-+ reaped++;
-+ }
-+
-+ if (reaped > 0) {
-+ int i;
-+
-+ AE531X_PRINT(AE531X_DEBUG_TX_REAP,
-+ ("reaped %d\n", reaped));
-+
-+ /*
-+ * Re-start transmit queues for all ethernet devices
-+ * associated with this MAC.
-+ */
-+ for (i=0; i<AE531X_DEV_PER_MAC; i++) {
-+ if (MAC_state->dev_sw_state[i]->dev)
-+ netif_start_queue(MAC_state->dev_sw_state[i]->dev);
-+ }
-+ } else {
-+ aeUselessReap++;
-+ }
-+
-+ LEAVE();
-+}
-+
-+/*******************************************************************************
-+* ae531x_MAC_start_xmit sends a packet.
-+*/
-+static int
-+ae531x_MAC_start_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+ ae531x_dev_sw_state_t *dev_sw_state;
-+ ae531x_MAC_state_t *MAC_state;
-+ ae531x_MAC_t *MACInfo;
-+ u32 buf;
-+ u32 ctrlen;
-+ u32 length;
-+ int mtu;
-+ int max_buf_size;
-+ VIRT_ADDR txDesc;
-+
-+ ARRIVE();
-+
-+ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
-+ MAC_state = dev_sw_state->MAC_state;
-+ MACInfo = &MAC_state->MACInfo;
-+
-+ length = skb->len;
-+
-+ /* Check if this port is up, else toss packet */
-+ if (!MACInfo->port_is_up) {
-+ buf = virt_to_bus(skb->data);
-+ AE531X_PRINT(AE531X_DEBUG_ERROR,
-+ ("eth%d Tx Down, dropping buf=0x%8.8x, length=0x%8.8x, skb=%p\n",
-+ dev_sw_state->enetUnit, buf, length, (void *)skb));
-+
-+ MAC_state->stats.tx_dropped++;
-+ MAC_state->stats.tx_carrier_errors++;
-+ goto dropFrame;
-+ }
-+
-+ if (ae531x_IsInResetMode(MACInfo)) {
-+ AE531X_PRINT(AE531X_DEBUG_ERROR,
-+ ("eth%d Tx: In Chip reset - drop frame\n",
-+ dev_sw_state->enetUnit));
-+
-+ MAC_state->stats.tx_dropped++;
-+ MAC_state->stats.tx_aborted_errors++;
-+ goto dropFrame;
-+ }
-+
-+ /* Check if we can transport this packet */
-+ length = max((u32)60, length); /* total length */
-+ mtu = dev->mtu;
-+ max_buf_size = mtu + HLEN;
-+ if (length > max_buf_size) {
-+ AE531X_PRINT(AE531X_DEBUG_ERROR,
-+ ("eth%d Tx: length %d too long. mtu=%d, trailer=%d\n",
-+ dev_sw_state->enetUnit, length, mtu, PHY_TRAILER_SIZE));
-+
-+ MAC_state->stats.tx_errors++;
-+ MAC_state->stats.tx_aborted_errors++;
-+
-+ goto dropFrame;
-+ }
-+
-+ /* Reap any old, completed Tx descriptors */
-+ ae531x_TxReap(MAC_state);
-+
-+ txDesc = MACInfo->txQueue.curDescAddr;
-+ if (txDesc == MACInfo->txQueue.reapDescAddr) {
-+ int i;
-+
-+ AE531X_PRINT(AE531X_DEBUG_ERROR,
-+ ("eth%d Tx: cannot get txDesc\n",
-+ dev_sw_state->enetUnit));
-+
-+ MAC_state->stats.tx_dropped++;
-+ MAC_state->stats.tx_fifo_errors++;
-+
-+ /*
-+ * Stop transmit queues for any ethernet devices
-+ * associated with this MAC.
-+ */
-+ for (i=0; i<AE531X_DEV_PER_MAC; i++) {
-+ if (MAC_state->dev_sw_state[i]->dev)
-+ netif_stop_queue(MAC_state->dev_sw_state[i]->dev);
-+ }
-+ goto dropFrame;
-+ }
-+
-+#ifdef CONFIG_VENETDEV
-+ {
-+ struct sk_buff *newskb;
-+
-+ if (skb_cloned(skb) || (skb_tailroom(skb) < PHY_TRAILER_SIZE)) {
-+#ifdef DEBUG_VENETDEV
-+ if (skb_cloned(skb)) {
-+ cloned_counter++;
-+ if (skb_tailroom(skb) < PHY_TRAILER_SIZE) {
-+ both_counter++;
-+ }
-+ } else {
-+ expand_counter++;
-+ }
-+#endif
-+ newskb = skb_copy_expand(skb, 0, PHY_TRAILER_SIZE, GFP_ATOMIC);
-+ if (newskb == NULL) {
-+ goto dropFrame;
-+ }
-+
-+ dev_kfree_skb(skb);
-+ skb = newskb;
-+ }
-+
-+ phySetDestinationPort(skb->data, length, dev_sw_state->isLAN);
-+ skb_put(skb, PHY_TRAILER_SIZE);
-+ length += PHY_TRAILER_SIZE;
-+ }
-+#endif
-+
-+ /* We won't fail now; so consume this descriptor */
-+ AE531X_CONSUME_DESC((&MACInfo->txQueue));
-+
-+ /* Update the descriptor */
-+ buf = virt_to_bus(skb->data);
-+ A_DATA_CACHE_FLUSH(skb->data, skb->len);
-+ AE531X_DESC_BUFPTR_SET(txDesc, buf);
-+ AE531X_DESC_SWPTR_SET(txDesc, skb);
-+ ctrlen = AE531X_DESC_CTRLEN_GET(txDesc);
-+ ctrlen = (ctrlen & (DescEndOfRing)) |
-+ DescTxFirst |
-+ DescTxLast |
-+ DescTxIntEnable;
-+
-+ ctrlen |= ((length << DescSize1Shift) & DescSize1Mask);
-+
-+ AE531X_DESC_CTRLEN_SET(txDesc, ctrlen);
-+ AE531X_DESC_STATUS_SET(txDesc, DescOwnByDma);
-+
-+ AE531X_PRINT(AE531X_DEBUG_TX,
-+ ("eth%d Tx: Desc=0x%8.8x, L=0x%8.8x, D=0x%8.8x, d=0x%8.8x, length=0x%8.8x\n",
-+ dev_sw_state->enetUnit,
-+ (UINT32)txDesc,
-+ AE531X_DESC_CTRLEN_GET(txDesc),
-+ buf,
-+ AE531X_DESC_LNKBUF_GET(txDesc),
-+ length));
-+
-+ /* Must not use txDesc after this point */
-+ A_DATA_CACHE_FLUSH_INVAL(txDesc, AE531X_DESC_SIZE);
-+
-+ /* Alert DMA engine to resume Tx */
-+ ae531x_WriteDmaReg(MACInfo, DmaTxPollDemand, 0);
-+ sysWbFlush();
-+
-+ MAC_state->stats.tx_packets++;
-+ MAC_state->stats.tx_bytes += length;
-+
-+ /* Tell upper layers to keep it coming */
-+ dev->trans_start = jiffies;
-+
-+ LEAVE();
-+ return 0;
-+
-+dropFrame:
-+ dev_kfree_skb(skb);
-+
-+ LEAVE();
-+ return 0;
-+}
-+
-+
-+/*******************************************************************************
-+* ae531x_MAC_tx_timeout handles transmit timeouts
-+*/
-+static void
-+ae531x_MAC_tx_timeout(struct net_device *dev)
-+{
-+ ae531x_dev_sw_state_t *dev_sw_state;
-+ ae531x_MAC_state_t *MAC_state;
-+ ae531x_MAC_t *MACInfo;
-+
-+ ARRIVE();
-+
-+ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
-+ MAC_state = dev_sw_state->MAC_state;
-+ MACInfo = &MAC_state->MACInfo;
-+
-+ AE531X_PRINT(AE531X_DEBUG_ERROR,
-+ ("enet%d: Tx timeout\n", dev_sw_state->enetUnit));
-+
-+ ae531x_restart(MACInfo);
-+
-+ LEAVE();
-+}
-+
-+
-+/*******************************************************************************
-+* ae531x_MAC_do_ioctl is a placeholder for future ioctls.
-+*/
-+static int
-+ae531x_MAC_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-+{
-+ int rv;
-+ ae531x_MAC_t *MACInfo;
-+ struct ioctl_data {
-+ u32 unit;
-+ u32 addr;
-+ u32 data;
-+ } *req;
-+ ae531x_dev_sw_state_t *dev_sw_state;
-+ ae531x_MAC_state_t *MAC_state;
-+
-+ ARRIVE();
-+
-+ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
-+ MAC_state = dev_sw_state->MAC_state;
-+ MACInfo = &MAC_state->MACInfo;
-+
-+ req = (struct ioctl_data *)ifr->ifr_data;
-+
-+ switch( cmd ) {
-+ default:
-+ AE531X_PRINT(AE531X_DEBUG_ERROR,
-+ ("Unsupported ioctl: 0x%x\n", cmd));
-+ rv = -EOPNOTSUPP;
-+ }
-+
-+ LEAVE();
-+ return rv;
-+}
-+
-+/*******************************************************************************
-+* ae531x_MAC_set_mac_address sets a new hardware address for the device
-+*/
-+static int
-+ae531x_MAC_set_mac_address(struct net_device *dev, void *addr)
-+{
-+ struct sockaddr *saddr = (struct sockaddr *)addr;
-+
-+ /* update dev struct */
-+ memcpy(dev->dev_addr, &saddr->sa_data[0], dev->addr_len);
-+
-+ return 0;
-+}
-+
-+/******************************************************************************
-+* macAddrGet - Given a MACInfo pointer, return a pointer to an
-+* array of chars that holds the corresponding MAC address.
-+*/
-+char *macAddrGet(ae531x_MAC_t *MACInfo)
-+{
-+ // return enet_mac_address_get(MACInfo->unit);
-+ return ae531x_MAC_dev[MACInfo->unit]->dev_addr;
-+}
-+
-+static void
-+ae531x_MAC_setup_fntable(struct net_device *dev)
-+{
-+ /* Set a default (should be overridden by software) */
-+ u8 default_MAC_address[] = { 0x00, 0x03, 0x7f, 0xe0, 0x02, 0xbF };
-+
-+ ARRIVE();
-+
-+ dev->get_stats = ae531x_MAC_get_stats;
-+ dev->open = ae531x_MAC_open;
-+ dev->stop = ae531x_MAC_stop;
-+ dev->hard_start_xmit = ae531x_MAC_start_xmit;
-+ dev->do_ioctl = ae531x_MAC_do_ioctl;
-+#ifdef AR531X_NAPI
-+ dev->poll = ae531x_MAC_poll;
-+ dev->weight = 16;
-+#endif
-+ dev->tx_timeout = ae531x_MAC_tx_timeout;
-+ dev->features = NETIF_F_HW_CSUM |\
-+ NETIF_F_HIGHDMA;
-+ dev->set_mac_address = ae531x_MAC_set_mac_address;
-+ dev->set_multicast_list = ae531x_MAC_set_rx_mode;
-+
-+ /* Copy default MAC address into device descriptor */
-+ memcpy(dev->dev_addr, default_MAC_address, dev->addr_len );
-+
-+ LEAVE();
-+}
-+
-+/*
-+ * ae531x_twisted_enet() returns 1 for chips where there is only one usable
-+ * MAC, and that MAC is 1.
-+ */
-+static BOOL
-+ae531x_twisted_enet(void)
-+{
-+ int wisoc_revision;
-+ int flash_bus_width;
-+
-+ wisoc_revision = (sysRegRead(AR531X_REV) & AR531X_REV_MAJ) >>
-+ AR531X_REV_MAJ_S;
-+ if (wisoc_revision == AR531X_REV_MAJ_AR2313)
-+ return TRUE;
-+
-+ flash_bus_width = sysRegRead(AR531X_FLASHCTL0) & FLASHCTL_MWx16;
-+
-+ if (flash_bus_width == 0) {
-+ printk("Found AR2312-01\n");
-+ return TRUE; /* AR2312-01 has 8 bit flash bus */
-+ } else {
-+ printk("Found AR2312-00\n");
-+ return FALSE;
-+ }
-+}
-+
-+int
-+ae531x_MAC_setup(void)
-+{
-+ int i;
-+ int next_dev;
-+ int rev;
-+ struct net_device *dev;
-+ ae531x_dev_sw_state_t *dev_sw_state;
-+ ae531x_MAC_state_t *MAC_state;
-+ ae531x_MAC_t *MACInfo;
-+
-+ ARRIVE();
-+
-+#if 0
-+ /*
-+ * This does not work since the AR2312 and AR5312 both have the same
-+ * revision information in the CPU :-(
-+ */
-+ rev = (sysRegRead(AR531X_REV) & AR531X_REV_CHIP);
-+
-+ if ((rev & AR531X_REV_MIN) == AR5312_REV_MIN_SINGLE_ENET) {
-+ ar531x_num_enet_macs = 1;
-+ } else {
-+ ar531x_num_enet_macs = 2;
-+ }
-+#else
-+ /*
-+ * Need to select the number of ethernet MACs based on the config
-+ * information (sadly)
-+ */
-+#ifdef CONFIG_AR5312
-+ ar531x_num_enet_macs = 2;
-+#else
-+ ar531x_num_enet_macs = 1;
-+#endif
-+#endif
-+
-+ next_dev = 0;
-+ for (i=0; i<ar531x_num_enet_macs; i++) {
-+
-+ dev = ae531x_MAC_dev[next_dev] =
-+ init_etherdev(NULL, sizeof(ae531x_dev_sw_state_t));
-+
-+ if (dev == NULL) {
-+ LEAVE();
-+ return -1;
-+ }
-+
-+ ae531x_MAC_setup_fntable(dev);
-+
-+ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
-+ dev_sw_state->enetUnit = next_dev;
-+ dev_sw_state->unit_on_MAC = 0;
-+ MAC_state = &per_MAC_info[i];
-+ dev_sw_state->MAC_state = MAC_state;
-+ MAC_state->dev_sw_state[AE531X_LAN_PORT] = dev_sw_state;
-+ MAC_state->primary_dev = -1;
-+
-+ next_dev++;
-+
-+#ifdef CONFIG_VENETDEV
-+ {
-+ ae531x_dev_sw_state_t *lan_dev_sw_state;
-+
-+ lan_dev_sw_state = dev_sw_state;
-+
-+ dev = ae531x_MAC_dev[next_dev] =
-+ init_etherdev(NULL, sizeof(ae531x_dev_sw_state_t));
-+
-+ if (dev == NULL) {
-+ LEAVE();
-+ return -1;
-+ }
-+
-+ ae531x_MAC_setup_fntable(dev);
-+
-+ dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
-+ dev_sw_state->enetUnit = next_dev;
-+ dev_sw_state->unit_on_MAC = 1;
-+ dev_sw_state->MAC_state = MAC_state;
-+ MAC_state->dev_sw_state[AE531X_WAN_PORT] = dev_sw_state;
-+ lan_dev_sw_state->isLAN = TRUE; /* enet0 is LAN */
-+ dev_sw_state->isLAN = FALSE ; /* enet1 is WAN */
-+
-+ next_dev++;
-+ }
-+#endif
-+
-+ /* Initialize per-MAC information */
-+ MACInfo = &MAC_state->MACInfo;
-+ MACInfo->unit = i;
-+
-+ if (ar531x_num_enet_macs == 1) {
-+ if (ae531x_twisted_enet()) {
-+ MACInfo->macBase =
-+ (u32)(PHYS_TO_K1(AR531X_ENET1)+AE531X_MAC_OFFSET);
-+ MACInfo->dmaBase =
-+ (u32)(PHYS_TO_K1(AR531X_ENET1)+AE531X_DMA_OFFSET);
-+ MACInfo->phyBase =
-+ (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET);
-+ MAC_state->irq = AR531X_IRQ_ENET1_INTRS;
-+ } else {
-+ MACInfo->macBase =
-+ (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_MAC_OFFSET);
-+ MACInfo->dmaBase =
-+ (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_DMA_OFFSET);
-+ MACInfo->phyBase =
-+ (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET);
-+ MAC_state->irq = AR531X_IRQ_ENET0_INTRS;
-+ }
-+ } else {
-+ if (MACInfo->unit == 0) {
-+ MACInfo->macBase =
-+ (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_MAC_OFFSET);
-+ MACInfo->dmaBase =
-+ (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_DMA_OFFSET);
-+ MACInfo->phyBase =
-+ (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET);
-+ MAC_state->irq = AR531X_IRQ_ENET0_INTRS;
-+ } else {
-+ MACInfo->macBase =
-+ (u32)(PHYS_TO_K1(AR531X_ENET1)+AE531X_MAC_OFFSET);
-+ MACInfo->dmaBase =
-+ (u32)(PHYS_TO_K1(AR531X_ENET1)+AE531X_DMA_OFFSET);
-+ MACInfo->phyBase =
-+ (u32)(PHYS_TO_K1(AR531X_ENET1)+AE531X_PHY_OFFSET);
-+ MAC_state->irq = AR531X_IRQ_ENET1_INTRS;
-+ }
-+ }
-+ MACInfo->OSinfo = (void *)MAC_state;
-+ }
-+
-+ LEAVE();
-+ return 0;
-+}
-+
-+module_init(ae531x_MAC_setup);
-+
-diff -urN linux-2.4.32.new/arch/mips/ar531x/ae531xmac.c linux-2.4.32.new-eth/arch/mips/ar531x/ae531xmac.c
---- linux-2.4.32.new/arch/mips/ar531x/ae531xmac.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new-eth/arch/mips/ar531x/ae531xmac.c 2005-12-25 11:54:20.771271672 +0000
-@@ -0,0 +1,942 @@
-+/*
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file "COPYING" in the main directory of this archive
-+ * for more details.
-+ *
-+ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
-+ */
-+
-+
-+/*
-+ * Ethernet driver for Atheros' ae531x ethernet MAC.
-+ */
-+
-+#if linux
-+#include <linux/config.h>
-+#include <linux/types.h>
-+#include <linux/delay.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/init.h>
-+#include <asm/io.h>
-+
-+#include "ar531xlnx.h"
-+#endif /* linux */
-+
-+#include "ae531xreg.h"
-+#include "ae531xmac.h"
-+
-+int ae531x_MAC_debug = AE531X_DEBUG_ERROR;
-+
-+/*
-+ * These externs are for functions that this layer relies on
-+ * that have OS-dependent implementations.
-+ */
-+extern UINT8 *macAddrGet(ae531x_MAC_t *MACInfo);
-+
-+/* Forward references to local functions */
-+static void ae531x_QueueDestroy(AE531X_QUEUE *q);
-+
-+
-+/******************************************************************************
-+*
-+* ae531x_ReadMacReg - read AE MAC register
-+*
-+* RETURNS: register value
-+*/
-+UINT32
-+ae531x_ReadMacReg(ae531x_MAC_t *MACInfo, UINT32 reg)
-+{
-+ UINT32 addr = MACInfo->macBase+reg;
-+ UINT32 data;
-+
-+ data = RegRead(addr);
-+ return data;
-+}
-+
-+
-+/******************************************************************************
-+*
-+* ae531x_WriteMacReg - write AE MAC register
-+*
-+* RETURNS: N/A
-+*/
-+void
-+ae531x_WriteMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data)
-+{
-+ UINT32 addr = MACInfo->macBase+reg;
-+
-+ RegWrite(data, addr);
-+}
-+
-+
-+/******************************************************************************
-+*
-+* ae531x_SetMacReg - set bits in AE MAC register
-+*
-+* RETURNS: N/A
-+*/
-+void
-+ae531x_SetMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val)
-+{
-+ UINT32 addr = MACInfo->macBase+reg;
-+ UINT32 data = RegRead(addr);
-+
-+ data |= val;
-+ RegWrite(data, addr);
-+}
-+
-+
-+/******************************************************************************
-+*
-+* ae531x_ClearMacReg - clear bits in AE MAC register
-+*
-+* RETURNS: N/A
-+*/
-+void
-+ae531x_ClearMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val)
-+{
-+ UINT32 addr = MACInfo->macBase+reg;
-+ UINT32 data = RegRead(addr);
-+
-+ data &= ~val;
-+ RegWrite(data, addr);
-+}
-+
-+
-+/******************************************************************************
-+*
-+* ae531x_ReadDmaReg - read AE DMA register
-+*
-+* RETURNS: register value
-+*/
-+UINT32
-+ae531x_ReadDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg)
-+{
-+ UINT32 addr = MACInfo->dmaBase+reg;
-+ UINT32 data = RegRead(addr);
-+
-+ return data;
-+}
-+
-+
-+/******************************************************************************
-+*
-+* ae531x_WriteDmaReg - write AE DMA register
-+*
-+* RETURNS: N/A
-+*/
-+void
-+ae531x_WriteDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data)
-+{
-+ UINT32 addr = MACInfo->dmaBase+reg;
-+
-+ RegWrite(data, addr);
-+}
-+
-+
-+/******************************************************************************
-+ *
-+ * ae531x_AckIntr - clear interrupt bits in the status register.
-+ * Note: Interrupt bits are *cleared* by writing a 1.
-+ */
-+void
-+ae531x_AckIntr(ae531x_MAC_t *MACInfo, UINT32 data)
-+{
-+ ae531x_WriteDmaReg(MACInfo, DmaStatus, data);
-+}
-+
-+
-+/******************************************************************************
-+*
-+* ae531x_SetDmaReg - set bits in an AE DMA register
-+*
-+* RETURNS: N/A
-+*/
-+void
-+ae531x_SetDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val)
-+{
-+ UINT32 addr = MACInfo->dmaBase+reg;
-+ UINT32 data = RegRead(addr);
-+
-+ data |= val;
-+ RegWrite(data, addr);
-+}
-+
-+
-+/******************************************************************************
-+*
-+* ae531x_ClearDmaReg - clear bits in an AE DMA register
-+*
-+* RETURNS: N/A
-+*/
-+void
-+ae531x_ClearDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val)
-+{
-+ UINT32 addr = MACInfo->dmaBase+reg;
-+ UINT32 data = RegRead(addr);
-+
-+ data &= ~val;
-+ RegWrite(data, addr);
-+}
-+
-+
-+/******************************************************************************
-+*
-+* ae531x_ReadMiiReg - read PHY registers via AE MAC Mii addr/data registers
-+*
-+* RETURNS: register value
-+*/
-+UINT32
-+ae531x_ReadMiiReg(UINT32 phyBase, UINT32 reg)
-+{
-+ UINT32 data;
-+ UINT32 addr = phyBase+reg;
-+
-+ data = RegRead(addr);
-+ return data;
-+}
-+
-+
-+/******************************************************************************
-+*
-+* ae531x_WriteMiiReg - write PHY registers via AE MAC Mii addr/data registers
-+*
-+* RETURNS: N/A
-+*/
-+void
-+ae531x_WriteMiiReg(UINT32 phyBase, UINT32 reg, UINT32 data)
-+{
-+ UINT32 addr = phyBase+reg;
-+
-+ RegWrite(data, addr);
-+}
-+
-+
-+/******************************************************************************
-+*
-+* ae531x_MiiRead - read AE Mii register
-+*
-+* RETURNS: register value
-+*/
-+UINT16
-+ae531x_MiiRead(UINT32 phyBase, UINT32 phyAddr, UINT8 reg)
-+{
-+ UINT32 addr;
-+ UINT16 data;
-+
-+ addr = ((phyAddr << MiiDevShift) & MiiDevMask) | ((reg << MiiRegShift) & MiiRegMask);
-+
-+ ae531x_WriteMiiReg(phyBase, MacMiiAddr, addr );
-+ do {
-+ /* nop */
-+ } while ((ae531x_ReadMiiReg(phyBase, MacMiiAddr ) & MiiBusy) == MiiBusy);
-+
-+ data = ae531x_ReadMiiReg(phyBase, MacMiiData) & 0xFFFF;
-+
-+ return data;
-+}
-+
-+
-+/******************************************************************************
-+*
-+* ae531x_MiiWrite - write AE Mii register
-+*
-+* RETURNS: N/A
-+*/
-+void
-+ae531x_MiiWrite(UINT32 phyBase, UINT32 phyAddr, UINT8 reg, UINT16 data)
-+{
-+ UINT32 addr;
-+
-+ ae531x_WriteMiiReg(phyBase, MacMiiData, data );
-+
-+ addr = ((phyAddr << MiiDevShift) & MiiDevMask) |
-+ ((reg << MiiRegShift) & MiiRegMask) | MiiWrite;
-+ ae531x_WriteMiiReg(phyBase, MacMiiAddr, addr );
-+
-+ do {
-+ /* nop */
-+ } while ((ae531x_ReadMiiReg(phyBase, MacMiiAddr ) & MiiBusy) == MiiBusy);
-+}
-+
-+
-+/*******************************************************************************
-+* ae531x_BeginResetMode - enter a special "reset mode" in which
-+* -no interrupts are expected from the device
-+* -the device will not transmit nor receive
-+* -attempts to send or receive will return with an error and
-+* -the device will be reset at the next convenient opportunity.
-+*/
-+void
-+ae531x_BeginResetMode(ae531x_MAC_t *MACInfo)
-+{
-+ /* Set the reset flag */
-+ MACInfo->aeProcessRst = 1;
-+}
-+
-+
-+/*******************************************************************************
-+* ae531x_EndResetMode - exit the special "reset mode" entered
-+* earlier via a call to ae531x_BeginResetMode.
-+*/
-+void
-+ae531x_EndResetMode(ae531x_MAC_t *MACInfo)
-+{
-+ MACInfo->aeProcessRst = 0;
-+}
-+
-+
-+/*******************************************************************************
-+* ae531x_IsInResetMode - determine whether or not the device is
-+* currently in "reset mode" (i.e. that a device reset is pending)
-+*/
-+BOOL
-+ae531x_IsInResetMode(ae531x_MAC_t *MACInfo)
-+{
-+ return MACInfo->aeProcessRst;
-+}
-+
-+
-+/******************************************************************************
-+*
-+* ae531x_DmaRxStart - Start Rx
-+*
-+* RETURNS: N/A
-+*/
-+static void
-+ae531x_DmaRxStart(ae531x_MAC_t *MACInfo)
-+{
-+ ae531x_SetDmaReg(MACInfo, DmaControl, DmaRxStart);
-+ sysWbFlush();
-+}
-+
-+
-+/******************************************************************************
-+*
-+* ae531x_DmaRxStop - Stop Rx
-+*
-+* RETURNS: N/A
-+*/
-+void
-+ae531x_DmaRxStop(ae531x_MAC_t *MACInfo)
-+{
-+ ae531x_ClearDmaReg(MACInfo, DmaControl, DmaRxStart);
-+ sysWbFlush();
-+}
-+
-+
-+/******************************************************************************
-+*
-+* ae531x_DmaTxStart - Start Tx
-+*
-+* RETURNS: N/A
-+*/
-+void
-+ae531x_DmaTxStart(ae531x_MAC_t *MACInfo)
-+{
-+ ae531x_SetDmaReg(MACInfo, DmaControl, DmaTxStart);
-+ sysWbFlush();
-+}
-+
-+
-+/******************************************************************************
-+*
-+* ae531x_DmaTxStop - Stop Tx
-+*
-+* RETURNS: N/A
-+*/
-+void
-+ae531x_DmaTxStop(ae531x_MAC_t *MACInfo)
-+{
-+ ae531x_ClearDmaReg(MACInfo, DmaControl, DmaTxStart);
-+ sysWbFlush();
-+}
-+
-+
-+/******************************************************************************
-+*
-+* ae531x_DmaIntEnable - Enable DMA interrupts
-+*
-+* RETURNS: N/A
-+*/
-+void
-+ae531x_DmaIntEnable(ae531x_MAC_t *MACInfo)
-+{
-+ ae531x_WriteDmaReg(MACInfo, DmaIntrEnb, DmaIntEnable);
-+}
-+
-+
-+/******************************************************************************
-+*
-+* ae531x_DmaIntDisable - Disable DMA interrupts
-+*
-+* RETURNS: N/A
-+*/
-+void
-+ae531x_DmaIntDisable(ae531x_MAC_t *MACInfo)
-+{
-+ ae531x_WriteDmaReg(MACInfo, DmaIntrEnb, DmaIntDisable);
-+}
-+
-+
-+/******************************************************************************
-+*
-+* ae531x_DmaIntClear - Clear DMA interrupts
-+*
-+* RETURNS: N/A
-+*/
-+static void
-+ae531x_DmaIntClear(ae531x_MAC_t *MACInfo)
-+{
-+ /* clear all interrupt requests */
-+ ae531x_WriteDmaReg(MACInfo, DmaStatus,
-+ ae531x_ReadDmaReg(MACInfo, DmaStatus));
-+}
-+
-+
-+/******************************************************************************
-+* Initialize generic queue data
-+*/
-+void
-+ae531x_QueueInit(AE531X_QUEUE *q, char *pMem, int count)
-+{
-+ ARRIVE();
-+ q->firstDescAddr = pMem;
-+ q->lastDescAddr = (VIRT_ADDR)((UINT32)q->firstDescAddr +
-+ (count - 1) * AE531X_QUEUE_ELE_SIZE);
-+ q->curDescAddr = q->firstDescAddr;
-+ q->count = count;
-+ LEAVE();
-+}
-+
-+
-+/******************************************************************************
-+* ae531x_TxQueueCreate - create a circular queue of descriptors for Transmit
-+*/
-+static int
-+ae531x_TxQueueCreate(ae531x_MAC_t *MACInfo,
-+ AE531X_QUEUE *q,
-+ char *pMem,
-+ int count)
-+{
-+ int i;
-+ VIRT_ADDR descAddr;
-+
-+ ARRIVE();
-+
-+ ae531x_QueueInit(q, pMem, count);
-+ q->reapDescAddr = q->lastDescAddr;
-+
-+ /* Initialize Tx buffer descriptors. */
-+ for (i=0, descAddr=q->firstDescAddr;
-+ i<count;
-+ i++, descAddr=(VIRT_ADDR)((UINT32)descAddr + AE531X_QUEUE_ELE_SIZE))
-+ {
-+ /* Update the size, BUFPTR, and SWPTR fields */
-+
-+ AE531X_DESC_STATUS_SET(descAddr, 0);
-+ AE531X_DESC_CTRLEN_SET(descAddr, 0);
-+
-+ AE531X_DESC_BUFPTR_SET(descAddr, (UINT32)0);
-+ AE531X_DESC_LNKBUF_SET(descAddr, (UINT32)0);
-+ AE531X_DESC_SWPTR_SET(descAddr, (void *)0);
-+ } /* for each desc */
-+
-+ /* Make the queue circular */
-+ AE531X_DESC_CTRLEN_SET(q->lastDescAddr,
-+ DescEndOfRing|AE531X_DESC_CTRLEN_GET(q->lastDescAddr));
-+
-+ AE531X_PRINT(AE531X_DEBUG_RESET,
-+ ("ethmac%d Txbuf begin = %x, end = %x\n",
-+ MACInfo->unit,
-+ (UINT32)q->firstDescAddr,
-+ (UINT32)q->lastDescAddr));
-+
-+ LEAVE();
-+ return 0;
-+}
-+
-+
-+/******************************************************************************
-+* ae531x_RxQueueCreate - create a circular queue of Rx descriptors
-+*/
-+int
-+ae531x_RxQueueCreate(ae531x_MAC_t *MACInfo,
-+ AE531X_QUEUE *q,
-+ char *pMem,
-+ int count)
-+{
-+ int i;
-+ VIRT_ADDR descAddr;
-+
-+ ARRIVE();
-+
-+ ae531x_QueueInit(q, pMem, count);
-+ q->reapDescAddr = NULL;
-+
-+
-+ /* Initialize Rx buffer descriptors */
-+ for (i=0, descAddr=q->firstDescAddr;
-+ i<count;
-+ i++, descAddr=(VIRT_ADDR)((UINT32)descAddr + AE531X_QUEUE_ELE_SIZE))
-+ {
-+ void *swptr;
-+ char *rxBuffer;
-+ int rxBufferSize;
-+
-+ swptr = ae531x_rxbuf_alloc(MACInfo, &rxBuffer, &rxBufferSize);
-+ if (swptr == NULL) {
-+ AE531X_PRINT(AE531X_DEBUG_RESET,
-+ ("ethmac%d RX queue: ae531x_rxbuf_alloc failed\n",
-+ MACInfo->unit));
-+ ae531x_QueueDestroy(q);
-+ return -1;
-+ }
-+ AE531X_DESC_SWPTR_SET(descAddr, swptr);
-+
-+ AE531X_DESC_STATUS_SET(descAddr, DescOwnByDma);
-+ AE531X_DESC_CTRLEN_SET(descAddr, rxBufferSize);
-+ AE531X_DESC_BUFPTR_SET(descAddr, virt_to_bus(rxBuffer));
-+ AE531X_DESC_LNKBUF_SET(descAddr, (UINT32)0);
-+ } /* for each desc */
-+
-+ /* Make the queue circular */
-+ AE531X_DESC_CTRLEN_SET(q->lastDescAddr,
-+ DescEndOfRing|AE531X_DESC_CTRLEN_GET(q->lastDescAddr));
-+
-+ AE531X_PRINT(AE531X_DEBUG_RESET,
-+ ("ethmac%d Rxbuf begin = %x, end = %x\n",
-+ MACInfo->unit,
-+ (UINT32)q->firstDescAddr,
-+ (UINT32)q->lastDescAddr));
-+
-+ LEAVE();
-+ return 0;
-+}
-+
-+
-+/******************************************************************************
-+* ae531x_QueueDestroy -- Free all buffers and descriptors associated
-+* with a queue.
-+*/
-+static void
-+ae531x_QueueDestroy(AE531X_QUEUE *q)
-+{
-+ int i;
-+ int count;
-+ VIRT_ADDR descAddr;
-+
-+ ARRIVE();
-+
-+ count = q->count;
-+
-+ for (i=0, descAddr=q->firstDescAddr;
-+ i<count;
-+ i++, descAddr=(VIRT_ADDR)((UINT32)descAddr + AE531X_QUEUE_ELE_SIZE)) {
-+
-+ AE531X_DESC_STATUS_SET(descAddr, 0);
-+ AE531X_DESC_CTRLEN_SET(descAddr, 0);
-+ AE531X_DESC_BUFPTR_SET(descAddr, (UINT32)0);
-+ AE531X_DESC_LNKBUF_SET(descAddr, (UINT32)0);
-+
-+ ae531x_swptr_free(descAddr); /* Free OS-specific software pointer */
-+ }
-+
-+ LEAVE();
-+}
-+
-+static void
-+ae531x_TxQueueDestroy(ae531x_MAC_t *MACInfo)
-+{
-+ ae531x_QueueDestroy(&MACInfo->txQueue);
-+}
-+
-+static void
-+ae531x_RxQueueDestroy(ae531x_MAC_t *MACInfo)
-+{
-+ ae531x_QueueDestroy(&MACInfo->rxQueue);
-+}
-+
-+
-+/******************************************************************************
-+* ae531x_AllocateQueues - Allocate receive and transmit queues
-+*/
-+int
-+ae531x_AllocateQueues(ae531x_MAC_t *MACInfo)
-+{
-+ size_t QMemSize;
-+ char *pTxBuf = NULL;
-+ char *pRxBuf = NULL;
-+
-+ ARRIVE();
-+
-+ MACInfo->txDescCount = AE531X_TX_DESC_COUNT_DEFAULT;
-+ QMemSize = AE531X_QUEUE_ELE_SIZE * MACInfo->txDescCount;
-+ pTxBuf = MALLOC(QMemSize);
-+ if (pTxBuf == NULL) {
-+ AE531X_PRINT(AE531X_DEBUG_RESET,
-+ ("ethmac%d Failed to allocate TX queue\n", MACInfo->unit));
-+ goto AllocQFail;
-+ }
-+
-+ if (ae531x_TxQueueCreate(MACInfo, &MACInfo->txQueue, pTxBuf,
-+ MACInfo->txDescCount) < 0)
-+ {
-+ AE531X_PRINT(AE531X_DEBUG_RESET,
-+ ("ethmac%d Failed to create TX queue\n", MACInfo->unit));
-+ goto AllocQFail;
-+ }
-+
-+ MACInfo->rxDescCount = AE531X_RX_DESC_COUNT_DEFAULT;
-+ QMemSize = AE531X_QUEUE_ELE_SIZE * MACInfo->rxDescCount;
-+ pRxBuf = MALLOC(QMemSize);
-+ if (pRxBuf == NULL) {
-+ AE531X_PRINT(AE531X_DEBUG_RESET,
-+ ("ethmac%d Failed to allocate RX queue\n", MACInfo->unit));
-+ goto AllocQFail;
-+ }
-+
-+ if (ae531x_RxQueueCreate(MACInfo, &MACInfo->rxQueue, pRxBuf,
-+ MACInfo->rxDescCount) < 0)
-+ {
-+ AE531X_PRINT(AE531X_DEBUG_RESET,
-+ ("ethmac%d Failed to create RX queue\n", MACInfo->unit));
-+ goto AllocQFail;
-+ }
-+
-+ AE531X_PRINT(AE531X_DEBUG_RESET,
-+ ("ethmac%d Memory setup complete.\n", MACInfo->unit));
-+
-+ LEAVE();
-+ return 0;
-+
-+AllocQFail:
-+ MACInfo->txDescCount = 0; /* sanity */
-+ MACInfo->rxDescCount = 0; /* sanity */
-+
-+ if (pTxBuf) {
-+ FREE(pTxBuf);
-+ }
-+ if (pRxBuf) {
-+ FREE(pRxBuf);
-+ }
-+
-+ LEAVE();
-+ return -1;
-+}
-+
-+
-+/******************************************************************************
-+*
-+* ae531x_FreeQueues - Free Transmit & Receive queues
-+*/
-+void
-+ae531x_FreeQueues(ae531x_MAC_t *MACInfo)
-+{
-+ ae531x_TxQueueDestroy(MACInfo);
-+ FREE(MACInfo->txQueue.firstDescAddr);
-+
-+ ae531x_RxQueueDestroy(MACInfo);
-+ FREE(MACInfo->rxQueue.firstDescAddr);
-+}
-+
-+/******************************************************************************
-+*
-+* ae531x_DmaReset - Reset DMA and TLI controllers
-+*
-+* RETURNS: N/A
-+*/
-+void
-+ae531x_DmaReset(ae531x_MAC_t *MACInfo)
-+{
-+ int i;
-+ UINT32 descAddr;
-+
-+ ARRIVE();
-+
-+ /* Disable device interrupts prior to any errors during stop */
-+ intDisable(MACInfo->ilevel);
-+
-+ /* Disable MAC rx and tx */
-+ ae531x_ClearMacReg(MACInfo, MacControl, (MacRxEnable | MacTxEnable));
-+
-+ /* Reset dma controller */
-+ ae531x_WriteDmaReg(MACInfo, DmaBusMode, DmaResetOn);
-+
-+ /* Delay 2 usec */
-+ sysUDelay(2);
-+
-+ /* Flush the rx queue */
-+ descAddr = (UINT32)MACInfo->rxQueue.firstDescAddr;
-+ MACInfo->rxQueue.curDescAddr = MACInfo->rxQueue.firstDescAddr;
-+ for (i=0;
-+ i<(MACInfo->rxDescCount);
-+ i++, descAddr += AE531X_QUEUE_ELE_SIZE) {
-+ AE531X_DESC_STATUS_SET(descAddr, DescOwnByDma);
-+ }
-+
-+ /* Flush the tx queue */
-+ descAddr = (UINT32)MACInfo->txQueue.firstDescAddr;
-+ MACInfo->txQueue.curDescAddr = MACInfo->txQueue.firstDescAddr;
-+ MACInfo->txQueue.reapDescAddr = MACInfo->txQueue.lastDescAddr;
-+ for (i=0;
-+ i<(MACInfo->txDescCount);
-+ i++, descAddr += AE531X_QUEUE_ELE_SIZE) {
-+ AE531X_DESC_STATUS_SET (descAddr, 0);
-+ }
-+
-+ /* Set init register values */
-+ ae531x_WriteDmaReg(MACInfo, DmaBusMode, DmaBusModeInit);
-+
-+ /* Install the first Tx and Rx queues on the device */
-+ ae531x_WriteDmaReg(MACInfo, DmaRxBaseAddr,
-+ (UINT32)MACInfo->rxQueue.firstDescAddr);
-+ ae531x_WriteDmaReg(MACInfo, DmaTxBaseAddr,
-+ (UINT32)MACInfo->txQueue.firstDescAddr);
-+
-+ ae531x_WriteDmaReg(MACInfo, DmaControl, DmaStoreAndForward);
-+
-+ ae531x_WriteDmaReg(MACInfo, DmaIntrEnb, DmaIntDisable);
-+
-+ AE531X_PRINT(AE531X_DEBUG_RESET,
-+ ("ethmac%d: DMA RESET!\n", MACInfo->unit));
-+
-+ /* Turn on device interrupts -- enable most errors */
-+ ae531x_DmaIntClear(MACInfo); /* clear interrupt requests */
-+ ae531x_DmaIntEnable(MACInfo); /* enable interrupts */
-+ /* Enable receive interrupts separately (they are not part
-+ * of the main group since they are enabled & disabled by
-+ * the polling routine.
-+ */
-+ ae531x_SetDmaReg(MACInfo, DmaIntrEnb,
-+ (DmaIntRxNoBuffer | DmaIntRxCompleted));
-+
-+ ae531x_EndResetMode(MACInfo);
-+
-+ intEnable(MACInfo->ilevel);
-+
-+ LEAVE();
-+}
-+
-+
-+/******************************************************************************
-+*
-+* ae531x_MACAddressSet - Set the ethernet address
-+*
-+* Sets the ethernet address according to settings in flash.
-+*
-+* RETURNS: void
-+*/
-+static void
-+ae531x_MACAddressSet(ae531x_MAC_t *MACInfo)
-+{
-+ unsigned int data;
-+ UINT8 *macAddr;
-+
-+ ARRIVE();
-+
-+ macAddr = macAddrGet(MACInfo);
-+
-+ /* set our MAC address */
-+ data = (macAddr[5]<<8) | macAddr[4];
-+ ae531x_WriteMacReg(MACInfo, MacAddrHigh, data );
-+
-+ data = (macAddr[3]<<24) | (macAddr[2]<<16) | (macAddr[1]<<8) | macAddr[0];
-+ ae531x_WriteMacReg(MACInfo, MacAddrLow, data );
-+
-+ AE531X_PRINT(AE531X_DEBUG_RESET,
-+ ("ethmac%d Verify MAC address %8.8X %8.8X \n",
-+ MACInfo->unit,
-+ ae531x_ReadMacReg(MACInfo, MacAddrLow),
-+ ae531x_ReadMacReg(MACInfo, MacAddrHigh)));
-+
-+ AE531X_PRINT(AE531X_DEBUG_RESET,
-+ (" sb = %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
-+ 0xff&macAddr[0],
-+ 0xff&macAddr[1],
-+ 0xff&macAddr[2],
-+ 0xff&macAddr[3],
-+ 0xff&macAddr[4],
-+ 0xff&macAddr[5]));
-+ LEAVE();
-+}
-+
-+
-+/******************************************************************************
-+*
-+* ae_SetMACFromPhy - read Phy settings and update Mac
-+* with current duplex and speed.
-+*
-+* RETURNS:
-+*/
-+static void
-+ae531x_SetMACFromPhy(ae531x_MAC_t *MACInfo)
-+{
-+ UINT32 macCtl;
-+ BOOL fullDuplex;
-+
-+ ARRIVE();
-+
-+ /* Get duplex mode from Phy */
-+ fullDuplex = phyIsFullDuplex(MACInfo->unit);
-+
-+ /* Flag is set for full duplex mode, else cleared */
-+ macCtl = ae531x_ReadMacReg(MACInfo, MacControl);
-+
-+ if (fullDuplex) {
-+ /* set values of control registers */
-+ macCtl &= ~MacDisableRxOwn;
-+ macCtl |= MacFullDuplex;
-+ ae531x_WriteMacReg(MACInfo, MacControl, macCtl);
-+ ae531x_WriteMacReg(MACInfo, MacFlowControl, MacFlowControlInitFdx);
-+#if 0
-+ printk ("[Full Duplex] CTRL=%#x FLOW=%#x\n", macCtl,
-+ MacFlowControlInitFdx);
-+#endif
-+ } else {
-+ /* set values of control registers */
-+ ae531x_WriteMacReg(MACInfo, MacFlowControl, MacFlowControlInitHdx);
-+ macCtl |= MacDisableRxOwn;
-+ macCtl &= ~MacFullDuplex;
-+ ae531x_WriteMacReg(MACInfo, MacControl, macCtl);
-+#if 0
-+ printk ("[Half Duplex] CTRL=%#x FLOW=%#x\n", macCtl,
-+ MacFlowControlInitHdx);
-+#endif
-+ }
-+
-+ LEAVE();
-+}
-+
-+
-+/******************************************************************************
-+* ae531x_MACReset -- sets MAC address and duplex.
-+*/
-+void
-+ae531x_MACReset(ae531x_MAC_t *MACInfo)
-+{
-+ ae531x_MACAddressSet(MACInfo);
-+
-+ ae531x_SetMACFromPhy(MACInfo);
-+}
-+
-+
-+/******************************************************************************
-+* ae531x_EnableComm -- enable Transmit and Receive
-+*/
-+void
-+ae531x_EnableComm(ae531x_MAC_t *MACInfo)
-+{
-+ ae531x_SetMacReg(MACInfo, MacControl, (MacRxEnable | MacTxEnable));
-+ ae531x_DmaRxStart(MACInfo); /* start receiver */
-+ ae531x_DmaTxStart(MACInfo); /* start transmitter */
-+}
-+
-+
-+/******************************************************************************
-+* ae531x_DisableComm -- disable Transmit and Receive
-+*/
-+void
-+ae531x_DisableComm(ae531x_MAC_t *MACInfo)
-+{
-+ ae531x_ClearMacReg(MACInfo, MacControl, (MacRxEnable | MacTxEnable));
-+}
-+
-+
-+/******************************************************************************
-+* ae531x_reset -- Cold reset ethernet interface
-+*/
-+void
-+ae531x_reset(ae531x_MAC_t *MACInfo)
-+{
-+ UINT32 mask = 0;
-+ UINT32 regtmp;
-+
-+ if (ar531x_num_enet_macs == 2) {
-+ if (MACInfo->unit == 0) {
-+ mask = AR531X_RESET_ENET0 | AR531X_RESET_EPHY0;
-+ } else {
-+ mask = AR531X_RESET_ENET1 | AR531X_RESET_EPHY1;
-+ }
-+ } else {
-+ mask = AR531X_RESET_ENET0 | AR531X_RESET_EPHY0 |
-+ AR531X_RESET_ENET1 | AR531X_RESET_EPHY1;
-+ }
-+
-+ /* Put into reset */
-+ regtmp = sysRegRead(AR531X_RESET);
-+ sysRegWrite(AR531X_RESET, regtmp | mask);
-+ sysMsDelay(15);
-+
-+ /* Pull out of reset */
-+ regtmp = sysRegRead(AR531X_RESET);
-+ sysRegWrite(AR531X_RESET, regtmp & ~mask);
-+ sysUDelay(25);
-+
-+ /* Enable */
-+ if (ar531x_num_enet_macs == 2) {
-+ if (MACInfo->unit == 0) {
-+ mask = AR531X_ENABLE_ENET0;
-+ } else {
-+ mask = AR531X_ENABLE_ENET1;
-+ }
-+ } else {
-+ mask = AR531X_ENABLE_ENET0 | AR531X_ENABLE_ENET1;
-+ }
-+ regtmp = sysRegRead(AR531X_ENABLE);
-+ sysRegWrite(AR531X_ENABLE, regtmp | mask);
-+}
-+
-+
-+/******************************************************************************
-+* ae531x_unitLinkLost -- Called from PHY layer to notify the MAC layer
-+* that there are no longer any live links associated with a MAC.
-+*/
-+void
-+ae531x_unitLinkLost(int ethUnit)
-+{
-+ AE531X_PRINT(AE531X_DEBUG_LINK_CHANGE,
-+ ("enetmac%d link down\n", ethUnit));
-+}
-+
-+
-+/******************************************************************************
-+* ae531x_unitLinkGained -- Called from PHY layer to notify the MAC layer
-+* that there are 1 or more live links associated with a MAC.
-+*/
-+void
-+ae531x_unitLinkGained(int ethUnit)
-+{
-+ AE531X_PRINT(AE531X_DEBUG_LINK_CHANGE,
-+ ("enet%d link up\n", ethUnit));
-+}
-+
-+/******************************************************************************
-+* ae531x_ethMacDefault -- Called from PHY layer to determine the default
-+* ethernet MAC. On some "twisted" platforms, the only usable MAC is 1,
-+* while on others the usable MAC is 0. Future boards may allow both MACs
-+* to be used; in this case, return -1 to indicate that there IS NO default
-+* MAC.
-+*
-+* Note: one some AR2312 platforms the PHY needs to be accessed through
-+* MAC 0, even though the MAC itself is addressed through MAC 1. Since this
-+* function is used by the PHY layer to determine which MAC it should use,
-+* the twisted case is limited to the one where the PHY is actually addressed
-+* through MAC 1 rather than MAC 0.
-+*/
-+int
-+ae531x_ethMacDefault(void)
-+{
-+ /*
-+ * Where there are two MACs, there is no real default
-+ */
-+ if (ar531x_num_enet_macs == 2)
-+ return -1;
-+
-+ /*
-+ * All single MAC platforms seem to address the PHY through MAC 0,
-+ * even when they use MAC 1 for the actual MAC functions.
-+ */
-+ return 0;
-+}
-diff -urN linux-2.4.32.new/arch/mips/ar531x/ae531xmac.h linux-2.4.32.new-eth/arch/mips/ar531x/ae531xmac.h
---- linux-2.4.32.new/arch/mips/ar531x/ae531xmac.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new-eth/arch/mips/ar531x/ae531xmac.h 2005-12-25 11:54:20.819264376 +0000
-@@ -0,0 +1,208 @@
-+/*
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file "COPYING" in the main directory of this archive
-+ * for more details.
-+ *
-+ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
-+ */
-+
-+/*
-+ * See README to understand the decomposition of the ethernet driver.
-+ *
-+ * This file contains OS-independent pure software definitions for
-+ * ethernet support on the AR531X platform.
-+ */
-+
-+#ifndef _AE531XMAC_H_
-+#define _AE531XMAC_H_
-+
-+/*
-+ * DEBUG switches to control verbosity.
-+ * Just modify the value of ae531x_MAC_debug.
-+ */
-+#define AE531X_DEBUG_ALL 0xffffffff
-+#define AE531X_DEBUG_ERROR 0x00000001 /* Unusual conditions and Errors */
-+#define AE531X_DEBUG_ARRIVE 0x00000002 /* Arrive into a function */
-+#define AE531X_DEBUG_LEAVE 0x00000004 /* Leave a function */
-+#define AE531X_DEBUG_RESET 0x00000008 /* Reset */
-+#define AE531X_DEBUG_TX 0x00000010 /* Transmit */
-+#define AE531X_DEBUG_TX_REAP 0x00000020 /* Transmit Descriptor Reaping */
-+#define AE531X_DEBUG_RX 0x00000040 /* Receive */
-+#define AE531X_DEBUG_RX_STOP 0x00000080 /* Receive Early Stop */
-+#define AE531X_DEBUG_INT 0x00000100 /* Interrupts */
-+#define AE531X_DEBUG_LINK_CHANGE 0x00000200 /* PHY Link status changed */
-+
-+extern int ae531x_MAC_debug;
-+
-+extern int ar531x_num_enet_macs;
-+
-+#define AE531X_PRINT(FLG, X) \
-+{ \
-+ if (ae531x_MAC_debug & (FLG)) { \
-+ DEBUG_PRINTF("%s#%d:%s ", \
-+ __FILE__, \
-+ __LINE__, \
-+ __FUNCTION__); \
-+ DEBUG_PRINTF X; \
-+ } \
-+}
-+
-+#define ARRIVE() AE531X_PRINT(AE531X_DEBUG_ARRIVE, ("Arrive{\n"))
-+#define LEAVE() AE531X_PRINT(AE531X_DEBUG_LEAVE, ("}Leave\n"))
-+
-+#define RegRead(addr) \
-+ (*(volatile unsigned int *)(addr))
-+
-+#define RegWrite(val,addr) \
-+ ((*(volatile unsigned int *)(addr)) = (val))
-+
-+/*****************************************************************
-+ * Phy code is broken out into a separate layer, so that different
-+ * PHY hardware can easily be supported.
-+ *
-+ * These functions are provided by the PHY layer for use by the MAC layer.
-+ * phySetup -- Set phy hardware appropriately for a MAC unit
-+ *
-+ * phyCheckStatusChange -- Look for dropped/initiated links on any
-+ * phy port associated with a MAC unit
-+ *
-+ * phyIsSpeed100 -- Determines whether or not a PHY is up and
-+ * running at 100Mbit
-+ *
-+ * phyIsFullDuplex -- Determines whether or not a PHY is up and
-+ * running in Full Duplex mode
-+ *
-+ */
-+#ifdef CONFIG_MARVELL_ENET_PHY
-+/*
-+ * Mapping of generic phy APIs to Marvell Ethernet Switch phy functions.
-+ */
-+#include "mvPhy.h"
-+#define phySetup(ethUnit, phyBase) mv_phySetup((ethUnit), (phyBase))
-+#define phyCheckStatusChange(ethUnit) mv_phyCheckStatusChange(ethUnit)
-+#define phyIsSpeed100(ethUnit) mv_phyIsSpeed100(ethUnit)
-+#define phyIsFullDuplex(ethUnit) mv_phyIsFullDuplex(ethUnit)
-+
-+#ifdef CONFIG_VENETDEV
-+#define PHY_TRAILER_SIZE MV_PHY_TRAILER_SIZE
-+extern int mv_phyDetermineSource(char *data, int len);
-+extern void mv_phySetDestinationPort(char *data, int len, int fromLAN);
-+#define phyDetermineSource(data, len) mv_phyDetermineSource((data), (len))
-+#define phySetDestinationPort(data, len, fromLAN) mv_phySetDestinationPort((data), (len), (fromLAN))
-+#else
-+#define PHY_TRAILER_SIZE 0
-+#endif
-+#endif /* CONFIG_MARVELL_ENET_PHY */
-+
-+#if defined(CONFIG_KENDIN_ENET_PHY) || defined(CONFIG_REALTEK_ENET_PHY)
-+/*
-+ * Mapping of generic phy APIs to Kendin KS8721B and RealTek RTL8201BL phys.
-+ */
-+#include "rtPhy.h"
-+#define phySetup(ethUnit, phyBase) rt_phySetup((ethUnit), (phyBase))
-+#define phyCheckStatusChange(ethUnit) rt_phyCheckStatusChange(ethUnit)
-+#define phyIsSpeed100(ethUnit) rt_phyIsSpeed100(ethUnit)
-+#define phyIsFullDuplex(ethUnit) rt_phyIsFullDuplex(ethUnit)
-+#endif
-+
-+#if !defined(PHY_TRAILER_SIZE)
-+#define PHY_TRAILER_SIZE 0
-+#endif
-+
-+/*****************************************************************
-+ * MAC-independent interface to be used by PHY code
-+ *
-+ * These functions are provided by the MAC layer for use by the PHY layer.
-+ */
-+#define phyRegRead ae531x_MiiRead
-+#define phyRegWrite ae531x_MiiWrite
-+#define phyLinkLost(ethUnit) ae531x_unitLinkLost(ethUnit)
-+#define phyLinkGained(ethUnit) ae531x_unitLinkGained(ethUnit)
-+#define phyEthMacDefault() ae531x_ethMacDefault()
-+
-+void ae531x_unitLinkLost(int unit);
-+void ae531x_unitLinkGained(int unit);
-+int ae531x_ethMacDefault(void);
-+
-+
-+/* RXBUFF_RESERVE enables building header on WLAN-side in place */
-+#define RXBUFF_RESERVE 96
-+#define ETH_CRC_LEN 4
-+
-+/*****************************************************************
-+ * Descriptor queue
-+ */
-+typedef struct ae531x_queue {
-+ VIRT_ADDR firstDescAddr; /* descriptor array address */
-+ VIRT_ADDR lastDescAddr; /* last descriptor address */
-+ VIRT_ADDR curDescAddr; /* current descriptor address */
-+ VIRT_ADDR reapDescAddr; /* current tail of tx descriptors reaped */
-+ UINT16 count; /* number of elements */
-+} AE531X_QUEUE;
-+
-+/* Given a descriptor, return the next one in a circular list */
-+#define AE531X_QUEUE_ELE_NEXT_GET(q, descAddr) \
-+ ((descAddr) == (q)->lastDescAddr) ? (q)->firstDescAddr : \
-+ (VIRT_ADDR)((UINT32)(descAddr) + AE531X_QUEUE_ELE_SIZE)
-+
-+/* Move the "current descriptor" forward to the next one */
-+#define AE531X_CONSUME_DESC(q) \
-+ q->curDescAddr = AE531X_QUEUE_ELE_NEXT_GET(q, q->curDescAddr)
-+
-+/*****************************************************************
-+ * Per-ethernet-MAC OS-independent information
-+ */
-+typedef struct ae531x_MAC_s {
-+ u32 unit; /* MAC unit ID */
-+ u32 macBase; /* MAC base address */
-+ u32 dmaBase; /* DMA base address */
-+ u32 phyBase; /* PHY base address */
-+ AE531X_QUEUE txQueue; /* Transmit descriptor queue */
-+ AE531X_QUEUE rxQueue; /* Receive descriptor queue */
-+ UINT16 txDescCount; /* Transmit descriptor count */
-+ UINT16 rxDescCount; /* Receive descriptor count */
-+ BOOL aeProcessRst; /* flag to indicate reset in progress */
-+ BOOL port_is_up; /* flag to indicate port is up */
-+ void *OSinfo; /* OS-dependent data */
-+} ae531x_MAC_t;
-+
-+#define AE531X_TX_DESC_COUNT_DEFAULT 64 /* Transmit descriptors */
-+#define AE531X_RX_DESC_COUNT_DEFAULT 64 /* Receive descriptors */
-+
-+
-+/*****************************************************************
-+ * Interfaces exported by the OS-independent MAC layer
-+ */
-+void ae531x_BeginResetMode(ae531x_MAC_t *MACInfo);
-+void ae531x_EndResetMode(ae531x_MAC_t *MACInfo);
-+BOOL ae531x_IsInResetMode(ae531x_MAC_t *MACInfo);
-+int ae531x_RxQueueCreate(ae531x_MAC_t *MACInfo, AE531X_QUEUE *q,
-+ char *pMem, int count);
-+int ae531x_QueueDelete(struct ae531x_queue *q);
-+void ae531x_DmaReset(ae531x_MAC_t *MACInfo);
-+void ae531x_MACReset(ae531x_MAC_t *MACInfo);
-+void ae531x_EnableComm(ae531x_MAC_t *MACInfo);
-+void ae531x_DisableComm(ae531x_MAC_t *MACInfo);
-+void ae531x_reset(ae531x_MAC_t *MACInfo);
-+int ae531x_AllocateQueues(ae531x_MAC_t *MACInfo);
-+void ae531x_FreeQueues(ae531x_MAC_t *MACInfo);
-+void ae531x_QueueInit(AE531X_QUEUE *q, char *pMem, int count);
-+UINT32 ae531x_ReadMacReg(ae531x_MAC_t *MACInfo, UINT32 reg);
-+void ae531x_WriteMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data);
-+void ae531x_SetMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
-+void ae531x_ClearMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
-+void ae531x_SetDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
-+void ae531x_ClearDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
-+UINT32 ae531x_ReadDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg);
-+void ae531x_WriteDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data);
-+UINT32 ae531x_ReadMiiReg(UINT32 phyBase, UINT32 reg);
-+void ae531x_WriteMiiReg(UINT32 phyBase, UINT32 reg, UINT32 data);
-+UINT16 ae531x_MiiRead(UINT32 phyBase, UINT32 phyAddr, UINT8 reg);
-+void ae531x_MiiWrite(UINT32 phyBase, UINT32 phyAddr, UINT8 reg, UINT16 data);
-+void ae531x_DmaIntEnable(ae531x_MAC_t *MACInfo);
-+void ae531x_DmaIntDisable(ae531x_MAC_t *MACInfo);
-+void ae531x_AckIntr(ae531x_MAC_t *MACInfo, UINT32 val);
-+void *ae531x_rxbuf_alloc(ae531x_MAC_t *MACInfo, char **rxBptr, int *rxBSize);
-+void ae531x_swptr_free(VIRT_ADDR txDesc);
-+
-+#endif /* _AE531XMAC_H_ */
-diff -urN linux-2.4.32.new/arch/mips/ar531x/ae531xreg.h linux-2.4.32.new-eth/arch/mips/ar531x/ae531xreg.h
---- linux-2.4.32.new/arch/mips/ar531x/ae531xreg.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new-eth/arch/mips/ar531x/ae531xreg.h 2005-12-25 11:54:20.834262096 +0000
-@@ -0,0 +1,437 @@
-+/*
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file "COPYING" in the main directory of this archive
-+ * for more details.
-+ *
-+ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
-+ */
-+
-+/*
-+ * See README to understand the decomposition of the ethernet driver.
-+ *
-+ * Register definitions for Atheros AR531X Ethernet MAC.
-+ */
-+
-+#ifndef _AE531XREG_H_
-+#define _AE531XREG_H_
-+
-+#define AE531X_MAC_OFFSET 0x0000
-+#define AE531X_PHY_OFFSET 0x0000 /* Same as MAC offset */
-+#define AE531X_DMA_OFFSET 0x1000
-+
-+/***********************************************************/
-+/* MAC110 registers, base address is BAR+AE531X_MAC_OFFSET */
-+/***********************************************************/
-+#define MacControl 0x00 /* control */
-+#define MacAddrHigh 0x04 /* address high */
-+#define MacAddrLow 0x08 /* address low */
-+#define MacMultiHashHigh 0x0C /* multicast hash table high */
-+#define MacMultiHashLow 0x10 /* multicast hash table low */
-+#define MacMiiAddr 0x14 /* MII address */
-+#define MacMiiData 0x18 /* MII data */
-+#define MacFlowControl 0x1C /* Flow control */
-+#define MacVlan1Tag 0x4C /* VLAN1 tag */
-+#define MacVlan2Tag 0x50 /* VLAN2 tag */
-+
-+
-+/***************************************************************/
-+/* DMA engine registers, base address is BAR+AE531X_DMA_OFFSET */
-+/***************************************************************/
-+#define DmaBusMode 0x00 /* CSR0 - Bus Mode */
-+#define DmaTxPollDemand 0x04 /* CSR1 - Transmit Poll Demand */
-+#define DmaRxPollDemand 0x08 /* CSR2 - Receive Poll Demand */
-+#define DmaRxBaseAddr 0x0C /* CSR3 - Receive list base address */
-+#define DmaTxBaseAddr 0x10 /* CSR4 - Transmit list base address */
-+#define DmaStatus 0x14 /* CSR5 - Dma status */
-+#define DmaControl 0x18 /* CSR6 - Dma control */
-+#define DmaIntrEnb 0x1C /* CSR7 - Interrupt enable */
-+#define DmaOverflowCnt 0x20 /* CSR8 - Missed Frame and Buff Overflow counter */
-+#define DmaTxCurrAddr 0x50 /* CSR20 - Current host transmit buffer address */
-+#define DmaRxCurrAddr 0x54 /* CSR21 - Current host receive buffer address */
-+
-+/**********************************************************/
-+/* MAC Control register layout */
-+/**********************************************************/
-+#define MacFilterOff 0x80000000 /* Receive all incoming packets RW */
-+#define MacFilterOn 0 /* Receive filtered packets only 0 */
-+#define MacBigEndian 0x40000000 /* Big endian mode RW */
-+#define MacLittleEndian 0 /* Little endian 0 */
-+#define MacHeartBeatOff 0x10000000 /* Heartbeat signal qual disable RW*/
-+#define MacHeartBeatOn 0 /* Heartbeat signal qual enable 0 */
-+#define MacSelectSrl 0x08000000 /* Select SRL port RW */
-+#define MacSelectMii 0 /* Select MII port 0 */
-+#define MacDisableRxOwn 0x00800000 /* Disable receive own packets RW */
-+#define MacEnableRxOwn 0 /* Enable receive own packets 0 */
-+#define MacLoopbackExt 0x00400000 /* External loopback RW */
-+#define MacLoopbackInt 0x00200000 /* Internal loopback */
-+#define MacLoopbackOff 0 /* Normal mode 00 */
-+#define MacFullDuplex 0x00100000 /* Full duplex mode RW */
-+#define MacHalfDuplex 0 /* Half duplex mode 0 */
-+#define MacMulticastFilterOff 0x00080000 /* Pass all multicast packets RW */
-+#define MacMulticastFilterOn 0 /* Pass filtered mcast packets 0 */
-+#define MacPromiscuousModeOn 0x00040000 /* Receive all valid packets RW 1 */
-+#define MacPromiscuousModeOff 0 /* Receive filtered packets only */
-+#define MacFilterInverse 0x00020000 /* Inverse filtering RW */
-+#define MacFilterNormal 0 /* Normal filtering 0 */
-+#define MacBadFramesEnable 0x00010000 /* Pass bad frames RW */
-+#define MacBadFramesDisable 0 /* Do not pass bad frames 0 */
-+#define MacPerfectFilterOff 0x00008000 /* Hash filtering only RW */
-+#define MacPerfectFilterOn 0 /* Both perfect and hash filtering 0 */
-+#define MacHashFilterOn 0x00002000 /* perform hash filtering RW */
-+#define MacHashFilterOff 0 /* perfect filtering only 0 */
-+#define MacLateCollisionOn 0x00001000 /* Enable late collision control RW */
-+#define MacLateCollisionOff 0 /* Disable late collision control 0 */
-+#define MacBroadcastDisable 0x00000800 /* Disable reception of bcast frames RW */
-+#define MacBroadcastEnable 0 /* Enable broadcast frames 0 */
-+#define MacRetryDisable 0x00000400 /* Disable retransmission RW */
-+#define MacRetryEnable 0 /* Enable retransmission 0 */
-+#define MacPadStripEnable 0x00000100 /* Pad stripping enable RW */
-+#define MacPadStripDisable 0 /* Pad stripping disable 0 */
-+#define MacBackoff 0 /* Backoff Limit RW 00 */
-+#define MacDeferralCheckEnable 0x00000020 /* Deferral check enable RW */
-+#define MacDeferralCheckDisable 0 /* Deferral check disable 0 */
-+#define MacTxEnable 0x00000008 /* Transmitter enable RW */
-+#define MacTxDisable 0 /* Transmitter disable 0 */
-+#define MacRxEnable 0x00000004 /* Receiver enable RW */
-+#define MacRxDisable 0 /* Receiver disable 0 */
-+
-+
-+/**********************************************************/
-+/* MII address register layout */
-+/**********************************************************/
-+#define MiiDevMask 0x0000F800 /* MII device address */
-+#define MiiDevShift 11
-+#define MiiRegMask 0x000007C0 /* MII register */
-+#define MiiRegShift 6
-+#define MiiWrite 0x00000002 /* Write to register */
-+#define MiiRead 0 /* Read from register */
-+#define MiiBusy 0x00000001 /* MII interface is busy */
-+
-+/**********************************************************/
-+/* MII Data register layout */
-+/**********************************************************/
-+#define MiiDataMask 0x0000FFFF /* MII Data */
-+
-+/**********************************************************/
-+/* MAC flow control register layout */
-+/**********************************************************/
-+#define MacPauseTimeMask 0xFFFF0000 /* PAUSE TIME field in ctrl frame */
-+#define MacPauseTimeShift 15
-+#define MacControlFrameEnable 0x00000004 /* Enable pass ctrl frames to host */
-+#define MacControlFrameDisable 0 /* Do not pass ctrl frames to host */
-+#define MacFlowControlEnable 0x00000002 /* Enable flow control */
-+#define MacFlowControlDisable 0 /* Disable flow control */
-+#define MacSendPauseFrame 0x00000001 /* send pause frame */
-+
-+/**********************************************************/
-+/* DMA bus mode register layout */
-+/**********************************************************/
-+#define DmaRxAlign16 0x01000000 /* Force all rx buffers to align on odd hw bndry */
-+#define DmaBigEndianDes 0x00100000 /* Big endian data buffer descriptors RW */
-+#define DmaLittleEndianDesc 0 /* Little endian data descriptors */
-+#define DmaBurstLength32 0x00002000 /* Dma burst length 32 RW */
-+#define DmaBurstLength16 0x00001000 /* Dma burst length 16 */
-+#define DmaBurstLength8 0x00000800 /* Dma burst length 8 */
-+#define DmaBurstLength4 0x00000400 /* Dma burst length 4 */
-+#define DmaBurstLength2 0x00000200 /* Dma burst length 2 */
-+#define DmaBurstLength1 0x00000100 /* Dma burst length 1 */
-+#define DmaBurstLength0 0x00000000 /* Dma burst length 0 */
-+#define DmaBigEndianData 0x00000080 /* Big endian data buffers RW */
-+#define DmaLittleEndianData 0 /* Little endian data buffers 0 */
-+#define DmaDescriptorSkip16 0x00000040 /* number of dwords to skip RW */
-+#define DmaDescriptorSkip8 0x00000020 /* between two unchained descriptors */
-+#define DmaDescriptorSkip4 0x00000010
-+#define DmaDescriptorSkip2 0x00000008
-+#define DmaDescriptorSkip1 0x00000004
-+#define DmaDescriptorSkip0 0
-+#define DmaReceivePriorityOff 0x00000002 /* equal rx and tx priorities RW */
-+#define DmaReceivePriorityOn 0 /* Rx has prioryty over Tx 0 */
-+#define DmaResetOn 0x00000001 /* Reset DMA engine RW */
-+#define DmaResetOff 0
-+
-+/**********************************************************/
-+/* DMA Status register layout */
-+/**********************************************************/
-+#define DmaRxAbort 0x01000000 /* receiver bus abort R 0 */
-+#define DmaTxAbort 0x00800000 /* transmitter bus abort R 0 */
-+#define DmaTxState 0x00700000 /* Transmit process state R 000 */
-+#define DmaTxStopped 0x00000000 /* Stopped */
-+#define DmaTxFetching 0x00100000 /* Running - fetching the descriptor */
-+#define DmaTxWaiting 0x00200000 /* Running - waiting for end of transmission */
-+#define DmaTxReading 0x00300000 /* Running - reading the data from memory */
-+#define DmaTxSuspended 0x00600000 /* Suspended */
-+#define DmaTxClosing 0x00700000 /* Running - closing descriptor */
-+#define DmaRxState 0x000E0000 /* Receive process state 000 */
-+#define DmaRxStopped 0x00000000 /* Stopped */
-+#define DmaRxFetching 0x00020000 /* Running - fetching the descriptor */
-+#define DmaRxChecking 0x00040000 /* Running - checking for end of packet */
-+#define DmaRxWaiting 0x00060000 /* Running - waiting for packet */
-+#define DmaRxSuspended 0x00080000 /* Suspended */
-+#define DmaRxClosing 0x000A0000 /* Running - closing descriptor */
-+#define DmaRxFlushing 0x000C0000 /* Running - flushing the current frame */
-+#define DmaRxQueuing 0x000E0000 /* Running - queuing the recieve frame into host memory */
-+#define DmaIntNormal 0x00010000 /* Normal interrupt summary RW 0 */
-+#define DmaIntAbnormal 0x00008000 /* Abnormal interrupt summary RW 0 */
-+#define DmaIntEarlyRx 0x00004000 /* Early receive interrupt (Normal) RW 0 */
-+#define DmaIntBusError 0x00002000 /* Fatal bus error (Abnormal) RW 0 */
-+#define DmaIntEarlyTx 0x00000400 /* Early transmit interrupt RW 0 */
-+#define DmaIntRxStopped 0x00000100 /* Receive process stopped (Abnormal) RW 0 */
-+#define DmaIntRxNoBuffer 0x00000080 /* Receive buffer unavailable (Abnormal) RW 0*/
-+#define DmaIntRxCompleted 0x00000040 /* Completion of frame reception(Normal) RW 0*/
-+#define DmaIntTxUnderflow 0x00000020 /* Transmit underflow (Abnormal) RW 0 */
-+#define DmaIntTxJabber 0x00000008 /* Transmit Jabber Timeout (Abnormal) RW 0 */
-+#define DmaIntTxNoBuffer 0x00000004 /* Transmit buffer unavailable (Normal) RW 0*/
-+#define DmaIntTxStopped 0x00000002 /* Transmit process stopped (Abnormal) RW 0 */
-+#define DmaIntTxCompleted 0x00000001 /* Transmit completed (Normal) RW 0 */
-+
-+/**********************************************************/
-+/* DMA control register layout */
-+/**********************************************************/
-+#define DmaStoreAndForward 0x00200000 /* Store and forward RW 0 */
-+#define DmaTxThreshCtl256 0x0000c000 /* Non-SF threshold is 256 words */
-+#define DmaTxThreshCtl128 0x00008000 /* Non-SF threshold is 128 words */
-+#define DmaTxThreshCtl064 0x00004000 /* Non-SF threshold is 64 words */
-+#define DmaTxThreshCtl032 0x00000000 /* Non-SF threshold is 32 words */
-+#define DmaTxStart 0x00002000 /* Start/Stop transmission RW 0 */
-+#define DmaTxSecondFrame 0x00000004 /* Operate on second frame RW 0 */
-+#define DmaRxStart 0x00000002 /* Start/Stop reception RW 0 */
-+
-+/**********************************************************/
-+/* DMA interrupt enable register layout */
-+/**********************************************************/
-+#define DmaIeNormal DmaIntNormal /* Normal interrupt enable RW 0 */
-+#define DmaIeAbnormal DmaIntAbnormal /* Abnormal interrupt enable RW 0 */
-+#define DmaIeEarlyRx DmaIntEarlyRx /* Early receive interrupt enable RW 0 */
-+#define DmaIeBusError DmaIntBusError /* Fatal bus error enable RW 0 */
-+#define DmaIeEarlyTx DmaIntEarlyTx /* Early transmit interrupt enable RW 0 */
-+#define DmaIeRxStopped DmaIntRxStopped /* Receive process stopped enable RW 0 */
-+#define DmaIeRxNoBuffer DmaIntRxNoBuffer /* Receive buffer unavailable enable RW 0 */
-+#define DmaIeRxCompleted DmaIntRxCompleted /* Completion of frame reception enable RW 0 */
-+#define DmaIeTxUnderflow DmaIntTxUnderflow /* Transmit underflow enable RW 0 */
-+#define DmaIeTxJabber DmaIntTxJabber /* Transmit jabber timeout RW 0 */
-+#define DmaIeTxNoBuffer DmaIntTxNoBuffer /* Transmit buffer unavailable enable RW 0 */
-+#define DmaIeTxStopped DmaIntTxStopped /* Transmit process stopped enable RW 0 */
-+#define DmaIeTxCompleted DmaIntTxCompleted /* Transmit completed enable RW 0 */
-+
-+/****************************************************************/
-+/* DMA Missed Frame and Buffer Overflow Counter register layout */
-+/****************************************************************/
-+#define DmaRxBufferMissedFrame 0xffff0000 /* cleared on read */
-+#define DmaMissedFrameShift 16
-+#define DmaRxBufferOverflowCnt 0x0000ffff /* cleared on read */
-+#define DmaMissedFrameCountMask 0x0000ffff
-+
-+/**********************************************************/
-+/* DMA Engine descriptor layout */
-+/**********************************************************/
-+/* status word of DMA descriptor */
-+#define DescOwnByDma 0x80000000 /* Descriptor is owned by DMA engine */
-+#define DescFrameLengthMask 0x3FFF0000 /* Receive descriptor frame length */
-+#define DescFrameLengthShift 16
-+#define DescError 0x00008000 /* Error summary bit OR of following bits */
-+#define DescRxTruncated 0x00004000 /* Rx - no more descs for receive frame */
-+#define DescRxLengthError 0x00001000 /* Rx - frame size not matching with length field */
-+#define DescRxRunt 0x00000800 /* Rx - runt frame, damaged by a
-+ collision or term before 64 bytes */
-+#define DescRxMulticast 0x00000400 /* Rx - received frame is multicast */
-+#define DescRxFirst 0x00000200 /* Rx - first descriptor of the frame */
-+#define DescRxLast 0x00000100 /* Rx - last descriptor of the frame */
-+#define DescRxLongFrame 0x00000080 /* Rx - frame is longer than 1518 bytes */
-+#define DescRxLateColl 0x00000040 /* Rx - frame was damaged by a late collision */
-+#define DescRxFrameEther 0x00000020 /* Rx - Frame type Ethernet 802.3*/
-+#define DescRxMiiError 0x00000008 /* Rx - error reported by MII interface */
-+#define DescRxDribbling 0x00000004 /* Rx - frame contains noninteger multiple of 8 bits */
-+#define DescRxCrc 0x00000002 /* Rx - CRC error */
-+#define DescTxTimeout 0x00004000 /* Tx - Transmit jabber timeout */
-+#define DescTxLostCarrier 0x00000800 /* Tx - carrier lost during tramsmission */
-+#define DescTxNoCarrier 0x00000400 /* Tx - no carrier signal from tranceiver */
-+#define DescTxLateCollision 0x00000200 /* Tx - transmission aborted due to collision */
-+#define DescTxExcCollisions 0x00000100 /* Tx - transmission aborted after 16 collisions */
-+#define DescTxHeartbeatFail 0x00000080 /* Tx - heartbeat collision check failure */
-+#define DescTxCollMask 0x00000078 /* Tx - Collision count */
-+#define DescTxCollShift 3
-+#define DescTxExcDeferral 0x00000004 /* Tx - excessive deferral */
-+#define DescTxUnderflow 0x00000002 /* Tx - late data arrival from memory */
-+#define DescTxDeferred 0x00000001 /* Tx - frame transmision deferred */
-+
-+/* length word of DMA descriptor */
-+#define DescTxIntEnable 0x80000000 /* Tx - interrupt on completion */
-+#define DescTxLast 0x40000000 /* Tx - Last segment of the frame */
-+#define DescTxFirst 0x20000000 /* Tx - First segment of the frame */
-+#define DescTxDisableCrc 0x04000000 /* Tx - Add CRC disabled (first segment only) */
-+#define DescEndOfRing 0x02000000 /* End of descriptors ring */
-+#define DescChain 0x01000000 /* Second buffer address is chain address */
-+#define DescTxDisablePadd 0x00800000 /* disable padding */
-+#define DescSize2Mask 0x003FF800 /* Buffer 2 size */
-+#define DescSize2Shift 11
-+#define DescSize1Mask 0x000007FF /* Buffer 1 size */
-+#define DescSize1Shift 0
-+
-+/**********************************************************/
-+/* Initial register values */
-+/**********************************************************/
-+/* Full-duplex mode with perfect filter on */
-+#define MacControlInitFdx \
-+ ( MacFilterOn \
-+ | MacLittleEndian \
-+ | MacHeartBeatOn \
-+ | MacSelectMii \
-+ | MacEnableRxOwn \
-+ | MacLoopbackOff \
-+ | MacFullDuplex \
-+ | MacMulticastFilterOn \
-+ | MacPromiscuousModeOff \
-+ | MacFilterNormal \
-+ | MacBadFramesDisable \
-+ | MacPerfectFilterOn \
-+ | MacHashFilterOff \
-+ | MacLateCollisionOff \
-+ | MacBroadcastEnable \
-+ | MacRetryEnable \
-+ | MacPadStripDisable \
-+ | MacDeferralCheckDisable \
-+ | MacTxEnable \
-+ | MacRxEnable)
-+
-+/* Full-duplex mode */
-+#define MacFlowControlInitFdx \
-+ ( MacControlFrameDisable \
-+ | MacFlowControlEnable)
-+
-+/* Half-duplex mode with perfect filter on */
-+#define MacControlInitHdx \
-+ ( MacFilterOn \
-+ | MacLittleEndian \
-+ | MacHeartBeatOn \
-+ | MacSelectMii \
-+ | MacDisableRxOwn \
-+ | MacLoopbackOff \
-+ | MacHalfDuplex \
-+ | MacMulticastFilterOn \
-+ | MacPromiscuousModeOff \
-+ | MacFilterNormal \
-+ | MacBadFramesDisable \
-+ | MacPerfectFilterOn \
-+ | MacHashFilterOff \
-+ | MacLateCollisionOff \
-+ | MacBroadcastEnable \
-+ | MacRetryEnable \
-+ | MacPadStripDisable \
-+ | MacDeferralCheckDisable \
-+ | MacTxEnable \
-+ | MacRxEnable)
-+
-+/* Half-duplex mode */
-+#define MacFlowControlInitHdx \
-+ ( MacControlFrameDisable \
-+ | MacFlowControlDisable)
-+
-+/* Bus Mode Rx odd half word align */
-+#define DmaBusModeInit \
-+ ( DmaLittleEndianDesc \
-+ | DmaRxAlign16 \
-+ | DmaBurstLength4 \
-+ | DmaBigEndianData \
-+ | DmaDescriptorSkip1 \
-+ | DmaReceivePriorityOn \
-+ | DmaResetOff)
-+
-+#define DmaControlInit (DmaStoreAndForward)
-+
-+/* Interrupt groups */
-+#define DmaIntEnable \
-+ ( DmaIeNormal \
-+ | DmaIeAbnormal \
-+ | DmaIntBusError \
-+ | DmaIntRxStopped \
-+ | DmaIntTxUnderflow \
-+ | DmaIntTxStopped)
-+
-+#define DmaIntDisable 0
-+
-+#define DmaAllIntCauseMask \
-+ ( DmaIeNormal \
-+ | DmaIeAbnormal \
-+ | DmaIntEarlyRx \
-+ | DmaIntBusError \
-+ | DmaIntEarlyTx \
-+ | DmaIntRxStopped \
-+ | DmaIntRxNoBuffer \
-+ | DmaIntRxCompleted \
-+ | DmaIntTxUnderflow \
-+ | DmaIntTxJabber \
-+ | DmaIntTxNoBuffer \
-+ | DmaIntTxStopped \
-+ | DmaIntTxCompleted)
-+
-+#define UnhandledIntrMask \
-+ (DmaAllIntCauseMask \
-+ & ~(DmaIntRxNoBuffer \
-+ | DmaIntTxStopped \
-+ | DmaIntTxJabber \
-+ | DmaIntTxUnderflow \
-+ | DmaIntBusError \
-+ | DmaIntRxCompleted ))
-+
-+#define DescRxErrors \
-+ (DescRxTruncated \
-+ | DescRxRunt \
-+ | DescRxLateColl \
-+ | DescRxMiiError \
-+ | DescRxCrc)
-+
-+#define DescTxErrors \
-+ ( DescTxTimeout \
-+ | DescTxLateCollision \
-+ | DescTxExcCollisions \
-+ | DescTxExcDeferral \
-+ | DescTxUnderflow)
-+
-+/**********************************************************/
-+/* Descriptor Layout */
-+/**********************************************************/
-+#define AE531X_DESC_STATUS 0x00 /* Status offset */
-+#define AE531X_DESC_CTRLEN 0x04 /* Control and Length offset */
-+#define AE531X_DESC_BUFPTR 0x08 /* Buffer pointer offset */
-+#define AE531X_DESC_LNKBUF 0x0c /* Link field offset, or ptr to 2nd buf */
-+#define AE531X_DESC_SWPTR 0x10 /* OS-Dependent software pointer */
-+
-+#define AE531X_DESC_SIZE 0x10 /* 4 words, 16 bytes */
-+#define AE531X_QUEUE_ELE_SIZE 0x14 /* with software pointer extension */
-+
-+/* Accessors to the dma descriptor fields */
-+#define AE531X_DESC_STATUS_GET(ptr) \
-+ *(volatile UINT32 *)((UINT32)(ptr) + AE531X_DESC_STATUS)
-+
-+#define AE531X_DESC_STATUS_SET(ptr, val) \
-+ AE531X_DESC_STATUS_GET(ptr) = (val)
-+
-+#define AE531X_DESC_CTRLEN_GET(ptr) \
-+ *(volatile UINT32 *)((UINT32)ptr + AE531X_DESC_CTRLEN)
-+
-+#define AE531X_DESC_CTRLEN_SET(ptr, val) \
-+ AE531X_DESC_CTRLEN_GET(ptr) = (val)
-+
-+#define AE531X_DESC_BUFPTR_GET(ptr) \
-+ *(volatile UINT32 *)((UINT32)ptr + AE531X_DESC_BUFPTR)
-+
-+#define AE531X_DESC_BUFPTR_SET(ptr,val) \
-+ AE531X_DESC_BUFPTR_GET(ptr) = (UINT32)(val)
-+
-+#define AE531X_DESC_LNKBUF_GET(ptr) \
-+ *(volatile UINT32 *)((UINT32)ptr + AE531X_DESC_LNKBUF)
-+
-+#define AE531X_DESC_LNKBUF_SET(ptr, val) \
-+ AE531X_DESC_LNKBUF_GET(ptr) = (val)
-+
-+#define AE531X_DESC_SWPTR_GET(ptr) \
-+ (void *)(*(volatile UINT32 *) ((UINT32)ptr + AE531X_DESC_SWPTR))
-+
-+#define AE531X_DESC_SWPTR_SET(ptr,val) \
-+ AE531X_DESC_SWPTR_GET(ptr) = (void *)(val)
-+
-+/* Get size of Rx data from desc, in bytes */
-+#define AE531X_DESC_STATUS_RX_SIZE(x) \
-+ (((x) & DescFrameLengthMask) >> DescFrameLengthShift)
-+
-+#endif /* _AE531XREG_H_ */
-diff -urN linux-2.4.32.new/arch/mips/ar531x/Makefile linux-2.4.32.new-eth/arch/mips/ar531x/Makefile
---- linux-2.4.32.new/arch/mips/ar531x/Makefile 2005-12-24 20:29:42.010325312 +0000
-+++ linux-2.4.32.new-eth/arch/mips/ar531x/Makefile 2005-12-25 12:03:16.213872024 +0000
-@@ -28,6 +28,13 @@
- ar531xirq.o \
- ar531xintr.o \
- ar531xgpio.o \
-- ar531xksyms.o
-+ ar531xksyms.o \
-+ ae531xlnx.o \
-+ ae531xmac.o
-
- include $(TOPDIR)/Rules.make
-+obj-$(CONFIG_MARVELL_ENET_PHY) += mvPhy.o
-+obj-$(CONFIG_KENDIN_ENET_PHY)) += rtPhy.o
-+obj-$(CONFIG_REALTEK_ENET_PHY) += rtPhy.o
-+
-+
-diff -urN linux-2.4.32.new/arch/mips/ar531x/mvPhy.c linux-2.4.32.new-eth/arch/mips/ar531x/mvPhy.c
---- linux-2.4.32.new/arch/mips/ar531x/mvPhy.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new-eth/arch/mips/ar531x/mvPhy.c 2005-12-25 11:54:39.730389448 +0000
-@@ -0,0 +1,1237 @@
-+/*
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file "COPYING" in the main directory of this archive
-+ * for more details.
-+ *
-+ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
-+ */
-+
-+/*
-+* Manage the ethernet PHY switch, Marvell 88E6060.
-+*
-+* This module is intended to be largely OS and platform-independent.
-+*/
-+
-+#if defined(linux)
-+#include <linux/config.h>
-+#include <linux/types.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/delay.h>
-+
-+#include "ar531xlnx.h"
-+#endif
-+
-+#if defined(__ECOS)
-+#include "ae531xecos.h"
-+#endif
-+
-+
-+#include "ae531xmac.h"
-+#include "ae531xreg.h"
-+#include "mvPhy.h"
-+
-+#if /* DEBUG */ 1
-+#define MV_DEBUG_ERROR 0x00000001
-+#define MV_DEBUG_PHYSETUP 0x00000002
-+#define MV_DEBUG_PHYCHANGE 0x00000004
-+
-+int mvPhyDebug = MV_DEBUG_ERROR;
-+
-+#define MV_PRINT(FLG, X) \
-+{ \
-+ if (mvPhyDebug & (FLG)) { \
-+ DEBUG_PRINTF X; \
-+ } \
-+}
-+#else
-+#define MV_PRINT(FLG, X)
-+#endif
-+
-+#ifdef CONFIG_VENETDEV
-+/*
-+ * On AR5312 with CONFIG_VENETDEV==1,
-+ * ports 0..3 are LAN ports (accessed through ae0)
-+ * port 4 is the WAN port. (accessed through ae1)
-+ *
-+ * The phy switch settings in the mvPhyInfo table are set accordingly.
-+ */
-+#define MV_WAN_PORT 4
-+#define MV_IS_LAN_PORT(port) ((port) < MV_WAN_PORT)
-+#define MV_IS_WAN_PORT(port) ((port) == MV_WAN_PORT)
-+#endif
-+
-+/*
-+ * Track per-PHY port information.
-+ */
-+typedef struct {
-+ BOOL isEnetPort; /* normal enet port */
-+ BOOL isPhyAlive; /* last known state of link */
-+ int ethUnit; /* MAC associated with this phy port */
-+ UINT32 phyBase;
-+ UINT32 phyAddr; /* PHY registers associated with this phy port */
-+ UINT32 switchPortAddr; /* switch port regs assoc'ed with this phy port */
-+ UINT32 VLANTableSetting; /* Value to be written to VLAN table */
-+} mvPhyInfo_t;
-+
-+/******************************************************************************
-+ * Per-PHY information, indexed by PHY unit number.
-+ *
-+ * This table is board-dependent. It includes information
-+ * about which enet MAC controls which PHY port.
-+ */
-+mvPhyInfo_t mvPhyInfo[] = {
-+ /*
-+ * On AP30/AR5312, all PHYs are associated with MAC0.
-+ * AP30/AR5312's MAC1 isn't used for anything.
-+ * CONFIG_VENETDEV==1 (router) configuration:
-+ * Ports 0,1,2, and 3 are "LAN ports"
-+ * Port 4 is a WAN port
-+ * Port 5 connects to MAC0 in the AR5312
-+ * CONFIG_VENETDEV==0 (bridge) configuration:
-+ * Ports 0,1,2,3,4 are "LAN ports"
-+ * Port 5 connects to the MAC0 in the AR5312
-+ */
-+ {isEnetPort: TRUE, /* phy port 0 -- LAN port 0 */
-+ isPhyAlive: FALSE,
-+ ethUnit: 0,
-+ phyBase: 0,
-+ phyAddr: 0x10,
-+ switchPortAddr: 0x18,
-+#ifdef CONFIG_VENETDEV
-+ VLANTableSetting: 0x2e
-+#else
-+ VLANTableSetting: 0x3e
-+#endif
-+ },
-+
-+ {isEnetPort: TRUE, /* phy port 1 -- LAN port 1 */
-+ isPhyAlive: FALSE,
-+ ethUnit: 0,
-+ phyBase: 0,
-+ phyAddr: 0x11,
-+ switchPortAddr: 0x19,
-+#ifdef CONFIG_VENETDEV
-+ VLANTableSetting: 0x2d
-+#else
-+ VLANTableSetting: 0x3d
-+#endif
-+ },
-+
-+ {isEnetPort: TRUE, /* phy port 2 -- LAN port 2 */
-+ isPhyAlive: FALSE,
-+ ethUnit: 0,
-+ phyBase: 0,
-+ phyAddr: 0x12,
-+ switchPortAddr: 0x1a,
-+#ifdef CONFIG_VENETDEV
-+ VLANTableSetting: 0x2b
-+#else
-+ VLANTableSetting: 0x3b
-+#endif
-+ },
-+
-+ {isEnetPort: TRUE, /* phy port 3 -- LAN port 3 */
-+ isPhyAlive: FALSE,
-+ ethUnit: 0,
-+ phyBase: 0,
-+ phyAddr: 0x13,
-+ switchPortAddr: 0x1b,
-+#ifdef CONFIG_VENETDEV
-+ VLANTableSetting: 0x27
-+#else
-+ VLANTableSetting: 0x37
-+#endif
-+ },
-+
-+ {isEnetPort: TRUE, /* phy port 4 -- WAN port or LAN port 4 */
-+ isPhyAlive: FALSE,
-+ ethUnit: 0,
-+ phyBase: 0,
-+ phyAddr: 0x14,
-+ switchPortAddr: 0x1c,
-+#ifdef CONFIG_VENETDEV
-+ VLANTableSetting: 0x1020 /* WAN port */
-+#else
-+ VLANTableSetting: 0x2f /* LAN port 4 */
-+#endif
-+ },
-+
-+ {isEnetPort: FALSE, /* phy port 5 -- CPU port (no RJ45 connector) */
-+ isPhyAlive: TRUE,
-+ ethUnit: 0,
-+ phyBase: 0,
-+ phyAddr: 0x15,
-+ switchPortAddr: 0x1d,
-+#ifdef CONFIG_VENETDEV
-+ VLANTableSetting: 0x0f /* Send only to LAN ports */
-+#else
-+ VLANTableSetting: 0x1f /* Send to all ports */
-+#endif
-+ },
-+};
-+
-+#define MV_PHY_MAX (sizeof(mvPhyInfo) / sizeof(mvPhyInfo[0]))
-+
-+/* Range of valid PHY IDs is [MIN..MAX] */
-+#define MV_ID_MIN 0
-+#define MV_ID_MAX (MV_PHY_MAX-1)
-+
-+/* Convenience macros to access myPhyInfo */
-+#define MV_IS_ENET_PORT(phyUnit) (mvPhyInfo[phyUnit].isEnetPort)
-+#define MV_IS_PHY_ALIVE(phyUnit) (mvPhyInfo[phyUnit].isPhyAlive)
-+#define MV_ETHUNIT(phyUnit) (mvPhyInfo[phyUnit].ethUnit)
-+#define MV_PHYBASE(phyUnit) (mvPhyInfo[phyUnit].phyBase)
-+#define MV_PHYADDR(phyUnit) (mvPhyInfo[phyUnit].phyAddr)
-+#define MV_SWITCH_PORT_ADDR(phyUnit) (mvPhyInfo[phyUnit].switchPortAddr)
-+#define MV_VLAN_TABLE_SETTING(phyUnit) (mvPhyInfo[phyUnit].VLANTableSetting)
-+
-+#define MV_IS_ETHUNIT(phyUnit, ethUnit) \
-+ (MV_IS_ENET_PORT(phyUnit) && \
-+ MV_ETHUNIT(phyUnit) == (ethUnit))
-+
-+
-+/* Forward references */
-+BOOL mv_phyIsLinkAlive(int phyUnit);
-+LOCAL void mv_VLANInit(int ethUnit);
-+LOCAL void mv_enableConfiguredPorts(int ethUnit);
-+LOCAL void mv_verifyReady(int ethUnit);
-+BOOL mv_phySetup(int ethUnit, UINT32 phyBase);
-+BOOL mv_phyIsFullDuplex(int ethUnit);
-+BOOL mv_phyIsSpeed100(int phyUnit);
-+LOCAL BOOL mv_validPhyId(int phyUnit);
-+void mv_flushATUDB(int phyUnit);
-+void mv_phyCheckStatusChange(int ethUnit);
-+#if DEBUG
-+void mv_phyShow(int phyUnit);
-+void mv_phySet(int phyUnit, UINT32 regnum, UINT32 value);
-+void mv_switchPortSet(int phyUnit, UINT32 regnum, UINT32 value);
-+void mv_switchGlobalSet(int phyUnit, UINT32 regnum, UINT32 value);
-+void mv_showATUDB(int phyUnit);
-+void mv_countGoodFrames(int phyUnit);
-+void mv_countBadFrames(int phyUnit);
-+void mv_showFrameCounts(int phyUnit);
-+#endif
-+
-+
-+/******************************************************************************
-+*
-+* mv_phyIsLinkAlive - test to see if the specified link is alive
-+*
-+* RETURNS:
-+* TRUE --> link is alive
-+* FALSE --> link is down
-+*/
-+BOOL
-+mv_phyIsLinkAlive(int phyUnit)
-+{
-+ UINT16 phyHwStatus;
-+ UINT32 phyBase;
-+ UINT32 phyAddr;
-+
-+ phyBase = MV_PHYBASE(phyUnit);
-+ phyAddr = MV_PHYADDR(phyUnit);
-+
-+ phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
-+
-+ if (phyHwStatus & MV_STATUS_REAL_TIME_LINK_UP) {
-+ return TRUE;
-+ } else {
-+ return FALSE;
-+ }
-+}
-+
-+/******************************************************************************
-+*
-+* mv_VLANInit - initialize "port-based VLANs" for the specified enet unit.
-+*/
-+LOCAL void
-+mv_VLANInit(int ethUnit)
-+{
-+ int phyUnit;
-+ UINT32 phyBase;
-+ UINT32 switchPortAddr;
-+
-+ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
-+ if (MV_ETHUNIT(phyUnit) != ethUnit) {
-+ continue;
-+ }
-+
-+ phyBase = MV_PHYBASE(phyUnit);
-+ switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
-+
-+ phyRegWrite(phyBase, switchPortAddr, MV_PORT_BASED_VLAN_MAP,
-+ MV_VLAN_TABLE_SETTING(phyUnit));
-+ }
-+}
-+
-+#define phyPortConfigured(phyUnit) TRUE /* TBDFREEDOM2 */
-+
-+/******************************************************************************
-+*
-+* mv_enableConfiguredPorts - enable whichever PHY ports are supposed
-+* to be enabled according to administrative configuration.
-+*/
-+LOCAL void
-+mv_enableConfiguredPorts(int ethUnit)
-+{
-+ int phyUnit;
-+ UINT32 phyBase;
-+ UINT32 switchPortAddr;
-+ UINT16 portControl;
-+ UINT16 portAssociationVector;
-+
-+ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
-+ if (MV_ETHUNIT(phyUnit) != ethUnit) {
-+ continue;
-+ }
-+
-+ phyBase = MV_PHYBASE(phyUnit);
-+ switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
-+
-+ if (phyPortConfigured(phyUnit)) {
-+
-+ portControl = MV_PORT_CONTROL_PORT_STATE_FORWARDING;
-+#ifdef CONFIG_VENETDEV
-+ if (!MV_IS_ENET_PORT(phyUnit)) { /* CPU port */
-+ portControl |= MV_PORT_CONTROL_INGRESS_TRAILER
-+ | MV_PORT_CONTROL_EGRESS_MODE;
-+ }
-+#endif
-+ phyRegWrite(phyBase, switchPortAddr, MV_PORT_CONTROL, portControl);
-+
-+ if (MV_IS_ENET_PORT(phyUnit)) {
-+ portAssociationVector = 1 << phyUnit;
-+ } else {
-+ /* Disable learning on the CPU port */
-+ portAssociationVector = 0;
-+ }
-+ phyRegWrite(phyBase, switchPortAddr,
-+ MV_PORT_ASSOCIATION_VECTOR, portAssociationVector);
-+ }
-+ }
-+}
-+
-+/******************************************************************************
-+*
-+* mv_verifyReady - validates that we're dealing with the device
-+* we think we're dealing with, and that it's ready.
-+*/
-+LOCAL void
-+mv_verifyReady(int ethUnit)
-+{
-+ int phyUnit;
-+ UINT16 globalStatus;
-+ UINT32 phyBase = 0;
-+ UINT32 phyAddr;
-+ UINT32 switchPortAddr;
-+ UINT16 phyID1;
-+ UINT16 phyID2;
-+ UINT16 switchID;
-+
-+ /*
-+ * The first read to the Phy port registers always fails and
-+ * returns 0. So get things started with a bogus read.
-+ */
-+ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
-+ if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
-+ continue;
-+ }
-+ phyBase = MV_PHYBASE(phyUnit);
-+ phyAddr = MV_PHYADDR(phyUnit);
-+
-+ (void)phyRegRead(phyBase, phyAddr, MV_PHY_ID1); /* returns 0 */
-+ break;
-+ }
-+
-+ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
-+ if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
-+ continue;
-+ }
-+
-+ /*******************/
-+ /* Verify phy port */
-+ /*******************/
-+ phyBase = MV_PHYBASE(phyUnit);
-+ phyAddr = MV_PHYADDR(phyUnit);
-+
-+ phyID1 = phyRegRead(phyBase, phyAddr, MV_PHY_ID1);
-+ if (phyID1 != MV_PHY_ID1_EXPECTATION) {
-+ MV_PRINT(MV_DEBUG_PHYSETUP,
-+ ("Invalid PHY ID1 for ethmac%d port%d. Expected 0x%04x, read 0x%04x\n",
-+ ethUnit,
-+ phyUnit,
-+ MV_PHY_ID1_EXPECTATION,
-+ phyID1));
-+ return;
-+ }
-+
-+ phyID2 = phyRegRead(phyBase, phyAddr, MV_PHY_ID2);
-+ if ((phyID2 & MV_OUI_LSB_MASK) != MV_OUI_LSB_EXPECTATION) {
-+ MV_PRINT(MV_DEBUG_PHYSETUP,
-+ ("Invalid PHY ID2 for ethmac%d port %d. Expected 0x%04x, read 0x%04x\n",
-+ ethUnit,
-+ phyUnit,
-+ MV_OUI_LSB_EXPECTATION,
-+ phyID2));
-+ return;
-+ }
-+
-+ MV_PRINT(MV_DEBUG_PHYSETUP,
-+ ("Found PHY ethmac%d port%d: model 0x%x revision 0x%x\n",
-+ ethUnit,
-+ phyUnit,
-+ (phyID2 & MV_MODEL_NUM_MASK) >> MV_MODEL_NUM_SHIFT,
-+ (phyID2 & MV_REV_NUM_MASK) >> MV_REV_NUM_SHIFT));
-+
-+
-+ /**********************/
-+ /* Verify switch port */
-+ /**********************/
-+ switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
-+
-+ switchID = phyRegRead(phyBase, switchPortAddr, MV_SWITCH_ID);
-+ if ((switchID & MV_SWITCH_ID_DEV_MASK) !=
-+ MV_SWITCH_ID_DEV_EXPECTATION) {
-+
-+ MV_PRINT(MV_DEBUG_PHYSETUP,
-+ ("Invalid switch ID for ethmac%d port %d. Expected 0x%04x, read 0x%04x\n",
-+ ethUnit,
-+ phyUnit,
-+ MV_SWITCH_ID_DEV_EXPECTATION,
-+ switchID));
-+ return;
-+ }
-+
-+ MV_PRINT(MV_DEBUG_PHYSETUP,
-+ ("Found PHY switch for enet %d port %d deviceID 0x%x revision 0x%x\n",
-+ ethUnit,
-+ phyUnit,
-+ (switchID & MV_SWITCH_ID_DEV_MASK) >> MV_SWITCH_ID_DEV_SHIFT,
-+ (switchID & MV_SWITCH_ID_REV_MASK) >> MV_SWITCH_ID_REV_SHIFT))
-+ }
-+
-+ /*******************************/
-+ /* Verify that switch is ready */
-+ /*******************************/
-+ if (phyBase) {
-+ globalStatus = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
-+ MV_SWITCH_GLOBAL_STATUS);
-+
-+ if (!(globalStatus & MV_SWITCH_STATUS_READY_MASK)) {
-+ MV_PRINT(MV_DEBUG_PHYSETUP,
-+ ("PHY switch for ethmac%d NOT ready!\n",
-+ ethUnit));
-+ }
-+ } else {
-+ MV_PRINT(MV_DEBUG_PHYSETUP,
-+ ("No ports configured for ethmac%d\n", ethUnit));
-+ }
-+}
-+
-+/******************************************************************************
-+*
-+* mv_phySetup - reset and setup the PHY switch.
-+*
-+* Resets each PHY port.
-+*
-+* RETURNS:
-+* TRUE --> at least 1 PHY with LINK
-+* FALSE --> no LINKs on this ethernet unit
-+*/
-+BOOL
-+mv_phySetup(int ethUnit, UINT32 phyBase)
-+{
-+ int phyUnit;
-+ int liveLinks = 0;
-+ BOOL foundPhy = FALSE;
-+ UINT32 phyAddr;
-+ UINT16 atuControl;
-+
-+ /*
-+ * Allow platform-specific code to determine the default Ethernet MAC
-+ * at run-time. If phyEthMacDefault returns a negative value, use the
-+ * static mvPhyInfo table "as is". But if phyEthMacDefault returns a
-+ * non-negative value, use it as the default ethernet unit.
-+ */
-+ {
-+ int ethMacDefault = phyEthMacDefault();
-+
-+ if (ethMacDefault >= 0) {
-+ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
-+ MV_ETHUNIT(phyUnit)=ethMacDefault;
-+ }
-+ }
-+ }
-+
-+ /*
-+ * See if there's any configuration data for this enet,
-+ * and set up phyBase in table.
-+ */
-+ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
-+ if (MV_ETHUNIT(phyUnit) != ethUnit) {
-+ continue;
-+ }
-+
-+ MV_PHYBASE(phyUnit) = phyBase;
-+ foundPhy = TRUE;
-+ }
-+
-+ if (!foundPhy) {
-+ return FALSE; /* No PHY's configured for this ethUnit */
-+ }
-+
-+ /* Verify that the switch is what we think it is, and that it's ready */
-+ mv_verifyReady(ethUnit);
-+
-+ /* Initialize global switch settings */
-+ atuControl = MV_ATUCTRL_AGE_TIME_DEFAULT << MV_ATUCTRL_AGE_TIME_SHIFT;
-+ atuControl |= MV_ATUCTRL_ATU_SIZE_DEFAULT << MV_ATUCTRL_ATU_SIZE_SHIFT;
-+ // atuControl |= MV_ATUCTRL_ATU_LEARNDIS;
-+ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_CONTROL, atuControl);
-+
-+ /* Reset PHYs and start autonegoation on each. */
-+ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
-+ if (MV_ETHUNIT(phyUnit) != ethUnit) {
-+ continue;
-+ }
-+
-+ phyBase = MV_PHYBASE(phyUnit);
-+ phyAddr = MV_PHYADDR(phyUnit);
-+
-+ phyRegWrite(phyBase, phyAddr, MV_PHY_CONTROL,
-+ MV_CTRL_SOFTWARE_RESET | MV_CTRL_AUTONEGOTIATION_ENABLE);
-+ }
-+
-+ {
-+ int timeout;
-+ UINT16 phyHwStatus;
-+
-+ /*
-+ * Wait 5 seconds for ALL associated PHYs to finish autonegotiation.
-+ */
-+ timeout=50;
-+ for (phyUnit=0; (phyUnit < MV_PHY_MAX) && (timeout > 0); phyUnit++) {
-+ if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
-+ continue;
-+ }
-+ for (;;) {
-+ phyBase = MV_PHYBASE(phyUnit);
-+ phyAddr = MV_PHYADDR(phyUnit);
-+
-+ phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
-+
-+ if (MV_AUTONEG_DONE(phyHwStatus)) {
-+ break;
-+ }
-+
-+ if (--timeout == 0) {
-+ break;
-+ }
-+
-+ sysMsDelay(100);
-+ }
-+ }
-+ }
-+
-+ /*
-+ * All PHYs have had adequate time to autonegotiate.
-+ * Now initialize software status.
-+ *
-+ * It's possible that some ports may take a bit longer
-+ * to autonegotiate; but we can't wait forever. They'll
-+ * get noticed by mv_phyCheckStatusChange during regular
-+ * polling activities.
-+ */
-+ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
-+ if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
-+ continue;
-+ }
-+
-+ if (mv_phyIsLinkAlive(phyUnit)) {
-+ liveLinks++;
-+ MV_IS_PHY_ALIVE(phyUnit) = TRUE;
-+#ifdef DEBUG
-+ mv_phyShow(phyUnit);
-+#endif
-+ } else {
-+ MV_IS_PHY_ALIVE(phyUnit) = FALSE;
-+ }
-+
-+ MV_PRINT(MV_DEBUG_PHYSETUP,
-+ ("ethmac%d: Phy Status=%4.4x\n",
-+ ethUnit,
-+ phyRegRead(MV_PHYBASE(phyUnit),
-+ MV_PHYADDR(phyUnit),
-+ MV_PHY_SPECIFIC_STATUS)));
-+
-+ }
-+
-+#ifdef DEBUG
-+ /* PHY 5 is the connection to the CPU */
-+ mv_phyShow(5);
-+#endif
-+
-+ mv_VLANInit(ethUnit);
-+
-+ mv_enableConfiguredPorts(ethUnit);
-+
-+ return (liveLinks > 0);
-+}
-+
-+
-+/******************************************************************************
-+*
-+* mv_phyIsDuplexFull - Determines whether the phy ports associated with the
-+* specified device are FULL or HALF duplex.
-+*
-+* RETURNS:
-+* TRUE --> at least one associated PHY in FULL DUPLEX
-+* FALSE --> all half duplex, or no links
-+*/
-+BOOL
-+mv_phyIsFullDuplex(int ethUnit)
-+{
-+ int phyUnit;
-+ UINT32 phyBase;
-+ UINT32 phyAddr;
-+ UINT16 phyHwStatus;
-+
-+ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
-+
-+ if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
-+ continue;
-+ }
-+
-+ if (mv_phyIsLinkAlive(phyUnit)) {
-+
-+ phyBase = MV_PHYBASE(phyUnit);
-+ phyAddr = MV_PHYADDR(phyUnit);
-+
-+ phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
-+
-+ if (phyHwStatus & MV_STATUS_RESOLVED_DUPLEX_FULL) {
-+ return TRUE;
-+ }
-+ }
-+ }
-+
-+ return FALSE;
-+}
-+
-+/******************************************************************************
-+*
-+* mv_phyIsSpeed100 - Determines the speed of a phy port
-+*
-+* RETURNS:
-+* TRUE --> PHY operating at 100 Mbit
-+* FALSE --> link down, or not operating at 100 Mbit
-+*/
-+BOOL
-+mv_phyIsSpeed100(int phyUnit)
-+{
-+ UINT16 phyHwStatus;
-+ UINT32 phyBase;
-+ UINT32 phyAddr;
-+
-+ if (MV_IS_ENET_PORT(phyUnit)) {
-+ if (mv_phyIsLinkAlive(phyUnit)) {
-+
-+ phyBase = MV_PHYBASE(phyUnit);
-+ phyAddr = MV_PHYADDR(phyUnit);
-+
-+ phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
-+
-+ if (phyHwStatus & MV_STATUS_RESOLVED_SPEED_100) {
-+ return TRUE;
-+ }
-+ }
-+ }
-+
-+ return FALSE;
-+}
-+
-+#ifdef CONFIG_VENETDEV
-+/******************************************************************************
-+*
-+* mv_phyDetermineSource - Examine a received frame's Egress Trailer
-+* to determine whether it came from a LAN or WAN port.
-+*
-+* RETURNS:
-+* Returns 1-->LAN, 0-->WAN, -1-->ERROR
-+*/
-+int
-+mv_phyDetermineSource(char *data, int len)
-+{
-+ unsigned char *phyTrailer;
-+ unsigned char incomingPort;
-+
-+ phyTrailer = &data[len - MV_PHY_TRAILER_SIZE];
-+
-+ /* ASSERT(phyTrailer[0] == MV_EGRESS_TRAILER_VALID); */
-+ if (phyTrailer[0] != MV_EGRESS_TRAILER_VALID) {
-+ printk(KERN_ERR "PHY trailer invalid; got %#02x, expected %#02x\n",
-+ phyTrailer[0], MV_EGRESS_TRAILER_VALID);
-+ return -1;
-+ }
-+
-+ incomingPort = phyTrailer[1];
-+ if (MV_IS_LAN_PORT(incomingPort)) {
-+ return 1;
-+ } else {
-+ /* ASSERT(MV_IS_WAN_PORT(incomingPort)); */
-+ if (!MV_IS_WAN_PORT(incomingPort)) {
-+ printk(KERN_ERR "incoming port was %d; expected 0-4\n", incomingPort);
-+ return -1;
-+ }
-+ return 0;
-+ }
-+}
-+
-+
-+/******************************************************************************
-+*
-+* mv_phySetDestinationPort - Set the Ingress Trailer to force the
-+* frame to be sent to LAN or WAN, as specified.
-+*
-+*/
-+void
-+mv_phySetDestinationPort(char *data, int len, int fromLAN)
-+{
-+ char *phyTrailer;
-+
-+ phyTrailer = &data[len];
-+ if (fromLAN) {
-+ /* LAN ports: Use default settings, as per mvPhyInfo */
-+ phyTrailer[0] = 0x00;
-+ phyTrailer[1] = 0x00;
-+ } else {
-+ /* WAN port: Direct to WAN port */
-+ phyTrailer[0] = MV_INGRESS_TRAILER_OVERRIDE;
-+ phyTrailer[1] = 1 << MV_WAN_PORT;
-+ }
-+ phyTrailer[2] = 0x00;
-+ phyTrailer[3] = 0x00;
-+}
-+#endif
-+
-+
-+/*****************************************************************************
-+*
-+* Validate that the specified PHY unit number is a valid PHY ID.
-+* Print a message if it is invalid.
-+* RETURNS
-+* TRUE --> valid
-+* FALSE --> invalid
-+*/
-+LOCAL BOOL
-+mv_validPhyId(int phyUnit)
-+{
-+ if ((phyUnit >= MV_ID_MIN) && (phyUnit <= MV_ID_MAX)) {
-+ return TRUE;
-+ } else {
-+ PRINTF("PHY unit number must be in the range [%d..%d]\n",
-+ MV_ID_MIN, MV_ID_MAX);
-+ return FALSE;
-+ }
-+}
-+
-+
-+/*****************************************************************************
-+*
-+* mv_waitWhileATUBusy - spins until the ATU completes
-+* its previous operation.
-+*/
-+LOCAL void
-+mv_waitWhileATUBusy(UINT32 phyBase)
-+{
-+ BOOL isBusy;
-+ UINT16 ATUOperation;
-+
-+ do {
-+
-+ ATUOperation = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
-+ MV_ATU_OPERATION);
-+
-+ isBusy = (ATUOperation & MV_ATU_BUSY_MASK) == MV_ATU_IS_BUSY;
-+
-+ } while(isBusy);
-+}
-+
-+/*****************************************************************************
-+*
-+* mv_flushATUDB - flushes ALL entries in the Address Translation Unit
-+* DataBase associated with phyUnit. [Since we use a single DB for
-+* all PHYs, this flushes the entire shared DataBase.]
-+*
-+* The current implementation flushes even more than absolutely needed --
-+* it flushes all entries for all phyUnits on the same ethernet as the
-+* specified phyUnit.
-+*
-+* It is called only when a link failure is detected on a port that was
-+* previously working. In other words, when the cable is unplugged.
-+*/
-+void
-+mv_flushATUDB(int phyUnit)
-+{
-+ UINT32 phyBase;
-+
-+ if (!mv_validPhyId(phyUnit)) {
-+ PRINTF("Invalid port number: %d\n", phyUnit);
-+ return;
-+ }
-+
-+ phyBase = MV_PHYBASE(phyUnit);
-+
-+ /* Wait for previous operation (if any) to complete */
-+ mv_waitWhileATUBusy(phyBase);
-+
-+ /* Tell hardware to flush all entries */
-+ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_OPERATION,
-+ MV_ATU_OP_FLUSH_ALL | MV_ATU_IS_BUSY);
-+
-+ mv_waitWhileATUBusy(phyBase);
-+}
-+
-+/*****************************************************************************
-+*
-+* mv_phyCheckStatusChange -- checks for significant changes in PHY state.
-+*
-+* A "significant change" is:
-+* dropped link (e.g. ethernet cable unplugged) OR
-+* autonegotiation completed + link (e.g. ethernet cable plugged in)
-+*/
-+void
-+mv_phyCheckStatusChange(int ethUnit)
-+{
-+ int phyUnit;
-+ UINT16 phyHwStatus;
-+ mvPhyInfo_t *lastStatus;
-+ int linkCount = 0;
-+ int lostLinks = 0;
-+ int gainedLinks = 0;
-+ UINT32 phyBase;
-+ UINT32 phyAddr;
-+
-+ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
-+ if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
-+ continue;
-+ }
-+
-+ phyBase = MV_PHYBASE(phyUnit);
-+ phyAddr = MV_PHYADDR(phyUnit);
-+
-+ lastStatus = &mvPhyInfo[phyUnit];
-+ phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
-+
-+ if (lastStatus->isPhyAlive) { /* last known link status was ALIVE */
-+ /* See if we've lost link */
-+ if (phyHwStatus & MV_STATUS_REAL_TIME_LINK_UP) {
-+ linkCount++;
-+ } else {
-+ lostLinks++;
-+ mv_flushATUDB(phyUnit);
-+ MV_PRINT(MV_DEBUG_PHYCHANGE,("\nethmac%d port%d down\n",
-+ ethUnit, phyUnit));
-+ lastStatus->isPhyAlive = FALSE;
-+ }
-+ } else { /* last known link status was DEAD */
-+ /* Check for AutoNegotiation complete */
-+ if (MV_AUTONEG_DONE(phyHwStatus)) {
-+ gainedLinks++;
-+ linkCount++;
-+ MV_PRINT(MV_DEBUG_PHYCHANGE,("\nethmac%d port%d up\n",
-+ ethUnit, phyUnit));
-+ lastStatus->isPhyAlive = TRUE;
-+ }
-+ }
-+ }
-+
-+ if (linkCount == 0) {
-+ if (lostLinks) {
-+ /* We just lost the last link for this MAC */
-+ phyLinkLost(ethUnit);
-+ }
-+ } else {
-+ if (gainedLinks == linkCount) {
-+ /* We just gained our first link(s) for this MAC */
-+ phyLinkGained(ethUnit);
-+ }
-+ }
-+}
-+
-+#if DEBUG
-+
-+/* Define the registers of interest for a phyShow command */
-+typedef struct mvRegisterTableEntry_s {
-+ UINT32 regNum;
-+ char *regIdString;
-+} mvRegisterTableEntry_t;
-+
-+mvRegisterTableEntry_t mvPhyRegisterTable[] = {
-+ {MV_PHY_CONTROL, "PHY Control "},
-+ {MV_PHY_STATUS, "PHY Status "},
-+ {MV_PHY_ID1, "PHY Identifier 1 "},
-+ {MV_PHY_ID2, "PHY Identifier 2 "},
-+ {MV_AUTONEG_ADVERT, "Auto-Negotiation Advertisement "},
-+ {MV_LINK_PARTNER_ABILITY, "Link Partner Ability "},
-+ {MV_AUTONEG_EXPANSION, "Auto-Negotiation Expansion "},
-+ {MV_NEXT_PAGE_TRANSMIT, "Next Page Transmit "},
-+ {MV_LINK_PARTNER_NEXT_PAGE, "Link Partner Next Page "},
-+ {MV_PHY_SPECIFIC_CONTROL_1, "PHY-Specific Control Register 1 "},
-+ {MV_PHY_SPECIFIC_STATUS, "PHY-Specific Status "},
-+ {MV_PHY_INTERRUPT_ENABLE, "PHY Interrupt Enable "},
-+ {MV_PHY_INTERRUPT_STATUS, "PHY Interrupt Status "},
-+ {MV_PHY_INTERRUPT_PORT_SUMMARY, "PHY Interrupt Port Summary "},
-+ {MV_RECEIVE_ERROR_COUNTER, "Receive Error Counter "},
-+ {MV_LED_PARALLEL_SELECT, "LED Parallel Select "},
-+ {MV_LED_STREAM_SELECT_LEDS, "LED Stream Select "},
-+ {MV_PHY_LED_CONTROL, "PHY LED Control "},
-+ {MV_PHY_MANUAL_LED_OVERRIDE, "PHY Manual LED Override "},
-+ {MV_VCT_CONTROL, "VCT Control "},
-+ {MV_VCT_STATUS, "VCT Status "},
-+ {MV_PHY_SPECIFIC_CONTROL_2, "PHY-Specific Control Register 2 "},
-+};
-+int mvPhyNumRegs = sizeof(mvPhyRegisterTable) / sizeof(mvPhyRegisterTable[0]);
-+
-+
-+mvRegisterTableEntry_t mvSwitchPortRegisterTable[] = {
-+ {MV_PORT_STATUS, "Port Status "},
-+ {MV_SWITCH_ID, "Switch ID "},
-+ {MV_PORT_CONTROL, "Port Control "},
-+ {MV_PORT_BASED_VLAN_MAP, "Port-Based VLAN Map "},
-+ {MV_PORT_ASSOCIATION_VECTOR, "Port Association Vector "},
-+ {MV_RX_COUNTER, "RX Counter "},
-+ {MV_TX_COUNTER, "TX Counter "},
-+};
-+int mvSwitchPortNumRegs =
-+ sizeof(mvSwitchPortRegisterTable) / sizeof(mvSwitchPortRegisterTable[0]);
-+
-+
-+mvRegisterTableEntry_t mvSwitchGlobalRegisterTable[] = {
-+ {MV_SWITCH_GLOBAL_STATUS, "Switch Global Status "},
-+ {MV_SWITCH_MAC_ADDR0, "Switch MAC Addr 0 & 1 "},
-+ {MV_SWITCH_MAC_ADDR2, "Switch MAC Addr 2 & 3 "},
-+ {MV_SWITCH_MAC_ADDR4, "Switch MAC Addr 4 & 5 "},
-+ {MV_SWITCH_GLOBAL_CONTROL, "Switch Global Control "},
-+ {MV_ATU_CONTROL, "ATU Control "},
-+ {MV_ATU_OPERATION, "ATU Operation "},
-+ {MV_ATU_DATA, "ATU Data "},
-+ {MV_ATU_MAC_ADDR0, "ATU MAC Addr 0 & 1 "},
-+ {MV_ATU_MAC_ADDR2, "ATU MAC Addr 2 & 3 "},
-+ {MV_ATU_MAC_ADDR4, "ATU MAC Addr 4 & 5 "},
-+};
-+int mvSwitchGlobalNumRegs =
-+ sizeof(mvSwitchGlobalRegisterTable) / sizeof(mvSwitchGlobalRegisterTable[0]);
-+
-+
-+/*****************************************************************************
-+*
-+* mv_phyShow - Dump the state of a PHY.
-+* There are two sets of registers for each phy port:
-+* "phy registers" and
-+* "switch port registers"
-+* We dump 'em all, plus the switch global registers.
-+*/
-+void
-+mv_phyShow(int phyUnit)
-+{
-+ int i;
-+ UINT16 value;
-+ UINT32 phyBase;
-+ UINT32 phyAddr;
-+ UINT32 switchPortAddr;
-+
-+ if (!mv_validPhyId(phyUnit)) {
-+ return;
-+ }
-+
-+ phyBase = MV_PHYBASE(phyUnit);
-+ phyAddr = MV_PHYADDR(phyUnit);
-+ switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
-+
-+ PRINTF("PHY state for PHY%d (ethmac%d, phyBase 0x%8x, phyAddr 0x%x, switchAddr 0x%x)\n",
-+ phyUnit,
-+ MV_ETHUNIT(phyUnit),
-+ MV_PHYBASE(phyUnit),
-+ MV_PHYADDR(phyUnit),
-+ MV_SWITCH_PORT_ADDR(phyUnit));
-+
-+ PRINTF("PHY Registers:\n");
-+ for (i=0; i < mvPhyNumRegs; i++) {
-+
-+ value = phyRegRead(phyBase, phyAddr, mvPhyRegisterTable[i].regNum);
-+
-+ PRINTF("Reg %02d (0x%02x) %s = 0x%08x\n",
-+ mvPhyRegisterTable[i].regNum,
-+ mvPhyRegisterTable[i].regNum,
-+ mvPhyRegisterTable[i].regIdString,
-+ value);
-+ }
-+
-+ PRINTF("Switch Port Registers:\n");
-+ for (i=0; i < mvSwitchPortNumRegs; i++) {
-+
-+ value = phyRegRead(phyBase, switchPortAddr,
-+ mvSwitchPortRegisterTable[i].regNum);
-+
-+ PRINTF("Reg %02d (0x%02x) %s = 0x%08x\n",
-+ mvSwitchPortRegisterTable[i].regNum,
-+ mvSwitchPortRegisterTable[i].regNum,
-+ mvSwitchPortRegisterTable[i].regIdString,
-+ value);
-+ }
-+
-+ PRINTF("Switch Global Registers:\n");
-+ for (i=0; i < mvSwitchGlobalNumRegs; i++) {
-+
-+ value = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
-+ mvSwitchGlobalRegisterTable[i].regNum);
-+
-+ PRINTF("Reg %02d (0x%02x) %s = 0x%08x\n",
-+ mvSwitchGlobalRegisterTable[i].regNum,
-+ mvSwitchGlobalRegisterTable[i].regNum,
-+ mvSwitchGlobalRegisterTable[i].regIdString,
-+ value);
-+ }
-+}
-+
-+/*****************************************************************************
-+*
-+* mv_phySet - Modify the value of a PHY register (debug only).
-+*/
-+void
-+mv_phySet(int phyUnit, UINT32 regnum, UINT32 value)
-+{
-+ UINT32 phyBase;
-+ UINT32 phyAddr;
-+
-+ if (mv_validPhyId(phyUnit)) {
-+
-+ phyBase = MV_PHYBASE(phyUnit);
-+ phyAddr = MV_PHYADDR(phyUnit);
-+
-+ phyRegWrite(phyBase, phyAddr, regnum, value);
-+ }
-+}
-+
-+
-+/*****************************************************************************
-+*
-+* mv_switchPortSet - Modify the value of a switch port register (debug only).
-+*/
-+void
-+mv_switchPortSet(int phyUnit, UINT32 regnum, UINT32 value)
-+{
-+ UINT32 phyBase;
-+ UINT32 switchPortAddr;
-+
-+ if (mv_validPhyId(phyUnit)) {
-+
-+ phyBase = MV_PHYBASE(phyUnit);
-+ switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
-+
-+ phyRegWrite(phyBase, switchPortAddr, regnum, value);
-+ }
-+}
-+
-+/*****************************************************************************
-+*
-+* mv_switchGlobalSet - Modify the value of a switch global register
-+* (debug only).
-+*/
-+void
-+mv_switchGlobalSet(int phyUnit, UINT32 regnum, UINT32 value)
-+{
-+ UINT32 phyBase;
-+
-+ if (mv_validPhyId(phyUnit)) {
-+
-+ phyBase = MV_PHYBASE(phyUnit);
-+
-+ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, regnum, value);
-+ }
-+}
-+
-+/*****************************************************************************
-+*
-+* mv_showATUDB - Dump the contents of the Address Translation Unit DataBase
-+* for the PHY switch associated with the specified phy.
-+*/
-+void
-+mv_showATUDB(int phyUnit)
-+{
-+ UINT32 phyBase;
-+ UINT16 ATUData;
-+ UINT16 ATUMac0;
-+ UINT16 ATUMac2;
-+ UINT16 ATUMac4;
-+ int portVec;
-+ int entryState;
-+
-+ if (!mv_validPhyId(phyUnit)) {
-+ PRINTF("Invalid port number: %d\n", phyUnit);
-+ return;
-+ }
-+
-+ phyBase = MV_PHYBASE(phyUnit);
-+
-+ /* Wait for previous operation (if any) to complete */
-+ mv_waitWhileATUBusy(phyBase);
-+
-+ /* Initialize ATU MAC to all 1's */
-+ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR0, 0xffff);
-+ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR2, 0xffff);
-+ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR4, 0xffff);
-+
-+ PRINTF(" MAC ADDRESS EntryState PortVector\n");
-+
-+ for(;;) {
-+ /* Tell hardware to get next MAC info */
-+ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_OPERATION,
-+ MV_ATU_OP_GET_NEXT | MV_ATU_IS_BUSY);
-+
-+ mv_waitWhileATUBusy(phyBase);
-+
-+ ATUData = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_DATA);
-+ entryState = (ATUData & MV_ENTRYSTATE_MASK) >> MV_ENTRYSTATE_SHIFT;
-+
-+ if (entryState == 0) {
-+ /* We've hit the end of the list */
-+ break;
-+ }
-+
-+ ATUMac0 = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR0);
-+ ATUMac2 = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR2);
-+ ATUMac4 = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR4);
-+
-+ portVec = (ATUData & MV_PORTVEC_MASK) >> MV_PORTVEC_SHIFT;
-+
-+ PRINTF("%02x:%02x:%02x:%02x:%02x:%02x 0x%02x 0x%02x\n",
-+ ATUMac0 >> 8, /* MAC byte 0 */
-+ ATUMac0 & 0xff, /* MAC byte 1 */
-+ ATUMac2 >> 8, /* MAC byte 2 */
-+ ATUMac2 & 0xff, /* MAC byte 3 */
-+ ATUMac4 >> 8, /* MAC byte 4 */
-+ ATUMac4 & 0xff, /* MAC byte 5 */
-+ entryState,
-+ portVec);
-+ }
-+}
-+
-+LOCAL BOOL countingGoodFrames;
-+
-+/*****************************************************************************
-+*
-+* mv_countGoodFrames - starts counting GOOD RX/TX frames per port
-+*/
-+void
-+mv_countGoodFrames(int phyUnit)
-+{
-+ UINT32 phyBase;
-+ UINT16 globalControl;
-+
-+ if (mv_validPhyId(phyUnit)) {
-+ /*
-+ * Guarantee that counters are cleared by
-+ * forcing CtrMode to toggle and end on GOODFRAMES.
-+ */
-+
-+ phyBase = MV_PHYBASE(phyUnit);
-+
-+ /* Read current Switch Global Control Register */
-+ globalControl = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
-+ MV_SWITCH_GLOBAL_CONTROL);
-+
-+ /* Set CtrMode to count BAD frames */
-+ globalControl = ((globalControl & ~MV_CTRMODE_MASK) |
-+ MV_CTRMODE_BADFRAMES);
-+
-+ /* Push new value out to hardware */
-+ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR,
-+ MV_SWITCH_GLOBAL_CONTROL, globalControl);
-+
-+ /* Now toggle CtrMode to count GOOD frames */
-+ globalControl = ((globalControl & ~MV_CTRMODE_MASK) |
-+ MV_CTRMODE_GOODFRAMES);
-+
-+ /* Push new value out to hardware */
-+ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR,
-+ MV_SWITCH_GLOBAL_CONTROL, globalControl);
-+
-+ countingGoodFrames = TRUE;
-+ }
-+}
-+
-+/*****************************************************************************
-+*
-+* mv_countBadFrames - starts counting BAD RX/TX frames per port
-+*/
-+void
-+mv_countBadFrames(int phyUnit)
-+{
-+ UINT32 phyBase;
-+ UINT16 globalControl;
-+
-+ if (mv_validPhyId(phyUnit)) {
-+ /*
-+ * Guarantee that counters are cleared by
-+ * forcing CtrMode to toggle and end on BADFRAMES.
-+ */
-+
-+ phyBase = MV_PHYBASE(phyUnit);
-+
-+ /* Read current Switch Global Control Register */
-+ globalControl = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
-+ MV_SWITCH_GLOBAL_CONTROL);
-+
-+ /* Set CtrMode to count GOOD frames */
-+ globalControl = ((globalControl & ~MV_CTRMODE_MASK) |
-+ MV_CTRMODE_GOODFRAMES);
-+
-+ /* Push new value out to hardware */
-+ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR,
-+ MV_SWITCH_GLOBAL_CONTROL, globalControl);
-+
-+ /* Now toggle CtrMode to count BAD frames */
-+ globalControl = ((globalControl & ~MV_CTRMODE_MASK) |
-+ MV_CTRMODE_BADFRAMES);
-+
-+ /* Push new value out to hardware */
-+ phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR,
-+ MV_SWITCH_GLOBAL_CONTROL, globalControl);
-+
-+ countingGoodFrames = FALSE;
-+ }
-+}
-+
-+/*****************************************************************************
-+*
-+* mv_showFrameCounts - shows current GOOD/BAD Frame counts
-+*/
-+void
-+mv_showFrameCounts(int phyUnit)
-+{
-+ UINT16 rxCounter;
-+ UINT16 txCounter;
-+ UINT32 phyBase;
-+ UINT32 switchPortAddr;
-+
-+ if (!mv_validPhyId(phyUnit)) {
-+ return;
-+ }
-+
-+ phyBase = MV_PHYBASE(phyUnit);
-+ switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
-+
-+ rxCounter = phyRegRead(phyBase, switchPortAddr, MV_RX_COUNTER);
-+
-+ txCounter = phyRegRead(phyBase, switchPortAddr, MV_TX_COUNTER);
-+
-+ PRINTF("port%d %s frames: receive: %05d transmit: %05d\n",
-+ phyUnit,
-+ (countingGoodFrames ? "good" : "error"),
-+ rxCounter,
-+ txCounter);
-+}
-+#endif
-diff -urN linux-2.4.32.new/arch/mips/ar531x/mvPhy.h linux-2.4.32.new-eth/arch/mips/ar531x/mvPhy.h
---- linux-2.4.32.new/arch/mips/ar531x/mvPhy.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new-eth/arch/mips/ar531x/mvPhy.h 2005-12-25 11:54:39.775382608 +0000
-@@ -0,0 +1,160 @@
-+/*
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file "COPYING" in the main directory of this archive
-+ * for more details.
-+ *
-+ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
-+ */
-+
-+/*
-+ * mvPhy.h - definitions for the ethernet PHY -- Marvell 88E6060
-+ * All definitions in this file are operating system independent!
-+ */
-+
-+#ifndef MVPHY_H
-+#define MVPHY_H
-+
-+/*****************/
-+/* PHY Registers */
-+/*****************/
-+#define MV_PHY_CONTROL 0
-+#define MV_PHY_STATUS 1
-+#define MV_PHY_ID1 2
-+#define MV_PHY_ID2 3
-+#define MV_AUTONEG_ADVERT 4
-+#define MV_LINK_PARTNER_ABILITY 5
-+#define MV_AUTONEG_EXPANSION 6
-+#define MV_NEXT_PAGE_TRANSMIT 7
-+#define MV_LINK_PARTNER_NEXT_PAGE 8
-+#define MV_PHY_SPECIFIC_CONTROL_1 16
-+#define MV_PHY_SPECIFIC_STATUS 17
-+#define MV_PHY_INTERRUPT_ENABLE 18
-+#define MV_PHY_INTERRUPT_STATUS 19
-+#define MV_PHY_INTERRUPT_PORT_SUMMARY 20
-+#define MV_RECEIVE_ERROR_COUNTER 21
-+#define MV_LED_PARALLEL_SELECT 22
-+#define MV_LED_STREAM_SELECT_LEDS 23
-+#define MV_PHY_LED_CONTROL 24
-+#define MV_PHY_MANUAL_LED_OVERRIDE 25
-+#define MV_VCT_CONTROL 26
-+#define MV_VCT_STATUS 27
-+#define MV_PHY_SPECIFIC_CONTROL_2 28
-+
-+/* MV_PHY_CONTROL fields */
-+#define MV_CTRL_SOFTWARE_RESET 0x8000
-+#define MV_CTRL_AUTONEGOTIATION_ENABLE 0x1000
-+
-+/* MV_PHY_ID1 fields */
-+#define MV_PHY_ID1_EXPECTATION 0x0141 /* OUI >> 6 */
-+
-+/* MV_PHY_ID2 fields */
-+#define MV_OUI_LSB_MASK 0xfc00
-+#define MV_OUI_LSB_EXPECTATION 0x0c00
-+#define MV_OUI_LSB_SHIFT 10
-+#define MV_MODEL_NUM_MASK 0x03f0
-+#define MV_MODEL_NUM_SHIFT 4
-+#define MV_REV_NUM_MASK 0x000f
-+#define MV_REV_NUM_SHIFT 0
-+
-+/* MV_PHY_SPECIFIC_STATUS fields */
-+#define MV_STATUS_RESOLVED_SPEED_100 0x4000
-+#define MV_STATUS_RESOLVED_DUPLEX_FULL 0x2000
-+#define MV_STATUS_RESOLVED 0x0800
-+#define MV_STATUS_REAL_TIME_LINK_UP 0x0400
-+
-+/* Check if autonegotiation is complete and link is up */
-+#define MV_AUTONEG_DONE(mv_phy_specific_status) \
-+ (((mv_phy_specific_status) & \
-+ (MV_STATUS_RESOLVED | MV_STATUS_REAL_TIME_LINK_UP)) == \
-+ (MV_STATUS_RESOLVED | MV_STATUS_REAL_TIME_LINK_UP))
-+
-+
-+/*************************/
-+/* Switch Port Registers */
-+/*************************/
-+#define MV_PORT_STATUS 0
-+#define MV_SWITCH_ID 3
-+#define MV_PORT_CONTROL 4
-+#define MV_PORT_BASED_VLAN_MAP 6
-+#define MV_PORT_ASSOCIATION_VECTOR 11
-+#define MV_RX_COUNTER 16
-+#define MV_TX_COUNTER 17
-+
-+/* MV_SWITCH_ID fields */
-+#define MV_SWITCH_ID_DEV_MASK 0xfff0
-+#define MV_SWITCH_ID_DEV_EXPECTATION 0x0600
-+#define MV_SWITCH_ID_DEV_SHIFT 4
-+#define MV_SWITCH_ID_REV_MASK 0x000f
-+#define MV_SWITCH_ID_REV_SHIFT 0
-+
-+/* MV_PORT_CONTROL fields */
-+#define MV_PORT_CONTROL_PORT_STATE_MASK 0x0003
-+#define MV_PORT_CONTROL_PORT_STATE_DISABLED 0x0000
-+#define MV_PORT_CONTROL_PORT_STATE_FORWARDING 0x0003
-+
-+#define MV_PORT_CONTROL_EGRESS_MODE 0x0100 /* Receive */
-+#define MV_PORT_CONTROL_INGRESS_TRAILER 0x4000 /* Transmit */
-+
-+#define MV_EGRESS_TRAILER_VALID 0x80
-+#define MV_INGRESS_TRAILER_OVERRIDE 0x80
-+
-+#define MV_PHY_TRAILER_SIZE 4
-+
-+
-+/***************************/
-+/* Switch Global Registers */
-+/***************************/
-+#define MV_SWITCH_GLOBAL_STATUS 0
-+#define MV_SWITCH_MAC_ADDR0 1
-+#define MV_SWITCH_MAC_ADDR2 2
-+#define MV_SWITCH_MAC_ADDR4 3
-+#define MV_SWITCH_GLOBAL_CONTROL 4
-+#define MV_ATU_CONTROL 10
-+#define MV_ATU_OPERATION 11
-+#define MV_ATU_DATA 12
-+#define MV_ATU_MAC_ADDR0 13
-+#define MV_ATU_MAC_ADDR2 14
-+#define MV_ATU_MAC_ADDR4 15
-+
-+/* MV_SWITCH_GLOBAL_STATUS fields */
-+#define MV_SWITCH_STATUS_READY_MASK 0x0800
-+
-+/* MV_SWITCH_GLOBAL_CONTROL fields */
-+#define MV_CTRMODE_MASK 0x0100
-+#define MV_CTRMODE_GOODFRAMES 0x0000
-+#define MV_CTRMODE_BADFRAMES 0x0100
-+
-+/* MV_ATU_CONTROL fields */
-+#define MV_ATUCTRL_ATU_LEARNDIS 0x4000
-+#define MV_ATUCTRL_ATU_SIZE_MASK 0x3000
-+#define MV_ATUCTRL_ATU_SIZE_SHIFT 12
-+#define MV_ATUCTRL_ATU_SIZE_DEFAULT 2 /* 1024 entry database */
-+#define MV_ATUCTRL_AGE_TIME_MASK 0x0ff0
-+#define MV_ATUCTRL_AGE_TIME_SHIFT 4
-+#define MV_ATUCTRL_AGE_TIME_DEFAULT 19 /* 19 * 16 = 304 seconds */
-+
-+/* MV_ATU_OPERATION fields */
-+#define MV_ATU_BUSY_MASK 0x8000
-+#define MV_ATU_IS_BUSY 0x8000
-+#define MV_ATU_IS_FREE 0x0000
-+#define MV_ATU_OP_MASK 0x7000
-+#define MV_ATU_OP_FLUSH_ALL 0x1000
-+#define MV_ATU_OP_GET_NEXT 0x4000
-+
-+/* MV_ATU_DATA fields */
-+#define MV_ENTRYPRI_MASK 0xc000
-+#define MV_ENTRYPRI_SHIFT 14
-+#define MV_PORTVEC_MASK 0x03f0
-+#define MV_PORTVEC_SHIFT 4
-+#define MV_ENTRYSTATE_MASK 0x000f
-+#define MV_ENTRYSTATE_SHIFT 0
-+
-+/* PHY Address for the switch itself */
-+#define MV_SWITCH_GLOBAL_ADDR 0x1f
-+
-+BOOL mv_phySetup(int ethUnit, UINT32 phyBase);
-+void mv_phyCheckStatusChange(int ethUnit);
-+BOOL mv_phyIsSpeed100(int ethUnit);
-+BOOL mv_phyIsFullDuplex(int ethUnit);
-+
-+#endif /* MVPHY_H */
-diff -urN linux-2.4.32.new/arch/mips/ar531x/rtPhy.c linux-2.4.32.new-eth/arch/mips/ar531x/rtPhy.c
---- linux-2.4.32.new/arch/mips/ar531x/rtPhy.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new-eth/arch/mips/ar531x/rtPhy.c 2005-12-25 11:54:46.086423184 +0000
-@@ -0,0 +1,272 @@
-+/*
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file "COPYING" in the main directory of this archive
-+ * for more details.
-+ *
-+ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
-+ */
-+
-+/*
-+ * Manage the ethernet PHY.
-+ * This code supports a simple 1-port ethernet phy, Realtek RTL8201BL,
-+ * and compatible PHYs, such as the Kendin KS8721B.
-+ * All definitions in this file are operating system independent!
-+ */
-+
-+#if defined(linux)
-+#include <linux/config.h>
-+#include <linux/types.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/delay.h>
-+
-+#include "ar531xlnx.h"
-+#endif
-+
-+#if defined(__ECOS)
-+#include "ae531xecos.h"
-+#endif
-+
-+
-+#include "ae531xmac.h"
-+#include "ae531xreg.h"
-+#include "rtPhy.h"
-+
-+#if /* DEBUG */ 1
-+#define RT_DEBUG_ERROR 0x00000001
-+#define RT_DEBUG_PHYSETUP 0x00000002
-+#define RT_DEBUG_PHYCHANGE 0x00000004
-+
-+int rtPhyDebug = RT_DEBUG_ERROR;
-+
-+#define RT_PRINT(FLG, X) \
-+{ \
-+ if (rtPhyDebug & (FLG)) { \
-+ DEBUG_PRINTF X; \
-+ } \
-+}
-+#else
-+#define RT_PRINT(FLG, X)
-+#endif
-+
-+/*
-+ * Track per-PHY port information.
-+ */
-+typedef struct {
-+ BOOL phyAlive; /* last known state of link */
-+ UINT32 phyBase;
-+ UINT32 phyAddr;
-+} rtPhyInfo_t;
-+
-+#define ETH_PHY_ADDR 1
-+
-+/*
-+ * This table defines the mapping from phy units to
-+ * per-PHY information.
-+ *
-+ * This table is somewhat board-dependent.
-+ */
-+rtPhyInfo_t rtPhyInfo[] = {
-+ {phyAlive: FALSE, /* PHY 0 */
-+ phyBase: 0, /* filled in by rt_phySetup */
-+ phyAddr: ETH_PHY_ADDR},
-+
-+ {phyAlive: FALSE, /* PHY 1 */
-+ phyBase: 0, /* filled in by rt_phySetup */
-+ phyAddr: ETH_PHY_ADDR}
-+};
-+
-+/* Convert from phy unit# to (phyBase, phyAddr) pair */
-+#define RT_PHYBASE(phyUnit) (rtPhyInfo[phyUnit].phyBase)
-+#define RT_PHYADDR(phyUnit) (rtPhyInfo[phyUnit].phyAddr)
-+
-+
-+/******************************************************************************
-+*
-+* rt_phySetup - reset and setup the PHY associated with
-+* the specified MAC unit number.
-+*
-+* Resets the associated PHY port.
-+*
-+* RETURNS:
-+* TRUE --> associated PHY is alive
-+* FALSE --> no LINKs on this ethernet unit
-+*/
-+
-+BOOL
-+rt_phySetup(int ethUnit, UINT32 phyBase)
-+{
-+ BOOL linkAlive = FALSE;
-+ UINT32 phyAddr;
-+
-+ RT_PHYBASE(ethUnit) = phyBase;
-+
-+ phyAddr = RT_PHYADDR(ethUnit);
-+
-+ /* Reset phy */
-+ phyRegWrite(phyBase, phyAddr, GEN_ctl, PHY_SW_RST | AUTONEGENA);
-+
-+ sysMsDelay(1500);
-+
-+ return linkAlive;
-+}
-+
-+/******************************************************************************
-+*
-+* rt_phyIsDuplexFull - Determines whether the phy ports associated with the
-+* specified device are FULL or HALF duplex.
-+*
-+* RETURNS:
-+* TRUE --> FULL
-+* FALSE --> HALF
-+*/
-+BOOL
-+rt_phyIsFullDuplex(int ethUnit)
-+{
-+ UINT16 phyCtl;
-+ UINT32 phyBase;
-+ UINT32 phyAddr;
-+
-+ phyBase = RT_PHYBASE(ethUnit);
-+ phyAddr = RT_PHYADDR(ethUnit);
-+
-+ phyCtl = phyRegRead(phyBase, phyAddr, GEN_ctl);
-+
-+ if (phyCtl & DUPLEX) {
-+ return TRUE;
-+ } else {
-+ return FALSE;
-+ }
-+}
-+
-+/******************************************************************************
-+*
-+* rt_phyIsSpeed100 - Determines the speed of phy ports associated with the
-+* specified device.
-+*
-+* RETURNS:
-+* TRUE --> 100Mbit
-+* FALSE --> 10Mbit
-+*/
-+BOOL
-+rt_phyIsSpeed100(int phyUnit)
-+{
-+ UINT16 phyLpa;
-+ UINT32 phyBase;
-+ UINT32 phyAddr;
-+
-+ phyBase = RT_PHYBASE(phyUnit);
-+ phyAddr = RT_PHYADDR(phyUnit);
-+
-+ phyLpa = phyRegRead(phyBase, phyAddr, AN_lpa);
-+
-+ if (phyLpa & (LPA_TXFD | LPA_TX)) {
-+ return TRUE;
-+ } else {
-+ return FALSE;
-+ }
-+}
-+
-+/*****************************************************************************
-+*
-+* rt_phyCheckStatusChange -- checks for significant changes in PHY state.
-+*
-+* A "significant change" is:
-+* dropped link (e.g. ethernet cable unplugged) OR
-+* autonegotiation completed + link (e.g. ethernet cable plugged in)
-+*
-+* On AR5311, there is a 1-to-1 mapping of ethernet units to PHYs.
-+* When a PHY is plugged in, phyLinkGained is called.
-+* When a PHY is unplugged, phyLinkLost is called.
-+*/
-+void
-+rt_phyCheckStatusChange(int ethUnit)
-+{
-+ UINT16 phyHwStatus;
-+ rtPhyInfo_t *lastStatus = &rtPhyInfo[ethUnit];
-+ UINT32 phyBase;
-+ UINT32 phyAddr;
-+
-+ phyBase = RT_PHYBASE(ethUnit);
-+ phyAddr = RT_PHYADDR(ethUnit);
-+
-+ phyHwStatus = phyRegRead(phyBase, phyAddr, GEN_sts);
-+
-+ if (lastStatus->phyAlive) { /* last known status was ALIVE */
-+ /* See if we've lost link */
-+ if (!(phyHwStatus & LINK)) {
-+ RT_PRINT(RT_DEBUG_PHYCHANGE,("\nethmac%d link down\n", ethUnit));
-+ lastStatus->phyAlive = FALSE;
-+ phyLinkLost(ethUnit);
-+ }
-+ } else { /* last known status was DEAD */
-+ /* Check for AN complete */
-+ if ((phyHwStatus & (AUTOCMPLT | LINK)) == (AUTOCMPLT | LINK)) {
-+ RT_PRINT(RT_DEBUG_PHYCHANGE,("\nethmac%d link up\n", ethUnit));
-+ lastStatus->phyAlive = TRUE;
-+ phyLinkGained(ethUnit);
-+ }
-+ }
-+}
-+
-+#if DEBUG
-+
-+/* Define the PHY registers of interest for a phyShow command */
-+struct rtRegisterTable_s {
-+ UINT32 regNum;
-+ char *regIdString;
-+} rtRegisterTable[] =
-+{
-+ {GEN_ctl, "Basic Mode Control (GEN_ctl) "},
-+ {GEN_sts, "Basic Mode Status (GEN_sts) "},
-+ {GEN_id_hi, "PHY Identifier 1 (GET_id_hi) "},
-+ {GEN_id_lo, "PHY Identifier 2 (GET_id_lo) "},
-+ {AN_adv, "Auto-Neg Advertisement (AN_adv) "},
-+ {AN_lpa, "Auto-Neg Link Partner Ability "},
-+ {AN_exp, "Auto-Neg Expansion "},
-+};
-+
-+int rtNumRegs = sizeof(rtRegisterTable) / sizeof(rtRegisterTable[0]);
-+
-+/*
-+ * Dump the state of a PHY.
-+ */
-+void
-+rt_phyShow(int phyUnit)
-+{
-+ int i;
-+ UINT16 value;
-+ UINT32 phyBase;
-+ UINT32 phyAddr;
-+
-+ phyBase = RT_PHYBASE(phyUnit);
-+ phyAddr = RT_PHYADDR(phyUnit);
-+
-+ printf("PHY state for ethphy%d\n", phyUnit);
-+
-+ for (i=0; i<rtNumRegs; i++) {
-+
-+ value = phyRegRead(phyBase, phyAddr, rtRegisterTable[i].regNum);
-+
-+ printf("Reg %02d (0x%02x) %s = 0x%08x\n",
-+ rtRegisterTable[i].regNum, rtRegisterTable[i].regNum,
-+ rtRegisterTable[i].regIdString, value);
-+ }
-+}
-+
-+/*
-+ * Modify the value of a PHY register.
-+ * This makes it a bit easier to modify PHY values during debug.
-+ */
-+void
-+rt_phySet(int phyUnit, UINT32 regnum, UINT32 value)
-+{
-+ UINT32 phyBase;
-+ UINT32 phyAddr;
-+
-+ phyBase = RT_PHYBASE(phyUnit);
-+ phyAddr = RT_PHYADDR(phyUnit);
-+
-+ phyRegWrite(phyBase, phyAddr, regnum, value);
-+}
-+#endif
-diff -urN linux-2.4.32.new/arch/mips/ar531x/rtPhy.h linux-2.4.32.new-eth/arch/mips/ar531x/rtPhy.h
---- linux-2.4.32.new/arch/mips/ar531x/rtPhy.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new-eth/arch/mips/ar531x/rtPhy.h 2005-12-25 11:54:46.089422728 +0000
-@@ -0,0 +1,50 @@
-+/*
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file "COPYING" in the main directory of this archive
-+ * for more details.
-+ *
-+ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
-+ */
-+
-+/*
-+ * rtPhy.h - definitions for the ethernet PHY.
-+ * This code supports a simple 1-port ethernet phy, Realtek RTL8201BL,
-+ * and compatible PHYs, such as the Kendin KS8721B.
-+ * All definitions in this file are operating system independent!
-+ */
-+
-+#ifndef RTPHY_H
-+#define RTPHY_H
-+
-+/* MII Registers */
-+
-+#define GEN_ctl 00
-+#define GEN_sts 01
-+#define GEN_id_hi 02
-+#define GEN_id_lo 03
-+#define AN_adv 04
-+#define AN_lpa 05
-+#define AN_exp 06
-+
-+/* GEN_ctl */
-+#define PHY_SW_RST 0x8000
-+#define LOOPBACK 0x4000
-+#define SPEED 0x2000 /* 100 Mbit/s */
-+#define AUTONEGENA 0x1000
-+#define DUPLEX 0x0100 /* Duplex mode */
-+
-+
-+/* GEN_sts */
-+#define AUTOCMPLT 0x0020 /* Autonegotiation completed */
-+#define LINK 0x0004 /* Link status */
-+
-+/* GEN_ids */
-+#define RT_PHY_ID1_EXPECTATION 0x22
-+
-+/* AN_lpa */
-+#define LPA_TXFD 0x0100 /* Link partner supports 100 TX Full Duplex */
-+#define LPA_TX 0x0080 /* Link partner supports 100 TX Half Duplex */
-+#define LPA_10FD 0x0040 /* Link partner supports 10 BT Full Duplex */
-+#define LPA_10 0x0020 /* Link partner supports 10 BT Half Duplex */
-+
-+#endif /* RTPHY_H */
diff --git a/target/linux/package/alsa/Config.in b/target/linux/package/alsa/Config.in
index 62dd21b97a..29a4e89e17 100644
--- a/target/linux/package/alsa/Config.in
+++ b/target/linux/package/alsa/Config.in
@@ -2,6 +2,7 @@ config BR2_PACKAGE_KMOD_ALSA
prompt "kmod-alsa......................... Alsa Sound Drivers"
tristate
default m if CONFIG_DEVEL
+ depends BR2_LINUX_2_4_X86 || BR2_LINUX_2_4_BRCM || BR2_LINUX_2_6_X86 || BR2_LINUX_2_6_BRCM
depends BR2_PACKAGE_KMOD_USB_CONTROLLER
select BR2_PACKAGE_KMOD_SOUNDCORE
help
diff --git a/target/linux/package/madwifi/Makefile b/target/linux/package/madwifi/Makefile
index ea2197c865..5432055c35 100644
--- a/target/linux/package/madwifi/Makefile
+++ b/target/linux/package/madwifi/Makefile
@@ -28,6 +28,14 @@ ifeq ($(ARCH),i386)
HAL_TARGET:=i386-elf
endif
+ifneq ($(BR2_LINUX_2_4_AR531X),)
+ BUS := AHB
+ bus := ahb
+else
+ BUS := PCI
+ bus := pci
+endif
+
include $(TOPDIR)/package/rules.mk
$(eval $(call PKG_template,KMOD_MADWIFI,kmod-madwifi,$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE),$(ARCH),kernel-$(LINUX_VERSION)-$(BOARD) ($(KERNEL_RELEASE))))
@@ -42,7 +50,9 @@ $(PKG_BUILD_DIR)/.built:
CROSS_COMPILE="$(TARGET_CROSS)" \
TARGET="$(HAL_TARGET)" \
TOOLPREFIX="$(KERNEL_CROSS)" \
+ TOOLPATH="$(KERNEL_CROSS)" \
KERNELPATH="$(KERNEL_DIR)" \
+ BUS="$(BUS)" \
all
touch $@
@@ -54,7 +64,7 @@ $(IPKG_KMOD_MADWIFI):
install -m0755 ./files/madwifi.init $(IDIR_KMOD_MADWIFI)/etc/init.d/S20madwifi
cp -fpR $(PKG_BUILD_DIR)/net80211/wlan*.$(LINUX_KMOD_SUFFIX) \
$(PKG_BUILD_DIR)/ath_hal/ath_hal.$(LINUX_KMOD_SUFFIX) \
- $(PKG_BUILD_DIR)/ath/ath_pci.$(LINUX_KMOD_SUFFIX) \
+ $(PKG_BUILD_DIR)/ath/ath_$(bus).$(LINUX_KMOD_SUFFIX) \
$(PKG_BUILD_DIR)/ath_rate/sample/ath_rate_sample.$(LINUX_KMOD_SUFFIX) \
$(PKG_BUILD_DIR)/net80211/*.$(LINUX_KMOD_SUFFIX) \
$(IDIR_KMOD_MADWIFI)/lib/modules/$(LINUX_VERSION)/