add updates for atheros SOC support from Mike A., thx
authorWaldemar Brodkorb <mail@waldemar-brodkorb.de>
Mon, 9 Jan 2006 16:03:36 +0000 (16:03 +0000)
committerWaldemar Brodkorb <mail@waldemar-brodkorb.de>
Mon, 9 Jan 2006 16:03:36 +0000 (16:03 +0000)
SVN-Revision: 2866

openwrt/target/linux/Config.in
openwrt/target/linux/image/squashfs.mk
openwrt/target/linux/linux-2.4/config/ar531x
openwrt/target/linux/linux-2.4/patches/ar531x/000-atheros-support.patch
openwrt/target/linux/linux-2.4/patches/ar531x/001-ar531x-ethernet.patch [deleted file]
openwrt/target/linux/package/alsa/Config.in
openwrt/target/linux/package/madwifi/Makefile

index e56b2c82bdd6421f3370e9c750e31f20b882c11b..893c8f56a2f8442fea5db7f76ce6b86fabd12f79 100644 (file)
@@ -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
 
index 63eba445a04cad2bf8d6ee8cd614601158ff4921..450718153c0d9d56c6e535fb9b34eae9df1aba7c 100644 (file)
@@ -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
index 4feca02dea6e7bc25c21ec262bbff2bef1d6762a..77c5beb3c27c3618f8e73a6a038ba00e94da986a 100644 (file)
@@ -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
index 1ec012f63082fdf3b58cfdc72559dedebaa11e03..de7115b46a158a6768d318e9e130ad621adf744c 100644 (file)
-diff -urN linux-2.4.32/arch/mips/ar531x/ar531xdbg_io.c linux-2.4.32.new/arch/mips/ar531x/ar531xdbg_io.c\r
---- linux-2.4.32/arch/mips/ar531x/ar531xdbg_io.c       1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/ar531xdbg_io.c   2005-12-24 20:29:42.102311328 +0000\r
-@@ -0,0 +1,217 @@\r
-+/*\r
-+ * This file is subject to the terms and conditions of the GNU General Public\r
-+ * License.  See the file "COPYING" in the main directory of this archive\r
-+ * for more details.\r
-+ *\r
-+ * Copyright MontaVista Software Inc\r
-+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.\r
-+ */\r
-+\r
-+/*\r
-+ * Basic support for polled character input/output\r
-+ * using the AR531X's serial port.\r
-+ */\r
-+\r
-+#include <linux/config.h>\r
-+#include <linux/init.h>\r
-+#include <linux/delay.h>\r
-+#include <linux/irq.h>\r
-+#include <linux/interrupt.h>\r
-+#include <linux/serial.h>\r
-+#include <linux/types.h>\r
-+#include <linux/string.h>\r
-+\r
-+#include <asm/reboot.h>\r
-+#include <asm/io.h>\r
-+#include <asm/time.h>\r
-+#include <asm/pgtable.h>\r
-+#include <asm/processor.h>\r
-+#include <asm/reboot.h>\r
-+#include <asm/system.h>\r
-+#include <asm/serial.h>\r
-+#include <asm/gdb-stub.h>\r
-+\r
-+#include "ar531xlnx.h"\r
-+\r
-+#if CONFIG_EARLY_PRINTK_HACK || CONFIG_KGDB\r
-+/* base addr of uart and clock timing */\r
-+#define         BASE                    0xbc000003\r
-+\r
-+/* distance in bytes between two serial registers */\r
-+#define         REG_OFFSET              4\r
-+\r
-+/*\r
-+ * 0 - we need to do serial init\r
-+ * 1 - skip serial init\r
-+ */\r
-+static int serialPortInitialized = 0;\r
-+\r
-+/*\r
-+ *  * the default baud rate *if* we do serial init\r
-+ *   */\r
-+#define         BAUD_DEFAULT            UART16550_BAUD_9600\r
-+\r
-+/* === END OF CONFIG === */\r
-+\r
-+#define         UART16550_BAUD_2400             2400\r
-+#define         UART16550_BAUD_4800             4800\r
-+#define         UART16550_BAUD_9600             9600\r
-+#define         UART16550_BAUD_19200            19200\r
-+#define         UART16550_BAUD_38400            38400\r
-+#define         UART16550_BAUD_57600            57600\r
-+#define         UART16550_BAUD_115200           115200\r
-+\r
-+#define         UART16550_PARITY_NONE           0\r
-+#define         UART16550_PARITY_ODD            0x08\r
-+#define         UART16550_PARITY_EVEN           0x18\r
-+#define         UART16550_PARITY_MARK           0x28\r
-+#define         UART16550_PARITY_SPACE          0x38\r
-+\r
-+#define         UART16550_DATA_5BIT             0x0\r
-+#define         UART16550_DATA_6BIT             0x1\r
-+#define         UART16550_DATA_7BIT             0x2\r
-+#define         UART16550_DATA_8BIT             0x3\r
-+\r
-+#define         UART16550_STOP_1BIT             0x0\r
-+#define         UART16550_STOP_2BIT             0x4\r
-+\r
-+/* register offset */\r
-+#define         OFS_RCV_BUFFER          (0*REG_OFFSET)\r
-+#define         OFS_TRANS_HOLD          (0*REG_OFFSET)\r
-+#define         OFS_SEND_BUFFER         (0*REG_OFFSET)\r
-+#define         OFS_INTR_ENABLE         (1*REG_OFFSET)\r
-+#define         OFS_INTR_ID             (2*REG_OFFSET)\r
-+#define         OFS_DATA_FORMAT         (3*REG_OFFSET)\r
-+#define         OFS_LINE_CONTROL        (3*REG_OFFSET)\r
-+#define         OFS_MODEM_CONTROL       (4*REG_OFFSET)\r
-+#define         OFS_RS232_OUTPUT        (4*REG_OFFSET)\r
-+#define         OFS_LINE_STATUS         (5*REG_OFFSET)\r
-+#define         OFS_MODEM_STATUS        (6*REG_OFFSET)\r
-+#define         OFS_RS232_INPUT         (6*REG_OFFSET)\r
-+#define         OFS_SCRATCH_PAD         (7*REG_OFFSET)\r
-+\r
-+#define         OFS_DIVISOR_LSB         (0*REG_OFFSET)\r
-+#define         OFS_DIVISOR_MSB         (1*REG_OFFSET)\r
-+\r
-+\r
-+/* memory-mapped read/write of the port */\r
-+#define         UART16550_READ(y)    (*((volatile u8*)(BASE + y)))\r
-+#define         UART16550_WRITE(y, z)  ((*((volatile u8*)(BASE + y))) = z)\r
-+\r
-+void\r
-+debugPortInit(u32 baud, u8 data, u8 parity, u8 stop)\r
-+{\r
-+      /* Pull UART out of reset */\r
-+      sysRegWrite(AR531X_RESET,\r
-+              sysRegRead(AR531X_RESET) & ~(AR531X_RESET_UART0));\r
-+\r
-+      /* disable interrupts */\r
-+        UART16550_WRITE(OFS_LINE_CONTROL, 0x0);\r
-+      UART16550_WRITE(OFS_INTR_ENABLE, 0);\r
-+\r
-+      /* set up buad rate */\r
-+      { \r
-+              u32 divisor;\r
-+              u32 uart_clock_rate = ar531x_cpu_frequency() / 4;\r
-+              u32 base_baud = uart_clock_rate / 16;\r
-+       \r
-+              /* set DIAB bit */\r
-+              UART16550_WRITE(OFS_LINE_CONTROL, 0x80);\r
-+        \r
-+              /* set divisor */\r
-+              divisor = base_baud / baud;\r
-+              UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);\r
-+              UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00)>>8);\r
-+\r
-+              /* clear DIAB bit */\r
-+              UART16550_WRITE(OFS_LINE_CONTROL, 0x0);\r
-+      }\r
-+\r
-+      /* set data format */\r
-+      UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);\r
-+}\r
-+\r
-+u8\r
-+getDebugChar(void)\r
-+{\r
-+        if (!serialPortInitialized) {\r
-+                serialPortInitialized = 1;\r
-+                debugPortInit(BAUD_DEFAULT,\r
-+                              UART16550_DATA_8BIT,\r
-+                              UART16550_PARITY_NONE, UART16550_STOP_1BIT);\r
-+        }\r
-+\r
-+      while((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);\r
-+      return UART16550_READ(OFS_RCV_BUFFER);\r
-+}\r
-+\r
-+#if CONFIG_KGDB\r
-+/*\r
-+ * Peek at the most recently received character.\r
-+ * Don't wait for a new character to be received.\r
-+ */\r
-+u8\r
-+peekDebugChar(void)\r
-+{\r
-+      return UART16550_READ(OFS_RCV_BUFFER);\r
-+}\r
-+\r
-+static int kgdbInitialized = 0;\r
-+\r
-+void\r
-+kgdbInit(void)\r
-+{\r
-+    sysRegWrite(AR531X_WD_CTRL, AR531X_WD_CTRL_IGNORE_EXPIRATION);\r
-+\r
-+    if (!kgdbInitialized) {\r
-+        printk("Setting debug traps - please connect the remote debugger.\n");\r
-+        set_debug_traps();\r
-+        kgdbInitialized = 1;\r
-+    }\r
-+    breakpoint();\r
-+}\r
-+\r
-+int\r
-+kgdbEnabled(void)\r
-+{\r
-+    return kgdbInitialized;\r
-+}\r
-+\r
-+#define DEBUG_CHAR '\001';\r
-+\r
-+int\r
-+kgdbInterrupt(void)\r
-+{\r
-+    if (!kgdbInitialized) {\r
-+        return 0;\r
-+    }\r
-+\r
-+    /* \r
-+     * Try to avoid swallowing too much input: Only consume\r
-+     * a character if nothing new has arrived.  Yes, there's\r
-+     * still a small hole here, and we may lose an input\r
-+     * character now and then.\r
-+     */\r
-+    if (UART16550_READ(OFS_LINE_STATUS) & 1) {\r
-+        return 0;\r
-+    } else {\r
-+        return UART16550_READ(OFS_RCV_BUFFER) == DEBUG_CHAR;\r
-+    }\r
-+}\r
-+#endif\r
-+\r
-+\r
-+void\r
-+putDebugChar(char byte)\r
-+{\r
-+        if (!serialPortInitialized) {\r
-+                serialPortInitialized = 1;\r
-+                debugPortInit(BAUD_DEFAULT,\r
-+                              UART16550_DATA_8BIT,\r
-+                              UART16550_PARITY_NONE, UART16550_STOP_1BIT);\r
-+        }\r
-+\r
-+      while ((UART16550_READ(OFS_LINE_STATUS) &0x20) == 0);\r
-+      UART16550_WRITE(OFS_SEND_BUFFER, byte);\r
-+ }\r
-+#endif /* CONFIG_EARLY_PRINTK_HACK || CONFIG_KGDB */\r
-diff -urN linux-2.4.32/arch/mips/ar531x/ar531xgpio.c linux-2.4.32.new/arch/mips/ar531x/ar531xgpio.c\r
---- linux-2.4.32/arch/mips/ar531x/ar531xgpio.c 1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/ar531xgpio.c     2005-12-24 20:29:42.102311328 +0000\r
-@@ -0,0 +1,141 @@\r
-+/*\r
-+ * This file is subject to the terms and conditions of the GNU General Public\r
-+ * License.  See the file "COPYING" in the main directory of this archive\r
-+ * for more details.\r
-+ *\r
-+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.\r
-+ */\r
-+\r
-+/*\r
-+ * Support for GPIO -- General Purpose Input/Output Pins\r
-+ */\r
-+\r
-+#include <linux/config.h>\r
-+#include <linux/kernel.h>\r
-+#include <linux/signal.h>\r
-+#include <linux/interrupt.h>\r
-+#include <linux/irq.h>\r
-+\r
-+#include "ar531xlnx.h"\r
-+\r
-+/* GPIO Interrupt Support */\r
-+\r
-+/* Turn on the specified AR531X_GPIO_IRQ interrupt */\r
-+static unsigned int\r
-+ar531x_gpio_intr_startup(unsigned int irq)\r
-+{\r
-+      ar531x_gpio_intr_enable(irq);\r
-+      return 0;\r
-+}\r
-+\r
-+/* Turn off the specified AR531X_GPIO_IRQ interrupt */\r
-+static void\r
-+ar531x_gpio_intr_shutdown(unsigned int irq)\r
-+{\r
-+      ar531x_gpio_intr_disable(irq);\r
-+}\r
-+\r
-+u32 gpioIntMask = 0;\r
-+\r
-+/* Enable the specified AR531X_GPIO_IRQ interrupt */\r
-+void\r
-+ar531x_gpio_intr_enable(unsigned int irq)\r
-+{\r
-+    u32 reg;\r
-+    int gpio;\r
-+\r
-+    gpio = irq - AR531X_GPIO_IRQ_BASE;\r
-+    gpioIntMask |= gpio;\r
-+\r
-+    reg = sysRegRead(AR531X_GPIO_CR);\r
-+    reg &= ~(GPIO_CR_M(gpio) | GPIO_CR_UART(gpio) | GPIO_CR_INT(gpio));\r
-+    reg |= GPIO_CR_I(gpio);\r
-+    reg |= GPIO_CR_INT(gpio);\r
-+\r
-+    sysRegWrite(AR531X_GPIO_CR, reg);\r
-+    (void)sysRegRead(AR531X_GPIO_CR); /* flush to hardware */\r
-+}\r
-+\r
-+/* Disable the specified AR531X_GPIO_IRQ interrupt */\r
-+void\r
-+ar531x_gpio_intr_disable(unsigned int irq)\r
-+{\r
-+    u32 reg;\r
-+    int gpio;\r
-+\r
-+    gpio = irq - AR531X_GPIO_IRQ_BASE;\r
-+\r
-+    reg = sysRegRead(AR531X_GPIO_CR);\r
-+    reg &= ~(GPIO_CR_M(gpio) | GPIO_CR_UART(gpio) | GPIO_CR_INT(gpio));\r
-+    reg |= GPIO_CR_I(gpio);\r
-+    /* No GPIO_CR_INT bit */\r
-+\r
-+    sysRegWrite(AR531X_GPIO_CR, reg);\r
-+    (void)sysRegRead(AR531X_GPIO_CR); /* flush to hardware */\r
-+\r
-+    gpioIntMask &= ~gpio;\r
-+}\r
-+\r
-+static void\r
-+ar531x_gpio_intr_ack(unsigned int irq)\r
-+{\r
-+      ar531x_gpio_intr_disable(irq);\r
-+}\r
-+\r
-+static void\r
-+ar531x_gpio_intr_end(unsigned int irq)\r
-+{\r
-+      if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))\r
-+              ar531x_gpio_intr_enable(irq);\r
-+}\r
-+\r
-+static void\r
-+ar531x_gpio_intr_set_affinity(unsigned int irq, unsigned long mask)\r
-+{\r
-+      /* Only 1 CPU; ignore affinity request */\r
-+}\r
-+\r
-+int ar531x_gpio_irq_base;\r
-+\r
-+struct hw_interrupt_type ar531x_gpio_intr_controller = {\r
-+      "AR531X GPIO",\r
-+      ar531x_gpio_intr_startup,\r
-+      ar531x_gpio_intr_shutdown,\r
-+      ar531x_gpio_intr_enable,\r
-+      ar531x_gpio_intr_disable,\r
-+      ar531x_gpio_intr_ack,\r
-+      ar531x_gpio_intr_end,\r
-+      ar531x_gpio_intr_set_affinity,\r
-+};\r
-+\r
-+void\r
-+ar531x_gpio_intr_init(int irq_base)\r
-+{\r
-+      int i;\r
-+\r
-+      for (i = irq_base; i < irq_base + AR531X_GPIO_IRQ_COUNT; i++) {\r
-+              irq_desc[i].status = IRQ_DISABLED;\r
-+              irq_desc[i].action = NULL;\r
-+              irq_desc[i].depth = 1;\r
-+              irq_desc[i].handler = &ar531x_gpio_intr_controller;\r
-+      }\r
-+\r
-+      ar531x_gpio_irq_base = irq_base;\r
-+}\r
-+\r
-+/* ARGSUSED */\r
-+void\r
-+spurious_gpio_handler(int cpl, void *dev_id, struct pt_regs *regs)\r
-+{\r
-+    u32 gpioDataIn;\r
-+\r
-+    gpioDataIn = sysRegRead(AR531X_GPIO_DI) & gpioIntMask;\r
-+\r
-+    printk("spurious_gpio_handler: 0x%x di=0x%8.8x gpioIntMask=0x%8.8x\n",\r
-+           cpl, gpioDataIn, gpioIntMask);\r
-+}\r
-+\r
-+struct irqaction spurious_gpio =\r
-+      {spurious_gpio_handler, SA_INTERRUPT, 0, "spurious_gpio",\r
-+            NULL, NULL};\r
-+\r
-diff -urN linux-2.4.32/arch/mips/ar531x/ar531x.h linux-2.4.32.new/arch/mips/ar531x/ar531x.h\r
---- linux-2.4.32/arch/mips/ar531x/ar531x.h     1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/ar531x.h 2005-12-24 20:29:42.102311328 +0000\r
-@@ -0,0 +1,280 @@\r
-+/*\r
-+ * This file is subject to the terms and conditions of the GNU General Public\r
-+ * License.  See the file "COPYING" in the main directory of this archive\r
-+ * for more details.\r
-+ *\r
-+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.\r
-+ */\r
-+\r
-+#ifndef AR531X_H\r
-+#define AR531X_H 1\r
-+\r
-+#include <asm/addrspace.h>\r
-+\r
-+/* Address Map */\r
-+#define AR531X_WLAN0            0x18000000\r
-+#define AR531X_WLAN1            0x18500000\r
-+#define AR531X_ENET0            0x18100000\r
-+#define AR531X_ENET1            0x18200000\r
-+#define AR531X_SDRAMCTL         0x18300000\r
-+#define AR531X_FLASHCTL         0x18400000\r
-+#define AR531X_APBBASE                0x1c000000\r
-+#define AR531X_FLASH            0x1e000000\r
-+\r
-+/*\r
-+ * AR531X_NUM_ENET_MAC defines the number of ethernet MACs that\r
-+ * should be considered available.  The AR5312 supports 2 enet MACS,\r
-+ * even though many reference boards only actually use 1 of them\r
-+ * (i.e. Only MAC 0 is actually connected to an enet PHY or PHY switch.\r
-+ * The AR2312 supports 1 enet MAC.\r
-+ */\r
-+#define AR531X_NUM_ENET_MAC             2\r
-+\r
-+/*\r
-+ * Need these defines to determine true number of ethernet MACs\r
-+ */\r
-+#define AR5212_AR5312_REV2      0x0052          /* AR5312 WMAC (AP31) */\r
-+#define AR5212_AR5312_REV7      0x0057          /* AR5312 WMAC (AP30-040) */\r
-+#define AR5212_AR2313_REV8      0x0058          /* AR2313 WMAC (AP43-030) */\r
-+#define AR531X_RADIO_MASK_OFF  0xc8\r
-+#define AR531X_RADIO0_MASK     0x0003\r
-+#define AR531X_RADIO1_MASK     0x000c\r
-+#define AR531X_RADIO1_S        2 \r
-+\r
-+/*\r
-+ * AR531X_NUM_WMAC defines the number of Wireless MACs that\\r
-+ * should be considered available.\r
-+ */\r
-+#define AR531X_NUM_WMAC                 2\r
-+\r
-+/* Reset/Timer Block Address Map */\r
-+#define AR531X_RESETTMR               (AR531X_APBBASE  + 0x3000)\r
-+#define AR531X_TIMER          (AR531X_RESETTMR + 0x0000) /* countdown timer */\r
-+#define AR531X_WD_CTRL          (AR531X_RESETTMR + 0x0008) /* watchdog cntrl */\r
-+#define AR531X_WD_TIMER         (AR531X_RESETTMR + 0x000c) /* watchdog timer */\r
-+#define AR531X_ISR            (AR531X_RESETTMR + 0x0010) /* Intr Status Reg */\r
-+#define AR531X_IMR            (AR531X_RESETTMR + 0x0014) /* Intr Mask Reg */\r
-+#define AR531X_RESET          (AR531X_RESETTMR + 0x0020)\r
-+#define AR5312_CLOCKCTL1      (AR531X_RESETTMR + 0x0064)\r
-+#define AR5312_SCRATCH        (AR531X_RESETTMR + 0x006c)\r
-+#define AR531X_PROCADDR               (AR531X_RESETTMR + 0x0070)\r
-+#define AR531X_PROC1          (AR531X_RESETTMR + 0x0074)\r
-+#define AR531X_DMAADDR                (AR531X_RESETTMR + 0x0078)\r
-+#define AR531X_DMA1           (AR531X_RESETTMR + 0x007c)\r
-+#define AR531X_ENABLE           (AR531X_RESETTMR + 0x0080) /* interface enb */\r
-+#define AR531X_REV            (AR531X_RESETTMR + 0x0090) /* revision */\r
-+\r
-+/* AR531X_WD_CTRL register bit field definitions */\r
-+#define AR531X_WD_CTRL_IGNORE_EXPIRATION 0x0000\r
-+#define AR531X_WD_CTRL_NMI               0x0001\r
-+#define AR531X_WD_CTRL_RESET             0x0002\r
-+\r
-+/* AR531X_ISR register bit field definitions */\r
-+#define AR531X_ISR_NONE               0x0000\r
-+#define AR531X_ISR_TIMER      0x0001\r
-+#define AR531X_ISR_AHBPROC    0x0002\r
-+#define AR531X_ISR_AHBDMA     0x0004\r
-+#define AR531X_ISR_GPIO               0x0008\r
-+#define AR531X_ISR_UART0      0x0010\r
-+#define AR531X_ISR_UART0DMA   0x0020\r
-+#define AR531X_ISR_WD         0x0040\r
-+#define AR531X_ISR_LOCAL      0x0080\r
-+\r
-+/* AR531X_RESET register bit field definitions */\r
-+#define AR531X_RESET_SYSTEM     0x00000001  /* cold reset full system */\r
-+#define AR531X_RESET_PROC       0x00000002  /* cold reset MIPS core */\r
-+#define AR531X_RESET_WLAN0      0x00000004  /* cold reset WLAN MAC and BB */\r
-+#define AR531X_RESET_EPHY0      0x00000008  /* cold reset ENET0 phy */\r
-+#define AR531X_RESET_EPHY1      0x00000010  /* cold reset ENET1 phy */\r
-+#define AR531X_RESET_ENET0      0x00000020  /* cold reset ENET0 mac */\r
-+#define AR531X_RESET_ENET1      0x00000040  /* cold reset ENET1 mac */\r
-+#define AR531X_RESET_UART0      0x00000100  /* cold reset UART0 (high speed) */\r
-+#define AR531X_RESET_WLAN1      0x00000200  /* cold reset WLAN MAC/BB */\r
-+#define AR531X_RESET_APB        0x00000400  /* cold reset APB (ar5312) */\r
-+#define AR531X_RESET_WARM_PROC  0x00001000  /* warm reset MIPS core */\r
-+#define AR531X_RESET_WARM_WLAN0_MAC 0x00002000  /* warm reset WLAN0 MAC */\r
-+#define AR531X_RESET_WARM_WLAN0_BB  0x00004000  /* warm reset WLAN0 BaseBand */\r
-+#define AR531X_RESET_NMI        0x00010000  /* send an NMI to the processor */\r
-+#define AR531X_RESET_WARM_WLAN1_MAC 0x00020000  /* warm reset WLAN1 mac */\r
-+#define AR531X_RESET_WARM_WLAN1_BB  0x00040000  /* warm reset WLAN1 baseband */\r
-+#define AR531X_RESET_LOCAL_BUS  0x00080000  /* reset local bus */\r
-+#define AR531X_RESET_WDOG       0x00100000  /* last reset was a watchdog */\r
-+\r
-+#define AR531X_RESET_WMAC0_BITS \\r
-+        AR531X_RESET_WLAN0 |\\r
-+        AR531X_RESET_WARM_WLAN0_MAC |\\r
-+        AR531X_RESET_WARM_WLAN0_BB\r
-+\r
-+#define AR531X_RESERT_WMAC1_BITS \\r
-+        AR531X_RESET_WLAN1 |\\r
-+        AR531X_RESET_WARM_WLAN1_MAC |\\r
-+        AR531X_RESET_WARM_WLAN1_BB\r
-+\r
-+/* AR5312_CLOCKCTL1 register bit field definitions */\r
-+#define AR5312_CLOCKCTL1_PREDIVIDE_MASK    0x00000030\r
-+#define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT            4\r
-+#define AR5312_CLOCKCTL1_MULTIPLIER_MASK   0x00001f00\r
-+#define AR5312_CLOCKCTL1_MULTIPLIER_SHIFT           8\r
-+#define AR5312_CLOCKCTL1_DOUBLER_MASK      0x00010000\r
-+\r
-+/* Valid for AR5312 and AR2312 */\r
-+#define AR5312_CLOCKCTL1_PREDIVIDE_MASK    0x00000030\r
-+#define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT            4\r
-+#define AR5312_CLOCKCTL1_MULTIPLIER_MASK   0x00001f00\r
-+#define AR5312_CLOCKCTL1_MULTIPLIER_SHIFT           8\r
-+#define AR5312_CLOCKCTL1_DOUBLER_MASK      0x00010000\r
-+\r
-+/* Valid for AR2313 */\r
-+#define AR2313_CLOCKCTL1_PREDIVIDE_MASK    0x00003000\r
-+#define AR2313_CLOCKCTL1_PREDIVIDE_SHIFT           12\r
-+#define AR2313_CLOCKCTL1_MULTIPLIER_MASK   0x001f0000\r
-+#define AR2313_CLOCKCTL1_MULTIPLIER_SHIFT          16\r
-+#define AR2313_CLOCKCTL1_DOUBLER_MASK      0x00000000\r
-+\r
-+\r
-+/* AR531X_ENABLE register bit field definitions */\r
-+#define AR531X_ENABLE_WLAN0              0x0001\r
-+#define AR531X_ENABLE_ENET0              0x0002\r
-+#define AR531X_ENABLE_ENET1              0x0004\r
-+#define AR531X_ENABLE_UART_AND_WLAN1_PIO 0x0008   /* UART, and WLAN1 PIOs */\r
-+#define AR531X_ENABLE_WLAN1_DMA          0x0010   /* WLAN1 DMAs */\r
-+#define AR531X_ENABLE_WLAN1 \\r
-+            (AR531X_ENABLE_UART_AND_WLAN1_PIO | AR531X_ENABLE_WLAN1_DMA)\r
-+\r
-+/* AR531X_REV register bit field definitions */\r
-+#define AR531X_REV_WMAC_MAJ    0xf000\r
-+#define AR531X_REV_WMAC_MAJ_S  12\r
-+#define AR531X_REV_WMAC_MIN    0x0f00\r
-+#define AR531X_REV_WMAC_MIN_S  8\r
-+#define AR531X_REV_MAJ         0x00f0\r
-+#define AR531X_REV_MAJ_S       4\r
-+#define AR531X_REV_MIN         0x000f\r
-+#define AR531X_REV_MIN_S       0\r
-+#define AR531X_REV_CHIP        (REV_MAJ|REV_MIN)\r
-+\r
-+/* Major revision numbers, bits 7..4 of Revision ID register */\r
-+#define AR531X_REV_MAJ_AR5312          0x4\r
-+#define AR531X_REV_MAJ_AR2313          0x5\r
-+\r
-+/* Minor revision numbers, bits 3..0 of Revision ID register */\r
-+#define AR5312_REV_MIN_DUAL     0x0     /* Dual WLAN version */\r
-+#define AR5312_REV_MIN_SINGLE   0x1     /* Single WLAN version */\r
-+\r
-+/* AR531X_FLASHCTL register bit field definitions */\r
-+#define FLASHCTL_IDCY   0x0000000f      /* Idle cycle turn around time */\r
-+#define FLASHCTL_IDCY_S 0\r
-+#define FLASHCTL_WST1   0x000003e0      /* Wait state 1 */\r
-+#define FLASHCTL_WST1_S 5\r
-+#define FLASHCTL_RBLE   0x00000400      /* Read byte lane enable */\r
-+#define FLASHCTL_WST2   0x0000f800      /* Wait state 2 */\r
-+#define FLASHCTL_WST2_S 11\r
-+#define FLASHCTL_AC     0x00070000      /* Flash address check (added) */\r
-+#define FLASHCTL_AC_S   16\r
-+#define FLASHCTL_AC_128K 0x00000000\r
-+#define FLASHCTL_AC_256K 0x00010000\r
-+#define FLASHCTL_AC_512K 0x00020000\r
-+#define FLASHCTL_AC_1M   0x00030000\r
-+#define FLASHCTL_AC_2M   0x00040000\r
-+#define FLASHCTL_AC_4M   0x00050000\r
-+#define FLASHCTL_AC_8M   0x00060000\r
-+#define FLASHCTL_AC_RES  0x00070000     /* 16MB is not supported */\r
-+#define FLASHCTL_E      0x00080000      /* Flash bank enable (added) */\r
-+#define FLASHCTL_BUSERR 0x01000000      /* Bus transfer error status flag */\r
-+#define FLASHCTL_WPERR  0x02000000      /* Write protect error status flag */\r
-+#define FLASHCTL_WP     0x04000000      /* Write protect */\r
-+#define FLASHCTL_BM     0x08000000      /* Burst mode */\r
-+#define FLASHCTL_MW     0x30000000      /* Memory width */\r
-+#define FLASHCTL_MWx8   0x00000000      /* Memory width x8 */\r
-+#define FLASHCTL_MWx16  0x10000000      /* Memory width x16 */\r
-+#define FLASHCTL_MWx32  0x20000000      /* Memory width x32 (not supported) */\r
-+#define FLASHCTL_ATNR   0x00000000      /* Access type == no retry */\r
-+#define FLASHCTL_ATR    0x80000000      /* Access type == retry every */\r
-+#define FLASHCTL_ATR4   0xc0000000      /* Access type == retry every 4 */\r
-+\r
-+/* ARM Flash Controller -- 3 flash banks with either x8 or x16 devices.  */\r
-+#define AR531X_FLASHCTL0        (AR531X_FLASHCTL + 0x00)\r
-+#define AR531X_FLASHCTL1        (AR531X_FLASHCTL + 0x04)\r
-+#define AR531X_FLASHCTL2        (AR531X_FLASHCTL + 0x08)\r
-+\r
-+/* ARM SDRAM Controller -- just enough to determine memory size */\r
-+#define AR531X_MEM_CFG1 (AR531X_SDRAMCTL + 0x04)\r
-+#define MEM_CFG1_AC0    0x00000700      /* bank 0: SDRAM addr check (added) */\r
-+#define MEM_CFG1_AC0_S  8\r
-+#define MEM_CFG1_AC1    0x00007000      /* bank 1: SDRAM addr check (added) */\r
-+#define MEM_CFG1_AC1_S  12\r
-+\r
-+/* GPIO Address Map */\r
-+#define AR531X_GPIO         (AR531X_APBBASE  + 0x2000)\r
-+#define AR531X_GPIO_DO      (AR531X_GPIO + 0x00)        /* output register */\r
-+#define AR531X_GPIO_DI      (AR531X_GPIO + 0x04)        /* intput register */\r
-+#define AR531X_GPIO_CR      (AR531X_GPIO + 0x08)        /* control register */\r
-+\r
-+/* GPIO Control Register bit field definitions */\r
-+#define GPIO_CR_M(x)    (1 << (x))                      /* mask for i/o */\r
-+#define GPIO_CR_O(x)    (0 << (x))                      /* mask for output */\r
-+#define GPIO_CR_I(x)    (1 << (x))                      /* mask for input */\r
-+#define GPIO_CR_INT(x)  (1 << ((x)+8))                  /* mask for interrupt */\r
-+#define GPIO_CR_UART(x) (1 << ((x)+16))                 /* uart multiplex */\r
-+\r
-+\r
-+typedef unsigned int AR531X_REG;\r
-+\r
-+#define sysRegRead(phys)      \\r
-+      (*(volatile AR531X_REG *)PHYS_TO_K1(phys))\r
-+\r
-+#define sysRegWrite(phys, val)        \\r
-+      ((*(volatile AR531X_REG *)PHYS_TO_K1(phys)) = (val))\r
-+\r
-+\r
-+/*\r
-+ * This is board-specific data that is stored in a "fixed" location in flash.\r
-+ * It is shared across operating systems, so it should not be changed lightly.\r
-+ * The main reason we need it is in order to extract the ethernet MAC\r
-+ * address(es).\r
-+ */\r
-+struct ar531x_boarddata {\r
-+    u32 magic;                       /* board data is valid */\r
-+#define AR531X_BD_MAGIC 0x35333131   /* "5311", for all 531x platforms */\r
-+    u16 cksum;                       /* checksum (starting with BD_REV 2) */\r
-+    u16 rev;                         /* revision of this struct */\r
-+#define BD_REV  4\r
-+    char   boardName[64];            /* Name of board */\r
-+    u16 major;                       /* Board major number */\r
-+    u16 minor;                       /* Board minor number */\r
-+    u32 config;                      /* Board configuration */\r
-+#define BD_ENET0        0x00000001   /* ENET0 is stuffed */\r
-+#define BD_ENET1        0x00000002   /* ENET1 is stuffed */\r
-+#define BD_UART1        0x00000004   /* UART1 is stuffed */\r
-+#define BD_UART0        0x00000008   /* UART0 is stuffed (dma) */\r
-+#define BD_RSTFACTORY   0x00000010   /* Reset factory defaults stuffed */\r
-+#define BD_SYSLED       0x00000020   /* System LED stuffed */\r
-+#define BD_EXTUARTCLK   0x00000040   /* External UART clock */\r
-+#define BD_CPUFREQ      0x00000080   /* cpu freq is valid in nvram */\r
-+#define BD_SYSFREQ      0x00000100   /* sys freq is set in nvram */\r
-+#define BD_WLAN0        0x00000200   /* Enable WLAN0 */\r
-+#define BD_MEMCAP       0x00000400   /* CAP SDRAM @ memCap for testing */\r
-+#define BD_DISWATCHDOG  0x00000800   /* disable system watchdog */\r
-+#define BD_WLAN1        0x00001000   /* Enable WLAN1 (ar5212) */\r
-+#define BD_ISCASPER     0x00002000   /* FLAG for AR2312 */\r
-+#define BD_WLAN0_2G_EN  0x00004000   /* FLAG for radio0_2G */\r
-+#define BD_WLAN0_5G_EN  0x00008000   /* FLAG for radio0_2G */\r
-+#define BD_WLAN1_2G_EN  0x00020000   /* FLAG for radio0_2G */\r
-+#define BD_WLAN1_5G_EN  0x00040000   /* FLAG for radio0_2G */\r
-+    u16 resetConfigGpio;             /* Reset factory GPIO pin */\r
-+    u16 sysLedGpio;                  /* System LED GPIO pin */\r
-+\r
-+    u32 cpuFreq;                     /* CPU core frequency in Hz */\r
-+    u32 sysFreq;                     /* System frequency in Hz */\r
-+    u32 cntFreq;                     /* Calculated C0_COUNT frequency */\r
-+\r
-+    u8  wlan0Mac[6];\r
-+    u8  enet0Mac[6];\r
-+    u8  enet1Mac[6];\r
-+\r
-+    u16 pciId;                       /* Pseudo PCIID for common code */\r
-+    u16 memCap;                      /* cap bank1 in MB */\r
-+\r
-+    /* version 3 */\r
-+    u8  wlan1Mac[6];                 /* (ar5212) */\r
-+};\r
-+#endif /* AR531X_H */\r
-diff -urN linux-2.4.32/arch/mips/ar531x/ar531xintr.S linux-2.4.32.new/arch/mips/ar531x/ar531xintr.S\r
---- linux-2.4.32/arch/mips/ar531x/ar531xintr.S 1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/ar531xintr.S     2005-12-24 20:29:42.103311176 +0000\r
-@@ -0,0 +1,30 @@\r
-+/*\r
-+ * This file is subject to the terms and conditions of the GNU General Public\r
-+ * License.  See the file "COPYING" in the main directory of this archive\r
-+ * for more details.\r
-+ *\r
-+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.\r
-+ */\r
-+\r
-+#include <asm/asm.h>\r
-+#include <asm/mipsregs.h>\r
-+#include <asm/regdef.h>\r
-+#include <asm/stackframe.h>\r
-+\r
-+/*\r
-+ * Glue code to save registers and get us to the interrupt dispatcher\r
-+ */\r
-+      .text\r
-+      .set    noat\r
-+      .align  5\r
-+NESTED(ar531x_interrupt_receive, PT_SIZE, sp)\r
-+      SAVE_ALL\r
-+      CLI\r
-+      .set    at\r
-+\r
-+      move    a0, sp\r
-+      jal     ar531x_irq_dispatch\r
-+\r
-+      j       ret_from_irq\r
-+\r
-+      END(ar531x_interrupt_receive)\r
-diff -urN linux-2.4.32/arch/mips/ar531x/ar531xirq.c linux-2.4.32.new/arch/mips/ar531x/ar531xirq.c\r
---- linux-2.4.32/arch/mips/ar531x/ar531xirq.c  1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/ar531xirq.c      2005-12-24 20:29:42.132306768 +0000\r
-@@ -0,0 +1,292 @@\r
-+/*\r
-+ * This file is subject to the terms and conditions of the GNU General Public\r
-+ * License.  See the file "COPYING" in the main directory of this archive\r
-+ * for more details.\r
-+ *\r
-+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.\r
-+ */\r
-+\r
-+/*\r
-+ * Interrupt support for AR531X WiSOC.\r
-+ */\r
-+\r
-+#include <linux/config.h>\r
-+#include <linux/init.h>\r
-+#include <linux/kernel_stat.h>\r
-+#include <linux/signal.h>\r
-+#include <linux/sched.h>\r
-+#include <linux/interrupt.h>\r
-+#include <linux/slab.h>\r
-+#include <linux/random.h>\r
-+#include <linux/pm.h>\r
-+#include <linux/delay.h>\r
-+#include <linux/reboot.h>\r
-+\r
-+#include <asm/irq.h>\r
-+#include <asm/mipsregs.h>\r
-+#include <asm/gdb-stub.h>\r
-+\r
-+#include "ar531xlnx.h"\r
-+#include <asm/irq_cpu.h>\r
-+\r
-+extern int setup_irq(unsigned int irq, struct irqaction *irqaction);\r
-+\r
-+static void ar531x_misc_intr_enable(unsigned int irq);\r
-+static void ar531x_misc_intr_disable(unsigned int irq);\r
-+\r
-+/* Turn on the specified AR531X_MISC_IRQ interrupt */\r
-+static unsigned int\r
-+ar531x_misc_intr_startup(unsigned int irq)\r
-+{\r
-+      ar531x_misc_intr_enable(irq);\r
-+      return 0;\r
-+}\r
-+\r
-+/* Turn off the specified AR531X_MISC_IRQ interrupt */\r
-+static void\r
-+ar531x_misc_intr_shutdown(unsigned int irq)\r
-+{\r
-+      ar531x_misc_intr_disable(irq);\r
-+}\r
-+\r
-+/* Enable the specified AR531X_MISC_IRQ interrupt */\r
-+static void\r
-+ar531x_misc_intr_enable(unsigned int irq)\r
-+{\r
-+      unsigned int imr;\r
-+\r
-+      imr = sysRegRead(AR531X_IMR);\r
-+      imr |= (1 << (irq - AR531X_MISC_IRQ_BASE - 1));\r
-+      sysRegWrite(AR531X_IMR, imr);\r
-+      sysRegRead(AR531X_IMR); /* flush write buffer */\r
-+}\r
-+\r
-+/* Disable the specified AR531X_MISC_IRQ interrupt */\r
-+static void\r
-+ar531x_misc_intr_disable(unsigned int irq)\r
-+{\r
-+      unsigned int imr;\r
-+\r
-+      imr = sysRegRead(AR531X_IMR);\r
-+      imr &= ~(1 << (irq - AR531X_MISC_IRQ_BASE - 1));\r
-+      sysRegWrite(AR531X_IMR, imr);\r
-+      sysRegRead(AR531X_IMR); /* flush write buffer */\r
-+}\r
-+\r
-+static void\r
-+ar531x_misc_intr_ack(unsigned int irq)\r
-+{\r
-+      ar531x_misc_intr_disable(irq);\r
-+}\r
-+\r
-+static void\r
-+ar531x_misc_intr_end(unsigned int irq)\r
-+{\r
-+      if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))\r
-+              ar531x_misc_intr_enable(irq);\r
-+}\r
-+\r
-+static void\r
-+ar531x_misc_intr_set_affinity(unsigned int irq, unsigned long mask)\r
-+{\r
-+      /* Only 1 CPU; ignore affinity request */\r
-+}\r
-+\r
-+struct hw_interrupt_type ar531x_misc_intr_controller = {\r
-+      "AR531X MISC",\r
-+      ar531x_misc_intr_startup,\r
-+      ar531x_misc_intr_shutdown,\r
-+      ar531x_misc_intr_enable,\r
-+      ar531x_misc_intr_disable,\r
-+      ar531x_misc_intr_ack,\r
-+      ar531x_misc_intr_end,\r
-+      ar531x_misc_intr_set_affinity,\r
-+};\r
-+\r
-+int ar531x_misc_irq_base;\r
-+\r
-+/*\r
-+ * Determine interrupt source among interrupts that use IP6\r
-+ */\r
-+void\r
-+ar531x_misc_intr_init(int irq_base)\r
-+{\r
-+      int i;\r
-+\r
-+      for (i = irq_base; i < irq_base + AR531X_MISC_IRQ_COUNT; i++) {\r
-+              irq_desc[i].status = IRQ_DISABLED;\r
-+              irq_desc[i].action = NULL;\r
-+              irq_desc[i].depth = 1;\r
-+              irq_desc[i].handler = &ar531x_misc_intr_controller;\r
-+      }\r
-+\r
-+      ar531x_misc_irq_base = irq_base;\r
-+}\r
-+\r
-+/* ARGSUSED */\r
-+void\r
-+spurious_irq_handler(int cpl, void *dev_id, struct pt_regs *regs)\r
-+{\r
-+    /* \r
-+    printk("spurious_irq_handler: %d  cause=0x%8.8x  status=0x%8.8x\n",\r
-+           cpl, cause_intrs, status_intrs); \r
-+    */\r
-+}\r
-+\r
-+/* ARGSUSED */\r
-+void\r
-+spurious_misc_handler(int cpl, void *dev_id, struct pt_regs *regs)\r
-+{\r
-+    /*\r
-+    printk("spurious_misc_handler: 0x%x isr=0x%8.8x imr=0x%8.8x\n",\r
-+           cpl, ar531x_isr, ar531x_imr);\r
-+    */\r
-+}\r
-+\r
-+void\r
-+ar531x_timer_handler(int cpl, void *dev_id, struct pt_regs *regs)\r
-+{\r
-+      (void)sysRegRead(AR531X_TIMER); /* clear interrupt */\r
-+}\r
-+\r
-+void\r
-+ar531x_ahb_proc_handler(int cpl, void *dev_id, struct pt_regs *regs)\r
-+{\r
-+    u32 procAddr;\r
-+    u32 proc1;\r
-+    u32 dmaAddr;\r
-+    u32 dma1;\r
-+\r
-+    proc1 = sysRegRead(AR531X_PROC1);\r
-+    procAddr = sysRegRead(AR531X_PROCADDR); /* clears error state */\r
-+    dma1 = sysRegRead(AR531X_DMA1);\r
-+    dmaAddr = sysRegRead(AR531X_DMAADDR);   /* clears error state */\r
-+\r
-+    printk("AHB interrupt: PROCADDR=0x%8.8x  PROC1=0x%8.8x  DMAADDR=0x%8.8x  DMA1=0x%8.8x\n",\r
-+        procAddr, proc1, dmaAddr, dma1);\r
-+        \r
-+    machine_restart("AHB error"); /* Catastrophic failure */\r
-+}\r
-+\r
-+static struct irqaction cascade  =\r
-+      {no_action, SA_INTERRUPT, 0, "cascade",\r
-+            NULL, NULL};\r
-+\r
-+static struct irqaction spurious_irq =\r
-+      {spurious_irq_handler, SA_INTERRUPT, 0, "spurious_irq",\r
-+            NULL, NULL};\r
-+\r
-+static struct irqaction spurious_misc =\r
-+      {spurious_misc_handler, SA_INTERRUPT, 0, "spurious_misc",\r
-+            NULL, NULL};\r
-+\r
-+static struct irqaction ar531x_timer_interrupt =\r
-+      {ar531x_timer_handler, SA_INTERRUPT, 0, "ar531x_timer_interrupt",\r
-+            NULL, NULL};\r
-+\r
-+static struct irqaction ar531x_ahb_proc_interrupt =\r
-+      {ar531x_ahb_proc_handler, SA_INTERRUPT, 0, "ar531x_ahb_proc_interrupt",\r
-+            NULL, NULL};\r
-+\r
-+extern asmlinkage void ar531x_interrupt_receive(void);\r
-+\r
-+/*\r
-+ * Called when an interrupt is received, this function\r
-+ * determines exactly which interrupt it was, and it\r
-+ * invokes the appropriate handler.\r
-+ *\r
-+ * Implicitly, we also define interrupt priority by\r
-+ * choosing which to dispatch first.\r
-+ */\r
-+void\r
-+ar531x_irq_dispatch(struct pt_regs *regs)\r
-+{\r
-+      int cause_intrs = regs->cp0_cause;\r
-+      int status_intrs = regs->cp0_status;\r
-+      int pending = cause_intrs & status_intrs;\r
-+\r
-+      if (pending & CAUSEF_IP2) {\r
-+              do_IRQ(AR531X_IRQ_WLAN0_INTRS, regs);\r
-+      }               \r
-+      else if (pending & CAUSEF_IP3) {\r
-+              do_IRQ(AR531X_IRQ_ENET0_INTRS, regs);\r
-+      }\r
-+      else if (pending & CAUSEF_IP4) {\r
-+              do_IRQ(AR531X_IRQ_ENET1_INTRS, regs);\r
-+      }\r
-+      else if (pending & CAUSEF_IP5) {\r
-+              do_IRQ(AR531X_IRQ_WLAN1_INTRS, regs);\r
-+      }\r
-+      else if (pending & CAUSEF_IP6) {\r
-+              AR531X_REG ar531x_isr = sysRegRead(AR531X_ISR);\r
-+              AR531X_REG ar531x_imr = sysRegRead(AR531X_IMR);\r
-+              unsigned int ar531x_misc_intrs = ar531x_isr & ar531x_imr;\r
-+\r
-+              if (ar531x_misc_intrs & AR531X_ISR_TIMER)\r
-+                      do_IRQ(AR531X_MISC_IRQ_TIMER, regs);\r
-+              else if (ar531x_misc_intrs & AR531X_ISR_AHBPROC)\r
-+                      do_IRQ(AR531X_MISC_IRQ_AHB_PROC, regs);\r
-+              else if (ar531x_misc_intrs & AR531X_ISR_AHBDMA)\r
-+                      do_IRQ(AR531X_MISC_IRQ_AHB_DMA, regs);\r
-+              else if (ar531x_misc_intrs & AR531X_ISR_GPIO)\r
-+                {\r
-+                    int i;\r
-+                    u32 gpioIntPending;\r
-+\r
-+                    gpioIntPending = sysRegRead(AR531X_GPIO_DI) & gpioIntMask;\r
-+                    for (i=0; i<AR531X_GPIO_IRQ_COUNT; i++) {\r
-+                        if (gpioIntPending & (1 << i))\r
-+                            do_IRQ(AR531X_GPIO_IRQ(i), regs);\r
-+                    }\r
-+                }\r
-+              else if ((ar531x_misc_intrs & AR531X_ISR_UART0) ||\r
-+                       (ar531x_misc_intrs & AR531X_ISR_UART0DMA)) {\r
-+                      do_IRQ(AR531X_MISC_IRQ_UART0, regs);\r
-+#if CONFIG_KGDB\r
-+                        if (kgdbInterrupt()) {\r
-+                                if (!user_mode(regs))\r
-+                                  set_async_breakpoint((unsigned long *)&regs->cp0_epc);\r
-+                        }\r
-+#endif        /* CONFIG_KGDB */\r
-+                }\r
-+              else if (ar531x_misc_intrs & AR531X_ISR_WD)\r
-+                      do_IRQ(AR531X_MISC_IRQ_WATCHDOG, regs);\r
-+              else if (ar531x_misc_intrs & AR531X_ISR_LOCAL)\r
-+                      do_IRQ(AR531X_MISC_IRQ_LOCAL, regs);\r
-+              else\r
-+                      do_IRQ(AR531X_MISC_IRQ_NONE, regs);\r
-+      } else if (pending & CAUSEF_IP7)\r
-+              do_IRQ(AR531X_IRQ_CPU_CLOCK, regs);\r
-+      else\r
-+              do_IRQ(AR531X_IRQ_NONE, regs);\r
-+}\r
-+\r
-+void __init init_IRQ(void)\r
-+{\r
-+      init_generic_irq();\r
-+      set_except_vector(0, ar531x_interrupt_receive);\r
-+\r
-+      /* Initialize interrupt controllers */\r
-+      mips_cpu_irq_init(MIPS_CPU_IRQ_BASE);\r
-+      ar531x_misc_intr_init(AR531X_MISC_IRQ_BASE);\r
-+        ar531x_gpio_intr_init(AR531X_GPIO_IRQ_BASE);\r
-+      setup_irq(AR531X_IRQ_MISC_INTRS, &cascade);\r
-+      /*\r
-+         * AR531X_IRQ_CPU_CLOCK is setup by ar531x_timer_setup.\r
-+         */\r
-+\r
-+      /* Default "spurious interrupt" handlers */\r
-+      setup_irq(AR531X_IRQ_NONE, &spurious_irq);\r
-+      setup_irq(AR531X_MISC_IRQ_NONE, &spurious_misc);\r
-+      setup_irq(AR531X_GPIO_IRQ_NONE, &spurious_gpio);\r
-+\r
-+      setup_irq(AR531X_MISC_IRQ_TIMER, &ar531x_timer_interrupt);\r
-+      setup_irq(AR531X_MISC_IRQ_AHB_PROC, &ar531x_ahb_proc_interrupt);\r
-+        setup_irq(AR531X_MISC_IRQ_GPIO, &cascade);\r
-+\r
-+#ifdef CONFIG_KGDB\r
-+#if CONFIG_EARLY_STOP\r
-+        kgdbInit();\r
-+#endif\r
-+#endif\r
-+}\r
-diff -urN linux-2.4.32/arch/mips/ar531x/ar531xksyms.c linux-2.4.32.new/arch/mips/ar531x/ar531xksyms.c\r
---- linux-2.4.32/arch/mips/ar531x/ar531xksyms.c        1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/ar531xksyms.c    2005-12-24 20:29:42.132306768 +0000\r
-@@ -0,0 +1,16 @@\r
-+/*\r
-+ * This file is subject to the terms and conditions of the GNU General Public\r
-+ * License.  See the file "COPYING" in the main directory of this archive\r
-+ * for more details.\r
-+ *\r
-+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.\r
-+ */\r
-+\r
-+#include <linux/module.h>\r
-+#include "asm/atheros/ar531xbsp.h"\r
-+\r
-+#if CONFIG_KGDB\r
-+EXPORT_SYMBOL(kgdbInit);\r
-+EXPORT_SYMBOL(kgdbEnabled);\r
-+#endif\r
-+EXPORT_SYMBOL(ar531x_sys_frequency);\r
-diff -urN linux-2.4.32/arch/mips/ar531x/ar531xlnx.h linux-2.4.32.new/arch/mips/ar531x/ar531xlnx.h\r
---- linux-2.4.32/arch/mips/ar531x/ar531xlnx.h  1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/ar531xlnx.h      2005-12-24 20:29:42.133306616 +0000\r
-@@ -0,0 +1,122 @@\r
-+/*\r
-+ * This file is subject to the terms and conditions of the GNU General Public\r
-+ * License.  See the file "COPYING" in the main directory of this archive\r
-+ * for more details.\r
-+ *\r
-+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.\r
-+ */\r
-+\r
-+/*\r
-+ * This file contains definitions needed in order to compile\r
-+ * AR531X products for linux.  Definitions that are largely\r
-+ * AR531X-specific and independent of operating system belong\r
-+ * in ar531x.h rather than this file.\r
-+ */\r
-+#include "ar531x.h"\r
-+\r
-+#define MIPS_CPU_IRQ_BASE             0x00\r
-+#define AR531X_HIGH_PRIO                0x10\r
-+#define AR531X_MISC_IRQ_BASE          0x20\r
-+#define AR531X_GPIO_IRQ_BASE            0x30\r
-+\r
-+/* Software's idea of interrupts handled by "CPU Interrupt Controller" */\r
-+#define AR531X_IRQ_NONE               MIPS_CPU_IRQ_BASE+0\r
-+#define AR531X_IRQ_WLAN0_INTRS        MIPS_CPU_IRQ_BASE+2 /* C0_CAUSE: 0x0400 */\r
-+#define AR531X_IRQ_ENET0_INTRS        MIPS_CPU_IRQ_BASE+3 /* C0_CAUSE: 0x0800 */\r
-+#define AR531X_IRQ_ENET1_INTRS        MIPS_CPU_IRQ_BASE+4 /* C0_CAUSE: 0x1000 */\r
-+#define AR531X_IRQ_WLAN1_INTRS        MIPS_CPU_IRQ_BASE+5 /* C0_CAUSE: 0x2000 */\r
-+#define AR531X_IRQ_MISC_INTRS MIPS_CPU_IRQ_BASE+6 /* C0_CAUSE: 0x4000 */\r
-+#define AR531X_IRQ_CPU_CLOCK  MIPS_CPU_IRQ_BASE+7 /* C0_CAUSE: 0x8000 */\r
-+\r
-+/* Miscellaneous interrupts, which share IP6 */\r
-+#define AR531X_MISC_IRQ_NONE          AR531X_MISC_IRQ_BASE+0\r
-+#define AR531X_MISC_IRQ_TIMER         AR531X_MISC_IRQ_BASE+1\r
-+#define AR531X_MISC_IRQ_AHB_PROC      AR531X_MISC_IRQ_BASE+2\r
-+#define AR531X_MISC_IRQ_AHB_DMA               AR531X_MISC_IRQ_BASE+3\r
-+#define AR531X_MISC_IRQ_GPIO          AR531X_MISC_IRQ_BASE+4\r
-+#define AR531X_MISC_IRQ_UART0         AR531X_MISC_IRQ_BASE+5\r
-+#define AR531X_MISC_IRQ_UART0_DMA     AR531X_MISC_IRQ_BASE+6\r
-+#define AR531X_MISC_IRQ_WATCHDOG      AR531X_MISC_IRQ_BASE+7\r
-+#define AR531X_MISC_IRQ_LOCAL         AR531X_MISC_IRQ_BASE+8\r
-+#define AR531X_MISC_IRQ_COUNT         9\r
-+\r
-+/* GPIO Interrupts [0..7], share AR531X_MISC_IRQ_GPIO */\r
-+#define AR531X_GPIO_IRQ_NONE            AR531X_MISC_IRQ_BASE+0\r
-+#define AR531X_GPIO_IRQ(n)              AR531X_MISC_IRQ_BASE+(n)+1\r
-+#define AR531X_GPIO_IRQ_COUNT           9\r
-+\r
-+#define PHYS_TO_K1(physaddr) KSEG1ADDR(physaddr)\r
-+#define PHYS_TO_K0(physaddr) KSEG0ADDR(physaddr)\r
-+#define UNMAPPED_TO_PHYS(vaddr)  PHYSADDR(vaddr)\r
-+#define IS_UNMAPPED_VADDR(vaddr) \\r
-+    ((KSEGX(vaddr) == KSEG0) || (KSEGX(vaddr) == KSEG1))\r
-+\r
-+/* IOCTL commands for /proc/ar531x */\r
-+#define AR531X_CTRL_DO_BREAKPOINT       1\r
-+#define AR531X_CTRL_DO_MADWIFI          2\r
-+\r
-+/*\r
-+ * Definitions for operating system portability.\r
-+ * These are vxWorks-->Linux translations.\r
-+ */\r
-+#define LOCAL static\r
-+#define BOOL int\r
-+#define TRUE 1\r
-+#define FALSE 0\r
-+#define UINT8 u8\r
-+#define UINT16 u16\r
-+#define UINT32 u32\r
-+#define PRINTF printk\r
-+#if /* DEBUG */ 1\r
-+#define DEBUG_PRINTF printk\r
-+#define INLINE\r
-+#else\r
-+DEBUG_PRINTF while (0) printk\r
-+#define INLINE inline\r
-+#endif\r
-+#define sysUDelay(usecs) udelay(usecs)\r
-+#define sysMsDelay(msecs) mdelay(msecs)\r
-+typedef volatile UINT8 *VIRT_ADDR;\r
-+#define MALLOC(sz) kmalloc(sz, GFP_KERNEL)\r
-+#define MALLOC_NOSLEEP(sz) kmalloc(sz, GFP_ATOMIC)\r
-+#define FREE(ptr) kfree((void *)ptr)\r
-+#define BSP_BUG() do { printk("kernel BSP BUG at %s:%d!\n", __FILE__, __LINE__); *(int *)0=0; } while (0)\r
-+#define BSP_BUG_ON(condition) do { if (unlikely((condition)!=0)) BSP_BUG(); } while(0)\r
-+#define ASSERT(x) BSP_BUG_ON(!(x))\r
-+\r
-+extern struct ar531x_boarddata *ar531x_board_configuration;\r
-+extern char *ar531x_radio_configuration;\r
-+extern char *enet_mac_address_get(int MACUnit);\r
-+\r
-+extern void kgdbInit(void);\r
-+extern int kgdbEnabled(void);\r
-+extern void breakpoint(void);\r
-+extern int kgdbInterrupt(void);\r
-+extern unsigned int ar531x_cpu_frequency(void);\r
-+extern unsigned int ar531x_sys_frequency(void);\r
-+\r
-+/* GPIO support */\r
-+extern struct irqaction spurious_gpio;\r
-+extern unsigned int gpioIntMask;\r
-+extern void ar531x_gpio_intr_init(int irq_base);\r
-+extern void ar531x_gpio_ctrl_output(int gpio);\r
-+extern void ar531x_gpio_ctrl_input(int gpio);\r
-+extern void ar531x_gpio_set(int gpio, int val);\r
-+extern int  ar531x_gpio_get(int gpio);\r
-+extern void ar531x_gpio_intr_enable(unsigned int irq);\r
-+extern void ar531x_gpio_intr_disable(unsigned int irq);\r
-+\r
-+/* Watchdog Timer support */\r
-+extern int watchdog_start(unsigned int milliseconds);\r
-+extern int watchdog_stop(void);\r
-+extern int watchdog_is_enabled(void);\r
-+extern unsigned int watchdog_min_timer_reached(void);\r
-+extern void watchdog_notify_alive(void);\r
-+\r
-+#define A_DATA_CACHE_INVAL(start, length) \\r
-+        dma_cache_inv((UINT32)(start),(length))\r
-+\r
-+#define sysWbFlush() mb()\r
-+\r
-+#define intDisable(x) cli()\r
-+#define intEnable(x) sti()\r
-diff -urN linux-2.4.32/arch/mips/ar531x/ar531xprom.c linux-2.4.32.new/arch/mips/ar531x/ar531xprom.c\r
---- linux-2.4.32/arch/mips/ar531x/ar531xprom.c 1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/ar531xprom.c     2005-12-24 20:29:42.133306616 +0000\r
-@@ -0,0 +1,84 @@\r
-+/*\r
-+ * This file is subject to the terms and conditions of the GNU General Public\r
-+ * License.  See the file "COPYING" in the main directory of this archive\r
-+ * for more details.\r
-+ *\r
-+ * Copyright MontaVista Software Inc\r
-+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.\r
-+ */\r
-+\r
-+/*\r
-+ * Prom setup file for ar531x\r
-+ */\r
-+\r
-+#include <linux/init.h>\r
-+#include <linux/config.h>\r
-+#include <linux/kernel.h>\r
-+#include <linux/string.h>\r
-+#include <linux/mm.h>\r
-+#include <linux/bootmem.h>\r
-+\r
-+#include <asm/bootinfo.h>\r
-+#include <asm/addrspace.h>\r
-+\r
-+#include "ar531xlnx.h"\r
-+\r
-+#define COMMAND_LINE_SIZE 512\r
-+\r
-+char arcs_cmdline[COMMAND_LINE_SIZE];\r
-+\r
-+void __init prom_init(int argc, char *argv[])\r
-+{\r
-+    int i;\r
-+    unsigned int memcfg1;\r
-+    int bank0AC, bank1AC;\r
-+    int memsz_in_mb;\r
-+\r
-+    strcpy(arcs_cmdline, "console=ttyS0,9600");\r
-+    for (i=0; i<argc; i++) {\r
-+        strcat(arcs_cmdline, " ");\r
-+        strcat(arcs_cmdline, argv[i]);\r
-+    }\r
-+\r
-+    mips_machgroup = MACH_GROUP_AR531X;\r
-+#ifdef CONFIG_APUNUSED\r
-+    mips_machtype = MACH_ATHEROS_UNUSED;\r
-+#endif\r
-+#ifdef CONFIG_AP30\r
-+    mips_machtype = MACH_ATHEROS_AP30;\r
-+#endif\r
-+#ifdef CONFIG_AP33\r
-+    mips_machtype = MACH_ATHEROS_AP33;\r
-+#endif\r
-+#ifdef CONFIG_AP38\r
-+    mips_machtype = MACH_ATHEROS_AP38;\r
-+#endif\r
-+#ifdef CONFIG_AP43\r
-+    mips_machtype = MACH_ATHEROS_AP43;\r
-+#endif\r
-+#ifdef CONFIG_AP48\r
-+    mips_machtype = MACH_ATHEROS_AP48;\r
-+#endif\r
-+#ifdef CONFIG_PB32\r
-+    mips_machtype = MACH_ATHEROS_PB32;\r
-+#endif\r
-+\r
-+\r
-+    /* Determine SDRAM size based on Address Checks done at startup */\r
-+    memcfg1 = sysRegRead(AR531X_MEM_CFG1);\r
-+    bank0AC = (memcfg1 & MEM_CFG1_AC0) >> MEM_CFG1_AC0_S;\r
-+    bank1AC = (memcfg1 & MEM_CFG1_AC1) >> MEM_CFG1_AC1_S;\r
-+    memsz_in_mb = (bank0AC ? (1 << (bank0AC+1)) : 0)\r
-+                + (bank1AC ? (1 << (bank1AC+1)) : 0);\r
-+\r
-+    /*\r
-+     * By default, use all available memory.  You can override this\r
-+     * to use, say, 8MB by specifying "mem=8M" as an argument on the\r
-+     * linux bootup command line.\r
-+     */\r
-+    add_memory_region(0, memsz_in_mb << 20, BOOT_MEM_RAM);\r
-+}\r
-+\r
-+void __init prom_free_prom_memory(void)\r
-+{\r
-+}\r
-diff -urN linux-2.4.32/arch/mips/ar531x/ar531xsetup.c linux-2.4.32.new/arch/mips/ar531x/ar531xsetup.c\r
---- linux-2.4.32/arch/mips/ar531x/ar531xsetup.c        1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/ar531xsetup.c    2005-12-24 20:29:42.133306616 +0000\r
-@@ -0,0 +1,240 @@\r
-+/*\r
-+ * This file is subject to the terms and conditions of the GNU General Public\r
-+ * License.  See the file "COPYING" in the main directory of this archive\r
-+ * for more details.\r
-+ *\r
-+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.\r
-+ */\r
-+\r
-+/*\r
-+ * Initialization for ar531x SOC.\r
-+ */\r
-+\r
-+#include <linux/config.h>\r
-+#include <linux/init.h>\r
-+#include <linux/delay.h>\r
-+#include <linux/irq.h>\r
-+#include <linux/interrupt.h>\r
-+#include <linux/serial.h>\r
-+#include <linux/types.h>\r
-+#include <linux/string.h>\r
-+\r
-+#include <asm/reboot.h>\r
-+#include <asm/io.h>\r
-+#include <asm/time.h>\r
-+#include <asm/pgtable.h>\r
-+#include <asm/processor.h>\r
-+#include <asm/reboot.h>\r
-+#include <asm/system.h>\r
-+#include <asm/serial.h>\r
-+\r
-+#include "ar531xlnx.h"\r
-+\r
-+void\r
-+ar531x_restart(char *command)\r
-+{\r
-+    for(;;) {\r
-+        sysRegWrite(AR531X_RESET, AR531X_RESET_SYSTEM);\r
-+    }\r
-+}\r
-+\r
-+void\r
-+ar531x_halt(void)\r
-+{\r
-+        printk(KERN_NOTICE "\n** You can safely turn off the power\n");\r
-+        while (1);\r
-+}\r
-+\r
-+void\r
-+ar531x_power_off(void)\r
-+{\r
-+        ar531x_halt();\r
-+}\r
-+\r
-+const char *\r
-+get_system_type(void)\r
-+{\r
-+      return "Atheros AR531X";\r
-+}\r
-+\r
-+/*\r
-+ * This table is indexed by bits 5..4 of the CLOCKCTL1 register\r
-+ * to determine the predevisor value.\r
-+ */\r
-+static int CLOCKCTL1_PREDIVIDE_TABLE[4] = {\r
-+    1,\r
-+    2,\r
-+    4,\r
-+    5\r
-+};\r
-+\r
-+unsigned int\r
-+ar531x_cpu_frequency(void)\r
-+{\r
-+      static unsigned int ar531x_calculated_cpu_freq;\r
-+        unsigned int clockctl1_predivide_mask;\r
-+        unsigned int clockctl1_predivide_shift;\r
-+        unsigned int clockctl1_multiplier_mask;\r
-+        unsigned int clockctl1_multiplier_shift;\r
-+        unsigned int clockctl1_doubler_mask;\r
-+        int wisoc_revision;\r
-+\r
-+        /*\r
-+         * Trust the bootrom's idea of cpu frequency.\r
-+         */\r
-+        ar531x_calculated_cpu_freq = sysRegRead(AR5312_SCRATCH);\r
-+        if (ar531x_calculated_cpu_freq)\r
-+          return ar531x_calculated_cpu_freq;\r
-+\r
-+        wisoc_revision = (sysRegRead(AR531X_REV) & AR531X_REV_MAJ) >> AR531X_REV_MAJ_S;\r
-+        if (wisoc_revision == AR531X_REV_MAJ_AR2313) {\r
-+            clockctl1_predivide_mask = AR2313_CLOCKCTL1_PREDIVIDE_MASK;\r
-+            clockctl1_predivide_shift = AR2313_CLOCKCTL1_PREDIVIDE_SHIFT;\r
-+            clockctl1_multiplier_mask = AR2313_CLOCKCTL1_MULTIPLIER_MASK;\r
-+            clockctl1_multiplier_shift = AR2313_CLOCKCTL1_MULTIPLIER_SHIFT;\r
-+            clockctl1_doubler_mask = AR2313_CLOCKCTL1_DOUBLER_MASK;\r
-+        } else { /* AR5312 and AR2312 */\r
-+            clockctl1_predivide_mask = AR5312_CLOCKCTL1_PREDIVIDE_MASK;\r
-+            clockctl1_predivide_shift = AR5312_CLOCKCTL1_PREDIVIDE_SHIFT;\r
-+            clockctl1_multiplier_mask = AR5312_CLOCKCTL1_MULTIPLIER_MASK;\r
-+            clockctl1_multiplier_shift = AR5312_CLOCKCTL1_MULTIPLIER_SHIFT;\r
-+            clockctl1_doubler_mask = AR5312_CLOCKCTL1_DOUBLER_MASK;\r
-+        }\r
-+\r
-+        /*\r
-+         * Clocking is derived from a fixed 40MHz input clock.\r
-+         *  cpuFreq = InputClock * MULT (where MULT is PLL multiplier)\r
-+         *\r
-+         *  sysFreq = cpuFreq / 4       (used for APB clock, serial,\r
-+         *                               flash, Timer, Watchdog Timer)\r
-+         *\r
-+         *  cntFreq = cpuFreq / 2       (use for CPU count/compare)\r
-+         *\r
-+         * So, for example, with a PLL multiplier of 5, we have\r
-+         *  cpuFrez = 200MHz\r
-+         *  sysFreq = 50MHz\r
-+         *  cntFreq = 100MHz\r
-+         *\r
-+         * We compute the CPU frequency, based on PLL settings.\r
-+         */\r
-+      if (ar531x_calculated_cpu_freq == 0) {\r
-+            unsigned int clockCtl1 = sysRegRead(AR5312_CLOCKCTL1);\r
-+\r
-+            int preDivideSelect = (clockCtl1 & clockctl1_predivide_mask) >>\r
-+                                   clockctl1_predivide_shift;\r
-+\r
-+            int preDivisor = CLOCKCTL1_PREDIVIDE_TABLE[preDivideSelect];\r
-+\r
-+            int multiplier = (clockCtl1 & clockctl1_multiplier_mask) >>\r
-+                              clockctl1_multiplier_shift;\r
-+\r
-+            if (clockCtl1 & clockctl1_doubler_mask) {\r
-+                multiplier = multiplier << 1;\r
-+            }\r
-+\r
-+            ar531x_calculated_cpu_freq = (40000000 / preDivisor) * multiplier;\r
-+        }\r
-+\r
-+      return ar531x_calculated_cpu_freq;\r
-+}\r
-+\r
-+unsigned int\r
-+ar531x_sys_frequency(void)\r
-+{\r
-+      static unsigned int ar531x_calculated_sys_freq = 0;\r
-+\r
-+      if (ar531x_calculated_sys_freq == 0) {\r
-+              ar531x_calculated_sys_freq = ar531x_cpu_frequency() / 4;\r
-+      }\r
-+\r
-+      return ar531x_calculated_sys_freq;\r
-+}\r
-+\r
-+static void __init\r
-+flash_setup(void)\r
-+{\r
-+    UINT32 flash_ctl;\r
-+\r
-+    /* Configure flash bank 0 */\r
-+    flash_ctl = FLASHCTL_E |\r
-+                FLASHCTL_AC_8M |\r
-+                FLASHCTL_RBLE |\r
-+                (0x01 << FLASHCTL_IDCY_S) |\r
-+                (0x07 << FLASHCTL_WST1_S) |\r
-+                (0x07 << FLASHCTL_WST2_S) |\r
-+                (sysRegRead(AR531X_FLASHCTL0) & FLASHCTL_MW);\r
-+\r
-+    sysRegWrite(AR531X_FLASHCTL0, flash_ctl);\r
-+\r
-+    /* Disable other flash banks */\r
-+    sysRegWrite(AR531X_FLASHCTL1,\r
-+                sysRegRead(AR531X_FLASHCTL1) & ~(FLASHCTL_E | FLASHCTL_AC));\r
-+\r
-+    sysRegWrite(AR531X_FLASHCTL2,\r
-+                sysRegRead(AR531X_FLASHCTL2) & ~(FLASHCTL_E | FLASHCTL_AC));\r
-+}\r
-+\r
-+\r
-+\r
-+void __init\r
-+serial_setup(void)\r
-+{\r
-+      struct serial_struct s;\r
-+\r
-+      memset(&s, 0, sizeof(s));\r
-+\r
-+      s.flags = STD_COM_FLAGS;\r
-+      s.io_type = SERIAL_IO_MEM;\r
-+      s.baud_base = ar531x_sys_frequency()/16;\r
-+      s.irq = AR531X_MISC_IRQ_UART0;\r
-+      s.iomem_reg_shift = 2;\r
-+      s.iomem_base = (u8 *)0xbc000003;\r
-+\r
-+      if (early_serial_setup(&s) != 0)\r
-+              printk(KERN_ERR "early_serial_setup failed\n");\r
-+}\r
-+\r
-+extern int setup_irq(unsigned int irq, struct irqaction *irqaction);\r
-+static void __init\r
-+ar531x_timer_setup(struct irqaction *irq)\r
-+{\r
-+        unsigned int count;\r
-+\r
-+      /* Usually irq is timer_irqaction (timer_interrupt) */\r
-+              setup_irq(AR531X_IRQ_CPU_CLOCK, irq);\r
-+\r
-+        /* to generate the first CPU timer interrupt */\r
-+        count = read_c0_count();\r
-+        write_c0_compare(count + 1000);\r
-+}\r
-+\r
-+extern void (*board_time_init)(void);\r
-+\r
-+static void __init\r
-+ar531x_time_init(void)\r
-+{\r
-+      mips_hpt_frequency = ar531x_cpu_frequency() / 2;\r
-+}\r
-+\r
-+void __init\r
-+ar531x_setup(void)\r
-+{\r
-+      /* Clear any lingering AHB errors */\r
-+      sysRegRead(AR531X_PROCADDR);\r
-+      sysRegRead(AR531X_DMAADDR);\r
-+\r
-+      sysRegWrite(AR531X_WD_CTRL, AR531X_WD_CTRL_IGNORE_EXPIRATION);\r
-+\r
-+        /* Disable data watchpoints */\r
-+        write_c0_watchlo0(0);\r
-+\r
-+      board_time_init = ar531x_time_init;\r
-+        board_timer_setup = ar531x_timer_setup;\r
-+\r
-+        _machine_restart = ar531x_restart;\r
-+        _machine_halt = ar531x_halt;\r
-+        _machine_power_off = ar531x_power_off;\r
-+\r
-+        flash_setup();\r
-+        serial_setup();\r
-+}\r
-diff -urN linux-2.4.32/arch/mips/ar531x/Makefile linux-2.4.32.new/arch/mips/ar531x/Makefile\r
---- linux-2.4.32/arch/mips/ar531x/Makefile     1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/Makefile 2005-12-24 20:29:42.010325312 +0000\r
-@@ -0,0 +1,33 @@\r
-+#\r
-+# This file is subject to the terms and conditions of the GNU General Public\r
-+# License.  See the file "COPYING" in the main directory of this archive\r
-+# for more details.\r
-+#\r
-+# Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.\r
-+#\r
-+\r
-+# Makefile for Atheros ar531x boards\r
-+#\r
-+# Note! Dependencies are done automagically by 'make dep', which also\r
-+# removes any old dependencies. DON'T put your own dependencies here\r
-+# unless it's something special (ie not a .c file).\r
-+#\r
-+\r
-+.S.s:\r
-+      $(CPP) $(CFLAGS) $< -o $*.s\r
-+.S.o:\r
-+      $(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $*.o\r
-+\r
-+O_TARGET:= ar531x.o\r
-+\r
-+export-objs = ar531xksyms.o\r
-+\r
-+obj-y    := ar531xdbg_io.o    \\r
-+      ar531xsetup.o   \\r
-+      ar531xprom.o    \\r
-+      ar531xirq.o     \\r
-+      ar531xintr.o    \\r
-+      ar531xgpio.o    \\r
-+      ar531xksyms.o\r
-+\r
-+include $(TOPDIR)/Rules.make\r
-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\r
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/backup-busybox.links 1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/backup-busybox.links     2005-12-24 20:29:42.011325160 +0000\r
-@@ -0,0 +1,33 @@\r
-+/usr/bin/[\r
-+/sbin/brctl\r
-+/bin/cat\r
-+/bin/chmod\r
-+/bin/cp\r
-+/bin/df\r
-+/bin/echo\r
-+/bin/false\r
-+/sbin/ifconfig\r
-+/sbin/init\r
-+/sbin/insmod\r
-+/bin/kill\r
-+/bin/ls\r
-+/sbin/lsmod\r
-+/bin/mkdir\r
-+/sbin/modprobe\r
-+/bin/mount\r
-+/bin/msh\r
-+/bin/mv\r
-+/bin/ping\r
-+/bin/ps\r
-+/bin/pwd\r
-+/sbin/reboot\r
-+/bin/rm\r
-+/bin/rmdir\r
-+/sbin/rmmod\r
-+/sbin/route\r
-+/bin/sh\r
-+/usr/bin/test\r
-+/usr/bin/top\r
-+/bin/true\r
-+/bin/umount\r
-+/usr/bin/wget\r
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/busybox.links linux-2.4.32.new/arch/mips/ar531x/RAMDISK/busybox.links\r
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/busybox.links        1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/busybox.links    2005-12-24 20:29:42.011325160 +0000\r
-@@ -0,0 +1,33 @@\r
-+/usr/bin/[\r
-+/sbin/brctl\r
-+/bin/cat\r
-+/bin/chmod\r
-+/bin/cp\r
-+/bin/df\r
-+/bin/echo\r
-+/bin/false\r
-+/sbin/ifconfig\r
-+/sbin/init\r
-+/sbin/insmod\r
-+/bin/kill\r
-+/bin/ls\r
-+/sbin/lsmod\r
-+/bin/mkdir\r
-+/sbin/modprobe\r
-+/bin/mount\r
-+/bin/msh\r
-+/bin/mv\r
-+/bin/ping\r
-+/bin/ps\r
-+/bin/pwd\r
-+/sbin/reboot\r
-+/bin/rm\r
-+/bin/rmdir\r
-+/sbin/rmmod\r
-+/sbin/route\r
-+/bin/sh\r
-+/usr/bin/test\r
-+/bin/true\r
-+/bin/umount\r
-+/bin/uname\r
-+/usr/bin/wget\r
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/Makefile linux-2.4.32.new/arch/mips/ar531x/RAMDISK/Makefile\r
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/Makefile     1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/Makefile 2005-12-24 20:29:42.011325160 +0000\r
-@@ -0,0 +1,53 @@\r
-+KERNEL_SOURCE=../../../..\r
-+\r
-+# The value for INITRDSIZE is extracted from linux/.config,\r
-+# if it exists; otherwise, a default value is used.\r
-+\r
-+CONFIG_FILE = $(KERNEL_SOURCE)/.config\r
-+\r
-+ifeq ($(CONFIG_FILE),$(wildcard $(CONFIG_FILE)))\r
-+\r
-+include $(CONFIG_FILE)\r
-+ifdef CONFIG_BLK_DEV_RAM_SIZE\r
-+INITRDSIZE  := $(shell echo $(CONFIG_BLK_DEV_RAM_SIZE))\r
-+else\r
-+INITRDSIZE := 8192\r
-+endif\r
-+\r
-+else\r
-+INITRDSIZE := 8192\r
-+endif\r
-+\r
-+MOUNTPT = /mnt/xtmp\r
-+\r
-+ramdisk.gz: ramdisk\r
-+      gzip -f ramdisk\r
-+\r
-+ramdisk:\r
-+      ./makelinks  \r
-+      @echo "CREATING RAMDISK OF SIZE $(INITRDSIZE) on $@"\r
-+      dd if=/dev/zero of=$@ bs=1k count=$(INITRDSIZE)\r
-+      /sbin/mke2fs -vFm0 $@ $(INITRDSIZE)\r
-+      if [ \! -e $(MOUNTPT) ]; then mkdir -p $(MOUNTPT) ; fi\r
-+      mount -o loop $@ $(MOUNTPT)\r
-+      @df $(MOUNTPT)\r
-+      (cd rootdir; tar cf - . ) | (cd $(MOUNTPT) && tar xf - )\r
-+      (cd $(MOUNTPT) ; chown -R root.root . )\r
-+      @df $(MOUNTPT)\r
-+      umount $(MOUNTPT)\r
-+\r
-+install:\r
-+      @(if [ -d $(KERNEL_SOURCE)/arch/mips/ramdisk ]; \\r
-+      then \\r
-+              if [ -f ramdisk.gz ]; \\r
-+              then \\r
-+                      cp ramdisk.gz $(KERNEL_SOURCE)/arch/mips/ramdisk/; \\r
-+              else \\r
-+                      echo "No ramdisk.gz image"; \\r
-+              fi; \\r
-+      else \\r
-+              echo "No ramdisk directory.  Check KERNEL_SOURCE variable."; \\r
-+      fi)\r
-+\r
-+clean:        \r
-+      rm -f ramdisk.gz ramdisk\r
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/makelinks linux-2.4.32.new/arch/mips/ar531x/RAMDISK/makelinks\r
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/makelinks    1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/makelinks        2005-12-24 20:29:42.012325008 +0000\r
-@@ -0,0 +1,65 @@\r
-+#!/bin/sh\r
-+\r
-+if [ -f busybox.links ]\r
-+then\r
-+    cat busybox.links | sed 's/\//ln -s -f \/bin\/busybox rootdir\//' | /bin/sh\r
-+fi\r
-+\r
-+cons="  root tty    622"\r
-+disk="  root disk   660"\r
-+mtd="  root root   640"\r
-+makedev () {    # usage: makedev name [bcu] major minor owner group mode\r
-+        if [ "$opt_v" ]\r
-+        then    if [ "$opt_d" ]\r
-+                then    echo "rm -f $1"\r
-+                else    echo "$1        = $2 $3 $4 $5:$6 $7"\r
-+                fi\r
-+        fi\r
-+        [ ! "$opt_n" ] && rm -f $1 &&\r
-+        [ ! "$opt_d" ] && mknod $1 $2 $3 $4 &&\r
-+                chown $5:$6 $1 &&\r
-+                chmod $7 $1\r
-+}  \r
-+\r
-+makedev rootdir/dev/console c 5 1 $cons\r
-+makedev rootdir/dev/ram  b 1 1 $disk \r
-+makedev rootdir/dev/ram0 b 1 0 $disk\r
-+makedev rootdir/dev/ram1 b 1 1 $disk \r
-+makedev rootdir/dev/ram2 b 1 2 $disk\r
-+makedev rootdir/dev/ram3 b 1 3 $disk\r
-+makedev rootdir/dev/ram4 b 1 4 $disk\r
-+makedev rootdir/dev/ram5 b 1 5 $disk\r
-+makedev rootdir/dev/ram6 b 1 6 $disk\r
-+makedev rootdir/dev/ram7 b 1 7 $disk\r
-+makedev rootdir/dev/ram8 b 1 8 $disk\r
-+makedev rootdir/dev/ram9 b 1 9 $disk\r
-+makedev rootdir/dev/ram10 b 1 10 $disk\r
-+makedev rootdir/dev/ram11 b 1 11 $disk\r
-+makedev rootdir/dev/ram12 b 1 12 $disk\r
-+makedev rootdir/dev/ram13 b 1 13 $disk\r
-+makedev rootdir/dev/ram14 b 1 14 $disk\r
-+makedev rootdir/dev/ram15 b 1 15 $disk\r
-+\r
-+makedev rootdir/dev/mtd0 c 90 0 $mtd\r
-+makedev rootdir/dev/mtd1 c 90 2 $mtd\r
-+makedev rootdir/dev/mtd2 c 90 4 $mtd\r
-+makedev rootdir/dev/mtd3 c 90 6 $mtd\r
-+makedev rootdir/dev/mtd4 c 90 8 $mtd\r
-+makedev rootdir/dev/mtd5 c 90 10 $mtd\r
-+makedev rootdir/dev/mtd6 c 90 12 $mtd\r
-+makedev rootdir/dev/mtdblock0 b 31 0 $mtd\r
-+makedev rootdir/dev/mtdblock1 b 31 1 $mtd\r
-+makedev rootdir/dev/mtdblock2 b 31 2 $mtd\r
-+makedev rootdir/dev/mtdblock3 b 31 3 $mtd\r
-+makedev rootdir/dev/mtdblock4 b 31 4 $mtd\r
-+makedev rootdir/dev/mtdblock5 b 31 5 $mtd\r
-+makedev rootdir/dev/mtdblock6 b 31 6 $mtd\r
-+makedev rootdir/dev/mtdr0 c 90 1 $mtd\r
-+makedev rootdir/dev/mtdr1 c 90 3 $mtd\r
-+makedev rootdir/dev/mtdr2 c 90 5 $mtd\r
-+makedev rootdir/dev/mtdr3 c 90 7 $mtd\r
-+makedev rootdir/dev/mtdr4 c 90 9 $mtd\r
-+makedev rootdir/dev/mtdr5 c 90 11 $mtd\r
-+makedev rootdir/dev/mtdr6 c 90 13 $mtd\r
-+\r
-+cd rootdir/dev;ln -sf ram1 ram\r
-diff -urN linux-2.4.32/arch/mips/ar531x/RAMDISK/README linux-2.4.32.new/arch/mips/ar531x/RAMDISK/README\r
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/README       1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/README   2005-12-24 20:29:42.011325160 +0000\r
-@@ -0,0 +1,40 @@\r
-+How to build a ramdisk image for use as a root filesystem with AR531X\r
-+\r
-+Overview:\r
-+In order to boot from a ramdisk root file system image, you will\r
-+first create a root directory structure in the "rootdir" directory.\r
-+Then run "make" to create a compressed root file system image in\r
-+ramdisk.gz.  Finally, copy this image into your kernel source tree\r
-+and remake the kernel.  The ramdisk image is then built into the\r
-+kernel.  When the kernel starts, it is uncompressed into RAM, and\r
-+used as a root file system.\r
-+\r
-+If you'd like to use a pre-built ramdisk.gz rather than build\r
-+one yourself:\r
-+  cp arch/mips/ar531x/RAMDISK/ramdisk.gz arch/mips/ramdisk/ramdisk.gz\r
-+\r
-+Here are the detailed steps to build your own:\r
-+\r
-+1) Modify Makefile to point KERNEL_SOURCE at your linux source tree.\r
-+\r
-+2) Copy whatever additional files/directories/links you'd like to\r
-+   under rootdir.  Note that you're limited to CONFIG_BLK_DEV_RAM_SIZE\r
-+   1KB blocks, as specified in your linux/.config file.\r
-+   Examples:\r
-+      Copy busybox to rootdir/bin/\r
-+        [NOTE: Copy busybox.links to this directory to\r
-+        cause the makelinks script to automatically\r
-+        set up all of the necessary busybox command links\r
-+        in the rootdir/bin directory].\r
-+\r
-+      Copy any wireless driver modules into rootdir tree\r
-+\r
-+   You might want to make a copy of the rootdir directory\r
-+   before you modify it, just in case you want to get back\r
-+   to the original.\r
-+\r
-+3) LOGIN AS ROOT (e.g. "su") and type "make"\r
-+\r
-+4) Copy the resulting ramdisk.gz to your linux source tree under\r
-+       arch/mips/ramdisk/ramdisk.gz\r
-+   (or "make install" will do this step for you)\r
-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\r
-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\r
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/fstab    1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/fstab        2005-12-24 20:29:42.063317256 +0000\r
-@@ -0,0 +1 @@\r
-+/proc /proc proc defaults 0 0\r
-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\r
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/group    1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/group        2005-12-24 20:29:42.064317104 +0000\r
-@@ -0,0 +1,18 @@\r
-+root:x:0:\r
-+wheel:x:10:\r
-+bin:x:1:bin,daemon\r
-+daemon:x:2:bin,daemon\r
-+sys:x:3:bin,adm\r
-+adm:x:4:adm,daemon\r
-+tty:x:5:\r
-+disk:x:6:\r
-+lp:x:7:daemon,lp\r
-+mem:x:8:\r
-+kmem:x:9:\r
-+operator:x:11:\r
-+uucp:x:14:uucp\r
-+dip:x:40:\r
-+utmp:x:45:\r
-+www:x:63:\r
-+nobody:x:65534:\r
-+users:x:100:\r
-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\r
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/host.conf        1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/host.conf    2005-12-24 20:29:42.064317104 +0000\r
-@@ -0,0 +1,2 @@\r
-+order hosts,bind\r
-+multi on\r
-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\r
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/inittab  1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/inittab      2005-12-24 20:29:42.064317104 +0000\r
-@@ -0,0 +1,2 @@\r
-+::sysinit:/etc/rc.d/rcS\r
-+::respawn:/bin/sh\r
-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\r
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/nsswitch.conf    1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/nsswitch.conf        2005-12-24 20:29:42.065316952 +0000\r
-@@ -0,0 +1,16 @@\r
-+# /etc/nsswitch.conf\r
-+#\r
-+# Name Service Switch configuration file.\r
-+#\r
-+\r
-+passwd:               compat\r
-+shadow:               compat\r
-+group:                compat\r
-+\r
-+hosts:                files dns\r
-+networks:     files dns\r
-+\r
-+ethers:               files\r
-+protocols:    files\r
-+rpc:          files\r
-+services:     files\r
-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\r
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/passwd   1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/passwd       2005-12-24 20:29:42.065316952 +0000\r
-@@ -0,0 +1,11 @@\r
-+root:x:0:0:root:/root:/bin/ash\r
-+bin:x:1:1:bin:/bin:/bin/sh\r
-+daemon:x:2:2:daemon:/usr/sbin:/bin/sh\r
-+adm:x:3:4:adm:/adm:/bin/sh\r
-+lp:x:4:7:lp:/var/spool/lpd:/bin/sh\r
-+sync:x:5:0:sync:/bin:/bin/sync\r
-+shutdown:x:6:11:shutdown:/sbin:/sbin/shutdown\r
-+halt:x:7:0:halt:/sbin:/sbin/halt\r
-+uucp:x:10:14:uucp:/var/spool/uucp:/bin/sh\r
-+operator:x:11:0:Operator:/var:/bin/sh\r
-+nobody:x:65534:65534:nobody:/home:/bin/sh\r
-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\r
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/rc.d/rcS 1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/rc.d/rcS     2005-12-24 20:29:42.066316800 +0000\r
-@@ -0,0 +1,17 @@\r
-+#!/bin/sh\r
-+\r
-+mount -a\r
-+mount -t jffs2 -o remount +w /\r
-+# mount -t ramfs /dev/ram /ramdisk\r
-+\r
-+echo Load MADWiFi wlan module\r
-+insmod ../../lib/modules/2.4.25/net/wlan.o\r
-+\r
-+echo Load MADWiFi Atheros HAL module\r
-+insmod ../../lib/modules/2.4.25/net/ath_hal.o\r
-+\r
-+echo Load MADWiFi Atheros Driver module\r
-+insmod ../../lib/modules/2.4.25/net/ath_lbus.o\r
-+\r
-+exit\r
-+\r
-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\r
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/resolv.conf      1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/resolv.conf  2005-12-24 20:29:42.066316800 +0000\r
-@@ -0,0 +1,18 @@\r
-+# /etc/resolv.conf - DNS setup file\r
-+#\r
-+# possible entries are:\r
-+#\r
-+#       domain <domain>                 Local domain name. If not present, the\r
-+#                                       gethostbyname syscall is used to\r
-+#                                       determine the local domain name.\r
-+#\r
-+#       search <list_of_domains>        Search list for hostname lookup.\r
-+#                                       The search list is normally determined\r
-+#                                       from the local domain name but it\r
-+#                                       can be set to a list of domains.\r
-+#\r
-+#       nameserver <ip_addr>            Define which server to contact\r
-+#                                       for DNS lookups. If there are\r
-+#                                       multiple nameserver lines (Max=3),\r
-+#                                       they are queried in the listed order.\r
-+#\r
-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\r
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/securetty        1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/securetty    2005-12-24 20:29:42.066316800 +0000\r
-@@ -0,0 +1,12 @@\r
-+tty1\r
-+tty2\r
-+tty3\r
-+tty4\r
-+tty5\r
-+tty6\r
-+tty7\r
-+tty8\r
-+ttyS0\r
-+ttyS1\r
-+ttyS2\r
-+ttyS3\r
-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\r
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/services 1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/services     2005-12-24 20:29:42.066316800 +0000\r
-@@ -0,0 +1,193 @@\r
-+#     $NetBSD: services,v 1.18 1996/03/26 00:07:58 mrg Exp $\r
-+#\r
-+# Network services, Internet style\r
-+#\r
-+# Note that it is presently the policy of IANA to assign a single well-known\r
-+# port number for both TCP and UDP; hence, most entries here have two entries\r
-+# even if the protocol doesn't support UDP operations.\r
-+# Updated from RFC 1340, ``Assigned Numbers'' (July 1992).  Not all ports\r
-+# are included, only the more common ones.\r
-+#\r
-+#     from: @(#)services      5.8 (Berkeley) 5/9/91\r
-+#\r
-+tcpmux                1/tcp           # TCP port service multiplexer\r
-+echo          7/tcp\r
-+echo          7/udp\r
-+discard               9/tcp           sink null\r
-+discard               9/udp           sink null\r
-+systat                11/tcp          users\r
-+daytime               13/tcp\r
-+daytime               13/udp\r
-+netstat               15/tcp\r
-+qotd          17/tcp          quote\r
-+msp           18/tcp          # message send protocol\r
-+msp           18/udp          # message send protocol\r
-+chargen               19/tcp          ttytst source\r
-+chargen               19/udp          ttytst source\r
-+ftp-data      20/tcp          # default ftp data port\r
-+ftp           21/tcp\r
-+ssh           22/tcp\r
-+ssh           22/udp\r
-+telnet                23/tcp\r
-+# 24 - private\r
-+smtp          25/tcp          mail\r
-+# 26 - unassigned\r
-+time          37/tcp          timserver\r
-+time          37/udp          timserver\r
-+rlp           39/udp          resource        # resource location\r
-+nameserver    42/tcp          name            # IEN 116\r
-+whois         43/tcp          nicname\r
-+domain                53/tcp          nameserver      # name-domain server\r
-+domain                53/udp          nameserver\r
-+mtp           57/tcp                          # deprecated\r
-+bootps                67/tcp          # BOOTP server\r
-+bootps                67/udp\r
-+bootpc                68/tcp          # BOOTP client\r
-+bootpc                68/udp\r
-+tftp          69/udp\r
-+gopher                70/tcp          # Internet Gopher\r
-+gopher                70/udp\r
-+rje           77/tcp          netrjs\r
-+finger                79/tcp\r
-+www           80/tcp          http    # WorldWideWeb HTTP\r
-+www           80/udp                  # HyperText Transfer Protocol\r
-+link          87/tcp          ttylink\r
-+kerberos      88/tcp          krb5    # Kerberos v5\r
-+kerberos      88/udp\r
-+supdup                95/tcp\r
-+# 100 - reserved\r
-+hostnames     101/tcp         hostname        # usually from sri-nic\r
-+iso-tsap      102/tcp         tsap            # part of ISODE.\r
-+csnet-ns      105/tcp         cso-ns  # also used by CSO name server\r
-+csnet-ns      105/udp         cso-ns\r
-+rtelnet               107/tcp         # Remote Telnet\r
-+rtelnet               107/udp\r
-+pop2          109/tcp         pop-2 postoffice        # POP version 2\r
-+pop2          109/udp\r
-+pop3          110/tcp         pop-3 # POP version 3\r
-+pop3          110/udp\r
-+sunrpc                111/tcp\r
-+sunrpc                111/udp\r
-+auth          113/tcp         authentication tap ident\r
-+sftp          115/tcp\r
-+uucp-path     117/tcp\r
-+nntp          119/tcp         readnews untp   # USENET News Transfer Protocol\r
-+ntp           123/tcp\r
-+ntp           123/udp                         # Network Time Protocol\r
-+netbios-ns    137/tcp                         # NETBIOS Name Service\r
-+netbios-ns    137/udp\r
-+netbios-dgm   138/tcp                         # NETBIOS Datagram Service\r
-+netbios-dgm   138/udp\r
-+netbios-ssn   139/tcp                         # NETBIOS session service\r
-+netbios-ssn   139/udp\r
-+imap2         143/tcp         imap            # Interim Mail Access Proto v2\r
-+imap2         143/udp\r
-+snmp          161/udp                         # Simple Net Mgmt Proto\r
-+snmp-trap     162/udp         snmptrap        # Traps for SNMP\r
-+cmip-man      163/tcp                         # ISO mgmt over IP (CMOT)\r
-+cmip-man      163/udp\r
-+cmip-agent    164/tcp\r
-+cmip-agent    164/udp\r
-+xdmcp         177/tcp                         # X Display Mgr. Control Proto\r
-+xdmcp         177/udp\r
-+nextstep      178/tcp         NeXTStep NextStep       # NeXTStep window\r
-+nextstep      178/udp         NeXTStep NextStep       # server\r
-+bgp           179/tcp                         # Border Gateway Proto.\r
-+bgp           179/udp\r
-+prospero      191/tcp                         # Cliff Neuman's Prospero\r
-+prospero      191/udp\r
-+irc           194/tcp                         # Internet Relay Chat\r
-+irc           194/udp\r
-+smux          199/tcp                         # SNMP Unix Multiplexer\r
-+smux          199/udp\r
-+at-rtmp               201/tcp                         # AppleTalk routing\r
-+at-rtmp               201/udp\r
-+at-nbp                202/tcp                         # AppleTalk name binding\r
-+at-nbp                202/udp\r
-+at-echo               204/tcp                         # AppleTalk echo\r
-+at-echo               204/udp\r
-+at-zis                206/tcp                         # AppleTalk zone information\r
-+at-zis                206/udp\r
-+z3950         210/tcp         wais            # NISO Z39.50 database\r
-+z3950         210/udp         wais\r
-+ipx           213/tcp                         # IPX\r
-+ipx           213/udp\r
-+imap3         220/tcp                         # Interactive Mail Access\r
-+imap3         220/udp                         # Protocol v3\r
-+ulistserv     372/tcp                         # UNIX Listserv\r
-+ulistserv     372/udp\r
-+#\r
-+# UNIX specific services\r
-+#\r
-+exec          512/tcp\r
-+biff          512/udp         comsat\r
-+login         513/tcp\r
-+who           513/udp         whod\r
-+shell         514/tcp         cmd             # no passwords used\r
-+syslog                514/udp\r
-+printer               515/tcp         spooler         # line printer spooler\r
-+talk          517/udp\r
-+ntalk         518/udp\r
-+route         520/udp         router routed   # RIP\r
-+timed         525/udp         timeserver\r
-+tempo         526/tcp         newdate\r
-+courier               530/tcp         rpc\r
-+conference    531/tcp         chat\r
-+netnews               532/tcp         readnews\r
-+netwall               533/udp                         # -for emergency broadcasts\r
-+uucp          540/tcp         uucpd           # uucp daemon\r
-+remotefs      556/tcp         rfs_server rfs  # Brunhoff remote filesystem\r
-+#\r
-+webster               765/tcp                         # Network dictionary\r
-+webster               765/udp\r
-+# temporary entry (not officially registered by the Samba Team!)\r
-+swat          901/tcp         # Samba Web Administration Tool\r
-+#\r
-+# From ``Assigned Numbers'':\r
-+#\r
-+#> The Registered Ports are not controlled by the IANA and on most systems\r
-+#> can be used by ordinary user processes or programs executed by ordinary\r
-+#> users.\r
-+#\r
-+#> Ports are used in the TCP [45,106] to name the ends of logical\r
-+#> connections which carry long term conversations.  For the purpose of\r
-+#> providing services to unknown callers, a service contact port is\r
-+#> defined.  This list specifies the port used by the server process as its\r
-+#> contact port.  While the IANA can not control uses of these ports it\r
-+#> does register or list uses of these ports as a convienence to the\r
-+#> community.\r
-+#\r
-+ingreslock    1524/tcp\r
-+ingreslock    1524/udp\r
-+prospero-np   1525/tcp                # Prospero non-privileged\r
-+prospero-np   1525/udp\r
-+rfe           5002/tcp                # Radio Free Ethernet\r
-+rfe           5002/udp                # Actually uses UDP only\r
-+#\r
-+#\r
-+# Kerberos (Project Athena/MIT) services\r
-+# Note that these are for Kerberos v4, and are unofficial.\r
-+#\r
-+klogin                543/tcp                 # Kerberos `rlogin'\r
-+kshell                544/tcp         krcmd   # Kerberos `rsh'\r
-+kerberos-adm  749/tcp                 # Kerberos `kadmin' (v5)\r
-+kerberos4     750/udp         kdc     # Kerberos (server) udp\r
-+kerberos4     750/tcp         kdc     # Kerberos (server) tcp\r
-+kerberos-master       751/udp                 # Kerberos admin server udp\r
-+kerberos-master       751/tcp                 # Kerberos admin server tcp\r
-+krbupdate     760/tcp         kreg    # BSD Kerberos registration\r
-+kpasswd               761/tcp         kpwd    # BSD Kerberos `passwd'\r
-+eklogin               2105/tcp                # Kerberos encrypted `rlogin'\r
-+#\r
-+# Unofficial but necessary (for NetBSD) services\r
-+#\r
-+supfilesrv    871/tcp                 # SUP server\r
-+supfiledbg    1127/tcp                # SUP debugging\r
-+#\r
-+# AppleTalk DDP entries (DDP: Datagram Delivery Protocol)\r
-+#\r
-+rtmp          1/ddp                   # Routing Table Maintenance Protocol\r
-+nbp           2/ddp                   # Name Binding Protocol\r
-+echo          4/ddp                   # AppleTalk Echo Protocol\r
-+zip           6/ddp                   # Zone Information Protocol\r
-+\r
-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\r
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/etc/shadow   1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/RAMDISK/rootdir/etc/shadow       2005-12-24 20:29:42.067316648 +0000\r
-@@ -0,0 +1,11 @@\r
-+root::10933:0:99999:7:::\r
-+bin:*:10933:0:99999:7:::\r
-+daemon:*:10933:0:99999:7:::\r
-+adm:*:10933:0:99999:7:::\r
-+lp:*:10933:0:99999:7:::\r
-+sync:*:10933:0:99999:7:::\r
-+shutdown:*:10933:0:99999:7:::\r
-+halt:*:10933:0:99999:7:::\r
-+uucp:*:10933:0:99999:7:::\r
-+operator:*:10933:0:99999:7:::\r
-+nobody:*:10933:0:99999:7:::\r
-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\r
---- 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\r
-+++ 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\r
-@@ -0,0 +1 @@\r
-+# module             id=string\r
-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\r
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.ieee1394map       1970-01-01 01:00:00.000000000 +0100\r
-+++ 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\r
-@@ -0,0 +1 @@\r
-+# ieee1394 module    match_flags vendor_id model_id specifier_id version\r
-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\r
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.isapnpmap 1970-01-01 01:00:00.000000000 +0100\r
-+++ 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\r
-@@ -0,0 +1 @@\r
-+# isapnp module      cardvendor carddevice driver_data vendor     function   ...\r
-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\r
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.parportmap        1970-01-01 01:00:00.000000000 +0100\r
-+++ 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\r
-@@ -0,0 +1 @@\r
-+# module             pattern\r
-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\r
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.pcimap    1970-01-01 01:00:00.000000000 +0100\r
-+++ 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\r
-@@ -0,0 +1 @@\r
-+# pci module         vendor     device     subvendor  subdevice  class      class_mask driver_data\r
-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\r
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.pnpbiosmap        1970-01-01 01:00:00.000000000 +0100\r
-+++ 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\r
-@@ -0,0 +1 @@\r
-+# module             id\r
-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\r
---- linux-2.4.32/arch/mips/ar531x/RAMDISK/rootdir/lib/modules/2.4.25/modules.usbmap    1970-01-01 01:00:00.000000000 +0100\r
-+++ 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\r
-@@ -0,0 +1 @@\r
-+# usb module         match_flags idVendor idProduct bcdDevice_lo bcdDevice_hi bDeviceClass bDeviceSubClass bDeviceProtocol bInterfaceClass bInterfaceSubClass bInterfaceProtocol driver_info\r
-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\r
-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\r
-diff -urN linux-2.4.32/arch/mips/ar531x/README linux-2.4.32.new/arch/mips/ar531x/README\r
---- linux-2.4.32/arch/mips/ar531x/README       1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/README   2005-12-24 20:29:42.101311480 +0000\r
-@@ -0,0 +1,68 @@\r
-+Basic information for the AR531X Board Support Package\r
-+\r
-+This directory contains the "LBSP" -- Linux Board Support Package --\r
-+for Linux on the Atheros AR531X Wireless System-On-a-Chip.  It is intended\r
-+primarily as a building block for wireless products.  At this time, the\r
-+AR531X Linux BSP is experimental code, and is actively UNDER CONSTRUCTION.\r
-+\r
-+Some components that are supported by this LBSP along with a standard 2.4\r
-+Linux MIPS kernel include\r
-+  R4Kc CPU\r
-+  instruction and data caches\r
-+  SDRAM\r
-+  flash (Macronix, AMD, STS, etc.)\r
-+  16550 serial port\r
-+  ethernet MACs\r
-+  ethernet PHY or PHY Switch (RealTek, Kendin, Marvell)\r
-+  General-Purpose I/O pins\r
-+  kernel debugging with kgdb\r
-+\r
-+This LBSP code does NOT include drivers for the wireless components of the\r
-+chip/boards!  Drivers for those components may be distributed separately.\r
-+In particular, the MADWiFi project under SourceForge supports (not yet!)\r
-+wireless functions on the AR531X chipset.  See\r
-+   http://www.sourceforge.net/projects/madwifi\r
-+\r
-+Files included in this BSP:\r
-+ae531xlnx.c      - Linux-specific portions of the ethernet driver\r
-+ae531xmac.c      - OS-independent AR531X ethernet MAC code\r
-+ae531xmac.h      - OS-independent AR531X ethernet MAC software definitions\r
-+ae531xreg.h      - OS-independent AR531X ethernet MAC hardware definitions\r
-+ar531x.h         - OS-independent AR531X system hardware definitions\r
-+ar531xlnx.h      - Linux-specific AR531X system definitions and externs\r
-+defconfig-ar531x - Default Linux configuration file\r
-+intr_recv.S      - Linux interrupt "glue" code\r
-+ar531xirq.c      - Linux Interrupt Request management\r
-+Makefile         - Linux makefile\r
-+mvPhy.c          - OS-independent ethernet PHY code for Marvell Switch\r
-+mvPhy.h          - OS-independent ethernet PHY definitions for Marvell Switch\r
-+ar531xprom.c     - Linux prom "glue" code\r
-+ar531xsetup.c    - Linux startup code\r
-+ar531xdbg_io.c   - Support for kgdb-based debugging and for EARLY_PRINTK_HACK\r
-+ar531xproc.c     - Pseudo-device driver for /proc/ar531x device\r
-+ar531xgpio.c     - Support for General Purpose I/O pins\r
-+ar531xwmacsl.c   - Wireless MAC Support Layer\r
-+\r
-+Additional files, distributed with the BSP:\r
-+README           - This file\r
-+README.BUILD     - Instructions for building a linux kernel from source\r
-+README.EXECUTE   - Instructions for testing your linux kernel\r
-+README.RAMDISK   - Instructions for building a root ramdisk image\r
-+\r
-+ramdisk.gz       - A binary ramdisk image, suitable for use with AR531X.\r
-+DIFFS            - Directory that contains "patch" files (See README.BUILD)\r
-+\r
-+\r
-+There are several ways to boot a vmlinux image on an AR531X board:\r
-+  -You can boot in over ethernet from the vxWorks bootrom, which is preloaded\r
-+   on all Atheros boards\r
-+  -You can use an ICE (e.g. VisionICE) to load the vmlinux image.  You will\r
-+   need appropriate register initialization (e.g. AP30.ini file)\r
-+  -You can use the eCos RedBoot bootrom loader.  This is a full-featured\r
-+   bootrom which as been ported to AR531x.  It can boot vmlinux over ethernet\r
-+   or from flash.  Source code is available from Atheros.\r
-+\r
-+Please send comments, corrections, complaints, criticisms, suggestions,\r
-+enhancements, requests, or any other reasonable communications regarding\r
-+this effort, to "linux@atheros.com".  Your email will be received by a\r
-+couple of engineers, and redirected as appropriate.\r
-diff -urN linux-2.4.32/arch/mips/ar531x/README.BUILD linux-2.4.32.new/arch/mips/ar531x/README.BUILD\r
---- linux-2.4.32/arch/mips/ar531x/README.BUILD 1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/README.BUILD     2005-12-24 20:29:42.101311480 +0000\r
-@@ -0,0 +1,47 @@\r
-+       How to BUILD a linux kernel for an AR531X system\r
-+\r
-+It is expected that you will build Linux on an existing Linux system, which \r
-+has all of the standard Linux tools.\r
-+\r
-+01) Obtain a MIPS BigEndian ELF gcc-compatible toolchain.  For example,\r
-+    if you're cross-compiling on a x86 Linux system, you could use:\r
-+    ftp://ftp.mips.com/pub/tools/software/sde-for-linux/sdelinux-5.01-4eb.i386.rpm\r
-+\r
-+02) Obtain the latest working MIPS Linux kernel\r
-+    cvs -d :pserver:cvs@ftp.linux-mips.org:/home/cvs login    (password "cvs")\r
-+    cvs -d :pserver:cvs@ftp.linux-mips.org:/home/cvs co -r linux_2_4 linux\r
-+\r
-+    Now "cd linux".  The remainder of these instructions assume\r
-+    that you are in the linux directory.\r
-+\r
-+03) Place the contents of this directory at arch/mips/ar531x.\r
-+\r
-+04) Use the patch command to patch generic linux files according\r
-+    to the DIFFS directory\r
-+    for i in arch/mips/ar531x/DIFFS/*.diff\r
-+    do\r
-+       patch -p1 < $i\r
-+    done\r
-+    NOTE: This version of the AR531X Linux BSP was tested with\r
-+    MIPS Linux 2.4.22 as of 11/14/03.  If you use a different\r
-+    (e.g. more recent) version of Linux source, you may need to\r
-+    resolve some minor patch and compilation issues.\r
-+\r
-+05) Set up a RAMDISK image.\r
-+    See the instructions in README.RAMDISK.\r
-+\r
-+06) Set up a linux configuration using ar531x/defconfig-ar531x.\r
-+    cp arch/mips/ar531x/defconfig-ar531x .config\r
-+    make oldconfig       (answer all questions that are asked)\r
-+    NOTE: For development/debug purposes, you may want to\r
-+    enable CONFIG_RUNTIME_DEBUG and CONFIG_KGDB.\r
-+\r
-+07) Make dependencies.\r
-+    make dep\r
-+\r
-+08) Build the linux kernel\r
-+    make\r
-+\r
-+09) The linux image you just built is in vmlinux.\r
-+    See instructions in README.EXECUTE to run your vmlinux\r
-+    image on an AP531X-based board.\r
-diff -urN linux-2.4.32/arch/mips/ar531x/README.EXECUTE linux-2.4.32.new/arch/mips/ar531x/README.EXECUTE\r
---- linux-2.4.32/arch/mips/ar531x/README.EXECUTE       1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/README.EXECUTE   2005-12-24 20:29:42.101311480 +0000\r
-@@ -0,0 +1,23 @@\r
-+      How to EXECUTE a linux image on an AR531X system\r
-+\r
-+There are currently three ways to run you vmlinux image:\r
-+  1) Load it using the vxWorks bootrom that is supplied with the board.\r
-+     You can load it over ethernet or from the TFFS file system, if you\r
-+     have sufficient flash to store the image.\r
-+  2) Load it using an ICE (e.g. VisionICE).\r
-+  3) Use a bootrom loader, such as eCos RedBoot.\r
-+\r
-+After you have booted linux:\r
-+  By default, the root filesystem on ramdisk is read-only.\r
-+  To make it writable, use "mount -o remount w /".\r
-+\r
-+  The user-level commands are slightly non-standard, as they\r
-+  are based on "busybox".\r
-+\r
-+  The "wget" command is included.  You can use wget to fetch\r
-+  files from any ftp server.  So, for instance, you can fetch\r
-+  a kernel module and then "insmod" it.\r
-+\r
-+Note that the standard source-level kernel debugger, kgdb, works well\r
-+over the serial line with this port.  We use kgdb and the kgdb_demux perl\r
-+script -- available over the www -- for debugging.\r
-diff -urN linux-2.4.32/arch/mips/ar531x/README.VERSION linux-2.4.32.new/arch/mips/ar531x/README.VERSION\r
---- linux-2.4.32/arch/mips/ar531x/README.VERSION       1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/arch/mips/ar531x/README.VERSION   2005-12-24 20:29:42.101311480 +0000\r
-@@ -0,0 +1 @@\r
-+Source release last modified: 12/16/03\r
-diff -urN linux-2.4.32/arch/mips/config-shared.in linux-2.4.32.new/arch/mips/config-shared.in\r
---- linux-2.4.32/arch/mips/config-shared.in    2005-12-24 16:11:21.000000000 +0000\r
-+++ linux-2.4.32.new/arch/mips/config-shared.in        2005-12-24 21:33:42.804435856 +0000\r
-@@ -31,6 +31,7 @@\r
- dep_bool 'Support for Alchemy PB1000 board' CONFIG_MIPS_PB1000 $CONFIG_MIPS32\r
- dep_bool 'Support for Alchemy PB1100 board' CONFIG_MIPS_PB1100 $CONFIG_MIPS32\r
- dep_bool 'Support for Alchemy PB1500 board' CONFIG_MIPS_PB1500 $CONFIG_MIPS32\r
-+dep_bool 'Support for Atheros AR5312/AR2312 WiSoC (EXPERIMENTAL)' CONFIG_AR531X $CONFIG_AR531X $CONFIG_EXPERIMENTAL\r
- dep_bool 'Support for Alchemy PB1550 board' CONFIG_MIPS_PB1550 $CONFIG_MIPS32\r
- dep_bool 'Support for Alchemy PB1200 board' CONFIG_MIPS_PB1200 $CONFIG_MIPS32\r
- dep_bool 'Support for Alchemy Hydrogen3 board' CONFIG_MIPS_HYDROGEN3 $CONFIG_MIPS32\r
-@@ -196,7 +197,7 @@\r
-    bool '   Support for ZBbus profiling' CONFIG_SIBYTE_TBPROF\r
\r
-    if [ "$CONFIG_SIBYTE_SWARM" = "y" -o \\r
--        "$CONFIG_SIBYTE_LITTLESUR" = "y" -o \\r
-+O5B        "$CONFIG_SIBYTE_LITTLESUR" = "y" -o \\r
-         "$CONFIG_SIBYTE_PTSWARM" = "y" -o \\r
-         "$CONFIG_SIBYTE_CARMEL" = "y" ]; then\r
-       define_bool CONFIG_SIBYTE_GENBUS_IDE y\r
-@@ -239,6 +240,43 @@\r
-    define_bool CONFIG_NONCOHERENT_IO y\r
-    define_bool CONFIG_PC_KEYB y\r
- fi\r
-+if [ "$CONFIG_AR531X" = "y" ]; then\r
-+   define_bool CONFIG_IRQ_CPU y\r
-+   define_bool CONFIG_CPU_VR4100 y\r
-+   define_bool CONFIG_SERIAL y\r
-+   define_bool CONFIG_NEW_IRQ y\r
-+   define_bool CONFIG_NEW_TIME_C y\r
-+   define_bool CONFIG_AR5312\r
-+   define_bool CONFIG_NONCOHERENT_IO y\r
-+   bool 'Enable early printk hack' CONFIG_EARLY_PRINTK_HACK\r
-+   define_bool CONFIG_SCSI n\r
-+   mainmenu_option next_comment\r
-+   comment 'Board selection'\r
-+      choice 'Board type' \\r
-+         "UNKNOWN CONFIG_APUNKNOWN \\r
-+        AP30 CONFIG_AP30 \\r
-+          AP31 CONFIG_AP31 \\r
-+        AP33 CONFIG_AP33 \\r
-+        AP38 CONFIG_AP38 \\r
-+        AP43 CONFIG_AP43 \\r
-+        AP48 CONFIG_AP48" AP30\r
-+   if [ "$CONFIG_AP30" = "y" ]; then\r
-+      define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 2\r
-+   fi\r
-+   if [ "$CONFIG_AP33" = "y" ]; then\r
-+      define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 1\r
-+   fi\r
-+   if [ "$CONFIG_AP38" = "y" ]; then\r
-+      define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 1\r
-+   fi\r
-+   if [ "$CONFIG_AP43" = "y" ]; then\r
-+      define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 1\r
-+   fi\r
-+   if [ "$CONFIG_AP48" = "y" ]; then\r
-+      define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 1\r
-+   fi\r
-+   endmenu\r
-+fi\r
- if [ "$CONFIG_CASIO_E55" = "y" ]; then\r
-    define_bool CONFIG_IRQ_CPU y\r
-    define_bool CONFIG_NONCOHERENT_IO y\r
-diff -urN linux-2.4.32/arch/mips/kernel/setup.c linux-2.4.32.new/arch/mips/kernel/setup.c\r
---- linux-2.4.32/arch/mips/kernel/setup.c      2005-12-24 16:08:53.000000000 +0000\r
-+++ linux-2.4.32.new/arch/mips/kernel/setup.c  2005-12-24 21:28:51.779678344 +0000\r
-@@ -494,6 +494,7 @@\r
-       void hp_setup(void);\r
-       void au1x00_setup(void);\r
-       void frame_info_init(void);\r
-+      void ar531x_setup(void);\r
\r
-       frame_info_init();\r
- #if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE)\r
-@@ -691,6 +692,12 @@\r
-                 pmc_yosemite_setup();\r
-                 break;\r
- #endif\r
-+\r
-+#ifdef CONFIG_AR531X\r
-+      case MACH_GROUP_AR531X:\r
-+              ar531x_setup();\r
-+              break;\r
-+#endif\r
-       default:\r
-               panic("Unsupported architecture");\r
-       }\r
-diff -urN linux-2.4.32/arch/mips/Makefile linux-2.4.32.new/arch/mips/Makefile\r
---- linux-2.4.32/arch/mips/Makefile    2005-12-24 16:09:51.000000000 +0000\r
-+++ linux-2.4.32.new/arch/mips/Makefile        2005-12-24 21:28:51.780678192 +0000\r
-@@ -725,6 +725,12 @@\r
- LOADADDR      += 0x80020000\r
- endif\r
\r
-+ifdef CONFIG_AR531X\r
-+SUBDIRS       += arch/mips/ar531x\r
-+LIBS          += arch/mips/ar531x/ar531x.o\r
-+LOADADDR      += 0x80002000\r
-+endif\r
-+\r
- #\r
- # Choosing incompatible machines durings configuration will result in\r
- # error messages during linking.  Select a default linkscript if\r
-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\r
---- linux-2.4.32/drivers/mtd/chips/cfi_cmdset_0002.c   2004-11-17 11:54:21.000000000 +0000\r
-+++ linux-2.4.32.new/drivers/mtd/chips/cfi_cmdset_0002.c       2005-12-24 21:28:51.795675912 +0000\r
-@@ -510,7 +510,7 @@\r
-          or tells us why it failed. */        \r
-       dq6 = CMD(1<<6);\r
-       dq5 = CMD(1<<5);\r
--      timeo = jiffies + (HZ/1000); /* setting timeout to 1ms for now */\r
-+      timeo = jiffies + (HZ/1000) + 1; /* setting timeout to 1ms for now */\r
-               \r
-       oldstatus = cfi_read(map, adr);\r
-       status = cfi_read(map, adr);\r
-@@ -535,12 +535,14 @@\r
-               if( (status & dq5) == dq5 ) {\r
-                       /* When DQ5 raises, we must check once again\r
-                          if DQ6 is toggling.  If not, the erase has been\r
--                         completed OK.  If not, reset chip. */\r
-+                         completed OK.  But if so, reset chip. */\r
-                       oldstatus = cfi_read(map, adr);\r
-                       status = cfi_read(map, adr);\r
-                   \r
-                       if ( (oldstatus & 0x00FF) == (status & 0x00FF) ) {\r
-+#if 0\r
-                               printk(KERN_WARNING "Warning: DQ5 raised while program operation was in progress, however operation completed OK\n" );\r
-+#endif\r
-                       } else { \r
-                               /* DQ5 is active so we can do a reset and stop the erase */\r
-                               cfi_write(map, CMD(0xF0), chip->start);\r
-diff -urN linux-2.4.32/drivers/mtd/chips/jedec_probe.c linux-2.4.32.new/drivers/mtd/chips/jedec_probe.c\r
---- linux-2.4.32/drivers/mtd/chips/jedec_probe.c       2003-06-13 15:51:34.000000000 +0100\r
-+++ linux-2.4.32.new/drivers/mtd/chips/jedec_probe.c   2005-12-24 21:28:51.797675608 +0000\r
-@@ -900,7 +900,16 @@\r
-               NumEraseRegions: 1,\r
-               regions: {ERASEINFO(0x01000,256),\r
-               }\r
--      } \r
-+      }, {\r
-+              mfr_id: MANUFACTURER_SST,\r
-+              dev_id: SST39LF160,\r
-+              name: "SST 39LF160",\r
-+              DevSize: SIZE_2MiB,\r
-+              CmdSet: P_ID_AMD_STD,\r
-+              NumEraseRegions: 1,\r
-+              regions: {ERASEINFO(0x01000,512),\r
-+              }\r
-+        }\r
- };\r
\r
\r
-diff -urN linux-2.4.32/drivers/mtd/Config.in linux-2.4.32.new/drivers/mtd/Config.in\r
---- linux-2.4.32/drivers/mtd/Config.in 2003-06-13 15:51:34.000000000 +0100\r
-+++ linux-2.4.32.new/drivers/mtd/Config.in     2005-12-24 21:28:51.803674696 +0000\r
-@@ -14,6 +14,9 @@\r
-    dep_tristate '  MTD partitioning support' CONFIG_MTD_PARTITIONS $CONFIG_MTD\r
-    dep_tristate '  MTD concatenating support' CONFIG_MTD_CONCAT $CONFIG_MTD\r
-    dep_tristate '  RedBoot partition table parsing' CONFIG_MTD_REDBOOT_PARTS $CONFIG_MTD_PARTITIONS\r
-+   if [ "$CONFIG_MTD_END_RESERVED" != "" ]; then\r
-+      define_int CONFIG_MTD_END_RESERVED $CONFIG_MTD_END_RESERVED\r
-+   fi\r
-    dep_tristate '  Command line partition table parsing' CONFIG_MTD_CMDLINE_PARTS $CONFIG_MTD_PARTITIONS\r
-    if [ "$CONFIG_ARM" = "y" ]; then\r
-       dep_tristate '  ARM Firmware Suite partition parsing' CONFIG_MTD_AFS_PARTS $CONFIG_MTD_PARTITIONS\r
-diff -urN linux-2.4.32/drivers/mtd/maps/physmap.c linux-2.4.32.new/drivers/mtd/maps/physmap.c\r
---- linux-2.4.32/drivers/mtd/maps/physmap.c    2003-06-13 15:51:34.000000000 +0100\r
-+++ linux-2.4.32.new/drivers/mtd/maps/physmap.c        2005-12-24 21:28:51.811673480 +0000\r
-@@ -80,12 +80,18 @@\r
- };\r
\r
- #ifdef CONFIG_MTD_PARTITIONS\r
--#ifdef CONFIG_MTD_CMDLINE_PARTS\r
-+#if defined(CONFIG_MTD_CMDLINE_PARTS) || defined(CONFIG_MTD_REDBOOT_PARTS)\r
- static struct mtd_partition *mtd_parts = 0;\r
- static int                   mtd_parts_nb = 0;\r
- #else\r
- static struct mtd_partition physmap_partitions[] = {\r
- /* Put your own partition definitions here */\r
-+    {\r
-+        name:   "rootfs",\r
-+        size:   0x000e0000,\r
-+        offset: 0x000f0000,\r
-+        /* Allow file system to be mounted for writing */\r
-+    }\r
- #if 0\r
-       {\r
-               name:           "bootROM",\r
-@@ -138,6 +144,22 @@\r
\r
-               add_mtd_device(mymtd);\r
- #ifdef CONFIG_MTD_PARTITIONS\r
-+#ifdef CONFIG_MTD_REDBOOT_PARTS\r
-+                {\r
-+                    extern int parse_redboot_partitions(struct mtd_info *master,\r
-+                                        struct mtd_partition **pparts);\r
-+\r
-+                    struct mtd_partition *rb_parts = 0;\r
-+                    int rb_parts_nb = 0;\r
-+\r
-+                  rb_parts_nb = parse_redboot_partitions(mymtd, &rb_parts);\r
-+                  if (rb_parts_nb > 0) {\r
-+                        printk(KERN_NOTICE\r
-+                               "Using redboot flash partitioning");\r
-+                      add_mtd_partitions (mymtd, rb_parts, rb_parts_nb);\r
-+                  }\r
-+                }\r
-+#endif\r
- #ifdef CONFIG_MTD_CMDLINE_PARTS\r
-               mtd_parts_nb = parse_cmdline_partitions(mymtd, &mtd_parts, \r
-                                                       "phys");\r
-@@ -147,7 +169,8 @@\r
-                              "Using command line partition definition\n");\r
-                       add_mtd_partitions (mymtd, mtd_parts, mtd_parts_nb);\r
-               }\r
--#else\r
-+#endif\r
-+#if !defined(CONFIG_MTD_CMDLINE_PARTS) && !defined(CONFIG_MTD_REDBOOT_PARTS)\r
-               if (NUM_PARTITIONS != 0) \r
-               {\r
-                       printk(KERN_NOTICE \r
-diff -urN linux-2.4.32/drivers/mtd/redboot.c linux-2.4.32.new/drivers/mtd/redboot.c\r
---- linux-2.4.32/drivers/mtd/redboot.c 2001-11-09 22:01:22.000000000 +0000\r
-+++ linux-2.4.32.new/drivers/mtd/redboot.c     2005-12-24 21:28:51.821671960 +0000\r
-@@ -51,8 +51,14 @@\r
-               return -ENOMEM;\r
\r
-       /* Read the start of the last erase block */\r
--      ret = master->read(master, master->size - master->erasesize,\r
-+        {\r
-+        u_int32_t part_table_start = master->size - master->erasesize;\r
-+#if defined(CONFIG_MTD_END_RESERVED)\r
-+        part_table_start -= CONFIG_MTD_END_RESERVED;\r
-+#endif\r
-+      ret = master->read(master, part_table_start,\r
-                          PAGE_SIZE, &retlen, (void *)buf);\r
-+        }\r
\r
-       if (ret)\r
-               goto out;\r
-diff -urN linux-2.4.32/drivers/net/Config.in linux-2.4.32.new/drivers/net/Config.in\r
---- linux-2.4.32/drivers/net/Config.in 2005-12-24 16:16:53.000000000 +0000\r
-+++ linux-2.4.32.new/drivers/net/Config.in     2005-12-24 21:28:51.856666640 +0000\r
-@@ -30,6 +30,8 @@\r
- comment 'Ethernet (10 or 100Mbit)'\r
- bool 'Ethernet (10 or 100Mbit)' CONFIG_NET_ETHERNET\r
- if [ "$CONFIG_NET_ETHERNET" = "y" ]; then\r
-+   define_bool CONFIG_VENETDEV n\r
-+   define_bool CONFIG_MARVELL_ENET_PHY y\r
-    if [ "$CONFIG_ARM" = "y" ]; then  \r
-       dep_bool '  ARM EBSA110 AM79C961A support' CONFIG_ARM_AM79C961A $CONFIG_ARCH_EBSA110\r
-       tristate '  Cirrus Logic CS8900A support' CONFIG_ARM_CIRRUS\r
-diff -urN linux-2.4.32/drivers/net/wireless/Config.in linux-2.4.32.new/drivers/net/wireless/Config.in\r
---- linux-2.4.32/drivers/net/wireless/Config.in        2004-11-17 11:54:21.000000000 +0000\r
-+++ linux-2.4.32.new/drivers/net/wireless/Config.in    2005-12-24 21:28:51.898660256 +0000\r
-@@ -38,7 +38,8 @@\r
\r
- # yes, this works even when no drivers are selected\r
- if [ "$CONFIG_ISA" = "y" -o "$CONFIG_PCI" = "y" -o \\r
--     "$CONFIG_ALL_PPC" = "y" -o "$CONFIG_PCMCIA" != "n" ]; then\r
-+     "$CONFIG_ALL_PPC" = "y" -o "$CONFIG_PCMCIA" != "n" -o \\r
-+     "$CONFIG_NET_WIRELESS" = "y" ]; then\r
-    define_bool CONFIG_NET_WIRELESS y\r
- else\r
-    define_bool CONFIG_NET_WIRELESS n\r
-diff -urN linux-2.4.32/include/asm-mips/atheros/ar531xbsp.h linux-2.4.32.new/include/asm-mips/atheros/ar531xbsp.h\r
---- linux-2.4.32/include/asm-mips/atheros/ar531xbsp.h  1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new/include/asm-mips/atheros/ar531xbsp.h      2005-12-24 20:29:06.898663096 +0000\r
-@@ -0,0 +1,16 @@\r
-+#ifndef __ASM_ATHEROS_BSP_SUPPORT_H\r
-+#define __ASM_ATHEROS_BSP_SUPPORT_H\r
-+/*\r
-+ * These are definitions and functions provided by the bsp to support the\r
-+ * AR5312 WiSoC running LSDK.  For different BSP implementations, different\r
-+ * BSP functions will be needed.\r
-+ */\r
-+\r
-+extern unsigned int ar531x_sys_frequency(void);\r
-+\r
-+#ifdef CONFIG_KGDB\r
-+extern  void kgdbInit(void);\r
-+extern int kgdbEnabled(void);\r
-+#endif\r
-+\r
-+#endif /* __ASM_ATHEROS_BSP_SUPPORT_H */\r
-diff -urN linux-2.4.32/include/asm-mips/bootinfo.h linux-2.4.32.new/include/asm-mips/bootinfo.h\r
---- linux-2.4.32/include/asm-mips/bootinfo.h   2005-12-24 16:08:53.000000000 +0000\r
-+++ linux-2.4.32.new/include/asm-mips/bootinfo.h       2005-12-24 21:28:51.899660104 +0000\r
-@@ -37,6 +37,7 @@\r
- #define MACH_GROUP_HP_LJ       20 /* Hewlett Packard LaserJet               */\r
- #define MACH_GROUP_LASAT       21\r
- #define MACH_GROUP_TITAN       22 /* PMC-Sierra Titan                             */\r
-+#define MACH_GROUP_AR531X      23 /* Atheros AR531X                         */\r
\r
- /*\r
-  * Valid machtype values for group unknown (low order halfword of mips_machtype)\r
-@@ -201,6 +202,17 @@\r
-  */\r
- #define       MACH_TITAN_YOSEMITE     1       /* PMC-Sierra Yosemite */\r
\r
-+/*\r
-+ * Valid machtype for group MACH_GROUP_AR5312\r
-+ */\r
-+#define MACH_ATHEROS_UNUSED     0\r
-+#define MACH_ATHEROS_AP30       1       /* AP30 */\r
-+#define MACH_ATHEROS_AP33     2       /* AP33 */\r
-+#define MACH_ATHEROS_AP38       3       /* AP38 */\r
-+#define MACH_ATHEROS_AP43       4       /* AP43 */\r
-+#define MACH_ATHEROS_AP48       5       /* AP48 */\r
-+#define MACH_ATHEROS_PB32       6       /* PB32 */\r
-+\r
- #define CL_SIZE                       (256)\r
\r
- const char *get_system_type(void);\r
-diff -urN linux-2.4.32/include/asm-mips/serial.h linux-2.4.32.new/include/asm-mips/serial.h\r
---- linux-2.4.32/include/asm-mips/serial.h     2005-01-19 14:10:12.000000000 +0000\r
-+++ linux-2.4.32.new/include/asm-mips/serial.h 2005-12-24 21:28:51.901659800 +0000\r
-@@ -467,6 +467,11 @@\r
- #define DDB5477_SERIAL_PORT_DEFNS\r
- #endif\r
\r
-+#if defined(CONFIG_AR531X)\r
-+#undef RS_TABLE_SIZE\r
-+#define RS_TABLE_SIZE 1\r
-+#endif\r
-+\r
- #define SERIAL_PORT_DFNS                      \\r
-       ATLAS_SERIAL_PORT_DEFNS                 \\r
-       AU1000_SERIAL_PORT_DEFNS                \\r
-diff -urN linux-2.4.32/kernel/printk.c linux-2.4.32.new/kernel/printk.c\r
---- linux-2.4.32/kernel/printk.c       2004-11-17 11:54:22.000000000 +0000\r
-+++ linux-2.4.32.new/kernel/printk.c   2005-12-24 21:28:51.929655544 +0000\r
-@@ -384,6 +384,18 @@\r
-       _call_console_drivers(start_print, end, msg_level);\r
- }\r
\r
-+#if CONFIG_EARLY_PRINTK_HACK\r
-+void putDebugChar(char byte);\r
-+static void emit_log_char(char c)\r
-+{\r
-+      if (c == '\n') {\r
-+              putDebugChar('\r');\r
-+              putDebugChar('\n');\r
-+      } else {\r
-+              putDebugChar(c);\r
-+      }\r
-+}\r
-+#else\r
- static void emit_log_char(char c)\r
- {\r
-       LOG_BUF(log_end) = c;\r
-@@ -395,6 +407,7 @@\r
-       if (logged_chars < LOG_BUF_LEN)\r
-               logged_chars++;\r
- }\r
-+#endif\r
\r
- /*\r
-  * This is printk.  It can be called from any context.  We want it to work.\r
-@@ -700,3 +713,4 @@\r
-               tty->driver.write(tty, 0, msg, strlen(msg));\r
-       return;\r
- }\r
-+\r
+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/openwrt/target/linux/linux-2.4/patches/ar531x/001-ar531x-ethernet.patch b/openwrt/target/linux/linux-2.4/patches/ar531x/001-ar531x-ethernet.patch
deleted file mode 100644 (file)
index 15dd777..0000000
+++ /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\r
---- linux-2.4.32.new/arch/mips/ar531x/ae531xlnx.c      1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new-eth/arch/mips/ar531x/ae531xlnx.c  2005-12-25 11:54:20.756273952 +0000\r
-@@ -0,0 +1,1534 @@\r
-+/*\r
-+ * This file is subject to the terms and conditions of the GNU General Public\r
-+ * License.  See the file "COPYING" in the main directory of this archive\r
-+ * for more details.\r
-+ *\r
-+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.\r
-+ */\r
-+\r
-+/*\r
-+ * Ethernet driver for Atheros' ae531x ethernet MAC.\r
-+ * This is a fairly generic driver, but it's intended\r
-+ * for use in typical Atheros products.\r
-+ */\r
-+\r
-+#include <linux/config.h>\r
-+#include <linux/types.h>\r
-+#include <linux/delay.h>\r
-+#include <linux/netdevice.h>\r
-+#include <linux/etherdevice.h>\r
-+#include <linux/init.h>\r
-+#include <linux/skbuff.h>\r
-+#include <asm/io.h>\r
-+\r
-+#include "ar531xlnx.h"\r
-+#include "ae531xreg.h"\r
-+#include "ae531xmac.h"\r
-+\r
-+/*\r
-+ * A word about CONFIG_VENETDEV: It's intended to support two\r
-+ * "virtualized ethernet devices" that share a single underlying MAC.\r
-+ * To upper layers, it appears that the hardware supports two MACs,\r
-+ * with enet0 used for LAN ports and enet1 used for a WAN port. This\r
-+ * is useful, for instance, when building a 5-port router on hardware\r
-+ * that uses only one of the AR5312's ethernet MACs.\r
-+ *\r
-+ * Virtualization is accomplished through trickery at the ethernet\r
-+ * PHY layer.  We use PHY hardware to determine which port a packet\r
-+ * was received on, and in order to direct a packet to a particular\r
-+ * port or set of ports.\r
-+ *\r
-+ * The code is mostly written to be generalized to more than two\r
-+ * virtual devices; but it's intended for one multi-port LAN enet\r
-+ * device and one single-port WAN enet device.\r
-+ */\r
-+\r
-+#define AE531X_LAN_PORT 0\r
-+#ifdef CONFIG_VENETDEV\r
-+#define AE531X_DEV_PER_MAC 2\r
-+#define AE531X_WAN_PORT 1\r
-+#else\r
-+#define AE531X_DEV_PER_MAC 1\r
-+#endif\r
-+\r
-+\r
-+/*\r
-+ * ae531x_MAC_state contains driver-specific linux-specific per-MAC information.\r
-+ * The OSinfo member of ae531x_MAC_t points to one of these.\r
-+ */\r
-+typedef struct ae531x_MAC_state {\r
-+    int                         irq;\r
-+    struct tq_struct            restart_task;\r
-+    struct net_device_stats     stats;\r
-+    struct ae531x_dev_sw_state  *dev_sw_state[AE531X_DEV_PER_MAC];\r
-+    int                         primary_dev;\r
-+    ae531x_MAC_t                MACInfo; /* hardware state */\r
-+} ae531x_MAC_state_t;\r
-+\r
-+/*\r
-+ * ae531x_dev_sw_state contains driver-specific linux-specific per-device\r
-+ * information.  The net_device priv member points to one of these, and\r
-+ * this structure contains a pointer to the associated MAC information.\r
-+ * In the case of CONFIG_VENETDEV, each virtual device has its own\r
-+ * ae531x_dev_sw_state, and virtual devices that share a physical MAC\r
-+ * point to the same ae531x_MAC_state.\r
-+ */\r
-+typedef struct ae531x_dev_sw_state {\r
-+    int                     enetUnit;        /* system unit number "eth%d" */\r
-+    int                     unit_on_MAC;     /* MAC-relative unit number */\r
-+    struct net_device       *dev;\r
-+    ae531x_MAC_state_t      *MAC_state;      /* underlying MAC hw/sw state */\r
-+#ifdef CONFIG_VENETDEV\r
-+    BOOL                    isLAN;           /* 0-->WAN; 1-->LAN */\r
-+#endif\r
-+} ae531x_dev_sw_state_t;\r
-+\r
-+/*\r
-+ * Driver-independent linux-specific per-ethernet device software information.\r
-+ * Regarding CONFIG_VENETDEV: If a system has 2 physical MACs, and each\r
-+ * physical MAC has 2 virtual ethernet devices (one for LAN and one for WAN),\r
-+ * then there are a total of 4 ethernet devices.\r
-+ */\r
-+static struct net_device *ae531x_MAC_dev[AR531X_NUM_ENET_MAC * AE531X_DEV_PER_MAC];\r
-+\r
-+/* Driver-dependent per-MAC information */\r
-+static ae531x_MAC_state_t per_MAC_info[AR531X_NUM_ENET_MAC];\r
-+\r
-+/*\r
-+ * Receive buffers need enough room to hold the following:\r
-+ * 1) a max MTU-sized packet.  \r
-+ * 2) space for an ethernet header\r
-+ * 3) room at the beginning of the receive buffer in order\r
-+ *    to facilitate cooperating drivers that need to PREpend\r
-+ *    data.\r
-+ * 4) Depending on configuration, we may need some additional\r
-+ *    room at the END of the rx buffer for phy-supplied\r
-+ *    trailers (if any). (c.f. CONFIG_VENETDEV)\r
-+ *\r
-+ * The DMA engine insists on 32-bit aligned RX buffers.\r
-+ * TBDXXX: With current code, the IP stack ends up looking\r
-+ * at misaligned headers with word operations.  The misaligned\r
-+ * reads are software-emulated via handle_adel_int.  We'd\r
-+ * rather align the buffers on a 16-bit boundary, but the\r
-+ * DMA engine doesn't permit it???\r
-+ */\r
-+\r
-+#ifdef CONFIG_VLAN_8021Q\r
-+#define ETH_MAX_MTU 1522\r
-+#define HLEN 18\r
-+#else\r
-+#define ETH_MAX_MTU 1518\r
-+#define HLEN ETH_HLEN\r
-+#endif\r
-+\r
-+#define AE531X_RX_BUF_SIZE \\r
-+    (((2 + RXBUFF_RESERVE + HLEN + ETH_MAX_MTU + PHY_TRAILER_SIZE) + 3) & ~3)\r
-+\r
-+/* Forward references to local functions */\r
-+static void ae531x_TxReap(ae531x_MAC_state_t *MAC_state);\r
-+static int ae531x_phy_poll(void *data);\r
-+static int ae531x_MAC_stop(struct net_device *dev);\r
-+static int ae531x_MAC_open(struct net_device *dev);\r
-+\r
-+/* Global to track number of MACs */\r
-+\r
-+int ar531x_num_enet_macs;\r
-+\r
-+#undef DEBUG_VENETDEV\r
-+#define AR531X_NAPI\r
-+\r
-+#if defined(CONFIG_VENETDEV) && defined(DEBUG_VENETDEV)\r
-+static int cloned_counter;\r
-+static int expand_counter;\r
-+static int both_counter;\r
-+#endif\r
-+\r
-+#ifdef AR531X_NAPI\r
-+/*******************************************************************************\r
-+* ae531x_MAC_poll checks for received packets, and sends data\r
-+* up the stack.\r
-+*/\r
-+int\r
-+ae531x_MAC_poll(struct net_device *dev, int *budget)\r
-+{\r
-+    struct sk_buff *skb;\r
-+    struct sk_buff *newskb;\r
-+    char *rxBufp;\r
-+    int unused_length;\r
-+    VIRT_ADDR   rxDesc;\r
-+    int length;\r
-+    ae531x_dev_sw_state_t *dev_sw_state;\r
-+    ae531x_MAC_state_t *MAC_state;\r
-+    ae531x_MAC_t *MACInfo;\r
-+    u32 cmdsts;\r
-+    int rx_limit;\r
-+    int rx_received;\r
-+    int rxDescCount;\r
-+    struct net_device *rxdev;\r
-+    int early_stop;\r
-+    int retval;\r
-+#ifdef CONFIG_VENETDEV\r
-+    int i;\r
-+#endif\r
-+\r
-+    ARRIVE();\r
-+\r
-+    dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;\r
-+    MAC_state = dev_sw_state->MAC_state;\r
-+    MACInfo = &MAC_state->MACInfo;\r
-+    rx_limit = MAC_state->dev_sw_state[MAC_state->primary_dev]->dev->quota;\r
-+    rx_received = 0;\r
-+\r
-+#ifdef CONFIG_VENETDEV\r
-+    /*\r
-+     * Non-primary devs don't explicitly get polled by the upper layers;\r
-+     * rather, they rely on primary_dev polling to feed packets.  But in\r
-+     * order to keep netif_receive_skb happy, we need to temporarily put the\r
-+     * net_devices into "polling mode".  We pull them back out before\r
-+     * leaving this function.\r
-+     */\r
-+    for (i=0; i<AE531X_DEV_PER_MAC; i++) {\r
-+        if ((MAC_state->dev_sw_state[i]->dev) &&\r
-+            (MAC_state->dev_sw_state[i]->unit_on_MAC != MAC_state->primary_dev)) {\r
-+                netif_rx_schedule(MAC_state->dev_sw_state[i]->dev);\r
-+        }\r
-+    }\r
-+#endif\r
-+    rxDescCount = 0;\r
-+\r
-+    early_stop = 0;\r
-+    do {\r
-+        for(;;) {\r
-+            // ae531x_AckIntr(MACInfo, (DmaIntRxCompleted | DmaIntRxNoBuffer));\r
-+\r
-+            rxDesc = MACInfo->rxQueue.curDescAddr;\r
-+            cmdsts = AE531X_DESC_STATUS_GET(KSEG1ADDR(rxDesc));\r
-+\r
-+            AE531X_PRINT(AE531X_DEBUG_RX,\r
-+                  ("examine rxDesc %p with cmdsts=0x%x\n",\r
-+                   (void *)rxDesc, cmdsts));\r
-+    \r
-+            if (cmdsts & DescOwnByDma) {\r
-+                /* There's nothing left to process in the RX ring */\r
-+                goto rx_all_done;\r
-+            }\r
-+\r
-+            rxDescCount++;\r
-+\r
-+            AE531X_CONSUME_DESC((&MACInfo->rxQueue));\r
-+    \r
-+            // A_DATA_CACHE_INVAL(rxDesc, AE531X_DESC_SIZE);\r
-+\r
-+            /*  Process a packet */\r
-+            length = AE531X_DESC_STATUS_RX_SIZE(cmdsts) - ETH_CRC_LEN;\r
-+            if ( (cmdsts & (DescRxFirst |DescRxLast | DescRxErrors)) ==\r
-+                           (DescRxFirst | DescRxLast) ) {\r
-+                /* Descriptor status indicates "NO errors" */\r
-+                skb = AE531X_DESC_SWPTR_GET(rxDesc);\r
-+    \r
-+                /*\r
-+                 * Allocate a replacement skb.\r
-+                 * We want to get another buffer ready for Rx ASAP.\r
-+                 */\r
-+                newskb = (struct sk_buff *)ae531x_rxbuf_alloc(MACInfo, &rxBufp, &unused_length);\r
-+                if(newskb == NULL ) {\r
-+                    /*\r
-+                     * Give this descriptor back to the DMA engine,\r
-+                     * and drop the received packet.\r
-+                     */\r
-+                    MAC_state->stats.rx_dropped++;\r
-+                    AE531X_PRINT(AE531X_DEBUG_ERROR,\r
-+                              ("Can't allocate new skb\n"));\r
-+                } else {\r
-+                    AE531X_DESC_BUFPTR_SET(rxDesc, rxBufp);\r
-+                    AE531X_DESC_SWPTR_SET(rxDesc, newskb);\r
-+                }\r
-+\r
-+                AE531X_DESC_STATUS_SET(rxDesc, DescOwnByDma);\r
-+              A_DATA_CACHE_FLUSH_INVAL(rxDesc, AE531X_DESC_SIZE);\r
-+                // rxDesc = NULL; /* sanity -- cannot use rxDesc now */\r
-+                sysWbFlush();\r
-+    \r
-+                if (newskb == NULL) {\r
-+                    retval = 1;\r
-+                    goto rx_no_skbs;\r
-+                } else {\r
-+                    /* Sync data cache w.r.t. DMA */\r
-+                    // A_DATA_CACHE_INVAL(skb->data, length);\r
-+        \r
-+#ifdef CONFIG_VENETDEV\r
-+                    /* Determine which associated device owns this rx buffer */\r
-+                    {\r
-+                        int fromLAN;\r
-+\r
-+                        fromLAN = phyDetermineSource(skb->data, length);\r
-+\r
-+                      if (fromLAN == -1) {\r
-+                          /*\r
-+                           * Could not determine source, so drop the packet\r
-+                           */\r
-+                          dev_kfree_skb(skb);\r
-+                          continue;\r
-+                      }\r
-+\r
-+                        length -= PHY_TRAILER_SIZE;\r
-+                        if (fromLAN) {\r
-+                            dev_sw_state = MAC_state->dev_sw_state[AE531X_LAN_PORT];\r
-+                        } else {\r
-+                            dev_sw_state = MAC_state->dev_sw_state[AE531X_WAN_PORT];\r
-+                        }\r
-+                    }\r
-+#endif\r
-+                    rxdev = dev_sw_state->dev;\r
-+\r
-+                    if (rxdev == NULL) {\r
-+                        /*\r
-+                         * We received a packet for a virtual enet device\r
-+                         * that is no longer up.  Ignore it.\r
-+                         */\r
-+                        dev_kfree_skb(skb);\r
-+                        continue;\r
-+                    }\r
-+\r
-+                    /* Advance data pointer to show that there's data here */\r
-+                    skb_put(skb, length);\r
-+                    skb->protocol = eth_type_trans(skb, rxdev);\r
-+                    skb->dev = rxdev;\r
-+                    rxdev->last_rx = jiffies;\r
-+                    rxdev->quota--;\r
-+\r
-+                    if (rx_limit-- < 0) {\r
-+                        early_stop=1;\r
-+                        /* We've done enough for now -- more later */\r
-+                        AE531X_PRINT(AE531X_DEBUG_RX_STOP,\r
-+                            ("Enet%d RX early stop.  Quota=%d rxDescCount=%d budget=%d\n",\r
-+                             MACInfo->unit, dev->quota, rxDescCount, *budget));\r
-+                    }\r
-+                    rx_received++;\r
-+        \r
-+                    /* Send the data up the stack */\r
-+                    AE531X_PRINT(AE531X_DEBUG_RX,\r
-+                              ("Send data up stack: skb=%p data=%p length=%d\n",\r
-+                               (void *)skb, (void *)skb->data, length));\r
-+\r
-+                    netif_receive_skb(skb);\r
-+\r
-+                    MAC_state->stats.rx_packets++;\r
-+                    MAC_state->stats.rx_bytes += length;\r
-+                }\r
-+            } else {\r
-+                /* Descriptor status indicates ERRORS */\r
-+                MAC_state->stats.rx_errors++;\r
-+    \r
-+                if (cmdsts & (DescRxRunt | DescRxLateColl)) {\r
-+                  AE531X_PRINT(AE531X_DEBUG_ERROR,\r
-+                                 ("Runt | RX Late Collision Error\n"));\r
-+                    MAC_state->stats.collisions++;\r
-+                }\r
-+    \r
-+                if (cmdsts & DescRxLengthError) {\r
-+                  AE531X_PRINT(AE531X_DEBUG_ERROR,\r
-+                                 ("RX Length Error\n"));\r
-+                    MAC_state->stats.rx_length_errors++;\r
-+                }\r
-+    \r
-+                if (cmdsts & DescRxCrc) {\r
-+                  AE531X_PRINT(AE531X_DEBUG_ERROR,\r
-+                                 ("RX CRC Error\n"));\r
-+                    MAC_state->stats.rx_crc_errors++;\r
-+                }\r
-+    \r
-+                if (cmdsts & DescRxDribbling) {\r
-+                  AE531X_PRINT(AE531X_DEBUG_ERROR,\r
-+                                 ("Dribbling Error\n"));\r
-+                    MAC_state->stats.rx_frame_errors++;\r
-+                }\r
-+    \r
-+                AE531X_PRINT(AE531X_DEBUG_ERROR,\r
-+                          ("Bad receive.  rxDesc=%p  cmdsts=0x%8.8x\n",\r
-+                           (void *)rxDesc, cmdsts));\r
-+\r
-+              /* Give this one back */\r
-+                AE531X_DESC_STATUS_SET(rxDesc, DescOwnByDma);\r
-+              A_DATA_CACHE_FLUSH_INVAL(rxDesc, AE531X_DESC_SIZE);\r
-+                sysWbFlush();\r
-+            }\r
-+        }\r
-+    } while ((!early_stop) &&\r
-+             ae531x_ReadDmaReg(MACInfo, DmaStatus) & DmaIntRxCompleted);\r
-+\r
-+rx_all_done:\r
-+    AE531X_PRINT(AE531X_DEBUG_RX, \r
-+             ("rx done (%d)\n", rxDescCount));\r
-+    *budget -= rxDescCount;\r
-+\r
-+    if (!early_stop) {\r
-+        netif_rx_complete(dev);\r
-+\r
-+        ae531x_SetDmaReg(MACInfo, DmaIntrEnb,\r
-+                     DmaIeRxCompleted | DmaIeRxNoBuffer);\r
-+        ae531x_WriteDmaReg(MACInfo, DmaRxPollDemand, 0);\r
-+    }\r
-+    \r
-+    retval = early_stop;\r
-+\r
-+rx_no_skbs:\r
-+\r
-+#ifdef CONFIG_VENETDEV\r
-+    for (i=0; i<AE531X_DEV_PER_MAC; i++) {\r
-+        if ((MAC_state->dev_sw_state[i]->dev) &&\r
-+            (MAC_state->dev_sw_state[i]->unit_on_MAC !=\r
-+                                      MAC_state->primary_dev)) {\r
-+                netif_rx_complete(MAC_state->dev_sw_state[i]->dev);\r
-+        }\r
-+    }\r
-+#endif\r
-+\r
-+    LEAVE();\r
-+    return retval;\r
-+}\r
-+#endif\r
-+\r
-+#ifndef AR531X_NAPI\r
-+/*******************************************************************************\r
-+* ae531x_MAC_recv checks for received packets, and sends data\r
-+* up the stack.\r
-+*/\r
-+static void\r
-+ae531x_MAC_recv(struct net_device *dev)\r
-+{\r
-+    struct sk_buff *skb;\r
-+    struct sk_buff *newskb;\r
-+    char *rxBufp;\r
-+    int unused_length;\r
-+    VIRT_ADDR   rxDesc;\r
-+    int length;\r
-+    ae531x_dev_sw_state_t *dev_sw_state;\r
-+    ae531x_MAC_state_t *MAC_state;\r
-+    ae531x_MAC_t *MACInfo;\r
-+    u32 cmdsts;\r
-+    int rx_limit;\r
-+    int rx_received;\r
-+    struct net_device *rxdev;\r
-+    int retval;\r
-+\r
-+    ARRIVE();\r
-+\r
-+    dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;\r
-+    MAC_state = dev_sw_state->MAC_state;\r
-+    MACInfo = &MAC_state->MACInfo;\r
-+    rx_limit = MAC_state->dev_sw_state[MAC_state->primary_dev]->dev->quota;\r
-+    rx_received = 0;\r
-+\r
-+    for(;;) {\r
-+      rxDesc = MACInfo->rxQueue.curDescAddr;\r
-+      cmdsts = AE531X_DESC_STATUS_GET(KSEG1ADDR(rxDesc));\r
-+\r
-+      AE531X_PRINT(AE531X_DEBUG_RX,\r
-+            ("examine rxDesc %p with cmdsts=0x%x\n",\r
-+             (void *)rxDesc, cmdsts));\r
-+\r
-+      if (cmdsts & DescOwnByDma) {\r
-+          /* There's nothing left to process in the RX ring */\r
-+          break;\r
-+      }\r
-+\r
-+      AE531X_CONSUME_DESC((&MACInfo->rxQueue));\r
-+\r
-+      // A_DATA_CACHE_INVAL(rxDesc, AE531X_DESC_SIZE);\r
-+\r
-+      /*  Process a packet */\r
-+      length = AE531X_DESC_STATUS_RX_SIZE(cmdsts) - ETH_CRC_LEN;\r
-+      if ( (cmdsts & (DescRxFirst |DescRxLast | DescRxErrors)) ==\r
-+                     (DescRxFirst | DescRxLast) ) {\r
-+          /* Descriptor status indicates "NO errors" */\r
-+          skb = AE531X_DESC_SWPTR_GET(rxDesc);\r
-+\r
-+          /*\r
-+           * Allocate a replacement skb.\r
-+           * We want to get another buffer ready for Rx ASAP.\r
-+           */\r
-+          newskb = (struct sk_buff *)ae531x_rxbuf_alloc(MACInfo,\r
-+                                                        &rxBufp,\r
-+                                                        &unused_length);\r
-+          if(newskb == NULL ) {\r
-+              /*\r
-+               * Give this descriptor back to the DMA engine,\r
-+               * and drop the received packet.\r
-+               */\r
-+              MAC_state->stats.rx_dropped++;\r
-+              AE531X_PRINT(AE531X_DEBUG_ERROR,\r
-+                        ("Can't allocate new skb\n"));\r
-+          } else {\r
-+              AE531X_DESC_BUFPTR_SET(rxDesc, rxBufp);\r
-+              AE531X_DESC_SWPTR_SET(rxDesc, newskb);\r
-+          }\r
-+\r
-+          AE531X_DESC_STATUS_SET(rxDesc, DescOwnByDma);\r
-+          A_DATA_CACHE_FLUSH_INVAL(rxDesc, AE531X_DESC_SIZE);\r
-+          sysWbFlush();\r
-+\r
-+          if (newskb == NULL) {\r
-+              break;\r
-+          } else {\r
-+#ifdef CONFIG_VENETDEV\r
-+              /* Determine which associated device owns this rx buffer */\r
-+              {\r
-+                  int fromLAN;\r
-+\r
-+                  fromLAN = phyDetermineSource(skb->data, length);\r
-+\r
-+                  if (fromLAN == -1) {\r
-+                      /*\r
-+                       * Could not determine source, so drop the packet\r
-+                       */\r
-+                      dev_kfree_skb(skb);\r
-+                      continue;\r
-+                  }\r
-+\r
-+                  length -= PHY_TRAILER_SIZE;\r
-+                  if (fromLAN) {\r
-+                      dev_sw_state =\r
-+                          MAC_state->dev_sw_state[AE531X_LAN_PORT];\r
-+                  } else {\r
-+                      dev_sw_state =\r
-+                          MAC_state->dev_sw_state[AE531X_WAN_PORT];\r
-+                  }\r
-+              }\r
-+#endif\r
-+              rxdev = dev_sw_state->dev;\r
-+\r
-+              if (rxdev == NULL) {\r
-+                  /*\r
-+                   * We received a packet for a virtual enet device\r
-+                   * that is no longer up.  Ignore it.\r
-+                   */\r
-+                  dev_kfree_skb(skb);\r
-+                  continue;\r
-+              }\r
-+\r
-+              /* Advance data pointer to show that there's data here */\r
-+              skb_put(skb, length);\r
-+              skb->protocol = eth_type_trans(skb, rxdev);\r
-+              skb->dev = rxdev;\r
-+              rxdev->last_rx = jiffies;\r
-+              rxdev->quota--;\r
-+\r
-+              rx_received++;\r
-+    \r
-+              /* Send the data up the stack */\r
-+              AE531X_PRINT(AE531X_DEBUG_RX,\r
-+                        ("Send data up stack: skb=%p data=%p length=%d\n",\r
-+                         (void *)skb, (void *)skb->data, length));\r
-+\r
-+              netif_rx(skb);\r
-+\r
-+              MAC_state->stats.rx_packets++;\r
-+              MAC_state->stats.rx_bytes += length;\r
-+          }\r
-+      } else {\r
-+          /* Descriptor status indicates ERRORS */\r
-+          MAC_state->stats.rx_errors++;\r
-+\r
-+          if (cmdsts & (DescRxRunt | DescRxLateColl)) {\r
-+              MAC_state->stats.collisions++;\r
-+          }\r
-+\r
-+          if (cmdsts & DescRxLengthError) {\r
-+              MAC_state->stats.rx_length_errors++;\r
-+          }\r
-+\r
-+          if (cmdsts & DescRxCrc) {\r
-+              MAC_state->stats.rx_crc_errors++;\r
-+          }\r
-+\r
-+          if (cmdsts & DescRxDribbling) {\r
-+              MAC_state->stats.rx_frame_errors++;\r
-+          }\r
-+\r
-+          AE531X_PRINT(AE531X_DEBUG_ERROR,\r
-+                    ("Bad receive.  rxDesc=%p  cmdsts=0x%8.8x\n",\r
-+                     (void *)rxDesc, cmdsts));\r
-+      }\r
-+    }\r
-+\r
-+    LEAVE();\r
-+    return;\r
-+}\r
-+#endif\r
-+\r
-+/*******************************************************************************\r
-+* ae531x_restart stops all ethernet devices associated with a physical MAC,\r
-+* then shuts down the MAC.  Then it re-opens all devices that were in use.\r
-+* TBDXXX: needs testing!\r
-+*/\r
-+static void\r
-+ae531x_restart(void *data)\r
-+{\r
-+    ae531x_MAC_t *MACInfo = (ae531x_MAC_t *)data;\r
-+    ae531x_MAC_state_t *MAC_state = (ae531x_MAC_state_t *)MACInfo->OSinfo;\r
-+    struct net_device *saved_dev[AE531X_DEV_PER_MAC];\r
-+    int i;\r
-+\r
-+    for (i=0; i<AE531X_DEV_PER_MAC; i++) {\r
-+        if ((saved_dev[i] = MAC_state->dev_sw_state[i]->dev) != NULL) {\r
-+            ae531x_MAC_stop(saved_dev[i]);\r
-+        }\r
-+    }\r
-+\r
-+    for (i=0; i<AE531X_DEV_PER_MAC; i++) {\r
-+        if (saved_dev[i])\r
-+            ae531x_MAC_open(saved_dev[i]);\r
-+    }\r
-+}\r
-+\r
-+/*******************************************************************************\r
-+* ae531x_MAC_intr handle interrupts from an ethernet MAC.\r
-+* It checks MAC status registers, and dispatches as appropriate.\r
-+*/\r
-+void\r
-+ae531x_MAC_intr(int cpl, void *dev_id, struct pt_regs *regs)\r
-+{\r
-+        ae531x_MAC_state_t *MAC_state;\r
-+        ae531x_MAC_t *MACInfo;\r
-+        u32 regIsr;\r
-+        u32 regImr;\r
-+        u32 pendIntrs;\r
-+      struct net_device * primary_dev;\r
-+\r
-+        ARRIVE();\r
-+\r
-+        MACInfo = (ae531x_MAC_t *)dev_id;\r
-+        MAC_state = (ae531x_MAC_state_t *)MACInfo->OSinfo;\r
-+      primary_dev = MAC_state->dev_sw_state[MAC_state->primary_dev]->dev;\r
-+\r
-+        for(;;) {\r
-+                /* Clear any unhandled intr causes. */\r
-+                ae531x_WriteDmaReg(MACInfo, DmaStatus, UnhandledIntrMask);\r
-+\r
-+                regIsr = ae531x_ReadDmaReg(MACInfo, DmaStatus);\r
-+\r
-+                regImr = ae531x_ReadDmaReg(MACInfo, DmaIntrEnb);\r
-+                pendIntrs = regIsr & regImr;\r
-+\r
-+                AE531X_PRINT(AE531X_DEBUG_INT,\r
-+                          ("ethmac%d: intIsr=0x%8.8x intImr=0x%8.8x\n",\r
-+                           MACInfo->unit, regIsr, regImr));\r
-+\r
-+                if ((pendIntrs & DmaAllIntCauseMask) == 0)\r
-+                    break;\r
-+\r
-+                if ((pendIntrs & DmaIntRxCompleted) ||\r
-+                    (pendIntrs & DmaIntRxNoBuffer)) {\r
-+#ifdef AR531X_NAPI\r
-+                    if (netif_rx_schedule_prep(primary_dev)) {\r
-+                        ae531x_ClearDmaReg(MACInfo,\r
-+                                           DmaIntrEnb,\r
-+                                           DmaIeRxCompleted | DmaIeRxNoBuffer);\r
-+                        ae531x_AckIntr(MACInfo,\r
-+                                       DmaIntRxCompleted | DmaIntRxNoBuffer);\r
-+                        (void)ae531x_ReadDmaReg(MACInfo, DmaIntrEnb);\r
-+                        __netif_rx_schedule(primary_dev);\r
-+                    } else {\r
-+                        AE531X_PRINT(AE531X_DEBUG_ERROR,\r
-+                                 ("%s: Interrupt (0x%8.8x/0x%8.8x) while in poll.  regs@%p, pc=%p, ra=%p\n",\r
-+                               __FILE__,\r
-+                               regIsr,\r
-+                               ae531x_ReadDmaReg(MACInfo, DmaIntrEnb),\r
-+                               (void *)regs,\r
-+                               (void *)regs->cp0_epc,\r
-+                               (void *)regs->regs[31]));\r
-+                        ae531x_ClearDmaReg(MACInfo,\r
-+                                           DmaIntrEnb,\r
-+                                           DmaIeRxCompleted | DmaIeRxNoBuffer);\r
-+                        ae531x_AckIntr(MACInfo,\r
-+                                       DmaIntRxCompleted | DmaIntRxNoBuffer);\r
-+                    }\r
-+#else\r
-+                  ae531x_MAC_recv(primary_dev);\r
-+                  ae531x_AckIntr(MACInfo,\r
-+                                   DmaIntRxCompleted | DmaIntRxNoBuffer);\r
-+#endif\r
-+                }\r
-+\r
-+                if (pendIntrs &\r
-+                    (DmaIntTxStopped | DmaIntTxJabber | DmaIntTxUnderflow)) {\r
-+                    AE531X_PRINT(AE531X_DEBUG_ERROR,\r
-+                              ("ethmac%d: TX Error Intr (0x%x)\n",\r
-+                               MACInfo->unit, pendIntrs));\r
-+                    ae531x_AckIntr(MACInfo,\r
-+                        (DmaIntTxStopped | DmaIntTxJabber | DmaIntTxUnderflow));\r
-+                }\r
-+\r
-+                if (pendIntrs & DmaIntBusError) {\r
-+                    AE531X_PRINT(AE531X_DEBUG_ERROR,\r
-+                              ("ethmac%d: DMA Bus Error Intr (0x%x)\n",\r
-+                               MACInfo->unit, pendIntrs));\r
-+                    ae531x_AckIntr(MACInfo, DmaIntBusError);\r
-+                    /* Reset the chip, if it's not already being done */\r
-+                    if (ae531x_IsInResetMode(MACInfo)) {\r
-+                        goto intr_done;\r
-+                    }\r
-+                    ae531x_BeginResetMode(MACInfo);\r
-+                    schedule_task(&MAC_state->restart_task);\r
-+                }\r
-+\r
-+                if (pendIntrs & DmaIntRxStopped) {\r
-+                    AE531X_PRINT(AE531X_DEBUG_ERROR,\r
-+                              ("ethmac%d: RX Stopped Intr (0x%x)\n",\r
-+                               MACInfo->unit, pendIntrs));\r
-+                    ae531x_AckIntr(MACInfo, DmaIntRxStopped);\r
-+                }\r
-+      }\r
-+\r
-+      ae531x_DmaIntEnable(MACInfo);\r
-+\r
-+intr_done:\r
-+      LEAVE();\r
-+}\r
-+\r
-+/*******************************************************************************\r
-+* ae531x_MAC_get_stats returns statistics for a specified device\r
-+*/\r
-+static struct net_device_stats*\r
-+ae531x_MAC_get_stats(struct net_device *dev)\r
-+{\r
-+        ae531x_dev_sw_state_t *dev_sw_state;\r
-+        ae531x_MAC_state_t *MAC_state;\r
-+\r
-+        ARRIVE();\r
-+        dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;\r
-+        MAC_state = dev_sw_state->MAC_state;\r
-+\r
-+        LEAVE();\r
-+        return &MAC_state->stats;\r
-+}\r
-+\r
-+#define AE531X_PHY_POLL_SECONDS 2\r
-+\r
-+/*******************************************************************************\r
-+* ae531x_phy_poll periodically checks for changes in phy status\r
-+* (e.g. dropped link).\r
-+*/\r
-+static int\r
-+ae531x_phy_poll(void *data)\r
-+{\r
-+    ae531x_dev_sw_state_t *dev_sw_state = (ae531x_dev_sw_state_t *)data;\r
-+    ae531x_MAC_t *MACInfo = &dev_sw_state->MAC_state->MACInfo;\r
-+    int unit = dev_sw_state->enetUnit;\r
-+\r
-+#if defined(CONFIG_VENETDEV) && defined(DEBUG_VENETDEV)\r
-+    int       previous_cloned = 0;\r
-+    int       previous_expand = 0;\r
-+    int       previous_both = 0;\r
-+#endif\r
-+\r
-+    daemonize();\r
-+    reparent_to_init();\r
-+    spin_lock_irq(&current->sigmask_lock);\r
-+    sigemptyset(&current->blocked);\r
-+    recalc_sigpending(current);\r
-+    spin_unlock_irq(&current->sigmask_lock);\r
-+\r
-+    snprintf(current->comm, sizeof(current->comm), "%s",\r
-+           dev_sw_state->dev->name);\r
-+\r
-+    for(;;) {\r
-+        if (MACInfo->port_is_up) {\r
-+            phyCheckStatusChange(unit);\r
-+        }\r
-+\r
-+#if defined(CONFIG_VENETDEV) && defined(DEBUG_VENETDEV)\r
-+      if (cloned_counter != previous_cloned) {\r
-+              printk("Cloned Counter: %d (delta %d)\n",\r
-+                      cloned_counter, cloned_counter - previous_cloned);\r
-+              previous_cloned = cloned_counter;\r
-+      }\r
-+      if (expand_counter != previous_expand) {\r
-+              printk("Expand Counter: %d (delta %d)\n",\r
-+                      expand_counter, expand_counter - previous_expand);\r
-+              previous_expand = expand_counter;\r
-+      }\r
-+      if (both_counter != previous_both) {\r
-+              printk("Expand & Cloned Counter: %d (delta %d)\n",\r
-+                      both_counter, both_counter - previous_both);\r
-+              previous_both = both_counter;\r
-+      }\r
-+#endif\r
-+\r
-+        set_current_state(TASK_UNINTERRUPTIBLE);\r
-+        schedule_timeout(AE531X_PHY_POLL_SECONDS * HZ);\r
-+    }\r
-+\r
-+    return 0;\r
-+}\r
-+\r
-+\r
-+/*******************************************************************************\r
-+* ae531x_MAC_set_rx_mode is used to set the RX mode options, such as\r
-+* promiscuous or multicast.\r
-+*/\r
-+static void\r
-+ae531x_MAC_set_rx_mode(struct net_device *dev)\r
-+{\r
-+    ae531x_dev_sw_state_t *dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;\r
-+    ae531x_MAC_state_t *MAC_state=dev_sw_state->MAC_state;\r
-+    ae531x_MAC_t *MACInfo = &MAC_state->MACInfo;\r
-+\r
-+    if (dev->flags & IFF_PROMISC) {\r
-+      ae531x_SetMacReg(MACInfo, MacControl, MacPromiscuousModeOn);\r
-+    } else {\r
-+      ae531x_ClearMacReg(MACInfo, MacControl, MacPromiscuousModeOn);\r
-+    }\r
-+\r
-+    if (dev->flags & IFF_MULTICAST) {\r
-+      ae531x_SetMacReg(MACInfo, MacControl, MacMulticastFilterOff);\r
-+    } else {\r
-+      ae531x_ClearMacReg(MACInfo, MacControl, MacMulticastFilterOff);\r
-+    }\r
-+}\r
-+\r
-+/*******************************************************************************\r
-+* ae531x_MAC_open is the standard Linux open function.  It puts\r
-+* hardware into a known good state, allocates queues, starts\r
-+* the phy polling task, and arranges for interrupts to be handled.\r
-+*/\r
-+static int\r
-+ae531x_MAC_open(struct net_device *dev)\r
-+{\r
-+    ae531x_dev_sw_state_t *dev_sw_state;\r
-+    ae531x_MAC_state_t *MAC_state;\r
-+    ae531x_MAC_t *MACInfo;\r
-+    int rv;\r
-+    struct tq_struct *restart_task;\r
-+    pid_t phy_poll_pid;\r
-+\r
-+    ARRIVE();\r
-+\r
-+    dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;\r
-+    dev_sw_state->dev = dev;\r
-+    MAC_state = dev_sw_state->MAC_state;\r
-+    MACInfo = &MAC_state->MACInfo;\r
-+\r
-+    restart_task = &MAC_state->restart_task;\r
-+    restart_task->routine = ae531x_restart;\r
-+    restart_task->data = (void *)MACInfo;\r
-+\r
-+    AE531X_PRINT(AE531X_DEBUG_RESET,\r
-+              ("ae531x_MAC_open eth%d ethmac%d macBase=0x%x dmaBase=0x%x irq=0x%x\n",\r
-+               dev_sw_state->enetUnit,\r
-+               MACInfo->unit,\r
-+               MACInfo->macBase,\r
-+               MACInfo->dmaBase,\r
-+               MAC_state->irq));\r
-+\r
-+    if (!MACInfo->port_is_up) {\r
-+        /* Bring MAC and PHY out of reset */\r
-+        ae531x_reset(MACInfo);\r
-+    \r
-+        /* Attach interrupt handler */\r
-+        rv = request_irq(MAC_state->irq, ae531x_MAC_intr, SA_INTERRUPT,\r
-+                    "ae531x_MAC_intr", (void *)MACInfo);\r
-+        if (rv < 0) {\r
-+            AE531X_PRINT(AE531X_DEBUG_ERROR,\r
-+                         ("request_irq(0x%x) failed (%d)\n",\r
-+                          MAC_state->irq, rv));\r
-+            goto open_failure;\r
-+        }\r
-+\r
-+        /* Initialize PHY */\r
-+        phySetup(MACInfo->unit, MACInfo->phyBase);\r
-+\r
-+        /* Start thread to poll for phy link status changes */\r
-+        phy_poll_pid = kernel_thread(ae531x_phy_poll,\r
-+                                   dev_sw_state,\r
-+                                   CLONE_FS | CLONE_FILES);\r
-+        if (phy_poll_pid < 0) {\r
-+            AE531X_PRINT(AE531X_DEBUG_ERROR,\r
-+                     ("ethmac%d unable to start Phy Poll thread\n",\r
-+                     MACInfo->unit));\r
-+        }\r
-+\r
-+        /* Allocate RX/TX Queues */\r
-+        if (ae531x_AllocateQueues(MACInfo) < 0) {\r
-+            AE531X_PRINT(AE531X_DEBUG_RESET, ("Queue allocation failed"));\r
-+            free_irq(MAC_state->irq, (void *)MACInfo);\r
-+            goto open_failure;\r
-+        }\r
-+    \r
-+        /* Initialize DMA and descriptors */\r
-+        ae531x_DmaReset(MACInfo);\r
-+\r
-+        /* Initialize MAC */\r
-+        ae531x_MACReset(MACInfo);\r
-+\r
-+      /* Set RX mode */\r
-+      ae531x_MAC_set_rx_mode(dev);\r
-+\r
-+        /* Enable Receive/Transmit */\r
-+        ae531x_EnableComm(MACInfo);\r
-+    \r
-+        MAC_state->primary_dev = dev_sw_state->unit_on_MAC;\r
-+        MACInfo->port_is_up = TRUE;\r
-+    }\r
-+\r
-+    dev->trans_start = jiffies;\r
-+\r
-+    LEAVE();\r
-+    return 0;\r
-+\r
-+open_failure:\r
-+    LEAVE();\r
-+    return -1;\r
-+}\r
-+\r
-+/*\r
-+ * Shut down MAC hardware.\r
-+ */\r
-+static void\r
-+ae531x_MAC_shutdown(ae531x_MAC_state_t *MAC_state)\r
-+{\r
-+    ae531x_MAC_t *MACInfo;\r
-+\r
-+    MACInfo = &MAC_state->MACInfo;\r
-+    MACInfo->port_is_up = FALSE;\r
-+\r
-+    /* Disable Receive/Transmit */\r
-+    ae531x_DisableComm(MACInfo);\r
-+\r
-+    /* Disable Interrupts */\r
-+    ae531x_DmaIntDisable(MACInfo);\r
-+    sysWbFlush();\r
-+    free_irq(MAC_state->irq, (void *)MACInfo);\r
-+\r
-+    /* Free Transmit & Receive skb's/descriptors */\r
-+    ae531x_TxReap(MAC_state); /* one last time */\r
-+    ae531x_FreeQueues(MACInfo);\r
-+}\r
-+\r
-+/*******************************************************************************\r
-+* ae531x_MAC_stop is the standard Linux stop function.  It undoes\r
-+* everything set up by ae531x_MAC_open.\r
-+*/\r
-+static int\r
-+ae531x_MAC_stop(struct net_device *dev)\r
-+{\r
-+    ae531x_dev_sw_state_t *dev_sw_state;\r
-+    ae531x_MAC_state_t *MAC_state;\r
-+    ae531x_MAC_t *MACInfo;\r
-+    int i;\r
-+\r
-+    ARRIVE();\r
-+\r
-+    dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;\r
-+    MAC_state = dev_sw_state->MAC_state;\r
-+    MACInfo = &MAC_state->MACInfo;\r
-+\r
-+    for (i=0; i<AE531X_DEV_PER_MAC; i++) {\r
-+        if ((MAC_state->dev_sw_state[i]->dev) &&\r
-+            (MAC_state->dev_sw_state[i]->dev != dev_sw_state->dev)) {\r
-+            break;\r
-+        }\r
-+    }\r
-+\r
-+    if (i < AE531X_DEV_PER_MAC) {\r
-+        /* Physical MAC is still in use */\r
-+        if (MAC_state->primary_dev == dev_sw_state->unit_on_MAC) {\r
-+            /*\r
-+             * If the primary_dev is being stopped\r
-+             * then we need to assign a new one.\r
-+             */\r
-+            MAC_state->primary_dev = i;\r
-+        }\r
-+    } else {\r
-+        /* Physical MAC is no longer in use */\r
-+        ae531x_MAC_shutdown(MAC_state);\r
-+    }\r
-+\r
-+    dev_sw_state->dev = NULL;\r
-+\r
-+    LEAVE();\r
-+    return 0;\r
-+}\r
-+\r
-+/*******************************************************************************\r
-+* ae531x_rxbuf_alloc - Allocate an skb to be associated with an RX descriptor.\r
-+*\r
-+* RETURNS: A pointer to the skb.  Also returns a pointer to the underlying\r
-+* buffer and the size of that buffer. \r
-+*/\r
-+void *\r
-+ae531x_rxbuf_alloc(ae531x_MAC_t *MACInfo, char **rxBuffp, int *rxBuffSizep)\r
-+{\r
-+    struct sk_buff *skb;\r
-+    char *rxBuff;\r
-+    int rxBuffSize;\r
-+\r
-+    skb = dev_alloc_skb(AE531X_RX_BUF_SIZE);\r
-+    if (skb) {\r
-+      /* Add 2 to align the IP header on a DWORD boundary */\r
-+        skb_reserve(skb, RXBUFF_RESERVE + 2);\r
-+\r
-+        rxBuffSize = skb_tailroom(skb);\r
-+        rxBuff = skb->tail;\r
-+\r
-+        *rxBuffp = rxBuff;\r
-+        *rxBuffSizep = rxBuffSize;\r
-+\r
-+      A_DATA_CACHE_INVAL(rxBuff, rxBuffSize);\r
-+    }\r
-+\r
-+    return skb;\r
-+}\r
-+\r
-+/*******************************************************************************\r
-+* ae531x_swptr_free - Free the skb, if any, associated with a descriptor.\r
-+*/\r
-+void\r
-+ae531x_swptr_free(VIRT_ADDR desc)\r
-+{\r
-+    struct sk_buff *skb;\r
-+\r
-+    skb = (struct sk_buff *)AE531X_DESC_SWPTR_GET(desc);\r
-+    if (skb) {\r
-+        AE531X_DESC_SWPTR_SET(desc, NULL);\r
-+        kfree_skb(skb);\r
-+    }\r
-+}\r
-+\r
-+/*******************************************************************************\r
-+*\r
-+* ae531x_TxReap - the driver Tx completion routine.\r
-+*\r
-+* This routine reaps sk_buffs which have already been transmitted.\r
-+*\r
-+*/\r
-+static void\r
-+ae531x_TxReap(ae531x_MAC_state_t *MAC_state)\r
-+{\r
-+    AE531X_QUEUE      *txq;\r
-+    VIRT_ADDR         txDesc;\r
-+    UINT32            cmdsts;\r
-+    struct            sk_buff *skb;\r
-+    int               reaped;\r
-+    ae531x_MAC_t      *MACInfo;\r
-+    static int        aeUselessReap = 0;\r
-+\r
-+    ARRIVE();\r
-+\r
-+    MACInfo = &MAC_state->MACInfo;\r
-+    txq = &MACInfo->txQueue;\r
-+    reaped = 0;\r
-+\r
-+    while (1) {\r
-+        txDesc = AE531X_QUEUE_ELE_NEXT_GET(txq, txq->reapDescAddr);\r
-+        if (txDesc == txq->curDescAddr) {\r
-+            break;\r
-+        }\r
-+\r
-+        cmdsts = AE531X_DESC_STATUS_GET(KSEG1ADDR(txDesc));\r
-+        if (cmdsts & DescOwnByDma) {\r
-+            break;\r
-+        }\r
-+\r
-+        /* Release sk_buff associated with completed transmit */\r
-+        skb = (struct sk_buff *)AE531X_DESC_SWPTR_GET(txDesc);\r
-+\r
-+        if (skb) {\r
-+            kfree_skb(skb);\r
-+            AE531X_DESC_SWPTR_SET(txDesc, NULL);\r
-+        }\r
-+\r
-+        /* Update statistics according to completed transmit desc */\r
-+        if (cmdsts & DescTxErrors) {\r
-+            AE531X_PRINT(AE531X_DEBUG_ERROR,\r
-+                    ("enetmac%d Tx prior error: 0x%8.8x <0x%8.8x> 0x%8.8x\n",\r
-+                    MACInfo->unit,\r
-+                    cmdsts,\r
-+                    DescTxErrors,\r
-+                    (int)txDesc));\r
-+            MAC_state->stats.tx_errors++;\r
-+            if (cmdsts & (DescTxLateCollision | DescTxExcCollisions)) {\r
-+                MAC_state->stats.tx_aborted_errors++;\r
-+            }\r
-+            if (cmdsts & (DescTxLostCarrier | DescTxNoCarrier)) {\r
-+                MAC_state->stats.tx_carrier_errors++;\r
-+            }\r
-+        } else {\r
-+            MAC_state->stats.tx_bytes += AE531X_DESC_STATUS_RX_SIZE(cmdsts);\r
-+            MAC_state->stats.tx_packets++;\r
-+        }\r
-+\r
-+        MAC_state->stats.collisions +=\r
-+            ((cmdsts & DescTxCollMask) >> DescTxCollShift);\r
-+\r
-+        txq->reapDescAddr = txDesc;\r
-+        reaped++;\r
-+    }\r
-+\r
-+    if (reaped > 0) {\r
-+        int i;\r
-+\r
-+        AE531X_PRINT(AE531X_DEBUG_TX_REAP,\r
-+             ("reaped %d\n", reaped));\r
-+\r
-+        /*\r
-+         * Re-start transmit queues for all ethernet devices\r
-+         * associated with this MAC.\r
-+         */\r
-+        for (i=0; i<AE531X_DEV_PER_MAC; i++) {\r
-+            if (MAC_state->dev_sw_state[i]->dev)\r
-+                netif_start_queue(MAC_state->dev_sw_state[i]->dev);\r
-+        }\r
-+    } else {\r
-+        aeUselessReap++;\r
-+    }\r
-+\r
-+    LEAVE();\r
-+}\r
-+\r
-+/*******************************************************************************\r
-+* ae531x_MAC_start_xmit sends a packet.\r
-+*/\r
-+static int\r
-+ae531x_MAC_start_xmit(struct sk_buff *skb, struct net_device *dev)\r
-+{\r
-+    ae531x_dev_sw_state_t *dev_sw_state;\r
-+    ae531x_MAC_state_t *MAC_state;\r
-+    ae531x_MAC_t *MACInfo;\r
-+    u32 buf;\r
-+    u32 ctrlen;\r
-+    u32 length;\r
-+    int mtu;\r
-+    int max_buf_size;\r
-+    VIRT_ADDR txDesc;\r
-+\r
-+    ARRIVE();\r
-+\r
-+    dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;\r
-+    MAC_state = dev_sw_state->MAC_state;\r
-+    MACInfo = &MAC_state->MACInfo;\r
-+\r
-+    length = skb->len;\r
-+\r
-+    /* Check if this port is up, else toss packet */\r
-+    if (!MACInfo->port_is_up) {\r
-+        buf = virt_to_bus(skb->data);\r
-+        AE531X_PRINT(AE531X_DEBUG_ERROR,\r
-+                  ("eth%d Tx Down, dropping buf=0x%8.8x, length=0x%8.8x, skb=%p\n",\r
-+                   dev_sw_state->enetUnit, buf, length, (void *)skb));\r
-+\r
-+        MAC_state->stats.tx_dropped++;\r
-+        MAC_state->stats.tx_carrier_errors++;\r
-+        goto dropFrame;\r
-+    }\r
-+\r
-+    if (ae531x_IsInResetMode(MACInfo)) {\r
-+        AE531X_PRINT(AE531X_DEBUG_ERROR,\r
-+                  ("eth%d Tx: In Chip reset - drop frame\n",\r
-+                   dev_sw_state->enetUnit));\r
-+\r
-+        MAC_state->stats.tx_dropped++;\r
-+        MAC_state->stats.tx_aborted_errors++;\r
-+        goto dropFrame;\r
-+    }\r
-+\r
-+    /* Check if we can transport this packet */\r
-+    length = max((u32)60, length);  /* total length */\r
-+    mtu = dev->mtu;\r
-+    max_buf_size = mtu + HLEN;\r
-+    if (length > max_buf_size) {\r
-+        AE531X_PRINT(AE531X_DEBUG_ERROR,\r
-+                  ("eth%d Tx: length %d too long.  mtu=%d, trailer=%d\n",\r
-+                   dev_sw_state->enetUnit, length, mtu, PHY_TRAILER_SIZE));\r
-+\r
-+        MAC_state->stats.tx_errors++;\r
-+        MAC_state->stats.tx_aborted_errors++;\r
-+\r
-+        goto dropFrame;\r
-+    }\r
-+\r
-+    /* Reap any old, completed Tx descriptors */\r
-+    ae531x_TxReap(MAC_state);\r
-+\r
-+    txDesc = MACInfo->txQueue.curDescAddr;\r
-+    if (txDesc == MACInfo->txQueue.reapDescAddr) {\r
-+        int i;\r
-+\r
-+        AE531X_PRINT(AE531X_DEBUG_ERROR,\r
-+                  ("eth%d Tx: cannot get txDesc\n",\r
-+                   dev_sw_state->enetUnit));\r
-+\r
-+        MAC_state->stats.tx_dropped++;\r
-+        MAC_state->stats.tx_fifo_errors++;\r
-+\r
-+        /*\r
-+         * Stop transmit queues for any ethernet devices\r
-+         * associated with this MAC.\r
-+         */\r
-+        for (i=0; i<AE531X_DEV_PER_MAC; i++) {\r
-+            if (MAC_state->dev_sw_state[i]->dev)\r
-+                netif_stop_queue(MAC_state->dev_sw_state[i]->dev);\r
-+        }\r
-+        goto dropFrame;\r
-+    }\r
-+\r
-+#ifdef CONFIG_VENETDEV\r
-+    {\r
-+        struct sk_buff *newskb;\r
-+\r
-+      if (skb_cloned(skb) || (skb_tailroom(skb) < PHY_TRAILER_SIZE)) {\r
-+#ifdef DEBUG_VENETDEV\r
-+              if (skb_cloned(skb)) {\r
-+                      cloned_counter++;\r
-+                      if (skb_tailroom(skb) < PHY_TRAILER_SIZE) {\r
-+                              both_counter++;\r
-+                      }\r
-+              } else {\r
-+                      expand_counter++;\r
-+              }\r
-+#endif\r
-+              newskb = skb_copy_expand(skb, 0, PHY_TRAILER_SIZE, GFP_ATOMIC);\r
-+              if (newskb == NULL) {\r
-+                  goto dropFrame;\r
-+              }\r
-+\r
-+              dev_kfree_skb(skb);\r
-+              skb = newskb;\r
-+      }\r
-+\r
-+        phySetDestinationPort(skb->data, length, dev_sw_state->isLAN);\r
-+        skb_put(skb, PHY_TRAILER_SIZE);\r
-+        length += PHY_TRAILER_SIZE;\r
-+    }\r
-+#endif\r
-+\r
-+    /* We won't fail now; so consume this descriptor */\r
-+    AE531X_CONSUME_DESC((&MACInfo->txQueue));\r
-+\r
-+    /* Update the descriptor */\r
-+    buf = virt_to_bus(skb->data);\r
-+    A_DATA_CACHE_FLUSH(skb->data, skb->len);\r
-+    AE531X_DESC_BUFPTR_SET(txDesc, buf);\r
-+    AE531X_DESC_SWPTR_SET(txDesc, skb);\r
-+    ctrlen = AE531X_DESC_CTRLEN_GET(txDesc);\r
-+    ctrlen = (ctrlen & (DescEndOfRing)) |\r
-+                            DescTxFirst |\r
-+                             DescTxLast |\r
-+                        DescTxIntEnable;\r
-+\r
-+    ctrlen |= ((length << DescSize1Shift) & DescSize1Mask);\r
-+\r
-+    AE531X_DESC_CTRLEN_SET(txDesc, ctrlen);\r
-+    AE531X_DESC_STATUS_SET(txDesc, DescOwnByDma);\r
-+\r
-+    AE531X_PRINT(AE531X_DEBUG_TX,\r
-+              ("eth%d Tx: Desc=0x%8.8x, L=0x%8.8x, D=0x%8.8x, d=0x%8.8x, length=0x%8.8x\n",\r
-+               dev_sw_state->enetUnit,\r
-+               (UINT32)txDesc,\r
-+               AE531X_DESC_CTRLEN_GET(txDesc),\r
-+               buf,\r
-+               AE531X_DESC_LNKBUF_GET(txDesc),\r
-+               length));\r
-+\r
-+    /* Must not use txDesc after this point */\r
-+    A_DATA_CACHE_FLUSH_INVAL(txDesc, AE531X_DESC_SIZE);\r
-+\r
-+    /* Alert DMA engine to resume Tx */\r
-+    ae531x_WriteDmaReg(MACInfo, DmaTxPollDemand, 0);\r
-+    sysWbFlush();\r
-+\r
-+    MAC_state->stats.tx_packets++;\r
-+    MAC_state->stats.tx_bytes += length;\r
-+\r
-+    /* Tell upper layers to keep it coming */\r
-+    dev->trans_start = jiffies;\r
-+\r
-+    LEAVE();\r
-+    return 0;\r
-+\r
-+dropFrame:\r
-+    dev_kfree_skb(skb);\r
-+\r
-+    LEAVE();\r
-+    return 0;\r
-+}\r
-+\r
-+\r
-+/*******************************************************************************\r
-+* ae531x_MAC_tx_timeout handles transmit timeouts\r
-+*/\r
-+static void\r
-+ae531x_MAC_tx_timeout(struct net_device *dev)\r
-+{\r
-+    ae531x_dev_sw_state_t *dev_sw_state;\r
-+    ae531x_MAC_state_t *MAC_state;\r
-+    ae531x_MAC_t *MACInfo;\r
-+\r
-+    ARRIVE();\r
-+\r
-+    dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;\r
-+    MAC_state = dev_sw_state->MAC_state;\r
-+    MACInfo = &MAC_state->MACInfo;\r
-+\r
-+    AE531X_PRINT(AE531X_DEBUG_ERROR,\r
-+             ("enet%d: Tx timeout\n", dev_sw_state->enetUnit));\r
-+\r
-+    ae531x_restart(MACInfo);\r
-+\r
-+    LEAVE();\r
-+}\r
-+\r
-+\r
-+/*******************************************************************************\r
-+* ae531x_MAC_do_ioctl is a placeholder for future ioctls.\r
-+*/\r
-+static int\r
-+ae531x_MAC_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)\r
-+{\r
-+        int rv;\r
-+        ae531x_MAC_t *MACInfo;\r
-+        struct ioctl_data {\r
-+                u32 unit;\r
-+                u32 addr;\r
-+                u32 data;\r
-+        } *req;\r
-+        ae531x_dev_sw_state_t *dev_sw_state;\r
-+        ae531x_MAC_state_t *MAC_state;\r
-+\r
-+        ARRIVE();\r
-+\r
-+        dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;\r
-+        MAC_state = dev_sw_state->MAC_state;\r
-+        MACInfo = &MAC_state->MACInfo;\r
-+\r
-+        req = (struct ioctl_data *)ifr->ifr_data;\r
-+\r
-+        switch( cmd ) {\r
-+        default:\r
-+            AE531X_PRINT(AE531X_DEBUG_ERROR,\r
-+                     ("Unsupported ioctl: 0x%x\n", cmd));\r
-+            rv = -EOPNOTSUPP;\r
-+        }\r
-+\r
-+        LEAVE();\r
-+        return rv;\r
-+}\r
-+\r
-+/*******************************************************************************\r
-+* ae531x_MAC_set_mac_address sets a new hardware address for the device\r
-+*/\r
-+static int\r
-+ae531x_MAC_set_mac_address(struct net_device *dev, void *addr)\r
-+{\r
-+      struct sockaddr *saddr = (struct sockaddr *)addr;\r
-+\r
-+      /* update dev struct */\r
-+      memcpy(dev->dev_addr, &saddr->sa_data[0], dev->addr_len);\r
-+\r
-+      return 0;\r
-+}\r
-+\r
-+/******************************************************************************\r
-+* macAddrGet - Given a MACInfo pointer, return a pointer to an\r
-+* array of chars that holds the corresponding MAC address.\r
-+*/\r
-+char *macAddrGet(ae531x_MAC_t *MACInfo)\r
-+{\r
-+    // return enet_mac_address_get(MACInfo->unit);\r
-+    return ae531x_MAC_dev[MACInfo->unit]->dev_addr;\r
-+}\r
-+\r
-+static void\r
-+ae531x_MAC_setup_fntable(struct net_device *dev)\r
-+{\r
-+    /* Set a default (should be overridden by software) */\r
-+    u8 default_MAC_address[] = { 0x00, 0x03, 0x7f, 0xe0, 0x02, 0xbF };\r
-+\r
-+    ARRIVE();\r
-+\r
-+    dev->get_stats            = ae531x_MAC_get_stats;\r
-+    dev->open                 = ae531x_MAC_open;\r
-+    dev->stop                 = ae531x_MAC_stop;\r
-+    dev->hard_start_xmit      = ae531x_MAC_start_xmit;\r
-+    dev->do_ioctl             = ae531x_MAC_do_ioctl;\r
-+#ifdef AR531X_NAPI\r
-+    dev->poll                 = ae531x_MAC_poll;\r
-+    dev->weight                       = 16;\r
-+#endif\r
-+    dev->tx_timeout           = ae531x_MAC_tx_timeout;\r
-+    dev->features             = NETIF_F_HW_CSUM |\\r
-+                                 NETIF_F_HIGHDMA;\r
-+    dev->set_mac_address      = ae531x_MAC_set_mac_address;\r
-+    dev->set_multicast_list   = ae531x_MAC_set_rx_mode;\r
-+\r
-+    /* Copy default MAC address into device descriptor */\r
-+    memcpy(dev->dev_addr, default_MAC_address, dev->addr_len );\r
-+\r
-+    LEAVE();\r
-+}\r
-+\r
-+/*\r
-+ * ae531x_twisted_enet() returns 1 for chips where there is only one usable\r
-+ * MAC, and that MAC is 1.\r
-+ */\r
-+static BOOL\r
-+ae531x_twisted_enet(void)\r
-+{\r
-+    int wisoc_revision;\r
-+    int flash_bus_width;\r
-+\r
-+    wisoc_revision = (sysRegRead(AR531X_REV) & AR531X_REV_MAJ) >>\r
-+                                                             AR531X_REV_MAJ_S;\r
-+    if (wisoc_revision == AR531X_REV_MAJ_AR2313)\r
-+        return TRUE;\r
-+\r
-+    flash_bus_width = sysRegRead(AR531X_FLASHCTL0) & FLASHCTL_MWx16;\r
-+\r
-+    if (flash_bus_width == 0) {\r
-+      printk("Found AR2312-01\n");\r
-+      return TRUE;            /* AR2312-01 has 8 bit flash bus */\r
-+    } else {\r
-+      printk("Found AR2312-00\n");\r
-+      return FALSE;\r
-+    }\r
-+}\r
-+\r
-+int\r
-+ae531x_MAC_setup(void)\r
-+{\r
-+    int i;\r
-+    int next_dev;\r
-+    int rev;\r
-+    struct net_device *dev;\r
-+    ae531x_dev_sw_state_t *dev_sw_state;\r
-+    ae531x_MAC_state_t *MAC_state;\r
-+    ae531x_MAC_t *MACInfo;\r
-+\r
-+    ARRIVE();\r
-+\r
-+#if 0\r
-+    /*\r
-+     * This does not work since the AR2312 and AR5312 both have the same\r
-+     * revision information in the CPU :-(\r
-+     */\r
-+    rev = (sysRegRead(AR531X_REV) & AR531X_REV_CHIP);\r
-+\r
-+    if ((rev & AR531X_REV_MIN) == AR5312_REV_MIN_SINGLE_ENET) {\r
-+      ar531x_num_enet_macs = 1;\r
-+    } else {\r
-+      ar531x_num_enet_macs = 2;\r
-+    }\r
-+#else\r
-+    /*\r
-+     * Need to select the number of ethernet MACs based on the config\r
-+     * information (sadly)\r
-+     */\r
-+#ifdef CONFIG_AR5312\r
-+    ar531x_num_enet_macs = 2;\r
-+#else\r
-+    ar531x_num_enet_macs = 1;\r
-+#endif\r
-+#endif\r
-+\r
-+    next_dev = 0;\r
-+    for (i=0; i<ar531x_num_enet_macs; i++) {\r
-+\r
-+        dev = ae531x_MAC_dev[next_dev] =\r
-+            init_etherdev(NULL, sizeof(ae531x_dev_sw_state_t));\r
-+\r
-+        if (dev == NULL) {\r
-+            LEAVE();\r
-+            return -1;\r
-+        }\r
-+\r
-+        ae531x_MAC_setup_fntable(dev);\r
-+\r
-+        dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;\r
-+        dev_sw_state->enetUnit = next_dev;\r
-+        dev_sw_state->unit_on_MAC = 0;\r
-+        MAC_state = &per_MAC_info[i];\r
-+        dev_sw_state->MAC_state = MAC_state;\r
-+        MAC_state->dev_sw_state[AE531X_LAN_PORT] = dev_sw_state;\r
-+        MAC_state->primary_dev = -1;\r
-+\r
-+        next_dev++;\r
-+\r
-+#ifdef CONFIG_VENETDEV\r
-+        {\r
-+            ae531x_dev_sw_state_t *lan_dev_sw_state;\r
-+\r
-+            lan_dev_sw_state = dev_sw_state;\r
-+    \r
-+            dev = ae531x_MAC_dev[next_dev] =\r
-+                init_etherdev(NULL, sizeof(ae531x_dev_sw_state_t));\r
-+\r
-+            if (dev == NULL) {\r
-+                LEAVE();\r
-+                return -1;\r
-+            }\r
-+    \r
-+            ae531x_MAC_setup_fntable(dev);\r
-+    \r
-+            dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;\r
-+            dev_sw_state->enetUnit = next_dev;\r
-+            dev_sw_state->unit_on_MAC = 1;\r
-+            dev_sw_state->MAC_state = MAC_state;\r
-+            MAC_state->dev_sw_state[AE531X_WAN_PORT] = dev_sw_state;\r
-+            lan_dev_sw_state->isLAN = TRUE; /* enet0 is LAN */\r
-+            dev_sw_state->isLAN = FALSE ;     /* enet1 is WAN */\r
-+\r
-+            next_dev++;\r
-+        }\r
-+#endif\r
-+\r
-+        /* Initialize per-MAC information */\r
-+        MACInfo = &MAC_state->MACInfo;\r
-+        MACInfo->unit = i;\r
-+\r
-+      if (ar531x_num_enet_macs == 1) {\r
-+          if (ae531x_twisted_enet()) {\r
-+                MACInfo->macBase =\r
-+                      (u32)(PHYS_TO_K1(AR531X_ENET1)+AE531X_MAC_OFFSET);\r
-+                MACInfo->dmaBase =\r
-+                      (u32)(PHYS_TO_K1(AR531X_ENET1)+AE531X_DMA_OFFSET);\r
-+                MACInfo->phyBase =\r
-+                      (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET);\r
-+                MAC_state->irq = AR531X_IRQ_ENET1_INTRS;\r
-+          } else {\r
-+                MACInfo->macBase =\r
-+                      (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_MAC_OFFSET);\r
-+                MACInfo->dmaBase =\r
-+                      (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_DMA_OFFSET);\r
-+                MACInfo->phyBase =\r
-+                      (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET);\r
-+                MAC_state->irq = AR531X_IRQ_ENET0_INTRS;\r
-+          }\r
-+      } else {\r
-+            if (MACInfo->unit == 0) {\r
-+                MACInfo->macBase =\r
-+                      (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_MAC_OFFSET);\r
-+                MACInfo->dmaBase =\r
-+                      (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_DMA_OFFSET);\r
-+                MACInfo->phyBase =\r
-+                      (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET);\r
-+                MAC_state->irq = AR531X_IRQ_ENET0_INTRS;\r
-+            } else {\r
-+                MACInfo->macBase =\r
-+                      (u32)(PHYS_TO_K1(AR531X_ENET1)+AE531X_MAC_OFFSET);\r
-+                MACInfo->dmaBase =\r
-+                      (u32)(PHYS_TO_K1(AR531X_ENET1)+AE531X_DMA_OFFSET);\r
-+                MACInfo->phyBase =\r
-+                      (u32)(PHYS_TO_K1(AR531X_ENET1)+AE531X_PHY_OFFSET);\r
-+                MAC_state->irq = AR531X_IRQ_ENET1_INTRS;\r
-+            }\r
-+      }\r
-+        MACInfo->OSinfo = (void *)MAC_state;\r
-+    }\r
-+\r
-+    LEAVE();\r
-+    return 0;\r
-+}\r
-+\r
-+module_init(ae531x_MAC_setup);\r
-+\r
-diff -urN linux-2.4.32.new/arch/mips/ar531x/ae531xmac.c linux-2.4.32.new-eth/arch/mips/ar531x/ae531xmac.c\r
---- linux-2.4.32.new/arch/mips/ar531x/ae531xmac.c      1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new-eth/arch/mips/ar531x/ae531xmac.c  2005-12-25 11:54:20.771271672 +0000\r
-@@ -0,0 +1,942 @@\r
-+/*\r
-+ * This file is subject to the terms and conditions of the GNU General Public\r
-+ * License.  See the file "COPYING" in the main directory of this archive\r
-+ * for more details.\r
-+ *\r
-+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.\r
-+ */\r
-+\r
-+\r
-+/*\r
-+ * Ethernet driver for Atheros' ae531x ethernet MAC.\r
-+ */\r
-+\r
-+#if linux\r
-+#include <linux/config.h>\r
-+#include <linux/types.h>\r
-+#include <linux/delay.h>\r
-+#include <linux/netdevice.h>\r
-+#include <linux/etherdevice.h>\r
-+#include <linux/init.h>\r
-+#include <asm/io.h>\r
-+\r
-+#include "ar531xlnx.h"\r
-+#endif /* linux */\r
-+\r
-+#include "ae531xreg.h"\r
-+#include "ae531xmac.h"\r
-+\r
-+int ae531x_MAC_debug = AE531X_DEBUG_ERROR;\r
-+\r
-+/*\r
-+ * These externs are for functions that this layer relies on\r
-+ * that have OS-dependent implementations.\r
-+ */\r
-+extern UINT8 *macAddrGet(ae531x_MAC_t *MACInfo);\r
-+\r
-+/* Forward references to local functions */\r
-+static void ae531x_QueueDestroy(AE531X_QUEUE *q);\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* ae531x_ReadMacReg - read AE MAC register\r
-+*\r
-+* RETURNS: register value\r
-+*/\r
-+UINT32\r
-+ae531x_ReadMacReg(ae531x_MAC_t *MACInfo, UINT32 reg)\r
-+{\r
-+    UINT32 addr = MACInfo->macBase+reg;\r
-+    UINT32 data;\r
-+\r
-+    data = RegRead(addr);\r
-+    return data;\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* ae531x_WriteMacReg - write AE MAC register\r
-+*\r
-+* RETURNS: N/A\r
-+*/\r
-+void\r
-+ae531x_WriteMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data)\r
-+{\r
-+    UINT32 addr = MACInfo->macBase+reg;\r
-+\r
-+    RegWrite(data, addr);\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* ae531x_SetMacReg - set bits in AE MAC register\r
-+*\r
-+* RETURNS: N/A\r
-+*/\r
-+void\r
-+ae531x_SetMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val)\r
-+{\r
-+    UINT32 addr = MACInfo->macBase+reg;\r
-+    UINT32 data = RegRead(addr);\r
-+\r
-+    data |= val;\r
-+    RegWrite(data, addr);\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* ae531x_ClearMacReg - clear bits in AE MAC register\r
-+*\r
-+* RETURNS: N/A\r
-+*/\r
-+void\r
-+ae531x_ClearMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val)\r
-+{\r
-+    UINT32 addr = MACInfo->macBase+reg;\r
-+    UINT32 data = RegRead(addr);\r
-+\r
-+    data &= ~val;\r
-+    RegWrite(data, addr);\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* ae531x_ReadDmaReg - read AE DMA register\r
-+*\r
-+* RETURNS: register value\r
-+*/\r
-+UINT32\r
-+ae531x_ReadDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg)\r
-+{\r
-+    UINT32 addr = MACInfo->dmaBase+reg;\r
-+    UINT32 data = RegRead(addr);\r
-+\r
-+    return data;\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* ae531x_WriteDmaReg - write AE DMA register\r
-+*\r
-+* RETURNS: N/A\r
-+*/\r
-+void\r
-+ae531x_WriteDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data)\r
-+{\r
-+    UINT32 addr = MACInfo->dmaBase+reg;\r
-+\r
-+    RegWrite(data, addr);\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+ *\r
-+ * ae531x_AckIntr - clear interrupt bits in the status register.\r
-+ * Note: Interrupt bits are *cleared* by writing a 1.\r
-+ */\r
-+void\r
-+ae531x_AckIntr(ae531x_MAC_t *MACInfo, UINT32 data)\r
-+{\r
-+      ae531x_WriteDmaReg(MACInfo, DmaStatus, data);\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* ae531x_SetDmaReg - set bits in an AE DMA register\r
-+*\r
-+* RETURNS: N/A\r
-+*/\r
-+void\r
-+ae531x_SetDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val)\r
-+{\r
-+    UINT32 addr = MACInfo->dmaBase+reg;\r
-+    UINT32 data = RegRead(addr);\r
-+\r
-+    data |= val;\r
-+    RegWrite(data, addr);\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* ae531x_ClearDmaReg - clear bits in an AE DMA register\r
-+*\r
-+* RETURNS: N/A\r
-+*/\r
-+void\r
-+ae531x_ClearDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val)\r
-+{\r
-+    UINT32 addr = MACInfo->dmaBase+reg;\r
-+    UINT32 data = RegRead(addr);\r
-+\r
-+    data &= ~val;\r
-+    RegWrite(data, addr);\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* ae531x_ReadMiiReg - read PHY registers via AE MAC Mii addr/data registers\r
-+*\r
-+* RETURNS: register value\r
-+*/\r
-+UINT32\r
-+ae531x_ReadMiiReg(UINT32 phyBase, UINT32 reg)\r
-+{\r
-+    UINT32 data;\r
-+    UINT32 addr = phyBase+reg;\r
-+\r
-+    data = RegRead(addr);\r
-+    return data;\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* ae531x_WriteMiiReg - write PHY registers via AE MAC Mii addr/data registers\r
-+*\r
-+* RETURNS: N/A\r
-+*/\r
-+void\r
-+ae531x_WriteMiiReg(UINT32 phyBase, UINT32 reg, UINT32 data)\r
-+{\r
-+    UINT32 addr = phyBase+reg;\r
-+\r
-+    RegWrite(data, addr);\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* ae531x_MiiRead - read AE Mii register\r
-+*\r
-+* RETURNS: register value\r
-+*/\r
-+UINT16\r
-+ae531x_MiiRead(UINT32 phyBase, UINT32 phyAddr, UINT8 reg)\r
-+{\r
-+    UINT32 addr;\r
-+    UINT16 data;\r
-+\r
-+    addr = ((phyAddr << MiiDevShift) & MiiDevMask) | ((reg << MiiRegShift) & MiiRegMask);\r
-+\r
-+    ae531x_WriteMiiReg(phyBase, MacMiiAddr, addr );\r
-+    do {\r
-+        /* nop */\r
-+    } while ((ae531x_ReadMiiReg(phyBase, MacMiiAddr ) & MiiBusy) == MiiBusy);\r
-+\r
-+    data = ae531x_ReadMiiReg(phyBase, MacMiiData) & 0xFFFF;\r
-+\r
-+    return data;\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* ae531x_MiiWrite - write AE Mii register\r
-+*\r
-+* RETURNS: N/A\r
-+*/\r
-+void\r
-+ae531x_MiiWrite(UINT32 phyBase, UINT32 phyAddr, UINT8 reg, UINT16 data)\r
-+{\r
-+    UINT32 addr;\r
-+\r
-+    ae531x_WriteMiiReg(phyBase, MacMiiData, data );\r
-+\r
-+    addr = ((phyAddr << MiiDevShift) & MiiDevMask) |\r
-+        ((reg << MiiRegShift) & MiiRegMask) | MiiWrite;\r
-+    ae531x_WriteMiiReg(phyBase, MacMiiAddr, addr );\r
-+\r
-+    do {\r
-+        /* nop */\r
-+    } while ((ae531x_ReadMiiReg(phyBase, MacMiiAddr ) & MiiBusy) == MiiBusy);\r
-+}\r
-+\r
-+\r
-+/*******************************************************************************\r
-+* ae531x_BeginResetMode - enter a special "reset mode" in which\r
-+*    -no interrupts are expected from the device\r
-+*    -the device will not transmit nor receive\r
-+*    -attempts to send or receive will return with an error and\r
-+*    -the device will be reset at the next convenient opportunity.\r
-+*/\r
-+void\r
-+ae531x_BeginResetMode(ae531x_MAC_t *MACInfo)\r
-+{\r
-+    /* Set the reset flag */\r
-+    MACInfo->aeProcessRst = 1;\r
-+}\r
-+\r
-+\r
-+/*******************************************************************************\r
-+* ae531x_EndResetMode - exit the special "reset mode" entered\r
-+* earlier via a call to ae531x_BeginResetMode.\r
-+*/\r
-+void\r
-+ae531x_EndResetMode(ae531x_MAC_t *MACInfo)\r
-+{\r
-+    MACInfo->aeProcessRst = 0;\r
-+}\r
-+\r
-+\r
-+/*******************************************************************************\r
-+* ae531x_IsInResetMode - determine whether or not the device is\r
-+* currently in "reset mode" (i.e. that a device reset is pending)\r
-+*/\r
-+BOOL\r
-+ae531x_IsInResetMode(ae531x_MAC_t *MACInfo)\r
-+{\r
-+    return MACInfo->aeProcessRst;\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* ae531x_DmaRxStart - Start Rx\r
-+*\r
-+* RETURNS: N/A\r
-+*/\r
-+static void\r
-+ae531x_DmaRxStart(ae531x_MAC_t *MACInfo)\r
-+{\r
-+    ae531x_SetDmaReg(MACInfo, DmaControl, DmaRxStart);\r
-+    sysWbFlush();\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* ae531x_DmaRxStop - Stop Rx\r
-+*\r
-+* RETURNS: N/A\r
-+*/\r
-+void\r
-+ae531x_DmaRxStop(ae531x_MAC_t *MACInfo)\r
-+{\r
-+    ae531x_ClearDmaReg(MACInfo, DmaControl, DmaRxStart);\r
-+    sysWbFlush();\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* ae531x_DmaTxStart - Start Tx\r
-+*\r
-+* RETURNS: N/A\r
-+*/\r
-+void\r
-+ae531x_DmaTxStart(ae531x_MAC_t *MACInfo)\r
-+{\r
-+    ae531x_SetDmaReg(MACInfo, DmaControl, DmaTxStart);\r
-+    sysWbFlush();\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* ae531x_DmaTxStop - Stop Tx\r
-+*\r
-+* RETURNS: N/A\r
-+*/\r
-+void\r
-+ae531x_DmaTxStop(ae531x_MAC_t *MACInfo)\r
-+{\r
-+    ae531x_ClearDmaReg(MACInfo, DmaControl, DmaTxStart);\r
-+    sysWbFlush();\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* ae531x_DmaIntEnable - Enable DMA interrupts\r
-+*\r
-+* RETURNS: N/A\r
-+*/\r
-+void\r
-+ae531x_DmaIntEnable(ae531x_MAC_t *MACInfo)\r
-+{\r
-+    ae531x_WriteDmaReg(MACInfo, DmaIntrEnb, DmaIntEnable);\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* ae531x_DmaIntDisable - Disable DMA interrupts\r
-+*\r
-+* RETURNS: N/A\r
-+*/\r
-+void\r
-+ae531x_DmaIntDisable(ae531x_MAC_t *MACInfo)\r
-+{\r
-+    ae531x_WriteDmaReg(MACInfo, DmaIntrEnb, DmaIntDisable);\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* ae531x_DmaIntClear - Clear DMA interrupts\r
-+*\r
-+* RETURNS: N/A\r
-+*/\r
-+static void\r
-+ae531x_DmaIntClear(ae531x_MAC_t *MACInfo)\r
-+{\r
-+    /* clear all interrupt requests */\r
-+    ae531x_WriteDmaReg(MACInfo, DmaStatus,\r
-+                      ae531x_ReadDmaReg(MACInfo, DmaStatus));  \r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+* Initialize generic queue data\r
-+*/\r
-+void\r
-+ae531x_QueueInit(AE531X_QUEUE *q, char *pMem, int count)\r
-+{\r
-+    ARRIVE();\r
-+    q->firstDescAddr = pMem;\r
-+    q->lastDescAddr = (VIRT_ADDR)((UINT32)q->firstDescAddr +\r
-+                                  (count - 1) * AE531X_QUEUE_ELE_SIZE);\r
-+    q->curDescAddr = q->firstDescAddr;\r
-+    q->count = count;\r
-+    LEAVE();\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+* ae531x_TxQueueCreate - create a circular queue of descriptors for Transmit\r
-+*/\r
-+static int\r
-+ae531x_TxQueueCreate(ae531x_MAC_t *MACInfo,\r
-+                  AE531X_QUEUE *q,\r
-+                  char *pMem,\r
-+                  int count)\r
-+{\r
-+    int         i;\r
-+    VIRT_ADDR   descAddr;\r
-+\r
-+    ARRIVE();\r
-+\r
-+    ae531x_QueueInit(q, pMem, count);\r
-+    q->reapDescAddr = q->lastDescAddr;\r
-+\r
-+    /* Initialize Tx buffer descriptors.  */\r
-+    for (i=0, descAddr=q->firstDescAddr;\r
-+         i<count;\r
-+         i++, descAddr=(VIRT_ADDR)((UINT32)descAddr + AE531X_QUEUE_ELE_SIZE))\r
-+    {\r
-+        /* Update the size, BUFPTR, and SWPTR fields */\r
-+\r
-+        AE531X_DESC_STATUS_SET(descAddr, 0);\r
-+        AE531X_DESC_CTRLEN_SET(descAddr, 0);\r
-+\r
-+        AE531X_DESC_BUFPTR_SET(descAddr, (UINT32)0);\r
-+        AE531X_DESC_LNKBUF_SET(descAddr, (UINT32)0);\r
-+        AE531X_DESC_SWPTR_SET(descAddr, (void *)0);\r
-+    } /* for each desc */\r
-+\r
-+    /* Make the queue circular */\r
-+    AE531X_DESC_CTRLEN_SET(q->lastDescAddr,\r
-+                       DescEndOfRing|AE531X_DESC_CTRLEN_GET(q->lastDescAddr));\r
-+\r
-+    AE531X_PRINT(AE531X_DEBUG_RESET,\r
-+            ("ethmac%d Txbuf begin = %x, end = %x\n",\r
-+            MACInfo->unit,\r
-+            (UINT32)q->firstDescAddr,\r
-+            (UINT32)q->lastDescAddr));\r
-+\r
-+    LEAVE();\r
-+    return 0;\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+* ae531x_RxQueueCreate - create a circular queue of Rx descriptors\r
-+*/\r
-+int\r
-+ae531x_RxQueueCreate(ae531x_MAC_t *MACInfo,\r
-+                  AE531X_QUEUE *q,\r
-+                  char *pMem,\r
-+                  int count)\r
-+{\r
-+    int               i;\r
-+    VIRT_ADDR         descAddr;\r
-+\r
-+    ARRIVE();\r
-+\r
-+    ae531x_QueueInit(q, pMem, count);\r
-+    q->reapDescAddr = NULL;\r
-+\r
-+\r
-+    /* Initialize Rx buffer descriptors */\r
-+    for (i=0, descAddr=q->firstDescAddr;\r
-+         i<count;\r
-+         i++, descAddr=(VIRT_ADDR)((UINT32)descAddr + AE531X_QUEUE_ELE_SIZE))\r
-+    {\r
-+        void *swptr;\r
-+        char *rxBuffer;\r
-+        int  rxBufferSize;\r
-+\r
-+        swptr = ae531x_rxbuf_alloc(MACInfo, &rxBuffer, &rxBufferSize);\r
-+        if (swptr == NULL) {\r
-+                AE531X_PRINT(AE531X_DEBUG_RESET,\r
-+                          ("ethmac%d RX queue: ae531x_rxbuf_alloc failed\n",\r
-+                           MACInfo->unit));\r
-+                ae531x_QueueDestroy(q);\r
-+                return -1;\r
-+        }\r
-+        AE531X_DESC_SWPTR_SET(descAddr, swptr);\r
-+\r
-+        AE531X_DESC_STATUS_SET(descAddr, DescOwnByDma);\r
-+        AE531X_DESC_CTRLEN_SET(descAddr, rxBufferSize);\r
-+        AE531X_DESC_BUFPTR_SET(descAddr, virt_to_bus(rxBuffer));\r
-+        AE531X_DESC_LNKBUF_SET(descAddr, (UINT32)0);\r
-+    } /* for each desc */\r
-+\r
-+    /* Make the queue circular */\r
-+    AE531X_DESC_CTRLEN_SET(q->lastDescAddr,\r
-+                       DescEndOfRing|AE531X_DESC_CTRLEN_GET(q->lastDescAddr));\r
-+\r
-+    AE531X_PRINT(AE531X_DEBUG_RESET,\r
-+              ("ethmac%d Rxbuf begin = %x, end = %x\n",\r
-+              MACInfo->unit,\r
-+              (UINT32)q->firstDescAddr,\r
-+              (UINT32)q->lastDescAddr));\r
-+\r
-+    LEAVE();\r
-+    return 0;\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+* ae531x_QueueDestroy -- Free all buffers and descriptors associated \r
-+* with a queue.\r
-+*/\r
-+static void\r
-+ae531x_QueueDestroy(AE531X_QUEUE *q)\r
-+{\r
-+    int i;\r
-+    int count;\r
-+    VIRT_ADDR    descAddr;\r
-+\r
-+    ARRIVE();\r
-+\r
-+    count = q->count;\r
-+\r
-+    for (i=0, descAddr=q->firstDescAddr;\r
-+         i<count;\r
-+         i++, descAddr=(VIRT_ADDR)((UINT32)descAddr + AE531X_QUEUE_ELE_SIZE)) {\r
-+\r
-+        AE531X_DESC_STATUS_SET(descAddr, 0);\r
-+        AE531X_DESC_CTRLEN_SET(descAddr, 0);\r
-+        AE531X_DESC_BUFPTR_SET(descAddr, (UINT32)0);\r
-+        AE531X_DESC_LNKBUF_SET(descAddr, (UINT32)0);\r
-+\r
-+        ae531x_swptr_free(descAddr); /* Free OS-specific software pointer */\r
-+    }\r
-+\r
-+    LEAVE();\r
-+}\r
-+\r
-+static void\r
-+ae531x_TxQueueDestroy(ae531x_MAC_t *MACInfo)\r
-+{\r
-+    ae531x_QueueDestroy(&MACInfo->txQueue);\r
-+}\r
-+\r
-+static void\r
-+ae531x_RxQueueDestroy(ae531x_MAC_t *MACInfo)\r
-+{\r
-+    ae531x_QueueDestroy(&MACInfo->rxQueue);\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+* ae531x_AllocateQueues - Allocate receive and transmit queues\r
-+*/\r
-+int\r
-+ae531x_AllocateQueues(ae531x_MAC_t *MACInfo)\r
-+{\r
-+    size_t QMemSize;\r
-+    char *pTxBuf = NULL;\r
-+    char *pRxBuf = NULL;\r
-+\r
-+    ARRIVE();\r
-+\r
-+    MACInfo->txDescCount = AE531X_TX_DESC_COUNT_DEFAULT;\r
-+    QMemSize = AE531X_QUEUE_ELE_SIZE * MACInfo->txDescCount;\r
-+    pTxBuf = MALLOC(QMemSize);\r
-+    if (pTxBuf == NULL) {\r
-+        AE531X_PRINT(AE531X_DEBUG_RESET,\r
-+                  ("ethmac%d Failed to allocate TX queue\n", MACInfo->unit));\r
-+        goto AllocQFail;\r
-+    }\r
-+\r
-+    if (ae531x_TxQueueCreate(MACInfo, &MACInfo->txQueue, pTxBuf,\r
-+                          MACInfo->txDescCount) < 0)\r
-+    {\r
-+        AE531X_PRINT(AE531X_DEBUG_RESET,\r
-+                ("ethmac%d Failed to create TX queue\n", MACInfo->unit));\r
-+        goto AllocQFail;\r
-+    }\r
-+\r
-+    MACInfo->rxDescCount = AE531X_RX_DESC_COUNT_DEFAULT;\r
-+    QMemSize = AE531X_QUEUE_ELE_SIZE * MACInfo->rxDescCount;\r
-+    pRxBuf = MALLOC(QMemSize);\r
-+    if (pRxBuf == NULL) {\r
-+        AE531X_PRINT(AE531X_DEBUG_RESET,\r
-+                  ("ethmac%d Failed to allocate RX queue\n", MACInfo->unit));\r
-+        goto AllocQFail;\r
-+    }\r
-+\r
-+    if (ae531x_RxQueueCreate(MACInfo, &MACInfo->rxQueue, pRxBuf,\r
-+                          MACInfo->rxDescCount) < 0)\r
-+    {\r
-+        AE531X_PRINT(AE531X_DEBUG_RESET,\r
-+                ("ethmac%d Failed to create RX queue\n", MACInfo->unit));\r
-+        goto AllocQFail;\r
-+    }\r
-+\r
-+    AE531X_PRINT(AE531X_DEBUG_RESET,\r
-+            ("ethmac%d Memory setup complete.\n", MACInfo->unit));\r
-+\r
-+    LEAVE();\r
-+    return 0;\r
-+\r
-+AllocQFail:\r
-+    MACInfo->txDescCount = 0; /* sanity */\r
-+    MACInfo->rxDescCount = 0; /* sanity */\r
-+\r
-+    if (pTxBuf) {\r
-+        FREE(pTxBuf);\r
-+    }\r
-+    if (pRxBuf) {\r
-+        FREE(pRxBuf);\r
-+    }\r
-+    \r
-+    LEAVE();\r
-+    return -1;\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* ae531x_FreeQueues - Free Transmit & Receive queues\r
-+*/\r
-+void\r
-+ae531x_FreeQueues(ae531x_MAC_t *MACInfo)\r
-+{\r
-+    ae531x_TxQueueDestroy(MACInfo);\r
-+    FREE(MACInfo->txQueue.firstDescAddr);\r
-+\r
-+    ae531x_RxQueueDestroy(MACInfo);\r
-+    FREE(MACInfo->rxQueue.firstDescAddr);\r
-+}\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* ae531x_DmaReset - Reset DMA and TLI controllers\r
-+*\r
-+* RETURNS: N/A\r
-+*/\r
-+void\r
-+ae531x_DmaReset(ae531x_MAC_t *MACInfo)\r
-+{\r
-+    int        i;\r
-+    UINT32     descAddr;\r
-+\r
-+    ARRIVE();\r
-+\r
-+    /* Disable device interrupts prior to any errors during stop */\r
-+    intDisable(MACInfo->ilevel);\r
-+\r
-+    /* Disable MAC rx and tx */\r
-+    ae531x_ClearMacReg(MACInfo, MacControl, (MacRxEnable | MacTxEnable));\r
-+\r
-+    /* Reset dma controller */\r
-+    ae531x_WriteDmaReg(MACInfo, DmaBusMode, DmaResetOn);\r
-+\r
-+    /* Delay 2 usec */\r
-+    sysUDelay(2);\r
-+\r
-+    /* Flush the rx queue */\r
-+    descAddr = (UINT32)MACInfo->rxQueue.firstDescAddr;\r
-+    MACInfo->rxQueue.curDescAddr = MACInfo->rxQueue.firstDescAddr;\r
-+    for (i=0;\r
-+         i<(MACInfo->rxDescCount);\r
-+         i++, descAddr += AE531X_QUEUE_ELE_SIZE) {\r
-+            AE531X_DESC_STATUS_SET(descAddr, DescOwnByDma);\r
-+    }\r
-+\r
-+    /* Flush the tx queue */\r
-+    descAddr = (UINT32)MACInfo->txQueue.firstDescAddr;\r
-+    MACInfo->txQueue.curDescAddr = MACInfo->txQueue.firstDescAddr;\r
-+    MACInfo->txQueue.reapDescAddr = MACInfo->txQueue.lastDescAddr;\r
-+    for (i=0;\r
-+         i<(MACInfo->txDescCount);\r
-+         i++, descAddr += AE531X_QUEUE_ELE_SIZE) {\r
-+            AE531X_DESC_STATUS_SET (descAddr, 0);\r
-+    }\r
-+\r
-+    /* Set init register values  */\r
-+    ae531x_WriteDmaReg(MACInfo, DmaBusMode, DmaBusModeInit);\r
-+\r
-+    /* Install the first Tx and Rx queues on the device */\r
-+    ae531x_WriteDmaReg(MACInfo, DmaRxBaseAddr,\r
-+                      (UINT32)MACInfo->rxQueue.firstDescAddr);\r
-+    ae531x_WriteDmaReg(MACInfo, DmaTxBaseAddr,\r
-+                      (UINT32)MACInfo->txQueue.firstDescAddr);\r
-+\r
-+    ae531x_WriteDmaReg(MACInfo, DmaControl, DmaStoreAndForward);\r
-+\r
-+    ae531x_WriteDmaReg(MACInfo, DmaIntrEnb, DmaIntDisable);\r
-+\r
-+    AE531X_PRINT(AE531X_DEBUG_RESET,\r
-+              ("ethmac%d: DMA RESET!\n", MACInfo->unit));\r
-+\r
-+    /* Turn on device interrupts -- enable most errors */\r
-+    ae531x_DmaIntClear(MACInfo);    /* clear interrupt requests  */\r
-+    ae531x_DmaIntEnable(MACInfo);   /* enable interrupts */\r
-+    /* Enable receive interrupts separately (they are not part\r
-+     * of the main group since they are enabled & disabled by\r
-+     * the polling routine.\r
-+     */\r
-+    ae531x_SetDmaReg(MACInfo, DmaIntrEnb,\r
-+              (DmaIntRxNoBuffer | DmaIntRxCompleted));\r
-+\r
-+    ae531x_EndResetMode(MACInfo);\r
-+\r
-+    intEnable(MACInfo->ilevel);\r
-+\r
-+    LEAVE();\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* ae531x_MACAddressSet - Set the ethernet address\r
-+*\r
-+* Sets the ethernet address according to settings in flash.\r
-+*\r
-+* RETURNS: void\r
-+*/\r
-+static void\r
-+ae531x_MACAddressSet(ae531x_MAC_t *MACInfo)\r
-+{\r
-+    unsigned int    data;\r
-+    UINT8 *macAddr;\r
-+\r
-+    ARRIVE();\r
-+        \r
-+    macAddr = macAddrGet(MACInfo);\r
-+\r
-+    /* set our MAC address  */\r
-+    data = (macAddr[5]<<8) | macAddr[4];\r
-+    ae531x_WriteMacReg(MACInfo, MacAddrHigh, data );\r
-+\r
-+    data = (macAddr[3]<<24) | (macAddr[2]<<16) | (macAddr[1]<<8) | macAddr[0];\r
-+    ae531x_WriteMacReg(MACInfo, MacAddrLow, data );\r
-+\r
-+    AE531X_PRINT(AE531X_DEBUG_RESET,\r
-+              ("ethmac%d Verify MAC address %8.8X %8.8X \n",\r
-+               MACInfo->unit,\r
-+               ae531x_ReadMacReg(MACInfo, MacAddrLow),\r
-+               ae531x_ReadMacReg(MACInfo, MacAddrHigh)));\r
-+\r
-+    AE531X_PRINT(AE531X_DEBUG_RESET,\r
-+              ("  sb = %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",\r
-+               0xff&macAddr[0],\r
-+               0xff&macAddr[1],\r
-+               0xff&macAddr[2],\r
-+               0xff&macAddr[3],\r
-+               0xff&macAddr[4],\r
-+               0xff&macAddr[5]));\r
-+    LEAVE();\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* ae_SetMACFromPhy - read Phy settings and update Mac\r
-+*                    with current duplex and speed.\r
-+*\r
-+* RETURNS:\r
-+*/\r
-+static void\r
-+ae531x_SetMACFromPhy(ae531x_MAC_t *MACInfo)\r
-+{\r
-+    UINT32  macCtl;\r
-+    BOOL    fullDuplex;\r
-+\r
-+    ARRIVE();\r
-+\r
-+    /* Get duplex mode from Phy */\r
-+    fullDuplex = phyIsFullDuplex(MACInfo->unit);\r
-+\r
-+    /* Flag is set for full duplex mode, else cleared */\r
-+    macCtl = ae531x_ReadMacReg(MACInfo, MacControl);\r
-+\r
-+    if (fullDuplex) {\r
-+        /* set values of control registers */\r
-+        macCtl &= ~MacDisableRxOwn;\r
-+        macCtl |= MacFullDuplex;\r
-+        ae531x_WriteMacReg(MACInfo, MacControl, macCtl);\r
-+        ae531x_WriteMacReg(MACInfo, MacFlowControl, MacFlowControlInitFdx);\r
-+#if 0\r
-+      printk ("[Full Duplex] CTRL=%#x FLOW=%#x\n", macCtl,\r
-+              MacFlowControlInitFdx);\r
-+#endif\r
-+    } else {\r
-+        /* set values of control registers */\r
-+        ae531x_WriteMacReg(MACInfo, MacFlowControl, MacFlowControlInitHdx);\r
-+        macCtl |= MacDisableRxOwn;\r
-+        macCtl &= ~MacFullDuplex;\r
-+        ae531x_WriteMacReg(MACInfo, MacControl, macCtl);\r
-+#if 0\r
-+      printk ("[Half Duplex] CTRL=%#x FLOW=%#x\n", macCtl,\r
-+              MacFlowControlInitHdx);\r
-+#endif\r
-+    }\r
-+\r
-+    LEAVE();\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+* ae531x_MACReset -- sets MAC address and duplex.\r
-+*/\r
-+void\r
-+ae531x_MACReset(ae531x_MAC_t *MACInfo)\r
-+{\r
-+    ae531x_MACAddressSet(MACInfo);\r
-+\r
-+    ae531x_SetMACFromPhy(MACInfo);\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+* ae531x_EnableComm -- enable Transmit and Receive\r
-+*/\r
-+void\r
-+ae531x_EnableComm(ae531x_MAC_t *MACInfo)\r
-+{\r
-+    ae531x_SetMacReg(MACInfo, MacControl, (MacRxEnable | MacTxEnable));\r
-+    ae531x_DmaRxStart(MACInfo);     /* start receiver  */\r
-+    ae531x_DmaTxStart(MACInfo);     /* start transmitter */\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+* ae531x_DisableComm -- disable Transmit and Receive\r
-+*/\r
-+void\r
-+ae531x_DisableComm(ae531x_MAC_t *MACInfo)\r
-+{\r
-+    ae531x_ClearMacReg(MACInfo, MacControl, (MacRxEnable | MacTxEnable));\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+* ae531x_reset -- Cold reset ethernet interface\r
-+*/\r
-+void\r
-+ae531x_reset(ae531x_MAC_t *MACInfo)\r
-+{\r
-+    UINT32 mask = 0;\r
-+    UINT32 regtmp;\r
-+   \r
-+    if (ar531x_num_enet_macs == 2) {\r
-+        if (MACInfo->unit == 0) {\r
-+            mask = AR531X_RESET_ENET0 | AR531X_RESET_EPHY0;\r
-+        } else {\r
-+            mask = AR531X_RESET_ENET1 | AR531X_RESET_EPHY1;\r
-+        }\r
-+    } else {\r
-+            mask = AR531X_RESET_ENET0 | AR531X_RESET_EPHY0 |\r
-+                   AR531X_RESET_ENET1 | AR531X_RESET_EPHY1;\r
-+    }\r
-+\r
-+    /* Put into reset */\r
-+    regtmp = sysRegRead(AR531X_RESET);\r
-+    sysRegWrite(AR531X_RESET, regtmp | mask);\r
-+    sysMsDelay(15);\r
-+\r
-+    /* Pull out of reset */\r
-+    regtmp = sysRegRead(AR531X_RESET);\r
-+    sysRegWrite(AR531X_RESET, regtmp & ~mask);\r
-+    sysUDelay(25);\r
-+\r
-+    /* Enable */\r
-+    if (ar531x_num_enet_macs == 2) {\r
-+        if (MACInfo->unit == 0) {\r
-+            mask = AR531X_ENABLE_ENET0;\r
-+        } else {\r
-+            mask = AR531X_ENABLE_ENET1;\r
-+        }\r
-+    } else {\r
-+            mask = AR531X_ENABLE_ENET0 | AR531X_ENABLE_ENET1;\r
-+    }\r
-+    regtmp = sysRegRead(AR531X_ENABLE);\r
-+    sysRegWrite(AR531X_ENABLE, regtmp | mask);\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+* ae531x_unitLinkLost -- Called from PHY layer to notify the MAC layer\r
-+* that there are no longer any live links associated with a MAC.\r
-+*/\r
-+void\r
-+ae531x_unitLinkLost(int ethUnit)\r
-+{\r
-+    AE531X_PRINT(AE531X_DEBUG_LINK_CHANGE,\r
-+             ("enetmac%d link down\n", ethUnit));\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+* ae531x_unitLinkGained -- Called from PHY layer to notify the MAC layer\r
-+* that there are 1 or more live links associated with a MAC.\r
-+*/\r
-+void\r
-+ae531x_unitLinkGained(int ethUnit)\r
-+{\r
-+    AE531X_PRINT(AE531X_DEBUG_LINK_CHANGE,\r
-+             ("enet%d link up\n", ethUnit));\r
-+}\r
-+\r
-+/******************************************************************************\r
-+* ae531x_ethMacDefault -- Called from PHY layer to determine the default\r
-+* ethernet MAC.  On some "twisted" platforms, the only usable MAC is 1,\r
-+* while on others the usable MAC is 0.  Future boards may allow both MACs\r
-+* to be used; in this case, return -1 to indicate that there IS NO default\r
-+* MAC.\r
-+*\r
-+* Note: one some AR2312 platforms the PHY needs to be accessed through\r
-+* MAC 0, even though the MAC itself is addressed through MAC 1. Since this\r
-+* function is used by the PHY layer to determine which MAC it should use,\r
-+* the twisted case is limited to the one where the PHY is actually addressed\r
-+* through MAC 1 rather than MAC 0.\r
-+*/\r
-+int\r
-+ae531x_ethMacDefault(void)\r
-+{\r
-+    /*\r
-+     * Where there are two MACs, there is no real default\r
-+     */\r
-+    if (ar531x_num_enet_macs == 2)\r
-+        return -1;\r
-+\r
-+    /*\r
-+     * All single MAC platforms seem to address the PHY through MAC 0,\r
-+     * even when they use MAC 1 for the actual MAC functions.\r
-+     */\r
-+    return 0;\r
-+}\r
-diff -urN linux-2.4.32.new/arch/mips/ar531x/ae531xmac.h linux-2.4.32.new-eth/arch/mips/ar531x/ae531xmac.h\r
---- linux-2.4.32.new/arch/mips/ar531x/ae531xmac.h      1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new-eth/arch/mips/ar531x/ae531xmac.h  2005-12-25 11:54:20.819264376 +0000\r
-@@ -0,0 +1,208 @@\r
-+/*\r
-+ * This file is subject to the terms and conditions of the GNU General Public\r
-+ * License.  See the file "COPYING" in the main directory of this archive\r
-+ * for more details.\r
-+ *\r
-+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.\r
-+ */\r
-+\r
-+/*\r
-+ * See README to understand the decomposition of the ethernet driver.\r
-+ *\r
-+ * This file contains OS-independent pure software definitions for\r
-+ * ethernet support on the AR531X platform.\r
-+ */\r
-+\r
-+#ifndef _AE531XMAC_H_\r
-+#define _AE531XMAC_H_\r
-+\r
-+/*\r
-+ * DEBUG switches to control verbosity.\r
-+ * Just modify the value of ae531x_MAC_debug.\r
-+ */\r
-+#define AE531X_DEBUG_ALL         0xffffffff\r
-+#define AE531X_DEBUG_ERROR       0x00000001 /* Unusual conditions and Errors */\r
-+#define AE531X_DEBUG_ARRIVE      0x00000002 /* Arrive into a function */\r
-+#define AE531X_DEBUG_LEAVE       0x00000004 /* Leave a function */\r
-+#define AE531X_DEBUG_RESET       0x00000008 /* Reset */\r
-+#define AE531X_DEBUG_TX          0x00000010 /* Transmit */\r
-+#define AE531X_DEBUG_TX_REAP     0x00000020 /* Transmit Descriptor Reaping */\r
-+#define AE531X_DEBUG_RX          0x00000040 /* Receive */\r
-+#define AE531X_DEBUG_RX_STOP     0x00000080 /* Receive Early Stop */\r
-+#define AE531X_DEBUG_INT         0x00000100 /* Interrupts */\r
-+#define AE531X_DEBUG_LINK_CHANGE 0x00000200 /* PHY Link status changed */\r
-+\r
-+extern int ae531x_MAC_debug;\r
-+\r
-+extern int ar531x_num_enet_macs;\r
-+\r
-+#define AE531X_PRINT(FLG, X)                            \\r
-+{                                                   \\r
-+    if (ae531x_MAC_debug & (FLG)) {                  \\r
-+        DEBUG_PRINTF("%s#%d:%s ",                   \\r
-+                     __FILE__,                      \\r
-+                     __LINE__,                      \\r
-+                     __FUNCTION__);                 \\r
-+        DEBUG_PRINTF X;                             \\r
-+    }                                               \\r
-+}\r
-+\r
-+#define ARRIVE() AE531X_PRINT(AE531X_DEBUG_ARRIVE, ("Arrive{\n"))\r
-+#define LEAVE() AE531X_PRINT(AE531X_DEBUG_LEAVE, ("}Leave\n"))\r
-+\r
-+#define RegRead(addr) \\r
-+      (*(volatile unsigned int *)(addr))\r
-+\r
-+#define RegWrite(val,addr)    \\r
-+      ((*(volatile unsigned int *)(addr)) = (val))\r
-+\r
-+/*****************************************************************\r
-+ * Phy code is broken out into a separate layer, so that different\r
-+ * PHY hardware can easily be supported.\r
-+ *\r
-+ * These functions are provided by the PHY layer for use by the MAC layer.\r
-+ *   phySetup             -- Set phy hardware appropriately for a MAC unit\r
-+ *\r
-+ *   phyCheckStatusChange -- Look for dropped/initiated links on any\r
-+ *                           phy port associated with a MAC unit\r
-+ *\r
-+ *   phyIsSpeed100        -- Determines whether or not a PHY is up and\r
-+ *                           running at 100Mbit\r
-+ *\r
-+ *   phyIsFullDuplex      -- Determines whether or not a PHY is up and\r
-+ *                           running in Full Duplex mode\r
-+ *\r
-+ */\r
-+#ifdef CONFIG_MARVELL_ENET_PHY\r
-+/*\r
-+ * Mapping of generic phy APIs to Marvell Ethernet Switch phy functions.\r
-+ */\r
-+#include "mvPhy.h"\r
-+#define phySetup(ethUnit, phyBase)      mv_phySetup((ethUnit), (phyBase))\r
-+#define phyCheckStatusChange(ethUnit)   mv_phyCheckStatusChange(ethUnit)\r
-+#define phyIsSpeed100(ethUnit)          mv_phyIsSpeed100(ethUnit)\r
-+#define phyIsFullDuplex(ethUnit)        mv_phyIsFullDuplex(ethUnit)\r
-+\r
-+#ifdef CONFIG_VENETDEV\r
-+#define PHY_TRAILER_SIZE    MV_PHY_TRAILER_SIZE\r
-+extern int mv_phyDetermineSource(char *data, int len);\r
-+extern void mv_phySetDestinationPort(char *data, int len, int fromLAN);\r
-+#define phyDetermineSource(data, len) mv_phyDetermineSource((data), (len))\r
-+#define phySetDestinationPort(data, len, fromLAN) mv_phySetDestinationPort((data), (len), (fromLAN))\r
-+#else\r
-+#define PHY_TRAILER_SIZE    0\r
-+#endif\r
-+#endif /* CONFIG_MARVELL_ENET_PHY */\r
-+\r
-+#if defined(CONFIG_KENDIN_ENET_PHY) || defined(CONFIG_REALTEK_ENET_PHY)\r
-+/*\r
-+ * Mapping of generic phy APIs to Kendin KS8721B and RealTek RTL8201BL phys.\r
-+ */\r
-+#include "rtPhy.h"\r
-+#define phySetup(ethUnit, phyBase)      rt_phySetup((ethUnit), (phyBase))\r
-+#define phyCheckStatusChange(ethUnit)   rt_phyCheckStatusChange(ethUnit)\r
-+#define phyIsSpeed100(ethUnit)          rt_phyIsSpeed100(ethUnit)\r
-+#define phyIsFullDuplex(ethUnit)        rt_phyIsFullDuplex(ethUnit)\r
-+#endif\r
-+\r
-+#if !defined(PHY_TRAILER_SIZE)\r
-+#define PHY_TRAILER_SIZE    0\r
-+#endif\r
-+\r
-+/*****************************************************************\r
-+ * MAC-independent interface to be used by PHY code\r
-+ *\r
-+ * These functions are provided by the MAC layer for use by the PHY layer.\r
-+ */\r
-+#define phyRegRead ae531x_MiiRead\r
-+#define phyRegWrite ae531x_MiiWrite\r
-+#define phyLinkLost(ethUnit) ae531x_unitLinkLost(ethUnit)\r
-+#define phyLinkGained(ethUnit) ae531x_unitLinkGained(ethUnit)\r
-+#define phyEthMacDefault() ae531x_ethMacDefault()\r
-+\r
-+void ae531x_unitLinkLost(int unit);\r
-+void ae531x_unitLinkGained(int unit);\r
-+int ae531x_ethMacDefault(void);\r
-+\r
-+\r
-+/* RXBUFF_RESERVE enables building header on WLAN-side in place */\r
-+#define RXBUFF_RESERVE   96\r
-+#define ETH_CRC_LEN       4\r
-+\r
-+/*****************************************************************\r
-+ * Descriptor queue\r
-+ */\r
-+typedef struct ae531x_queue {\r
-+    VIRT_ADDR   firstDescAddr;  /* descriptor array address */\r
-+    VIRT_ADDR   lastDescAddr;   /* last descriptor address */\r
-+    VIRT_ADDR   curDescAddr;    /* current descriptor address */\r
-+    VIRT_ADDR   reapDescAddr;   /* current tail of tx descriptors reaped */\r
-+    UINT16      count;          /* number of elements */\r
-+} AE531X_QUEUE;\r
-+\r
-+/* Given a descriptor, return the next one in a circular list */\r
-+#define AE531X_QUEUE_ELE_NEXT_GET(q, descAddr)                          \\r
-+        ((descAddr) == (q)->lastDescAddr) ? (q)->firstDescAddr :    \\r
-+        (VIRT_ADDR)((UINT32)(descAddr) + AE531X_QUEUE_ELE_SIZE)\r
-+\r
-+/* Move the "current descriptor" forward to the next one */\r
-+#define AE531X_CONSUME_DESC(q)    \\r
-+         q->curDescAddr = AE531X_QUEUE_ELE_NEXT_GET(q, q->curDescAddr)\r
-+\r
-+/*****************************************************************\r
-+ * Per-ethernet-MAC OS-independent information\r
-+ */\r
-+typedef struct ae531x_MAC_s {\r
-+    u32             unit;          /* MAC unit ID */\r
-+    u32             macBase;       /* MAC base address */\r
-+    u32             dmaBase;       /* DMA base address */\r
-+    u32             phyBase;       /* PHY base address */\r
-+    AE531X_QUEUE    txQueue;       /* Transmit descriptor queue */\r
-+    AE531X_QUEUE    rxQueue;       /* Receive descriptor queue */\r
-+    UINT16          txDescCount;   /* Transmit descriptor count */\r
-+    UINT16          rxDescCount;   /* Receive descriptor count */\r
-+    BOOL            aeProcessRst;  /* flag to indicate reset in progress */\r
-+    BOOL            port_is_up;    /* flag to indicate port is up */\r
-+    void            *OSinfo;       /* OS-dependent data */\r
-+} ae531x_MAC_t;\r
-+\r
-+#define       AE531X_TX_DESC_COUNT_DEFAULT    64     /* Transmit descriptors */\r
-+#define AE531X_RX_DESC_COUNT_DEFAULT  64     /* Receive descriptors */\r
-+\r
-+\r
-+/*****************************************************************\r
-+ * Interfaces exported by the OS-independent MAC layer\r
-+ */\r
-+void ae531x_BeginResetMode(ae531x_MAC_t *MACInfo);\r
-+void ae531x_EndResetMode(ae531x_MAC_t *MACInfo);\r
-+BOOL ae531x_IsInResetMode(ae531x_MAC_t *MACInfo);\r
-+int ae531x_RxQueueCreate(ae531x_MAC_t *MACInfo, AE531X_QUEUE *q,\r
-+                  char *pMem, int count);\r
-+int ae531x_QueueDelete(struct ae531x_queue *q);\r
-+void ae531x_DmaReset(ae531x_MAC_t *MACInfo);\r
-+void ae531x_MACReset(ae531x_MAC_t *MACInfo);\r
-+void ae531x_EnableComm(ae531x_MAC_t *MACInfo);\r
-+void ae531x_DisableComm(ae531x_MAC_t *MACInfo);\r
-+void ae531x_reset(ae531x_MAC_t *MACInfo);\r
-+int ae531x_AllocateQueues(ae531x_MAC_t *MACInfo);\r
-+void ae531x_FreeQueues(ae531x_MAC_t *MACInfo);\r
-+void ae531x_QueueInit(AE531X_QUEUE *q, char *pMem, int count);\r
-+UINT32 ae531x_ReadMacReg(ae531x_MAC_t *MACInfo, UINT32 reg);\r
-+void ae531x_WriteMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data);\r
-+void ae531x_SetMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);\r
-+void ae531x_ClearMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);\r
-+void ae531x_SetDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);\r
-+void ae531x_ClearDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);\r
-+UINT32 ae531x_ReadDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg);\r
-+void ae531x_WriteDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data);\r
-+UINT32 ae531x_ReadMiiReg(UINT32 phyBase, UINT32 reg);\r
-+void ae531x_WriteMiiReg(UINT32 phyBase, UINT32 reg, UINT32 data);\r
-+UINT16 ae531x_MiiRead(UINT32 phyBase, UINT32 phyAddr, UINT8 reg);\r
-+void ae531x_MiiWrite(UINT32 phyBase, UINT32 phyAddr, UINT8 reg, UINT16 data);\r
-+void ae531x_DmaIntEnable(ae531x_MAC_t *MACInfo);\r
-+void ae531x_DmaIntDisable(ae531x_MAC_t *MACInfo);\r
-+void ae531x_AckIntr(ae531x_MAC_t *MACInfo, UINT32 val);\r
-+void *ae531x_rxbuf_alloc(ae531x_MAC_t *MACInfo, char **rxBptr, int *rxBSize);\r
-+void ae531x_swptr_free(VIRT_ADDR txDesc);\r
-+\r
-+#endif /* _AE531XMAC_H_ */\r
-diff -urN linux-2.4.32.new/arch/mips/ar531x/ae531xreg.h linux-2.4.32.new-eth/arch/mips/ar531x/ae531xreg.h\r
---- linux-2.4.32.new/arch/mips/ar531x/ae531xreg.h      1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new-eth/arch/mips/ar531x/ae531xreg.h  2005-12-25 11:54:20.834262096 +0000\r
-@@ -0,0 +1,437 @@\r
-+/*\r
-+ * This file is subject to the terms and conditions of the GNU General Public\r
-+ * License.  See the file "COPYING" in the main directory of this archive\r
-+ * for more details.\r
-+ *\r
-+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.\r
-+ */\r
-+\r
-+/*\r
-+ * See README to understand the decomposition of the ethernet driver.\r
-+ *\r
-+ * Register definitions for Atheros AR531X Ethernet MAC.\r
-+ */\r
-+\r
-+#ifndef _AE531XREG_H_\r
-+#define _AE531XREG_H_\r
-+\r
-+#define AE531X_MAC_OFFSET 0x0000\r
-+#define AE531X_PHY_OFFSET 0x0000 /* Same as MAC offset */\r
-+#define AE531X_DMA_OFFSET 0x1000\r
-+\r
-+/***********************************************************/\r
-+/* MAC110 registers, base address is BAR+AE531X_MAC_OFFSET */\r
-+/***********************************************************/\r
-+#define MacControl            0x00  /* control */\r
-+#define MacAddrHigh           0x04  /* address high */\r
-+#define MacAddrLow            0x08  /* address low */\r
-+#define MacMultiHashHigh      0x0C  /* multicast hash table high */\r
-+#define MacMultiHashLow       0x10  /* multicast hash table low */\r
-+#define MacMiiAddr            0x14  /* MII address */\r
-+#define MacMiiData            0x18  /* MII data */\r
-+#define MacFlowControl        0x1C  /* Flow control */\r
-+#define MacVlan1Tag           0x4C  /* VLAN1 tag */\r
-+#define MacVlan2Tag           0x50  /* VLAN2 tag */\r
-+\r
-+\r
-+/***************************************************************/\r
-+/* DMA engine registers, base address is BAR+AE531X_DMA_OFFSET */\r
-+/***************************************************************/\r
-+#define DmaBusMode      0x00 /* CSR0 - Bus Mode */\r
-+#define DmaTxPollDemand 0x04 /* CSR1 - Transmit Poll Demand */\r
-+#define DmaRxPollDemand 0x08 /* CSR2 - Receive Poll Demand */\r
-+#define DmaRxBaseAddr   0x0C /* CSR3 - Receive list base address */\r
-+#define DmaTxBaseAddr   0x10 /* CSR4 - Transmit list base address */\r
-+#define DmaStatus       0x14 /* CSR5 - Dma status */\r
-+#define DmaControl      0x18 /* CSR6 - Dma control */\r
-+#define DmaIntrEnb      0x1C /* CSR7 - Interrupt enable */\r
-+#define DmaOverflowCnt  0x20 /* CSR8 - Missed Frame and Buff Overflow counter */\r
-+#define DmaTxCurrAddr   0x50 /* CSR20 - Current host transmit buffer address */\r
-+#define DmaRxCurrAddr   0x54 /* CSR21 - Current host receive buffer address */\r
-+\r
-+/**********************************************************/\r
-+/* MAC Control register layout                            */\r
-+/**********************************************************/\r
-+#define MacFilterOff           0x80000000 /* Receive all incoming packets RW */\r
-+#define MacFilterOn                     0 /* Receive filtered packets only 0 */\r
-+#define MacBigEndian           0x40000000 /* Big endian mode RW */\r
-+#define MacLittleEndian                 0 /* Little endian 0 */\r
-+#define MacHeartBeatOff        0x10000000 /* Heartbeat signal qual disable RW*/\r
-+#define MacHeartBeatOn                  0 /* Heartbeat signal qual enable 0 */\r
-+#define MacSelectSrl           0x08000000 /* Select SRL port RW */\r
-+#define MacSelectMii                    0 /* Select MII port 0 */\r
-+#define MacDisableRxOwn        0x00800000 /* Disable receive own packets RW */\r
-+#define MacEnableRxOwn                  0 /* Enable receive own packets 0 */\r
-+#define MacLoopbackExt         0x00400000 /* External loopback RW */\r
-+#define MacLoopbackInt         0x00200000 /* Internal loopback */\r
-+#define MacLoopbackOff                  0 /* Normal mode 00 */\r
-+#define MacFullDuplex          0x00100000 /* Full duplex mode RW */\r
-+#define MacHalfDuplex                   0 /* Half duplex mode 0 */\r
-+#define MacMulticastFilterOff  0x00080000 /* Pass all multicast packets RW */\r
-+#define MacMulticastFilterOn            0 /* Pass filtered mcast packets 0 */\r
-+#define MacPromiscuousModeOn   0x00040000 /* Receive all valid packets RW 1 */\r
-+#define MacPromiscuousModeOff           0 /* Receive filtered packets only */\r
-+#define MacFilterInverse       0x00020000 /* Inverse filtering RW */\r
-+#define MacFilterNormal                 0 /* Normal filtering 0 */\r
-+#define MacBadFramesEnable     0x00010000 /* Pass bad frames RW */\r
-+#define MacBadFramesDisable             0 /* Do not pass bad frames 0 */\r
-+#define MacPerfectFilterOff    0x00008000 /* Hash filtering only RW */\r
-+#define MacPerfectFilterOn              0 /* Both perfect and hash filtering 0 */\r
-+#define MacHashFilterOn        0x00002000 /* perform hash filtering RW */\r
-+#define MacHashFilterOff                0 /* perfect filtering only 0 */\r
-+#define MacLateCollisionOn     0x00001000 /* Enable late collision control RW */\r
-+#define MacLateCollisionOff             0 /* Disable late collision control 0 */\r
-+#define MacBroadcastDisable    0x00000800 /* Disable reception of bcast frames RW */\r
-+#define MacBroadcastEnable              0 /* Enable broadcast frames 0 */\r
-+#define MacRetryDisable        0x00000400 /* Disable retransmission RW */\r
-+#define MacRetryEnable                  0 /* Enable retransmission 0 */\r
-+#define MacPadStripEnable      0x00000100 /* Pad stripping enable RW */\r
-+#define MacPadStripDisable              0 /* Pad stripping disable 0 */\r
-+#define MacBackoff                      0 /* Backoff Limit RW 00 */\r
-+#define MacDeferralCheckEnable 0x00000020 /* Deferral check enable RW */\r
-+#define MacDeferralCheckDisable         0 /* Deferral check disable 0 */\r
-+#define MacTxEnable            0x00000008 /* Transmitter enable RW */\r
-+#define MacTxDisable                    0 /* Transmitter disable 0 */\r
-+#define MacRxEnable            0x00000004 /* Receiver enable RW */\r
-+#define MacRxDisable                    0 /* Receiver disable 0 */\r
-+\r
-+\r
-+/**********************************************************/\r
-+/* MII address register layout                            */\r
-+/**********************************************************/\r
-+#define MiiDevMask   0x0000F800 /* MII device address */\r
-+#define MiiDevShift          11\r
-+#define MiiRegMask   0x000007C0 /* MII register */\r
-+#define MiiRegShift           6\r
-+#define MiiWrite     0x00000002 /* Write to register */\r
-+#define MiiRead               0 /* Read from register */\r
-+#define MiiBusy      0x00000001 /* MII interface is busy */\r
-+\r
-+/**********************************************************/\r
-+/* MII Data register layout                               */\r
-+/**********************************************************/\r
-+#define MiiDataMask  0x0000FFFF /* MII Data */\r
-+\r
-+/**********************************************************/\r
-+/* MAC flow control register layout                       */\r
-+/**********************************************************/\r
-+#define MacPauseTimeMask      0xFFFF0000  /* PAUSE TIME field in ctrl frame */\r
-+#define MacPauseTimeShift             15\r
-+#define MacControlFrameEnable 0x00000004  /* Enable pass ctrl frames to host */\r
-+#define MacControlFrameDisable         0  /* Do not pass ctrl frames to host */\r
-+#define MacFlowControlEnable  0x00000002  /* Enable flow control */\r
-+#define MacFlowControlDisable          0  /* Disable flow control */\r
-+#define MacSendPauseFrame     0x00000001  /* send pause frame */\r
-+\r
-+/**********************************************************/\r
-+/* DMA bus mode register layout                           */\r
-+/**********************************************************/\r
-+#define DmaRxAlign16            0x01000000 /* Force all rx buffers to align on odd hw bndry */\r
-+#define DmaBigEndianDes         0x00100000 /* Big endian data buffer descriptors RW */\r
-+#define DmaLittleEndianDesc              0 /* Little endian data descriptors */\r
-+#define DmaBurstLength32        0x00002000 /* Dma burst length 32 RW */\r
-+#define DmaBurstLength16        0x00001000 /* Dma burst length 16 */\r
-+#define DmaBurstLength8         0x00000800 /* Dma burst length 8 */\r
-+#define DmaBurstLength4         0x00000400 /* Dma burst length 4 */\r
-+#define DmaBurstLength2         0x00000200 /* Dma burst length 2 */\r
-+#define DmaBurstLength1         0x00000100 /* Dma burst length 1 */\r
-+#define DmaBurstLength0         0x00000000 /* Dma burst length 0 */\r
-+#define DmaBigEndianData        0x00000080 /* Big endian data buffers RW */\r
-+#define DmaLittleEndianData              0 /* Little endian data buffers 0 */\r
-+#define DmaDescriptorSkip16     0x00000040 /* number of dwords to skip RW */\r
-+#define DmaDescriptorSkip8      0x00000020 /* between two unchained descriptors */\r
-+#define DmaDescriptorSkip4      0x00000010\r
-+#define DmaDescriptorSkip2      0x00000008\r
-+#define DmaDescriptorSkip1      0x00000004\r
-+#define DmaDescriptorSkip0               0\r
-+#define DmaReceivePriorityOff   0x00000002 /* equal rx and tx priorities RW */\r
-+#define DmaReceivePriorityOn             0 /* Rx has prioryty over Tx 0 */\r
-+#define DmaResetOn              0x00000001 /* Reset DMA engine RW */\r
-+#define DmaResetOff                      0\r
-+\r
-+/**********************************************************/\r
-+/* DMA Status register layout                             */\r
-+/**********************************************************/\r
-+#define DmaRxAbort        0x01000000 /* receiver bus abort R 0 */\r
-+#define DmaTxAbort        0x00800000 /* transmitter bus abort R 0 */\r
-+#define DmaTxState        0x00700000 /* Transmit process state R 000 */\r
-+#define DmaTxStopped      0x00000000 /* Stopped */\r
-+#define DmaTxFetching     0x00100000 /* Running - fetching the descriptor */\r
-+#define DmaTxWaiting      0x00200000 /* Running - waiting for end of transmission */\r
-+#define DmaTxReading      0x00300000 /* Running - reading the data from memory */\r
-+#define DmaTxSuspended    0x00600000 /* Suspended */\r
-+#define DmaTxClosing      0x00700000 /* Running - closing descriptor */\r
-+#define DmaRxState        0x000E0000 /* Receive process state 000 */\r
-+#define DmaRxStopped      0x00000000 /* Stopped */\r
-+#define DmaRxFetching     0x00020000 /* Running - fetching the descriptor */\r
-+#define DmaRxChecking     0x00040000 /* Running - checking for end of packet */\r
-+#define DmaRxWaiting      0x00060000 /* Running - waiting for packet */\r
-+#define DmaRxSuspended    0x00080000 /* Suspended */\r
-+#define DmaRxClosing      0x000A0000 /* Running - closing descriptor */\r
-+#define DmaRxFlushing     0x000C0000 /* Running - flushing the current frame */\r
-+#define DmaRxQueuing      0x000E0000 /* Running - queuing the recieve frame into host memory */\r
-+#define DmaIntNormal      0x00010000 /* Normal interrupt summary RW 0 */\r
-+#define DmaIntAbnormal    0x00008000 /* Abnormal interrupt summary RW 0 */\r
-+#define DmaIntEarlyRx     0x00004000 /* Early receive interrupt (Normal) RW 0 */\r
-+#define DmaIntBusError    0x00002000 /* Fatal bus error (Abnormal) RW 0 */\r
-+#define DmaIntEarlyTx     0x00000400 /* Early transmit interrupt RW 0 */\r
-+#define DmaIntRxStopped   0x00000100 /* Receive process stopped (Abnormal) RW 0 */\r
-+#define DmaIntRxNoBuffer  0x00000080 /* Receive buffer unavailable (Abnormal) RW 0*/\r
-+#define DmaIntRxCompleted 0x00000040 /* Completion of frame reception(Normal) RW 0*/\r
-+#define DmaIntTxUnderflow 0x00000020 /* Transmit underflow (Abnormal) RW 0 */\r
-+#define DmaIntTxJabber    0x00000008 /* Transmit Jabber Timeout (Abnormal) RW 0 */ \r
-+#define DmaIntTxNoBuffer  0x00000004 /* Transmit buffer unavailable (Normal) RW 0*/\r
-+#define DmaIntTxStopped   0x00000002 /* Transmit process stopped (Abnormal) RW 0 */\r
-+#define DmaIntTxCompleted 0x00000001 /* Transmit completed (Normal) RW 0 */\r
-+\r
-+/**********************************************************/\r
-+/* DMA control register layout                            */\r
-+/**********************************************************/\r
-+#define DmaStoreAndForward 0x00200000 /* Store and forward RW 0 */\r
-+#define DmaTxThreshCtl256  0x0000c000 /* Non-SF threshold is 256 words */\r
-+#define DmaTxThreshCtl128  0x00008000 /* Non-SF threshold is 128 words */\r
-+#define DmaTxThreshCtl064  0x00004000 /* Non-SF threshold is 64 words */\r
-+#define DmaTxThreshCtl032  0x00000000 /* Non-SF threshold is 32 words */\r
-+#define DmaTxStart         0x00002000 /* Start/Stop transmission RW 0 */\r
-+#define DmaTxSecondFrame   0x00000004 /* Operate on second frame RW 0 */\r
-+#define DmaRxStart         0x00000002 /* Start/Stop reception RW 0 */\r
-+\r
-+/**********************************************************/\r
-+/* DMA interrupt enable register layout                   */\r
-+/**********************************************************/\r
-+#define DmaIeNormal      DmaIntNormal      /* Normal interrupt enable RW 0 */\r
-+#define DmaIeAbnormal    DmaIntAbnormal    /* Abnormal interrupt enable RW 0 */\r
-+#define DmaIeEarlyRx     DmaIntEarlyRx     /* Early receive interrupt enable RW 0 */\r
-+#define DmaIeBusError    DmaIntBusError    /* Fatal bus error enable RW 0 */\r
-+#define DmaIeEarlyTx     DmaIntEarlyTx     /* Early transmit interrupt enable RW 0 */\r
-+#define DmaIeRxStopped   DmaIntRxStopped   /* Receive process stopped enable RW 0 */\r
-+#define DmaIeRxNoBuffer  DmaIntRxNoBuffer  /* Receive buffer unavailable enable RW 0 */\r
-+#define DmaIeRxCompleted DmaIntRxCompleted /* Completion of frame reception enable RW 0 */\r
-+#define DmaIeTxUnderflow DmaIntTxUnderflow /* Transmit underflow enable RW 0 */\r
-+#define DmaIeTxJabber    DmaIntTxJabber    /* Transmit jabber timeout RW 0 */\r
-+#define DmaIeTxNoBuffer  DmaIntTxNoBuffer  /* Transmit buffer unavailable enable RW 0 */\r
-+#define DmaIeTxStopped   DmaIntTxStopped   /* Transmit process stopped enable RW 0 */\r
-+#define DmaIeTxCompleted DmaIntTxCompleted /* Transmit completed enable RW 0 */\r
-+\r
-+/****************************************************************/\r
-+/* DMA Missed Frame and Buffer Overflow Counter register layout */\r
-+/****************************************************************/\r
-+#define DmaRxBufferMissedFrame  0xffff0000  /* cleared on read */\r
-+#define DmaMissedFrameShift             16\r
-+#define DmaRxBufferOverflowCnt  0x0000ffff  /* cleared on read */\r
-+#define DmaMissedFrameCountMask 0x0000ffff\r
-+\r
-+/**********************************************************/\r
-+/* DMA Engine descriptor layout                           */\r
-+/**********************************************************/\r
-+/* status word of DMA descriptor */\r
-+#define DescOwnByDma         0x80000000 /* Descriptor is owned by DMA engine */\r
-+#define DescFrameLengthMask  0x3FFF0000 /* Receive descriptor frame length */\r
-+#define DescFrameLengthShift         16\r
-+#define DescError            0x00008000 /* Error summary bit OR of following bits */\r
-+#define DescRxTruncated      0x00004000 /* Rx - no more descs for receive frame */\r
-+#define DescRxLengthError    0x00001000 /* Rx - frame size not matching with length field */\r
-+#define DescRxRunt           0x00000800 /* Rx - runt frame, damaged by a\r
-+                                           collision or term before 64 bytes */\r
-+#define DescRxMulticast      0x00000400 /* Rx - received frame is multicast */\r
-+#define DescRxFirst          0x00000200 /* Rx - first descriptor of the frame */\r
-+#define DescRxLast           0x00000100 /* Rx - last descriptor of the frame */\r
-+#define DescRxLongFrame      0x00000080 /* Rx - frame is longer than 1518 bytes */\r
-+#define DescRxLateColl       0x00000040 /* Rx - frame was damaged by a late collision */\r
-+#define DescRxFrameEther     0x00000020 /* Rx - Frame type Ethernet 802.3*/ \r
-+#define DescRxMiiError       0x00000008 /* Rx - error reported by MII interface */\r
-+#define DescRxDribbling      0x00000004 /* Rx - frame contains noninteger multiple of 8 bits */\r
-+#define DescRxCrc            0x00000002 /* Rx - CRC error */\r
-+#define DescTxTimeout        0x00004000 /* Tx - Transmit jabber timeout */\r
-+#define DescTxLostCarrier    0x00000800 /* Tx - carrier lost during tramsmission */\r
-+#define DescTxNoCarrier      0x00000400 /* Tx - no carrier signal from tranceiver */\r
-+#define DescTxLateCollision  0x00000200 /* Tx - transmission aborted due to collision */\r
-+#define DescTxExcCollisions  0x00000100 /* Tx - transmission aborted after 16 collisions */\r
-+#define DescTxHeartbeatFail  0x00000080 /* Tx - heartbeat collision check failure */\r
-+#define DescTxCollMask       0x00000078 /* Tx - Collision count */\r
-+#define DescTxCollShift               3\r
-+#define DescTxExcDeferral    0x00000004 /* Tx - excessive deferral */\r
-+#define DescTxUnderflow      0x00000002 /* Tx - late data arrival from memory */\r
-+#define DescTxDeferred       0x00000001 /* Tx - frame transmision deferred */\r
-+\r
-+/* length word of DMA descriptor */\r
-+#define DescTxIntEnable      0x80000000 /* Tx - interrupt on completion */\r
-+#define DescTxLast           0x40000000 /* Tx - Last segment of the frame */\r
-+#define DescTxFirst          0x20000000 /* Tx - First segment of the frame */\r
-+#define DescTxDisableCrc     0x04000000 /* Tx - Add CRC disabled (first segment only) */\r
-+#define DescEndOfRing        0x02000000 /* End of descriptors ring */\r
-+#define DescChain            0x01000000 /* Second buffer address is chain address */\r
-+#define DescTxDisablePadd    0x00800000 /* disable padding */\r
-+#define DescSize2Mask        0x003FF800 /* Buffer 2 size */\r
-+#define DescSize2Shift               11\r
-+#define DescSize1Mask        0x000007FF /* Buffer 1 size */\r
-+#define DescSize1Shift                0\r
-+\r
-+/**********************************************************/\r
-+/* Initial register values                                */\r
-+/**********************************************************/\r
-+/* Full-duplex mode with perfect filter on */\r
-+#define MacControlInitFdx \\r
-+       ( MacFilterOn \\r
-+       | MacLittleEndian \\r
-+       | MacHeartBeatOn \\r
-+       | MacSelectMii \\r
-+       | MacEnableRxOwn \\r
-+       | MacLoopbackOff \\r
-+       | MacFullDuplex \\r
-+       | MacMulticastFilterOn \\r
-+       | MacPromiscuousModeOff \\r
-+       | MacFilterNormal \\r
-+       | MacBadFramesDisable \\r
-+       | MacPerfectFilterOn \\r
-+       | MacHashFilterOff \\r
-+       | MacLateCollisionOff \\r
-+       | MacBroadcastEnable \\r
-+       | MacRetryEnable \\r
-+       | MacPadStripDisable \\r
-+       | MacDeferralCheckDisable \\r
-+       | MacTxEnable \\r
-+       | MacRxEnable)\r
-+\r
-+/* Full-duplex mode */\r
-+#define MacFlowControlInitFdx \\r
-+        ( MacControlFrameDisable \\r
-+        | MacFlowControlEnable)\r
-+\r
-+/* Half-duplex mode with perfect filter on */\r
-+#define MacControlInitHdx \\r
-+       ( MacFilterOn \\r
-+       | MacLittleEndian \\r
-+       | MacHeartBeatOn \\r
-+       | MacSelectMii \\r
-+       | MacDisableRxOwn \\r
-+       | MacLoopbackOff \\r
-+       | MacHalfDuplex \\r
-+       | MacMulticastFilterOn \\r
-+       | MacPromiscuousModeOff \\r
-+       | MacFilterNormal \\r
-+       | MacBadFramesDisable \\r
-+       | MacPerfectFilterOn \\r
-+       | MacHashFilterOff \\r
-+       | MacLateCollisionOff \\r
-+       | MacBroadcastEnable \\r
-+       | MacRetryEnable \\r
-+       | MacPadStripDisable \\r
-+       | MacDeferralCheckDisable \\r
-+       | MacTxEnable \\r
-+       | MacRxEnable)\r
-+\r
-+/* Half-duplex mode */\r
-+#define MacFlowControlInitHdx \\r
-+        ( MacControlFrameDisable \\r
-+        | MacFlowControlDisable)\r
-+\r
-+/* Bus Mode Rx odd half word align */\r
-+#define DmaBusModeInit  \\r
-+       ( DmaLittleEndianDesc \\r
-+       | DmaRxAlign16 \\r
-+       | DmaBurstLength4 \\r
-+       | DmaBigEndianData \\r
-+       | DmaDescriptorSkip1 \\r
-+       | DmaReceivePriorityOn \\r
-+       | DmaResetOff)\r
-+\r
-+#define DmaControlInit (DmaStoreAndForward)\r
-+\r
-+/* Interrupt groups */\r
-+#define DmaIntEnable \\r
-+     ( DmaIeNormal \\r
-+     | DmaIeAbnormal \\r
-+     | DmaIntBusError \\r
-+     | DmaIntRxStopped \\r
-+     | DmaIntTxUnderflow \\r
-+     | DmaIntTxStopped)\r
-+\r
-+#define DmaIntDisable 0\r
-+\r
-+#define DmaAllIntCauseMask \\r
-+      ( DmaIeNormal  \\r
-+      | DmaIeAbnormal  \\r
-+      | DmaIntEarlyRx  \\r
-+      | DmaIntBusError \\r
-+      | DmaIntEarlyTx  \\r
-+      | DmaIntRxStopped \\r
-+      | DmaIntRxNoBuffer \\r
-+      | DmaIntRxCompleted \\r
-+      | DmaIntTxUnderflow \\r
-+      | DmaIntTxJabber \\r
-+      | DmaIntTxNoBuffer \\r
-+      | DmaIntTxStopped \\r
-+      | DmaIntTxCompleted)\r
-+\r
-+#define UnhandledIntrMask    \\r
-+       (DmaAllIntCauseMask   \\r
-+       & ~(DmaIntRxNoBuffer  \\r
-+         | DmaIntTxStopped   \\r
-+         | DmaIntTxJabber    \\r
-+         | DmaIntTxUnderflow \\r
-+         | DmaIntBusError    \\r
-+         | DmaIntRxCompleted ))\r
-+\r
-+#define DescRxErrors    \\r
-+      (DescRxTruncated  \\r
-+     | DescRxRunt       \\r
-+     | DescRxLateColl   \\r
-+     | DescRxMiiError   \\r
-+     | DescRxCrc)\r
-+\r
-+#define DescTxErrors        \\r
-+     ( DescTxTimeout        \\r
-+     | DescTxLateCollision  \\r
-+     | DescTxExcCollisions  \\r
-+     | DescTxExcDeferral    \\r
-+     | DescTxUnderflow)\r
-+\r
-+/**********************************************************/\r
-+/* Descriptor Layout                                      */\r
-+/**********************************************************/\r
-+#define AE531X_DESC_STATUS     0x00 /* Status offset */\r
-+#define AE531X_DESC_CTRLEN     0x04 /* Control and Length offset */ \r
-+#define AE531X_DESC_BUFPTR     0x08 /* Buffer pointer offset */\r
-+#define AE531X_DESC_LNKBUF     0x0c /* Link field offset, or ptr to 2nd buf */\r
-+#define AE531X_DESC_SWPTR      0x10 /* OS-Dependent software pointer */\r
-+\r
-+#define AE531X_DESC_SIZE       0x10 /* 4 words, 16 bytes */\r
-+#define AE531X_QUEUE_ELE_SIZE  0x14 /* with software pointer extension */\r
-+\r
-+/* Accessors to the dma descriptor fields */\r
-+#define AE531X_DESC_STATUS_GET(ptr) \\r
-+    *(volatile UINT32 *)((UINT32)(ptr) + AE531X_DESC_STATUS)\r
-+\r
-+#define AE531X_DESC_STATUS_SET(ptr, val)  \\r
-+    AE531X_DESC_STATUS_GET(ptr) = (val)\r
-+\r
-+#define AE531X_DESC_CTRLEN_GET(ptr) \\r
-+    *(volatile UINT32 *)((UINT32)ptr + AE531X_DESC_CTRLEN)\r
-+\r
-+#define AE531X_DESC_CTRLEN_SET(ptr, val)  \\r
-+    AE531X_DESC_CTRLEN_GET(ptr) = (val)\r
-+\r
-+#define AE531X_DESC_BUFPTR_GET(ptr) \\r
-+    *(volatile UINT32 *)((UINT32)ptr + AE531X_DESC_BUFPTR)\r
-+\r
-+#define AE531X_DESC_BUFPTR_SET(ptr,val)  \\r
-+    AE531X_DESC_BUFPTR_GET(ptr) = (UINT32)(val)\r
-+\r
-+#define AE531X_DESC_LNKBUF_GET(ptr)  \\r
-+    *(volatile UINT32 *)((UINT32)ptr + AE531X_DESC_LNKBUF)\r
-+\r
-+#define AE531X_DESC_LNKBUF_SET(ptr, val)  \\r
-+    AE531X_DESC_LNKBUF_GET(ptr) = (val)\r
-+\r
-+#define AE531X_DESC_SWPTR_GET(ptr) \\r
-+    (void *)(*(volatile UINT32 *) ((UINT32)ptr + AE531X_DESC_SWPTR))\r
-+\r
-+#define AE531X_DESC_SWPTR_SET(ptr,val)   \\r
-+    AE531X_DESC_SWPTR_GET(ptr) = (void *)(val)\r
-+\r
-+/* Get size of Rx data from desc, in bytes */\r
-+#define AE531X_DESC_STATUS_RX_SIZE(x) \\r
-+        (((x) & DescFrameLengthMask) >> DescFrameLengthShift)\r
-+\r
-+#endif /* _AE531XREG_H_ */\r
-diff -urN linux-2.4.32.new/arch/mips/ar531x/Makefile linux-2.4.32.new-eth/arch/mips/ar531x/Makefile\r
---- linux-2.4.32.new/arch/mips/ar531x/Makefile 2005-12-24 20:29:42.010325312 +0000\r
-+++ linux-2.4.32.new-eth/arch/mips/ar531x/Makefile     2005-12-25 12:03:16.213872024 +0000\r
-@@ -28,6 +28,13 @@\r
-       ar531xirq.o     \\r
-       ar531xintr.o    \\r
-       ar531xgpio.o    \\r
--      ar531xksyms.o\r
-+      ar531xksyms.o   \\r
-+       ae531xlnx.o     \\r
-+       ae531xmac.o\r
\r
- include $(TOPDIR)/Rules.make\r
-+obj-$(CONFIG_MARVELL_ENET_PHY)  += mvPhy.o\r
-+obj-$(CONFIG_KENDIN_ENET_PHY))  += rtPhy.o\r
-+obj-$(CONFIG_REALTEK_ENET_PHY)  += rtPhy.o\r
-+\r
-+\r
-diff -urN linux-2.4.32.new/arch/mips/ar531x/mvPhy.c linux-2.4.32.new-eth/arch/mips/ar531x/mvPhy.c\r
---- linux-2.4.32.new/arch/mips/ar531x/mvPhy.c  1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new-eth/arch/mips/ar531x/mvPhy.c      2005-12-25 11:54:39.730389448 +0000\r
-@@ -0,0 +1,1237 @@\r
-+/*\r
-+ * This file is subject to the terms and conditions of the GNU General Public\r
-+ * License.  See the file "COPYING" in the main directory of this archive\r
-+ * for more details.\r
-+ *\r
-+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.\r
-+ */\r
-+\r
-+/*\r
-+* Manage the ethernet PHY switch, Marvell 88E6060.\r
-+* \r
-+* This module is intended to be largely OS and platform-independent.\r
-+*/\r
-+\r
-+#if defined(linux)\r
-+#include <linux/config.h>\r
-+#include <linux/types.h>\r
-+#include <linux/netdevice.h>\r
-+#include <linux/etherdevice.h>\r
-+#include <linux/delay.h>\r
-+\r
-+#include "ar531xlnx.h"\r
-+#endif\r
-+\r
-+#if defined(__ECOS)\r
-+#include "ae531xecos.h"\r
-+#endif\r
-+\r
-+\r
-+#include "ae531xmac.h"\r
-+#include "ae531xreg.h"\r
-+#include "mvPhy.h"\r
-+\r
-+#if /* DEBUG */ 1\r
-+#define MV_DEBUG_ERROR     0x00000001\r
-+#define MV_DEBUG_PHYSETUP  0x00000002\r
-+#define MV_DEBUG_PHYCHANGE 0x00000004\r
-+\r
-+int mvPhyDebug = MV_DEBUG_ERROR;\r
-+\r
-+#define MV_PRINT(FLG, X)                            \\r
-+{                                                   \\r
-+    if (mvPhyDebug & (FLG)) {                       \\r
-+        DEBUG_PRINTF X;                             \\r
-+    }                                               \\r
-+}\r
-+#else\r
-+#define MV_PRINT(FLG, X)\r
-+#endif\r
-+\r
-+#ifdef CONFIG_VENETDEV\r
-+/*\r
-+ * On AR5312 with CONFIG_VENETDEV==1,\r
-+ *   ports 0..3 are LAN ports  (accessed through ae0)\r
-+ *   port 4 is the WAN port.   (accessed through ae1)\r
-+ * \r
-+ * The phy switch settings in the mvPhyInfo table are set accordingly.\r
-+ */\r
-+#define MV_WAN_PORT          4\r
-+#define MV_IS_LAN_PORT(port) ((port) <  MV_WAN_PORT)\r
-+#define MV_IS_WAN_PORT(port) ((port) == MV_WAN_PORT)\r
-+#endif\r
-+\r
-+/*\r
-+ * Track per-PHY port information.\r
-+ */\r
-+typedef struct {\r
-+    BOOL   isEnetPort;       /* normal enet port */\r
-+    BOOL   isPhyAlive;       /* last known state of link */\r
-+    int    ethUnit;          /* MAC associated with this phy port */\r
-+    UINT32 phyBase;\r
-+    UINT32 phyAddr;          /* PHY registers associated with this phy port */\r
-+    UINT32 switchPortAddr;   /* switch port regs assoc'ed with this phy port */\r
-+    UINT32 VLANTableSetting; /* Value to be written to VLAN table */\r
-+} mvPhyInfo_t;\r
-+\r
-+/******************************************************************************\r
-+ * Per-PHY information, indexed by PHY unit number.\r
-+ *\r
-+ * This table is board-dependent.  It includes information\r
-+ * about which enet MAC controls which PHY port.\r
-+ */\r
-+mvPhyInfo_t mvPhyInfo[] = {\r
-+    /*\r
-+     * On AP30/AR5312, all PHYs are associated with MAC0.\r
-+     * AP30/AR5312's MAC1 isn't used for anything.\r
-+     * CONFIG_VENETDEV==1 (router) configuration:\r
-+     *    Ports 0,1,2, and 3 are "LAN ports"\r
-+     *    Port 4 is a WAN port\r
-+     *    Port 5 connects to MAC0 in the AR5312\r
-+     * CONFIG_VENETDEV==0 (bridge) configuration:\r
-+     *    Ports 0,1,2,3,4 are "LAN ports"\r
-+     *    Port 5 connects to the MAC0 in the AR5312\r
-+     */\r
-+    {isEnetPort: TRUE,   /* phy port 0 -- LAN port 0 */\r
-+     isPhyAlive: FALSE,\r
-+     ethUnit: 0,\r
-+     phyBase: 0,\r
-+     phyAddr: 0x10,\r
-+     switchPortAddr: 0x18,\r
-+#ifdef CONFIG_VENETDEV\r
-+     VLANTableSetting: 0x2e\r
-+#else\r
-+     VLANTableSetting: 0x3e\r
-+#endif\r
-+    },\r
-+\r
-+    {isEnetPort: TRUE,   /* phy port 1 -- LAN port 1 */\r
-+     isPhyAlive: FALSE,\r
-+     ethUnit: 0,\r
-+     phyBase: 0,\r
-+     phyAddr: 0x11,\r
-+     switchPortAddr: 0x19,\r
-+#ifdef CONFIG_VENETDEV\r
-+     VLANTableSetting: 0x2d\r
-+#else\r
-+     VLANTableSetting: 0x3d\r
-+#endif\r
-+    },\r
-+\r
-+    {isEnetPort: TRUE,   /* phy port 2 -- LAN port 2 */\r
-+     isPhyAlive: FALSE,\r
-+     ethUnit: 0,\r
-+     phyBase: 0,\r
-+     phyAddr: 0x12, \r
-+     switchPortAddr: 0x1a,\r
-+#ifdef CONFIG_VENETDEV\r
-+     VLANTableSetting: 0x2b\r
-+#else\r
-+     VLANTableSetting: 0x3b\r
-+#endif\r
-+    },\r
-+\r
-+    {isEnetPort: TRUE,   /* phy port 3 -- LAN port 3 */\r
-+     isPhyAlive: FALSE,\r
-+     ethUnit: 0,\r
-+     phyBase: 0,\r
-+     phyAddr: 0x13, \r
-+     switchPortAddr: 0x1b,\r
-+#ifdef CONFIG_VENETDEV\r
-+     VLANTableSetting: 0x27\r
-+#else\r
-+     VLANTableSetting: 0x37\r
-+#endif\r
-+    },\r
-+\r
-+    {isEnetPort: TRUE,   /* phy port 4 -- WAN port or LAN port 4 */\r
-+     isPhyAlive: FALSE,\r
-+     ethUnit: 0,\r
-+     phyBase: 0,\r
-+     phyAddr: 0x14, \r
-+     switchPortAddr: 0x1c,\r
-+#ifdef CONFIG_VENETDEV\r
-+     VLANTableSetting: 0x1020  /* WAN port */\r
-+#else\r
-+     VLANTableSetting: 0x2f    /* LAN port 4 */\r
-+#endif\r
-+    },\r
-+\r
-+    {isEnetPort: FALSE,  /* phy port 5 -- CPU port (no RJ45 connector) */\r
-+     isPhyAlive: TRUE,\r
-+     ethUnit: 0,\r
-+     phyBase: 0,\r
-+     phyAddr: 0x15, \r
-+     switchPortAddr: 0x1d,\r
-+#ifdef CONFIG_VENETDEV\r
-+     VLANTableSetting: 0x0f    /* Send only to LAN ports */\r
-+#else\r
-+     VLANTableSetting: 0x1f    /* Send to all ports */\r
-+#endif\r
-+    },\r
-+};\r
-+\r
-+#define MV_PHY_MAX (sizeof(mvPhyInfo) / sizeof(mvPhyInfo[0]))\r
-+\r
-+/* Range of valid PHY IDs is [MIN..MAX] */\r
-+#define MV_ID_MIN 0\r
-+#define MV_ID_MAX (MV_PHY_MAX-1)\r
-+\r
-+/* Convenience macros to access myPhyInfo */\r
-+#define MV_IS_ENET_PORT(phyUnit) (mvPhyInfo[phyUnit].isEnetPort)\r
-+#define MV_IS_PHY_ALIVE(phyUnit) (mvPhyInfo[phyUnit].isPhyAlive)\r
-+#define MV_ETHUNIT(phyUnit) (mvPhyInfo[phyUnit].ethUnit)\r
-+#define MV_PHYBASE(phyUnit) (mvPhyInfo[phyUnit].phyBase)\r
-+#define MV_PHYADDR(phyUnit) (mvPhyInfo[phyUnit].phyAddr)\r
-+#define MV_SWITCH_PORT_ADDR(phyUnit) (mvPhyInfo[phyUnit].switchPortAddr)\r
-+#define MV_VLAN_TABLE_SETTING(phyUnit) (mvPhyInfo[phyUnit].VLANTableSetting)\r
-+\r
-+#define MV_IS_ETHUNIT(phyUnit, ethUnit) \\r
-+    (MV_IS_ENET_PORT(phyUnit) &&        \\r
-+    MV_ETHUNIT(phyUnit) == (ethUnit))\r
-+\r
-+\r
-+/* Forward references */\r
-+BOOL       mv_phyIsLinkAlive(int phyUnit);\r
-+LOCAL void mv_VLANInit(int ethUnit);\r
-+LOCAL void mv_enableConfiguredPorts(int ethUnit);\r
-+LOCAL void mv_verifyReady(int ethUnit);\r
-+BOOL       mv_phySetup(int ethUnit, UINT32 phyBase);\r
-+BOOL       mv_phyIsFullDuplex(int ethUnit);\r
-+BOOL       mv_phyIsSpeed100(int phyUnit);\r
-+LOCAL BOOL mv_validPhyId(int phyUnit);\r
-+void       mv_flushATUDB(int phyUnit);\r
-+void       mv_phyCheckStatusChange(int ethUnit);\r
-+#if DEBUG\r
-+void       mv_phyShow(int phyUnit);\r
-+void       mv_phySet(int phyUnit, UINT32 regnum, UINT32 value);\r
-+void       mv_switchPortSet(int phyUnit, UINT32 regnum, UINT32 value);\r
-+void       mv_switchGlobalSet(int phyUnit, UINT32 regnum, UINT32 value);\r
-+void       mv_showATUDB(int phyUnit);\r
-+void       mv_countGoodFrames(int phyUnit);\r
-+void       mv_countBadFrames(int phyUnit);\r
-+void       mv_showFrameCounts(int phyUnit);\r
-+#endif\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* mv_phyIsLinkAlive - test to see if the specified link is alive\r
-+*\r
-+* RETURNS:\r
-+*    TRUE  --> link is alive\r
-+*    FALSE --> link is down\r
-+*/\r
-+BOOL\r
-+mv_phyIsLinkAlive(int phyUnit)\r
-+{\r
-+    UINT16 phyHwStatus;\r
-+    UINT32 phyBase;\r
-+    UINT32 phyAddr;\r
-+\r
-+    phyBase = MV_PHYBASE(phyUnit);\r
-+    phyAddr = MV_PHYADDR(phyUnit);\r
-+\r
-+    phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);\r
-+\r
-+    if (phyHwStatus & MV_STATUS_REAL_TIME_LINK_UP) {\r
-+        return TRUE;\r
-+    } else {\r
-+        return FALSE;\r
-+    }\r
-+}\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* mv_VLANInit - initialize "port-based VLANs" for the specified enet unit.\r
-+*/\r
-+LOCAL void\r
-+mv_VLANInit(int ethUnit)\r
-+{\r
-+    int     phyUnit;\r
-+    UINT32  phyBase;\r
-+    UINT32  switchPortAddr;\r
-+\r
-+    for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {\r
-+        if (MV_ETHUNIT(phyUnit) != ethUnit) {\r
-+            continue;\r
-+        }\r
-+\r
-+        phyBase        = MV_PHYBASE(phyUnit);\r
-+        switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);\r
-+\r
-+        phyRegWrite(phyBase, switchPortAddr, MV_PORT_BASED_VLAN_MAP,\r
-+                    MV_VLAN_TABLE_SETTING(phyUnit));\r
-+    }\r
-+}\r
-+\r
-+#define phyPortConfigured(phyUnit) TRUE /* TBDFREEDOM2 */\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* mv_enableConfiguredPorts - enable whichever PHY ports are supposed\r
-+* to be enabled according to administrative configuration.\r
-+*/\r
-+LOCAL void\r
-+mv_enableConfiguredPorts(int ethUnit)\r
-+{\r
-+    int     phyUnit;\r
-+    UINT32  phyBase;\r
-+    UINT32  switchPortAddr;\r
-+    UINT16  portControl;\r
-+    UINT16  portAssociationVector;\r
-+\r
-+    for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {\r
-+        if (MV_ETHUNIT(phyUnit) != ethUnit) {\r
-+            continue;\r
-+        }\r
-+\r
-+        phyBase        = MV_PHYBASE(phyUnit);\r
-+        switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);\r
-+\r
-+        if (phyPortConfigured(phyUnit)) {\r
-+\r
-+            portControl = MV_PORT_CONTROL_PORT_STATE_FORWARDING;\r
-+#ifdef CONFIG_VENETDEV\r
-+            if (!MV_IS_ENET_PORT(phyUnit)) {       /* CPU port */\r
-+                portControl |= MV_PORT_CONTROL_INGRESS_TRAILER\r
-+                            | MV_PORT_CONTROL_EGRESS_MODE;\r
-+            }\r
-+#endif\r
-+            phyRegWrite(phyBase, switchPortAddr, MV_PORT_CONTROL, portControl);\r
-+\r
-+            if (MV_IS_ENET_PORT(phyUnit)) {\r
-+                portAssociationVector = 1 << phyUnit;\r
-+            } else {\r
-+                /* Disable learning on the CPU port */\r
-+                portAssociationVector = 0;\r
-+            }\r
-+            phyRegWrite(phyBase, switchPortAddr,\r
-+                MV_PORT_ASSOCIATION_VECTOR, portAssociationVector);\r
-+        }\r
-+    }\r
-+}\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* mv_verifyReady - validates that we're dealing with the device\r
-+* we think we're dealing with, and that it's ready.\r
-+*/\r
-+LOCAL void\r
-+mv_verifyReady(int ethUnit)\r
-+{\r
-+    int     phyUnit;\r
-+    UINT16  globalStatus;\r
-+    UINT32  phyBase = 0;\r
-+    UINT32  phyAddr;\r
-+    UINT32  switchPortAddr;\r
-+    UINT16  phyID1;\r
-+    UINT16  phyID2;\r
-+    UINT16  switchID;\r
-+\r
-+    /*\r
-+     * The first read to the Phy port registers always fails and\r
-+     * returns 0.   So get things started with a bogus read.\r
-+     */\r
-+    for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {\r
-+        if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {\r
-+            continue;\r
-+        }\r
-+        phyBase = MV_PHYBASE(phyUnit);\r
-+        phyAddr = MV_PHYADDR(phyUnit);\r
-+    \r
-+        (void)phyRegRead(phyBase, phyAddr, MV_PHY_ID1); /* returns 0 */\r
-+        break;\r
-+    }\r
-+\r
-+    for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {\r
-+        if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {\r
-+            continue;\r
-+        }\r
-+\r
-+        /*******************/\r
-+        /* Verify phy port */\r
-+        /*******************/\r
-+        phyBase = MV_PHYBASE(phyUnit);\r
-+        phyAddr = MV_PHYADDR(phyUnit);\r
-+    \r
-+        phyID1 = phyRegRead(phyBase, phyAddr, MV_PHY_ID1);\r
-+        if (phyID1 != MV_PHY_ID1_EXPECTATION) {\r
-+            MV_PRINT(MV_DEBUG_PHYSETUP,\r
-+                      ("Invalid PHY ID1 for ethmac%d port%d.  Expected 0x%04x, read 0x%04x\n",\r
-+                       ethUnit,\r
-+                       phyUnit,\r
-+                       MV_PHY_ID1_EXPECTATION,\r
-+                       phyID1));\r
-+            return;\r
-+        }\r
-+    \r
-+        phyID2 = phyRegRead(phyBase, phyAddr, MV_PHY_ID2);\r
-+        if ((phyID2 & MV_OUI_LSB_MASK) != MV_OUI_LSB_EXPECTATION) {\r
-+            MV_PRINT(MV_DEBUG_PHYSETUP,\r
-+                      ("Invalid PHY ID2 for ethmac%d port %d.  Expected 0x%04x, read 0x%04x\n",\r
-+                       ethUnit,\r
-+                       phyUnit,\r
-+                       MV_OUI_LSB_EXPECTATION,\r
-+                       phyID2));\r
-+            return;\r
-+        }\r
-+    \r
-+        MV_PRINT(MV_DEBUG_PHYSETUP,\r
-+                  ("Found PHY ethmac%d port%d: model 0x%x revision 0x%x\n",\r
-+                   ethUnit,\r
-+                   phyUnit,\r
-+                   (phyID2 & MV_MODEL_NUM_MASK) >> MV_MODEL_NUM_SHIFT,\r
-+                   (phyID2 & MV_REV_NUM_MASK) >> MV_REV_NUM_SHIFT));\r
-+    \r
-+    \r
-+        /**********************/\r
-+        /* Verify switch port */\r
-+        /**********************/\r
-+        switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);\r
-+    \r
-+        switchID = phyRegRead(phyBase, switchPortAddr, MV_SWITCH_ID);\r
-+        if ((switchID & MV_SWITCH_ID_DEV_MASK) !=\r
-+            MV_SWITCH_ID_DEV_EXPECTATION) {\r
-+    \r
-+            MV_PRINT(MV_DEBUG_PHYSETUP,\r
-+                      ("Invalid switch ID for ethmac%d port %d.  Expected 0x%04x, read 0x%04x\n",\r
-+                       ethUnit,\r
-+                       phyUnit,\r
-+                       MV_SWITCH_ID_DEV_EXPECTATION,\r
-+                       switchID));\r
-+            return;\r
-+        }\r
-+    \r
-+        MV_PRINT(MV_DEBUG_PHYSETUP,\r
-+                  ("Found PHY switch for enet %d port %d deviceID 0x%x revision 0x%x\n",\r
-+                    ethUnit,\r
-+                    phyUnit,\r
-+                    (switchID & MV_SWITCH_ID_DEV_MASK) >> MV_SWITCH_ID_DEV_SHIFT,\r
-+                    (switchID & MV_SWITCH_ID_REV_MASK) >> MV_SWITCH_ID_REV_SHIFT))\r
-+    }\r
-+    \r
-+    /*******************************/\r
-+    /* Verify that switch is ready */\r
-+    /*******************************/\r
-+    if (phyBase) {\r
-+        globalStatus = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,\r
-+                                  MV_SWITCH_GLOBAL_STATUS);\r
-+\r
-+        if (!(globalStatus & MV_SWITCH_STATUS_READY_MASK)) {\r
-+            MV_PRINT(MV_DEBUG_PHYSETUP,\r
-+                      ("PHY switch for ethmac%d NOT ready!\n",\r
-+                       ethUnit));\r
-+        }\r
-+    } else {\r
-+        MV_PRINT(MV_DEBUG_PHYSETUP,\r
-+                  ("No ports configured for ethmac%d\n", ethUnit));\r
-+    }\r
-+}\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* mv_phySetup - reset and setup the PHY switch.\r
-+*\r
-+* Resets each PHY port.\r
-+*\r
-+* RETURNS:\r
-+*    TRUE  --> at least 1 PHY with LINK\r
-+*    FALSE --> no LINKs on this ethernet unit\r
-+*/\r
-+BOOL\r
-+mv_phySetup(int ethUnit, UINT32 phyBase)\r
-+{\r
-+    int     phyUnit;\r
-+    int     liveLinks = 0;\r
-+    BOOL    foundPhy = FALSE;\r
-+    UINT32  phyAddr;\r
-+    UINT16  atuControl;\r
-+\r
-+    /*\r
-+     * Allow platform-specific code to determine the default Ethernet MAC\r
-+     * at run-time.  If phyEthMacDefault returns a negative value, use the\r
-+     * static mvPhyInfo table "as is".  But if phyEthMacDefault returns a\r
-+     * non-negative value, use it as the default ethernet unit.\r
-+     */\r
-+    {\r
-+        int ethMacDefault = phyEthMacDefault();\r
-+\r
-+        if (ethMacDefault >= 0) {\r
-+            for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {\r
-+                MV_ETHUNIT(phyUnit)=ethMacDefault;\r
-+            }\r
-+        }\r
-+    }\r
-+\r
-+    /*\r
-+     * See if there's any configuration data for this enet,\r
-+     * and set up phyBase in table.\r
-+     */\r
-+    for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {\r
-+        if (MV_ETHUNIT(phyUnit) != ethUnit) {\r
-+            continue;\r
-+        }\r
-+\r
-+        MV_PHYBASE(phyUnit) = phyBase;\r
-+        foundPhy = TRUE;\r
-+    }\r
-+\r
-+    if (!foundPhy) {\r
-+        return FALSE; /* No PHY's configured for this ethUnit */\r
-+    }\r
-+\r
-+    /* Verify that the switch is what we think it is, and that it's ready */\r
-+    mv_verifyReady(ethUnit);\r
-+\r
-+    /* Initialize global switch settings */\r
-+    atuControl  = MV_ATUCTRL_AGE_TIME_DEFAULT << MV_ATUCTRL_AGE_TIME_SHIFT;\r
-+    atuControl |= MV_ATUCTRL_ATU_SIZE_DEFAULT << MV_ATUCTRL_ATU_SIZE_SHIFT;\r
-+    // atuControl |= MV_ATUCTRL_ATU_LEARNDIS;\r
-+    phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_CONTROL, atuControl);\r
-+\r
-+    /* Reset PHYs and start autonegoation on each. */\r
-+    for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {\r
-+        if (MV_ETHUNIT(phyUnit) != ethUnit) {\r
-+            continue;\r
-+        }\r
-+\r
-+        phyBase = MV_PHYBASE(phyUnit);\r
-+        phyAddr = MV_PHYADDR(phyUnit);\r
-+\r
-+        phyRegWrite(phyBase, phyAddr, MV_PHY_CONTROL,\r
-+                    MV_CTRL_SOFTWARE_RESET | MV_CTRL_AUTONEGOTIATION_ENABLE);\r
-+    }\r
-+\r
-+    {\r
-+      int timeout;\r
-+      UINT16  phyHwStatus;\r
-+\r
-+      /*\r
-+       * Wait 5 seconds for ALL associated PHYs to finish autonegotiation.\r
-+       */\r
-+      timeout=50;\r
-+      for (phyUnit=0; (phyUnit < MV_PHY_MAX) && (timeout > 0); phyUnit++) {\r
-+          if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {\r
-+              continue;\r
-+          }\r
-+          for (;;) {\r
-+              phyBase = MV_PHYBASE(phyUnit);\r
-+              phyAddr = MV_PHYADDR(phyUnit);\r
-+\r
-+              phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);\r
-+\r
-+              if (MV_AUTONEG_DONE(phyHwStatus)) {\r
-+                  break;\r
-+              }\r
-+\r
-+              if (--timeout == 0) {\r
-+                  break;\r
-+              }\r
-+\r
-+              sysMsDelay(100);\r
-+          }\r
-+      }\r
-+    }\r
-+\r
-+    /*\r
-+     * All PHYs have had adequate time to autonegotiate.\r
-+     * Now initialize software status.\r
-+     *\r
-+     * It's possible that some ports may take a bit longer\r
-+     * to autonegotiate; but we can't wait forever.  They'll\r
-+     * get noticed by mv_phyCheckStatusChange during regular\r
-+     * polling activities.\r
-+     */\r
-+    for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {\r
-+        if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {\r
-+            continue;\r
-+        }\r
-+\r
-+        if (mv_phyIsLinkAlive(phyUnit)) {\r
-+            liveLinks++;\r
-+            MV_IS_PHY_ALIVE(phyUnit) = TRUE;\r
-+#ifdef DEBUG\r
-+          mv_phyShow(phyUnit);\r
-+#endif\r
-+        } else {\r
-+            MV_IS_PHY_ALIVE(phyUnit) = FALSE;\r
-+        }\r
-+\r
-+        MV_PRINT(MV_DEBUG_PHYSETUP,\r
-+            ("ethmac%d: Phy Status=%4.4x\n",\r
-+            ethUnit, \r
-+            phyRegRead(MV_PHYBASE(phyUnit),\r
-+                       MV_PHYADDR(phyUnit),\r
-+                       MV_PHY_SPECIFIC_STATUS)));\r
-+\r
-+    }\r
-+\r
-+#ifdef DEBUG\r
-+    /* PHY 5 is the connection to the CPU */\r
-+    mv_phyShow(5);\r
-+#endif\r
-+\r
-+    mv_VLANInit(ethUnit);\r
-+\r
-+    mv_enableConfiguredPorts(ethUnit);\r
-+\r
-+    return (liveLinks > 0);\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* mv_phyIsDuplexFull - Determines whether the phy ports associated with the\r
-+* specified device are FULL or HALF duplex.\r
-+*\r
-+* RETURNS:\r
-+*    TRUE --> at least one associated PHY in FULL DUPLEX\r
-+*    FALSE --> all half duplex, or no links\r
-+*/\r
-+BOOL\r
-+mv_phyIsFullDuplex(int ethUnit)\r
-+{\r
-+    int     phyUnit;\r
-+    UINT32  phyBase;\r
-+    UINT32  phyAddr;\r
-+    UINT16  phyHwStatus;\r
-+\r
-+    for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {\r
-+\r
-+        if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {\r
-+            continue;\r
-+        }\r
-+\r
-+        if (mv_phyIsLinkAlive(phyUnit)) {\r
-+\r
-+            phyBase = MV_PHYBASE(phyUnit);\r
-+            phyAddr = MV_PHYADDR(phyUnit);\r
-+\r
-+            phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);\r
-+\r
-+            if (phyHwStatus & MV_STATUS_RESOLVED_DUPLEX_FULL) {\r
-+                return TRUE;\r
-+            }\r
-+        }\r
-+    }\r
-+\r
-+    return FALSE;\r
-+}\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* mv_phyIsSpeed100 - Determines the speed of a phy port\r
-+*\r
-+* RETURNS:\r
-+*    TRUE --> PHY operating at 100 Mbit\r
-+*    FALSE --> link down, or not operating at 100 Mbit\r
-+*/\r
-+BOOL\r
-+mv_phyIsSpeed100(int phyUnit)\r
-+{\r
-+    UINT16  phyHwStatus;\r
-+    UINT32  phyBase;\r
-+    UINT32  phyAddr;\r
-+\r
-+    if (MV_IS_ENET_PORT(phyUnit)) {\r
-+        if (mv_phyIsLinkAlive(phyUnit)) {\r
-+\r
-+            phyBase = MV_PHYBASE(phyUnit);\r
-+            phyAddr = MV_PHYADDR(phyUnit);\r
-+\r
-+            phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);\r
-+\r
-+            if (phyHwStatus & MV_STATUS_RESOLVED_SPEED_100) {\r
-+                return TRUE;\r
-+            }\r
-+        }\r
-+    }\r
-+\r
-+    return FALSE;\r
-+}\r
-+\r
-+#ifdef CONFIG_VENETDEV\r
-+/******************************************************************************\r
-+*\r
-+* mv_phyDetermineSource - Examine a received frame's Egress Trailer\r
-+* to determine whether it came from a LAN or WAN port.\r
-+*\r
-+* RETURNS:\r
-+*    Returns 1-->LAN, 0-->WAN, -1-->ERROR\r
-+*/\r
-+int\r
-+mv_phyDetermineSource(char *data, int len)\r
-+{\r
-+    unsigned char *phyTrailer;\r
-+    unsigned char incomingPort;\r
-+\r
-+    phyTrailer = &data[len - MV_PHY_TRAILER_SIZE];\r
-+\r
-+    /* ASSERT(phyTrailer[0] == MV_EGRESS_TRAILER_VALID); */\r
-+    if (phyTrailer[0] != MV_EGRESS_TRAILER_VALID) {\r
-+      printk(KERN_ERR "PHY trailer invalid; got %#02x, expected %#02x\n",\r
-+             phyTrailer[0], MV_EGRESS_TRAILER_VALID);\r
-+      return -1;\r
-+    }\r
-+\r
-+    incomingPort = phyTrailer[1];\r
-+    if (MV_IS_LAN_PORT(incomingPort)) {\r
-+        return 1;\r
-+    } else {\r
-+        /* ASSERT(MV_IS_WAN_PORT(incomingPort)); */\r
-+      if (!MV_IS_WAN_PORT(incomingPort)) {\r
-+          printk(KERN_ERR "incoming port was %d; expected 0-4\n", incomingPort);\r
-+          return -1;\r
-+      }\r
-+        return 0;\r
-+    }\r
-+}\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* mv_phySetDestinationPort - Set the Ingress Trailer to force the\r
-+* frame to be sent to LAN or WAN, as specified.\r
-+*\r
-+*/\r
-+void\r
-+mv_phySetDestinationPort(char *data, int len, int fromLAN)\r
-+{\r
-+    char *phyTrailer;\r
-+\r
-+    phyTrailer = &data[len];\r
-+    if (fromLAN) {\r
-+        /* LAN ports: Use default settings, as per mvPhyInfo */\r
-+        phyTrailer[0] = 0x00;\r
-+        phyTrailer[1] = 0x00;\r
-+    } else {\r
-+        /* WAN port: Direct to WAN port */\r
-+        phyTrailer[0] = MV_INGRESS_TRAILER_OVERRIDE;\r
-+        phyTrailer[1] = 1 << MV_WAN_PORT;\r
-+    }\r
-+    phyTrailer[2] = 0x00;\r
-+    phyTrailer[3] = 0x00;\r
-+}\r
-+#endif\r
-+\r
-+\r
-+/*****************************************************************************\r
-+*\r
-+* Validate that the specified PHY unit number is a valid PHY ID.\r
-+* Print a message if it is invalid.\r
-+* RETURNS\r
-+*   TRUE  --> valid\r
-+*   FALSE --> invalid\r
-+*/\r
-+LOCAL BOOL\r
-+mv_validPhyId(int phyUnit)\r
-+{\r
-+    if ((phyUnit >= MV_ID_MIN) && (phyUnit <= MV_ID_MAX)) {\r
-+        return TRUE;\r
-+    } else {\r
-+        PRINTF("PHY unit number must be in the range [%d..%d]\n",\r
-+            MV_ID_MIN, MV_ID_MAX);\r
-+        return FALSE;\r
-+    } \r
-+}\r
-+\r
-+\r
-+/*****************************************************************************\r
-+*\r
-+* mv_waitWhileATUBusy - spins until the ATU completes\r
-+* its previous operation.\r
-+*/\r
-+LOCAL void\r
-+mv_waitWhileATUBusy(UINT32 phyBase)\r
-+{\r
-+    BOOL   isBusy;\r
-+    UINT16 ATUOperation;\r
-+\r
-+    do {\r
-+\r
-+        ATUOperation = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,\r
-+                                  MV_ATU_OPERATION);\r
-+\r
-+        isBusy = (ATUOperation & MV_ATU_BUSY_MASK) == MV_ATU_IS_BUSY;\r
-+\r
-+    } while(isBusy);\r
-+}\r
-+\r
-+/*****************************************************************************\r
-+*\r
-+* mv_flushATUDB - flushes ALL entries in the Address Translation Unit\r
-+* DataBase associated with phyUnit.  [Since we use a single DB for\r
-+* all PHYs, this flushes the entire shared DataBase.]\r
-+*\r
-+* The current implementation flushes even more than absolutely needed --\r
-+* it flushes all entries for all phyUnits on the same ethernet as the\r
-+* specified phyUnit.\r
-+*\r
-+* It is called only when a link failure is detected on a port that was\r
-+* previously working.  In other words, when the cable is unplugged.\r
-+*/\r
-+void\r
-+mv_flushATUDB(int phyUnit)\r
-+{\r
-+    UINT32 phyBase;\r
-+\r
-+    if (!mv_validPhyId(phyUnit)) {\r
-+        PRINTF("Invalid port number: %d\n", phyUnit);\r
-+        return;\r
-+    }\r
-+\r
-+    phyBase = MV_PHYBASE(phyUnit);\r
-+    \r
-+    /* Wait for previous operation (if any) to complete */\r
-+    mv_waitWhileATUBusy(phyBase);\r
-+\r
-+    /* Tell hardware to flush all entries */\r
-+    phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_OPERATION, \r
-+                MV_ATU_OP_FLUSH_ALL | MV_ATU_IS_BUSY);\r
-+\r
-+    mv_waitWhileATUBusy(phyBase);\r
-+}\r
-+ \r
-+/*****************************************************************************\r
-+*\r
-+* mv_phyCheckStatusChange -- checks for significant changes in PHY state.\r
-+*\r
-+* A "significant change" is:\r
-+*     dropped link (e.g. ethernet cable unplugged) OR\r
-+*     autonegotiation completed + link (e.g. ethernet cable plugged in)\r
-+*/\r
-+void\r
-+mv_phyCheckStatusChange(int ethUnit)\r
-+{\r
-+    int           phyUnit;\r
-+    UINT16        phyHwStatus;\r
-+    mvPhyInfo_t   *lastStatus;\r
-+    int           linkCount   = 0;\r
-+    int           lostLinks   = 0;\r
-+    int           gainedLinks = 0;\r
-+    UINT32        phyBase;\r
-+    UINT32        phyAddr;\r
-+\r
-+    for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {\r
-+        if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {\r
-+            continue;\r
-+        }\r
-+\r
-+        phyBase = MV_PHYBASE(phyUnit);\r
-+        phyAddr = MV_PHYADDR(phyUnit);\r
-+\r
-+        lastStatus = &mvPhyInfo[phyUnit];\r
-+        phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);\r
-+\r
-+        if (lastStatus->isPhyAlive) { /* last known link status was ALIVE */\r
-+            /* See if we've lost link */\r
-+            if (phyHwStatus & MV_STATUS_REAL_TIME_LINK_UP) {\r
-+                linkCount++;\r
-+            } else {\r
-+                lostLinks++;\r
-+                mv_flushATUDB(phyUnit);\r
-+                MV_PRINT(MV_DEBUG_PHYCHANGE,("\nethmac%d port%d down\n",\r
-+                                               ethUnit, phyUnit));\r
-+                lastStatus->isPhyAlive = FALSE;\r
-+            }\r
-+        } else { /* last known link status was DEAD */\r
-+            /* Check for AutoNegotiation complete */\r
-+            if (MV_AUTONEG_DONE(phyHwStatus)) {\r
-+                gainedLinks++;\r
-+              linkCount++;\r
-+                MV_PRINT(MV_DEBUG_PHYCHANGE,("\nethmac%d port%d up\n",\r
-+                                               ethUnit, phyUnit));\r
-+                lastStatus->isPhyAlive = TRUE;\r
-+            }\r
-+        }\r
-+    }\r
-+\r
-+    if (linkCount == 0) {\r
-+        if (lostLinks) {\r
-+            /* We just lost the last link for this MAC */\r
-+            phyLinkLost(ethUnit);\r
-+        }\r
-+    } else {\r
-+        if (gainedLinks == linkCount) {\r
-+            /* We just gained our first link(s) for this MAC */\r
-+            phyLinkGained(ethUnit);\r
-+        }\r
-+    }\r
-+}\r
-+\r
-+#if DEBUG\r
-+\r
-+/* Define the registers of interest for a phyShow command */\r
-+typedef struct mvRegisterTableEntry_s {\r
-+    UINT32 regNum;\r
-+    char  *regIdString;\r
-+} mvRegisterTableEntry_t;\r
-+\r
-+mvRegisterTableEntry_t mvPhyRegisterTable[] = {\r
-+    {MV_PHY_CONTROL,                 "PHY Control                     "},\r
-+    {MV_PHY_STATUS,                  "PHY Status                      "},\r
-+    {MV_PHY_ID1,                     "PHY Identifier 1                "},\r
-+    {MV_PHY_ID2,                     "PHY Identifier 2                "},\r
-+    {MV_AUTONEG_ADVERT,              "Auto-Negotiation Advertisement  "},\r
-+    {MV_LINK_PARTNER_ABILITY,        "Link Partner Ability            "},\r
-+    {MV_AUTONEG_EXPANSION,           "Auto-Negotiation Expansion      "},\r
-+    {MV_NEXT_PAGE_TRANSMIT,          "Next Page Transmit              "},\r
-+    {MV_LINK_PARTNER_NEXT_PAGE,      "Link Partner Next Page          "},\r
-+    {MV_PHY_SPECIFIC_CONTROL_1,      "PHY-Specific Control Register 1 "},\r
-+    {MV_PHY_SPECIFIC_STATUS,         "PHY-Specific Status             "},\r
-+    {MV_PHY_INTERRUPT_ENABLE,        "PHY Interrupt Enable            "},\r
-+    {MV_PHY_INTERRUPT_STATUS,        "PHY Interrupt Status            "},\r
-+    {MV_PHY_INTERRUPT_PORT_SUMMARY,  "PHY Interrupt Port Summary      "},\r
-+    {MV_RECEIVE_ERROR_COUNTER,       "Receive Error Counter           "},\r
-+    {MV_LED_PARALLEL_SELECT,         "LED Parallel Select             "},\r
-+    {MV_LED_STREAM_SELECT_LEDS,      "LED Stream Select               "},\r
-+    {MV_PHY_LED_CONTROL,             "PHY LED Control                 "},\r
-+    {MV_PHY_MANUAL_LED_OVERRIDE,     "PHY Manual LED Override         "},\r
-+    {MV_VCT_CONTROL,                 "VCT Control                     "},\r
-+    {MV_VCT_STATUS,                  "VCT Status                      "},\r
-+    {MV_PHY_SPECIFIC_CONTROL_2,      "PHY-Specific Control Register 2 "},\r
-+};\r
-+int mvPhyNumRegs = sizeof(mvPhyRegisterTable) / sizeof(mvPhyRegisterTable[0]);\r
-+\r
-+\r
-+mvRegisterTableEntry_t mvSwitchPortRegisterTable[] = {\r
-+    {MV_PORT_STATUS,              "Port Status             "},\r
-+    {MV_SWITCH_ID,                "Switch ID               "},\r
-+    {MV_PORT_CONTROL,             "Port Control            "},\r
-+    {MV_PORT_BASED_VLAN_MAP,      "Port-Based VLAN Map     "},\r
-+    {MV_PORT_ASSOCIATION_VECTOR,  "Port Association Vector "},\r
-+    {MV_RX_COUNTER,               "RX Counter              "},\r
-+    {MV_TX_COUNTER,               "TX Counter              "},\r
-+};\r
-+int mvSwitchPortNumRegs =\r
-+    sizeof(mvSwitchPortRegisterTable) / sizeof(mvSwitchPortRegisterTable[0]);\r
-+\r
-+\r
-+mvRegisterTableEntry_t mvSwitchGlobalRegisterTable[] = {\r
-+    {MV_SWITCH_GLOBAL_STATUS,  "Switch Global Status  "},\r
-+    {MV_SWITCH_MAC_ADDR0,      "Switch MAC Addr 0 & 1 "},\r
-+    {MV_SWITCH_MAC_ADDR2,      "Switch MAC Addr 2 & 3 "},\r
-+    {MV_SWITCH_MAC_ADDR4,      "Switch MAC Addr 4 & 5 "},\r
-+    {MV_SWITCH_GLOBAL_CONTROL, "Switch Global Control "},\r
-+    {MV_ATU_CONTROL,           "ATU Control           "},\r
-+    {MV_ATU_OPERATION,         "ATU Operation         "},\r
-+    {MV_ATU_DATA,              "ATU Data              "},\r
-+    {MV_ATU_MAC_ADDR0,         "ATU MAC Addr 0 & 1    "},\r
-+    {MV_ATU_MAC_ADDR2,         "ATU MAC Addr 2 & 3    "},\r
-+    {MV_ATU_MAC_ADDR4,         "ATU MAC Addr 4 & 5    "},\r
-+};\r
-+int mvSwitchGlobalNumRegs =\r
-+    sizeof(mvSwitchGlobalRegisterTable) / sizeof(mvSwitchGlobalRegisterTable[0]);\r
-+\r
-+\r
-+/*****************************************************************************\r
-+*\r
-+* mv_phyShow - Dump the state of a PHY.\r
-+* There are two sets of registers for each phy port:\r
-+*  "phy registers" and\r
-+*  "switch port registers"\r
-+* We dump 'em all, plus the switch global registers.\r
-+*/\r
-+void\r
-+mv_phyShow(int phyUnit)\r
-+{\r
-+    int     i;\r
-+    UINT16  value;\r
-+    UINT32  phyBase;\r
-+    UINT32  phyAddr;\r
-+    UINT32  switchPortAddr;\r
-+\r
-+    if (!mv_validPhyId(phyUnit)) {\r
-+        return;\r
-+    }\r
-+\r
-+    phyBase        = MV_PHYBASE(phyUnit);\r
-+    phyAddr        = MV_PHYADDR(phyUnit);\r
-+    switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);\r
-+\r
-+    PRINTF("PHY state for PHY%d (ethmac%d, phyBase 0x%8x, phyAddr 0x%x, switchAddr 0x%x)\n",\r
-+           phyUnit,\r
-+           MV_ETHUNIT(phyUnit),\r
-+           MV_PHYBASE(phyUnit),\r
-+           MV_PHYADDR(phyUnit),\r
-+           MV_SWITCH_PORT_ADDR(phyUnit));\r
-+\r
-+    PRINTF("PHY Registers:\n");\r
-+    for (i=0; i < mvPhyNumRegs; i++) {\r
-+\r
-+        value = phyRegRead(phyBase, phyAddr, mvPhyRegisterTable[i].regNum);\r
-+\r
-+        PRINTF("Reg %02d (0x%02x) %s = 0x%08x\n",\r
-+               mvPhyRegisterTable[i].regNum,\r
-+               mvPhyRegisterTable[i].regNum,\r
-+               mvPhyRegisterTable[i].regIdString,\r
-+               value);\r
-+    }\r
-+\r
-+    PRINTF("Switch Port Registers:\n");\r
-+    for (i=0; i < mvSwitchPortNumRegs; i++) {\r
-+\r
-+        value = phyRegRead(phyBase, switchPortAddr,\r
-+                           mvSwitchPortRegisterTable[i].regNum);\r
-+\r
-+        PRINTF("Reg %02d (0x%02x) %s = 0x%08x\n",\r
-+               mvSwitchPortRegisterTable[i].regNum,\r
-+               mvSwitchPortRegisterTable[i].regNum,\r
-+               mvSwitchPortRegisterTable[i].regIdString,\r
-+               value);\r
-+    }\r
-+\r
-+    PRINTF("Switch Global Registers:\n");\r
-+    for (i=0; i < mvSwitchGlobalNumRegs; i++) {\r
-+\r
-+        value = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,\r
-+                           mvSwitchGlobalRegisterTable[i].regNum);\r
-+\r
-+        PRINTF("Reg %02d (0x%02x) %s = 0x%08x\n",\r
-+               mvSwitchGlobalRegisterTable[i].regNum,\r
-+               mvSwitchGlobalRegisterTable[i].regNum,\r
-+               mvSwitchGlobalRegisterTable[i].regIdString,\r
-+               value);\r
-+    }\r
-+}\r
-+\r
-+/*****************************************************************************\r
-+*\r
-+* mv_phySet - Modify the value of a PHY register (debug only).\r
-+*/\r
-+void\r
-+mv_phySet(int phyUnit, UINT32 regnum, UINT32 value)\r
-+{\r
-+    UINT32  phyBase;\r
-+    UINT32  phyAddr;\r
-+\r
-+    if (mv_validPhyId(phyUnit)) {\r
-+\r
-+        phyBase = MV_PHYBASE(phyUnit);\r
-+        phyAddr = MV_PHYADDR(phyUnit);\r
-+\r
-+        phyRegWrite(phyBase, phyAddr, regnum, value);\r
-+    }\r
-+}\r
-+\r
-+\r
-+/*****************************************************************************\r
-+*\r
-+* mv_switchPortSet - Modify the value of a switch port register (debug only).\r
-+*/\r
-+void\r
-+mv_switchPortSet(int phyUnit, UINT32 regnum, UINT32 value)\r
-+{\r
-+    UINT32  phyBase;\r
-+    UINT32  switchPortAddr;\r
-+\r
-+    if (mv_validPhyId(phyUnit)) {\r
-+\r
-+        phyBase = MV_PHYBASE(phyUnit);\r
-+        switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);\r
-+\r
-+        phyRegWrite(phyBase, switchPortAddr, regnum, value);\r
-+    }\r
-+}\r
-+ \r
-+/*****************************************************************************\r
-+*\r
-+* mv_switchGlobalSet - Modify the value of a switch global register\r
-+* (debug only).\r
-+*/\r
-+void\r
-+mv_switchGlobalSet(int phyUnit, UINT32 regnum, UINT32 value)\r
-+{\r
-+    UINT32  phyBase;\r
-+\r
-+    if (mv_validPhyId(phyUnit)) {\r
-+\r
-+        phyBase = MV_PHYBASE(phyUnit);\r
-+\r
-+        phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, regnum, value);\r
-+    }\r
-+}\r
-+\r
-+/*****************************************************************************\r
-+*\r
-+* mv_showATUDB - Dump the contents of the Address Translation Unit DataBase\r
-+* for the PHY switch associated with the specified phy.\r
-+*/\r
-+void\r
-+mv_showATUDB(int phyUnit)\r
-+{\r
-+    UINT32 phyBase;\r
-+    UINT16 ATUData;\r
-+    UINT16 ATUMac0;\r
-+    UINT16 ATUMac2;\r
-+    UINT16 ATUMac4;\r
-+    int portVec;\r
-+    int entryState;\r
-+\r
-+    if (!mv_validPhyId(phyUnit)) {\r
-+        PRINTF("Invalid port number: %d\n", phyUnit);\r
-+        return;\r
-+    }\r
-+\r
-+    phyBase = MV_PHYBASE(phyUnit);\r
-+    \r
-+    /* Wait for previous operation (if any) to complete */\r
-+    mv_waitWhileATUBusy(phyBase);\r
-+\r
-+    /* Initialize ATU MAC to all 1's */\r
-+    phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR0, 0xffff);\r
-+    phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR2, 0xffff);\r
-+    phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR4, 0xffff);\r
-+\r
-+    PRINTF("   MAC ADDRESS    EntryState PortVector\n");\r
-+\r
-+    for(;;) {\r
-+        /* Tell hardware to get next MAC info */\r
-+        phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_OPERATION, \r
-+                    MV_ATU_OP_GET_NEXT | MV_ATU_IS_BUSY);\r
-+\r
-+        mv_waitWhileATUBusy(phyBase);\r
-+\r
-+        ATUData = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_DATA);\r
-+        entryState = (ATUData & MV_ENTRYSTATE_MASK) >> MV_ENTRYSTATE_SHIFT;\r
-+\r
-+        if (entryState == 0) {\r
-+            /* We've hit the end of the list */\r
-+            break;\r
-+        }\r
-+\r
-+        ATUMac0 = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR0);\r
-+        ATUMac2 = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR2);\r
-+        ATUMac4 = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR4);\r
-+\r
-+        portVec    = (ATUData & MV_PORTVEC_MASK) >> MV_PORTVEC_SHIFT;\r
-+\r
-+        PRINTF("%02x:%02x:%02x:%02x:%02x:%02x    0x%02x       0x%02x\n",\r
-+               ATUMac0 >> 8,    /* MAC byte 0 */\r
-+               ATUMac0 & 0xff,  /* MAC byte 1 */\r
-+               ATUMac2 >> 8,    /* MAC byte 2 */\r
-+               ATUMac2 & 0xff,  /* MAC byte 3 */\r
-+               ATUMac4 >> 8,    /* MAC byte 4 */\r
-+               ATUMac4 & 0xff,  /* MAC byte 5 */\r
-+               entryState,\r
-+               portVec);\r
-+    }\r
-+}\r
-+\r
-+LOCAL BOOL countingGoodFrames;\r
-+\r
-+/*****************************************************************************\r
-+*\r
-+* mv_countGoodFrames - starts counting GOOD RX/TX frames per port\r
-+*/\r
-+void\r
-+mv_countGoodFrames(int phyUnit)\r
-+{\r
-+    UINT32 phyBase;\r
-+    UINT16 globalControl;\r
-+\r
-+    if (mv_validPhyId(phyUnit)) {\r
-+        /*\r
-+         * Guarantee that counters are cleared by\r
-+         * forcing CtrMode to toggle and end on GOODFRAMES.\r
-+         */\r
-+\r
-+        phyBase = MV_PHYBASE(phyUnit);\r
-+\r
-+        /* Read current Switch Global Control Register */\r
-+        globalControl = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,\r
-+                                   MV_SWITCH_GLOBAL_CONTROL);\r
-+\r
-+        /* Set CtrMode to count BAD frames */\r
-+        globalControl = ((globalControl & ~MV_CTRMODE_MASK) |\r
-+                         MV_CTRMODE_BADFRAMES);\r
-+\r
-+        /* Push new value out to hardware */\r
-+        phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR,\r
-+                    MV_SWITCH_GLOBAL_CONTROL, globalControl);\r
-+\r
-+        /* Now toggle CtrMode to count GOOD frames */\r
-+        globalControl = ((globalControl & ~MV_CTRMODE_MASK) |\r
-+                         MV_CTRMODE_GOODFRAMES);\r
-+\r
-+        /* Push new value out to hardware */\r
-+        phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR,\r
-+                    MV_SWITCH_GLOBAL_CONTROL, globalControl);\r
-+\r
-+        countingGoodFrames = TRUE;\r
-+    }\r
-+}\r
-+\r
-+/*****************************************************************************\r
-+*\r
-+* mv_countBadFrames - starts counting BAD RX/TX frames per port\r
-+*/\r
-+void\r
-+mv_countBadFrames(int phyUnit)\r
-+{\r
-+    UINT32 phyBase;\r
-+    UINT16 globalControl;\r
-+\r
-+    if (mv_validPhyId(phyUnit)) {\r
-+        /*\r
-+         * Guarantee that counters are cleared by\r
-+         * forcing CtrMode to toggle and end on BADFRAMES.\r
-+         */\r
-+\r
-+        phyBase = MV_PHYBASE(phyUnit);\r
-+\r
-+        /* Read current Switch Global Control Register */\r
-+        globalControl = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,\r
-+                                   MV_SWITCH_GLOBAL_CONTROL);\r
-+\r
-+        /* Set CtrMode to count GOOD frames */\r
-+        globalControl = ((globalControl & ~MV_CTRMODE_MASK) |\r
-+                         MV_CTRMODE_GOODFRAMES);\r
-+\r
-+        /* Push new value out to hardware */\r
-+        phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR,\r
-+                    MV_SWITCH_GLOBAL_CONTROL, globalControl);\r
-+\r
-+        /* Now toggle CtrMode to count BAD frames */\r
-+        globalControl = ((globalControl & ~MV_CTRMODE_MASK) |\r
-+                         MV_CTRMODE_BADFRAMES);\r
-+\r
-+        /* Push new value out to hardware */\r
-+        phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR,\r
-+                    MV_SWITCH_GLOBAL_CONTROL, globalControl);\r
-+\r
-+        countingGoodFrames = FALSE;\r
-+    }\r
-+}\r
-+\r
-+/*****************************************************************************\r
-+*\r
-+* mv_showFrameCounts - shows current GOOD/BAD Frame counts\r
-+*/\r
-+void\r
-+mv_showFrameCounts(int phyUnit)\r
-+{\r
-+    UINT16 rxCounter;\r
-+    UINT16 txCounter;\r
-+    UINT32 phyBase;\r
-+    UINT32 switchPortAddr;\r
-+\r
-+    if (!mv_validPhyId(phyUnit)) {\r
-+        return;\r
-+    }\r
-+\r
-+    phyBase = MV_PHYBASE(phyUnit);\r
-+    switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);\r
-+\r
-+    rxCounter = phyRegRead(phyBase, switchPortAddr, MV_RX_COUNTER);\r
-+\r
-+    txCounter = phyRegRead(phyBase, switchPortAddr, MV_TX_COUNTER);\r
-+\r
-+    PRINTF("port%d %s frames: receive: %05d   transmit: %05d\n",\r
-+           phyUnit,\r
-+           (countingGoodFrames ? "good" : "error"),\r
-+           rxCounter,\r
-+           txCounter);\r
-+}\r
-+#endif\r
-diff -urN linux-2.4.32.new/arch/mips/ar531x/mvPhy.h linux-2.4.32.new-eth/arch/mips/ar531x/mvPhy.h\r
---- linux-2.4.32.new/arch/mips/ar531x/mvPhy.h  1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new-eth/arch/mips/ar531x/mvPhy.h      2005-12-25 11:54:39.775382608 +0000\r
-@@ -0,0 +1,160 @@\r
-+/*\r
-+ * This file is subject to the terms and conditions of the GNU General Public\r
-+ * License.  See the file "COPYING" in the main directory of this archive\r
-+ * for more details.\r
-+ *\r
-+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.\r
-+ */\r
-+\r
-+/*\r
-+ * mvPhy.h - definitions for the ethernet PHY -- Marvell 88E6060\r
-+ * All definitions in this file are operating system independent!\r
-+ */\r
-+\r
-+#ifndef MVPHY_H\r
-+#define MVPHY_H\r
-+\r
-+/*****************/\r
-+/* PHY Registers */\r
-+/*****************/\r
-+#define MV_PHY_CONTROL                 0\r
-+#define MV_PHY_STATUS                  1\r
-+#define MV_PHY_ID1                     2\r
-+#define MV_PHY_ID2                     3\r
-+#define MV_AUTONEG_ADVERT              4\r
-+#define MV_LINK_PARTNER_ABILITY        5\r
-+#define MV_AUTONEG_EXPANSION           6\r
-+#define MV_NEXT_PAGE_TRANSMIT          7\r
-+#define MV_LINK_PARTNER_NEXT_PAGE      8\r
-+#define MV_PHY_SPECIFIC_CONTROL_1     16\r
-+#define MV_PHY_SPECIFIC_STATUS        17\r
-+#define MV_PHY_INTERRUPT_ENABLE       18\r
-+#define MV_PHY_INTERRUPT_STATUS       19\r
-+#define MV_PHY_INTERRUPT_PORT_SUMMARY 20\r
-+#define MV_RECEIVE_ERROR_COUNTER      21\r
-+#define MV_LED_PARALLEL_SELECT        22\r
-+#define MV_LED_STREAM_SELECT_LEDS     23\r
-+#define MV_PHY_LED_CONTROL            24\r
-+#define MV_PHY_MANUAL_LED_OVERRIDE    25\r
-+#define MV_VCT_CONTROL                26\r
-+#define MV_VCT_STATUS                 27\r
-+#define MV_PHY_SPECIFIC_CONTROL_2     28\r
-+\r
-+/* MV_PHY_CONTROL fields */\r
-+#define MV_CTRL_SOFTWARE_RESET                    0x8000\r
-+#define MV_CTRL_AUTONEGOTIATION_ENABLE            0x1000\r
-+\r
-+/* MV_PHY_ID1 fields */\r
-+#define MV_PHY_ID1_EXPECTATION                    0x0141 /* OUI >> 6 */\r
-+\r
-+/* MV_PHY_ID2 fields */\r
-+#define MV_OUI_LSB_MASK                           0xfc00\r
-+#define MV_OUI_LSB_EXPECTATION                    0x0c00\r
-+#define MV_OUI_LSB_SHIFT                              10\r
-+#define MV_MODEL_NUM_MASK                         0x03f0\r
-+#define MV_MODEL_NUM_SHIFT                             4\r
-+#define MV_REV_NUM_MASK                           0x000f\r
-+#define MV_REV_NUM_SHIFT                               0\r
-+\r
-+/* MV_PHY_SPECIFIC_STATUS fields */\r
-+#define MV_STATUS_RESOLVED_SPEED_100              0x4000\r
-+#define MV_STATUS_RESOLVED_DUPLEX_FULL            0x2000\r
-+#define MV_STATUS_RESOLVED                        0x0800\r
-+#define MV_STATUS_REAL_TIME_LINK_UP               0x0400\r
-+\r
-+/* Check if autonegotiation is complete and link is up */\r
-+#define MV_AUTONEG_DONE(mv_phy_specific_status)                   \\r
-+    (((mv_phy_specific_status) &                                  \\r
-+        (MV_STATUS_RESOLVED | MV_STATUS_REAL_TIME_LINK_UP)) ==    \\r
-+        (MV_STATUS_RESOLVED | MV_STATUS_REAL_TIME_LINK_UP))\r
-+\r
-+\r
-+/*************************/\r
-+/* Switch Port Registers */\r
-+/*************************/\r
-+#define MV_PORT_STATUS                 0\r
-+#define MV_SWITCH_ID                   3\r
-+#define MV_PORT_CONTROL                4\r
-+#define MV_PORT_BASED_VLAN_MAP         6\r
-+#define MV_PORT_ASSOCIATION_VECTOR    11\r
-+#define MV_RX_COUNTER                 16\r
-+#define MV_TX_COUNTER                 17\r
-+\r
-+/* MV_SWITCH_ID fields */\r
-+#define MV_SWITCH_ID_DEV_MASK                       0xfff0\r
-+#define MV_SWITCH_ID_DEV_EXPECTATION                0x0600\r
-+#define MV_SWITCH_ID_DEV_SHIFT                           4\r
-+#define MV_SWITCH_ID_REV_MASK                       0x000f\r
-+#define MV_SWITCH_ID_REV_SHIFT                           0\r
-+\r
-+/* MV_PORT_CONTROL fields */\r
-+#define MV_PORT_CONTROL_PORT_STATE_MASK             0x0003\r
-+#define MV_PORT_CONTROL_PORT_STATE_DISABLED         0x0000\r
-+#define MV_PORT_CONTROL_PORT_STATE_FORWARDING       0x0003\r
-+\r
-+#define MV_PORT_CONTROL_EGRESS_MODE                 0x0100 /* Receive */\r
-+#define MV_PORT_CONTROL_INGRESS_TRAILER             0x4000 /* Transmit */\r
-+\r
-+#define MV_EGRESS_TRAILER_VALID                       0x80\r
-+#define MV_INGRESS_TRAILER_OVERRIDE                   0x80\r
-+\r
-+#define MV_PHY_TRAILER_SIZE                              4\r
-+\r
-+\r
-+/***************************/\r
-+/* Switch Global Registers */\r
-+/***************************/\r
-+#define MV_SWITCH_GLOBAL_STATUS        0\r
-+#define MV_SWITCH_MAC_ADDR0            1\r
-+#define MV_SWITCH_MAC_ADDR2            2\r
-+#define MV_SWITCH_MAC_ADDR4            3\r
-+#define MV_SWITCH_GLOBAL_CONTROL       4\r
-+#define MV_ATU_CONTROL                10\r
-+#define MV_ATU_OPERATION              11\r
-+#define MV_ATU_DATA                   12\r
-+#define MV_ATU_MAC_ADDR0              13\r
-+#define MV_ATU_MAC_ADDR2              14\r
-+#define MV_ATU_MAC_ADDR4              15\r
-+\r
-+/* MV_SWITCH_GLOBAL_STATUS fields */\r
-+#define MV_SWITCH_STATUS_READY_MASK  0x0800\r
-+\r
-+/* MV_SWITCH_GLOBAL_CONTROL fields */\r
-+#define MV_CTRMODE_MASK              0x0100\r
-+#define MV_CTRMODE_GOODFRAMES        0x0000\r
-+#define MV_CTRMODE_BADFRAMES         0x0100\r
-+\r
-+/* MV_ATU_CONTROL fields */\r
-+#define MV_ATUCTRL_ATU_LEARNDIS            0x4000\r
-+#define MV_ATUCTRL_ATU_SIZE_MASK     0x3000\r
-+#define MV_ATUCTRL_ATU_SIZE_SHIFT        12\r
-+#define MV_ATUCTRL_ATU_SIZE_DEFAULT       2 /* 1024 entry database */\r
-+#define MV_ATUCTRL_AGE_TIME_MASK     0x0ff0\r
-+#define MV_ATUCTRL_AGE_TIME_SHIFT         4\r
-+#define MV_ATUCTRL_AGE_TIME_DEFAULT      19 /* 19 * 16 = 304 seconds */\r
-+\r
-+/* MV_ATU_OPERATION fields */\r
-+#define MV_ATU_BUSY_MASK             0x8000\r
-+#define MV_ATU_IS_BUSY               0x8000\r
-+#define MV_ATU_IS_FREE               0x0000\r
-+#define MV_ATU_OP_MASK               0x7000\r
-+#define MV_ATU_OP_FLUSH_ALL          0x1000\r
-+#define MV_ATU_OP_GET_NEXT           0x4000\r
-+\r
-+/* MV_ATU_DATA fields */\r
-+#define MV_ENTRYPRI_MASK             0xc000\r
-+#define MV_ENTRYPRI_SHIFT                14\r
-+#define MV_PORTVEC_MASK              0x03f0\r
-+#define MV_PORTVEC_SHIFT                  4\r
-+#define MV_ENTRYSTATE_MASK           0x000f\r
-+#define MV_ENTRYSTATE_SHIFT               0\r
-+\r
-+/* PHY Address for the switch itself */\r
-+#define MV_SWITCH_GLOBAL_ADDR 0x1f\r
-+\r
-+BOOL    mv_phySetup(int ethUnit, UINT32 phyBase);\r
-+void    mv_phyCheckStatusChange(int ethUnit);\r
-+BOOL    mv_phyIsSpeed100(int ethUnit);\r
-+BOOL    mv_phyIsFullDuplex(int ethUnit);\r
-+\r
-+#endif /* MVPHY_H */\r
-diff -urN linux-2.4.32.new/arch/mips/ar531x/rtPhy.c linux-2.4.32.new-eth/arch/mips/ar531x/rtPhy.c\r
---- linux-2.4.32.new/arch/mips/ar531x/rtPhy.c  1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new-eth/arch/mips/ar531x/rtPhy.c      2005-12-25 11:54:46.086423184 +0000\r
-@@ -0,0 +1,272 @@\r
-+/*\r
-+ * This file is subject to the terms and conditions of the GNU General Public\r
-+ * License.  See the file "COPYING" in the main directory of this archive\r
-+ * for more details.\r
-+ *\r
-+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.\r
-+ */\r
-+\r
-+/*\r
-+ * Manage the ethernet PHY.\r
-+ * This code supports a simple 1-port ethernet phy, Realtek RTL8201BL,\r
-+ * and compatible PHYs, such as the Kendin KS8721B.\r
-+ * All definitions in this file are operating system independent!\r
-+ */\r
-+\r
-+#if defined(linux)\r
-+#include <linux/config.h>\r
-+#include <linux/types.h>\r
-+#include <linux/netdevice.h>\r
-+#include <linux/etherdevice.h>\r
-+#include <linux/delay.h>\r
-+\r
-+#include "ar531xlnx.h"\r
-+#endif\r
-+\r
-+#if defined(__ECOS)\r
-+#include "ae531xecos.h"\r
-+#endif\r
-+\r
-+\r
-+#include "ae531xmac.h"\r
-+#include "ae531xreg.h"\r
-+#include "rtPhy.h"\r
-+\r
-+#if /* DEBUG */ 1\r
-+#define RT_DEBUG_ERROR     0x00000001\r
-+#define RT_DEBUG_PHYSETUP  0x00000002\r
-+#define RT_DEBUG_PHYCHANGE 0x00000004\r
-+\r
-+int rtPhyDebug = RT_DEBUG_ERROR;\r
-+\r
-+#define RT_PRINT(FLG, X)                            \\r
-+{                                                   \\r
-+    if (rtPhyDebug & (FLG)) {                       \\r
-+        DEBUG_PRINTF X;                             \\r
-+    }                                               \\r
-+}\r
-+#else\r
-+#define RT_PRINT(FLG, X)\r
-+#endif\r
-+\r
-+/*\r
-+ * Track per-PHY port information.\r
-+ */\r
-+typedef struct {\r
-+    BOOL   phyAlive;    /* last known state of link */\r
-+    UINT32 phyBase;\r
-+    UINT32 phyAddr;\r
-+} rtPhyInfo_t;\r
-+\r
-+#define ETH_PHY_ADDR          1\r
-+\r
-+/*\r
-+ * This table defines the mapping from phy units to\r
-+ * per-PHY information.\r
-+ *\r
-+ * This table is somewhat board-dependent.\r
-+ */\r
-+rtPhyInfo_t rtPhyInfo[] = {\r
-+    {phyAlive: FALSE,  /* PHY 0 */\r
-+     phyBase: 0,       /* filled in by rt_phySetup */\r
-+     phyAddr: ETH_PHY_ADDR},                             \r
-+\r
-+    {phyAlive: FALSE,  /* PHY 1 */\r
-+     phyBase: 0,       /* filled in by rt_phySetup */\r
-+     phyAddr: ETH_PHY_ADDR}\r
-+};\r
-+\r
-+/* Convert from phy unit# to (phyBase, phyAddr) pair */\r
-+#define RT_PHYBASE(phyUnit) (rtPhyInfo[phyUnit].phyBase)\r
-+#define RT_PHYADDR(phyUnit) (rtPhyInfo[phyUnit].phyAddr)\r
-+\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* rt_phySetup - reset and setup the PHY associated with\r
-+* the specified MAC unit number.\r
-+*\r
-+* Resets the associated PHY port.\r
-+*\r
-+* RETURNS:\r
-+*    TRUE  --> associated PHY is alive\r
-+*    FALSE --> no LINKs on this ethernet unit\r
-+*/\r
-+\r
-+BOOL\r
-+rt_phySetup(int ethUnit, UINT32 phyBase)\r
-+{\r
-+    BOOL    linkAlive = FALSE;\r
-+    UINT32  phyAddr;\r
-+\r
-+    RT_PHYBASE(ethUnit) = phyBase;\r
-+\r
-+    phyAddr = RT_PHYADDR(ethUnit);\r
-+\r
-+    /* Reset phy */\r
-+    phyRegWrite(phyBase, phyAddr, GEN_ctl, PHY_SW_RST | AUTONEGENA);\r
-+\r
-+    sysMsDelay(1500);\r
-+\r
-+    return linkAlive;\r
-+}\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* rt_phyIsDuplexFull - Determines whether the phy ports associated with the\r
-+* specified device are FULL or HALF duplex.\r
-+*\r
-+* RETURNS:\r
-+*    TRUE  --> FULL\r
-+*    FALSE --> HALF\r
-+*/\r
-+BOOL\r
-+rt_phyIsFullDuplex(int ethUnit)\r
-+{\r
-+    UINT16  phyCtl;\r
-+    UINT32  phyBase;\r
-+    UINT32  phyAddr;\r
-+\r
-+    phyBase = RT_PHYBASE(ethUnit);\r
-+    phyAddr = RT_PHYADDR(ethUnit);\r
-+\r
-+    phyCtl = phyRegRead(phyBase, phyAddr, GEN_ctl);\r
-+\r
-+    if (phyCtl & DUPLEX) {\r
-+        return TRUE;\r
-+    } else {\r
-+        return FALSE;\r
-+    }\r
-+}\r
-+\r
-+/******************************************************************************\r
-+*\r
-+* rt_phyIsSpeed100 - Determines the speed of phy ports associated with the\r
-+* specified device.\r
-+*\r
-+* RETURNS:\r
-+*    TRUE --> 100Mbit\r
-+*    FALSE --> 10Mbit\r
-+*/\r
-+BOOL\r
-+rt_phyIsSpeed100(int phyUnit)\r
-+{\r
-+    UINT16  phyLpa;\r
-+    UINT32  phyBase;\r
-+    UINT32  phyAddr;\r
-+\r
-+    phyBase = RT_PHYBASE(phyUnit);\r
-+    phyAddr = RT_PHYADDR(phyUnit);\r
-+\r
-+    phyLpa = phyRegRead(phyBase, phyAddr, AN_lpa);\r
-+\r
-+    if (phyLpa & (LPA_TXFD | LPA_TX)) {\r
-+        return TRUE;\r
-+    } else {\r
-+        return FALSE;\r
-+    }\r
-+}\r
-+\r
-+/*****************************************************************************\r
-+*\r
-+* rt_phyCheckStatusChange -- checks for significant changes in PHY state.\r
-+*\r
-+* A "significant change" is:\r
-+*     dropped link (e.g. ethernet cable unplugged) OR\r
-+*     autonegotiation completed + link (e.g. ethernet cable plugged in)\r
-+*\r
-+* On AR5311, there is a 1-to-1 mapping of ethernet units to PHYs.\r
-+* When a PHY is plugged in, phyLinkGained is called.\r
-+* When a PHY is unplugged, phyLinkLost is called.\r
-+*/\r
-+void\r
-+rt_phyCheckStatusChange(int ethUnit)\r
-+{\r
-+    UINT16          phyHwStatus;\r
-+    rtPhyInfo_t     *lastStatus = &rtPhyInfo[ethUnit];\r
-+    UINT32          phyBase;\r
-+    UINT32          phyAddr;\r
-+\r
-+    phyBase = RT_PHYBASE(ethUnit);\r
-+    phyAddr = RT_PHYADDR(ethUnit);\r
-+\r
-+    phyHwStatus = phyRegRead(phyBase, phyAddr, GEN_sts);\r
-+\r
-+    if (lastStatus->phyAlive) { /* last known status was ALIVE */\r
-+        /* See if we've lost link */\r
-+        if (!(phyHwStatus & LINK)) {\r
-+            RT_PRINT(RT_DEBUG_PHYCHANGE,("\nethmac%d link down\n", ethUnit));\r
-+            lastStatus->phyAlive = FALSE;\r
-+            phyLinkLost(ethUnit);\r
-+        }\r
-+    } else { /* last known status was DEAD */\r
-+        /* Check for AN complete */\r
-+        if ((phyHwStatus & (AUTOCMPLT | LINK)) == (AUTOCMPLT | LINK)) {\r
-+            RT_PRINT(RT_DEBUG_PHYCHANGE,("\nethmac%d link up\n", ethUnit));\r
-+            lastStatus->phyAlive = TRUE;\r
-+            phyLinkGained(ethUnit);\r
-+        }\r
-+    }\r
-+}\r
-+\r
-+#if DEBUG\r
-+\r
-+/* Define the PHY registers of interest for a phyShow command */\r
-+struct rtRegisterTable_s {\r
-+    UINT32 regNum;\r
-+    char  *regIdString;\r
-+} rtRegisterTable[] =\r
-+{\r
-+    {GEN_ctl,    "Basic Mode Control (GEN_ctl)    "},\r
-+    {GEN_sts,    "Basic Mode Status (GEN_sts)     "},\r
-+    {GEN_id_hi,  "PHY Identifier 1 (GET_id_hi)    "},\r
-+    {GEN_id_lo,  "PHY Identifier 2 (GET_id_lo)    "},\r
-+    {AN_adv,     "Auto-Neg Advertisement (AN_adv) "},\r
-+    {AN_lpa,     "Auto-Neg Link Partner Ability   "},\r
-+    {AN_exp,     "Auto-Neg Expansion              "},\r
-+};\r
-+\r
-+int rtNumRegs = sizeof(rtRegisterTable) / sizeof(rtRegisterTable[0]);\r
-+\r
-+/*\r
-+ * Dump the state of a PHY.\r
-+ */\r
-+void\r
-+rt_phyShow(int phyUnit)\r
-+{\r
-+    int i;\r
-+    UINT16  value;\r
-+    UINT32  phyBase;\r
-+    UINT32  phyAddr;\r
-+\r
-+    phyBase = RT_PHYBASE(phyUnit);\r
-+    phyAddr = RT_PHYADDR(phyUnit);\r
-+\r
-+    printf("PHY state for ethphy%d\n", phyUnit);\r
-+\r
-+    for (i=0; i<rtNumRegs; i++) {\r
-+\r
-+        value = phyRegRead(phyBase, phyAddr, rtRegisterTable[i].regNum);\r
-+\r
-+        printf("Reg %02d (0x%02x) %s = 0x%08x\n",\r
-+            rtRegisterTable[i].regNum, rtRegisterTable[i].regNum,\r
-+            rtRegisterTable[i].regIdString, value);\r
-+    }\r
-+}\r
-+\r
-+/*\r
-+ * Modify the value of a PHY register.\r
-+ * This makes it a bit easier to modify PHY values during debug.\r
-+ */\r
-+void\r
-+rt_phySet(int phyUnit, UINT32 regnum, UINT32 value)\r
-+{\r
-+    UINT32  phyBase;\r
-+    UINT32  phyAddr;\r
-+\r
-+    phyBase = RT_PHYBASE(phyUnit);\r
-+    phyAddr = RT_PHYADDR(phyUnit);\r
-+\r
-+    phyRegWrite(phyBase, phyAddr, regnum, value);\r
-+}\r
-+#endif\r
-diff -urN linux-2.4.32.new/arch/mips/ar531x/rtPhy.h linux-2.4.32.new-eth/arch/mips/ar531x/rtPhy.h\r
---- linux-2.4.32.new/arch/mips/ar531x/rtPhy.h  1970-01-01 01:00:00.000000000 +0100\r
-+++ linux-2.4.32.new-eth/arch/mips/ar531x/rtPhy.h      2005-12-25 11:54:46.089422728 +0000\r
-@@ -0,0 +1,50 @@\r
-+/*\r
-+ * This file is subject to the terms and conditions of the GNU General Public\r
-+ * License.  See the file "COPYING" in the main directory of this archive\r
-+ * for more details.\r
-+ *\r
-+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.\r
-+ */\r
-+\r
-+/*\r
-+ * rtPhy.h - definitions for the ethernet PHY.\r
-+ * This code supports a simple 1-port ethernet phy, Realtek RTL8201BL,\r
-+ * and compatible PHYs, such as the Kendin KS8721B.\r
-+ * All definitions in this file are operating system independent!\r
-+ */\r
-+\r
-+#ifndef RTPHY_H\r
-+#define RTPHY_H\r
-+\r
-+/* MII Registers */\r
-+\r
-+#define       GEN_ctl         00\r
-+#define       GEN_sts         01\r
-+#define       GEN_id_hi       02\r
-+#define       GEN_id_lo       03\r
-+#define       AN_adv          04\r
-+#define       AN_lpa          05\r
-+#define       AN_exp          06\r
-+\r
-+/* GEN_ctl */ \r
-+#define       PHY_SW_RST      0x8000\r
-+#define       LOOPBACK        0x4000\r
-+#define       SPEED           0x2000  /* 100 Mbit/s */\r
-+#define       AUTONEGENA      0x1000\r
-+#define       DUPLEX          0x0100  /* Duplex mode */\r
-+\r
-+              \r
-+/* GEN_sts */\r
-+#define       AUTOCMPLT       0x0020  /* Autonegotiation completed */\r
-+#define       LINK            0x0004  /* Link status */\r
-+\r
-+/* GEN_ids */\r
-+#define RT_PHY_ID1_EXPECTATION  0x22\r
-+\r
-+/* AN_lpa */\r
-+#define       LPA_TXFD        0x0100  /* Link partner supports 100 TX Full Duplex */\r
-+#define       LPA_TX          0x0080  /* Link partner supports 100 TX Half Duplex */\r
-+#define       LPA_10FD        0x0040  /* Link partner supports 10 BT Full Duplex */\r
-+#define       LPA_10          0x0020  /* Link partner supports 10 BT Half Duplex */\r
-+\r
-+#endif /* RTPHY_H */\r
index 62dd21b97aef95f03682ddc70439b68c68995e9b..29a4e89e1786c6a4a28250319d5d4ac220246760 100644 (file)
@@ -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
index ea2197c8659ffac4a909985d2ae198a62d14a4dd..5432055c3523c7d11c906753c52f9c5174acaec9 100644 (file)
@@ -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)/