From: Imre Kaloz Date: Mon, 19 Jun 2006 11:17:46 +0000 (+0000) Subject: fix the Aruba ethernet drivers for 2.6.17 X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=77f666e354c517dad0368fcd654c3a7081f1c34a;p=openwrt%2Fstaging%2Fnbd.git fix the Aruba ethernet drivers for 2.6.17 SVN-Revision: 4006 --- diff --git a/openwrt/target/linux/aruba-2.6/patches/000-aruba.patch b/openwrt/target/linux/aruba-2.6/patches/000-aruba.patch index 52fb3bab0a..83f023cfe0 100644 --- a/openwrt/target/linux/aruba-2.6/patches/000-aruba.patch +++ b/openwrt/target/linux/aruba-2.6/patches/000-aruba.patch @@ -1200,7 +1200,7 @@ diff -Nur linux-2.6.17/drivers/net/natsemi.c linux-2.6.17-owrt/drivers/net/natse diff -Nur linux-2.6.17/drivers/net/rc32434_eth.c linux-2.6.17-owrt/drivers/net/rc32434_eth.c --- linux-2.6.17/drivers/net/rc32434_eth.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.17-owrt/drivers/net/rc32434_eth.c 2006-06-18 12:44:28.000000000 +0200 -@@ -0,0 +1,1268 @@ +@@ -0,0 +1,1273 @@ +/************************************************************************** + * + * BRIEF MODULE DESCRIPTION @@ -1242,6 +1242,7 @@ diff -Nur linux-2.6.17/drivers/net/rc32434_eth.c linux-2.6.17-owrt/drivers/net/r + */ + +#include ++#include +#include +#include +#include @@ -1287,7 +1288,11 @@ diff -Nur linux-2.6.17/drivers/net/rc32434_eth.c linux-2.6.17-owrt/drivers/net/r +#define MII_CLOCK 1250000 /* no more than 2.5MHz */ +static char mac0[18] = "08:00:06:05:40:01"; + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) ++module_param_string(mac0, mac0, 18, 0); ++#else +MODULE_PARM(mac0, "c18"); ++#endif +MODULE_PARM_DESC(mac0, "MAC address for RC32434 ethernet0"); + +static struct rc32434_if_t { diff --git a/openwrt/target/linux/aruba-2.6/patches/010-ar2313_enet.patch b/openwrt/target/linux/aruba-2.6/patches/010-ar2313_enet.patch index 01fe26fac5..b5ef4d324a 100644 --- a/openwrt/target/linux/aruba-2.6/patches/010-ar2313_enet.patch +++ b/openwrt/target/linux/aruba-2.6/patches/010-ar2313_enet.patch @@ -1,1339 +1,832 @@ -diff -urN linux.old/drivers/net/Kconfig linux.net/drivers/net/Kconfig ---- linux.old/drivers/net/Kconfig 2006-01-21 20:15:08.279272000 +0100 -+++ linux.net/drivers/net/Kconfig 2006-01-30 01:18:34.910315000 +0100 -@@ -176,6 +176,13 @@ - - source "drivers/net/arm/Kconfig" - -+ -+config AR2313 -+ tristate "AR2313 Ethernet support" -+ depends on NET_ETHERNET && MACH_ARUBA -+ help -+ Support for the AR2313 Ethernet part on Aruba AP60/61 -+ - config IDT_RC32434_ETH - tristate "IDT RC32434 Local Ethernet support" - depends on NET_ETHERNET -diff -urN linux.old/drivers/net/Makefile linux.net/drivers/net/Makefile ---- linux.old/drivers/net/Makefile 2006-01-21 20:15:08.383226000 +0100 -+++ linux.net/drivers/net/Makefile 2006-01-30 01:18:34.914315250 +0100 -@@ -35,6 +35,7 @@ - - obj-$(CONFIG_OAKNET) += oaknet.o 8390.o - -+obj-$(CONFIG_AR2313) += ar2313.o - obj-$(CONFIG_IDT_RC32434_ETH) += rc32434_eth.o - obj-$(CONFIG_DGRS) += dgrs.o - obj-$(CONFIG_VORTEX) += 3c59x.o -diff -urN linux.old/drivers/net/ar2313/ar2313.h linux.net/drivers/net/ar2313/ar2313.h ---- linux.old/drivers/net/ar2313/ar2313.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.net/drivers/net/ar2313/ar2313.h 2006-01-25 00:35:55.000000000 +0100 -@@ -0,0 +1,190 @@ -+#ifndef _AR2313_H_ -+#define _AR2313_H_ +diff -Nur linux-2.6.17/drivers/net/ar2313/ar2313.c linux-2.6.17-owrt/drivers/net/ar2313/ar2313.c +--- linux-2.6.17/drivers/net/ar2313/ar2313.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.17-owrt/drivers/net/ar2313/ar2313.c 2006-06-19 12:57:27.000000000 +0200 +@@ -0,0 +1,1649 @@ ++/* ++ * ar2313.c: Linux driver for the Atheros AR2313 Ethernet device. ++ * ++ * Copyright 2004 by Sameer Dekate, . ++ * Copyright (C) 2006 Imre Kaloz ++ * ++ * Thanks to Atheros for providing hardware and documentation ++ * enabling me to write this driver. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * Additional credits: ++ * This code is taken from John Taylor's Sibyte driver and then ++ * modified for the AR2313. ++ */ + +#include -+#include -+#include "platform.h" -+ -+extern unsigned long mips_machtype; -+ -+#undef ETHERNET_BASE -+#define ETHERNET_BASE ar_eth_base -+#define ETHERNET_SIZE 0x00100000 -+#define ETHERNET_MACS 2 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+#undef DMA_BASE -+#define DMA_BASE ar_dma_base -+#define DMA_SIZE 0x00100000 ++#include ++#include + ++#include ++#include ++#include ++#include ++#include ++#include + -+/* -+ * probe link timer - 5 secs -+ */ -+#define LINK_TIMER (5*HZ) ++extern char *getenv(char *e); + -+/* -+ * Interrupt register base address -+ */ -+#define INTERRUPT_BASE PHYS_TO_K1(ar_int_base) + -+/* -+ * Reset Register -+ */ -+#define AR531X_RESET (AR531X_RESETTMR + 0x0020) -+#define RESET_SYSTEM 0x00000001 /* cold reset full system */ -+#define RESET_PROC 0x00000002 /* cold reset MIPS core */ -+#define RESET_WLAN0 0x00000004 /* cold reset WLAN MAC and BB */ -+#define RESET_EPHY0 0x00000008 /* cold reset ENET0 phy */ -+#define RESET_EPHY1 0x00000010 /* cold reset ENET1 phy */ -+#define RESET_ENET0 0x00000020 /* cold reset ENET0 mac */ -+#define RESET_ENET1 0x00000040 /* cold reset ENET1 mac */ ++#undef INDEX_DEBUG ++#define DEBUG 0 ++#define DEBUG_TX 0 ++#define DEBUG_RX 0 ++#define DEBUG_INT 0 ++#define DEBUG_MC 0 ++#define DEBUG_ERR 1 + -+#define IS_DMA_TX_INT(X) (((X) & (DMA_STATUS_TI)) != 0) -+#define IS_DMA_RX_INT(X) (((X) & (DMA_STATUS_RI)) != 0) -+#define IS_DRIVER_OWNED(X) (((X) & (DMA_TX_OWN)) == 0) ++#ifndef __exit ++#define __exit ++#endif + -+#ifndef K1_TO_PHYS -+// hack -+#define K1_TO_PHYS(x) (((unsigned int)(x)) & 0x1FFFFFFF) /* kseg1 to physical */ ++#ifndef min ++#define min(a,b) (((a)<(b))?(a):(b)) +#endif + -+#ifndef PHYS_TO_K1 -+// hack -+#define PHYS_TO_K1(x) (((unsigned int)(x)) | 0xA0000000) /* physical to kseg1 */ ++#ifndef SMP_CACHE_BYTES ++#define SMP_CACHE_BYTES L1_CACHE_BYTES +#endif + -+#define AR2313_TX_TIMEOUT (HZ/4) ++#ifndef SET_MODULE_OWNER ++#define SET_MODULE_OWNER(dev) {do{} while(0);} ++#define AR2313_MOD_INC_USE_COUNT MOD_INC_USE_COUNT ++#define AR2313_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT ++#else ++#define AR2313_MOD_INC_USE_COUNT {do{} while(0);} ++#define AR2313_MOD_DEC_USE_COUNT {do{} while(0);} ++#endif + -+/* -+ * Rings -+ */ -+#define DSC_RING_ENTRIES_SIZE (AR2313_DESCR_ENTRIES * sizeof(struct desc)) -+#define DSC_NEXT(idx) ((idx + 1) & (AR2313_DESCR_ENTRIES - 1)) ++#define PHYSADDR(a) ((_ACAST32_ (a)) & 0x1fffffff) + -+static inline int tx_space (u32 csm, u32 prd) -+{ -+ return (csm - prd - 1) & (AR2313_DESCR_ENTRIES - 1); -+} ++static char ethaddr[18] = "00:00:00:00:00:00"; ++static char ifname[5] = "bond"; + -+#if MAX_SKB_FRAGS -+#define TX_RESERVED (MAX_SKB_FRAGS+1) /* +1 for message header */ -+#define tx_ring_full(csm, prd) (tx_space(csm, prd) <= TX_RESERVED) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) ++module_param_string(ethaddr, ethaddr, 18, 0); ++module_param_string(ifname, ifname, 5, 0); +#else -+#define tx_ring_full 0 ++MODULE_PARM(ethaddr, "c18"); ++MODULE_PARM(ifname, "c5"); +#endif + -+#define AR2313_MBGET 2 -+#define AR2313_MBSET 3 -+#define AR2313_PCI_RECONFIG 4 -+#define AR2313_PCI_DUMP 5 -+#define AR2313_TEST_PANIC 6 -+#define AR2313_TEST_NULLPTR 7 -+#define AR2313_READ_DATA 8 -+#define AR2313_WRITE_DATA 9 -+#define AR2313_GET_VERSION 10 -+#define AR2313_TEST_HANG 11 -+#define AR2313_SYNC 12 ++#define AR2313_MBOX_SET_BIT 0x8 + ++#define BOARD_IDX_STATIC 0 ++#define BOARD_IDX_OVERFLOW -1 + -+struct ar2313_cmd { -+ u32 cmd; -+ u32 address; /* virtual address of image */ -+ u32 length; /* size of image to download */ -+ u32 mailbox; /* mailbox to get/set */ -+ u32 data[2]; /* contents of mailbox to read/write */ -+}; ++/* margot includes */ ++#include + ++#include "ar2313_msg.h" ++#include "platform.h" ++#include "dma.h" ++#include "ar2313.h" + +/* -+ * Struct private for the Sibyte. ++ * New interrupt handler strategy: + * -+ * Elements are grouped so variables used by the tx handling goes -+ * together, and will go into the same cache lines etc. in order to -+ * avoid cache line contention between the rx and tx handling on SMP. ++ * An old interrupt handler worked using the traditional method of ++ * replacing an skbuff with a new one when a packet arrives. However ++ * the rx rings do not need to contain a static number of buffer ++ * descriptors, thus it makes sense to move the memory allocation out ++ * of the main interrupt handler and do it in a bottom half handler ++ * and only allocate new buffers when the number of buffers in the ++ * ring is below a certain threshold. In order to avoid starving the ++ * NIC under heavy load it is however necessary to force allocation ++ * when hitting a minimum threshold. The strategy for alloction is as ++ * follows: + * -+ * Frequently accessed variables are put at the beginning of the -+ * struct to help the compiler generate better/shorter code. ++ * RX_LOW_BUF_THRES - allocate buffers in the bottom half ++ * RX_PANIC_LOW_THRES - we are very low on buffers, allocate ++ * the buffers in the interrupt handler ++ * RX_RING_THRES - maximum number of buffers in the rx ring ++ * ++ * One advantagous side effect of this allocation approach is that the ++ * entire rx processing can be done without holding any spin lock ++ * since the rx rings and registers are totally independent of the tx ++ * ring and its registers. This of course includes the kmalloc's of ++ * new skb's. Thus start_xmit can run in parallel with rx processing ++ * and the memory allocation on SMP systems. ++ * ++ * Note that running the skb reallocation in a bottom half opens up ++ * another can of races which needs to be handled properly. In ++ * particular it can happen that the interrupt handler tries to run ++ * the reallocation while the bottom half is either running on another ++ * CPU or was interrupted on the same CPU. To get around this the ++ * driver uses bitops to prevent the reallocation routines from being ++ * reentered. ++ * ++ * TX handling can also be done without holding any spin lock, wheee ++ * this is fun! since tx_csm is only written to by the interrupt ++ * handler. + */ -+struct ar2313_private -+{ -+ int version; -+ u32 mb[2]; -+ -+ volatile ETHERNET_STRUCT *eth_regs; -+ volatile DMA *dma_regs; -+ volatile u32 *int_regs; -+ -+ spinlock_t lock; /* Serialise access to device */ + -+ /* -+ * RX and TX descriptors, must be adjacent -+ */ -+ ar2313_descr_t *rx_ring; -+ ar2313_descr_t *tx_ring; ++/* ++ * Threshold values for RX buffer allocation - the low water marks for ++ * when to start refilling the rings are set to 75% of the ring ++ * sizes. It seems to make sense to refill the rings entirely from the ++ * intrrupt handler once it gets below the panic threshold, that way ++ * we don't risk that the refilling is moved to another CPU when the ++ * one running the interrupt handler just got the slab code hot in its ++ * cache. ++ */ ++#define RX_RING_SIZE AR2313_DESCR_ENTRIES ++#define RX_PANIC_THRES (RX_RING_SIZE/4) ++#define RX_LOW_THRES ((3*RX_RING_SIZE)/4) ++#define CRC_LEN 4 ++#define RX_OFFSET 2 + ++#define AR2313_BUFSIZE (AR2313_MTU + ETH_HLEN + CRC_LEN + RX_OFFSET) + -+ struct sk_buff **rx_skb; -+ struct sk_buff **tx_skb; ++#ifdef MODULE ++MODULE_AUTHOR("Sameer Dekate"); ++MODULE_DESCRIPTION("AR2313 Ethernet driver"); ++#endif + -+ /* -+ * RX elements -+ */ -+ u32 rx_skbprd; -+ u32 cur_rx; ++#if DEBUG ++static char version[] __initdata = ++ "ar2313.c: v0.02 2006/06/19 sdekate@arubanetworks.com\n"; ++#endif /* DEBUG */ + -+ /* -+ * TX elements -+ */ -+ u32 tx_prd; -+ u32 tx_csm; ++#define virt_to_phys(x) ((u32)(x) & 0x1fffffff) + -+ /* -+ * Misc elements -+ */ -+ int board_idx; -+ char name[48]; -+ struct net_device_stats stats; -+ struct { -+ u32 address; -+ u32 length; -+ char *mapping; -+ } desc; -+ -+ -+ struct timer_list link_timer; -+ unsigned short phy; /* merlot phy = 1, samsung phy = 0x1f */ -+ unsigned short mac; -+ unsigned short link; /* 0 - link down, 1 - link up */ -+ u16 phyData; -+ -+ struct tasklet_struct rx_tasklet; -+ int unloading; -+}; -+ -+ -+/* -+ * Prototypes -+ */ -+static int ar2313_init(struct net_device *dev); ++// prototypes ++static short armiiread(short phy, short reg); ++static void armiiwrite(short phy, short reg, short data); +#ifdef TX_TIMEOUT +static void ar2313_tx_timeout(struct net_device *dev); +#endif -+#if 0 ++static void ar2313_halt(struct net_device *dev); ++static void rx_tasklet_func(unsigned long data); +static void ar2313_multicast_list(struct net_device *dev); -+#endif -+static int ar2313_restart(struct net_device *dev); -+#if DEBUG -+static void ar2313_dump_regs(struct net_device *dev); -+#endif -+static void ar2313_load_rx_ring(struct net_device *dev, int bufs); -+static irqreturn_t ar2313_interrupt(int irq, void *dev_id, struct pt_regs *regs); -+static int ar2313_open(struct net_device *dev); -+static int ar2313_start_xmit(struct sk_buff *skb, struct net_device *dev); -+static int ar2313_close(struct net_device *dev); -+static int ar2313_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); -+static void ar2313_init_cleanup(struct net_device *dev); -+static int ar2313_setup_timer(struct net_device *dev); -+static void ar2313_link_timer_fn(unsigned long data); -+static void ar2313_check_link(struct net_device *dev); -+static struct net_device_stats *ar2313_get_stats(struct net_device *dev); -+#endif /* _AR2313_H_ */ -diff -urN linux.old/drivers/net/ar2313/ar2313_msg.h linux.net/drivers/net/ar2313/ar2313_msg.h ---- linux.old/drivers/net/ar2313/ar2313_msg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.net/drivers/net/ar2313/ar2313_msg.h 2006-01-24 22:57:25.000000000 +0100 -@@ -0,0 +1,17 @@ -+#ifndef _AR2313_MSG_H_ -+#define _AR2313_MSG_H_ -+ -+#define AR2313_MTU 1692 -+#define AR2313_PRIOS 1 -+#define AR2313_QUEUES (2*AR2313_PRIOS) + -+#define AR2313_DESCR_ENTRIES 64 ++static struct net_device *root_dev; ++static int probed __initdata = 0; ++static unsigned long ar_eth_base; ++static unsigned long ar_dma_base; ++static unsigned long ar_int_base; ++static unsigned long ar_int_mac_mask; ++static unsigned long ar_int_phy_mask; + -+typedef struct { -+ volatile unsigned int status; // OWN, Device control and status. -+ volatile unsigned int devcs; // pkt Control bits + Length -+ volatile unsigned int addr; // Current Address. -+ volatile unsigned int descr; // Next descriptor in chain. -+} ar2313_descr_t; ++#ifndef ERR ++#define ERR(fmt, args...) printk("%s: " fmt, __func__, ##args) ++#endif + -+#endif /* _AR2313_MSG_H_ */ -diff -urN linux.old/drivers/net/ar2313/dma.h linux.net/drivers/net/ar2313/dma.h ---- linux.old/drivers/net/ar2313/dma.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.net/drivers/net/ar2313/dma.h 2006-01-24 22:58:45.000000000 +0100 -@@ -0,0 +1,135 @@ -+#ifndef __ARUBA_DMA_H__ -+#define __ARUBA_DMA_H__ ++static int parse_mac_addr(struct net_device *dev, char* macstr){ ++ int i, j; ++ unsigned char result, value; ++ ++ for (i=0; i<6; i++) { ++ result = 0; ++ if (i != 5 && *(macstr+2) != ':') { ++ ERR("invalid mac address format: %d %c\n", ++ i, *(macstr+2)); ++ return -EINVAL; ++ } ++ for (j=0; j<2; j++) { ++ if (isxdigit(*macstr) && (value = isdigit(*macstr) ? *macstr-'0' : ++ toupper(*macstr)-'A'+10) < 16) ++ { ++ result = result*16 + value; ++ macstr++; ++ } ++ else { ++ ERR("invalid mac address " ++ "character: %c\n", *macstr); ++ return -EINVAL; ++ } ++ } ++ ++ macstr++; ++ dev->dev_addr[i] = result; ++ } ++ ++ return 0; ++} + -+/******************************************************************************* -+ * -+ * Copyright 2002 Integrated Device Technology, Inc. -+ * All rights reserved. -+ * -+ * DMA register definition. -+ * -+ * File : $Id: dma.h,v 1.3 2002/06/06 18:34:03 astichte Exp $ -+ * -+ * Author : ryan.holmQVist@idt.com -+ * Date : 20011005 -+ * Update : -+ * $Log: dma.h,v $ -+ * Revision 1.3 2002/06/06 18:34:03 astichte -+ * Added XXX_PhysicalAddress and XXX_VirtualAddress -+ * -+ * Revision 1.2 2002/06/05 18:30:46 astichte -+ * Removed IDTField -+ * -+ * Revision 1.1 2002/05/29 17:33:21 sysarch -+ * jba File moved from vcode/include/idt/acacia -+ * -+ * -+ ******************************************************************************/ + -+#define AR_BIT(x) (1 << (x)) -+#define DMA_RX_ERR_CRC AR_BIT(1) -+#define DMA_RX_ERR_DRIB AR_BIT(2) -+#define DMA_RX_ERR_MII AR_BIT(3) -+#define DMA_RX_EV2 AR_BIT(5) -+#define DMA_RX_ERR_COL AR_BIT(6) -+#define DMA_RX_LONG AR_BIT(7) -+#define DMA_RX_LS AR_BIT(8) /* last descriptor */ -+#define DMA_RX_FS AR_BIT(9) /* first descriptor */ -+#define DMA_RX_MF AR_BIT(10) /* multicast frame */ -+#define DMA_RX_ERR_RUNT AR_BIT(11) /* runt frame */ -+#define DMA_RX_ERR_LENGTH AR_BIT(12) /* length error */ -+#define DMA_RX_ERR_DESC AR_BIT(14) /* descriptor error */ -+#define DMA_RX_ERROR AR_BIT(15) /* error summary */ -+#define DMA_RX_LEN_MASK 0x3fff0000 -+#define DMA_RX_LEN_SHIFT 16 -+#define DMA_RX_FILT AR_BIT(30) -+#define DMA_RX_OWN AR_BIT(31) /* desc owned by DMA controller */ ++int __init ar2313_probe(void) ++{ ++ struct net_device *dev; ++ struct ar2313_private *sp; ++ int version_disp; ++ char name[64] ; + -+#define DMA_RX1_BSIZE_MASK 0x000007ff -+#define DMA_RX1_BSIZE_SHIFT 0 -+#define DMA_RX1_CHAINED AR_BIT(24) -+#define DMA_RX1_RER AR_BIT(25) ++ if (probed) ++ return -ENODEV; ++ probed++; + -+#define DMA_TX_ERR_UNDER AR_BIT(1) /* underflow error */ -+#define DMA_TX_ERR_DEFER AR_BIT(2) /* excessive deferral */ -+#define DMA_TX_COL_MASK 0x78 -+#define DMA_TX_COL_SHIFT 3 -+#define DMA_TX_ERR_HB AR_BIT(7) /* hearbeat failure */ -+#define DMA_TX_ERR_COL AR_BIT(8) /* excessive collisions */ -+#define DMA_TX_ERR_LATE AR_BIT(9) /* late collision */ -+#define DMA_TX_ERR_LINK AR_BIT(10) /* no carrier */ -+#define DMA_TX_ERR_LOSS AR_BIT(11) /* loss of carrier */ -+#define DMA_TX_ERR_JABBER AR_BIT(14) /* transmit jabber timeout */ -+#define DMA_TX_ERROR AR_BIT(15) /* frame aborted */ -+#define DMA_TX_OWN AR_BIT(31) /* descr owned by DMA controller */ ++ version_disp = 0; ++ sprintf(name, "%s%%d", ifname) ; ++ dev = alloc_etherdev(sizeof(struct ar2313_private)); + -+#define DMA_TX1_BSIZE_MASK 0x000007ff -+#define DMA_TX1_BSIZE_SHIFT 0 -+#define DMA_TX1_CHAINED AR_BIT(24) /* chained descriptors */ -+#define DMA_TX1_TER AR_BIT(25) /* transmit end of ring */ -+#define DMA_TX1_FS AR_BIT(29) /* first segment */ -+#define DMA_TX1_LS AR_BIT(30) /* last segment */ -+#define DMA_TX1_IC AR_BIT(31) /* interrupt on completion */ ++ if (dev == NULL) { ++ printk(KERN_ERR "ar2313: Unable to allocate net_device structure!\n"); ++ return -ENOMEM; ++ } + -+#define RCVPKT_LENGTH(X) (X >> 16) /* Received pkt Length */ ++ SET_MODULE_OWNER(dev); + -+#define MAC_CONTROL_RE AR_BIT(2) /* receive enable */ -+#define MAC_CONTROL_TE AR_BIT(3) /* transmit enable */ -+#define MAC_CONTROL_DC AR_BIT(5) /* Deferral check*/ -+#define MAC_CONTROL_ASTP AR_BIT(8) /* Auto pad strip */ -+#define MAC_CONTROL_DRTY AR_BIT(10) /* Disable retry */ -+#define MAC_CONTROL_DBF AR_BIT(11) /* Disable bcast frames */ -+#define MAC_CONTROL_LCC AR_BIT(12) /* late collision ctrl */ -+#define MAC_CONTROL_HP AR_BIT(13) /* Hash Perfect filtering */ -+#define MAC_CONTROL_HASH AR_BIT(14) /* Unicast hash filtering */ -+#define MAC_CONTROL_HO AR_BIT(15) /* Hash only filtering */ -+#define MAC_CONTROL_PB AR_BIT(16) /* Pass Bad frames */ -+#define MAC_CONTROL_IF AR_BIT(17) /* Inverse filtering */ -+#define MAC_CONTROL_PR AR_BIT(18) /* promiscuous mode (valid frames only) */ -+#define MAC_CONTROL_PM AR_BIT(19) /* pass multicast */ -+#define MAC_CONTROL_F AR_BIT(20) /* full-duplex */ -+#define MAC_CONTROL_DRO AR_BIT(23) /* Disable Receive Own */ -+#define MAC_CONTROL_HBD AR_BIT(28) /* heart-beat disabled (MUST BE SET) */ -+#define MAC_CONTROL_BLE AR_BIT(30) /* big endian mode */ -+#define MAC_CONTROL_RA AR_BIT(31) /* receive all (valid and invalid frames) */ ++ sp = dev->priv; + -+#define MII_ADDR_BUSY AR_BIT(0) -+#define MII_ADDR_WRITE AR_BIT(1) -+#define MII_ADDR_REG_SHIFT 6 -+#define MII_ADDR_PHY_SHIFT 11 -+#define MII_DATA_SHIFT 0 ++ sp->link = 0; ++ switch (mips_machtype) { ++ case MACH_ARUBA_AP60: ++ ar_eth_base = 0xb8100000; ++ ar_dma_base = ar_eth_base + 0x1000; ++ ar_int_base = 0x1C003020; ++ ar_int_mac_mask = RESET_ENET0|RESET_ENET1; ++ ar_int_phy_mask = RESET_EPHY0|RESET_EPHY1; ++ sp->mac = 1; ++ sp->phy = 1; ++ dev->irq = 4; ++ break; + -+#define FLOW_CONTROL_FCE AR_BIT(1) ++ case MACH_ARUBA_AP40: ++ ar_eth_base = 0xb0500000; ++ ar_dma_base = ar_eth_base + 0x1000; ++ ar_int_base = 0x11000004; ++ ar_int_mac_mask = 0x800; ++ ar_int_phy_mask = 0x400; ++ sp->mac = 0; ++ sp->phy = 1; ++ dev->irq = 4; ++ break; + -+#define DMA_BUS_MODE_SWR AR_BIT(0) /* software reset */ -+#define DMA_BUS_MODE_BLE AR_BIT(7) /* big endian mode */ -+#define DMA_BUS_MODE_PBL_SHIFT 8 /* programmable burst length 32 */ -+#define DMA_BUS_MODE_DBO AR_BIT(20) /* big-endian descriptors */ ++ case MACH_ARUBA_AP65: ++ ar_eth_base = 0xb8100000; ++ ar_dma_base = ar_eth_base + 0x1000; ++ ar_int_base = 0x1C003020; ++ ar_int_mac_mask = RESET_ENET0|RESET_ENET1; ++ ar_int_phy_mask = RESET_EPHY0|RESET_EPHY1; ++ sp->mac = 0; ++#if 0 ++ // commented out, for now + -+#define DMA_STATUS_TI AR_BIT(0) /* transmit interrupt */ -+#define DMA_STATUS_TPS AR_BIT(1) /* transmit process stopped */ -+#define DMA_STATUS_TU AR_BIT(2) /* transmit buffer unavailable */ -+#define DMA_STATUS_TJT AR_BIT(3) /* transmit buffer timeout */ -+#define DMA_STATUS_UNF AR_BIT(5) /* transmit underflow */ -+#define DMA_STATUS_RI AR_BIT(6) /* receive interrupt */ -+#define DMA_STATUS_RU AR_BIT(7) /* receive buffer unavailable */ -+#define DMA_STATUS_RPS AR_BIT(8) /* receive process stopped */ -+#define DMA_STATUS_ETI AR_BIT(10) /* early transmit interrupt */ -+#define DMA_STATUS_FBE AR_BIT(13) /* fatal bus interrupt */ -+#define DMA_STATUS_ERI AR_BIT(14) /* early receive interrupt */ -+#define DMA_STATUS_AIS AR_BIT(15) /* abnormal interrupt summary */ -+#define DMA_STATUS_NIS AR_BIT(16) /* normal interrupt summary */ -+#define DMA_STATUS_RS_SHIFT 17 /* receive process state */ -+#define DMA_STATUS_TS_SHIFT 20 /* transmit process state */ -+#define DMA_STATUS_EB_SHIFT 23 /* error bits */ -+ -+#define DMA_CONTROL_SR AR_BIT(1) /* start receive */ -+#define DMA_CONTROL_ST AR_BIT(13) /* start transmit */ -+#define DMA_CONTROL_SF AR_BIT(21) /* store and forward */ -+ -+#endif // __ARUBA_DMA_H__ ++ if (mips_machtype == MACH_ARUBA_SAMSUNG) { ++ sp->phy = 0x1f; ++ } else { ++ sp->phy = 1; ++ } ++#else ++ sp->phy = 1; ++#endif ++ dev->irq = 3; ++ break; + ++ default: ++ printk("%s: unsupported mips_machtype=0x%lx\n", ++ __FUNCTION__, mips_machtype) ; ++ return -ENODEV; ++ } + ++ spin_lock_init(&sp->lock); + ++ /* initialize func pointers */ ++ dev->open = &ar2313_open; ++ dev->stop = &ar2313_close; ++ dev->hard_start_xmit = &ar2313_start_xmit; + ++ dev->get_stats = &ar2313_get_stats; ++ dev->set_multicast_list = &ar2313_multicast_list; ++#ifdef TX_TIMEOUT ++ dev->tx_timeout = ar2313_tx_timeout; ++ dev->watchdog_timeo = AR2313_TX_TIMEOUT; ++#endif ++ dev->do_ioctl = &ar2313_ioctl; + -diff -urN linux.old/drivers/net/ar2313/platform.h linux.net/drivers/net/ar2313/platform.h ---- linux.old/drivers/net/ar2313/platform.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.net/drivers/net/ar2313/platform.h 2006-01-25 00:10:25.000000000 +0100 -@@ -0,0 +1,128 @@ -+/******************************************************************************** -+ Title: $Source: platform.h,v $ ++ // SAMEER: do we need this? ++ dev->features |= NETIF_F_SG | NETIF_F_HIGHDMA; + -+ Author: Dan Steinberg -+ Copyright Integrated Device Technology 2001 ++ tasklet_init(&sp->rx_tasklet, rx_tasklet_func, (unsigned long) dev); ++ tasklet_disable(&sp->rx_tasklet); + -+ Purpose: AR2313 Register/Bit Definitions -+ -+ Update: -+ $Log: platform.h,v $ -+ -+ Notes: See Merlot architecture spec for complete details. Note, all -+ addresses are virtual addresses in kseg1 (Uncached, Unmapped). -+ -+********************************************************************************/ ++ /* display version info if adapter is found */ ++ if (!version_disp) { ++ /* set display flag to TRUE so that */ ++ /* we only display this string ONCE */ ++ version_disp = 1; ++#if DEBUG ++ printk(version); ++#endif /* DEBUG */ ++ } + -+#ifndef PLATFORM_H -+#define PLATFORM_H ++ request_region(PHYSADDR(ETHERNET_BASE), ETHERNET_SIZE*ETHERNET_MACS, ++ "AR2313ENET"); + -+#define BIT(x) (1 << (x)) ++ sp->eth_regs = ioremap_nocache(PHYSADDR(ETHERNET_BASE + ETHERNET_SIZE*sp->mac), ++ sizeof(*sp->eth_regs)); ++ if (!sp->eth_regs) { ++ printk("Can't remap eth registers\n"); ++ return(-ENXIO); ++ } + -+#define RESET_BASE 0xBC003020 -+#define RESET_VALUE 0x00000001 ++ sp->dma_regs = ioremap_nocache(PHYSADDR(DMA_BASE + DMA_SIZE*sp->mac), ++ sizeof(*sp->dma_regs)); ++ dev->base_addr = (unsigned int) sp->dma_regs; ++ if (!sp->dma_regs) { ++ printk("Can't remap DMA registers\n"); ++ return(-ENXIO); ++ } + -+/******************************************************************** -+ * Device controller -+ ********************************************************************/ -+typedef struct { -+ volatile unsigned int flash0; -+} DEVICE; ++ sp->int_regs = ioremap_nocache(PHYSADDR(INTERRUPT_BASE), ++ sizeof(*sp->int_regs)); ++ if (!sp->int_regs) { ++ printk("Can't remap INTERRUPT registers\n"); ++ return(-ENXIO); ++ } + -+#define device (*((volatile DEVICE *) DEV_CTL_BASE)) ++ strncpy(sp->name, "Atheros AR2313", sizeof (sp->name) - 1); ++ sp->name [sizeof (sp->name) - 1] = '\0'; + -+// DDRC register -+#define DEV_WP (1<<26) ++ { ++ char mac[32]; ++ extern char *getenv(char *e); ++ unsigned char def_mac[6] = {0, 0x0b, 0x86, 0xba, 0xdb, 0xad}; ++ memset(mac, 0, 32); ++ memcpy(mac, getenv("ethaddr"), 17); ++ if (parse_mac_addr(dev, mac)){ ++ printk("%s: MAC address not found, using default\n", __func__); ++ memcpy(dev->dev_addr, def_mac, 6); ++ } ++ } + -+/******************************************************************** -+ * DDR controller -+ ********************************************************************/ -+typedef struct { -+ volatile unsigned int ddrc0; -+ volatile unsigned int ddrc1; -+ volatile unsigned int ddrrefresh; -+} DDR; ++ sp->board_idx = BOARD_IDX_STATIC; + -+#define ddr (*((volatile DDR *) DDR_BASE)) ++ if (ar2313_init(dev)) { ++ /* ++ * ar2313_init() calls ar2313_init_cleanup() on error. ++ */ ++ kfree(dev); ++ return -ENODEV; ++ } + -+// DDRC register -+#define DDRC_CS(i) ((i&0x3)<<0) -+#define DDRC_WE (1<<2) ++ if (register_netdev(dev)){ ++ printk("%s: register_netdev failed\n", __func__); ++ return -1; ++ } + -+/******************************************************************** -+ * Ethernet interfaces -+ ********************************************************************/ -+#define ETHERNET_BASE 0xB8200000 ++ printk("%s: %s: %02x:%02x:%02x:%02x:%02x:%02x, irq %d\n", ++ dev->name, sp->name, ++ dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], ++ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5], ++ dev->irq); + -+// -+// New Combo structure for Both Eth0 AND eth1 -+// -+typedef struct { -+ volatile unsigned int mac_control; /* 0x00 */ -+ volatile unsigned int mac_addr[2]; /* 0x04 - 0x08*/ -+ volatile unsigned int mcast_table[2]; /* 0x0c - 0x10 */ -+ volatile unsigned int mii_addr; /* 0x14 */ -+ volatile unsigned int mii_data; /* 0x18 */ -+ volatile unsigned int flow_control; /* 0x1c */ -+ volatile unsigned int vlan_tag; /* 0x20 */ -+ volatile unsigned int pad[7]; /* 0x24 - 0x3c */ -+ volatile unsigned int ucast_table[8]; /* 0x40-0x5c */ -+ -+} ETHERNET_STRUCT; ++ /* start link poll timer */ ++ ar2313_setup_timer(dev); + -+/******************************************************************** -+ * Interrupt controller -+ ********************************************************************/ ++ /* ++ * Register the device ++ */ ++ root_dev = dev; + -+typedef struct { -+ volatile unsigned int wdog_control; /* 0x08 */ -+ volatile unsigned int wdog_timer; /* 0x0c */ -+ volatile unsigned int misc_status; /* 0x10 */ -+ volatile unsigned int misc_mask; /* 0x14 */ -+ volatile unsigned int global_status; /* 0x18 */ -+ volatile unsigned int reserved; /* 0x1c */ -+ volatile unsigned int reset_control; /* 0x20 */ -+} INTERRUPT; ++ return 0; ++} + -+#define interrupt (*((volatile INTERRUPT *) INTERRUPT_BASE)) ++#if 0 ++static void ar2313_dump_regs(struct net_device *dev) ++{ ++ unsigned int *ptr, i; ++ struct ar2313_private *sp = (struct ar2313_private *)dev->priv; + -+#define INTERRUPT_MISC_TIMER BIT(0) -+#define INTERRUPT_MISC_AHBPROC BIT(1) -+#define INTERRUPT_MISC_AHBDMA BIT(2) -+#define INTERRUPT_MISC_GPIO BIT(3) -+#define INTERRUPT_MISC_UART BIT(4) -+#define INTERRUPT_MISC_UARTDMA BIT(5) -+#define INTERRUPT_MISC_WATCHDOG BIT(6) -+#define INTERRUPT_MISC_LOCAL BIT(7) ++ ptr = (unsigned int *)sp->eth_regs; ++ for(i=0; i< (sizeof(ETHERNET_STRUCT)/ sizeof(unsigned int)); i++, ptr++) { ++ printk("ENET: %08x = %08x\n", (int)ptr, *ptr); ++ } + -+#define INTERRUPT_GLOBAL_ETH BIT(2) -+#define INTERRUPT_GLOBAL_WLAN BIT(3) -+#define INTERRUPT_GLOBAL_MISC BIT(4) -+#define INTERRUPT_GLOBAL_ITIMER BIT(5) ++ ptr = (unsigned int *)sp->dma_regs; ++ for(i=0; i< (sizeof(DMA)/ sizeof(unsigned int)); i++, ptr++) { ++ printk("DMA: %08x = %08x\n", (int)ptr, *ptr); ++ } + -+/******************************************************************** -+ * DMA controller -+ ********************************************************************/ -+#define DMA_BASE 0xB8201000 ++ ptr = (unsigned int *)sp->int_regs; ++ for(i=0; i< (sizeof(INTERRUPT)/ sizeof(unsigned int)); i++, ptr++){ ++ printk("INT: %08x = %08x\n", (int)ptr, *ptr); ++ } + -+typedef struct { -+ volatile unsigned int bus_mode; /* 0x00 (CSR0) */ -+ volatile unsigned int xmt_poll; /* 0x04 (CSR1) */ -+ volatile unsigned int rcv_poll; /* 0x08 (CSR2) */ -+ volatile unsigned int rcv_base; /* 0x0c (CSR3) */ -+ volatile unsigned int xmt_base; /* 0x10 (CSR4) */ -+ volatile unsigned int status; /* 0x14 (CSR5) */ -+ volatile unsigned int control; /* 0x18 (CSR6) */ -+ volatile unsigned int intr_ena; /* 0x1c (CSR7) */ -+ volatile unsigned int rcv_missed; /* 0x20 (CSR8) */ -+ volatile unsigned int reserved[11]; /* 0x24-0x4c (CSR9-19) */ -+ volatile unsigned int cur_tx_buf_addr; /* 0x50 (CSR20) */ -+ volatile unsigned int cur_rx_buf_addr; /* 0x50 (CSR21) */ -+} DMA; ++ for (i = 0; i < AR2313_DESCR_ENTRIES; i++) { ++ ar2313_descr_t *td = &sp->tx_ring[i]; ++ printk("Tx desc %2d: %08x %08x %08x %08x\n", i, ++ td->status, td->devcs, td->addr, td->descr); ++ } ++} ++#endif + -+#define dma (*((volatile DMA *) DMA_BASE)) ++#ifdef TX_TIMEOUT ++static void ++ar2313_tx_timeout(struct net_device *dev) ++{ ++ struct ar2313_private *sp = (struct ar2313_private *)dev->priv; ++ unsigned long flags; ++ ++#if DEBUG_TX ++ printk("Tx timeout\n"); ++#endif ++ spin_lock_irqsave(&sp->lock, flags); ++ ar2313_restart(dev); ++ spin_unlock_irqrestore(&sp->lock, flags); ++} ++#endif + -+// macro to convert from virtual to physical address -+#define phys_addr(x) (x & 0x1fffffff) ++#if DEBUG_MC ++static void ++printMcList(struct net_device *dev) ++{ ++ struct dev_mc_list *list = dev->mc_list; ++ int num=0, i; ++ while(list){ ++ printk("%d MC ADDR ", num); ++ for(i=0;idmi_addrlen;i++) { ++ printk(":%02x", list->dmi_addr[i]); ++ } ++ list = list->next; ++ printk("\n"); ++ } ++} ++#endif + -+#endif /* PLATFORM_H */ -diff -urN linux.old/drivers/net/ar2313.c linux.net/drivers/net/ar2313.c ---- linux.old/drivers/net/ar2313.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.net/drivers/net/ar2313.c 2006-01-30 01:21:56.822933750 +0100 -@@ -0,0 +1,1642 @@ +/* -+ * ar2313.c: Linux driver for the Atheros AR2313 Ethernet device. -+ * -+ * Copyright 2004 by Sameer Dekate, . -+ * -+ * Thanks to Atheros for providing hardware and documentation -+ * enabling me to write this driver. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * Additional credits: -+ * This code is taken from John Taylor's Sibyte driver and then -+ * modified for the AR2313. ++ * Set or clear the multicast filter for this adaptor. ++ * THIS IS ABSOLUTE CRAP, disabled + */ ++static void ++ar2313_multicast_list(struct net_device *dev) ++{ ++ /* ++ * Always listen to broadcasts and ++ * treat IFF bits independently ++ */ ++ struct ar2313_private *sp = (struct ar2313_private *)dev->priv; ++ unsigned int recognise; + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+extern char *getenv(char *e); -+ -+ -+#undef INDEX_DEBUG -+#define DEBUG 0 -+#define DEBUG_TX 0 -+#define DEBUG_RX 0 -+#define DEBUG_INT 0 -+#define DEBUG_MC 0 -+#define DEBUG_ERR 1 ++ recognise = sp->eth_regs->mac_control; + -+#ifndef __exit -+#define __exit -+#endif ++ if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */ ++ recognise |= MAC_CONTROL_PR; ++ } else { ++ recognise &= ~MAC_CONTROL_PR; ++ } + -+#ifndef min -+#define min(a,b) (((a)<(b))?(a):(b)) ++ if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 15)) { ++#if DEBUG_MC ++ printMcList(dev); ++ printk("%s: all MULTICAST mc_count %d\n", __FUNCTION__, dev->mc_count); +#endif -+ -+#ifndef SMP_CACHE_BYTES -+#define SMP_CACHE_BYTES L1_CACHE_BYTES ++ recognise |= MAC_CONTROL_PM;/* all multicast */ ++ } else if (dev->mc_count > 0) { ++#if DEBUG_MC ++ printMcList(dev); ++ printk("%s: mc_count %d\n", __FUNCTION__, dev->mc_count); +#endif -+ -+#ifndef SET_MODULE_OWNER -+#define SET_MODULE_OWNER(dev) {do{} while(0);} -+#define AR2313_MOD_INC_USE_COUNT MOD_INC_USE_COUNT -+#define AR2313_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT -+#else -+#define AR2313_MOD_INC_USE_COUNT {do{} while(0);} -+#define AR2313_MOD_DEC_USE_COUNT {do{} while(0);} ++ recognise |= MAC_CONTROL_PM; /* for the time being */ ++ } ++#if DEBUG_MC ++ printk("%s: setting %08x to %08x\n", __FUNCTION__, (int)sp->eth_regs, recognise); +#endif ++ ++ sp->eth_regs->mac_control = recognise; ++} + -+#define PHYSADDR(a) ((_ACAST32_ (a)) & 0x1fffffff) -+ -+MODULE_PARM(ethaddr, "s"); -+static char *ethaddr = "00:00:00:00:00:00"; -+MODULE_PARM(ifname, "s"); -+static char *ifname = "bond" ; ++static void rx_tasklet_cleanup(struct net_device *dev) ++{ ++ struct ar2313_private *sp = dev->priv; + -+#define AR2313_MBOX_SET_BIT 0x8 ++ /* ++ * Tasklet may be scheduled. Need to get it removed from the list ++ * since we're about to free the struct. ++ */ + -+#define BOARD_IDX_STATIC 0 -+#define BOARD_IDX_OVERFLOW -1 ++ sp->unloading = 1; ++ tasklet_enable(&sp->rx_tasklet); ++ tasklet_kill(&sp->rx_tasklet); ++} + -+/* margot includes */ -+#include ++static void __exit ar2313_module_cleanup(void) ++{ ++ rx_tasklet_cleanup(root_dev); ++ ar2313_init_cleanup(root_dev); ++ unregister_netdev(root_dev); ++ kfree(root_dev); ++ release_region(PHYSADDR(ETHERNET_BASE), ETHERNET_SIZE*ETHERNET_MACS); ++} + -+#include "ar2313/ar2313_msg.h" -+#include "ar2313/platform.h" -+#include "ar2313/dma.h" -+#include "ar2313/ar2313.h" + +/* -+ * New interrupt handler strategy: -+ * -+ * An old interrupt handler worked using the traditional method of -+ * replacing an skbuff with a new one when a packet arrives. However -+ * the rx rings do not need to contain a static number of buffer -+ * descriptors, thus it makes sense to move the memory allocation out -+ * of the main interrupt handler and do it in a bottom half handler -+ * and only allocate new buffers when the number of buffers in the -+ * ring is below a certain threshold. In order to avoid starving the -+ * NIC under heavy load it is however necessary to force allocation -+ * when hitting a minimum threshold. The strategy for alloction is as -+ * follows: -+ * -+ * RX_LOW_BUF_THRES - allocate buffers in the bottom half -+ * RX_PANIC_LOW_THRES - we are very low on buffers, allocate -+ * the buffers in the interrupt handler -+ * RX_RING_THRES - maximum number of buffers in the rx ring -+ * -+ * One advantagous side effect of this allocation approach is that the -+ * entire rx processing can be done without holding any spin lock -+ * since the rx rings and registers are totally independent of the tx -+ * ring and its registers. This of course includes the kmalloc's of -+ * new skb's. Thus start_xmit can run in parallel with rx processing -+ * and the memory allocation on SMP systems. -+ * -+ * Note that running the skb reallocation in a bottom half opens up -+ * another can of races which needs to be handled properly. In -+ * particular it can happen that the interrupt handler tries to run -+ * the reallocation while the bottom half is either running on another -+ * CPU or was interrupted on the same CPU. To get around this the -+ * driver uses bitops to prevent the reallocation routines from being -+ * reentered. -+ * -+ * TX handling can also be done without holding any spin lock, wheee -+ * this is fun! since tx_csm is only written to by the interrupt -+ * handler. ++ * Restart the AR2313 ethernet controller. + */ ++static int ar2313_restart(struct net_device *dev) ++{ ++ /* disable interrupts */ ++ disable_irq(dev->irq); + -+/* -+ * Threshold values for RX buffer allocation - the low water marks for -+ * when to start refilling the rings are set to 75% of the ring -+ * sizes. It seems to make sense to refill the rings entirely from the -+ * intrrupt handler once it gets below the panic threshold, that way -+ * we don't risk that the refilling is moved to another CPU when the -+ * one running the interrupt handler just got the slab code hot in its -+ * cache. -+ */ -+#define RX_RING_SIZE AR2313_DESCR_ENTRIES -+#define RX_PANIC_THRES (RX_RING_SIZE/4) -+#define RX_LOW_THRES ((3*RX_RING_SIZE)/4) -+#define CRC_LEN 4 -+#define RX_OFFSET 2 ++ /* stop mac */ ++ ar2313_halt(dev); ++ ++ /* initialize */ ++ ar2313_init(dev); ++ ++ /* enable interrupts */ ++ enable_irq(dev->irq); ++ ++ return 0; ++} + -+#define AR2313_BUFSIZE (AR2313_MTU + ETH_HLEN + CRC_LEN + RX_OFFSET) ++extern unsigned long mips_machtype; + -+#ifdef MODULE -+MODULE_AUTHOR("Sameer Dekate"); -+MODULE_DESCRIPTION("AR2313 Ethernet driver"); -+#endif ++int __init ar2313_module_init(void) ++{ ++ int status=-1; ++ switch (mips_machtype){ ++ case MACH_ARUBA_AP60: ++ case MACH_ARUBA_AP65: ++ case MACH_ARUBA_AP40: ++ root_dev = NULL; ++ status = ar2313_probe(); ++ break; ++ } ++ return status; ++} + -+#if DEBUG -+static char version[] __initdata = -+ "ar2313.c: v0.01 2004/01/06 sdekate@arubanetworks.com\n"; -+#endif /* DEBUG */ + -+#define virt_to_phys(x) ((u32)(x) & 0x1fffffff) ++module_init(ar2313_module_init); ++module_exit(ar2313_module_cleanup); + -+// prototypes -+static short armiiread(short phy, short reg); -+static void armiiwrite(short phy, short reg, short data); -+#ifdef TX_TIMEOUT -+static void ar2313_tx_timeout(struct net_device *dev); -+#endif -+static void ar2313_halt(struct net_device *dev); -+static void rx_tasklet_func(unsigned long data); -+static void ar2313_multicast_list(struct net_device *dev); + -+static struct net_device *root_dev; -+static int probed __initdata = 0; -+static unsigned long ar_eth_base; -+static unsigned long ar_dma_base; -+static unsigned long ar_int_base; -+static unsigned long ar_int_mac_mask; -+static unsigned long ar_int_phy_mask; -+ -+#ifndef ERR -+#define ERR(fmt, args...) printk("%s: " fmt, __func__, ##args) -+#endif -+ -+static int parse_mac_addr(struct net_device *dev, char* macstr){ -+ int i, j; -+ unsigned char result, value; -+ -+ for (i=0; i<6; i++) { -+ result = 0; -+ if (i != 5 && *(macstr+2) != ':') { -+ ERR("invalid mac address format: %d %c\n", -+ i, *(macstr+2)); -+ return -EINVAL; -+ } -+ for (j=0; j<2; j++) { -+ if (isxdigit(*macstr) && (value = isdigit(*macstr) ? *macstr-'0' : -+ toupper(*macstr)-'A'+10) < 16) -+ { -+ result = result*16 + value; -+ macstr++; -+ } -+ else { -+ ERR("invalid mac address " -+ "character: %c\n", *macstr); -+ return -EINVAL; -+ } ++static void ar2313_free_descriptors(struct net_device *dev) ++{ ++ struct ar2313_private *sp = dev->priv; ++ if (sp->rx_ring != NULL) { ++ kfree((void*)KSEG0ADDR(sp->rx_ring)); ++ sp->rx_ring = NULL; ++ sp->tx_ring = NULL; + } -+ -+ macstr++; -+ dev->dev_addr[i] = result; -+ } -+ -+ return 0; +} + + -+int __init ar2313_probe(void) ++static int ar2313_allocate_descriptors(struct net_device *dev) +{ -+ struct net_device *dev; -+ struct ar2313_private *sp; -+ int version_disp; -+ char name[64] ; -+ -+ if (probed) -+ return -ENODEV; -+ probed++; -+ -+ version_disp = 0; -+ sprintf(name, "%s%%d", ifname) ; -+ dev = alloc_etherdev(sizeof(struct ar2313_private)); ++ struct ar2313_private *sp = dev->priv; ++ int size; ++ int j; ++ ar2313_descr_t *space; + -+ if (dev == NULL) { -+ printk(KERN_ERR "ar2313: Unable to allocate net_device structure!\n"); -+ return -ENOMEM; ++ if(sp->rx_ring != NULL){ ++ printk("%s: already done.\n", __FUNCTION__); ++ return 0; + } + -+ SET_MODULE_OWNER(dev); ++ size = (sizeof(ar2313_descr_t) * (AR2313_DESCR_ENTRIES * AR2313_QUEUES)); ++ space = kmalloc(size, GFP_KERNEL); ++ if (space == NULL) ++ return 1; + -+ sp = dev->priv; ++ /* invalidate caches */ ++ dma_cache_inv((unsigned int)space, size); + -+ sp->link = 0; -+ switch (mips_machtype) { -+ case MACH_ARUBA_AP60: -+ ar_eth_base = 0xb8100000; -+ ar_dma_base = ar_eth_base + 0x1000; -+ ar_int_base = 0x1C003020; -+ ar_int_mac_mask = RESET_ENET0|RESET_ENET1; -+ ar_int_phy_mask = RESET_EPHY0|RESET_EPHY1; -+ sp->mac = 1; -+ sp->phy = 1; -+ dev->irq = 4; -+ break; ++ /* now convert pointer to KSEG1 */ ++ space = (ar2313_descr_t *)KSEG1ADDR(space); + -+ case MACH_ARUBA_AP40: -+ ar_eth_base = 0xb0500000; -+ ar_dma_base = ar_eth_base + 0x1000; -+ ar_int_base = 0x11000004; -+ ar_int_mac_mask = 0x800; -+ ar_int_phy_mask = 0x400; -+ sp->mac = 0; -+ sp->phy = 1; -+ dev->irq = 4; -+ break; ++ memset((void *)space, 0, size); + -+ case MACH_ARUBA_AP65: -+ ar_eth_base = 0xb8100000; -+ ar_dma_base = ar_eth_base + 0x1000; -+ ar_int_base = 0x1C003020; -+ ar_int_mac_mask = RESET_ENET0|RESET_ENET1; -+ ar_int_phy_mask = RESET_EPHY0|RESET_EPHY1; -+ sp->mac = 0; -+#if 0 -+ // commented out, for now ++ sp->rx_ring = space; ++ space += AR2313_DESCR_ENTRIES; + -+ if (mips_machtype == MACH_ARUBA_SAMSUNG) { -+ sp->phy = 0x1f; -+ } else { -+ sp->phy = 1; -+ } -+#else -+ sp->phy = 1; -+#endif -+ dev->irq = 3; -+ break; ++ sp->tx_ring = space; ++ space += AR2313_DESCR_ENTRIES; + -+ default: -+ printk("%s: unsupported mips_machtype=0x%lx\n", -+ __FUNCTION__, mips_machtype) ; -+ return -ENODEV; ++ /* Initialize the transmit Descriptors */ ++ for (j = 0; j < AR2313_DESCR_ENTRIES; j++) { ++ ar2313_descr_t *td = &sp->tx_ring[j]; ++ td->status = 0; ++ td->devcs = DMA_TX1_CHAINED; ++ td->addr = 0; ++ td->descr = K1_TO_PHYS(&sp->tx_ring[(j+1) & (AR2313_DESCR_ENTRIES-1)]); + } + -+ spin_lock_init(&sp->lock); -+ -+ /* initialize func pointers */ -+ dev->open = &ar2313_open; -+ dev->stop = &ar2313_close; -+ dev->hard_start_xmit = &ar2313_start_xmit; -+ -+ dev->get_stats = &ar2313_get_stats; -+ dev->set_multicast_list = &ar2313_multicast_list; -+#ifdef TX_TIMEOUT -+ dev->tx_timeout = ar2313_tx_timeout; -+ dev->watchdog_timeo = AR2313_TX_TIMEOUT; -+#endif -+ dev->do_ioctl = &ar2313_ioctl; ++ return 0; ++} + -+ // SAMEER: do we need this? -+ dev->features |= NETIF_F_SG | NETIF_F_HIGHDMA; + -+ tasklet_init(&sp->rx_tasklet, rx_tasklet_func, (unsigned long) dev); -+ tasklet_disable(&sp->rx_tasklet); ++/* ++ * Generic cleanup handling data allocated during init. Used when the ++ * module is unloaded or if an error occurs during initialization ++ */ ++static void ar2313_init_cleanup(struct net_device *dev) ++{ ++ struct ar2313_private *sp = dev->priv; ++ struct sk_buff *skb; ++ int j; + -+ /* display version info if adapter is found */ -+ if (!version_disp) { -+ /* set display flag to TRUE so that */ -+ /* we only display this string ONCE */ -+ version_disp = 1; -+#if DEBUG -+ printk(version); -+#endif /* DEBUG */ -+ } ++ ar2313_free_descriptors(dev); + -+ request_region(PHYSADDR(ETHERNET_BASE), ETHERNET_SIZE*ETHERNET_MACS, -+ "AR2313ENET"); ++ if (sp->eth_regs) iounmap((void*)sp->eth_regs); ++ if (sp->dma_regs) iounmap((void*)sp->dma_regs); + -+ sp->eth_regs = ioremap_nocache(PHYSADDR(ETHERNET_BASE + ETHERNET_SIZE*sp->mac), -+ sizeof(*sp->eth_regs)); -+ if (!sp->eth_regs) { -+ printk("Can't remap eth registers\n"); -+ return(-ENXIO); ++ if (sp->rx_skb) { ++ for (j = 0; j < AR2313_DESCR_ENTRIES; j++) { ++ skb = sp->rx_skb[j]; ++ if (skb) { ++ sp->rx_skb[j] = NULL; ++ dev_kfree_skb(skb); ++ } ++ } ++ kfree(sp->rx_skb); ++ sp->rx_skb = NULL; + } + -+ sp->dma_regs = ioremap_nocache(PHYSADDR(DMA_BASE + DMA_SIZE*sp->mac), -+ sizeof(*sp->dma_regs)); -+ dev->base_addr = (unsigned int) sp->dma_regs; -+ if (!sp->dma_regs) { -+ printk("Can't remap DMA registers\n"); -+ return(-ENXIO); ++ if (sp->tx_skb) { ++ for (j = 0; j < AR2313_DESCR_ENTRIES; j++) { ++ skb = sp->tx_skb[j]; ++ if (skb) { ++ sp->tx_skb[j] = NULL; ++ dev_kfree_skb(skb); ++ } ++ } ++ kfree(sp->tx_skb); ++ sp->tx_skb = NULL; + } ++} + -+ sp->int_regs = ioremap_nocache(PHYSADDR(INTERRUPT_BASE), -+ sizeof(*sp->int_regs)); -+ if (!sp->int_regs) { -+ printk("Can't remap INTERRUPT registers\n"); -+ return(-ENXIO); -+ } ++static int ar2313_setup_timer(struct net_device *dev) ++{ ++ struct ar2313_private *sp = dev->priv; + -+ strncpy(sp->name, "Atheros AR2313", sizeof (sp->name) - 1); -+ sp->name [sizeof (sp->name) - 1] = '\0'; ++ init_timer(&sp->link_timer); + -+ { -+ char mac[32]; -+ extern char *getenv(char *e); -+ unsigned char def_mac[6] = {0, 0x0b, 0x86, 0xba, 0xdb, 0xad}; -+ memset(mac, 0, 32); -+ memcpy(mac, getenv("ethaddr"), 17); -+ if (parse_mac_addr(dev, mac)){ -+ printk("%s: MAC address not found, using default\n", __func__); -+ memcpy(dev->dev_addr, def_mac, 6); -+ } -+ } ++ sp->link_timer.function = ar2313_link_timer_fn; ++ sp->link_timer.data = (int) dev; ++ sp->link_timer.expires = jiffies + HZ; + -+ sp->board_idx = BOARD_IDX_STATIC; ++ add_timer(&sp->link_timer); ++ return 0; + -+ if (ar2313_init(dev)) { -+ /* -+ * ar2313_init() calls ar2313_init_cleanup() on error. -+ */ -+ kfree(dev); -+ return -ENODEV; -+ } ++} + -+ if (register_netdev(dev)){ -+ printk("%s: register_netdev failed\n", __func__); -+ return -1; -+ } ++static void ar2313_link_timer_fn(unsigned long data) ++{ ++ struct net_device *dev = (struct net_device *) data; ++ struct ar2313_private *sp = dev->priv; + -+ printk("%s: %s: %02x:%02x:%02x:%02x:%02x:%02x, irq %d\n", -+ dev->name, sp->name, -+ dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], -+ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5], -+ dev->irq); -+ -+ /* start link poll timer */ -+ ar2313_setup_timer(dev); -+ -+ /* -+ * Register the device -+ */ -+ root_dev = dev; -+ -+ return 0; ++ // see if the link status changed ++ // This was needed to make sure we set the PHY to the ++ // autonegotiated value of half or full duplex. ++ ar2313_check_link(dev); ++ ++ // Loop faster when we don't have link. ++ // This was needed to speed up the AP bootstrap time. ++ if(sp->link == 0) { ++ mod_timer(&sp->link_timer, jiffies + HZ/2); ++ } else { ++ mod_timer(&sp->link_timer, jiffies + LINK_TIMER); ++ } +} + -+#if 0 -+static void ar2313_dump_regs(struct net_device *dev) ++static void ar2313_check_link(struct net_device *dev) +{ -+ unsigned int *ptr, i; -+ struct ar2313_private *sp = (struct ar2313_private *)dev->priv; ++ struct ar2313_private *sp = dev->priv; ++ u16 phyData; + -+ ptr = (unsigned int *)sp->eth_regs; -+ for(i=0; i< (sizeof(ETHERNET_STRUCT)/ sizeof(unsigned int)); i++, ptr++) { -+ printk("ENET: %08x = %08x\n", (int)ptr, *ptr); -+ } ++ phyData = armiiread(sp->phy, MII_BMSR); ++ if (sp->phyData != phyData) { ++ if (phyData & BMSR_LSTATUS) { ++ /* link is present, ready link partner ability to deterine duplexity */ ++ int duplex = 0; ++ u16 reg; + -+ ptr = (unsigned int *)sp->dma_regs; -+ for(i=0; i< (sizeof(DMA)/ sizeof(unsigned int)); i++, ptr++) { -+ printk("DMA: %08x = %08x\n", (int)ptr, *ptr); -+ } ++ sp->link = 1; ++ reg = armiiread(sp->phy, MII_BMCR); ++ if (reg & BMCR_ANENABLE) { ++ /* auto neg enabled */ ++ reg = armiiread(sp->phy, MII_LPA); ++ duplex = (reg & (LPA_100FULL|LPA_10FULL))? 1:0; ++ } else { ++ /* no auto neg, just read duplex config */ ++ duplex = (reg & BMCR_FULLDPLX)? 1:0; ++ } + -+ ptr = (unsigned int *)sp->int_regs; -+ for(i=0; i< (sizeof(INTERRUPT)/ sizeof(unsigned int)); i++, ptr++){ -+ printk("INT: %08x = %08x\n", (int)ptr, *ptr); -+ } ++ printk(KERN_INFO "%s: Configuring MAC for %s duplex\n", dev->name, ++ (duplex)? "full":"half"); + -+ for (i = 0; i < AR2313_DESCR_ENTRIES; i++) { -+ ar2313_descr_t *td = &sp->tx_ring[i]; -+ printk("Tx desc %2d: %08x %08x %08x %08x\n", i, -+ td->status, td->devcs, td->addr, td->descr); ++ if (duplex) { ++ /* full duplex */ ++ sp->eth_regs->mac_control = ((sp->eth_regs->mac_control | MAC_CONTROL_F) & ++ ~MAC_CONTROL_DRO); ++ } else { ++ /* half duplex */ ++ sp->eth_regs->mac_control = ((sp->eth_regs->mac_control | MAC_CONTROL_DRO) & ++ ~MAC_CONTROL_F); ++ } ++ } else { ++ /* no link */ ++ sp->link = 0; ++ } ++ sp->phyData = phyData; + } +} -+#endif -+ -+#ifdef TX_TIMEOUT -+static void -+ar2313_tx_timeout(struct net_device *dev) ++ ++static int ++ar2313_reset_reg(struct net_device *dev) +{ + struct ar2313_private *sp = (struct ar2313_private *)dev->priv; -+ unsigned long flags; -+ -+#if DEBUG_TX -+ printk("Tx timeout\n"); -+#endif -+ spin_lock_irqsave(&sp->lock, flags); -+ ar2313_restart(dev); -+ spin_unlock_irqrestore(&sp->lock, flags); -+} -+#endif ++ unsigned int ethsal, ethsah; ++ unsigned int flags; + -+#if DEBUG_MC -+static void -+printMcList(struct net_device *dev) -+{ -+ struct dev_mc_list *list = dev->mc_list; -+ int num=0, i; -+ while(list){ -+ printk("%d MC ADDR ", num); -+ for(i=0;idmi_addrlen;i++) { -+ printk(":%02x", list->dmi_addr[i]); -+ } -+ list = list->next; -+ printk("\n"); -+ } -+} -+#endif ++ *sp->int_regs |= ar_int_mac_mask; ++ mdelay(10); ++ *sp->int_regs &= ~ar_int_mac_mask; ++ mdelay(10); ++ *sp->int_regs |= ar_int_phy_mask; ++ mdelay(10); ++ *sp->int_regs &= ~ar_int_phy_mask; ++ mdelay(10); + -+/* -+ * Set or clear the multicast filter for this adaptor. -+ * THIS IS ABSOLUTE CRAP, disabled -+ */ -+static void -+ar2313_multicast_list(struct net_device *dev) -+{ -+ /* -+ * Always listen to broadcasts and -+ * treat IFF bits independently -+ */ -+ struct ar2313_private *sp = (struct ar2313_private *)dev->priv; -+ unsigned int recognise; ++ sp->dma_regs->bus_mode = (DMA_BUS_MODE_SWR); ++ mdelay(10); ++ sp->dma_regs->bus_mode = ((32 << DMA_BUS_MODE_PBL_SHIFT) | DMA_BUS_MODE_BLE); + -+ recognise = sp->eth_regs->mac_control; ++ /* enable interrupts */ ++ sp->dma_regs->intr_ena = (DMA_STATUS_AIS | ++ DMA_STATUS_NIS | ++ DMA_STATUS_RI | ++ DMA_STATUS_TI | ++ DMA_STATUS_FBE); ++ sp->dma_regs->xmt_base = K1_TO_PHYS(sp->tx_ring); ++ sp->dma_regs->rcv_base = K1_TO_PHYS(sp->rx_ring); ++ sp->dma_regs->control = (DMA_CONTROL_SR | DMA_CONTROL_ST | DMA_CONTROL_SF); ++ ++ sp->eth_regs->flow_control = (FLOW_CONTROL_FCE); ++ sp->eth_regs->vlan_tag = (0x8100); ++ ++ /* Enable Ethernet Interface */ ++ flags = (MAC_CONTROL_TE | /* transmit enable */ ++ MAC_CONTROL_PM | /* pass mcast */ ++ MAC_CONTROL_F | /* full duplex */ ++ MAC_CONTROL_HBD); /* heart beat disabled */ + + if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */ -+ recognise |= MAC_CONTROL_PR; -+ } else { -+ recognise &= ~MAC_CONTROL_PR; ++ flags |= MAC_CONTROL_PR; + } ++ sp->eth_regs->mac_control = flags; + -+ if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 15)) { -+#if DEBUG_MC -+ printMcList(dev); -+ printk("%s: all MULTICAST mc_count %d\n", __FUNCTION__, dev->mc_count); -+#endif -+ recognise |= MAC_CONTROL_PM;/* all multicast */ -+ } else if (dev->mc_count > 0) { -+#if DEBUG_MC -+ printMcList(dev); -+ printk("%s: mc_count %d\n", __FUNCTION__, dev->mc_count); -+#endif -+ recognise |= MAC_CONTROL_PM; /* for the time being */ -+ } -+#if DEBUG_MC -+ printk("%s: setting %08x to %08x\n", __FUNCTION__, (int)sp->eth_regs, recognise); -+#endif -+ -+ sp->eth_regs->mac_control = recognise; -+} ++ /* Set all Ethernet station address registers to their initial values */ ++ ethsah = ((((u_int)(dev->dev_addr[5]) << 8) & (u_int)0x0000FF00) | ++ (((u_int)(dev->dev_addr[4]) << 0) & (u_int)0x000000FF)); + -+static void rx_tasklet_cleanup(struct net_device *dev) -+{ -+ struct ar2313_private *sp = dev->priv; ++ ethsal = ((((u_int)(dev->dev_addr[3]) << 24) & (u_int)0xFF000000) | ++ (((u_int)(dev->dev_addr[2]) << 16) & (u_int)0x00FF0000) | ++ (((u_int)(dev->dev_addr[1]) << 8) & (u_int)0x0000FF00) | ++ (((u_int)(dev->dev_addr[0]) << 0) & (u_int)0x000000FF) ); + -+ /* -+ * Tasklet may be scheduled. Need to get it removed from the list -+ * since we're about to free the struct. -+ */ ++ sp->eth_regs->mac_addr[0] = ethsah; ++ sp->eth_regs->mac_addr[1] = ethsal; + -+ sp->unloading = 1; -+ tasklet_enable(&sp->rx_tasklet); -+ tasklet_kill(&sp->rx_tasklet); -+} ++ mdelay(10); + -+static void __exit ar2313_module_cleanup(void) -+{ -+ rx_tasklet_cleanup(root_dev); -+ ar2313_init_cleanup(root_dev); -+ unregister_netdev(root_dev); -+ kfree(root_dev); -+ release_region(PHYSADDR(ETHERNET_BASE), ETHERNET_SIZE*ETHERNET_MACS); ++ return(0); +} + + -+/* -+ * Restart the AR2313 ethernet controller. -+ */ -+static int ar2313_restart(struct net_device *dev) ++static int ar2313_init(struct net_device *dev) +{ -+ /* disable interrupts */ -+ disable_irq(dev->irq); -+ -+ /* stop mac */ -+ ar2313_halt(dev); -+ -+ /* initialize */ -+ ar2313_init(dev); -+ -+ /* enable interrupts */ -+ enable_irq(dev->irq); -+ -+ return 0; -+} -+ -+extern unsigned long mips_machtype; ++ struct ar2313_private *sp = dev->priv; ++ int ecode=0; + -+int __init ar2313_module_init(void) -+{ -+ int status=-1; -+ switch (mips_machtype){ -+ case MACH_ARUBA_AP60: -+ case MACH_ARUBA_AP65: -+ case MACH_ARUBA_AP40: -+ root_dev = NULL; -+ status = ar2313_probe(); -+ break; -+ } -+ return status; -+} -+ -+ -+module_init(ar2313_module_init); -+module_exit(ar2313_module_cleanup); -+ -+ -+static void ar2313_free_descriptors(struct net_device *dev) -+{ -+ struct ar2313_private *sp = dev->priv; -+ if (sp->rx_ring != NULL) { -+ kfree((void*)KSEG0ADDR(sp->rx_ring)); -+ sp->rx_ring = NULL; -+ sp->tx_ring = NULL; -+ } -+} -+ -+ -+static int ar2313_allocate_descriptors(struct net_device *dev) -+{ -+ struct ar2313_private *sp = dev->priv; -+ int size; -+ int j; -+ ar2313_descr_t *space; -+ -+ if(sp->rx_ring != NULL){ -+ printk("%s: already done.\n", __FUNCTION__); -+ return 0; -+ } -+ -+ size = (sizeof(ar2313_descr_t) * (AR2313_DESCR_ENTRIES * AR2313_QUEUES)); -+ space = kmalloc(size, GFP_KERNEL); -+ if (space == NULL) -+ return 1; -+ -+ /* invalidate caches */ -+ dma_cache_inv((unsigned int)space, size); -+ -+ /* now convert pointer to KSEG1 */ -+ space = (ar2313_descr_t *)KSEG1ADDR(space); -+ -+ memset((void *)space, 0, size); -+ -+ sp->rx_ring = space; -+ space += AR2313_DESCR_ENTRIES; -+ -+ sp->tx_ring = space; -+ space += AR2313_DESCR_ENTRIES; -+ -+ /* Initialize the transmit Descriptors */ -+ for (j = 0; j < AR2313_DESCR_ENTRIES; j++) { -+ ar2313_descr_t *td = &sp->tx_ring[j]; -+ td->status = 0; -+ td->devcs = DMA_TX1_CHAINED; -+ td->addr = 0; -+ td->descr = K1_TO_PHYS(&sp->tx_ring[(j+1) & (AR2313_DESCR_ENTRIES-1)]); -+ } -+ -+ return 0; -+} -+ -+ -+/* -+ * Generic cleanup handling data allocated during init. Used when the -+ * module is unloaded or if an error occurs during initialization -+ */ -+static void ar2313_init_cleanup(struct net_device *dev) -+{ -+ struct ar2313_private *sp = dev->priv; -+ struct sk_buff *skb; -+ int j; -+ -+ ar2313_free_descriptors(dev); -+ -+ if (sp->eth_regs) iounmap((void*)sp->eth_regs); -+ if (sp->dma_regs) iounmap((void*)sp->dma_regs); -+ -+ if (sp->rx_skb) { -+ for (j = 0; j < AR2313_DESCR_ENTRIES; j++) { -+ skb = sp->rx_skb[j]; -+ if (skb) { -+ sp->rx_skb[j] = NULL; -+ dev_kfree_skb(skb); -+ } -+ } -+ kfree(sp->rx_skb); -+ sp->rx_skb = NULL; -+ } -+ -+ if (sp->tx_skb) { -+ for (j = 0; j < AR2313_DESCR_ENTRIES; j++) { -+ skb = sp->tx_skb[j]; -+ if (skb) { -+ sp->tx_skb[j] = NULL; -+ dev_kfree_skb(skb); -+ } -+ } -+ kfree(sp->tx_skb); -+ sp->tx_skb = NULL; -+ } -+} -+ -+static int ar2313_setup_timer(struct net_device *dev) -+{ -+ struct ar2313_private *sp = dev->priv; -+ -+ init_timer(&sp->link_timer); -+ -+ sp->link_timer.function = ar2313_link_timer_fn; -+ sp->link_timer.data = (int) dev; -+ sp->link_timer.expires = jiffies + HZ; -+ -+ add_timer(&sp->link_timer); -+ return 0; -+ -+} -+ -+static void ar2313_link_timer_fn(unsigned long data) -+{ -+ struct net_device *dev = (struct net_device *) data; -+ struct ar2313_private *sp = dev->priv; -+ -+ // see if the link status changed -+ // This was needed to make sure we set the PHY to the -+ // autonegotiated value of half or full duplex. -+ ar2313_check_link(dev); -+ -+ // Loop faster when we don't have link. -+ // This was needed to speed up the AP bootstrap time. -+ if(sp->link == 0) { -+ mod_timer(&sp->link_timer, jiffies + HZ/2); -+ } else { -+ mod_timer(&sp->link_timer, jiffies + LINK_TIMER); -+ } -+} -+ -+static void ar2313_check_link(struct net_device *dev) -+{ -+ struct ar2313_private *sp = dev->priv; -+ u16 phyData; -+ -+ phyData = armiiread(sp->phy, MII_BMSR); -+ if (sp->phyData != phyData) { -+ if (phyData & BMSR_LSTATUS) { -+ /* link is present, ready link partner ability to deterine duplexity */ -+ int duplex = 0; -+ u16 reg; -+ -+ sp->link = 1; -+ reg = armiiread(sp->phy, MII_BMCR); -+ if (reg & BMCR_ANENABLE) { -+ /* auto neg enabled */ -+ reg = armiiread(sp->phy, MII_LPA); -+ duplex = (reg & (LPA_100FULL|LPA_10FULL))? 1:0; -+ } else { -+ /* no auto neg, just read duplex config */ -+ duplex = (reg & BMCR_FULLDPLX)? 1:0; -+ } -+ -+ printk(KERN_INFO "%s: Configuring MAC for %s duplex\n", dev->name, -+ (duplex)? "full":"half"); -+ -+ if (duplex) { -+ /* full duplex */ -+ sp->eth_regs->mac_control = ((sp->eth_regs->mac_control | MAC_CONTROL_F) & -+ ~MAC_CONTROL_DRO); -+ } else { -+ /* half duplex */ -+ sp->eth_regs->mac_control = ((sp->eth_regs->mac_control | MAC_CONTROL_DRO) & -+ ~MAC_CONTROL_F); -+ } -+ } else { -+ /* no link */ -+ sp->link = 0; -+ } -+ sp->phyData = phyData; -+ } -+} -+ -+static int -+ar2313_reset_reg(struct net_device *dev) -+{ -+ struct ar2313_private *sp = (struct ar2313_private *)dev->priv; -+ unsigned int ethsal, ethsah; -+ unsigned int flags; -+ -+ *sp->int_regs |= ar_int_mac_mask; -+ mdelay(10); -+ *sp->int_regs &= ~ar_int_mac_mask; -+ mdelay(10); -+ *sp->int_regs |= ar_int_phy_mask; -+ mdelay(10); -+ *sp->int_regs &= ~ar_int_phy_mask; -+ mdelay(10); -+ -+ sp->dma_regs->bus_mode = (DMA_BUS_MODE_SWR); -+ mdelay(10); -+ sp->dma_regs->bus_mode = ((32 << DMA_BUS_MODE_PBL_SHIFT) | DMA_BUS_MODE_BLE); -+ -+ /* enable interrupts */ -+ sp->dma_regs->intr_ena = (DMA_STATUS_AIS | -+ DMA_STATUS_NIS | -+ DMA_STATUS_RI | -+ DMA_STATUS_TI | -+ DMA_STATUS_FBE); -+ sp->dma_regs->xmt_base = K1_TO_PHYS(sp->tx_ring); -+ sp->dma_regs->rcv_base = K1_TO_PHYS(sp->rx_ring); -+ sp->dma_regs->control = (DMA_CONTROL_SR | DMA_CONTROL_ST | DMA_CONTROL_SF); -+ -+ sp->eth_regs->flow_control = (FLOW_CONTROL_FCE); -+ sp->eth_regs->vlan_tag = (0x8100); -+ -+ /* Enable Ethernet Interface */ -+ flags = (MAC_CONTROL_TE | /* transmit enable */ -+ MAC_CONTROL_PM | /* pass mcast */ -+ MAC_CONTROL_F | /* full duplex */ -+ MAC_CONTROL_HBD); /* heart beat disabled */ -+ -+ if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */ -+ flags |= MAC_CONTROL_PR; -+ } -+ sp->eth_regs->mac_control = flags; -+ -+ /* Set all Ethernet station address registers to their initial values */ -+ ethsah = ((((u_int)(dev->dev_addr[5]) << 8) & (u_int)0x0000FF00) | -+ (((u_int)(dev->dev_addr[4]) << 0) & (u_int)0x000000FF)); -+ -+ ethsal = ((((u_int)(dev->dev_addr[3]) << 24) & (u_int)0xFF000000) | -+ (((u_int)(dev->dev_addr[2]) << 16) & (u_int)0x00FF0000) | -+ (((u_int)(dev->dev_addr[1]) << 8) & (u_int)0x0000FF00) | -+ (((u_int)(dev->dev_addr[0]) << 0) & (u_int)0x000000FF) ); -+ -+ sp->eth_regs->mac_addr[0] = ethsah; -+ sp->eth_regs->mac_addr[1] = ethsal; -+ -+ mdelay(10); -+ -+ return(0); -+} -+ -+ -+static int ar2313_init(struct net_device *dev) -+{ -+ struct ar2313_private *sp = dev->priv; -+ int ecode=0; -+ -+ /* -+ * Allocate descriptors -+ */ -+ if (ar2313_allocate_descriptors(dev)) { -+ printk("%s: %s: ar2313_allocate_descriptors failed\n", -+ dev->name, __FUNCTION__); -+ ecode = -EAGAIN; -+ goto init_error; ++ /* ++ * Allocate descriptors ++ */ ++ if (ar2313_allocate_descriptors(dev)) { ++ printk("%s: %s: ar2313_allocate_descriptors failed\n", ++ dev->name, __FUNCTION__); ++ ecode = -EAGAIN; ++ goto init_error; + } + + /* @@ -2033,128 +1526,650 @@ diff -urN linux.old/drivers/net/ar2313.c linux.net/drivers/net/ar2313.c + return -EOPNOTSUPP; +} + -+static int ar2313_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -+{ -+ struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data; ++static int ar2313_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ++{ ++ struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data; ++ ++ switch (cmd) { ++ case SIOCDEVPRIVATE: { ++ struct ar2313_cmd scmd; ++ ++ if (copy_from_user(&scmd, ifr->ifr_data, sizeof(scmd))) ++ return -EFAULT; ++ ++#if DEBUG ++ printk("%s: ioctl devprivate c=%d a=%x l=%d m=%d d=%x,%x\n", ++ dev->name, scmd.cmd, ++ scmd.address, scmd.length, ++ scmd.mailbox, scmd.data[0], scmd.data[1]); ++#endif /* DEBUG */ ++ ++ switch (scmd.cmd) { ++ case AR2313_READ_DATA: ++ if(scmd.length==4){ ++ scmd.data[0] = *((u32*)scmd.address); ++ } else if(scmd.length==2) { ++ scmd.data[0] = *((u16*)scmd.address); ++ } else if (scmd.length==1) { ++ scmd.data[0] = *((u8*)scmd.address); ++ } else { ++ return -EOPNOTSUPP; ++ } ++ if(copy_to_user(ifr->ifr_data, &scmd, sizeof(scmd))) ++ return -EFAULT; ++ break; ++ ++ case AR2313_WRITE_DATA: ++ if(scmd.length==4){ ++ *((u32*)scmd.address) = scmd.data[0]; ++ } else if(scmd.length==2) { ++ *((u16*)scmd.address) = scmd.data[0]; ++ } else if (scmd.length==1) { ++ *((u8*)scmd.address) = scmd.data[0]; ++ } else { ++ return -EOPNOTSUPP; ++ } ++ break; ++ ++ case AR2313_GET_VERSION: ++ // SAMEER: sprintf((char*) &scmd, "%s", ARUBA_VERSION); ++ if(copy_to_user(ifr->ifr_data, &scmd, sizeof(scmd))) ++ return -EFAULT; ++ break; ++ ++ default: ++ return -EOPNOTSUPP; ++ } ++ return 0; ++ } ++ ++ case SIOCETHTOOL: ++ return netdev_ethtool_ioctl(dev, (void *) ifr->ifr_data); ++ ++ case SIOCGMIIPHY: /* Get address of MII PHY in use. */ ++ data->phy_id = 1; ++ /* Fall Through */ ++ ++ case SIOCGMIIREG: /* Read MII PHY register. */ ++ case SIOCDEVPRIVATE+1: /* for binary compat, remove in 2.5 */ ++ data->val_out = armiiread(data->phy_id & 0x1f, ++ data->reg_num & 0x1f); ++ return 0; ++ case SIOCSMIIREG: /* Write MII PHY register. */ ++ case SIOCDEVPRIVATE+2: /* for binary compat, remove in 2.5 */ ++ if (!capable(CAP_NET_ADMIN)) ++ return -EPERM; ++ armiiwrite(data->phy_id & 0x1f, ++ data->reg_num & 0x1f, data->val_in); ++ return 0; ++ ++ case SIOCSIFHWADDR: ++ if (copy_from_user(dev->dev_addr, ifr->ifr_data, sizeof(dev->dev_addr))) ++ return -EFAULT; ++ return 0; ++ ++ case SIOCGIFHWADDR: ++ if (copy_to_user(ifr->ifr_data, dev->dev_addr, sizeof(dev->dev_addr))) ++ return -EFAULT; ++ return 0; ++ ++ default: ++ break; ++ } ++ ++ return -EOPNOTSUPP; ++} ++ ++static struct net_device_stats *ar2313_get_stats(struct net_device *dev) ++{ ++ struct ar2313_private *sp = dev->priv; ++ return &sp->stats; ++} ++ ++static short ++armiiread(short phy, short reg) ++{ ++ volatile ETHERNET_STRUCT * ethernet; ++ ++ ethernet = (volatile ETHERNET_STRUCT *)ETHERNET_BASE; /* always MAC 0 */ ++ ethernet->mii_addr = ((reg << MII_ADDR_REG_SHIFT) | ++ (phy << MII_ADDR_PHY_SHIFT)); ++ while (ethernet->mii_addr & MII_ADDR_BUSY); ++ return (ethernet->mii_data >> MII_DATA_SHIFT); ++} ++ ++static void ++armiiwrite(short phy, short reg, short data) ++{ ++ volatile ETHERNET_STRUCT * ethernet; ++ ++ ethernet = (volatile ETHERNET_STRUCT *)ETHERNET_BASE; /* always MAC 0 */ ++ while (ethernet->mii_addr & MII_ADDR_BUSY); ++ ethernet->mii_data = data << MII_DATA_SHIFT; ++ ethernet->mii_addr = ((reg << MII_ADDR_REG_SHIFT) | ++ (phy << MII_ADDR_PHY_SHIFT) | ++ MII_ADDR_WRITE); ++} ++ +diff -Nur linux-2.6.17/drivers/net/ar2313/ar2313.h linux-2.6.17-owrt/drivers/net/ar2313/ar2313.h +--- linux-2.6.17/drivers/net/ar2313/ar2313.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.17-owrt/drivers/net/ar2313/ar2313.h 2006-06-19 12:05:29.000000000 +0200 +@@ -0,0 +1,190 @@ ++#ifndef _AR2313_H_ ++#define _AR2313_H_ ++ ++#include ++#include ++#include "platform.h" ++ ++extern unsigned long mips_machtype; ++ ++#undef ETHERNET_BASE ++#define ETHERNET_BASE ar_eth_base ++#define ETHERNET_SIZE 0x00100000 ++#define ETHERNET_MACS 2 ++ ++#undef DMA_BASE ++#define DMA_BASE ar_dma_base ++#define DMA_SIZE 0x00100000 ++ ++ ++/* ++ * probe link timer - 5 secs ++ */ ++#define LINK_TIMER (5*HZ) ++ ++/* ++ * Interrupt register base address ++ */ ++#define INTERRUPT_BASE PHYS_TO_K1(ar_int_base) ++ ++/* ++ * Reset Register ++ */ ++#define AR531X_RESET (AR531X_RESETTMR + 0x0020) ++#define RESET_SYSTEM 0x00000001 /* cold reset full system */ ++#define RESET_PROC 0x00000002 /* cold reset MIPS core */ ++#define RESET_WLAN0 0x00000004 /* cold reset WLAN MAC and BB */ ++#define RESET_EPHY0 0x00000008 /* cold reset ENET0 phy */ ++#define RESET_EPHY1 0x00000010 /* cold reset ENET1 phy */ ++#define RESET_ENET0 0x00000020 /* cold reset ENET0 mac */ ++#define RESET_ENET1 0x00000040 /* cold reset ENET1 mac */ ++ ++#define IS_DMA_TX_INT(X) (((X) & (DMA_STATUS_TI)) != 0) ++#define IS_DMA_RX_INT(X) (((X) & (DMA_STATUS_RI)) != 0) ++#define IS_DRIVER_OWNED(X) (((X) & (DMA_TX_OWN)) == 0) ++ ++#ifndef K1_TO_PHYS ++// hack ++#define K1_TO_PHYS(x) (((unsigned int)(x)) & 0x1FFFFFFF) /* kseg1 to physical */ ++#endif ++ ++#ifndef PHYS_TO_K1 ++// hack ++#define PHYS_TO_K1(x) (((unsigned int)(x)) | 0xA0000000) /* physical to kseg1 */ ++#endif ++ ++#define AR2313_TX_TIMEOUT (HZ/4) ++ ++/* ++ * Rings ++ */ ++#define DSC_RING_ENTRIES_SIZE (AR2313_DESCR_ENTRIES * sizeof(struct desc)) ++#define DSC_NEXT(idx) ((idx + 1) & (AR2313_DESCR_ENTRIES - 1)) ++ ++static inline int tx_space (u32 csm, u32 prd) ++{ ++ return (csm - prd - 1) & (AR2313_DESCR_ENTRIES - 1); ++} ++ ++#if MAX_SKB_FRAGS ++#define TX_RESERVED (MAX_SKB_FRAGS+1) /* +1 for message header */ ++#define tx_ring_full(csm, prd) (tx_space(csm, prd) <= TX_RESERVED) ++#else ++#define tx_ring_full 0 ++#endif ++ ++#define AR2313_MBGET 2 ++#define AR2313_MBSET 3 ++#define AR2313_PCI_RECONFIG 4 ++#define AR2313_PCI_DUMP 5 ++#define AR2313_TEST_PANIC 6 ++#define AR2313_TEST_NULLPTR 7 ++#define AR2313_READ_DATA 8 ++#define AR2313_WRITE_DATA 9 ++#define AR2313_GET_VERSION 10 ++#define AR2313_TEST_HANG 11 ++#define AR2313_SYNC 12 ++ ++ ++struct ar2313_cmd { ++ u32 cmd; ++ u32 address; /* virtual address of image */ ++ u32 length; /* size of image to download */ ++ u32 mailbox; /* mailbox to get/set */ ++ u32 data[2]; /* contents of mailbox to read/write */ ++}; ++ ++ ++/* ++ * Struct private for the Sibyte. ++ * ++ * Elements are grouped so variables used by the tx handling goes ++ * together, and will go into the same cache lines etc. in order to ++ * avoid cache line contention between the rx and tx handling on SMP. ++ * ++ * Frequently accessed variables are put at the beginning of the ++ * struct to help the compiler generate better/shorter code. ++ */ ++struct ar2313_private ++{ ++ int version; ++ u32 mb[2]; ++ ++ volatile ETHERNET_STRUCT *eth_regs; ++ volatile DMA *dma_regs; ++ volatile u32 *int_regs; ++ ++ spinlock_t lock; /* Serialise access to device */ ++ ++ /* ++ * RX and TX descriptors, must be adjacent ++ */ ++ ar2313_descr_t *rx_ring; ++ ar2313_descr_t *tx_ring; ++ ++ ++ struct sk_buff **rx_skb; ++ struct sk_buff **tx_skb; ++ ++ /* ++ * RX elements ++ */ ++ u32 rx_skbprd; ++ u32 cur_rx; ++ ++ /* ++ * TX elements ++ */ ++ u32 tx_prd; ++ u32 tx_csm; ++ ++ /* ++ * Misc elements ++ */ ++ int board_idx; ++ char name[48]; ++ struct net_device_stats stats; ++ struct { ++ u32 address; ++ u32 length; ++ char *mapping; ++ } desc; ++ ++ ++ struct timer_list link_timer; ++ unsigned short phy; /* merlot phy = 1, samsung phy = 0x1f */ ++ unsigned short mac; ++ unsigned short link; /* 0 - link down, 1 - link up */ ++ u16 phyData; ++ ++ struct tasklet_struct rx_tasklet; ++ int unloading; ++}; ++ ++ ++/* ++ * Prototypes ++ */ ++static int ar2313_init(struct net_device *dev); ++#ifdef TX_TIMEOUT ++static void ar2313_tx_timeout(struct net_device *dev); ++#endif ++#if 0 ++static void ar2313_multicast_list(struct net_device *dev); ++#endif ++static int ar2313_restart(struct net_device *dev); ++#if DEBUG ++static void ar2313_dump_regs(struct net_device *dev); ++#endif ++static void ar2313_load_rx_ring(struct net_device *dev, int bufs); ++static irqreturn_t ar2313_interrupt(int irq, void *dev_id, struct pt_regs *regs); ++static int ar2313_open(struct net_device *dev); ++static int ar2313_start_xmit(struct sk_buff *skb, struct net_device *dev); ++static int ar2313_close(struct net_device *dev); ++static int ar2313_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); ++static void ar2313_init_cleanup(struct net_device *dev); ++static int ar2313_setup_timer(struct net_device *dev); ++static void ar2313_link_timer_fn(unsigned long data); ++static void ar2313_check_link(struct net_device *dev); ++static struct net_device_stats *ar2313_get_stats(struct net_device *dev); ++#endif /* _AR2313_H_ */ +diff -Nur linux-2.6.17/drivers/net/ar2313/ar2313_msg.h linux-2.6.17-owrt/drivers/net/ar2313/ar2313_msg.h +--- linux-2.6.17/drivers/net/ar2313/ar2313_msg.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.17-owrt/drivers/net/ar2313/ar2313_msg.h 2006-06-19 12:05:29.000000000 +0200 +@@ -0,0 +1,17 @@ ++#ifndef _AR2313_MSG_H_ ++#define _AR2313_MSG_H_ ++ ++#define AR2313_MTU 1692 ++#define AR2313_PRIOS 1 ++#define AR2313_QUEUES (2*AR2313_PRIOS) ++ ++#define AR2313_DESCR_ENTRIES 64 ++ ++typedef struct { ++ volatile unsigned int status; // OWN, Device control and status. ++ volatile unsigned int devcs; // pkt Control bits + Length ++ volatile unsigned int addr; // Current Address. ++ volatile unsigned int descr; // Next descriptor in chain. ++} ar2313_descr_t; ++ ++#endif /* _AR2313_MSG_H_ */ +diff -Nur linux-2.6.17/drivers/net/ar2313/dma.h linux-2.6.17-owrt/drivers/net/ar2313/dma.h +--- linux-2.6.17/drivers/net/ar2313/dma.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.17-owrt/drivers/net/ar2313/dma.h 2006-06-19 12:05:29.000000000 +0200 +@@ -0,0 +1,135 @@ ++#ifndef __ARUBA_DMA_H__ ++#define __ARUBA_DMA_H__ ++ ++/******************************************************************************* ++ * ++ * Copyright 2002 Integrated Device Technology, Inc. ++ * All rights reserved. ++ * ++ * DMA register definition. ++ * ++ * File : $Id: dma.h,v 1.3 2002/06/06 18:34:03 astichte Exp $ ++ * ++ * Author : ryan.holmQVist@idt.com ++ * Date : 20011005 ++ * Update : ++ * $Log: dma.h,v $ ++ * Revision 1.3 2002/06/06 18:34:03 astichte ++ * Added XXX_PhysicalAddress and XXX_VirtualAddress ++ * ++ * Revision 1.2 2002/06/05 18:30:46 astichte ++ * Removed IDTField ++ * ++ * Revision 1.1 2002/05/29 17:33:21 sysarch ++ * jba File moved from vcode/include/idt/acacia ++ * ++ * ++ ******************************************************************************/ ++ ++#define AR_BIT(x) (1 << (x)) ++#define DMA_RX_ERR_CRC AR_BIT(1) ++#define DMA_RX_ERR_DRIB AR_BIT(2) ++#define DMA_RX_ERR_MII AR_BIT(3) ++#define DMA_RX_EV2 AR_BIT(5) ++#define DMA_RX_ERR_COL AR_BIT(6) ++#define DMA_RX_LONG AR_BIT(7) ++#define DMA_RX_LS AR_BIT(8) /* last descriptor */ ++#define DMA_RX_FS AR_BIT(9) /* first descriptor */ ++#define DMA_RX_MF AR_BIT(10) /* multicast frame */ ++#define DMA_RX_ERR_RUNT AR_BIT(11) /* runt frame */ ++#define DMA_RX_ERR_LENGTH AR_BIT(12) /* length error */ ++#define DMA_RX_ERR_DESC AR_BIT(14) /* descriptor error */ ++#define DMA_RX_ERROR AR_BIT(15) /* error summary */ ++#define DMA_RX_LEN_MASK 0x3fff0000 ++#define DMA_RX_LEN_SHIFT 16 ++#define DMA_RX_FILT AR_BIT(30) ++#define DMA_RX_OWN AR_BIT(31) /* desc owned by DMA controller */ ++ ++#define DMA_RX1_BSIZE_MASK 0x000007ff ++#define DMA_RX1_BSIZE_SHIFT 0 ++#define DMA_RX1_CHAINED AR_BIT(24) ++#define DMA_RX1_RER AR_BIT(25) ++ ++#define DMA_TX_ERR_UNDER AR_BIT(1) /* underflow error */ ++#define DMA_TX_ERR_DEFER AR_BIT(2) /* excessive deferral */ ++#define DMA_TX_COL_MASK 0x78 ++#define DMA_TX_COL_SHIFT 3 ++#define DMA_TX_ERR_HB AR_BIT(7) /* hearbeat failure */ ++#define DMA_TX_ERR_COL AR_BIT(8) /* excessive collisions */ ++#define DMA_TX_ERR_LATE AR_BIT(9) /* late collision */ ++#define DMA_TX_ERR_LINK AR_BIT(10) /* no carrier */ ++#define DMA_TX_ERR_LOSS AR_BIT(11) /* loss of carrier */ ++#define DMA_TX_ERR_JABBER AR_BIT(14) /* transmit jabber timeout */ ++#define DMA_TX_ERROR AR_BIT(15) /* frame aborted */ ++#define DMA_TX_OWN AR_BIT(31) /* descr owned by DMA controller */ ++ ++#define DMA_TX1_BSIZE_MASK 0x000007ff ++#define DMA_TX1_BSIZE_SHIFT 0 ++#define DMA_TX1_CHAINED AR_BIT(24) /* chained descriptors */ ++#define DMA_TX1_TER AR_BIT(25) /* transmit end of ring */ ++#define DMA_TX1_FS AR_BIT(29) /* first segment */ ++#define DMA_TX1_LS AR_BIT(30) /* last segment */ ++#define DMA_TX1_IC AR_BIT(31) /* interrupt on completion */ ++ ++#define RCVPKT_LENGTH(X) (X >> 16) /* Received pkt Length */ ++ ++#define MAC_CONTROL_RE AR_BIT(2) /* receive enable */ ++#define MAC_CONTROL_TE AR_BIT(3) /* transmit enable */ ++#define MAC_CONTROL_DC AR_BIT(5) /* Deferral check*/ ++#define MAC_CONTROL_ASTP AR_BIT(8) /* Auto pad strip */ ++#define MAC_CONTROL_DRTY AR_BIT(10) /* Disable retry */ ++#define MAC_CONTROL_DBF AR_BIT(11) /* Disable bcast frames */ ++#define MAC_CONTROL_LCC AR_BIT(12) /* late collision ctrl */ ++#define MAC_CONTROL_HP AR_BIT(13) /* Hash Perfect filtering */ ++#define MAC_CONTROL_HASH AR_BIT(14) /* Unicast hash filtering */ ++#define MAC_CONTROL_HO AR_BIT(15) /* Hash only filtering */ ++#define MAC_CONTROL_PB AR_BIT(16) /* Pass Bad frames */ ++#define MAC_CONTROL_IF AR_BIT(17) /* Inverse filtering */ ++#define MAC_CONTROL_PR AR_BIT(18) /* promiscuous mode (valid frames only) */ ++#define MAC_CONTROL_PM AR_BIT(19) /* pass multicast */ ++#define MAC_CONTROL_F AR_BIT(20) /* full-duplex */ ++#define MAC_CONTROL_DRO AR_BIT(23) /* Disable Receive Own */ ++#define MAC_CONTROL_HBD AR_BIT(28) /* heart-beat disabled (MUST BE SET) */ ++#define MAC_CONTROL_BLE AR_BIT(30) /* big endian mode */ ++#define MAC_CONTROL_RA AR_BIT(31) /* receive all (valid and invalid frames) */ ++ ++#define MII_ADDR_BUSY AR_BIT(0) ++#define MII_ADDR_WRITE AR_BIT(1) ++#define MII_ADDR_REG_SHIFT 6 ++#define MII_ADDR_PHY_SHIFT 11 ++#define MII_DATA_SHIFT 0 ++ ++#define FLOW_CONTROL_FCE AR_BIT(1) ++ ++#define DMA_BUS_MODE_SWR AR_BIT(0) /* software reset */ ++#define DMA_BUS_MODE_BLE AR_BIT(7) /* big endian mode */ ++#define DMA_BUS_MODE_PBL_SHIFT 8 /* programmable burst length 32 */ ++#define DMA_BUS_MODE_DBO AR_BIT(20) /* big-endian descriptors */ ++ ++#define DMA_STATUS_TI AR_BIT(0) /* transmit interrupt */ ++#define DMA_STATUS_TPS AR_BIT(1) /* transmit process stopped */ ++#define DMA_STATUS_TU AR_BIT(2) /* transmit buffer unavailable */ ++#define DMA_STATUS_TJT AR_BIT(3) /* transmit buffer timeout */ ++#define DMA_STATUS_UNF AR_BIT(5) /* transmit underflow */ ++#define DMA_STATUS_RI AR_BIT(6) /* receive interrupt */ ++#define DMA_STATUS_RU AR_BIT(7) /* receive buffer unavailable */ ++#define DMA_STATUS_RPS AR_BIT(8) /* receive process stopped */ ++#define DMA_STATUS_ETI AR_BIT(10) /* early transmit interrupt */ ++#define DMA_STATUS_FBE AR_BIT(13) /* fatal bus interrupt */ ++#define DMA_STATUS_ERI AR_BIT(14) /* early receive interrupt */ ++#define DMA_STATUS_AIS AR_BIT(15) /* abnormal interrupt summary */ ++#define DMA_STATUS_NIS AR_BIT(16) /* normal interrupt summary */ ++#define DMA_STATUS_RS_SHIFT 17 /* receive process state */ ++#define DMA_STATUS_TS_SHIFT 20 /* transmit process state */ ++#define DMA_STATUS_EB_SHIFT 23 /* error bits */ + -+ switch (cmd) { -+ case SIOCDEVPRIVATE: { -+ struct ar2313_cmd scmd; ++#define DMA_CONTROL_SR AR_BIT(1) /* start receive */ ++#define DMA_CONTROL_ST AR_BIT(13) /* start transmit */ ++#define DMA_CONTROL_SF AR_BIT(21) /* store and forward */ + -+ if (copy_from_user(&scmd, ifr->ifr_data, sizeof(scmd))) -+ return -EFAULT; ++#endif // __ARUBA_DMA_H__ + -+#if DEBUG -+ printk("%s: ioctl devprivate c=%d a=%x l=%d m=%d d=%x,%x\n", -+ dev->name, scmd.cmd, -+ scmd.address, scmd.length, -+ scmd.mailbox, scmd.data[0], scmd.data[1]); -+#endif /* DEBUG */ + -+ switch (scmd.cmd) { -+ case AR2313_READ_DATA: -+ if(scmd.length==4){ -+ scmd.data[0] = *((u32*)scmd.address); -+ } else if(scmd.length==2) { -+ scmd.data[0] = *((u16*)scmd.address); -+ } else if (scmd.length==1) { -+ scmd.data[0] = *((u8*)scmd.address); -+ } else { -+ return -EOPNOTSUPP; -+ } -+ if(copy_to_user(ifr->ifr_data, &scmd, sizeof(scmd))) -+ return -EFAULT; -+ break; + -+ case AR2313_WRITE_DATA: -+ if(scmd.length==4){ -+ *((u32*)scmd.address) = scmd.data[0]; -+ } else if(scmd.length==2) { -+ *((u16*)scmd.address) = scmd.data[0]; -+ } else if (scmd.length==1) { -+ *((u8*)scmd.address) = scmd.data[0]; -+ } else { -+ return -EOPNOTSUPP; -+ } -+ break; + -+ case AR2313_GET_VERSION: -+ // SAMEER: sprintf((char*) &scmd, "%s", ARUBA_VERSION); -+ if(copy_to_user(ifr->ifr_data, &scmd, sizeof(scmd))) -+ return -EFAULT; -+ break; + -+ default: -+ return -EOPNOTSUPP; -+ } -+ return 0; -+ } +diff -Nur linux-2.6.17/drivers/net/ar2313/Makefile linux-2.6.17-owrt/drivers/net/ar2313/Makefile +--- linux-2.6.17/drivers/net/ar2313/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.17-owrt/drivers/net/ar2313/Makefile 2006-06-19 12:25:58.000000000 +0200 +@@ -0,0 +1,5 @@ ++# ++# Makefile for the AR2313 ethernet driver ++# ++ ++obj-$(CONFIG_AR2313) += ar2313.o +diff -Nur linux-2.6.17/drivers/net/ar2313/platform.h linux-2.6.17-owrt/drivers/net/ar2313/platform.h +--- linux-2.6.17/drivers/net/ar2313/platform.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.17-owrt/drivers/net/ar2313/platform.h 2006-06-19 12:05:29.000000000 +0200 +@@ -0,0 +1,128 @@ ++/******************************************************************************** ++ Title: $Source: platform.h,v $ ++ ++ Author: Dan Steinberg ++ Copyright Integrated Device Technology 2001 ++ ++ Purpose: AR2313 Register/Bit Definitions ++ ++ Update: ++ $Log: platform.h,v $ + -+ case SIOCETHTOOL: -+ return netdev_ethtool_ioctl(dev, (void *) ifr->ifr_data); ++ Notes: See Merlot architecture spec for complete details. Note, all ++ addresses are virtual addresses in kseg1 (Uncached, Unmapped). ++ ++********************************************************************************/ + -+ case SIOCGMIIPHY: /* Get address of MII PHY in use. */ -+ data->phy_id = 1; -+ /* Fall Through */ ++#ifndef PLATFORM_H ++#define PLATFORM_H + -+ case SIOCGMIIREG: /* Read MII PHY register. */ -+ case SIOCDEVPRIVATE+1: /* for binary compat, remove in 2.5 */ -+ data->val_out = armiiread(data->phy_id & 0x1f, -+ data->reg_num & 0x1f); -+ return 0; -+ case SIOCSMIIREG: /* Write MII PHY register. */ -+ case SIOCDEVPRIVATE+2: /* for binary compat, remove in 2.5 */ -+ if (!capable(CAP_NET_ADMIN)) -+ return -EPERM; -+ armiiwrite(data->phy_id & 0x1f, -+ data->reg_num & 0x1f, data->val_in); -+ return 0; ++#define BIT(x) (1 << (x)) + -+ case SIOCSIFHWADDR: -+ if (copy_from_user(dev->dev_addr, ifr->ifr_data, sizeof(dev->dev_addr))) -+ return -EFAULT; -+ return 0; ++#define RESET_BASE 0xBC003020 ++#define RESET_VALUE 0x00000001 + -+ case SIOCGIFHWADDR: -+ if (copy_to_user(ifr->ifr_data, dev->dev_addr, sizeof(dev->dev_addr))) -+ return -EFAULT; -+ return 0; ++/******************************************************************** ++ * Device controller ++ ********************************************************************/ ++typedef struct { ++ volatile unsigned int flash0; ++} DEVICE; + -+ default: -+ break; -+ } ++#define device (*((volatile DEVICE *) DEV_CTL_BASE)) + -+ return -EOPNOTSUPP; -+} ++// DDRC register ++#define DEV_WP (1<<26) + -+static struct net_device_stats *ar2313_get_stats(struct net_device *dev) -+{ -+ struct ar2313_private *sp = dev->priv; -+ return &sp->stats; -+} ++/******************************************************************** ++ * DDR controller ++ ********************************************************************/ ++typedef struct { ++ volatile unsigned int ddrc0; ++ volatile unsigned int ddrc1; ++ volatile unsigned int ddrrefresh; ++} DDR; + -+static short -+armiiread(short phy, short reg) -+{ -+ volatile ETHERNET_STRUCT * ethernet; ++#define ddr (*((volatile DDR *) DDR_BASE)) + -+ ethernet = (volatile ETHERNET_STRUCT *)ETHERNET_BASE; /* always MAC 0 */ -+ ethernet->mii_addr = ((reg << MII_ADDR_REG_SHIFT) | -+ (phy << MII_ADDR_PHY_SHIFT)); -+ while (ethernet->mii_addr & MII_ADDR_BUSY); -+ return (ethernet->mii_data >> MII_DATA_SHIFT); -+} ++// DDRC register ++#define DDRC_CS(i) ((i&0x3)<<0) ++#define DDRC_WE (1<<2) + -+static void -+armiiwrite(short phy, short reg, short data) -+{ -+ volatile ETHERNET_STRUCT * ethernet; ++/******************************************************************** ++ * Ethernet interfaces ++ ********************************************************************/ ++#define ETHERNET_BASE 0xB8200000 + -+ ethernet = (volatile ETHERNET_STRUCT *)ETHERNET_BASE; /* always MAC 0 */ -+ while (ethernet->mii_addr & MII_ADDR_BUSY); -+ ethernet->mii_data = data << MII_DATA_SHIFT; -+ ethernet->mii_addr = ((reg << MII_ADDR_REG_SHIFT) | -+ (phy << MII_ADDR_PHY_SHIFT) | -+ MII_ADDR_WRITE); -+} ++// ++// New Combo structure for Both Eth0 AND eth1 ++// ++typedef struct { ++ volatile unsigned int mac_control; /* 0x00 */ ++ volatile unsigned int mac_addr[2]; /* 0x04 - 0x08*/ ++ volatile unsigned int mcast_table[2]; /* 0x0c - 0x10 */ ++ volatile unsigned int mii_addr; /* 0x14 */ ++ volatile unsigned int mii_data; /* 0x18 */ ++ volatile unsigned int flow_control; /* 0x1c */ ++ volatile unsigned int vlan_tag; /* 0x20 */ ++ volatile unsigned int pad[7]; /* 0x24 - 0x3c */ ++ volatile unsigned int ucast_table[8]; /* 0x40-0x5c */ ++ ++} ETHERNET_STRUCT; ++ ++/******************************************************************** ++ * Interrupt controller ++ ********************************************************************/ ++ ++typedef struct { ++ volatile unsigned int wdog_control; /* 0x08 */ ++ volatile unsigned int wdog_timer; /* 0x0c */ ++ volatile unsigned int misc_status; /* 0x10 */ ++ volatile unsigned int misc_mask; /* 0x14 */ ++ volatile unsigned int global_status; /* 0x18 */ ++ volatile unsigned int reserved; /* 0x1c */ ++ volatile unsigned int reset_control; /* 0x20 */ ++} INTERRUPT; ++ ++#define interrupt (*((volatile INTERRUPT *) INTERRUPT_BASE)) ++ ++#define INTERRUPT_MISC_TIMER BIT(0) ++#define INTERRUPT_MISC_AHBPROC BIT(1) ++#define INTERRUPT_MISC_AHBDMA BIT(2) ++#define INTERRUPT_MISC_GPIO BIT(3) ++#define INTERRUPT_MISC_UART BIT(4) ++#define INTERRUPT_MISC_UARTDMA BIT(5) ++#define INTERRUPT_MISC_WATCHDOG BIT(6) ++#define INTERRUPT_MISC_LOCAL BIT(7) ++ ++#define INTERRUPT_GLOBAL_ETH BIT(2) ++#define INTERRUPT_GLOBAL_WLAN BIT(3) ++#define INTERRUPT_GLOBAL_MISC BIT(4) ++#define INTERRUPT_GLOBAL_ITIMER BIT(5) ++ ++/******************************************************************** ++ * DMA controller ++ ********************************************************************/ ++#define DMA_BASE 0xB8201000 ++ ++typedef struct { ++ volatile unsigned int bus_mode; /* 0x00 (CSR0) */ ++ volatile unsigned int xmt_poll; /* 0x04 (CSR1) */ ++ volatile unsigned int rcv_poll; /* 0x08 (CSR2) */ ++ volatile unsigned int rcv_base; /* 0x0c (CSR3) */ ++ volatile unsigned int xmt_base; /* 0x10 (CSR4) */ ++ volatile unsigned int status; /* 0x14 (CSR5) */ ++ volatile unsigned int control; /* 0x18 (CSR6) */ ++ volatile unsigned int intr_ena; /* 0x1c (CSR7) */ ++ volatile unsigned int rcv_missed; /* 0x20 (CSR8) */ ++ volatile unsigned int reserved[11]; /* 0x24-0x4c (CSR9-19) */ ++ volatile unsigned int cur_tx_buf_addr; /* 0x50 (CSR20) */ ++ volatile unsigned int cur_rx_buf_addr; /* 0x50 (CSR21) */ ++} DMA; ++ ++#define dma (*((volatile DMA *) DMA_BASE)) ++ ++// macro to convert from virtual to physical address ++#define phys_addr(x) (x & 0x1fffffff) ++ ++#endif /* PLATFORM_H */ +diff -Nur linux-2.6.17/drivers/net/Kconfig linux-2.6.17-owrt/drivers/net/Kconfig +--- linux-2.6.17/drivers/net/Kconfig 2006-06-19 12:05:01.000000000 +0200 ++++ linux-2.6.17-owrt/drivers/net/Kconfig 2006-06-19 12:26:35.000000000 +0200 +@@ -310,6 +310,12 @@ + + source "drivers/net/arm/Kconfig" + ++config AR2313 ++ tristate "AR2313 Ethernet support" ++ depends on NET_ETHERNET && MACH_ARUBA ++ help ++ Support for the AR2313 Ethernet part on Aruba AP60/61 + + config IDT_RC32434_ETH + tristate "IDT RC32434 Local Ethernet support" + depends on NET_ETHERNET +diff -Nur linux-2.6.17/drivers/net/Makefile linux-2.6.17-owrt/drivers/net/Makefile +--- linux-2.6.17/drivers/net/Makefile 2006-06-19 12:05:01.000000000 +0200 ++++ linux-2.6.17-owrt/drivers/net/Makefile 2006-06-19 12:27:02.000000000 +0200 +@@ -12,6 +12,7 @@ + obj-$(CONFIG_CHELSIO_T1) += chelsio/ + obj-$(CONFIG_BONDING) += bonding/ + obj-$(CONFIG_GIANFAR) += gianfar_driver.o ++obj-$(CONFIG_AR2313) += ar2313/ + + gianfar_driver-objs := gianfar.o \ + gianfar_ethtool.o \