some additions to the ar7 system code, added cpmac network driver
authorFelix Fietkau <nbd@openwrt.org>
Sat, 9 Jul 2005 15:05:01 +0000 (15:05 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Sat, 9 Jul 2005 15:05:01 +0000 (15:05 +0000)
SVN-Revision: 1383

openwrt/target/linux/linux-2.4/Makefile
openwrt/target/linux/linux-2.4/config/ar7
openwrt/target/linux/linux-2.4/patches/ar7/000-ar7_support.patch
openwrt/target/linux/linux-2.4/patches/ar7/002-net_driver_cpmac.patch [new file with mode: 0644]

index 6993c3de7384d2388156fd736e5b78d9706bd6ea..de0f815cad7d10d72bbf75ff1d791dd2f934ad6b 100644 (file)
@@ -52,6 +52,10 @@ ifeq ($(BOARD),brcm)
 include ./broadcom.mk
 endif
 
+
+$(eval $(call KMOD_template,CPMAC,cpmac,\
+        $(MODULES_DIR)/kernel/drivers/net/avalanche_cpmac/avalanche_cpmac.o \
+,CONFIG_MIPS_AVALANCHE_CPMAC))
 $(eval $(call KMOD_template,USB_ACM,usb-acm,\
        $(MODULES_DIR)/kernel/drivers/usb/acm.o \
 ,CONFIG_USB_ACM))
index 34af62c5ff97626e5d2fec75e4a53fc2c2c03e1b..d1b474246e9b8ed17645d41c0732f8b616f66b6e 100644 (file)
@@ -166,7 +166,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_OOM_KILLER is not set
 CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="root=/dev/mtdblock0 console=ttyS0,38400 rootfstype=squashfs,jffs2 init=/etc/preinit noinitrd"
+CONFIG_CMDLINE="root=/dev/mtdblock0 rootfstype=squashfs,jffs2 init=/etc/preinit noinitrd"
 
 #
 # Memory Technology Devices (MTD)
@@ -605,6 +605,12 @@ CONFIG_NET_RANDOM=y
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
+CONFIG_MIPS_AVALANCHE_CPMAC=m
+CONFIG_MIPS_CPMAC_INIT_BUF_MALLOC=y
+CONFIG_MIPS_CPMAC_PORTS=1
+CONFIG_AVALANCHE_CPMAC_AUTO=y
+# CONFIG_AVALANCHE_LOW_CPMAC is not set
+# CONFIG_AVALANCHE_HIGH_CPMAC is not set
 # CONFIG_SUNLANCE is not set
 # CONFIG_SUNBMAC is not set
 # CONFIG_SUNQE is not set
index e06c7ee89ac6c808c4d2fa4302ec9489f2a76a55..109c85846d3f0d157026ffd712b1336eead64a26 100644 (file)
@@ -1,6 +1,6 @@
 diff -urN linux.old/arch/mips/ar7/avalanche/avalanche_jump.S linux.dev/arch/mips/ar7/avalanche/avalanche_jump.S
 --- linux.old/arch/mips/ar7/avalanche/avalanche_jump.S 1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/arch/mips/ar7/avalanche/avalanche_jump.S 2005-07-07 04:39:14.418226000 +0200
++++ linux.dev/arch/mips/ar7/avalanche/avalanche_jump.S 2005-07-09 08:00:15.286026000 +0200
 @@ -0,0 +1,69 @@
 +#include <linux/config.h>
 +#include <linux/threads.h>
@@ -71,9 +71,340 @@ diff -urN linux.old/arch/mips/ar7/avalanche/avalanche_jump.S linux.dev/arch/mips
 +END(jump_dedicated_interrupt)
 +
 +      .set at
+diff -urN linux.old/arch/mips/ar7/avalanche/avalanche_misc.c linux.dev/arch/mips/ar7/avalanche/avalanche_misc.c
+--- linux.old/arch/mips/ar7/avalanche/avalanche_misc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/ar7/avalanche/avalanche_misc.c 2005-07-09 08:00:15.287026000 +0200
+@@ -0,0 +1,327 @@
++#include <asm/ar7/sangam.h>
++#include <asm/ar7/avalanche_misc.h>
++#include <linux/module.h>
++#include <linux/spinlock.h>
++
++static unsigned int avalanche_vbus_freq;
++
++REMOTE_VLYNQ_DEV_RESET_CTRL_FN p_remote_vlynq_dev_reset_ctrl = NULL;
++
++/*****************************************************************************
++ * Reset Control Module.
++ *****************************************************************************/
++void avalanche_reset_ctrl(unsigned int module_reset_bit, 
++                          AVALANCHE_RESET_CTRL_T reset_ctrl)
++{
++    volatile unsigned int *reset_reg = (unsigned int*) AVALANCHE_RST_CTRL_PRCR;
++   
++    if(module_reset_bit >= 32 && module_reset_bit < 64)
++        return;
++
++    if(module_reset_bit >= 64)
++    {
++        if(p_remote_vlynq_dev_reset_ctrl)
++            return(p_remote_vlynq_dev_reset_ctrl(module_reset_bit - 64, reset_ctrl));
++        else
++            return;
++    }
++    
++    if(reset_ctrl == OUT_OF_RESET)
++        *reset_reg |= 1 << module_reset_bit;
++    else
++        *reset_reg &= ~(1 << module_reset_bit);
++}
++
++AVALANCHE_RESET_CTRL_T avalanche_get_reset_status(unsigned int module_reset_bit)
++{
++    volatile unsigned int *reset_reg = (unsigned int*) AVALANCHE_RST_CTRL_PRCR;
++
++    return (((*reset_reg) & (1 << module_reset_bit)) ? OUT_OF_RESET : IN_RESET );
++}
++
++void avalanche_sys_reset(AVALANCHE_SYS_RST_MODE_T mode)
++{
++    volatile unsigned int *sw_reset_reg = (unsigned int*) AVALANCHE_RST_CTRL_SWRCR;
++    *sw_reset_reg =  mode;
++}
++
++#define AVALANCHE_RST_CTRL_RSR_MASK 0x3
++
++AVALANCHE_SYS_RESET_STATUS_T avalanche_get_sys_last_reset_status()
++{
++    volatile unsigned int *sys_reset_status = (unsigned int*) AVALANCHE_RST_CTRL_RSR;
++
++    return ( (AVALANCHE_SYS_RESET_STATUS_T) (*sys_reset_status & AVALANCHE_RST_CTRL_RSR_MASK) );
++}
++
++
++/*****************************************************************************
++ * Power Control Module
++ *****************************************************************************/
++#define AVALANCHE_GLOBAL_POWER_DOWN_MASK    0x3FFFFFFF      /* bit 31, 30 masked */
++#define AVALANCHE_GLOBAL_POWER_DOWN_BIT     30              /* shift to bit 30, 31 */
++
++
++void avalanche_power_ctrl(unsigned int module_power_bit, AVALANCHE_POWER_CTRL_T power_ctrl)
++{
++    volatile unsigned int *power_reg = (unsigned int*)AVALANCHE_POWER_CTRL_PDCR;
++
++    if (power_ctrl == POWER_CTRL_POWER_DOWN)
++        /* power down the module */
++        *power_reg |= (1 << module_power_bit);
++    else
++        /* power on the module */
++        *power_reg &= (~(1 << module_power_bit));
++}
++
++AVALANCHE_POWER_CTRL_T avalanche_get_power_status(unsigned int module_power_bit)
++{
++    volatile unsigned int *power_status_reg = (unsigned int*)AVALANCHE_POWER_CTRL_PDCR;
++
++    return (((*power_status_reg) & (1 << module_power_bit)) ? POWER_CTRL_POWER_DOWN : POWER_CTRL_POWER_UP);
++}
++
++void avalanche_set_global_power_mode(AVALANCHE_SYS_POWER_MODE_T power_mode)
++{
++    volatile unsigned int *power_status_reg = (unsigned int*)AVALANCHE_POWER_CTRL_PDCR;
++
++    *power_status_reg &= AVALANCHE_GLOBAL_POWER_DOWN_MASK;
++    *power_status_reg |= ( power_mode << AVALANCHE_GLOBAL_POWER_DOWN_BIT);
++}
++
++AVALANCHE_SYS_POWER_MODE_T avalanche_get_global_power_mode(void)
++{
++    volatile unsigned int *power_status_reg = (unsigned int*)AVALANCHE_POWER_CTRL_PDCR;
++
++    return((AVALANCHE_SYS_POWER_MODE_T) (((*power_status_reg) & (~AVALANCHE_GLOBAL_POWER_DOWN_MASK)) 
++                                           >> AVALANCHE_GLOBAL_POWER_DOWN_BIT));
++}
++
++#if defined (CONFIG_AVALANCHE_GENERIC_GPIO)
++/*****************************************************************************
++ * GPIO  Control
++ *****************************************************************************/
++
++/****************************************************************************
++ * FUNCTION: avalanche_gpio_init
++ ***************************************************************************/
++void avalanche_gpio_init(void)
++{
++    spinlock_t closeLock;
++    unsigned int closeFlag;
++    volatile unsigned int *reset_reg = (unsigned int*) AVALANCHE_RST_CTRL_PRCR;
++    spin_lock_irqsave(&closeLock, closeFlag);
++    *reset_reg |= (1 << AVALANCHE_GPIO_RESET_BIT);
++    spin_unlock_irqrestore(&closeLock, closeFlag);  
++}
++
++/****************************************************************************
++ * FUNCTION: avalanche_gpio_ctrl
++ ***************************************************************************/
++int avalanche_gpio_ctrl(unsigned int gpio_pin,
++                        AVALANCHE_GPIO_PIN_MODE_T pin_mode,
++                        AVALANCHE_GPIO_PIN_DIRECTION_T pin_direction)
++{
++    spinlock_t closeLock;
++    unsigned int closeFlag;
++    volatile unsigned int *gpio_ctrl = (unsigned int*)AVALANCHE_GPIO_ENBL;
++
++    if(gpio_pin >= 32)
++        return(-1);
++
++    spin_lock_irqsave(&closeLock, closeFlag);
++
++    if(pin_mode == GPIO_PIN)
++    {
++        *gpio_ctrl |= (1 << gpio_pin);
++
++      gpio_ctrl = (unsigned int*)AVALANCHE_GPIO_DIR;
++        
++        if(pin_direction == GPIO_INPUT_PIN)
++            *gpio_ctrl |=  (1 << gpio_pin);
++        else
++            *gpio_ctrl &= ~(1 << gpio_pin);
++    }
++    else /* FUNCTIONAL PIN */
++    {
++        *gpio_ctrl &= ~(1 << gpio_pin);
++    }
++  
++    spin_unlock_irqrestore(&closeLock, closeFlag);  
++
++    return (0);
++}
++
++/****************************************************************************
++ * FUNCTION: avalanche_gpio_out
++ ***************************************************************************/
++int avalanche_gpio_out_bit(unsigned int gpio_pin, int value)
++{
++    spinlock_t closeLock;
++    unsigned int closeFlag;
++    volatile unsigned int *gpio_out = (unsigned int*) AVALANCHE_GPIO_DATA_OUT;
++ 
++    if(gpio_pin >= 32)
++        return(-1);
++    
++    spin_lock_irqsave(&closeLock, closeFlag);
++    if(value == TRUE)
++        *gpio_out |= 1 << gpio_pin;
++    else
++      *gpio_out &= ~(1 << gpio_pin);
++    spin_unlock_irqrestore(&closeLock, closeFlag);
++
++    return(0);
++}
++
++/****************************************************************************
++ * FUNCTION: avalanche_gpio_in
++ ***************************************************************************/
++int avalanche_gpio_in_bit(unsigned int gpio_pin)
++{
++    spinlock_t closeLock;
++    unsigned int closeFlag;
++    volatile unsigned int *gpio_in = (unsigned int*) AVALANCHE_GPIO_DATA_IN;
++    int ret_val = 0;
++    
++    if(gpio_pin >= 32)
++        return(-1);
++
++    spin_lock_irqsave(&closeLock, closeFlag); 
++    ret_val = ((*gpio_in) & (1 << gpio_pin));
++    spin_unlock_irqrestore(&closeLock, closeFlag);
++ 
++    return (ret_val);
++}
++
++/****************************************************************************
++ * FUNCTION: avalanche_gpio_out_val
++ ***************************************************************************/
++int avalanche_gpio_out_value(unsigned int out_val, unsigned int out_mask, 
++                           unsigned int reg_index)
++{
++    spinlock_t closeLock;
++    unsigned int closeFlag;
++    volatile unsigned int *gpio_out = (unsigned int*) AVALANCHE_GPIO_DATA_OUT;
++
++    if(reg_index > 0)
++        return(-1);
++
++    spin_lock_irqsave(&closeLock, closeFlag);
++    *gpio_out &= ~out_mask;
++    *gpio_out |= out_val;
++    spin_unlock_irqrestore(&closeLock, closeFlag);
++
++    return(0);
++}
++
++/****************************************************************************
++ * FUNCTION: avalanche_gpio_in_value
++ ***************************************************************************/
++int avalanche_gpio_in_value(unsigned int* in_val, unsigned int reg_index)
++{
++    spinlock_t closeLock;
++    unsigned int closeFlag;
++    volatile unsigned int *gpio_in = (unsigned int*) AVALANCHE_GPIO_DATA_IN;
++ 
++    if(reg_index > 0)
++        return(-1);
++
++    spin_lock_irqsave(&closeLock, closeFlag);
++    *in_val = *gpio_in;
++    spin_unlock_irqrestore(&closeLock, closeFlag);
++
++    return (0);
++}
++
++#endif
++
++/***********************************************************************
++ *
++ *    Wakeup Control Module for TNETV1050 Communication Processor
++ *
++ ***********************************************************************/
++
++#define AVALANCHE_WAKEUP_POLARITY_BIT   16
++
++void avalanche_wakeup_ctrl(AVALANCHE_WAKEUP_INTERRUPT_T wakeup_int,
++                           AVALANCHE_WAKEUP_CTRL_T      wakeup_ctrl,
++                           AVALANCHE_WAKEUP_POLARITY_T  wakeup_polarity)
++{
++    volatile unsigned int *wakeup_status_reg = (unsigned int*) AVALANCHE_WAKEUP_CTRL_WKCR;
++
++    /* enable/disable */
++    if (wakeup_ctrl == WAKEUP_ENABLED)
++        /* enable wakeup */
++        *wakeup_status_reg |= wakeup_int;
++    else
++        /* disable wakeup */
++        *wakeup_status_reg &= (~wakeup_int);
++
++    /* set polarity */
++    if (wakeup_polarity == WAKEUP_ACTIVE_LOW)
++        *wakeup_status_reg |=  (wakeup_int << AVALANCHE_WAKEUP_POLARITY_BIT);
++    else
++        *wakeup_status_reg &= ~(wakeup_int << AVALANCHE_WAKEUP_POLARITY_BIT);
++}
++
++void avalanche_set_vbus_freq(unsigned int new_vbus_freq)
++{
++    avalanche_vbus_freq = new_vbus_freq;
++}
++
++unsigned int avalanche_get_vbus_freq()
++{
++    return(avalanche_vbus_freq);
++}
++
++unsigned int avalanche_get_chip_version_info()
++{
++    return(*(volatile unsigned int*)AVALANCHE_CVR);
++}
++
++SET_MDIX_ON_CHIP_FN_T p_set_mdix_on_chip_fn = NULL;
++
++int avalanche_set_mdix_on_chip(unsigned int base_addr, unsigned int operation)
++{
++    if(p_set_mdix_on_chip_fn)
++        return (p_set_mdix_on_chip_fn(base_addr, operation));
++    else
++        return(-1);
++}
++
++unsigned int avalanche_is_mdix_on_chip(void)
++{
++    return(p_set_mdix_on_chip_fn ? 1:0);
++}
++
++/* software abstraction for HAL */
++
++
++EXPORT_SYMBOL(avalanche_reset_ctrl);
++EXPORT_SYMBOL(avalanche_get_reset_status);
++EXPORT_SYMBOL(avalanche_sys_reset);
++EXPORT_SYMBOL(avalanche_get_sys_last_reset_status);
++EXPORT_SYMBOL(avalanche_power_ctrl);
++EXPORT_SYMBOL(avalanche_get_power_status);
++EXPORT_SYMBOL(avalanche_set_global_power_mode);
++EXPORT_SYMBOL(avalanche_get_global_power_mode);
++EXPORT_SYMBOL(avalanche_set_mdix_on_chip);
++EXPORT_SYMBOL(avalanche_is_mdix_on_chip);
++
++
++
++#if defined (CONFIG_AVALANCHE_GENERIC_GPIO)
++EXPORT_SYMBOL(avalanche_gpio_init);
++EXPORT_SYMBOL(avalanche_gpio_ctrl);
++EXPORT_SYMBOL(avalanche_gpio_out_bit);
++EXPORT_SYMBOL(avalanche_gpio_in_bit);
++EXPORT_SYMBOL(avalanche_gpio_out_value);
++EXPORT_SYMBOL(avalanche_gpio_in_value);
++#endif
++
++EXPORT_SYMBOL(avalanche_set_vbus_freq);
++EXPORT_SYMBOL(avalanche_get_vbus_freq);
++
++EXPORT_SYMBOL(avalanche_get_chip_version_info);
++
 diff -urN linux.old/arch/mips/ar7/avalanche/avalanche_paging.c linux.dev/arch/mips/ar7/avalanche/avalanche_paging.c
 --- linux.old/arch/mips/ar7/avalanche/avalanche_paging.c       1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/arch/mips/ar7/avalanche/avalanche_paging.c       2005-07-07 04:39:14.418226000 +0200
++++ linux.dev/arch/mips/ar7/avalanche/avalanche_paging.c       2005-07-09 08:00:15.287026000 +0200
 @@ -0,0 +1,314 @@
 +/*
 + *  -*- linux-c -*-
@@ -391,8 +722,8 @@ diff -urN linux.old/arch/mips/ar7/avalanche/avalanche_paging.c linux.dev/arch/mi
 +}
 diff -urN linux.old/arch/mips/ar7/avalanche/Makefile linux.dev/arch/mips/ar7/avalanche/Makefile
 --- linux.old/arch/mips/ar7/avalanche/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/arch/mips/ar7/avalanche/Makefile 2005-07-07 04:39:14.417226000 +0200
-@@ -0,0 +1,13 @@
++++ linux.dev/arch/mips/ar7/avalanche/Makefile 2005-07-09 08:00:15.288026000 +0200
+@@ -0,0 +1,16 @@
 +.S.s:
 +      $(CPP) $(AFLAGS) $< -o $*.s
 +
@@ -403,12 +734,15 @@ diff -urN linux.old/arch/mips/ar7/avalanche/Makefile linux.dev/arch/mips/ar7/ava
 +
 +O_TARGET := avalanche.o
 +
-+obj-y += avalanche_paging.o avalanche_jump.o
++export-objs := avalanche_misc.o
++
++obj-y += avalanche_paging.o avalanche_jump.o avalanche_misc.o
 +
 +include $(TOPDIR)/Rules.make
++
 diff -urN linux.old/arch/mips/ar7/cmdline.c linux.dev/arch/mips/ar7/cmdline.c
 --- linux.old/arch/mips/ar7/cmdline.c  1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/arch/mips/ar7/cmdline.c  2005-07-07 04:39:14.419226000 +0200
++++ linux.dev/arch/mips/ar7/cmdline.c  2005-07-09 08:00:15.288026000 +0200
 @@ -0,0 +1,64 @@
 +/*
 + * Carsten Langgaard, carstenl@mips.com
@@ -474,10 +808,36 @@ diff -urN linux.old/arch/mips/ar7/cmdline.c linux.dev/arch/mips/ar7/cmdline.c
 +              --cp;
 +      *cp = '\0';
 +}
+diff -urN linux.old/arch/mips/ar7/hal/misc.c linux.dev/arch/mips/ar7/hal/misc.c
+--- linux.old/arch/mips/ar7/hal/misc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/ar7/hal/misc.c 2005-07-09 08:00:15.288026000 +0200
+@@ -0,0 +1,22 @@
++#include <linux/slab.h>
++
++void *os_platform_malloc(unsigned int size)
++{
++      return kmalloc(size,GFP_KERNEL);
++}
++
++void os_platform_free(void *p)
++{
++      kfree(p);
++}
++
++void *os_platform_memset(void *p, int num, unsigned int size)
++{
++        return memset(p,num,size);
++}
++
++EXPORT_SYMBOL(os_platform_malloc);
++EXPORT_SYMBOL(os_platform_free);
++EXPORT_SYMBOL(os_platform_memset);
++
++
 diff -urN linux.old/arch/mips/ar7/init.c linux.dev/arch/mips/ar7/init.c
 --- linux.old/arch/mips/ar7/init.c     1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/arch/mips/ar7/init.c     2005-07-07 04:39:14.419226000 +0200
-@@ -0,0 +1,144 @@
++++ linux.dev/arch/mips/ar7/init.c     2005-07-09 08:11:36.592452520 +0200
+@@ -0,0 +1,146 @@
 +/*
 + * Carsten Langgaard, carstenl@mips.com
 + * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
@@ -501,6 +861,7 @@ diff -urN linux.old/arch/mips/ar7/init.c linux.dev/arch/mips/ar7/init.c
 +#include <linux/init.h>
 +#include <linux/string.h>
 +#include <linux/kernel.h>
++#include <linux/module.h>
 +
 +#include <asm/io.h>
 +#include <asm/mips-boards/prom.h>
@@ -519,7 +880,6 @@ diff -urN linux.old/arch/mips/ar7/init.c linux.dev/arch/mips/ar7/init.c
 +#define MAX_ENV_ENTRY 80
 +
 +static t_env_var local_envp[MAX_ENV_ENTRY];
-+
 +int init_debug = 0;
 +
 +char *prom_getenv(char *envname)
@@ -622,9 +982,11 @@ diff -urN linux.old/arch/mips/ar7/init.c linux.dev/arch/mips/ar7/init.c
 +
 +      return 0;
 +}
++
++EXPORT_SYMBOL(prom_getenv);
 diff -urN linux.old/arch/mips/ar7/irq.c linux.dev/arch/mips/ar7/irq.c
 --- linux.old/arch/mips/ar7/irq.c      1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/arch/mips/ar7/irq.c      2005-07-07 04:39:14.420226000 +0200
++++ linux.dev/arch/mips/ar7/irq.c      2005-07-09 08:00:15.289026000 +0200
 @@ -0,0 +1,669 @@
 +/*
 + * Nitin Dhingra, iamnd@ti.com
@@ -1297,8 +1659,8 @@ diff -urN linux.old/arch/mips/ar7/irq.c linux.dev/arch/mips/ar7/irq.c
 +
 diff -urN linux.old/arch/mips/ar7/Makefile linux.dev/arch/mips/ar7/Makefile
 --- linux.old/arch/mips/ar7/Makefile   1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/arch/mips/ar7/Makefile   2005-07-07 04:39:14.417226000 +0200
-@@ -0,0 +1,12 @@
++++ linux.dev/arch/mips/ar7/Makefile   2005-07-09 08:12:52.981839568 +0200
+@@ -0,0 +1,14 @@
 +.S.s:
 +      $(CPP) $(AFLAGS) $< -o $*.s
 +
@@ -1307,13 +1669,15 @@ diff -urN linux.old/arch/mips/ar7/Makefile linux.dev/arch/mips/ar7/Makefile
 +
 +O_TARGET := ar7.o
 +
-+obj-y := tnetd73xx_misc.o
-+obj-y += setup.o irq.o mipsIRQ.o reset.o init.o memory.o printf.o cmdline.o time.o
++export-objs += tnetd73xx_misc.o init.o
++obj-y := setup.o irq.o mipsIRQ.o reset.o init.o memory.o printf.o cmdline.o time.o
++obj-y += tnetd73xx_misc.o
++obj-y += hal/misc.o
 +
 +include $(TOPDIR)/Rules.make
 diff -urN linux.old/arch/mips/ar7/memory.c linux.dev/arch/mips/ar7/memory.c
 --- linux.old/arch/mips/ar7/memory.c   1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/arch/mips/ar7/memory.c   2005-07-07 04:39:14.420226000 +0200
++++ linux.dev/arch/mips/ar7/memory.c   2005-07-09 08:00:15.290026000 +0200
 @@ -0,0 +1,130 @@
 +/*
 + * Carsten Langgaard, carstenl@mips.com
@@ -1447,7 +1811,7 @@ diff -urN linux.old/arch/mips/ar7/memory.c linux.dev/arch/mips/ar7/memory.c
 +}
 diff -urN linux.old/arch/mips/ar7/mipsIRQ.S linux.dev/arch/mips/ar7/mipsIRQ.S
 --- linux.old/arch/mips/ar7/mipsIRQ.S  1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/arch/mips/ar7/mipsIRQ.S  2005-07-07 04:39:14.421226000 +0200
++++ linux.dev/arch/mips/ar7/mipsIRQ.S  2005-07-09 08:00:15.290026000 +0200
 @@ -0,0 +1,120 @@
 +/*
 + * Carsten Langgaard, carstenl@mips.com
@@ -1571,7 +1935,7 @@ diff -urN linux.old/arch/mips/ar7/mipsIRQ.S linux.dev/arch/mips/ar7/mipsIRQ.S
 +END(mipsIRQ)
 diff -urN linux.old/arch/mips/ar7/printf.c linux.dev/arch/mips/ar7/printf.c
 --- linux.old/arch/mips/ar7/printf.c   1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/arch/mips/ar7/printf.c   2005-07-07 04:39:14.421226000 +0200
++++ linux.dev/arch/mips/ar7/printf.c   2005-07-09 08:00:15.291026000 +0200
 @@ -0,0 +1,51 @@
 +/*
 + * Carsten Langgaard, carstenl@mips.com
@@ -1626,7 +1990,7 @@ diff -urN linux.old/arch/mips/ar7/printf.c linux.dev/arch/mips/ar7/printf.c
 +}
 diff -urN linux.old/arch/mips/ar7/reset.c linux.dev/arch/mips/ar7/reset.c
 --- linux.old/arch/mips/ar7/reset.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/arch/mips/ar7/reset.c    2005-07-07 04:39:14.421226000 +0200
++++ linux.dev/arch/mips/ar7/reset.c    2005-07-09 08:00:15.291026000 +0200
 @@ -0,0 +1,54 @@
 +/*
 + * Carsten Langgaard, carstenl@mips.com
@@ -1684,7 +2048,7 @@ diff -urN linux.old/arch/mips/ar7/reset.c linux.dev/arch/mips/ar7/reset.c
 +}
 diff -urN linux.old/arch/mips/ar7/setup.c linux.dev/arch/mips/ar7/setup.c
 --- linux.old/arch/mips/ar7/setup.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/arch/mips/ar7/setup.c    2005-07-07 06:45:41.786771352 +0200
++++ linux.dev/arch/mips/ar7/setup.c    2005-07-09 08:00:15.291026000 +0200
 @@ -0,0 +1,167 @@
 +/*
 + * Carsten Langgaard, carstenl@mips.com
@@ -1855,7 +2219,7 @@ diff -urN linux.old/arch/mips/ar7/setup.c linux.dev/arch/mips/ar7/setup.c
 +}
 diff -urN linux.old/arch/mips/ar7/time.c linux.dev/arch/mips/ar7/time.c
 --- linux.old/arch/mips/ar7/time.c     1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/arch/mips/ar7/time.c     2005-07-07 04:39:14.422226000 +0200
++++ linux.dev/arch/mips/ar7/time.c     2005-07-09 08:00:15.292025000 +0200
 @@ -0,0 +1,125 @@
 +/*
 + * Carsten Langgaard, carstenl@mips.com
@@ -1984,8 +2348,8 @@ diff -urN linux.old/arch/mips/ar7/time.c linux.dev/arch/mips/ar7/time.c
 +}
 diff -urN linux.old/arch/mips/ar7/tnetd73xx_misc.c linux.dev/arch/mips/ar7/tnetd73xx_misc.c
 --- linux.old/arch/mips/ar7/tnetd73xx_misc.c   1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/arch/mips/ar7/tnetd73xx_misc.c   2005-07-07 04:39:14.423225000 +0200
-@@ -0,0 +1,924 @@
++++ linux.dev/arch/mips/ar7/tnetd73xx_misc.c   2005-07-09 08:19:34.066865376 +0200
+@@ -0,0 +1,927 @@
 +/******************************************************************************
 + * FILE PURPOSE:    TNETD73xx Misc modules API Source
 + ******************************************************************************
@@ -2006,6 +2370,7 @@ diff -urN linux.old/arch/mips/ar7/tnetd73xx_misc.c linux.dev/arch/mips/ar7/tnetd
 +#define _LINK_KSEG0_
 +
 +#include <linux/types.h>
++#include <linux/module.h>
 +#include <asm/ar7/tnetd73xx.h>
 +#include <asm/ar7/tnetd73xx_misc.h>
 +
@@ -2257,31 +2622,31 @@ diff -urN linux.old/arch/mips/ar7/tnetd73xx_misc.c linux.dev/arch/mips/ar7/tnetd
 +
 +
 +
-+                                                            /****************************************************************************
-+                                                             * DATA PURPOSE:    PRIVATE Variables
-+                                                             **************************************************************************/
-+                                                            static u32 *clk_src[4];
-+                                                            static u32 mips_pll_out;
-+                                                            static u32 sys_pll_out;
-+                                                            static u32 afeclk_inp;
-+                                                            static u32 refclk_inp;
-+                                                            static u32 xtal_inp;
-+                                                            static u32 present_min;
-+                                                            static u32 present_max;
-+
-+                                                            /* Forward References */
-+                                                            static u32 find_gcd(u32 min, u32 max);
-+                                                            static u32 compute_prediv( u32 divider, u32 min, u32 max);
-+                                                            static void get_val(u32 base_freq, u32 output_freq,u32 *multiplier, u32 *divider);
-+                                                            static u32 get_base_frequency(TNETD73XX_CLKC_ID_T clk_id);
-+                                                            static void find_approx(u32 *,u32 *,u32);
-+
-+                                                            /****************************************************************************
-+                                                             * FUNCTION: tnetd73xx_clkc_init
-+                                                             ****************************************************************************
-+                                                             * Description: The routine initializes the internal variables depending on
-+                                                             *              on the sources selected for different clocks.
-+                                                             ***************************************************************************/
++/****************************************************************************
++* DATA PURPOSE:    PRIVATE Variables
++**************************************************************************/
++static u32 *clk_src[4];
++static u32 mips_pll_out;
++static u32 sys_pll_out;
++static u32 afeclk_inp;
++static u32 refclk_inp;
++static u32 xtal_inp;
++static u32 present_min;
++static u32 present_max;
++
++/* Forward References */
++static u32 find_gcd(u32 min, u32 max);
++static u32 compute_prediv( u32 divider, u32 min, u32 max);
++static void get_val(u32 base_freq, u32 output_freq,u32 *multiplier, u32 *divider);
++static u32 get_base_frequency(TNETD73XX_CLKC_ID_T clk_id);
++static void find_approx(u32 *,u32 *,u32);
++
++/****************************************************************************
++* FUNCTION: tnetd73xx_clkc_init
++****************************************************************************
++* Description: The routine initializes the internal variables depending on
++*              on the sources selected for different clocks.
++***************************************************************************/
 +void tnetd73xx_clkc_init(u32 afeclk, u32 refclk, u32 xtal3in)
 +{
 +
@@ -2910,9 +3275,11 @@ diff -urN linux.old/arch/mips/ar7/tnetd73xx_misc.c linux.dev/arch/mips/ar7/tnetd
 +      return ( (pin_value & (1 << gpio_pin)) ? 1 : 0 );
 +}
 +
++EXPORT_SYMBOL(tnetd73xx_clkc_get_freq);
++
 diff -urN linux.old/arch/mips/config-shared.in linux.dev/arch/mips/config-shared.in
---- linux.old/arch/mips/config-shared.in       2005-07-07 05:38:31.343491864 +0200
-+++ linux.dev/arch/mips/config-shared.in       2005-07-07 04:39:14.424225000 +0200
+--- linux.old/arch/mips/config-shared.in       2005-07-09 08:01:49.831653720 +0200
++++ linux.dev/arch/mips/config-shared.in       2005-07-09 08:00:15.293025000 +0200
 @@ -20,6 +20,15 @@
  mainmenu_option next_comment
  comment 'Machine selection'
@@ -2958,8 +3325,8 @@ diff -urN linux.old/arch/mips/config-shared.in linux.dev/arch/mips/config-shared
       "$CONFIG_DECSTATION" = "y" -o \
       "$CONFIG_IBM_WORKPAD" = "y" -o \
 diff -urN linux.old/arch/mips/kernel/irq.c linux.dev/arch/mips/kernel/irq.c
---- linux.old/arch/mips/kernel/irq.c   2005-07-07 05:38:31.343491864 +0200
-+++ linux.dev/arch/mips/kernel/irq.c   2005-07-07 04:39:14.424225000 +0200
+--- linux.old/arch/mips/kernel/irq.c   2005-07-09 08:01:49.831653720 +0200
++++ linux.dev/arch/mips/kernel/irq.c   2005-07-09 08:00:15.294025000 +0200
 @@ -76,6 +76,7 @@
   * Generic, controller-independent functions:
   */
@@ -3009,8 +3376,8 @@ diff -urN linux.old/arch/mips/kernel/irq.c linux.dev/arch/mips/kernel/irq.c
  /*
   * IRQ autodetection code..
 diff -urN linux.old/arch/mips/kernel/setup.c linux.dev/arch/mips/kernel/setup.c
---- linux.old/arch/mips/kernel/setup.c 2005-07-07 05:38:31.344491712 +0200
-+++ linux.dev/arch/mips/kernel/setup.c 2005-07-07 04:39:14.425225000 +0200
+--- linux.old/arch/mips/kernel/setup.c 2005-07-09 08:01:49.832653568 +0200
++++ linux.dev/arch/mips/kernel/setup.c 2005-07-09 08:00:15.295025000 +0200
 @@ -109,6 +109,7 @@
  unsigned long isa_slot_offset;
  EXPORT_SYMBOL(isa_slot_offset);
@@ -3059,8 +3426,8 @@ diff -urN linux.old/arch/mips/kernel/setup.c linux.dev/arch/mips/kernel/setup.c
                panic("Unsupported architecture");
        }
 diff -urN linux.old/arch/mips/kernel/traps.c linux.dev/arch/mips/kernel/traps.c
---- linux.old/arch/mips/kernel/traps.c 2005-07-07 05:38:31.345491560 +0200
-+++ linux.dev/arch/mips/kernel/traps.c 2005-07-07 04:39:14.425225000 +0200
+--- linux.old/arch/mips/kernel/traps.c 2005-07-09 08:01:49.832653568 +0200
++++ linux.dev/arch/mips/kernel/traps.c 2005-07-09 08:00:15.295025000 +0200
 @@ -40,6 +40,10 @@
  #include <asm/uaccess.h>
  #include <asm/mmu_context.h>
@@ -3179,8 +3546,8 @@ diff -urN linux.old/arch/mips/kernel/traps.c linux.dev/arch/mips/kernel/traps.c
        per_cpu_trap_init();
  }
 diff -urN linux.old/arch/mips/lib/promlib.c linux.dev/arch/mips/lib/promlib.c
---- linux.old/arch/mips/lib/promlib.c  2005-07-07 05:38:31.345491560 +0200
-+++ linux.dev/arch/mips/lib/promlib.c  2005-07-07 04:39:14.426225000 +0200
+--- linux.old/arch/mips/lib/promlib.c  2005-07-09 08:01:49.833653416 +0200
++++ linux.dev/arch/mips/lib/promlib.c  2005-07-09 08:00:15.296025000 +0200
 @@ -1,3 +1,4 @@
 +#ifndef CONFIG_AR7
  #include <stdarg.h>
@@ -3192,8 +3559,8 @@ diff -urN linux.old/arch/mips/lib/promlib.c linux.dev/arch/mips/lib/promlib.c
  }
 +#endif
 diff -urN linux.old/arch/mips/Makefile linux.dev/arch/mips/Makefile
---- linux.old/arch/mips/Makefile       2005-07-07 05:38:31.320495360 +0200
-+++ linux.dev/arch/mips/Makefile       2005-07-07 04:39:14.510212000 +0200
+--- linux.old/arch/mips/Makefile       2005-07-09 08:01:49.833653416 +0200
++++ linux.dev/arch/mips/Makefile       2005-07-09 08:00:15.413007000 +0200
 @@ -369,6 +369,16 @@
  endif
  
@@ -3212,8 +3579,8 @@ diff -urN linux.old/arch/mips/Makefile linux.dev/arch/mips/Makefile
  #
  ifdef CONFIG_DECSTATION
 diff -urN linux.old/arch/mips/mm/init.c linux.dev/arch/mips/mm/init.c
---- linux.old/arch/mips/mm/init.c      2005-07-07 05:38:31.345491560 +0200
-+++ linux.dev/arch/mips/mm/init.c      2005-07-07 04:39:14.426225000 +0200
+--- linux.old/arch/mips/mm/init.c      2005-07-09 08:01:49.834653264 +0200
++++ linux.dev/arch/mips/mm/init.c      2005-07-09 08:00:15.297025000 +0200
 @@ -40,8 +40,10 @@
  
  mmu_gather_t mmu_gathers[NR_CPUS];
@@ -3281,8 +3648,8 @@ diff -urN linux.old/arch/mips/mm/init.c linux.dev/arch/mips/mm/init.c
  }
 +#endif
 diff -urN linux.old/arch/mips/mm/tlb-r4k.c linux.dev/arch/mips/mm/tlb-r4k.c
---- linux.old/arch/mips/mm/tlb-r4k.c   2005-07-07 05:38:31.346491408 +0200
-+++ linux.dev/arch/mips/mm/tlb-r4k.c   2005-07-07 04:39:14.427225000 +0200
+--- linux.old/arch/mips/mm/tlb-r4k.c   2005-07-09 08:01:49.834653264 +0200
++++ linux.dev/arch/mips/mm/tlb-r4k.c   2005-07-09 08:00:15.297025000 +0200
 @@ -20,6 +20,10 @@
  #include <asm/pgtable.h>
  #include <asm/system.h>
@@ -3308,8 +3675,8 @@ diff -urN linux.old/arch/mips/mm/tlb-r4k.c linux.dev/arch/mips/mm/tlb-r4k.c
        }
  }
 diff -urN linux.old/drivers/char/serial.c linux.dev/drivers/char/serial.c
---- linux.old/drivers/char/serial.c    2005-07-07 05:38:31.348491104 +0200
-+++ linux.dev/drivers/char/serial.c    2005-07-07 04:39:14.429225000 +0200
+--- linux.old/drivers/char/serial.c    2005-07-09 08:01:49.836652960 +0200
++++ linux.dev/drivers/char/serial.c    2005-07-09 08:00:15.299024000 +0200
 @@ -419,7 +419,40 @@
        return 0;
  }
@@ -3408,7 +3775,7 @@ diff -urN linux.old/drivers/char/serial.c linux.dev/drivers/char/serial.c
        cval >>= 8;
 diff -urN linux.old/include/asm-mips/ar7/ar7.h linux.dev/include/asm-mips/ar7/ar7.h
 --- linux.old/include/asm-mips/ar7/ar7.h       1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/include/asm-mips/ar7/ar7.h       2005-07-07 04:39:14.430224000 +0200
++++ linux.dev/include/asm-mips/ar7/ar7.h       2005-07-09 08:00:15.300024000 +0200
 @@ -0,0 +1,137 @@
 +#ifndef _MIPS_AR7_H
 +#define _MIPS_AR7_H
@@ -3549,7 +3916,7 @@ diff -urN linux.old/include/asm-mips/ar7/ar7.h linux.dev/include/asm-mips/ar7/ar
 +#endif /*_MIPS_AR7_H */
 diff -urN linux.old/include/asm-mips/ar7/avalanche.h linux.dev/include/asm-mips/ar7/avalanche.h
 --- linux.old/include/asm-mips/ar7/avalanche.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/include/asm-mips/ar7/avalanche.h 2005-07-07 04:39:14.430224000 +0200
++++ linux.dev/include/asm-mips/ar7/avalanche.h 2005-07-09 08:00:15.301024000 +0200
 @@ -0,0 +1,183 @@
 +/* $Id$
 + *
@@ -3736,7 +4103,7 @@ diff -urN linux.old/include/asm-mips/ar7/avalanche.h linux.dev/include/asm-mips/
 +
 diff -urN linux.old/include/asm-mips/ar7/avalanche_intc.h linux.dev/include/asm-mips/ar7/avalanche_intc.h
 --- linux.old/include/asm-mips/ar7/avalanche_intc.h    1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/include/asm-mips/ar7/avalanche_intc.h    2005-07-07 04:39:14.431224000 +0200
++++ linux.dev/include/asm-mips/ar7/avalanche_intc.h    2005-07-09 08:00:15.301024000 +0200
 @@ -0,0 +1,273 @@
 + /*
 + * Nitin Dhingra, iamnd@ti.com
@@ -4011,311 +4378,162 @@ diff -urN linux.old/include/asm-mips/ar7/avalanche_intc.h linux.dev/include/asm-
 +
 +
 +#endif /* _AVALANCHE_INTC_H */
-diff -urN linux.old/include/asm-mips/ar7/avalanche_int.h linux.dev/include/asm-mips/ar7/avalanche_int.h
---- linux.old/include/asm-mips/ar7/avalanche_int.h     1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/include/asm-mips/ar7/avalanche_int.h     2005-07-07 04:39:14.431224000 +0200
-@@ -0,0 +1,298 @@
-+/* $Id$
-+ *
-+ * avalancheint.h
-+ *
-+ * Jeff Harrell, jharrell@ti.com
-+ * Copyright (C) 2000,2001 Texas Instruments , Inc.
-+ *
-+ * ########################################################################
-+ *
-+ *  This program is free software; you can distribute it and/or modify it
-+ *  under the terms of the GNU General Public License (Version 2) as
-+ *  published by the Free Software Foundation.
-+ *
-+ *  This program is distributed in the hope it will be useful, but WITHOUT
-+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-+ *  for more details.
-+ *
-+ *  You should have received a copy of the GNU General Public License along
-+ *  with this program; if not, write to the Free Software Foundation, Inc.,
-+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
-+ *
-+ * ########################################################################
-+ *
-+ * Defines for the AVALANCHE interrupt controller.
-+ *
-+ */
-+#ifndef _MIPS_AVALANCHEINT_H
-+#define _MIPS_AVALANCHEINT_H
-+
-+#include <linux/config.h>
-+
-+/* Avalanche Interrupt number */
-+#define AVINTNUM(x) ((x) - MIPS_EXCEPTION_OFFSET)
-+/* Linux Interrupt number     */ 
-+#define LNXINTNUM(x)((x) + MIPS_EXCEPTION_OFFSET)
-+/* Number of IRQ supported on hw interrupt 0. */
+diff -urN linux.old/include/asm-mips/ar7/avalanche_misc.h linux.dev/include/asm-mips/ar7/avalanche_misc.h
+--- linux.old/include/asm-mips/ar7/avalanche_misc.h    1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/ar7/avalanche_misc.h    2005-07-09 08:00:15.302024000 +0200
+@@ -0,0 +1,149 @@
++#ifndef _AVALANCHE_MISC_H_
++#define _AVALANCHE_MISC_H_
++
++typedef enum AVALANCHE_ERR_t
++{
++    AVALANCHE_ERR_OK        = 0,    /* OK or SUCCESS */
++    AVALANCHE_ERR_ERROR     = -1,   /* Unspecified/Generic ERROR */
 +
-+//#define SEADINT_UART0      3            /* TTYS0 interrupt on SEAD */
-+//#define SEADINT_UART1      4            /* TTYS1 interrupt on SEAD */
++    /* Pointers and args */
++    AVALANCHE_ERR_INVARG        = -2,   /* Invaild argument to the call */
++    AVALANCHE_ERR_NULLPTR       = -3,   /* NULL pointer */
++    AVALANCHE_ERR_BADPTR        = -4,   /* Bad (out of mem) pointer */
 +
++    /* Memory issues */
++    AVALANCHE_ERR_ALLOC_FAIL    = -10,  /* allocation failed */
++    AVALANCHE_ERR_FREE_FAIL     = -11,  /* free failed */
++    AVALANCHE_ERR_MEM_CORRUPT   = -12,  /* corrupted memory */
++    AVALANCHE_ERR_BUF_LINK      = -13,  /* buffer linking failed */
 +
-+#define MIPS_EXCEPTION_OFFSET 8
-+#define AVALANCHE_INT_END_PRIMARY      (40 + MIPS_EXCEPTION_OFFSET)
-+#define AVALANCHE_INT_END_SECONDARY    (32 + MIPS_EXCEPTION_OFFSET)
++    /* Device issues */
++    AVALANCHE_ERR_DEVICE_TIMEOUT    = -20,  /* device timeout on read/write */
++    AVALANCHE_ERR_DEVICE_MALFUNC    = -21,  /* device malfunction */
 +
-+#define AVALANCHE_INT_END_PRIMARY_REG1 (31 + MIPS_EXCEPTION_OFFSET)
-+#define AVALANCHE_INT_END_PRIMARY_REG2 (39 + MIPS_EXCEPTION_OFFSET)
++    AVALANCHE_ERR_INVID     = -30   /* Invalid ID */
 +
++} AVALANCHE_ERR;
 +
-+#define AVALANCHE_INT_END (AVINTNUM(AVALANCHE_INT_END_PRIMARY) + AVINTNUM(AVALANCHE_INT_END_SECONDARY)  \
-+                     + MIPS_EXCEPTION_OFFSET - 1)
++/*****************************************************************************
++ * Reset Control Module
++ *****************************************************************************/
 +
-+struct avalanche_ictrl_regs /* Avalanche Interrupt control registers */
++typedef enum AVALANCHE_RESET_CTRL_tag
 +{
-+  volatile unsigned long intsr1;    /* Interrupt Status/Set Register 1   */ /* 0x00 */      
-+  volatile unsigned long intsr2;    /* Interrupt Status/Set Register 2   */ /* 0x04 */
-+  volatile unsigned long unused1;                                           /* 0x08 */
-+  volatile unsigned long unused2;                                           /* 0x0C */
-+  volatile unsigned long intcr1;    /* Interrupt Clear Register 1        */ /* 0x10 */
-+  volatile unsigned long intcr2;    /* Interrupt Clear Register 2        */ /* 0x14 */
-+  volatile unsigned long unused3;                                           /* 0x18 */
-+  volatile unsigned long unused4;                                           /* 0x1C */
-+  volatile unsigned long intesr1;   /* Interrupt Enable (Set) Register 1 */ /* 0x20 */
-+  volatile unsigned long intesr2;   /* Interrupt Enable (Set) Register 2 */ /* 0x24 */
-+  volatile unsigned long unused5;                                           /* 0x28 */
-+  volatile unsigned long unused6;                                           /* 0x2C */
-+  volatile unsigned long intecr1;   /* Interrupt Enable Clear Register 1 */ /* 0x30 */
-+  volatile unsigned long intecr2;   /* Interrupt Enable Clear Register 2 */ /* 0x34 */
-+  volatile unsigned long unused7;                                           /* 0x38 */
-+  volatile unsigned long unused8;                                           /* 0x3c */
-+  volatile unsigned long pintir;    /* Priority Interrupt Index Register */ /* 0x40 */
-+  volatile unsigned long intmsr;    /* Priority Interrupt Mask Index Reg.*/ /* 0x44 */
-+  volatile unsigned long unused9;                                           /* 0x48 */
-+  volatile unsigned long unused10;                                          /* 0x4C */
-+  volatile unsigned long intpolr1;  /* Interrupt Polarity Mask register 1*/ /* 0x50 */
-+  volatile unsigned long intpolr2;  /* Interrupt Polarity Mask register 2*/ /* 0x54 */
-+};
++    IN_RESET        = 0,
++    OUT_OF_RESET
++} AVALANCHE_RESET_CTRL_T;
 +
-+struct avalanche_exctrl_regs   /* Avalanche Exception control registers */
++typedef enum AVALANCHE_SYS_RST_MODE_tag
 +{
-+  volatile unsigned long exsr;      /* Exceptions Status/Set register    */  /* 0x80 */
-+  volatile unsigned long reserved;                                           /* 0x84 */
-+  volatile unsigned long excr;      /* Exceptions Clear Register         */  /* 0x88 */
-+  volatile unsigned long reserved1;                                          /* 0x8c */
-+  volatile unsigned long exiesr;    /* Exceptions Interrupt Enable (set) */  /* 0x90 */
-+  volatile unsigned long reserved2;                                          /* 0x94 */
-+  volatile unsigned long exiecr;    /* Exceptions Interrupt Enable (clear)*/ /* 0x98 */
-+};
++    RESET_SOC_WITH_MEMCTRL      = 1,    /* SW0 bit in SWRCR register */
++    RESET_SOC_WITHOUT_MEMCTRL   = 2     /* SW1 bit in SWRCR register */
++} AVALANCHE_SYS_RST_MODE_T;
 +
-+struct avalanche_channel_int_number
++typedef enum AVALANCHE_SYS_RESET_STATUS_tag
 +{
-+  volatile unsigned long cintnr0;   /* Channel Interrupt Number Register */  /* 0x200 */
-+  volatile unsigned long cintnr1;   /* Channel Interrupt Number Register */  /* 0x204 */
-+  volatile unsigned long cintnr2;   /* Channel Interrupt Number Register */  /* 0x208 */
-+  volatile unsigned long cintnr3;   /* Channel Interrupt Number Register */  /* 0x20C */
-+  volatile unsigned long cintnr4;   /* Channel Interrupt Number Register */  /* 0x210 */
-+  volatile unsigned long cintnr5;   /* Channel Interrupt Number Register */  /* 0x214 */
-+  volatile unsigned long cintnr6;   /* Channel Interrupt Number Register */  /* 0x218 */
-+  volatile unsigned long cintnr7;   /* Channel Interrupt Number Register */  /* 0x21C */
-+  volatile unsigned long cintnr8;   /* Channel Interrupt Number Register */  /* 0x220 */
-+  volatile unsigned long cintnr9;   /* Channel Interrupt Number Register */  /* 0x224 */
-+  volatile unsigned long cintnr10;  /* Channel Interrupt Number Register */  /* 0x228 */
-+  volatile unsigned long cintnr11;  /* Channel Interrupt Number Register */  /* 0x22C */
-+  volatile unsigned long cintnr12;  /* Channel Interrupt Number Register */  /* 0x230 */
-+  volatile unsigned long cintnr13;  /* Channel Interrupt Number Register */  /* 0x234 */
-+  volatile unsigned long cintnr14;  /* Channel Interrupt Number Register */  /* 0x238 */
-+  volatile unsigned long cintnr15;  /* Channel Interrupt Number Register */  /* 0x23C */
-+  volatile unsigned long cintnr16;  /* Channel Interrupt Number Register */  /* 0x240 */
-+  volatile unsigned long cintnr17;  /* Channel Interrupt Number Register */  /* 0x244 */
-+  volatile unsigned long cintnr18;  /* Channel Interrupt Number Register */  /* 0x248 */
-+  volatile unsigned long cintnr19;  /* Channel Interrupt Number Register */  /* 0x24C */
-+  volatile unsigned long cintnr20;  /* Channel Interrupt Number Register */  /* 0x250 */
-+  volatile unsigned long cintnr21;  /* Channel Interrupt Number Register */  /* 0x254 */
-+  volatile unsigned long cintnr22;  /* Channel Interrupt Number Register */  /* 0x358 */
-+  volatile unsigned long cintnr23;  /* Channel Interrupt Number Register */  /* 0x35C */
-+  volatile unsigned long cintnr24;  /* Channel Interrupt Number Register */  /* 0x260 */
-+  volatile unsigned long cintnr25;  /* Channel Interrupt Number Register */  /* 0x264 */
-+  volatile unsigned long cintnr26;  /* Channel Interrupt Number Register */  /* 0x268 */
-+  volatile unsigned long cintnr27;  /* Channel Interrupt Number Register */  /* 0x26C */
-+  volatile unsigned long cintnr28;  /* Channel Interrupt Number Register */  /* 0x270 */
-+  volatile unsigned long cintnr29;  /* Channel Interrupt Number Register */  /* 0x274 */
-+  volatile unsigned long cintnr30;  /* Channel Interrupt Number Register */  /* 0x278 */
-+  volatile unsigned long cintnr31;  /* Channel Interrupt Number Register */  /* 0x27C */
-+  volatile unsigned long cintnr32;  /* Channel Interrupt Number Register */  /* 0x280 */
-+  volatile unsigned long cintnr33;  /* Channel Interrupt Number Register */  /* 0x284 */
-+  volatile unsigned long cintnr34;  /* Channel Interrupt Number Register */  /* 0x288 */
-+  volatile unsigned long cintnr35;  /* Channel Interrupt Number Register */  /* 0x28C */
-+  volatile unsigned long cintnr36;  /* Channel Interrupt Number Register */  /* 0x290 */
-+  volatile unsigned long cintnr37;  /* Channel Interrupt Number Register */  /* 0x294 */
-+  volatile unsigned long cintnr38;  /* Channel Interrupt Number Register */  /* 0x298 */
-+  volatile unsigned long cintnr39;  /* Channel Interrupt Number Register */  /* 0x29C */
-+};
++    HARDWARE_RESET = 0,
++    SOFTWARE_RESET0,            /* Caused by writing 1 to SW0 bit in SWRCR register */
++    WATCHDOG_RESET,
++    SOFTWARE_RESET1             /* Caused by writing 1 to SW1 bit in SWRCR register */
++} AVALANCHE_SYS_RESET_STATUS_T;
++
++void avalanche_reset_ctrl(unsigned int reset_module,AVALANCHE_RESET_CTRL_T reset_ctrl);
++AVALANCHE_RESET_CTRL_T avalanche_get_reset_status(unsigned int reset_module);
++void avalanche_sys_reset(AVALANCHE_SYS_RST_MODE_T mode);
++AVALANCHE_SYS_RESET_STATUS_T avalanche_get_sys_last_reset_status(void);
++
++typedef void (*REMOTE_VLYNQ_DEV_RESET_CTRL_FN)(unsigned int reset_module, 
++                                               AVALANCHE_RESET_CTRL_T reset_ctrl);
++
++/*****************************************************************************
++ * Power Control Module
++ *****************************************************************************/
 +
-+struct avalanche_interrupt_line_to_channel 
++typedef enum AVALANCHE_POWER_CTRL_tag
 +{
-+  unsigned long int_line0;    /* Start of primary interrupts */
-+  unsigned long int_line1;
-+  unsigned long int_line2;
-+  unsigned long int_line3;
-+  unsigned long int_line4;
-+  unsigned long int_line5;
-+  unsigned long int_line6;
-+  unsigned long int_line7;
-+  unsigned long int_line8;
-+  unsigned long int_line9;
-+  unsigned long int_line10;
-+  unsigned long int_line11; 
-+  unsigned long int_line12; 
-+  unsigned long int_line13; 
-+  unsigned long int_line14; 
-+  unsigned long int_line15; 
-+  unsigned long int_line16; 
-+  unsigned long int_line17; 
-+  unsigned long int_line18; 
-+  unsigned long int_line19; 
-+  unsigned long int_line20; 
-+  unsigned long int_line21;
-+  unsigned long int_line22; 
-+  unsigned long int_line23; 
-+  unsigned long int_line24; 
-+  unsigned long int_line25; 
-+  unsigned long int_line26; 
-+  unsigned long int_line27; 
-+  unsigned long int_line28; 
-+  unsigned long int_line29; 
-+  unsigned long int_line30; 
-+  unsigned long int_line31; 
-+  unsigned long int_line32;
-+  unsigned long int_line33; 
-+  unsigned long int_line34; 
-+  unsigned long int_line35; 
-+  unsigned long int_line36; 
-+  unsigned long int_line37; 
-+  unsigned long int_line38; 
-+  unsigned long int_line39;  
-+};
++    POWER_CTRL_POWER_UP = 0,
++    POWER_CTRL_POWER_DOWN
++} AVALANCHE_POWER_CTRL_T;
 +
-+/* Interrupt Line #'s  (Avalanche peripherals) */
++typedef enum AVALANCHE_SYS_POWER_MODE_tag
++{
++    GLOBAL_POWER_MODE_RUN       = 0,    /* All system is up */
++    GLOBAL_POWER_MODE_IDLE,             /* MIPS is power down, all peripherals working */
++    GLOBAL_POWER_MODE_STANDBY,          /* Chip in power down, but clock to ADSKL subsystem is running */
++    GLOBAL_POWER_MODE_POWER_DOWN        /* Total chip is powered down */
++} AVALANCHE_SYS_POWER_MODE_T;
 +
-+/*------------------------------*/
-+/* Avalanche primary interrupts */
-+/*------------------------------*/
-+#define UNIFIED_SECONDARY_INTERRUPT  0
-+#define AVALANCHE_EXT_INT_0          1
-+#define AVALANCHE_EXT_INT_1          2
-+#define AVALANCHE_EXT_INT_2          3
-+#define AVALANCHE_EXT_INT_3          4
-+#define AVALANCHE_TIMER_0_INT        5
-+#define AVALANCHE_TIMER_1_INT        6
-+#define AVALANCHE_UART0_INT          7
-+#define AVALANCHE_UART1_INT          8
-+#define AVALANCHE_PDMA_INT0          9
-+#define AVALANCHE_PDMA_INT1          10
-+#define AVALANCHE_HDLC_TXA           11
-+#define AVALANCHE_HDLC_TXB           12
-+#define AVALANCHE_HDLC_RXA           13
-+#define AVALANCHE_HDLC_RXB           14
-+#define AVALANCHE_ATM_SAR_TXA        15
-+#define AVALANCHE_ATM_SAR_TXB        16
-+#define AVALANCHE_ATM_SAR_RXA        17
-+#define AVALANCHE_ATM_SAR_RXB        18
-+#define AVALANCHE_MAC_TXA            19
-+#define AVALANCHE_MAC_RXA            20
-+#define AVALANCHE_DSP_SUB0           21
-+#define AVALANCHE_DSP_SUB1           22
-+#define AVALANCHE_DES_INT            23
-+#define AVALANCHE_USB_INT            24
-+#define AVALANCHE_PCI_INTA           25
-+#define AVALANCHE_PCI_INTB           26
-+#define AVALANCHE_PCI_INTC           27
-+/*  Line #28  Reserved               */
-+#define AVALANCHE_I2CM_INT           29
-+#define AVALANCHE_PDMA_INT2          30
-+#define AVALANCHE_PDMA_INT3          31
-+#define AVALANCHE_CODEC              32
-+#define AVALANCHE_MAC_TXB            33
-+#define AVALANCHE_MAC_RXB            34
-+/*  Line #35  Reserved               */
-+/*  Line #36  Reserved               */
-+/*  Line #37  Reserved               */
-+/*  Line #38  Reserved               */
-+/*  Line #39  Reserved               */
++void avalanche_power_ctrl(unsigned int power_module,  AVALANCHE_POWER_CTRL_T power_ctrl);
++AVALANCHE_POWER_CTRL_T avalanche_get_power_status(unsigned int power_module);
++void avalanche_set_global_power_mode(AVALANCHE_SYS_POWER_MODE_T power_mode);
++AVALANCHE_SYS_POWER_MODE_T avalanche_get_global_power_mode(void);
 +
-+#define DEBUG_MISSED_INTS 1
++/*****************************************************************************
++ * Wakeup Control
++ *****************************************************************************/
 +
-+#ifdef DEBUG_MISSED_INTS
-+struct debug_missed_int
++typedef enum AVALANCHE_WAKEUP_INTERRUPT_tag
 +{
-+  unsigned int atm_sar_txa;
-+  unsigned int atm_sar_txb;
-+  unsigned int atm_sar_rxa;
-+  unsigned int atm_sar_rxb;
-+  unsigned int mac_txa;
-+  unsigned int mac_rxa;
-+  unsigned int mac_txb;
-+  unsigned int mac_rxb;
-+};
-+#endif /* DEBUG_MISSED_INTS */
++    WAKEUP_INT0 = 1,
++    WAKEUP_INT1 = 2,
++    WAKEUP_INT2 = 4,
++    WAKEUP_INT3 = 8
++} AVALANCHE_WAKEUP_INTERRUPT_T;
 +
-+/*-----------------------------------*/
-+/* Avalanche Secondary Interrupts    */
-+/*-----------------------------------*/
-+#define PRIMARY_INTS                 40
++typedef enum TNETV1050_WAKEUP_CTRL_tag
++{
++    WAKEUP_DISABLED = 0,
++    WAKEUP_ENABLED
++} AVALANCHE_WAKEUP_CTRL_T;
 +
-+#define AVALANCHE_HDLC_STATUS        (0 + PRIMARY_INTS)
-+#define AVALANCHE_SAR_STATUS         (1 + PRIMARY_INTS)
-+/*  Line #02  Reserved               */
-+#define AVALANCHE_ETH_MACA_LNK_CHG   (3 + PRIMARY_INTS)
-+#define AVALANCHE_ETH_MACA_MGT       (4 + PRIMARY_INTS)
-+#define AVALANCHE_PCI_STATUS_INT     (5 + PRIMARY_INTS)
-+/*  Line #06  Reserved               */
-+#define AVALANCHE_EXTERN_MEM_INT     (7 + PRIMARY_INTS)
-+#define AVALANCHE_DSP_A_DOG          (8 + PRIMARY_INTS)
-+#define AVALANCHE_DSP_B_DOG          (9 + PRIMARY_INTS)
-+/*  Line #10-#20 Reserved            */
-+#define AVALANCHE_ETH_MACB_LNK_CHG   (21 + PRIMARY_INTS)
-+#define AVALANCHE_ETH_MACB_MGT       (22 + PRIMARY_INTS)
-+#define AVALANCHE_AAL2_STATUS        (23 + PRIMARY_INTS)
-+/*  Line #24-#31 Reserved            */
-+
-+#define AVALANCHEINT_UART0        LNXINTNUM(AVALANCHE_UART0_INT)
-+#define AVALANCHEINT_UART1        LNXINTNUM(AVALANCHE_UART1_INT)
-+#define SEADINT_UART0    3   /* TTYS0 interrupt on SEAD */
-+#define SEADINT_UART1    4   /* TTYS1 interrupt on SEAD */
-+
-+#ifdef JIMK_INT_CTRLR
-+/*-----------------------------------*/
-+/* Jim Kennedy's Interrupt Controller*/
-+/*-----------------------------------*/
++typedef enum TNETV1050_WAKEUP_POLARITY_tag
++{
++    WAKEUP_ACTIVE_HIGH = 0,
++    WAKEUP_ACTIVE_LOW
++} AVALANCHE_WAKEUP_POLARITY_T;
 +
-+/* to clear the interrupt write the bit back to the status reg */
++void avalanche_wakeup_ctrl(AVALANCHE_WAKEUP_INTERRUPT_T wakeup_int,
++                           AVALANCHE_WAKEUP_CTRL_T wakeup_ctrl,
++                           AVALANCHE_WAKEUP_POLARITY_T wakeup_polarity);
 +
-+#define JIMK_INT_STATUS (*(volatile unsigned int *)(0xA8612400))
-+#define JIMK_INT_MASK   (*(volatile unsigned int *)(0xA8612404))
-+#define JIMK_SAR_STATUS  (1<<0)
-+#define JIMK_SAR_TX_A    (1<<1)
-+#define JIMK_SAR_TX_B    (1<<2)
-+#define JIMK_SAR_RX_A    (1<<3)
-+#define JIMK_SAR_RX_B    (1<<4)
-+#define JIMK_AAL2_STATUS (1<<5)
-+#define JIMK_UART0_INT   (1<<11)
++/*****************************************************************************
++ * GPIO Control
++ *****************************************************************************/
 +
-+#ifdef SEAD_USB_DEVELOPMENT
-+#define JIMK_USB_INT     (1<<0)
-+#endif /* SEAD_USB_DEVELOPMENT */
++typedef enum AVALANCHE_GPIO_PIN_MODE_tag
++{
++    FUNCTIONAL_PIN = 0,
++    GPIO_PIN = 1
++} AVALANCHE_GPIO_PIN_MODE_T;
 +
-+#endif /* JIMK_INT_CTRLR */
++typedef enum AVALANCHE_GPIO_PIN_DIRECTION_tag
++{
++    GPIO_OUTPUT_PIN = 0,
++    GPIO_INPUT_PIN = 1
++} AVALANCHE_GPIO_PIN_DIRECTION_T;
 +
-+extern void avalanche_int_set(int channel, int line);
-+extern void avalancheint_init(void);
++typedef enum { GPIO_FALSE, GPIO_TRUE } AVALANCHE_GPIO_BOOL_T;
 +
++void avalanche_gpio_init(void);
++int avalanche_gpio_ctrl(unsigned int gpio_pin,
++                         AVALANCHE_GPIO_PIN_MODE_T pin_mode,
++                         AVALANCHE_GPIO_PIN_DIRECTION_T pin_direction);
++int avalanche_gpio_out_bit(unsigned int gpio_pin, int value);
++int avalanche_gpio_in_bit(unsigned int gpio_pin);
++int avalanche_gpio_out_value(unsigned int out_val, unsigned int set_mask, 
++                             unsigned int reg_index);
++int avalanche_gpio_in_value(unsigned int *in_val, unsigned int reg_index);
 +
-+#endif /* !(_MIPS_AVALANCHEINT_H) */
++unsigned int avalanche_get_chip_version_info(void);
 +
++unsigned int avalanche_get_vbus_freq(void);
++void         avalanche_set_vbus_freq(unsigned int);
 +
 +
++typedef int (*SET_MDIX_ON_CHIP_FN_T)(unsigned int base_addr, unsigned int operation);
++int avalanche_set_mdix_on_chip(unsigned int base_addr, unsigned int operation);
++unsigned int avalanche_is_mdix_on_chip(void);
 +
++#endif
 diff -urN linux.old/include/asm-mips/ar7/avalanche_prom.h linux.dev/include/asm-mips/ar7/avalanche_prom.h
 --- linux.old/include/asm-mips/ar7/avalanche_prom.h    1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/include/asm-mips/ar7/avalanche_prom.h    2005-07-07 04:39:14.431224000 +0200
++++ linux.dev/include/asm-mips/ar7/avalanche_prom.h    2005-07-09 08:00:15.302024000 +0200
 @@ -0,0 +1,54 @@
 +/* $Id$
 + *
@@ -4373,7 +4591,7 @@ diff -urN linux.old/include/asm-mips/ar7/avalanche_prom.h linux.dev/include/asm-
 +
 diff -urN linux.old/include/asm-mips/ar7/avalanche_regs.h linux.dev/include/asm-mips/ar7/avalanche_regs.h
 --- linux.old/include/asm-mips/ar7/avalanche_regs.h    1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/include/asm-mips/ar7/avalanche_regs.h    2005-07-07 04:39:14.433224000 +0200
++++ linux.dev/include/asm-mips/ar7/avalanche_regs.h    2005-07-09 08:00:15.303024000 +0200
 @@ -0,0 +1,567 @@
 +/* 
 + *  $Id$
@@ -4942,9 +5160,383 @@ diff -urN linux.old/include/asm-mips/ar7/avalanche_regs.h linux.dev/include/asm-
 +
 +
 +
+diff -urN linux.old/include/asm-mips/ar7/hal/haltypes.h linux.dev/include/asm-mips/ar7/hal/haltypes.h
+--- linux.old/include/asm-mips/ar7/hal/haltypes.h      1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/ar7/hal/haltypes.h      2005-07-09 08:00:15.303024000 +0200
+@@ -0,0 +1,46 @@
++/******************************************************************************
++ * FILE PURPOSE:    Platform dependent type information Header
++ ********************************************************************************
++ * FILE NAME:       haltypes.h
++ *
++ * DESCRIPTION:     Platform dependent (tuned) types definations.
++ *                  Intented to be used by HAL/Drivers etc.
++ *
++ * REVISION HISTORY:
++ * 27 Nov 02 - PSP TII  
++ *
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++
++#ifndef __HAL_TYPES_H__
++#define __HAL_TYPES_H__
++
++typedef char    INT8;
++typedef short   INT16;
++typedef int     INT32;
++
++typedef unsigned char   UINT8;
++typedef unsigned short  UINT16;
++typedef unsigned int    UINT32;
++
++typedef unsigned char   UCHAR;
++typedef unsigned short  USHORT;
++typedef unsigned int    UINT;
++typedef unsigned long   ULONG;
++
++typedef int     BOOL;
++typedef int     STATUS;
++
++#ifndef FALSE
++#define FALSE 0
++#endif
++
++#ifndef TRUE
++#define TRUE 1
++#endif
++
++#ifndef NULL
++#define NULL 0
++#endif
++
++#endif /*  __HAL_TYPES_H__ */
+diff -urN linux.old/include/asm-mips/ar7/if_port.h linux.dev/include/asm-mips/ar7/if_port.h
+--- linux.old/include/asm-mips/ar7/if_port.h   1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/ar7/if_port.h   2005-07-09 08:00:15.304024000 +0200
+@@ -0,0 +1,26 @@
++/*******************************************************************************   
++ * FILE PURPOSE:    Interface port id Header file                                      
++ *******************************************************************************   
++ * FILE NAME:       if_port.h                                                   
++ *                                                                                 
++ * DESCRIPTION:     Header file carrying information about port ids of interfaces                             
++ *                                                                                 
++ *                                                                                 
++ * (C) Copyright 2003, Texas Instruments, Inc                                      
++ ******************************************************************************/   
++#ifndef _IF_PORT_H_
++#define _IF_PORT_H_
++
++#define AVALANCHE_CPMAC_LOW_PORT_ID         0
++#define AVALANCHE_CPMAC_HIGH_PORT_ID        1    
++#define AVALANCHE_USB_PORT_ID               2
++#define AVALANCHE_WLAN_PORT_ID              3
++
++
++#define AVALANCHE_MARVELL_BASE_PORT_ID      4
++
++/* The marvell ports occupy port ids from  4 to 8 */
++/* so the next port id number should start at 9   */
++
++
++#endif /* _IF_PORT_H_ */
+diff -urN linux.old/include/asm-mips/ar7/sangam_boards.h linux.dev/include/asm-mips/ar7/sangam_boards.h
+--- linux.old/include/asm-mips/ar7/sangam_boards.h     1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/ar7/sangam_boards.h     2005-07-09 08:00:15.304024000 +0200
+@@ -0,0 +1,77 @@
++#ifndef _SANGAM_BOARDS_H
++#define _SANGAM_BOARDS_H
++
++// Let us define board specific information here. 
++
++
++#if defined(CONFIG_AR7DB)
++
++#define AFECLK_FREQ                                 35328000
++#define REFCLK_FREQ                                 25000000
++#define OSC3_FREQ                                   24000000
++#define AVALANCHE_LOW_CPMAC_PHY_MASK                0x80000000
++#define AVALANCHE_HIGH_CPMAC_PHY_MASK               0x55555555  
++#define AVALANCHE_LOW_CPMAC_MDIX_MASK               0x80000000
++
++#endif
++
++
++#if defined(CONFIG_AR7RD)
++#define AFECLK_FREQ                                 35328000
++#define REFCLK_FREQ                                 25000000
++#define OSC3_FREQ                                   24000000
++#define AVALANCHE_LOW_CPMAC_PHY_MASK                0x80000000
++#define AVALANCHE_HIGH_CPMAC_PHY_MASK               0x2
++#define AVALANCHE_LOW_CPMAC_MDIX_MASK               0x80000000
++#endif
++
++
++#if defined(CONFIG_AR7WI)
++#define AFECLK_FREQ                                 35328000
++#define REFCLK_FREQ                                 25000000
++#define OSC3_FREQ                                   24000000
++#define AVALANCHE_LOW_CPMAC_PHY_MASK                0x80000000
++#define AVALANCHE_HIGH_CPMAC_PHY_MASK               0x2
++#define AVALANCHE_LOW_CPMAC_MDIX_MASK               0x80000000
++#endif
++
++
++#if defined(CONFIG_AR7V)
++#define AFECLK_FREQ                                 35328000
++#define REFCLK_FREQ                                 25000000
++#define OSC3_FREQ                                   24000000
++#define AVALANCHE_LOW_CPMAC_PHY_MASK                0x80000000
++#define AVALANCHE_HIGH_CPMAC_PHY_MASK               0x2
++#define AVALANCHE_LOW_CPMAC_MDIX_MASK               0x80000000
++#endif
++
++
++#if defined(CONFIG_AR7WRD) 
++#define AFECLK_FREQ                                 35328000
++#define REFCLK_FREQ                                 25000000
++#define OSC3_FREQ                                   24000000
++#define AVALANCHE_LOW_CPMAC_PHY_MASK                0x80000000
++#define AVALANCHE_HIGH_CPMAC_PHY_MASK               0x00010000
++#define AVALANCHE_LOW_CPMAC_MDIX_MASK               0x80000000
++#endif
++
++
++#if defined(CONFIG_AR7VWI) 
++#define AFECLK_FREQ                                 35328000
++#define REFCLK_FREQ                                 25000000
++#define OSC3_FREQ                                   24000000
++#define AVALANCHE_LOW_CPMAC_PHY_MASK                0x80000000
++#define AVALANCHE_HIGH_CPMAC_PHY_MASK               0x00010000
++#define AVALANCHE_LOW_CPMAC_MDIX_MASK               0x80000000
++#endif
++
++
++#if defined CONFIG_SEAD2
++#define AVALANCHE_LOW_CPMAC_PHY_MASK                0xAAAAAAAA
++#define AVALANCHE_HIGH_CPMAC_PHY_MASK               0x55555555
++#define AVALANCHE_LOW_CPMAC_MDIX_MASK               0
++#include <asm/mips-boards/sead.h>
++#endif
++
++
++#endif
+diff -urN linux.old/include/asm-mips/ar7/sangam_clk_cntl.h linux.dev/include/asm-mips/ar7/sangam_clk_cntl.h
+--- linux.old/include/asm-mips/ar7/sangam_clk_cntl.h   1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/ar7/sangam_clk_cntl.h   2005-07-09 08:00:15.304024000 +0200
+@@ -0,0 +1,25 @@
++/*****************************************************************************
++ * Clock Control
++ *****************************************************************************/
++#ifndef _SANGAM_CLK_CNTL_H_
++#define _SANGAM_CLK_CNTL_H_
++#include <asm/ar7/avalanche_misc.h>
++
++#define CLK_MHZ(x)    ( (x) * 1000000 )
++
++/* The order of ENUMs here should not be altered since
++ * the register addresses are derived from the order
++ */
++
++typedef enum AVALANCHE_CLKC_ID_tag
++{
++    CLKC_VBUS,
++    CLKC_MIPS,
++    CLKC_USB,
++    CLKC_SYS
++} AVALANCHE_CLKC_ID_T;
++
++void avalanche_clkc_init(unsigned int afe_clk,unsigned int refclk, unsigned int xtal3in);
++int avalanche_clkc_set_freq(AVALANCHE_CLKC_ID_T clk_id, unsigned int output_freq);
++unsigned int avalanche_clkc_get_freq(AVALANCHE_CLKC_ID_T clk_id);
++#endif
+diff -urN linux.old/include/asm-mips/ar7/sangam.h linux.dev/include/asm-mips/ar7/sangam.h
+--- linux.old/include/asm-mips/ar7/sangam.h    1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/asm-mips/ar7/sangam.h    2005-07-09 08:00:15.305023000 +0200
+@@ -0,0 +1,180 @@
++#ifndef _SANGAM_H_
++#define _SANGAM_H_
++
++#include <linux/config.h>
++#include <asm/addrspace.h>
++
++/*----------------------------------------------------
++ * Sangam's Module Base Addresses
++ *--------------------------------------------------*/
++#define AVALANCHE_ADSL_SUB_SYS_MEM_BASE       (KSEG1ADDR(0x01000000)) /* AVALANCHE ADSL Mem Base */
++#define AVALANCHE_BROADBAND_INTERFACE__BASE   (KSEG1ADDR(0x02000000)) /* AVALANCHE BBIF */        
++#define AVALANCHE_ATM_SAR_BASE                (KSEG1ADDR(0x03000000)) /* AVALANCHE ATM SAR */
++#define AVALANCHE_USB_SLAVE_BASE              (KSEG1ADDR(0x03400000)) /* AVALANCHE USB SLAVE */
++#define AVALANCHE_LOW_VLYNQ_MEM_MAP_BASE      (KSEG1ADDR(0x04000000)) /* AVALANCHE VLYNQ 0 Mem map */
++#define AVALANCHE_LOW_CPMAC_BASE              (KSEG1ADDR(0x08610000)) /* AVALANCHE CPMAC 0 */
++#define AVALANCHE_EMIF_CONTROL_BASE           (KSEG1ADDR(0x08610800)) /* AVALANCHE EMIF */
++#define AVALANCHE_GPIO_BASE                   (KSEG1ADDR(0x08610900)) /* AVALANCHE GPIO */
++#define AVALANCHE_CLOCK_CONTROL_BASE          (KSEG1ADDR(0x08610A00)) /* AVALANCHE Clock Control */
++#define AVALANCHE_WATCHDOG_TIMER_BASE         (KSEG1ADDR(0x08610B00)) /* AVALANCHE Watch Dog Timer */  
++#define AVALANCHE_TIMER0_BASE                 (KSEG1ADDR(0x08610C00)) /* AVALANCHE Timer 1 */  
++#define AVALANCHE_TIMER1_BASE                 (KSEG1ADDR(0x08610D00)) /* AVALANCHE Timer 2 */  
++#define AVALANCHE_UART0_REGS_BASE             (KSEG1ADDR(0x08610E00)) /* AVALANCHE UART 0 */
++#define AVALANCHE_UART1_REGS_BASE             (KSEG1ADDR(0x08610F00)) /* AVALANCHE UART 0 */
++#define AVALANCHE_I2C_BASE                    (KSEG1ADDR(0x08611000)) /* AVALANCHE I2C */
++#define AVALANCHE_USB_SLAVE_CONTROL_BASE      (KSEG1ADDR(0x08611200)) /* AVALANCHE USB DMA */
++#define AVALANCHE_MCDMA0_CTRL_BASE            (KSEG1ADDR(0x08611400)) /* AVALANCHE MC DMA 0 (channels 0-3) */
++#define AVALANCHE_RESET_CONTROL_BASE          (KSEG1ADDR(0x08611600)) /* AVALANCHE Reset Control */
++#define AVALANCHE_BIST_CONTROL_BASE           (KSEG1ADDR(0x08611700)) /* AVALANCHE BIST Control */
++#define AVALANCHE_LOW_VLYNQ_CONTROL_BASE      (KSEG1ADDR(0x08611800)) /* AVALANCHE VLYNQ0 Control */
++#define AVALANCHE_DEVICE_CONFIG_LATCH_BASE    (KSEG1ADDR(0x08611A00)) /* AVALANCHE Device Config Latch */
++#define AVALANCHE_HIGH_VLYNQ_CONTROL_BASE     (KSEG1ADDR(0x08611C00)) /* AVALANCHE VLYNQ1 Control */
++#define AVALANCHE_MDIO_BASE                   (KSEG1ADDR(0x08611E00)) /* AVALANCHE MDIO    */
++#define AVALANCHE_FSER_BASE                   (KSEG1ADDR(0x08612000)) /* AVALANCHE FSER base */
++#define AVALANCHE_INTC_BASE                   (KSEG1ADDR(0x08612400)) /* AVALANCHE INTC  */
++#define AVALANCHE_HIGH_CPMAC_BASE             (KSEG1ADDR(0x08612800)) /* AVALANCHE CPMAC 1 */
++#define AVALANCHE_HIGH_VLYNQ_MEM_MAP_BASE     (KSEG1ADDR(0x0C000000)) /* AVALANCHE VLYNQ 1 Mem map */
++
++#define AVALANCHE_SDRAM_BASE                  0x14000000UL
++
++
++/*----------------------------------------------------
++ * Sangam Interrupt Map (Primary Interrupts)
++ *--------------------------------------------------*/
++
++#define AVALANCHE_UNIFIED_SECONDARY_INT            0
++#define AVALANCHE_EXT_INT_0                        1
++#define AVALANCHE_EXT_INT_1                        2
++/* Line#  3 to 4 are reserved                            */
++#define AVALANCHE_TIMER_0_INT                      5
++#define AVALANCHE_TIMER_1_INT                      6
++#define AVALANCHE_UART0_INT                        7
++#define AVALANCHE_UART1_INT                        8
++#define AVALANCHE_DMA_INT0                         9
++#define AVALANCHE_DMA_INT1                        10
++/* Line# 11 to 14 are reserved                    */
++#define AVALANCHE_ATM_SAR_INT                     15
++/* Line# 16 to 18 are reserved                    */
++#define AVALANCHE_LOW_CPMAC_INT                   19
++/* Line# 20 is reserved                           */
++#define AVALANCHE_LOW_VLYNQ_INT                   21
++#define AVALANCHE_CODEC_WAKEUP_INT                22
++/* Line# 23 is reserved                           */
++#define AVALANCHE_USB_SLAVE_INT                   24
++#define AVALANCHE_HIGH_VLYNQ_INT                  25
++/* Line# 26 to 27 are reserved                    */
++#define AVALANCHE_UNIFIED_PHY_INT                 28
++#define AVALANCHE_I2C_INT                         29
++#define AVALANCHE_DMA_INT2                        30
++#define AVALANCHE_DMA_INT3                        31
++/* Line# 32 is reserved                           */
++#define AVALANCHE_HIGH_CPMAC_INT                  33
++/* Line# 34 to 36 is reserved                     */
++#define AVALANCHE_VDMA_VT_RX_INT                  37
++#define AVALANCHE_VDMA_VT_TX_INT                  38
++#define AVALANCHE_ADSL_SUB_SYSTEM_INT             39
++
++
++#define AVALANCHE_EMIF_INT                        47
++
++
++
++/*-----------------------------------------------------------
++ * Sangam's Reset Bits
++ *---------------------------------------------------------*/
++
++#define AVALANCHE_UART0_RESET_BIT                  0
++#define AVALANCHE_UART1_RESET_BIT                  1
++#define AVALANCHE_I2C_RESET_BIT                    2
++#define AVALANCHE_TIMER0_RESET_BIT                 3
++#define AVALANCHE_TIMER1_RESET_BIT                 4
++/* Reset bit  5 is reserved.                       */
++#define AVALANCHE_GPIO_RESET_BIT                   6
++#define AVALANCHE_ADSL_SUB_SYS_RESET_BIT           7
++#define AVALANCHE_USB_SLAVE_RESET_BIT              8
++#define AVALANCHE_ATM_SAR_RESET_BIT                9
++/* Reset bit 10 is reserved.                      */
++#define AVALANCHE_VDMA_VT_RESET_BIT               11
++#define AVALANCHE_FSER_RESET_BIT                  12
++/* Reset bit 13 to 15 are reserved                */
++#define AVALANCHE_HIGH_VLYNQ_RESET_BIT            16
++#define AVALANCHE_LOW_CPMAC_RESET_BIT             17
++#define AVALANCHE_MCDMA_RESET_BIT                 18
++#define AVALANCHE_BIST_RESET_BIT                  19
++#define AVALANCHE_LOW_VLYNQ_RESET_BIT             20
++#define AVALANCHE_HIGH_CPMAC_RESET_BIT            21
++#define AVALANCHE_MDIO_RESET_BIT                  22
++#define AVALANCHE_ADSL_SUB_SYS_DSP_RESET_BIT      23
++/* Reset bit 24 to 25 are reserved                */
++#define AVALANCHE_LOW_EPHY_RESET_BIT              26
++/* Reset bit 27 to 31 are reserved                */
++
++
++#define AVALANCHE_POWER_MODULE_USBSP               0
++#define AVALANCHE_POWER_MODULE_WDTP                1
++#define AVALANCHE_POWER_MODULE_UT0P                2
++#define AVALANCHE_POWER_MODULE_UT1P                3
++#define AVALANCHE_POWER_MODULE_IICP                4
++#define AVALANCHE_POWER_MODULE_VDMAP               5
++#define AVALANCHE_POWER_MODULE_GPIOP               6
++#define AVALANCHE_POWER_MODULE_VLYNQ1P             7
++#define AVALANCHE_POWER_MODULE_SARP                8
++#define AVALANCHE_POWER_MODULE_ADSLP               9
++#define AVALANCHE_POWER_MODULE_EMIFP              10
++#define AVALANCHE_POWER_MODULE_ADSPP              12
++#define AVALANCHE_POWER_MODULE_RAMP               13
++#define AVALANCHE_POWER_MODULE_ROMP               14
++#define AVALANCHE_POWER_MODULE_DMAP               15
++#define AVALANCHE_POWER_MODULE_BISTP              16
++#define AVALANCHE_POWER_MODULE_TIMER0P            18
++#define AVALANCHE_POWER_MODULE_TIMER1P            19
++#define AVALANCHE_POWER_MODULE_EMAC0P             20
++#define AVALANCHE_POWER_MODULE_EMAC1P             22
++#define AVALANCHE_POWER_MODULE_EPHYP              24
++#define AVALANCHE_POWER_MODULE_VLYNQ0P            27
++
++
++
++
++
++/*
++ * Sangam board vectors
++ */
++
++#define AVALANCHE_VECS       (KSEG1ADDR(AVALANCHE_SDRAM_BASE))
++#define AVALANCHE_VECS_KSEG0 (KSEG0ADDR(AVALANCHE_SDRAM_BASE))
++
++/*-----------------------------------------------------------------------------
++ * Sangam's system register.
++ * 
++ *---------------------------------------------------------------------------*/
++#define AVALANCHE_DCL_BOOTCR          (KSEG1ADDR(0x08611A00))
++#define AVALANCHE_EMIF_SDRAM_CFG      (AVALANCHE_EMIF_CONTROL_BASE + 0x8)
++#define AVALANCHE_RST_CTRL_PRCR       (KSEG1ADDR(0x08611600))
++#define AVALANCHE_RST_CTRL_SWRCR      (KSEG1ADDR(0x08611604))
++#define AVALANCHE_RST_CTRL_RSR        (KSEG1ADDR(0x08611600))
++
++#define AVALANCHE_POWER_CTRL_PDCR     (KSEG1ADDR(0x08610A00))
++#define AVALANCHE_WAKEUP_CTRL_WKCR    (KSEG1ADDR(0x08610A0C))
++
++#define AVALANCHE_GPIO_DATA_IN        (AVALANCHE_GPIO_BASE +  0x0)
++#define AVALANCHE_GPIO_DATA_OUT       (AVALANCHE_GPIO_BASE +  0x4)
++#define AVALANCHE_GPIO_DIR            (AVALANCHE_GPIO_BASE +  0x8)    
++#define AVALANCHE_GPIO_ENBL           (AVALANCHE_GPIO_BASE +  0xC)
++#define AVALANCHE_CVR                 (AVALANCHE_GPIO_BASE +  0x14)
++
++/*
++ * Yamon Prom print address.
++ */
++#define AVALANCHE_YAMON_FUNCTION_BASE             (KSEG1ADDR(0x10000500))
++#define AVALANCHE_YAMON_PROM_PRINT_COUNT_ADDR     (AVALANCHE_YAMON_FUNCTION_BASE + 0x4)  /* print_count function */
++#define AVALANCHE_YAMON_PROM_PRINT_ADDR           (AVALANCHE_YAMON_FUNCTION_BASE + 0x34)
++
++#define AVALANCHE_BASE_BAUD       ( 3686400 / 16 )
++
++#define  AVALANCHE_GPIO_PIN_COUNT         32             
++#define  AVALANCHE_GPIO_OFF_MAP           {0xF34FFFC0} 
++
++#include "sangam_boards.h"
++
++#endif /*_SANGAM_H_ */
 diff -urN linux.old/include/asm-mips/ar7/tnetd73xx_err.h linux.dev/include/asm-mips/ar7/tnetd73xx_err.h
 --- linux.old/include/asm-mips/ar7/tnetd73xx_err.h     1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/include/asm-mips/ar7/tnetd73xx_err.h     2005-07-07 04:39:14.434224000 +0200
++++ linux.dev/include/asm-mips/ar7/tnetd73xx_err.h     2005-07-09 08:00:15.305023000 +0200
 @@ -0,0 +1,42 @@
 +/******************************************************************************
 + * FILE PURPOSE:    TNETD73xx Error Definations Header File
@@ -4990,7 +5582,7 @@ diff -urN linux.old/include/asm-mips/ar7/tnetd73xx_err.h linux.dev/include/asm-m
 +#endif /* __TNETD73XX_ERR_H__ */
 diff -urN linux.old/include/asm-mips/ar7/tnetd73xx.h linux.dev/include/asm-mips/ar7/tnetd73xx.h
 --- linux.old/include/asm-mips/ar7/tnetd73xx.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/include/asm-mips/ar7/tnetd73xx.h 2005-07-07 04:39:14.433224000 +0200
++++ linux.dev/include/asm-mips/ar7/tnetd73xx.h 2005-07-09 08:00:15.306023000 +0200
 @@ -0,0 +1,340 @@
 +/******************************************************************************
 + * FILE PURPOSE:    TNETD73xx Common Header File
@@ -5334,7 +5926,7 @@ diff -urN linux.old/include/asm-mips/ar7/tnetd73xx.h linux.dev/include/asm-mips/
 +#endif /* __TNETD73XX_H_ */
 diff -urN linux.old/include/asm-mips/ar7/tnetd73xx_misc.h linux.dev/include/asm-mips/ar7/tnetd73xx_misc.h
 --- linux.old/include/asm-mips/ar7/tnetd73xx_misc.h    1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/include/asm-mips/ar7/tnetd73xx_misc.h    2005-07-07 04:39:14.434224000 +0200
++++ linux.dev/include/asm-mips/ar7/tnetd73xx_misc.h    2005-07-09 08:00:15.306023000 +0200
 @@ -0,0 +1,243 @@
 +/******************************************************************************
 + * FILE PURPOSE:    TNETD73xx Misc modules API Header
@@ -5580,8 +6172,8 @@ diff -urN linux.old/include/asm-mips/ar7/tnetd73xx_misc.h linux.dev/include/asm-
 +
 +#endif /* __TNETD73XX_MISC_H__ */
 diff -urN linux.old/include/asm-mips/io.h linux.dev/include/asm-mips/io.h
---- linux.old/include/asm-mips/io.h    2005-07-07 05:38:31.416480768 +0200
-+++ linux.dev/include/asm-mips/io.h    2005-07-07 04:39:14.434224000 +0200
+--- linux.old/include/asm-mips/io.h    2005-07-09 08:01:49.846651440 +0200
++++ linux.dev/include/asm-mips/io.h    2005-07-09 08:00:15.307023000 +0200
 @@ -63,8 +63,12 @@
  #ifdef CONFIG_64BIT_PHYS_ADDR
  #define page_to_phys(page)    ((u64)(page - mem_map) << PAGE_SHIFT)
@@ -5596,8 +6188,8 @@ diff -urN linux.old/include/asm-mips/io.h linux.dev/include/asm-mips/io.h
  #define IO_SPACE_LIMIT 0xffff
  
 diff -urN linux.old/include/asm-mips/irq.h linux.dev/include/asm-mips/irq.h
---- linux.old/include/asm-mips/irq.h   2005-07-07 05:38:31.424479552 +0200
-+++ linux.dev/include/asm-mips/irq.h   2005-07-07 04:39:14.435224000 +0200
+--- linux.old/include/asm-mips/irq.h   2005-07-09 08:01:49.847651288 +0200
++++ linux.dev/include/asm-mips/irq.h   2005-07-09 08:00:15.307023000 +0200
 @@ -14,7 +14,12 @@
  #include <linux/config.h>
  #include <linux/linkage.h>
@@ -5612,8 +6204,8 @@ diff -urN linux.old/include/asm-mips/irq.h linux.dev/include/asm-mips/irq.h
  #ifdef CONFIG_I8259
  static inline int irq_cannonicalize(int irq)
 diff -urN linux.old/include/asm-mips/page.h linux.dev/include/asm-mips/page.h
---- linux.old/include/asm-mips/page.h  2005-07-07 05:38:31.426479248 +0200
-+++ linux.dev/include/asm-mips/page.h  2005-07-07 04:39:14.435224000 +0200
+--- linux.old/include/asm-mips/page.h  2005-07-09 08:01:49.847651288 +0200
++++ linux.dev/include/asm-mips/page.h  2005-07-09 08:00:15.308023000 +0200
 @@ -129,7 +129,11 @@
  
  #define __pa(x)               ((unsigned long) (x) - PAGE_OFFSET)
@@ -5627,8 +6219,8 @@ diff -urN linux.old/include/asm-mips/page.h linux.dev/include/asm-mips/page.h
  
  #define VM_DATA_DEFAULT_FLAGS  (VM_READ | VM_WRITE | VM_EXEC | \
 diff -urN linux.old/include/asm-mips/pgtable-32.h linux.dev/include/asm-mips/pgtable-32.h
---- linux.old/include/asm-mips/pgtable-32.h    2005-07-07 05:38:31.434478032 +0200
-+++ linux.dev/include/asm-mips/pgtable-32.h    2005-07-07 04:39:14.435224000 +0200
+--- linux.old/include/asm-mips/pgtable-32.h    2005-07-09 08:01:49.847651288 +0200
++++ linux.dev/include/asm-mips/pgtable-32.h    2005-07-09 08:00:15.308023000 +0200
 @@ -108,7 +108,18 @@
   * and a page entry and page directory to the page they refer to.
   */
@@ -5670,8 +6262,8 @@ diff -urN linux.old/include/asm-mips/pgtable-32.h linux.dev/include/asm-mips/pgt
  #define __mk_pte(page_nr,pgprot) __pte(((page_nr) << (PAGE_SHIFT+2)) | pgprot_val(pgprot))
  #else
 diff -urN linux.old/include/asm-mips/serial.h linux.dev/include/asm-mips/serial.h
---- linux.old/include/asm-mips/serial.h        2005-07-07 05:38:31.470472560 +0200
-+++ linux.dev/include/asm-mips/serial.h        2005-07-07 04:39:14.436223000 +0200
+--- linux.old/include/asm-mips/serial.h        2005-07-09 08:01:49.848651136 +0200
++++ linux.dev/include/asm-mips/serial.h        2005-07-09 08:00:15.308023000 +0200
 @@ -65,6 +65,15 @@
  
  #define C_P(card,port) (((card)<<6|(port)<<3) + 1)
@@ -5697,8 +6289,8 @@ diff -urN linux.old/include/asm-mips/serial.h linux.dev/include/asm-mips/serial.
        AU1000_SERIAL_PORT_DEFNS                \
        COBALT_SERIAL_PORT_DEFNS                \
 diff -urN linux.old/Makefile linux.dev/Makefile
---- linux.old/Makefile 2005-07-07 05:38:31.320495360 +0200
-+++ linux.dev/Makefile 2005-07-07 04:39:14.501214000 +0200
+--- linux.old/Makefile 2005-07-09 08:01:49.848651136 +0200
++++ linux.dev/Makefile 2005-07-09 08:00:15.404008000 +0200
 @@ -91,7 +91,7 @@
  
  CPPFLAGS := -D__KERNEL__ -I$(HPATH)
diff --git a/openwrt/target/linux/linux-2.4/patches/ar7/002-net_driver_cpmac.patch b/openwrt/target/linux/linux-2.4/patches/ar7/002-net_driver_cpmac.patch
new file mode 100644 (file)
index 0000000..1bb7ac8
--- /dev/null
@@ -0,0 +1,13324 @@
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/cpcommon_cpmac.c linux-2.4.30/drivers/net/avalanche_cpmac/cpcommon_cpmac.c
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/cpcommon_cpmac.c     1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/cpcommon_cpmac.c  2005-04-15 05:10:40.000000000 +0200
+@@ -0,0 +1,728 @@
++#ifndef _INC_CPCOMMON_C
++#define _INC_CPCOMMON_C
++
++#ifdef _CPHAL_CPMAC
++#include "cpremap_cpmac.c"
++#endif
++
++#ifdef _CPHAL_AAL5
++#include "cpremap_cpaal5.c"
++#endif
++
++#ifdef _CPHAL_CPSAR
++#include "cpremap_cpsar.c"
++#endif
++
++#ifdef _CPHAL_AAL2
++#include "cpremap_cpaal2.c"
++#endif
++
++/**
++@defgroup Common_Config_Params Common Configuration Parameters
++
++This section documents the configuration parameters that are valid across
++all CPHAL devices.
++@{
++*/
++/** This is the debug level.  The field is bit defined, such that the user
++should set to 1 all the bits corresponding to desired debug outputs.  The following 
++are the meanings for each debug bit:
++- bit0 (LSB): CPHAL Function Trace
++- b1 : OS Function call trace
++- b2 : Critical section entry/exit
++- b3 : Memory allocation/destruction
++- b4 : Detailed information in Rx path
++- b5 : Detailed information in Tx path
++- b6 : Extended error information
++- b7 : General info
++*/
++static const char pszDebug[]        = "debug";
++/** CPU Frequency. */
++/*static const char pszCpuFreq[]      = "CpuFreq";*/               /*MJH-030403*/
++/** Base address for the module. */
++static const char pszBase[]         = "base";
++/** Reset bit for the module. */
++static const char pszResetBit[]     = "reset_bit";
++/** Reset base address for the module. */
++static const char pszResetBase[]    = "ResetBase";
++/** Interrupt line for the module. */
++static const char pszIntLine[]      = "int_line";
++/** VLYNQ offset for the module.  Disregard if not using VLYNQ. */
++static const char pszOffset[]       = "offset";
++/** The OS may "Get" this parameter, which is a pointer
++    to a character string that indicates the version of CPHAL. */
++static const char pszVer[]          = "Version";
++/*@}*/
++
++/**
++@defgroup Common_Control_Params Common Keys for [os]Control()
++
++This section documents the keys used with the OS @c Control() interface that
++are required by CPHAL devices.
++
++@{
++*/
++/** Used to wait for an integer number of clock ticks, given as an integer
++    pointer in the @p Value parameter.  No actions are defined. */
++static const char pszSleep[]             = "Sleep";
++/** Requests the OS to flush it's IO buffers.  No actions are defined. */
++static const char pszSioFlush[]          = "SioFlush";
++/*@}*/
++
++static const char pszStateChange[]       = "StateChange";
++static const char pszStatus[]            = "Status";
++
++static const char pszGET[]               = "Get";
++static const char pszSET[]               = "Set";
++static const char pszCLEAR[]             = "Clear";
++static const char pszNULL[]              = "";
++static const char pszLocator[]           = "Locator";
++static const char pszOff[]               = "Off";
++static const char pszOn[]                = "On";
++static const char hcMaxFrags[]           = "MaxFrags";
++
++#ifdef _CPHAL_CPMAC
++
++/*  New method for string constants */
++const char hcClear[]  = "Clear";
++const char hcGet[]    = "Get";
++const char hcSet[]    = "Set";
++
++const char hcTick[]   = "Tick";
++
++static const CONTROL_KEY KeyCommon[] =
++   {
++     {""                   , enCommonStart},
++     {pszStatus            , enStatus},
++     {pszOff               , enOff},
++     {pszOn                , enOn},
++     {pszDebug             , enDebug},
++     {hcCpuFrequency       , enCpuFreq},                           /*MJH~030403*/
++     {""                   , enCommonEnd}
++   };
++#endif
++
++/**
++@defgroup Common_Statistics Statistics
++
++A broad array of module statistics is available.  Statistics values are accessed
++through the @c Control() interface of the CPHAL.  There are 5 different levels
++of statistics, each of which correspond to a unique set of data.  Furthermore,
++certain statistics data is indexed by using a channel number and Tx queue number.
++The following is a brief description of each statistics level, along with the
++indexes used for the level:
++
++- Level 0:  Hardware Statistics (index with channel)
++- Level 1:  CPHAL Software Statistics (channel, queue)
++- Level 2:  CPHAL Flags (channel, queue)
++- Level 3:  CPHAL Channel Configuration (channel)
++- Level 4:  CPHAL General Configuration (no index)
++
++The caller requests statistics information by providing a Key string to the
++@c Control() API in the following format: "Stats;[Level #];[Ch #];[Queue #]".
++The only valid Action parameter for statistics usage is "Get".
++
++Code Examples:
++@code
++unsigned int *StatsData;
++
++# Get Level 0 stats for Channel 1
++HalFunc->Control(OsDev->HalDev, "Stats;0;1", "Get", &StatsData);
++
++# Get Level 2 stats for Channel 0, Queue 0
++HalFunc->Control(OsDev->HalDev, "Stats;2;0;0", "Get", &StatsData);
++
++# Get Level 4 stats
++HalFunc->Control(OsDev->HalDev, "Stats;4", "Get", &StatsData);
++@endcode
++
++The information returned in the Value parameter of @c Control() is an
++array of pointers to strings.  The pointers are arranged in pairs.
++The first pointer is a pointer to a name string for a particular statistic.
++The next pointer is a pointer to a string containing the representation of
++the integer statistic value corresponding to the first pointer.  This is followed
++by another pair of pointers, and so on, until a NULL pointer is encountered.  The
++following is example code for processing the statistics data.  Note that the OS
++is responsible for freeing the memory passed back through the Value parameter of
++@c Control().
++
++@code
++unsigned int *StatsData;
++
++# Get Level 0 stats for Channel 1
++HalFunc->Control(OsDev->HalDev, "Stats;0;1", "Get", &StatsData);
++
++# output Statistics data
++PrintStats(StatsData);
++
++# the upper layer is responsible for freeing stats info
++free(&StatsPtr);
++
++...
++
++void PrintStats(unsigned int *StatsPtr)
++  {
++   while(*StatsPtr)
++     {
++      printf("%20s:",  (char *)*StatsPtr);
++      StatsPtr++;
++      printf("%11s\n", (char *)*StatsPtr);
++      StatsPtr++;
++     }
++   MySioFlush();
++  }
++@endcode
++
++Within each statistics level, there are several statistics defined.  The statistics that
++are common to every CPPI module are listed below.  In addition, each module may define
++extra statistics in each level, which will be documented within the module-specific
++documentation appendices.
++
++- Level 0 Statistics
++  - All level 0 statistics are module-specific.
++- Level 1 Statistics (CPHAL Software Statistics)
++  - DmaLenErrors: Incremented when the port DMA's more data than expected (per channel). (AAL5 Only)
++  - TxMisQCnt: Incremented when host queues a packet for transmission as the port finishes
++transmitting the previous last packet in the queue (per channel and queue).
++  - RxMisQCnt: Incremented when host queues adds buffers to a queue as the port finished the
++reception of the previous last packet in the queue (per channel).
++  - TxEOQCnt: Number of times the port has reached the end of the transmit queue (per channel and queue).
++  - RxEOQCnt: Number of times the port has reached the end of the receive queue (per channel).
++  - RxPacketsServiced: Number of received packets (per channel).
++  - TxPacketsServiced: Number of transmitted packets (per channel and queue).
++  - RxMaxServiced: Maximum number of packets that the CPHAL receive interrupt has serviced at a time (per channel).
++  - TxMaxServiced: Maximum number of packets that the CPHAL transmit interrupt has serviced at a time (per channel and queue).
++  - RxTotal: Total number of received packets, all channels.
++  - TxTotal: Total number of transmitted packets, all channels and queues.
++- Level 2 Statistics (CPHAL Flags)
++  - RcbPool: Pointer to receive descriptor pool (per channel).
++  - RxActQueueCount: Number of buffers currently available for receive (per channel).
++  - RxActQueueHead: Pointer to first buffer in receive queue (per channel).
++  - RxActQueueTail: Pointer to last buffer in receive queue (per channel).
++  - RxActive: 0 if inactive (no buffers available), or 1 if active (buffers available).
++  - RcbStart: Pointer to block of receive descriptors.
++  - RxTeardownPending: 1 if Rx teardown is pending but incomplete, 0 otherwise.
++  - TcbPool: Pointer to transmit descriptor pool (per channel and queue).
++  - TxActQueueCount: Number of buffers currently queued to be transmitted (per channel and queue).
++  - TxActQueueHead: Pointer to first buffer in transmit queue (per channel and queue).
++  - TxActQueueTail: Pointer to last buffer in transmit queue (per channel and queue).
++  - TxActive: 0 if inactive (no buffers to send), or 1 if active (buffers queued to send).
++  - TcbStart: Pointer to block of transmit descriptors.
++  - TxTeardownPending: 1 if Tx teardown is pending but incomplete, 0 otherwise.
++- Level 3 Statistics (CPHAL Channel Configuration)
++  - RxBufSize: Rx buffer size.
++  - RxBufferOffset: Rx buffer offset.
++  - RxNumBuffers: Number of Rx buffers.
++  - RxServiceMax: Maximum number of receive packets to service at a time.
++  - TxNumBuffers: Number of Tx buffer descriptors.
++  - TxNumQueues: Number of Tx queues to use.
++  - TxServiceMax: Maximum number of transmit packets to service at a time.
++- Level 4 Statistics (CPHAL General Configuration)
++  - Base Address: Base address of the module.
++  - Offset (VLYNQ): VLYNQ relative module offset.
++  - Interrupt Line: Interrupt number.
++  - Debug: Debug flag, 1 to enable debug.
++  - Inst: Instance number.
++*/
++
++/* 
++   Data Type 0 = int display
++   Data Type 1 = hex display
++   Data Type 2 = channel structure, int display
++   Data Type 3 = queue index and int display
++   Data Type 4 = queue index and hex display
++*/
++#if (defined(_CPHAL_AAL5) || defined(_CPHAL_CPMAC)) /* +GSG 030307 */
++static STATS_TABLE StatsTable0[] =
++  {
++#ifdef _CPHAL_AAL5
++   /* Name ,        Data Ptr,   Data Type */
++   {"Crc Errors",          0,          0},
++   {"Len Errors",          0,          0},
++   {"Abort Errors",        0,          0},
++   {"Starv Errors",        0,          0}
++#endif
++#ifdef _CPHAL_CPMAC
++   {"Rx Good Frames",      0,          0}
++#endif
++  };
++
++static STATS_TABLE StatsTable1[] =
++  {
++   /* Name ,        Data Ptr,   Data Type */
++   {"DmaLenErrors",        0,          0},
++   {"TxMisQCnt",           0,          3},
++   {"RxMisQCnt",           0,          0},
++   {"TxEOQCnt",            0,          3},
++   {"RxEOQCnt",            0,          0},
++   {"RxPacketsServiced",   0,          0},
++   {"TxPacketsServiced",   0,          3},
++   {"RxMaxServiced",       0,          0},
++   {"TxMaxServiced",       0,          3},
++   {"RxTotal",             0,          0},
++   {"TxTotal",             0,          0},
++  };
++
++static STATS_TABLE StatsTable2[] =
++  {
++   /* Name ,        Data Ptr,   Data Type */
++   {"RcbPool",             0,          1},
++   {"RxActQueueCount",     0,          0},
++   {"RxActQueueHead",      0,          1},
++   {"RxActQueueTail",      0,          1},
++   {"RxActive",            0,          0},
++   {"RcbStart",            0,          1},
++   {"RxTeardownPending",   0,          0},
++   {"TcbPool",             0,          4},
++   {"TxActQueueCount",     0,          3},
++   {"TxActQueueHead",      0,          4},
++   {"TxActQueueTail",      0,          4},
++   {"TxActive",            0,          3},
++   {"TcbStart",            0,          4},
++   {"TxTeardownPending",   0,          0}
++  };
++
++static STATS_TABLE StatsTable3[] =
++  {
++   /* Name ,        Data Ptr,   Data Type */
++   {"RxBufSize",           0,          2},
++   {"RxBufferOffset",      0,          2},
++   {"RxNumBuffers",        0,          2},
++   {"RxServiceMax",        0,          2},
++   {"TxNumBuffers",        0,          2},
++   {"TxNumQueues",         0,          2},
++   {"TxServiceMax",        0,          2},
++#ifdef _CPHAL_AAL5
++   {"CpcsUU",              0,          2},
++   {"Gfc",                 0,          2},
++   {"Clp",                 0,          2},
++   {"Pti",                 0,          2},
++   {"DaMask",              0,          2},
++   {"Priority",            0,          2},
++   {"PktType",             0,          2},
++   {"Vci",                 0,          2},
++   {"Vpi",                 0,          2},
++   {"CellRate",            0,          2},
++   {"QosType",             0,          2},
++   {"Mbs",                 0,          2},
++   {"Pcr",                 0,          2}
++#endif
++  };
++
++static STATS_TABLE StatsTable4[] =
++  {
++   {"Base Address",        0,          1},
++   {"Offset (VLYNQ)",      0,          0},
++   {"Interrupt Line",      0,          0},
++   {"Debug",               0,          0},
++   {"Instance",            0,          0},
++#ifdef _CPHAL_AAL5
++   {"UniNni",              0,          0}
++#endif
++  };
++
++static STATS_DB StatsDb[] =
++  {
++    {(sizeof(StatsTable0)/sizeof(STATS_TABLE)), StatsTable0},
++    {(sizeof(StatsTable1)/sizeof(STATS_TABLE)), StatsTable1},
++    {(sizeof(StatsTable2)/sizeof(STATS_TABLE)), StatsTable2},
++    {(sizeof(StatsTable3)/sizeof(STATS_TABLE)), StatsTable3},
++    {(sizeof(StatsTable4)/sizeof(STATS_TABLE)), StatsTable4}
++  };
++#endif /* +GSG 030307 */
++
++#ifdef _CPHAL_CPMAC /* +RC 3.02 */
++static void resetWait(HAL_DEVICE *HalDev)
++  {                                                                  /*+RC3.02*/
++  const int TickReset=64;
++  osfuncSleep((int*)&TickReset);
++  }                                                                  /*+RC3.02*/
++#endif /* +RC 3.02 */
++
++/* I only define the reset base function for the modules
++   that can perform a reset.  The AAL5 and AAL2 modules
++   do not perform a reset, that is done by the shared module
++   CPSAR */
++#if defined(_CPHAL_CPSAR) || defined(_CPHAL_CPMAC) || defined(_CPHAL_VDMAVT)
++/*
++ *  Determines the reset register address to be used for a particular device.
++ *  It will search the current device entry for Locator information.  If the
++ *  device is a root device, there will be no Locator information, and the
++ *  function will find and return the root reset register.  If a Locator value
++ *  is found, the function will search each VLYNQ device entry in the system
++ *  looking for a matching Locator.  Once it finds a VLYNQ device entry with
++ *  a matching Locator, it will extract the "ResetBase" parameter from that
++ *  VLYNQ device entry (thus every VLYNQ entry must have the ResetBase parameter).
++ *
++ *  @param  HalDev   CPHAL module instance. (set by xxxInitModule())
++ *  @param  ResetBase Pointer to integer address of reset register.
++ *
++ *  @return 0 OK, Non-zero not OK
++ */
++static int ResetBaseGet(HAL_DEVICE *HalDev, bit32u *ResetBase)
++  {
++   char *DeviceInfo = HalDev->DeviceInfo;
++   char *MyLocator, *NextLocator;
++   int Inst=1;
++   bit32u error_code;
++
++#ifdef __CPHAL_DEBUG
++   if (DBG(0))
++     {
++      dbgPrintf("[cpcommon]ResetBaseGet(HalDev:%08x, ResetBase:%08x)\n", (bit32u)HalDev, ResetBase);
++      osfuncSioFlush();
++     }
++#endif
++
++   error_code = HalDev->OsFunc->DeviceFindParmValue(DeviceInfo, "Locator", &MyLocator);
++   if (error_code)
++     {
++      /* if no Locator value, device is on the root, so get the "reset" device */
++      error_code = HalDev->OsFunc->DeviceFindInfo(0, "reset", &DeviceInfo);
++      if  (error_code)
++        {
++         return(EC_VAL_DEVICE_NOT_FOUND);
++        }
++
++      error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, "base", ResetBase);
++      if (error_code)
++        {
++         return(EC_VAL_BASE_ADDR_NOT_FOUND);
++        }
++
++      *ResetBase = ((bit32u)PhysToVirtNoCache(*ResetBase));
++
++      /* found base address for root device, so we're done */
++      return (EC_NO_ERRORS);
++     }
++    else
++     {
++      /* we have a Locator value, so the device is remote */
++
++      /* Find a vlynq device with a matching locator value */
++      while ((HalDev->OsFunc->DeviceFindInfo(Inst, "vlynq", &DeviceInfo)) == EC_NO_ERRORS)
++        {
++         error_code = HalDev->OsFunc->DeviceFindParmValue(DeviceInfo, "Locator", &NextLocator);
++         if (error_code)
++           {
++            /* no Locator value for this VLYNQ, so move on */
++            continue;
++           }
++         if (HalDev->OsFunc->Strcmpi(MyLocator, NextLocator)==0)
++           {
++            /* we have found a VLYNQ with a matching Locator, so extract the ResetBase */
++            error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, "ResetBase", ResetBase);
++            if (error_code)
++              {
++               return(EC_VAL_BASE_ADDR_NOT_FOUND);
++              }
++            *ResetBase = ((bit32u)PhysToVirtNoCache(*ResetBase));
++
++            /* found base address for root device, so we're done */
++            return (EC_NO_ERRORS);
++           }
++         Inst++;
++        } /* while */
++     } /* else */
++
++   return (EC_NO_ERRORS);
++  }
++#endif
++
++#ifndef _CPHAL_AAL2 /* + RC 3.02 */
++static bit32u ConfigGetCommon(HAL_DEVICE *HalDev)
++  {
++   bit32u ParmValue;
++   bit32 error_code;
++   char *DeviceInfo = HalDev->DeviceInfo;
++
++#ifdef __CPHAL_DEBUG
++   if (DBG(0))
++     {
++      dbgPrintf("[cpcommon]ConfigGetCommon(HalDev:%08x)\n", (bit32u)HalDev);
++      osfuncSioFlush();
++     }
++#endif
++
++   error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszBase, &ParmValue);
++   if (error_code)
++     {
++      return(EC_FUNC_HAL_INIT|EC_VAL_BASE_ADDR_NOT_FOUND);
++     }
++   HalDev->dev_base = ((bit32u)PhysToVirtNoCache(ParmValue));
++
++#ifndef _CPHAL_AAL5
++#ifndef _CPHAL_AAL2
++   error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszResetBit, &ParmValue);
++   if(error_code)
++     {
++      return(EC_FUNC_HAL_INIT|EC_VAL_RESET_BIT_NOT_FOUND);
++     }
++   HalDev->ResetBit = ParmValue;
++
++   /* Get reset base address */
++   error_code = ResetBaseGet(HalDev, &ParmValue);
++   if (error_code)
++     return(EC_FUNC_HAL_INIT|EC_VAL_RESET_BASE_NOT_FOUND);
++   HalDev->ResetBase = ParmValue;
++#endif
++#endif
++
++#ifndef _CPHAL_CPSAR
++   error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszIntLine,&ParmValue);
++   if (error_code)
++     {
++      return(EC_FUNC_HAL_INIT|EC_VAL_INTERRUPT_NOT_FOUND);
++     }
++   HalDev->interrupt = ParmValue;
++#endif
++
++   /* only look for the offset if there is a Locator field, which indicates that
++      the module is a VLYNQ module */
++   error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszLocator,&ParmValue);
++   if (!error_code)
++     {
++      error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszOffset,&ParmValue);
++      if (error_code)
++        {
++         return(EC_FUNC_HAL_INIT|EC_VAL_OFFSET_NOT_FOUND);
++        }
++      HalDev->offset = ParmValue;
++     }
++    else
++      HalDev->offset = 0;
++
++   error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszDebug, &ParmValue);
++   if (!error_code) HalDev->debug = ParmValue;
++
++   return (EC_NO_ERRORS);
++  }
++#endif /* +RC 3.02 */
++
++#ifdef _CPHAL_CPMAC /* +RC 3.02 */
++static void StatsInit(HAL_DEVICE *HalDev)                             /* +() RC3.02 */
++  {
++   /* even though these statistics may be for multiple channels and
++      queues, i need only configure the pointer to the beginning
++      of the array, and I can index from there if necessary */
++
++#ifdef _CPHAL_AAL5
++   StatsTable0[0].StatPtr  = &HalDev->Stats.CrcErrors[0];
++   StatsTable0[1].StatPtr  = &HalDev->Stats.LenErrors[0];
++   StatsTable0[2].StatPtr  = &HalDev->Stats.AbortErrors[0];
++   StatsTable0[3].StatPtr  = &HalDev->Stats.StarvErrors[0];
++
++   StatsTable1[0].StatPtr  = &HalDev->Stats.DmaLenErrors[0];
++   StatsTable1[1].StatPtr  = &HalDev->Stats.TxMisQCnt[0][0];
++   StatsTable1[2].StatPtr  = &HalDev->Stats.RxMisQCnt[0];
++   StatsTable1[3].StatPtr  = &HalDev->Stats.TxEOQCnt[0][0];
++   StatsTable1[4].StatPtr  = &HalDev->Stats.RxEOQCnt[0];
++   StatsTable1[5].StatPtr  = &HalDev->Stats.RxPacketsServiced[0];
++   StatsTable1[6].StatPtr  = &HalDev->Stats.TxPacketsServiced[0][0];
++   StatsTable1[7].StatPtr  = &HalDev->Stats.RxMaxServiced;
++   StatsTable1[8].StatPtr  = &HalDev->Stats.TxMaxServiced[0][0];
++   StatsTable1[9].StatPtr  = &HalDev->Stats.RxTotal;
++   StatsTable1[10].StatPtr = &HalDev->Stats.TxTotal;
++#endif
++
++#if (defined(_CPHAL_AAL5) || defined(_CPHAL_CPMAC))
++   StatsTable2[0].StatPtr  = (bit32u *)&HalDev->RcbPool[0];
++   StatsTable2[1].StatPtr  = &HalDev->RxActQueueCount[0];
++   StatsTable2[2].StatPtr  = (bit32u *)&HalDev->RxActQueueHead[0];
++   StatsTable2[3].StatPtr  = (bit32u *)&HalDev->RxActQueueTail[0];
++   StatsTable2[4].StatPtr  = &HalDev->RxActive[0];
++   StatsTable2[5].StatPtr  = (bit32u *)&HalDev->RcbStart[0];
++   StatsTable2[6].StatPtr  = &HalDev->RxTeardownPending[0];
++   StatsTable2[7].StatPtr  = (bit32u *)&HalDev->TcbPool[0][0];
++   StatsTable2[8].StatPtr  = &HalDev->TxActQueueCount[0][0];
++   StatsTable2[9].StatPtr  = (bit32u *)&HalDev->TxActQueueHead[0][0];
++   StatsTable2[10].StatPtr = (bit32u *)&HalDev->TxActQueueTail[0][0];
++   StatsTable2[11].StatPtr = &HalDev->TxActive[0][0];
++   StatsTable2[12].StatPtr = (bit32u *)&HalDev->TcbStart[0][0];
++   StatsTable2[13].StatPtr = &HalDev->TxTeardownPending[0];
++
++   StatsTable3[0].StatPtr  = &HalDev->ChData[0].RxBufSize;
++   StatsTable3[1].StatPtr  = &HalDev->ChData[0].RxBufferOffset;
++   StatsTable3[2].StatPtr  = &HalDev->ChData[0].RxNumBuffers;
++   StatsTable3[3].StatPtr  = &HalDev->ChData[0].RxServiceMax;
++   StatsTable3[4].StatPtr  = &HalDev->ChData[0].TxNumBuffers;
++   StatsTable3[5].StatPtr  = &HalDev->ChData[0].TxNumQueues;
++   StatsTable3[6].StatPtr  = &HalDev->ChData[0].TxServiceMax;
++#ifdef _CPHAL_AAL5
++   StatsTable3[7].StatPtr  = &HalDev->ChData[0].CpcsUU;
++   StatsTable3[8].StatPtr  = &HalDev->ChData[0].Gfc;
++   StatsTable3[9].StatPtr  = &HalDev->ChData[0].Clp;
++   StatsTable3[10].StatPtr = &HalDev->ChData[0].Pti;
++   StatsTable3[11].StatPtr = &HalDev->ChData[0].DaMask;
++   StatsTable3[12].StatPtr = &HalDev->ChData[0].Priority;
++   StatsTable3[13].StatPtr = &HalDev->ChData[0].PktType;
++   StatsTable3[14].StatPtr = &HalDev->ChData[0].Vci;
++   StatsTable3[15].StatPtr = &HalDev->ChData[0].Vpi;
++   StatsTable3[16].StatPtr = &HalDev->ChData[0].TxVc_CellRate;
++   StatsTable3[17].StatPtr = &HalDev->ChData[0].TxVc_QosType;
++   StatsTable3[18].StatPtr = &HalDev->ChData[0].TxVc_Mbs;
++   StatsTable3[19].StatPtr = &HalDev->ChData[0].TxVc_Pcr;
++#endif
++#endif
++
++   StatsTable4[0].StatPtr  = &HalDev->dev_base;
++   StatsTable4[1].StatPtr  = &HalDev->offset;
++   StatsTable4[2].StatPtr  = &HalDev->interrupt;
++   StatsTable4[3].StatPtr  = &HalDev->debug;
++   StatsTable4[4].StatPtr  = &HalDev->Inst;
++  }
++#endif /* +RC 3.02 */
++
++#ifndef _CPHAL_CPSAR /* +RC 3.02 */
++#ifndef _CPHAL_AAL2 /* +RC 3.02 */
++/*
++ *  Returns statistics information.
++ *
++ *  @param  HalDev   CPHAL module instance. (set by xxxInitModule())
++ *
++ *  @return 0
++ */
++static int StatsGet(HAL_DEVICE *HalDev, void **StatPtr, int Index, int Ch, int Queue)
++  {
++   int Size;
++   bit32u *AddrPtr;
++   char *DataPtr;
++   STATS_TABLE *StatsTable;
++   int i, NumberOfStats;
++
++#ifdef __CPHAL_DEBUG
++   if (DBG(0))
++     {
++      dbgPrintf("[cpcommon]StatsGet(HalDev:%08x, StatPtr:%08x)\n",
++                (bit32u)HalDev, (bit32u)StatPtr);
++      osfuncSioFlush();
++     }
++#endif
++
++   StatsTable = StatsDb[Index].StatTable;
++   NumberOfStats = StatsDb[Index].NumberOfStats;
++
++   Size = sizeof(bit32u)*((NumberOfStats*2)+1);
++   Size += (NumberOfStats*11);
++   *StatPtr = (bit32u *)HalDev->OsFunc->Malloc(Size);
++
++   AddrPtr = (bit32u *) *StatPtr;
++   DataPtr = (char *)AddrPtr;
++   DataPtr += sizeof(bit32u)*((NumberOfStats*2)+1);
++
++   for (i=0; i<NumberOfStats; i++)
++     {
++      *AddrPtr++ = (bit32u)StatsTable[i].StatName;
++      *AddrPtr++ = (bit32u)DataPtr;
++      if (&StatsTable[i].StatPtr[Ch] != 0)
++        {
++         switch(StatsTable[i].DataType)
++           {
++            case 0:
++              HalDev->OsFunc->Sprintf(DataPtr, "%d", (bit32u *)StatsTable[i].StatPtr[Ch]);
++              break;
++            case 1:
++              HalDev->OsFunc->Sprintf(DataPtr, "0x%x", (bit32u *)StatsTable[i].StatPtr[Ch]);
++              break;
++            case 2:
++              HalDev->OsFunc->Sprintf(DataPtr, "%d", *((bit32u *)StatsTable[i].StatPtr + (Ch * (sizeof(CHANNEL_INFO)/4))));
++              break;
++            case 3:
++              HalDev->OsFunc->Sprintf(DataPtr, "%d", *((bit32u *)StatsTable[i].StatPtr + (Ch*MAX_QUEUE)+Queue));
++              break;
++            case 4:
++              HalDev->OsFunc->Sprintf(DataPtr, "0x%x", *((bit32u *)StatsTable[i].StatPtr + (Ch*MAX_QUEUE)+Queue));
++              break;
++            default:
++              /* invalid data type, due to CPHAL programming error */
++              break;
++           }
++        }
++       else
++        {
++         /* invalid statistics pointer, probably was not initialized */
++        }
++      DataPtr += HalDev->OsFunc->Strlen(DataPtr) + 1;
++     }
++
++   *AddrPtr = (bit32u) 0;
++
++   return (EC_NO_ERRORS);
++  }
++#endif /* +RC 3.02 */
++#endif /* +RC 3.02 */
++
++#ifdef _CPHAL_CPMAC
++static void gpioFunctional(int base, int bit)
++  {                                                                  /*+RC3.02*/
++  bit32u GpioEnr = base + 0xC;
++  /*  To make functional, set to zero  */
++  *(volatile bit32u *)(GpioEnr) &= ~(1 << bit);                      /*+RC3.02*/
++  }                                                                  /*+RC3.02*/
++
++
++/*+RC3.02*/
++/* Common function, Checks to see if GPIO should be in functional mode */
++static void gpioCheck(HAL_DEVICE *HalDev, void *moduleDeviceInfo)
++  {                                                                  /*+RC3.02*/
++  int rc;
++  void *DeviceInfo;
++  char *pszMuxBits;
++  char pszMuxBit[20];
++  char *pszTmp;
++  char szMuxBit[20];
++  char *ptr;
++  int base;
++  int reset_bit;
++  int bit;
++  OS_FUNCTIONS *OsFunc = HalDev->OsFunc;
++
++  rc = OsFunc->DeviceFindParmValue(moduleDeviceInfo, "gpio_mux",&pszTmp);
++  if(rc) return;
++  /*  gpio entry found, get GPIO register info and make functional  */
++
++  /* temp copy until FinParmValue fixed */
++  ptr = &szMuxBit[0];
++  while ((*ptr++ = *pszTmp++));
++
++  pszMuxBits = &szMuxBit[0];
++
++  rc = OsFunc->DeviceFindInfo(0,"gpio",&DeviceInfo);
++  if(rc) return;
++
++  rc = OsFunc->DeviceFindParmUint(DeviceInfo, "base",&base);
++  if(rc) return;
++
++  rc = OsFunc->DeviceFindParmUint(DeviceInfo, "reset_bit",&reset_bit);
++  if(rc) return;
++
++  /* If GPIO still in reset, then exit  */
++  if((VOLATILE32(HalDev->ResetBase) & (1 << reset_bit)) == 0)
++    return;
++  /*  format for gpio_mux is  gpio_mux = <int>;<int>;<int>...*/
++  while (*pszMuxBits)
++    {
++    pszTmp = &pszMuxBit[0];
++    if(*pszMuxBits == ';') pszMuxBits++;
++    while ((*pszMuxBits != ';') && (*pszMuxBits != '\0'))
++      {
++      osfuncSioFlush();
++      /*If value not a number, skip */
++      if((*pszMuxBits < '0') || (*pszMuxBits > '9'))
++        pszMuxBits++;
++      else
++        *pszTmp++ = *pszMuxBits++;
++      }
++    *pszTmp = '\0';
++    bit = OsFunc->Strtoul(pszMuxBit, &pszTmp, 10);
++    gpioFunctional(base, bit);
++    resetWait(HalDev);  /* not sure if this is needed */
++    }
++  }                                                                  /*+RC3.02*/
++#endif  /* CPMAC  */
++
++#ifdef _CPHAL_AAL5
++const char hcSarFrequency[] = "SarFreq";
++#endif
++
++#endif  /* _INC  */
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/cpcommon_cpmac.h linux-2.4.30/drivers/net/avalanche_cpmac/cpcommon_cpmac.h
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/cpcommon_cpmac.h     1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/cpcommon_cpmac.h  2005-04-15 05:10:40.000000000 +0200
+@@ -0,0 +1,79 @@
++#ifndef _INC_CPCOMMON_H
++#define _INC_CPCOMMON_H
++
++#define VOLATILE32(addr)  (*(volatile bit32u *)(addr))
++#ifndef dbgPrintf
++#define dbgPrintf HalDev->OsFunc->Printf
++#endif
++
++#define ChannelUpdate(Field) if(HalChn->Field != 0xFFFFFFFF) HalDev->ChData[Ch].Field = HalChn->Field
++
++#define DBG(level)  (HalDev->debug & (1<<(level)))
++/*
++#define DBG0()      DBG(0)
++#define DBG1()      DBG(1)
++#define DBG2()      DBG(2)
++#define DBG3()      DBG(3)
++#define DBG4()      DBG(4)
++#define DBG5()      DBG(5)
++#define DBG6()      DBG(6)
++#define DBG7()      DBG(7)
++*/
++
++/*
++ *  List of defined actions for use with Control().
++ */
++typedef enum 
++  {
++   enGET=0,     /**< Get the value associated with a key */
++   enSET,       /**< Set the value associates with a key */
++   enCLEAR,     /**<Clear the value */ 
++   enNULL       /**< No data action, used to initiate a service or send a message */
++  }ACTION;
++
++/*
++ *  Enumerated hardware states.
++ */
++typedef enum
++  {
++   enConnected=1, enDevFound, enInitialized, enOpened
++  }DEVICE_STATE;
++
++typedef enum 
++  {
++   enCommonStart=0,
++   /* General  */
++   enOff, enOn, enDebug, 
++   /* Module General */
++   enCpuFreq, 
++   enStatus,
++   enCommonEnd
++   }COMMON_KEY;
++
++typedef struct
++  {
++   const char  *strKey;
++   int  enKey;
++  }CONTROL_KEY;
++
++typedef struct
++  {
++   char *StatName;
++   unsigned int *StatPtr;
++   int DataType; /* 0: int, 1: hex int, 2:channel data */
++  }STATS_TABLE;
++
++typedef struct
++  {
++   int NumberOfStats;
++   STATS_TABLE *StatTable;
++  }STATS_DB;
++
++#define osfuncSioFlush()    HalDev->OsFunc->Control(HalDev->OsDev,"SioFlush",pszNULL,0)
++#define osfuncSleep(Ticks)  HalDev->OsFunc->Control(HalDev->OsDev,pszSleep,pszNULL,Ticks)
++#define osfuncStateChange() HalDev->OsFunc->Control(HalDev->OsDev,pszStateChange,pszNULL,0)
++
++#define CHANNEL_NAMES {"Ch0","Ch1","Ch2","Ch3","Ch4","Ch5","Ch6","Ch7","Ch8","Ch9","Ch10","Ch11","Ch12","Ch13","Ch14","Ch15"}
++
++#endif
++
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/cpmac.c linux-2.4.30/drivers/net/avalanche_cpmac/cpmac.c
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/cpmac.c      1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/cpmac.c   2005-07-08 22:20:26.953335844 +0200
+@@ -0,0 +1,2507 @@
++/******************************************************************************
++ * FILE PURPOSE:    CPMAC Linux Network Device Driver Source
++ ******************************************************************************
++ * FILE NAME:       cpmac.c
++ *
++ * DESCRIPTION:     CPMAC Network Device Driver Source
++ *
++ * REVISION HISTORY:
++ *
++ * Date           Description                               Author
++ *-----------------------------------------------------------------------------
++ * 27 Nov 2002    Initial Creation                          Suraj S Iyer  
++ * 09 Jun 2003    Updates for GA                            Suraj S Iyer
++ * 30 Sep 2003    Updates for LED, Reset stats              Suraj S Iyer
++ * 
++ * (C) Copyright 2003, Texas Instruments, Inc
++ *******************************************************************************/
++#include <linux/kernel.h> 
++#include <linux/module.h> 
++#include <linux/init.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/delay.h>     
++#include <linux/spinlock.h>
++#include <linux/proc_fs.h>
++#include <linux/ioport.h>
++#include <asm/io.h>
++
++#include <linux/skbuff.h>
++
++#include <asm/mips-boards/prom.h>
++#include <linux/string.h>
++#include <asm/uaccess.h>
++#include <linux/config.h>
++
++#include <asm/ar7/avalanche_misc.h>
++#include <asm/ar7/sangam_clk_cntl.h>
++#include <asm/ar7/if_port.h>
++extern void build_psp_config(void);
++extern void psp_config_cleanup(void);
++
++#include "cpmacHalLx.h"
++#include "cpmac.h"
++
++static struct net_device *last_cpmac_device = NULL;
++static int    cpmac_devices_installed = 0;
++
++void xdump( u_char*  cp, int  length, char*  prefix );
++
++unsigned int  cpmac_cpu_freq = 0;
++
++char cpmac_version[] = "1.5";
++
++char l3_align_array[]            = {0x02, 0x01, 0x00, 0x03};
++#define L3_ALIGN(i)                l3_align_array[i]
++
++char add_for_4byte_align[]       = {0x04, 0x03, 0x02, 0x05};
++#define ADD_FOR_4BYTE_ALIGN(i)     add_for_4byte_align[i]
++
++
++#define TPID                       0x8100
++#define IS_802_1Q_FRAME(byte_ptr)  (*(unsigned short*)byte_ptr == TPID)
++#define TPID_START_OFFSET          12
++#define TCI_START_OFFSET           14
++#define TCI_LENGTH                 2
++#define TPID_LENGTH                2
++#define TPID_END_OFFSET            (TPID_START_OFFSET + TPID_LENGTH)
++#define TCI_END_OFFSET             (TCI_START_OFFSET  + TCI_LENGTH)
++#define IS_VALID_VLAN_ID(byte_ptr) ((*(unsigned short*)byte_ptr) && 0xfff != 0)
++#define MAX_CLASSES                8
++#define MAX_USER_PRIORITY          8
++#define CONTROL_802_1Q_SIZE        (TCI_LENGTH + TPID_LENGTH)
++
++unsigned char user_priority_to_traffic_class_map[MAX_CLASSES][MAX_USER_PRIORITY] = 
++{ 
++  {0, 0, 0, 1, 1, 1, 1, 2}, 
++  {0, 0, 0, 0, 0, 0, 0, 0}, 
++  {0, 0, 0, 0, 0, 0, 0, 1}, 
++  {0, 0, 0, 1, 1, 2, 2, 3}, 
++  {0, 1, 1, 2, 2, 3, 3, 4}, 
++  {0, 1, 1, 2, 3, 4, 4, 5}, 
++  {0, 1, 2, 3, 4, 5, 5, 6}, 
++  {0, 1, 2, 3, 4, 5, 6, 7}
++};
++
++#define GET_802_1P_CHAN(x,y) user_priority_to_traffic_class_map[x][(y & 0xe0)]
++
++#if defined(CONFIG_MIPS_SEAD2)
++unsigned long temp_base_address[2] = {0xa8610000, 0xa8612800};
++unsigned long temp_reset_value[2] = { 1<< 17,1<<21};
++#define RESET_REG_PRCR   (*(volatile unsigned int *)((0xa8611600 + 0x0)))
++#define VERSION(base)   (*(volatile unsigned int *)(((base)|0xa0000000) + 0x0))
++#endif
++
++MODULE_AUTHOR("Maintainer: Suraj S Iyer <ssiyer@ti.com>");
++MODULE_DESCRIPTION("Driver for TI CPMAC");
++
++static int cfg_link_speed = 0;
++MODULE_PARM(cfg_link_speed, "i");
++MODULE_PARM_DESC(cfg_link_speed, "Fixed speed of the Link: <100/10>");
++
++static char *cfg_link_mode = NULL;
++MODULE_PARM(cfg_link_mode, "1-3s");
++MODULE_PARM_DESC(cfg_link_mode, "Fixed mode of the Link: <fd/hd>");
++
++int cpmac_debug_mode = 0;
++MODULE_PARM(debug_mode, "i");
++MODULE_PARM_DESC(debug_mode, "Turn on the debug info: <0/1>. Default is 0 (off)");
++
++#define dbgPrint if (cpmac_debug_mode) printk
++#define errPrint printk
++
++static int g_cfg_start_link_params = CFG_START_LINK_SPEED;
++static int g_init_enable_flag      = 0;
++static int cfg_start_link_speed;
++static int cpmac_max_frame_size;
++
++static struct net_device *g_dev_array[2];
++static struct proc_dir_entry *gp_stats_file = NULL;
++
++//-----------------------------------------------------------------------------
++// Statistics related private functions.
++//----------------------------------------------------------------------------- 
++static int  cpmac_p_update_statistics(struct net_device *p_dev, char *buf, int limit, int *len);
++static int  cpmac_p_read_rfc2665_stats(char *buf, char **start, off_t offset, int count, int *eof, void *data);
++static int  cpmac_p_read_link(char *buf, char **start, off_t offset, int count, int *eof, void *data);
++static int  cpmac_p_read_stats(char* buf, char **start, off_t offset, int count, int *eof, void *data);
++static int  cpmac_p_write_stats (struct file *fp, const char * buf, unsigned long count, void * data);
++static int  cpmac_p_reset_statistics (struct net_device *p_dev);
++static int  cpmac_p_get_version(char *buf, char **start, off_t offset, int count, int *eof, void *data);
++
++static int  cpmac_p_detect_manual_cfg(int, char*, int);
++static int  cpmac_p_process_status_ind(CPMAC_PRIVATE_INFO_T *p_cpmac_priv);
++
++//-----------------------------------------------------------------------------
++// Timer related private functions.
++//-----------------------------------------------------------------------------
++static int  cpmac_p_timer_init(CPMAC_PRIVATE_INFO_T *p_cpmac_priv);
++// static int  cpmac_timer_cleanup(CPMAC_PRIVATE_INFO_T *p_cpmac_priv);
++static void cpmac_p_tick_timer_expiry(unsigned long p_cb_param);
++inline static int cpmac_p_start_timer(struct timer_list *p_timer, unsigned int delay_ticks);
++static int  cpmac_p_stop_timer(struct timer_list *p_timer);
++
++//------------------------------------------------------------------------------
++// Device configuration and setup related private functions.
++//------------------------------------------------------------------------------
++static int cpmac_p_probe_and_setup_device(CPMAC_PRIVATE_INFO_T *p_cpmac_priv, unsigned long *p_dev_flags);
++static int cpmac_p_setup_driver_params(CPMAC_PRIVATE_INFO_T *p_cpmac_priv);
++inline static int cpmac_p_rx_buf_setup(CPMAC_RX_CHAN_INFO_T *p_rx_chan);
++
++//-----------------------------------------------------------------------------
++// Net device related private functions.
++//-----------------------------------------------------------------------------
++static int  cpmac_dev_init(struct net_device *p_dev);
++static int  cpmac_dev_open( struct net_device *dev );
++static int  cpmac_dev_close(struct net_device *p_dev);
++static void cpmac_dev_mcast_set(struct net_device *p_dev);
++static int cpmac_dev_set_mac_addr(struct net_device *p_dev,void * addr);
++static int  cpmac_dev_tx( struct sk_buff *skb, struct net_device *p_dev);
++static struct net_device_stats *cpmac_dev_get_net_stats (struct net_device *dev);
++
++static int cpmac_p_dev_enable( struct net_device *p_dev);
++
++
++
++/* Max. Reserved headroom in front of each packet so that the headers can be added to
++ * a packet. Worst case scenario would be PPPoE + 2684 LLC Encapsulation + Ethernet
++ * header. */
++#define MAX_RESERVED_HEADROOM       20
++
++/* This is the MAX size of the static buffer for pure data. */
++#define MAX_SIZE_STATIC_BUFFER      1600
++
++typedef struct DRIVER_BUFFER
++{
++      /* Pointer to the allocated data buffer. This is the static data buffer 
++     * allocated for the TI-Cache. 60 bytes out of the below buffer are required
++     * by the SKB shared info. We always reserve at least MAX_RESERVED_HEADROOM bytes 
++     * so that the packets always have sufficient headroom. */
++      char                                    ptr_buffer[MAX_SIZE_STATIC_BUFFER + MAX_RESERVED_HEADROOM + 60];
++
++      /* List of the driver buffers. */
++      struct DRIVER_BUFFER*   ptr_next;
++}DRIVER_BUFFER;
++
++typedef struct DRIVER_BUFFER_MCB
++{
++      /* List of the driver buffers. */
++      DRIVER_BUFFER*  ptr_available_driver_buffers;
++
++    /* The number of available buffers. */
++    int                     num_available_buffers;
++}DRIVER_BUFFER_MCB;
++
++DRIVER_BUFFER_MCB     driver_mcb;
++int                 hybrid_mode = 0;
++
++static union {
++      struct sk_buff_head     list;
++      char                    pad[SMP_CACHE_BYTES];
++} skb_head_pool[NR_CPUS];
++
++/**************************************************************************
++ * FUNCTION NAME : ti_release_skb
++ **************************************************************************
++ * DESCRIPTION   :
++ *  This function is called from the ti_alloc_skb when there were no more
++ *  data buffers available. The allocated SKB had to released back to the 
++ *  data pool. The reason why this function was moved from the fast path 
++ *  below was because '__skb_queue_head' is an inline function which adds
++ *  a large code chunk on the fast path.
++ *
++ * NOTES         :
++ *  This function is called with interrupts disabled. 
++ **************************************************************************/
++static void ti_release_skb (struct sk_buff_head* list, struct sk_buff* skb)
++{
++    __skb_queue_head(list, skb);
++    return;
++}
++
++/**************************************************************************
++ * FUNCTION NAME : ti_alloc_skb
++ **************************************************************************
++ * DESCRIPTION   :
++ *  The function is called to allocate memory from the static allocated 
++ *  TI-Cached memory pool.
++ *
++ * RETURNS       :
++ *      Allocated static memory buffer - Success
++ *      NULL                           - Error.
++ **************************************************************************/
++struct sk_buff *ti_alloc_skb(unsigned int size,int gfp_mask)
++{
++    register struct sk_buff*    skb;
++    unsigned long               flags;
++      struct sk_buff_head*        list;
++      DRIVER_BUFFER*              ptr_node = NULL;
++
++    /* Critical Section Begin: Lock out interrupts. */
++    local_irq_save(flags);
++
++    /* Get the SKB Pool list associated with the processor and dequeue the head. */
++    list = &skb_head_pool[smp_processor_id()].list;
++    skb = __skb_dequeue(list);
++
++    /* Align the data size. */
++    size = SKB_DATA_ALIGN(size);
++
++    /* Did we get one. */
++    if (skb != NULL)
++    {
++        /* YES. Now get a data block from the head of statically allocated block. */
++        ptr_node = driver_mcb.ptr_available_driver_buffers;
++          if (ptr_node != NULL)
++        {
++            /* YES. Got a data block. Advance the free list pointer to the next available buffer. */
++              driver_mcb.ptr_available_driver_buffers = ptr_node->ptr_next;
++            ptr_node->ptr_next = NULL;
++
++            /* Decrement the number of available data buffers. */
++            driver_mcb.num_available_buffers = driver_mcb.num_available_buffers - 1;
++        }
++        else
++        {
++          /* NO. Was unable to get a data block. So put the SKB back on the free list. 
++           * This is slow path. */
++#ifdef DEBUG_SKB 
++           printk ("DEBUG: No Buffer memory available: Number of free buffer:%d.\n",
++                   driver_mcb.num_available_buffers);
++#endif
++           ti_release_skb (list, skb);
++        }
++    }
++
++    /* Critical Section End: Unlock interrupts. */
++    local_irq_restore(flags);
++
++    /* Did we get an SKB and data buffer. Proceed only if we were succesful in getting both else drop */
++    if (skb != NULL && ptr_node != NULL)
++    {
++              /* XXX: does not include slab overhead */ 
++        skb->truesize = size + sizeof(struct sk_buff);
++ 
++        /* Load the data pointers. */
++      skb->head = ptr_node->ptr_buffer;
++        skb->data = ptr_node->ptr_buffer + MAX_RESERVED_HEADROOM;
++          skb->tail = ptr_node->ptr_buffer + MAX_RESERVED_HEADROOM;
++        skb->end  = ptr_node->ptr_buffer + size + MAX_RESERVED_HEADROOM;
++
++          /* Set up other state */
++      skb->len    = 0;
++      skb->cloned = 0;
++        skb->data_len = 0;
++    
++        /* Mark the SKB indicating that the SKB is from the TI cache. */
++        skb->cb[45] = 1;
++
++      atomic_set(&skb->users, 1); 
++      atomic_set(&(skb_shinfo(skb)->dataref), 1);
++        skb_shinfo(skb)->nr_frags = 0;
++          skb_shinfo(skb)->frag_list = NULL;
++        return skb;
++    }
++    else
++    {
++        /* Control comes here only when there is no statically allocated data buffers
++         * available. This case is handled using the mode selected
++         *
++         * 1. Hybrid Mode.
++         *  In that case lets jump to the old allocation code. This way we
++         *  can allocate a small number of data buffers upfront and the rest will hit
++         *  this portion of the code, which is slow path. Note the number of hits here
++         *  should be kept as low as possible to satisfy performance requirements. 
++         *
++         * 2. Pure Static Mode.
++         *  Return NULL the user should have tuned the number of static buffers for
++         *  worst case scenario. So return NULL and let the drivers handle the error. */
++        if (hybrid_mode == 1)
++        {
++            /* Hybrid Mode: Old allocation. */
++            return dev_alloc_skb(size);
++        }
++        else
++        {
++            /* Pure Static Mode: No buffers available. */
++            return NULL;
++        }
++    }
++}
++
++/**************************************************************************
++ * FUNCTION NAME : ti_skb_release_fragment
++ **************************************************************************
++ * DESCRIPTION   :
++ *  This function is called to release fragmented packets. This is NOT in 
++ *  the fast path and this function requires some work. 
++ **************************************************************************/
++static void ti_skb_release_fragment(struct sk_buff *skb)
++{
++    if (skb_shinfo(skb)->nr_frags)
++    {
++        /* PANKAJ TODO: This portion has not been tested. */
++          int i;
++#ifdef DEBUG_SKB 
++        printk ("DEBUG: Releasing fragments in TI-Cached code.\n");
++#endif
++              for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
++                  printk ("DEBUG: Fragmented Page = 0x%p.\n", skb_shinfo(skb)->frags[i].page);
++    }
++
++    /* Check if there were any fragments present and if so clean all the SKB's. 
++     * This is required to recursivly clean the SKB's. */
++      if (skb_shinfo(skb)->frag_list)
++          skb_drop_fraglist(skb);
++
++    return;
++}
++
++/**************************************************************************
++ * FUNCTION NAME : ti_skb_release_data
++ **************************************************************************
++ * DESCRIPTION   :
++ *  The function is called to release the SKB back into the TI-Cached static
++ *  memory pool. 
++ **************************************************************************/
++static void ti_skb_release_data(struct sk_buff *skb)
++{
++    DRIVER_BUFFER*    ptr_node;
++    unsigned long   flags;
++
++    /* The SKB data can be cleaned only if the packet has not been cloned and we
++     * are the only one holding a reference to the data. */
++      if (!skb->cloned || atomic_dec_and_test(&(skb_shinfo(skb)->dataref)))
++    {
++        /* Are there any fragments associated with the SKB ?*/
++              if ((skb_shinfo(skb)->nr_frags != 0) || (skb_shinfo(skb)->frag_list != NULL))
++        {
++            /* Slow Path: Try and clean up the fragments. */
++            ti_skb_release_fragment (skb);
++        }
++
++        /* Cleanup the SKB data memory. This is fast path. */
++        ptr_node = (DRIVER_BUFFER *)skb->head;
++
++        /* Critical Section: Lock out interrupts. */
++        local_irq_save(flags);
++
++        /* Add the data buffer to the list of available buffers. */
++        ptr_node->ptr_next = driver_mcb.ptr_available_driver_buffers;
++          driver_mcb.ptr_available_driver_buffers = ptr_node;
++
++        /* Increment the number of available data buffers. */
++        driver_mcb.num_available_buffers = driver_mcb.num_available_buffers + 1;
++
++        /* Criticial Section: Unlock interrupts. */
++        local_irq_restore(flags);
++      }
++    return;
++}
++
++
++
++
++static unsigned char str2hexnum(unsigned char c)
++{
++        if(c >= '0' && c <= '9')
++                return c - '0';
++        if(c >= 'a' && c <= 'f')
++                return c - 'a' + 10;
++        if(c >= 'A' && c <= 'F')
++                return c - 'A' + 10;
++        return 0; 
++}
++
++static void str2eaddr(unsigned char *ea, unsigned char *str)
++{
++    int i;
++    unsigned char num;
++    for(i = 0; i < 6; i++) {
++        if((*str == '.') || (*str == ':'))
++            str++;
++        num = str2hexnum(*str++) << 4;
++        num |= (str2hexnum(*str++));
++        ea[i] = num;
++    }
++}
++
++//-----------------------------------------------------------------------------
++// Statistics related private functions.
++//-----------------------------------------------------------------------------
++static int cpmac_p_update_statistics(struct net_device *p_dev, char *buf, int limit, int *p_len)
++{
++    int                 ret_val   = -1;
++    unsigned long rx_hal_errors   = 0;
++    unsigned long rx_hal_discards = 0;
++    unsigned long tx_hal_errors   = 0;
++    unsigned long ifOutDiscards   = 0;
++    unsigned long ifInDiscards    = 0;
++    unsigned long ifOutErrors     = 0;
++    unsigned long ifInErrors      = 0;
++
++    CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv;
++    CPMAC_DRV_HAL_INFO_T *p_drv_hal    = p_cpmac_priv->drv_hal;
++    CPMAC_DEVICE_MIB_T   *p_device_mib = p_cpmac_priv->device_mib;
++    CPMAC_DRV_STATS_T    *p_stats      = p_cpmac_priv->stats;
++    CPMAC_DEVICE_MIB_T   local_mib;
++    CPMAC_DEVICE_MIB_T   *p_local_mib  = &local_mib;
++
++    struct net_device_stats *p_net_dev_stats = &p_cpmac_priv->net_dev_stats;
++
++    int                 len      = 0;
++    int  dev_mib_elem_count      = 0;
++
++    /* do not access the hardware if it is in the reset state. */
++    if(!test_bit(0, &p_cpmac_priv->set_to_close))
++    {
++        if(p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "StatsDump", "Get",
++                                       p_local_mib) != 0)
++        {
++            errPrint("The stats dump for %s is failing.\n", p_dev->name);
++            return(ret_val);
++        }
++
++        p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "StatsClear", "Set", NULL);
++
++        dev_mib_elem_count = sizeof(CPMAC_DEVICE_MIB_T)/sizeof(unsigned long);
++
++        /* Update the history of the stats. This takes care of any reset of the 
++         * device and stats that might have taken place during the life time of 
++         * the driver. 
++         */
++        while(dev_mib_elem_count--)
++        {
++            *((unsigned long*) p_device_mib + dev_mib_elem_count) += 
++            *((unsigned long*) p_local_mib  + dev_mib_elem_count); 
++        }
++    }
++
++    /* RFC2665, section 3.2.7, page 9 */
++    rx_hal_errors          = p_device_mib->ifInFragments       +
++                           p_device_mib->ifInCRCErrors       +
++                           p_device_mib->ifInAlignCodeErrors +
++                           p_device_mib->ifInJabberFrames;
++
++    /* RFC2233 */
++    rx_hal_discards        = p_device_mib->ifRxDMAOverruns;
++
++    /* RFC2665, section 3.2.7, page 9 */
++    tx_hal_errors          = p_device_mib->ifExcessiveCollisionFrames +
++                             p_device_mib->ifLateCollisions           +
++                             p_device_mib->ifCarrierSenseErrors       +
++                             p_device_mib->ifOutUnderrun;
++
++    /* if not set, the short frames (< 64 bytes) are considered as errors */
++    if(!p_cpmac_priv->flags & IFF_PRIV_SHORT_FRAMES)
++        rx_hal_errors += p_device_mib->ifInUndersizedFrames;
++
++    /* if not set, the long frames ( > 1518) are considered as errors 
++     * RFC2665, section 3.2.7, page 9. */
++    if(!p_cpmac_priv->flags & IFF_PRIV_JUMBO_FRAMES)
++        rx_hal_errors += p_device_mib->ifInOversizedFrames;
++
++    /* if not in promiscous, then non addr matching frames are discarded */
++    /* CPMAC 2.0 Manual Section 2.8.1.14 */
++    if(!p_dev->flags & IFF_PROMISC)
++    {
++        ifInDiscards  +=  p_device_mib->ifInFilteredFrames;
++    }
++
++     /* total rx discards = hal discards + driver discards. */
++    ifInDiscards  = rx_hal_discards + p_net_dev_stats->rx_dropped;
++    ifInErrors    = rx_hal_errors;
++
++    ifOutErrors   = tx_hal_errors;
++    ifOutDiscards = p_net_dev_stats->tx_dropped;
++
++    /* Let us update the net device stats struct. To be updated in the later releases.*/
++    p_cpmac_priv->net_dev_stats.rx_errors  = ifInErrors;
++    p_cpmac_priv->net_dev_stats.collisions = p_device_mib->ifCollisionFrames;
++
++    if(buf == NULL || limit == 0)
++    {
++        return(0);
++    }
++
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %ld\n", "ifSpeed",                                 (long)p_cpmac_priv->link_speed);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "dot3StatsDuplexStatus",                   (long)p_cpmac_priv->link_mode);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifAdminStatus",                           (long)(p_dev->flags & IFF_UP ? 1:2));
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifOperStatus",                            (long)(((p_dev->flags & IFF_UP) && netif_carrier_ok(p_dev)) ? 1:2));
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifLastChange",                            p_stats->start_tick);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifInDiscards",                            ifInDiscards);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifInErrors",                              ifInErrors);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifOutDiscards",                           ifOutDiscards);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifOutErrors",                             ifOutErrors);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifInGoodFrames",                          p_device_mib->ifInGoodFrames);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifInBroadcasts",                          p_device_mib->ifInBroadcasts);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifInMulticasts",                          p_device_mib->ifInMulticasts);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifInPauseFrames",                         p_device_mib->ifInPauseFrames);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifInCRCErrors",                           p_device_mib->ifInCRCErrors);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifInAlignCodeErrors",                     p_device_mib->ifInAlignCodeErrors);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifInOversizedFrames",                     p_device_mib->ifInOversizedFrames);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifInJabberFrames",                        p_device_mib->ifInJabberFrames);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifInUndersizedFrames",                    p_device_mib->ifInUndersizedFrames);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifInFragments",                           p_device_mib->ifInFragments);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifInFilteredFrames",                      p_device_mib->ifInFilteredFrames);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifInQosFilteredFrames",                   p_device_mib->ifInQosFilteredFrames);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifInOctets",                              p_device_mib->ifInOctets);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifOutGoodFrames",                         p_device_mib->ifOutGoodFrames);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifOutBroadcasts",                         p_device_mib->ifOutBroadcasts);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifOutMulticasts",                         p_device_mib->ifOutMulticasts);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifOutPauseFrames",                        p_device_mib->ifOutPauseFrames);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifDeferredTransmissions",                 p_device_mib->ifDeferredTransmissions);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifCollisionFrames",                       p_device_mib->ifCollisionFrames);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifSingleCollisionFrames",                 p_device_mib->ifSingleCollisionFrames);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifMultipleCollisionFrames",               p_device_mib->ifMultipleCollisionFrames);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifExcessiveCollisionFrames",              p_device_mib->ifExcessiveCollisionFrames);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifLateCollisions",                        p_device_mib->ifLateCollisions);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifOutUnderrun",                           p_device_mib->ifOutUnderrun);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifCarrierSenseErrors",                    p_device_mib->ifCarrierSenseErrors);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifOutOctets",                             p_device_mib->ifOutOctets);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "if64OctetFrames",                         p_device_mib->if64OctetFrames);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "if65To127POctetFrames",                   p_device_mib->if65To127OctetFrames);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "if128To255OctetFrames",                   p_device_mib->if128To255OctetFrames);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "if256To511OctetFrames",                   p_device_mib->if256To511OctetFrames);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "if512To1023OctetFrames",                  p_device_mib->if512To1023OctetFrames);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "if1024ToUpOctetFrames",                   p_device_mib->if1024ToUPOctetFrames);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifNetOctets",                             p_device_mib->ifNetOctets);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifRxSofOverruns",                         p_device_mib->ifRxSofOverruns);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifRxMofOverruns",                         p_device_mib->ifRxMofOverruns);
++    if(len <= limit)
++        len+= sprintf(buf + len, "%-35s: %lu\n", "ifRxDMAOverruns",                         p_device_mib->ifRxDMAOverruns);
++
++    *p_len = len;
++
++    return(0);
++}
++
++
++static int cpmac_p_read_rfc2665_stats(char* buf, char **start, off_t offset, 
++                             int count, int *eof, void *data)
++{
++    int limit = count - 80;
++    int len   = 0;
++    struct net_device *p_dev = (struct net_device*)data;
++
++    cpmac_p_update_statistics(p_dev, buf, limit, &len);
++
++    *eof = 1;
++
++    return len;
++}
++
++static int cpmac_p_read_link(char *buf, char **start, off_t offset, int count, 
++                             int *eof, void *data)
++{
++    int len = 0;
++
++    struct net_device    *p_dev;
++    CPMAC_PRIVATE_INFO_T *p_cpmac_priv;
++    struct net_device    *cpmac_dev_list[cpmac_devices_installed];
++    CPMAC_DRV_HAL_INFO_T *p_drv_hal;
++
++    int                  i;
++    int                  phy;            /* what phy are we using? */
++
++    len += sprintf(buf+len, "CPMAC devices = %d\n",cpmac_devices_installed);
++
++    p_dev        = last_cpmac_device;
++
++    /* Reverse the the device link list to list eth0,eth1...in correct order */
++    for(i=0; i< cpmac_devices_installed; i++)
++    {
++        cpmac_dev_list[cpmac_devices_installed -(i+1)] = p_dev;
++        p_cpmac_priv = p_dev->priv;
++        p_dev = p_cpmac_priv->next_device;
++    }
++
++    for(i=0; i< cpmac_devices_installed; i++)
++    {
++        p_dev        = cpmac_dev_list[i];
++        p_cpmac_priv = p_dev->priv;
++        p_drv_hal    = p_cpmac_priv->drv_hal;
++
++        /*  This prints them out from high to low because of how the devices are linked */
++        if(netif_carrier_ok(p_dev))
++        {
++            p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "PhyNum", "Get", &phy);
++
++
++            len += sprintf(buf+len,"eth%d: Link State: %s    Phy:0x%x, Speed = %s, Duplex = %s\n",
++                           p_cpmac_priv->instance_num, "UP", phy, 
++                           (p_cpmac_priv->link_speed == 100000000) ? "100":"10",
++                           (p_cpmac_priv->link_mode  == 2) ? "Half":"Full");
++
++        }
++        else
++            len += sprintf(buf+len,"eth%d: Link State: DOWN\n",p_cpmac_priv->instance_num);
++
++        p_dev = p_cpmac_priv->next_device;
++    }
++
++    return len;
++
++}
++
++static int cpmac_p_read_stats(char* buf, char **start, off_t offset, int count,
++                              int *eof, void *data)
++{
++    struct net_device *p_dev = last_cpmac_device;
++    int                len   = 0;
++    int                limit = count - 80;
++    int i;
++    struct net_device     *cpmac_dev_list[cpmac_devices_installed];
++    CPMAC_PRIVATE_INFO_T  *p_cpmac_priv;
++    CPMAC_DEVICE_MIB_T    *p_device_mib;
++
++    /* Reverse the the device link list to list eth0,eth1...in correct order */
++    for(i=0; i< cpmac_devices_installed; i++)
++    {
++        cpmac_dev_list[cpmac_devices_installed - (i+1)] = p_dev;
++        p_cpmac_priv = p_dev->priv;
++        p_dev = p_cpmac_priv->next_device;
++    }
++
++    for(i=0; i< cpmac_devices_installed; i++)
++    {
++        p_dev = cpmac_dev_list[i];
++
++        if(!p_dev)
++          goto proc_error;
++
++        /* Get Stats */
++        cpmac_p_update_statistics(p_dev, NULL, 0, NULL);
++
++        p_cpmac_priv = p_dev->priv;
++        p_device_mib = p_cpmac_priv->device_mib;
++
++        /* Transmit stats */
++        if(len<=limit)
++          len+= sprintf(buf+len, "\nCpmac %d, Address %lx\n",i+1, p_dev->base_addr);
++        if(len<=limit)
++          len+= sprintf(buf+len, " Transmit Stats\n");
++        if(len<=limit)
++          len+= sprintf(buf+len, "   Tx Valid Bytes Sent        :%lu\n",p_device_mib->ifOutOctets);
++        if(len<=limit)
++          len+= sprintf(buf+len, "   Good Tx Frames (Hardware)  :%lu\n",p_device_mib->ifOutGoodFrames);
++        if(len<=limit)
++          len+= sprintf(buf+len, "   Good Tx Frames (Software)  :%lu\n",p_cpmac_priv->net_dev_stats.tx_packets);
++        if(len<=limit)
++          len+= sprintf(buf+len, "   Good Tx Broadcast Frames   :%lu\n",p_device_mib->ifOutBroadcasts);
++        if(len<=limit)
++          len+= sprintf(buf+len, "   Good Tx Multicast Frames   :%lu\n",p_device_mib->ifOutMulticasts);
++        if(len<=limit)
++          len+= sprintf(buf+len, "   Pause Frames Sent          :%lu\n",p_device_mib->ifOutPauseFrames);
++        if(len<=limit)
++          len+= sprintf(buf+len, "   Collisions                 :%lu\n",p_device_mib->ifCollisionFrames);
++        if(len<=limit)
++          len+= sprintf(buf+len, "   Tx Error Frames            :%lu\n",p_cpmac_priv->net_dev_stats.tx_errors);
++        if(len<=limit)
++          len+= sprintf(buf+len, "   Carrier Sense Errors       :%lu\n",p_device_mib->ifCarrierSenseErrors);
++        if(len<=limit)
++          len+= sprintf(buf+len, "\n");
++
++
++        /* Receive Stats */
++        if(len<=limit)
++          len+= sprintf(buf+len, "\nCpmac %d, Address %lx\n",i+1,p_dev->base_addr);
++        if(len<=limit)
++          len+= sprintf(buf+len, " Receive Stats\n");
++        if(len<=limit)
++          len+= sprintf(buf+len, "   Rx Valid Bytes Received    :%lu\n",p_device_mib->ifInOctets);
++        if(len<=limit)
++          len+= sprintf(buf+len, "   Good Rx Frames (Hardware)  :%lu\n",p_device_mib->ifInGoodFrames);
++        if(len<=limit)
++          len+= sprintf(buf+len, "   Good Rx Frames (Software)  :%lu\n",p_cpmac_priv->net_dev_stats.rx_packets);
++        if(len<=limit)
++          len+= sprintf(buf+len, "   Good Rx Broadcast Frames   :%lu\n",p_device_mib->ifInBroadcasts);
++        if(len<=limit)
++          len+= sprintf(buf+len, "   Good Rx Multicast Frames   :%lu\n",p_device_mib->ifInMulticasts);
++        if(len<=limit)
++          len+= sprintf(buf+len, "   Pause Frames Received      :%lu\n",p_device_mib->ifInPauseFrames);
++        if(len<=limit)
++          len+= sprintf(buf+len, "   Rx CRC Errors              :%lu\n",p_device_mib->ifInCRCErrors);
++        if(len<=limit)
++          len+= sprintf(buf+len, "   Rx Align/Code Errors       :%lu\n",p_device_mib->ifInAlignCodeErrors);
++        if(len<=limit)
++          len+= sprintf(buf+len, "   Rx Jabbers                 :%lu\n",p_device_mib->ifInOversizedFrames);
++        if(len<=limit)
++          len+= sprintf(buf+len, "   Rx Filtered Frames         :%lu\n",p_device_mib->ifInFilteredFrames);
++        if(len<=limit)
++          len+= sprintf(buf+len, "   Rx Fragments               :%lu\n",p_device_mib->ifInFragments);
++        if(len<=limit)
++          len+= sprintf(buf+len, "   Rx Undersized Frames       :%lu\n",p_device_mib->ifInUndersizedFrames);
++        if(len<=limit)
++          len+= sprintf(buf+len, "   Rx Overruns                :%lu\n",p_device_mib->ifRxDMAOverruns);
++    }
++
++
++    return len;
++
++ proc_error:
++    *eof=1;
++    return len;
++}
++
++static int cpmac_p_write_stats (struct file *fp, const char * buf, unsigned long count, void * data)
++{
++      char local_buf[31];
++        int  ret_val = 0;
++
++      if(count > 30)
++      {
++              printk("Error : Buffer Overflow\n");
++              printk("Use \"echo 0 > cpmac_stat\" to reset the statistics\n");
++              return -EFAULT;
++      }
++
++      copy_from_user(local_buf,buf,count);
++      local_buf[count-1]='\0'; /* Ignoring last \n char */
++        ret_val = count;
++      
++      if(strcmp("0",local_buf)==0)
++      {
++            struct net_device *p_dev = last_cpmac_device;
++            int i;
++            struct net_device     *cpmac_dev_list[cpmac_devices_installed];
++            CPMAC_PRIVATE_INFO_T  *p_cpmac_priv;
++
++            /* Valid command */
++          printk("Resetting statistics for CPMAC interface.\n");
++
++            /* Reverse the the device link list to list eth0,eth1...in correct order */
++            for(i=0; i< cpmac_devices_installed; i++)
++            {
++                cpmac_dev_list[cpmac_devices_installed - (i+1)] = p_dev;
++                p_cpmac_priv = p_dev->priv;
++                p_dev = p_cpmac_priv->next_device;
++            }
++
++            for(i=0; i< cpmac_devices_installed; i++)
++             {
++                p_dev = cpmac_dev_list[i];
++                if(!p_dev)
++                {
++                    ret_val = -EFAULT;
++                    break;
++                }
++
++                cpmac_p_reset_statistics(p_dev);
++            }
++      }
++      else
++      {
++              printk("Error: Unknown operation on cpmac statistics\n");
++              printk("Use \"echo 0 > cpmac_stats\" to reset the statistics\n");
++              return -EFAULT;
++      }
++      
++      return ret_val;
++}
++
++static int cpmac_p_reset_statistics(struct net_device *p_dev)
++{
++    int                       ret_val  = 0;
++    CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv;
++    CPMAC_DRV_HAL_INFO_T *p_drv_hal    = p_cpmac_priv->drv_hal;
++
++    memset(p_cpmac_priv->device_mib, 0, sizeof(CPMAC_DEVICE_MIB_T));
++    memset(p_cpmac_priv->stats, 0, sizeof(CPMAC_DRV_STATS_T));
++    memset(&p_cpmac_priv->net_dev_stats, 0, sizeof(struct net_device_stats));
++
++    p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "StatsClear", "Set", NULL);
++
++    return(ret_val);
++}
++
++static int cpmac_p_get_version(char* buf, char **start, off_t offset, int count,int *eof, void *data)
++{
++    int  len                           = 0;
++    int  limit                         = count - 80;
++    char *hal_version                  = NULL;
++    struct net_device *p_dev           = last_cpmac_device;
++    CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv;
++    CPMAC_DRV_HAL_INFO_T *p_drv_hal    = p_cpmac_priv->drv_hal;
++
++    p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "Version", "Get", &hal_version);
++
++    len += sprintf(buf+len, "Texas Instruments CPMAC driver version: %s\n", cpmac_version);
++
++    if(len <= limit && hal_version)
++        len += sprintf(buf+len, "Texas Instruments CPMAC HAL version: %s\n", hal_version);
++
++    return len;
++}
++
++static struct net_device_stats *cpmac_dev_get_net_stats (struct net_device *p_dev)
++{
++    CPMAC_PRIVATE_INFO_T *p_cpmac_priv = (CPMAC_PRIVATE_INFO_T *) p_dev->priv;
++
++    cpmac_p_update_statistics(p_dev, NULL, 0, NULL);
++
++    return &p_cpmac_priv->net_dev_stats;
++}
++
++static int cpmac_p_detect_manual_cfg(int link_speed, char* link_mode, int debug)
++{
++    char *pSpeed = NULL;
++
++    if(debug == 1)
++    {
++        cpmac_debug_mode = 1;
++        dbgPrint("Enabled the debug print.\n");
++    }
++
++    if(!link_speed && !link_mode)
++    {
++        dbgPrint("No manual link params, defaulting to auto negotiation.\n");
++        return (0);
++    }
++
++    if(!link_speed || (link_speed != 10 && link_speed != 100))
++    {
++        dbgPrint("Invalid or No value of link speed specified, defaulting to auto speed.\n");
++        pSpeed = "auto";
++    }
++    else if(link_speed == 10)
++    {
++        g_cfg_start_link_params &= ~(_CPMDIO_100);
++        pSpeed = "10 Mbps";
++    }
++    else
++    {
++      g_cfg_start_link_params &= ~(_CPMDIO_10);
++        pSpeed = "100 Mbps";
++    }
++
++    if(!link_mode || (!strcmp(link_mode, "fd") && !strcmp(link_mode, "hd")))
++    {
++        dbgPrint("Invalid or No value of link mode specified, defaulting to auto mode.\n");
++    }
++    else if(!strcmp(link_mode, "hd"))
++    {
++        g_cfg_start_link_params &= ~(_CPMDIO_FD);
++    }
++    else
++    {
++        g_cfg_start_link_params &= ~(_CPMDIO_HD);
++    }
++
++    dbgPrint("Link is manually set to the speed of %s speed and %s mode.\n", 
++              pSpeed, link_mode ? link_mode : "auto");
++
++    return(0);
++}
++
++//------------------------------------------------------------------------------
++// Call back from the HAL.
++//------------------------------------------------------------------------------
++static int cpmac_p_process_status_ind(CPMAC_PRIVATE_INFO_T *p_cpmac_priv)
++{
++    struct net_device    *p_dev        = p_cpmac_priv->owner;
++    CPMAC_DRV_HAL_INFO_T *p_drv_hal    = p_cpmac_priv->drv_hal;
++    int status;
++
++    p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "Status", "Get", &status);
++
++    /* We do not reflect the real link status if in loopback.
++     * After all, we want the packets to reach the hardware so
++     * that Send() should work. */
++    if(p_dev->flags & IFF_LOOPBACK)
++    {
++        dbgPrint("Maintaining the link up loopback for %s.\n", p_dev->name);
++      netif_carrier_on(p_dev);
++
++#if defined (CONFIG_MIPS_AVALANCHE_LED)
++        avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_LINK_ON);
++#endif
++
++        return(0);
++    }
++
++    if(status & CPMAC_STATUS_ADAPTER_CHECK) /* ???? */
++    {
++        ; /* what to do ? */
++    }    
++    else if(status)
++    {
++        if(!netif_carrier_ok(p_dev))
++      {
++            netif_carrier_on(p_cpmac_priv->owner);
++
++#if defined (CONFIG_MIPS_AVALANCHE_LED)
++            avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_LINK_ON);
++#endif
++          dbgPrint("Found the Link for the CPMAC instance %s.\n", p_dev->name);
++        }
++
++        if(netif_running(p_dev) & netif_queue_stopped(p_dev))
++        {
++            netif_wake_queue(p_dev);
++        }
++
++      p_cpmac_priv->link_speed = status & CPMAC_STATUS_LINK_SPEED ? 100000000:10000000;
++      p_cpmac_priv->link_mode  = status & CPMAC_STATUS_LINK_DUPLEX? 3:2;
++
++    }
++    else
++    {
++        if(netif_carrier_ok(p_dev))
++      {
++          /* do we need to register synchronization issues with stats here. */
++          p_cpmac_priv->link_speed        = 100000000;
++          p_cpmac_priv->link_mode         = 1;
++
++          netif_carrier_off(p_dev);
++
++#if defined (CONFIG_MIPS_AVALANCHE_LED)
++            avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_LINK_OFF);
++#endif
++
++          dbgPrint("Lost the Link for the CPMAC for %s.\n", p_dev->name);
++      }
++
++        if(!netif_queue_stopped(p_dev))
++        {
++            netif_stop_queue(p_dev);     /* So that kernel does not keep on xmiting pkts. */
++        }
++    }
++
++    return(0);
++}
++
++//-----------------------------------------------------------------------------
++// Timer related private functions.
++//-----------------------------------------------------------------------------
++static int cpmac_p_timer_init(CPMAC_PRIVATE_INFO_T *p_cpmac_priv)
++{
++    struct timer_list *p_timer = p_cpmac_priv->timer;
++
++    init_timer(p_timer);
++    
++    p_timer                    = p_cpmac_priv->timer + TICK_TIMER;
++    p_timer->expires           = 0;
++    p_timer->data              = (unsigned long)p_cpmac_priv;
++    p_timer->function          = cpmac_p_tick_timer_expiry;
++
++    return(0);
++}
++
++#if 0
++static int cpmac_timer_cleanup(CPMAC_PRIVATE_INFO_T *p_cpmac_priv)
++{
++    struct timer_list *p_timer;
++
++    p_timer = p_cpmac_priv->timer + TICK_TIMER;
++   
++    /* use spin lock to establish synchronization with the dispatch */
++    if(p_timer->function) del_timer_sync(p_timer);
++    p_timer->function = NULL;
++
++    return (0);
++}
++#endif
++
++static int cpmac_p_start_timer(struct timer_list *p_timer, unsigned int delay_ticks)
++{
++    p_timer->expires        = jiffies + delay_ticks;
++
++    if(p_timer->function)
++    {
++        add_timer(p_timer);
++    }
++
++    return(0);
++} 
++
++static void cpmac_p_tick_timer_expiry(unsigned long p_cb_param)
++{
++    CPMAC_PRIVATE_INFO_T   *p_cpmac_priv = (CPMAC_PRIVATE_INFO_T*) p_cb_param;
++    CPMAC_DRV_HAL_INFO_T   *p_drv_hal    = p_cpmac_priv->drv_hal; 
++    struct timer_list       *p_timer     = p_cpmac_priv->timer + TICK_TIMER;
++
++    if(test_bit(0, &p_cpmac_priv->set_to_close))
++    {
++        return;
++    }
++
++    p_drv_hal->hal_funcs->Tick(p_drv_hal->hal_dev);
++  
++    cpmac_p_start_timer(p_timer, p_cpmac_priv->delay_ticks);
++}
++
++static int cpmac_p_stop_timer(struct timer_list *p_timer)
++{
++    /* Ideally we need to a set flag indicating not to start the timer again
++       before del_timer_sync() is called up. But here we assume that the 
++       caller has set the p_cpmac_priv->set_to_close (ok for now). */
++    del_timer_sync(p_timer);
++    
++    return(0);
++}
++
++//------------------------------------------------------------------------------
++// Device configuration and setup related private functions.
++//------------------------------------------------------------------------------
++static int cpmac_p_probe_and_setup_device(CPMAC_PRIVATE_INFO_T *p_cpmac_priv, 
++                                        unsigned long *p_dev_flags)
++{
++    CPMAC_DRV_HAL_INFO_T *p_drv_hal   = p_cpmac_priv->drv_hal;
++    HAL_FUNCTIONS        *p_hal_funcs = p_drv_hal->hal_funcs;
++    HAL_DEVICE           *p_hal_dev   = p_drv_hal->hal_dev;
++    CPMAC_ABILITY_INFO_T *p_capability= p_cpmac_priv->ability_info;
++    unsigned int         val          = 0;
++    int                  channel      = 0;
++
++    p_cpmac_priv->flags                  = 0;
++
++    p_capability->promiscous             = CFG_PROMISCOUS;
++    p_capability->broadcast              = CFG_BROADCAST;
++    p_capability->multicast              = CFG_MULTICAST;
++    p_capability->all_multi              = CFG_ALL_MULTI;
++    p_capability->jumbo_frames           = CFG_JUMBO_FRAMES;
++    p_capability->short_frames           = CFG_SHORT_FRAMES;
++    p_capability->auto_negotiation       = CFG_AUTO_NEGOTIATION;
++    p_capability->link_speed             = cfg_start_link_speed;
++    p_capability->loop_back              = CFG_LOOP_BACK;
++    p_capability->tx_flow_control        = CFG_TX_FLOW_CNTL;
++    p_capability->rx_flow_control        = CFG_RX_FLOW_CNTL;
++    p_capability->tx_pacing              = CFG_TX_PACING;
++    p_capability->rx_pass_crc            = CFG_RX_PASS_CRC;
++    p_capability->qos_802_1q             = CFG_QOS_802_1Q;
++    p_capability->tx_num_chan            = CFG_TX_NUM_CHAN;
++
++    /* Lets probe the device for the configured capabilities (netdev specific).*/ 
++
++    /* Following are set in the set_multi_list, when indicated by the kernel 
++     * Promiscous and all multi.
++     */
++
++    if(p_capability->broadcast)
++    {
++        channel = 0;
++      val     = 1;
++        if((p_hal_funcs->Control(p_hal_dev, pszRX_BROAD_EN, pszSet, &val) == 0) && 
++           (p_hal_funcs->Control(p_hal_dev, pszRX_BROAD_CH, pszSet, &channel) == 0))
++          *p_dev_flags |= IFF_BROADCAST;
++      else
++          p_capability->broadcast = 0; /* no broadcast capabilities */
++    }
++
++    if(p_capability->multicast)
++    {
++        val     = 1;
++      channel = 0;
++      if((p_hal_funcs->Control(p_hal_dev, pszRX_MULT_EN, pszSet, &val) == 0) &&
++         (p_hal_funcs->Control(p_hal_dev, pszRX_MULT_CH, pszSet, &channel) == 0))
++          *p_dev_flags |= IFF_MULTICAST;
++      else
++      {
++          p_capability->multicast = 0; 
++          p_capability->all_multi = 0; /* no multicast, no all-multi. */
++      }
++    }
++
++    if(p_capability->loop_back)
++    {
++        ;  /* We do not put the device in loopback, if required use ioctl */
++    }
++    
++    /* Lets probe the device for the configured capabilities (Non net device specific).*/
++
++    if(p_capability->jumbo_frames)
++    {
++      val = 0;
++        if(p_hal_funcs->Control(p_hal_dev, pszRX_NO_CHAIN, pszSet, &val) == 0)
++            p_cpmac_priv->flags |= IFF_PRIV_JUMBO_FRAMES;
++      else
++          p_capability->jumbo_frames = 0;
++    }
++
++    if(p_capability->short_frames)
++    {
++      val = 1;
++        if(p_hal_funcs->Control(p_hal_dev, pszRX_CSF_EN, pszSet, &val) == 0)
++            p_cpmac_priv->flags |= IFF_PRIV_SHORT_FRAMES;
++      else
++          p_capability->short_frames = 0;
++    }            
++
++    val = g_cfg_start_link_params;
++
++    if( avalanche_is_mdix_on_chip() )
++    {
++        val |= _CPMDIO_AUTOMDIX;
++    }
++
++    if(p_hal_funcs->Control(p_hal_dev,pszMdioConnect,pszSet, &val) !=0)
++    {
++        p_capability->link_speed = 0;
++    }
++    else
++    {
++      if(g_cfg_start_link_params & (_CPMDIO_100 | _CPMDIO_HD | _CPMDIO_FD | _CPMDIO_10))
++            p_cpmac_priv->flags |= IFF_PRIV_AUTOSPEED;
++      else if(g_cfg_start_link_params & (_CPMDIO_100 | _CPMDIO_HD))
++          p_cpmac_priv->flags |= IFF_PRIV_LINK100_HD;
++      else if(g_cfg_start_link_params & (_CPMDIO_100 | _CPMDIO_FD))
++          p_cpmac_priv->flags |= IFF_PRIV_LINK100_FD;
++      else if(g_cfg_start_link_params & (_CPMDIO_10 | _CPMDIO_HD))
++          p_cpmac_priv->flags |= IFF_PRIV_LINK10_HD;
++      else if(g_cfg_start_link_params & (_CPMDIO_10 | _CPMDIO_FD))
++          p_cpmac_priv->flags |= IFF_PRIV_LINK10_FD;
++      else
++          ;
++    }
++
++    if(p_capability->tx_flow_control)
++    {
++      val = 1;
++        if(p_hal_funcs->Control(p_hal_dev,pszTX_FLOW_EN, pszSet, &val) ==0)
++            p_cpmac_priv->flags |= IFF_PRIV_TX_FLOW_CNTL;
++      else
++            p_capability->tx_flow_control = 0;
++    }
++
++    if(p_capability->rx_flow_control)
++    {
++      val = 1;
++        if(p_hal_funcs->Control(p_hal_dev, pszRX_FLOW_EN, pszSet, &val) ==0)
++          p_cpmac_priv->flags |= IFF_PRIV_RX_FLOW_CNTL;
++      else
++            p_capability->rx_flow_control = 0;
++    }
++
++    if(p_capability->tx_pacing)
++    {
++      val = 1;
++        if(p_hal_funcs->Control(p_hal_dev, pszTX_PACE, pszSet, &val) ==0)
++            p_cpmac_priv->flags |= IFF_PRIV_TX_PACING;
++      else
++          p_capability->tx_pacing = 0;
++    }
++
++    if(p_capability->rx_pass_crc)
++    {
++      val = 1;
++      if(p_hal_funcs->Control(p_hal_dev, pszRX_PASS_CRC, pszSet, &val) == 0)
++          p_cpmac_priv->flags |= IFF_PRIV_RX_PASS_CRC;
++      else                                  
++            p_capability->rx_pass_crc = 0;
++    }
++
++    if(p_capability->qos_802_1q)
++    {
++      val  = 1;
++        if(p_hal_funcs->Control(p_hal_dev, pszRX_QOS_EN, pszSet, &val) == 0)
++            p_cpmac_priv->flags |= IFF_PRIV_8021Q_EN;
++      else
++      {
++          p_capability->qos_802_1q = 0;
++          p_capability->tx_num_chan= 1;
++        }
++    }
++
++    if(p_capability->tx_num_chan > 1)
++    {
++      int cfg_tx_num_chan = p_capability->tx_num_chan;
++        val = 0;
++#ifdef TEST
++      if(p_hal_funcs->Control(p_hal_dev, pszTX_NUM_CH, pszGet, &val) == 0)
++          cfg_tx_num_chan = cfg_tx_num_chan > val ? val : cfg_tx_num_chan;
++      else 
++          cfg_tx_num_chan = 1;
++#endif
++      p_capability->tx_num_chan = cfg_tx_num_chan;
++    }
++
++    return(0);
++}
++
++static int cpmac_p_setup_driver_params(CPMAC_PRIVATE_INFO_T *p_cpmac_priv)
++{
++   int i=0;
++   int threshold = CFG_TX_NUM_BUF_SERVICE;
++
++   char *tx_threshold_ptr = prom_getenv("threshold");
++   
++    CPMAC_TX_CHAN_INFO_T *p_tx_chan_info = p_cpmac_priv->tx_chan_info;
++    CPMAC_RX_CHAN_INFO_T *p_rx_chan_info = p_cpmac_priv->rx_chan_info;
++    CPMAC_ABILITY_INFO_T *p_capability   = p_cpmac_priv->ability_info;
++
++    /* Timer stuff */
++    p_cpmac_priv->timer_count      = 1; /* should be < or = the MAX TIMER */
++    p_cpmac_priv->timer_created    = 0;
++    p_cpmac_priv->timer_access_hal = 1;
++
++    for(i=0; i < MAX_TIMER; i++)
++        p_cpmac_priv->timer[i].function = NULL;
++
++    p_cpmac_priv->enable_802_1q  = p_capability->qos_802_1q;  
++
++    /* Tx channel related.*/
++    p_tx_chan_info->cfg_chan     = p_capability->tx_num_chan;
++    p_tx_chan_info->opened_chan  = 0;
++    
++    if(tx_threshold_ptr)
++       threshold = simple_strtol(tx_threshold_ptr, (char **)NULL, 10);
++    
++    if((threshold <= 0) && tx_threshold_ptr) /* If threshold set to 0 then Enable the TX interrupt */
++    {
++       threshold  = CFG_TX_NUM_BUF_SERVICE;
++       p_tx_chan_info->tx_int_disable = 0;
++       
++    }
++    else
++    {
++       p_tx_chan_info->tx_int_disable = CFG_TX_INT_DISABLE;
++    }
++
++    for(i=0; i < MAX_TX_CHAN; i++)
++    {
++       
++
++
++       p_tx_chan_info->chan[i].state         = CHAN_CLOSE; 
++       p_tx_chan_info->chan[i].num_BD        = CFG_TX_NUM_BUF_DESC;  
++       p_tx_chan_info->chan[i].buffer_size   = cpmac_max_frame_size;
++       p_tx_chan_info->chan[i].buffer_offset = CFG_TX_BUF_OFFSET;
++
++
++
++       p_tx_chan_info->chan[i].service_max   = threshold;
++    }
++    
++    if (p_tx_chan_info->tx_int_disable)
++       printk("Cpmac driver Disable TX complete interrupt setting threshold to %d.\n",threshold);
++    else
++       printk("Cpmac driver Enable TX complete interrupt\n");
++
++    
++    /* Assuming just one rx channel for now */
++    p_rx_chan_info->cfg_chan            = 1;
++    p_rx_chan_info->opened_chan         = 0;
++    p_rx_chan_info->chan->state         = CHAN_CLOSE;
++    p_rx_chan_info->chan->num_BD        = CFG_RX_NUM_BUF_DESC;
++    p_rx_chan_info->chan->buffer_size   = cpmac_max_frame_size;
++    p_rx_chan_info->chan->buffer_offset = CFG_RX_BUF_OFFSET;
++    p_rx_chan_info->chan->service_max   = CFG_RX_NUM_BUF_SERVICE;
++
++    /* Set as per RFC 2665 */
++    p_cpmac_priv->link_speed     = 100000000; 
++    p_cpmac_priv->link_mode      = 1;
++
++    p_cpmac_priv->loop_back      = 0;
++
++    return(0);
++}
++
++inline static int cpmac_p_rx_buf_setup(CPMAC_RX_CHAN_INFO_T *p_rx_chan)
++{
++    /* Number of ethernet packets & max pkt length */
++    p_rx_chan->chan->tot_buf_size  = p_rx_chan->chan->buffer_size   + 
++                                     2*(CONTROL_802_1Q_SIZE)        +
++                                   p_rx_chan->chan->buffer_offset +
++                                     ADD_FOR_4BYTE_ALIGN(p_rx_chan->chan->buffer_offset & 0x3);
++
++    p_rx_chan->chan->tot_reserve_bytes = CONTROL_802_1Q_SIZE + 
++                                         p_rx_chan->chan->buffer_offset +
++                                       L3_ALIGN(p_rx_chan->chan->buffer_offset & 0x3);
++
++    return(0);
++}
++
++//-----------------------------------------------------------------------------
++// Net device related private functions.
++//-----------------------------------------------------------------------------
++
++/***************************************************************
++ *    cpmac_dev_init
++ *
++ *    Returns:
++ *            0 on success, error code otherwise.
++ *    Parms:
++ *            dev     The structure of the device to be
++ *                    init'ed.
++ *
++ *    This function completes the initialization of the
++ *    device structure and driver.  It reserves the IO
++ *    addresses and assignes the device's methods.
++ *
++ *    
++ **************************************************************/
++
++static int cpmac_dev_init(struct net_device *p_dev)
++{
++    int retVal = -1;
++    CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv;
++    int instance_num                   = p_cpmac_priv->instance_num;
++    unsigned long net_flags = 0;
++    char *mac_name          = NULL;
++    char *mac_string        = NULL;
++
++    CPMAC_TX_CHAN_INFO_T *p_tx_chan_info;
++    CPMAC_RX_CHAN_INFO_T *p_rx_chan_info;
++    CPMAC_DRV_HAL_INFO_T *p_drv_hal;
++    int i;
++
++    int mem_size =    sizeof(CPMAC_DRV_HAL_INFO_T)
++                  + sizeof(CPMAC_TX_CHAN_INFO_T)
++                  + sizeof(CPMAC_RX_CHAN_INFO_T)
++                  + sizeof(CPMAC_ABILITY_INFO_T)
++                    + sizeof(CPMAC_DEVICE_MIB_T)
++                    + sizeof(CPMAC_DRV_STATS_T);
++
++
++#if defined(CONFIG_MIPS_SEAD2)
++    int prev_reset_val = RESET_REG_PRCR;
++    /* Bring the module out of reset */
++    RESET_REG_PRCR |= temp_reset_value[p_cpmac_priv->instance_num];     
++
++    /* Read the version id of the device to check if the device really exists */
++    if( VERSION(temp_base_address[p_cpmac_priv->instance_num]) == 0)
++    {
++        printk(" CPMAC:Device not found\n");
++      RESET_REG_PRCR = prev_reset_val;
++        return -ENODEV;
++    }
++
++    RESET_REG_PRCR = prev_reset_val;
++#endif
++
++
++    if((p_drv_hal = kmalloc(mem_size,  GFP_KERNEL)) == NULL)
++    {
++        errPrint("Failed to allocate memory; rewinding.\n");
++        return(-1);
++    }
++
++    memset(p_drv_hal, 0, mem_size);
++
++    /* build the cpmac private object */
++    p_cpmac_priv->drv_hal       = p_drv_hal;
++    p_cpmac_priv->tx_chan_info  = p_tx_chan_info
++                                = (CPMAC_TX_CHAN_INFO_T*)((char*)p_drv_hal 
++                                + sizeof(CPMAC_DRV_HAL_INFO_T));
++    p_cpmac_priv->rx_chan_info  = p_rx_chan_info 
++                                = (CPMAC_RX_CHAN_INFO_T*)((char *)p_tx_chan_info 
++                                + sizeof(CPMAC_TX_CHAN_INFO_T));
++    p_cpmac_priv->ability_info  = (CPMAC_ABILITY_INFO_T *)((char *)p_rx_chan_info 
++                                + sizeof(CPMAC_RX_CHAN_INFO_T));
++    p_cpmac_priv->device_mib    = (CPMAC_DEVICE_MIB_T *)((char *)p_cpmac_priv->ability_info 
++                                + sizeof(CPMAC_ABILITY_INFO_T));
++    p_cpmac_priv->stats         = (CPMAC_DRV_STATS_T *)((char *)p_cpmac_priv->device_mib   
++                                + sizeof(CPMAC_DEVICE_MIB_T));
++
++    p_drv_hal->owner            = p_cpmac_priv;
++
++
++    switch(instance_num)
++    {
++
++        case 0:
++            mac_name="maca";
++
++            /* Also setting port information */
++            p_dev->if_port =  AVALANCHE_CPMAC_LOW_PORT_ID;            
++
++            break;
++
++        case 1:
++            mac_name="macb";
++
++            /* Also setting port information */
++            p_dev->if_port =  AVALANCHE_CPMAC_HIGH_PORT_ID;            
++
++            break;
++    }
++
++    if(mac_name)
++        mac_string=prom_getenv(mac_name);
++
++    if(!mac_string)
++    {
++        mac_string="08.00.28.32.06.02";
++        printk("Error getting mac from Boot enviroment for %s\n",p_dev->name);
++        printk("Using default mac address: %s\n",mac_string);
++        if(mac_name)
++        {
++            printk("Use Bootloader command:\n");
++            printk("    setenv %s xx.xx.xx.xx.xx.xx\n","<env_name>");
++            printk("to set mac address\n");
++        }
++    }
++
++    str2eaddr(p_cpmac_priv->mac_addr,mac_string);
++
++    for (i=0; i <= ETH_ALEN; i++)
++    {
++        /* This sets the hardware address */
++      p_dev->dev_addr[i] = p_cpmac_priv->mac_addr[i]; 
++    }
++
++    p_cpmac_priv->set_to_close          = 1;
++    p_cpmac_priv->non_data_irq_expected = 0;
++
++#if defined (CONFIG_MIPS_AVALANCHE_LED)
++    if((p_cpmac_priv->led_handle = avalanche_led_register("cpmac", instance_num)) == NULL)
++    {
++        errPrint("Could not allocate handle for CPMAC[%d] LED.\n", instance_num);
++        goto cpmac_init_mod_error;
++    }
++#endif
++
++    if(cpmac_drv_init_module(p_drv_hal, p_dev, instance_num) != 0)
++    {
++        errPrint("Could not initialize the HAL for %s.\n", p_dev->name);
++        goto cpmac_init_mod_error;
++    } 
++
++    /* initialize the CPMAC device */
++    if (cpmac_drv_init(p_drv_hal) == -1)
++    {
++      errPrint("HAL init failed for %s.\n", p_dev->name);
++      goto cpmac_init_device_error;
++    }
++
++    if(cpmac_p_probe_and_setup_device(p_cpmac_priv, &net_flags) == -1)
++    {
++        errPrint("Failed to configure up %s.\n", p_dev->name);
++        goto cpmac_init_device_error;
++    }
++
++    if(cpmac_p_setup_driver_params(p_cpmac_priv) == -1)
++    {
++        errPrint("Failed to set driver parameters for %s.\n", p_dev->name);
++        goto cpmac_init_device_error;
++    }
++
++    cpmac_p_rx_buf_setup(p_rx_chan_info);
++
++    /* initialize the timers for the net device */
++    if(cpmac_p_timer_init(p_cpmac_priv) == -1)
++    {
++        errPrint("Failed to set timer(s) for %s.\n", p_dev->name);
++        goto cpmac_timer_init_error;
++    }
++
++    p_dev->addr_len           = 6;
++
++    p_dev->open               = &cpmac_dev_open;    /*  i.e. Start Device  */
++    p_dev->hard_start_xmit    = &cpmac_dev_tx;
++    p_dev->stop               = &cpmac_dev_close;
++    p_dev->get_stats          = &cpmac_dev_get_net_stats;
++
++    p_dev->set_multicast_list = &cpmac_dev_mcast_set;
++    p_dev->set_mac_address    = cpmac_dev_set_mac_addr;
++    /* Knocking off the default broadcast and multicast flags. Allowing the 
++       device configuration to control the flags. */
++    p_dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
++    p_dev->flags |= net_flags;
++
++    netif_carrier_off(p_dev);
++
++#if defined (CONFIG_MIPS_AVALANCHE_LED)
++    avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_LINK_OFF);
++#endif
++
++    /* Tasklet is initialized at the isr registeration time. */
++    p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "CpmacBase", "Get", &p_dev->base_addr);
++    p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "CpmacSize", "Get", &p_cpmac_priv->dev_size);
++
++    request_mem_region(p_dev->base_addr, p_cpmac_priv->dev_size, p_dev->name);
++
++    retVal = 0;
++
++    if(g_init_enable_flag)
++        cpmac_p_dev_enable(p_dev);
++
++    return(retVal);
++
++cpmac_timer_init_error:
++cpmac_init_device_error  :
++    cpmac_drv_cleanup(p_drv_hal);
++
++cpmac_init_mod_error:
++    kfree(p_drv_hal);
++
++    return (retVal);
++
++} /* cpmac_dev_init */
++
++
++/***************************************************************
++ *    cpmac_p_dev_enable
++ *
++ *    Returns:
++ *            0 on success, error code otherwise.
++ *    Parms:
++ *            dev     Structure of device to be opened.
++ *
++ *    This routine puts the driver and CPMAC adapter in a
++ *    state where it is ready to send and receive packets.
++ *    
++ *
++ **************************************************************/
++int cpmac_p_dev_enable( struct net_device *p_dev)
++{
++    int ret_val = 0;
++    int channel = 0;
++ 
++    CPMAC_PRIVATE_INFO_T *p_cpmac_priv   = p_dev->priv;
++    CPMAC_DRV_HAL_INFO_T *p_drv_hal      = p_cpmac_priv->drv_hal;
++    CPMAC_RX_CHAN_INFO_T *p_rx_chan_info = p_cpmac_priv->rx_chan_info;
++    int max_length                       = p_rx_chan_info->chan->tot_buf_size;
++
++    p_cpmac_priv->set_to_close = 0;
++
++    if((ret_val = cpmac_drv_start(p_drv_hal, p_cpmac_priv->tx_chan_info, 
++                                p_cpmac_priv->rx_chan_info, CHAN_SETUP))==-1)
++    {
++        errPrint("%s error: failed to start the device.\n", p_dev->name);
++        ret_val = -1;
++    }
++    else if(p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev,"RX_UNICAST_SET",  
++                                        "Set", &channel)!=0)
++    {
++        errPrint("%s error: device chan 0 could not be enabled.\n", p_dev->name);     
++      ret_val = -1;
++    }
++    else if(p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, pszRX_MAXLEN, pszSet, &max_length) != 0)
++    {
++        errPrint(" CPMAC registers can't be written \n");
++        ret_val = -1;
++    }
++    else if(p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "TxIntDisable", "Set", 
++            &p_cpmac_priv->tx_chan_info->tx_int_disable) != 0)
++    {    
++        errPrint(" CPMAC registers can't be written \n");
++        ret_val = -1;
++    }
++    else
++    {
++        ; // Every thing went OK. 
++    }
++    
++    return(ret_val);
++} /* cpmac_dev_enable */
++
++
++static int cpmac_dev_open(struct net_device *p_dev)
++{
++    CPMAC_PRIVATE_INFO_T *p_cpmac_priv   = p_dev->priv;
++    CPMAC_ISR_INFO_T     *p_isr_cb_param = &p_cpmac_priv->cpmac_isr;
++
++    if(!g_init_enable_flag)
++        cpmac_p_dev_enable(p_dev);
++   
++    if(request_irq(p_isr_cb_param->intr, cpmac_hal_isr, SA_INTERRUPT, 
++                   "Cpmac Driver", p_isr_cb_param))
++    {
++        errPrint("Failed to register the irq %d for Cpmac %s.\n",
++                  p_isr_cb_param->intr, p_dev->name); 
++        return (-1);          
++    }
++    
++    netif_start_queue(p_dev);
++
++    MOD_INC_USE_COUNT;
++    p_cpmac_priv->stats->start_tick = jiffies;
++    dbgPrint("Started the network queue for %s.\n", p_dev->name);    
++    return(0);
++}
++
++/***************************************************************
++ *    cpmac_p_dev_disable
++ *  
++ *    Returns:
++ *            An error code.
++ *    Parms:
++ *            dev     The device structure of the device to
++ *                    close.
++ *
++ *    This function shuts down the adapter.  
++ *
++ **************************************************************/
++int cpmac_p_dev_disable(struct net_device *p_dev)
++{
++    int ret_val = 0;
++    CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv;
++    CPMAC_DRV_HAL_INFO_T *p_drv_hal    = p_cpmac_priv->drv_hal;
++
++    set_bit(0, &p_cpmac_priv->set_to_close);
++    set_bit(0, &p_cpmac_priv->non_data_irq_expected);
++   
++    /* The driver does not re-schedule the tasklet after kill is called. So, this 
++       should take care of the bug in the kernel. */
++    tasklet_kill(&p_cpmac_priv->cpmac_isr.tasklet);
++ 
++    if(cpmac_drv_stop(p_drv_hal, p_cpmac_priv->tx_chan_info,
++                    p_cpmac_priv->rx_chan_info, 
++                    CHAN_TEARDOWN | FREE_BUFFER | BLOCKING | COMPLETE) == -1)
++    {
++        ret_val = -1;
++    }
++    else
++    {
++        /* hope that the HAL closes down the tick timer.*/
++
++        dbgPrint("Device %s Closed.\n", p_dev->name);
++        p_cpmac_priv->stats->start_tick = jiffies;
++
++        p_cpmac_priv->link_speed        = 100000000;
++        p_cpmac_priv->link_mode         = 1;
++        netif_carrier_off(p_dev);
++
++#if defined (CONFIG_MIPS_AVALANCHE_LED)
++        avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_LINK_OFF);
++#endif
++
++        clear_bit(0, &p_cpmac_priv->non_data_irq_expected);
++
++    }
++    
++    return (ret_val);
++
++} /* cpmac_dev_close */
++
++
++/***************************************************************
++ *    cpmac_dev_close
++ *  
++ *    Returns:
++ *            An error code.
++ *    Parms:
++ *            dev     The device structure of the device to
++ *                    close.
++ *
++ *    This function shuts down the adapter.  
++ *
++ **************************************************************/
++static int cpmac_dev_close(struct net_device *p_dev)
++{
++    CPMAC_PRIVATE_INFO_T *p_cpmac_priv   = p_dev->priv;
++    CPMAC_ISR_INFO_T     *p_isr_cb_param = &p_cpmac_priv->cpmac_isr;
++
++    /* inform the upper layers. */
++    netif_stop_queue(p_dev);
++
++    if(!g_init_enable_flag)
++        cpmac_p_dev_disable(p_dev);
++    else
++        free_irq(p_isr_cb_param->intr, p_isr_cb_param);
++
++    MOD_DEC_USE_COUNT;
++
++    return(0);
++}
++
++static void cpmac_dev_mcast_set(struct net_device *p_dev)
++{
++    CPMAC_PRIVATE_INFO_T    *p_cpmac_priv = p_dev->priv;
++    CPMAC_DRV_HAL_INFO_T    *p_drv_hal    = p_cpmac_priv->drv_hal;
++    CPMAC_ABILITY_INFO_T    *p_capability = p_cpmac_priv->ability_info;
++    HAL_FUNCTIONS           *p_hal_funcs  = p_drv_hal->hal_funcs;
++    HAL_DEVICE              *p_hal_dev    = p_drv_hal->hal_dev;
++    int                     val           = 1;
++    int                     channel       = 0;
++
++#if defined (CONFIG_MIPS_AVALANCHE_LED)    
++    if(netif_carrier_ok(p_dev))
++       avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_LINK_ON);
++#endif
++
++    if(p_dev->flags & IFF_PROMISC)
++    {
++        if(p_capability->promiscous)
++        {       
++            /* multi mode in the HAL, check this */
++          val = 0;
++          p_hal_funcs->Control(p_hal_dev, pszRX_MULTI_ALL, "Clear", &val);
++
++          val = 1;
++            /* set the promiscous mode in the HAL */
++            p_hal_funcs->Control(p_hal_dev, pszRX_CAF_EN, pszSet, &val);
++            p_hal_funcs->Control(p_hal_dev, pszRX_PROM_CH, pszSet, &channel);
++
++                  dbgPrint("%s set in the Promisc mode.\n", p_dev->name);     
++      }
++        else
++        {
++          errPrint("%s not configured for Promisc mode.\n", p_dev->name);
++        }
++    }
++    else if(p_dev->flags & IFF_ALLMULTI)
++    {
++        if(p_capability->all_multi)
++        {     
++          val = 0;
++          /* disable the promiscous mode in the HAL */
++          p_hal_funcs->Control(p_hal_dev, pszRX_CAF_EN, "Clear", &val);
++
++          val = 1;
++            /* set the all multi mode in the HAL */
++          p_hal_funcs->Control(p_hal_dev, pszRX_MULTI_ALL, pszSet, &val);
++          p_hal_funcs->Control(p_hal_dev, pszRX_MULT_CH, pszSet, &channel);
++
++            dbgPrint("%s has been set to the ALL_MULTI mode.\n", p_dev->name);
++        }
++        else
++        {
++          errPrint("%s not configured for ALL MULTI mode.\n", p_dev->name);
++        }
++    }
++    else if(p_dev->mc_count)
++    {
++        if(p_capability->multicast)
++        {
++          struct dev_mc_list *p_dmi = p_dev->mc_list;
++            int    count;
++
++            val = 0;
++            /* clear all the previous data, we are going to populate new ones.*/
++          p_hal_funcs->Control(p_hal_dev, pszRX_MULTI_ALL, "Clear", &val);
++          /* disable the promiscous mode in the HAL */
++          p_hal_funcs->Control(p_hal_dev, pszRX_CAF_EN, pszSet, &val);
++
++          for(count = 0; count < p_dev->mc_count; count++, p_dmi = p_dmi->next)
++          {
++               p_hal_funcs->Control(p_hal_dev, "RX_MULTI_SINGLE", "Set", p_dmi->dmi_addr); 
++          }
++
++            dbgPrint("%s configured for %d multicast addresses.\n", p_dev->name, p_dev->mc_count);
++        }
++        else
++        {
++          errPrint("%s has not been configuted for multicast handling.\n", p_dev->name);
++        }
++    }
++    else
++    {
++       val = 0;
++       /* clear all the previous data, we are going to populate new ones.*/
++       p_hal_funcs->Control(p_hal_dev, pszRX_MULTI_ALL, "Clear", &val);
++       /* disable the promiscous mode in the HAL */
++       p_hal_funcs->Control(p_hal_dev, pszRX_CAF_EN, pszSet, &val);
++       dbgPrint("Dev set to  Unicast mode.\n");
++    }
++}
++
++static int cpmac_dev_set_mac_addr(struct net_device *p_dev,void * addr)
++{
++    CPMAC_PRIVATE_INFO_T    *p_cpmac_priv = p_dev->priv;
++    CPMAC_DRV_HAL_INFO_T    *p_drv_hal    = p_cpmac_priv->drv_hal;
++    HAL_FUNCTIONS           *p_hal_funcs  = p_drv_hal->hal_funcs;
++    HAL_DEVICE              *p_hal_dev    = p_drv_hal->hal_dev;
++    struct sockaddr *sa = addr;
++
++   memcpy(p_cpmac_priv->mac_addr,sa->sa_data,p_dev->addr_len);
++   memcpy(p_dev->dev_addr,sa->sa_data,p_dev->addr_len);
++   p_hal_funcs->Control(p_hal_dev, pszMacAddr, pszSet, p_cpmac_priv->mac_addr);   
++
++      return 0;
++
++}
++
++/* VLAN is handled by vlan/vconfig support. Here, we just check for the 
++ * 802.1q configuration of the device and en-queue the packet accordingly.
++ * We do not do any 802.1q processing here.
++ */
++static int cpmac_dev_tx( struct sk_buff *skb, struct net_device *p_dev)
++{
++    CPMAC_PRIVATE_INFO_T *p_cpmac_priv  = p_dev->priv;
++    CPMAC_DRV_HAL_INFO_T *p_drv_hal     = p_cpmac_priv->drv_hal;
++    int channel                         = 0;
++    int ret_val                         = 0;
++    FRAGLIST             send_frag_list[1];
++
++#ifdef CPMAC_8021Q_SUPPORT
++    if(skb->len < TCI_END_OFFSET)
++    {
++        /* Whee, frame shorter than 14 bytes !! We need to copy 
++       * fragments to understand the frame. Too much work. 
++       * Hmm, dump it. */
++
++        /* Free the buffer */
++      goto cpmac_dev_tx_drop_pkt;
++    }
++
++    /* 802.1p/q stuff */
++    if(IS_802_1Q_FRAME(skb->data + TPID_START_OFFSET)) 
++    {
++        /* IEEE 802.1q, section 8.8 and section 8.11.9 */
++        if(!p_cpmac_priv->enable_802_1q) 
++        {
++           /* free the buffer */
++           goto cpmac_dev_tx_drop_pkt;
++        }             
++
++        channel = GET_802_1P_CHAN(p_cpmac_priv->tx_chan_info->opened_chan,
++                                        skb->data[TCI_START_OFFSET]);
++
++    }
++    /* sending a non 802.1q frame, when configured for 802.1q: dump it.*/
++    else if(p_cpmac_priv->enable_802_1q)
++    {
++         /* free the buffer */
++       goto cpmac_dev_tx_drop_pkt;
++    }
++    else
++    {
++        ;/* it is the good old non 802.1q */
++    }
++#endif
++
++    send_frag_list->len  = skb->len;
++    send_frag_list->data = skb->data;
++
++#ifdef CPMAC_TEST
++    xdump(skb->data, skb->len, "send");
++#endif
++
++    dma_cache_wback_inv((unsigned long)skb->data, skb->len);    
++
++    if(p_drv_hal->hal_funcs->Send(p_drv_hal->hal_dev, send_frag_list, 1, 
++                                skb->len, skb, channel) != 0)
++    {
++      /* code here to stop the queue, when allowing tx timeout, perhaps next release.*/
++        p_cpmac_priv->net_dev_stats.tx_errors++;  
++#ifndef TI_SLOW_PATH
++       /* Free the skb in case of Send return error */
++        dev_kfree_skb_any(skb);
++        p_cpmac_priv->net_dev_stats.tx_dropped++;
++        return 0;
++#endif
++        goto cpmac_dev_tx_drop_pkt; 
++    }
++
++#if defined (CONFIG_MIPS_AVALANCHE_LED)
++    avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_TX_ACTIVITY);
++#endif
++
++    return(ret_val);
++
++cpmac_dev_tx_drop_pkt:
++
++    p_cpmac_priv->net_dev_stats.tx_dropped++;
++    ret_val = -1;
++    return (ret_val);
++
++} /*cpmac_dev_tx */
++
++
++//------------------------------------------------------------------------------
++// Public functions : Called by outsiders to this file.
++//------------------------------------------------------------------------------
++
++
++void *cpmac_hal_malloc_buffer(unsigned int size, void* mem_base, unsigned int mem_range,
++                            OS_SETUP *p_os_setup, HAL_RECEIVEINFO *HalReceiveInfo, 
++                            OS_RECEIVEINFO **osReceiveInfo, OS_DEVICE *p_dev)
++{
++    CPMAC_RX_CHAN_INFO_T *p_rx_chan_info = (CPMAC_RX_CHAN_INFO_T *)p_os_setup;
++    int                  tot_buf_size    = p_rx_chan_info->chan->tot_buf_size;
++    int             tot_reserve_bytes    = p_rx_chan_info->chan->tot_reserve_bytes;
++    struct sk_buff  *p_skb;
++    void             *ret_ptr;
++
++    /* use TI SKB private pool */
++    p_skb = dev_alloc_skb(tot_buf_size);
++
++    if(p_skb == NULL)
++    {
++        errPrint("Failed to allocate skb for %s.\n", ((struct net_device*)p_dev)->name);
++        return (NULL);
++    }
++
++    p_skb->dev = p_dev;
++    skb_reserve(p_skb, tot_reserve_bytes);
++
++    *osReceiveInfo = p_skb;
++
++    ret_ptr = skb_put(p_skb, p_rx_chan_info->chan->buffer_size);
++
++    return(ret_ptr);
++}
++
++void cpmac_hal_isr(int irq, void *p_param, struct pt_regs *regs)
++{
++    CPMAC_ISR_INFO_T      *p_cb_param    = (CPMAC_ISR_INFO_T*) p_param;
++    CPMAC_DRV_HAL_INFO_T  *p_drv_hal     = p_cb_param->owner;
++    CPMAC_PRIVATE_INFO_T *p_cpmac_priv   = p_drv_hal->owner;
++    int                   pkts_to_handle = 0;
++
++    if(p_cpmac_priv->non_data_irq_expected)
++    {
++        p_cb_param->hal_isr(p_drv_hal->hal_dev, &pkts_to_handle);
++        p_drv_hal->hal_funcs->PacketProcessEnd(p_drv_hal->hal_dev);
++    }
++    else if(!p_cpmac_priv->set_to_close)
++        tasklet_schedule(&((CPMAC_ISR_INFO_T*) p_param)->tasklet);
++    else
++        ; // back off from doing anything more. We are closing down.
++}
++
++void cpmac_handle_tasklet(unsigned long data)
++{
++    CPMAC_ISR_INFO_T     *p_cb_param   = (CPMAC_ISR_INFO_T*) data;
++    CPMAC_DRV_HAL_INFO_T *p_drv_hal    = p_cb_param->owner;
++    CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_drv_hal->owner;
++    int                  pkts_to_handle;
++
++    p_cb_param->hal_isr(p_drv_hal->hal_dev, &pkts_to_handle);
++
++    if(test_bit(0, &p_cpmac_priv->non_data_irq_expected) || !pkts_to_handle)
++        p_drv_hal->hal_funcs->PacketProcessEnd(p_drv_hal->hal_dev);
++    else if(!test_bit(0, &p_cpmac_priv->set_to_close))
++        tasklet_schedule(&p_cb_param->tasklet);
++    else
++        ; // Back off from processing packets we are closing down.
++}
++
++int cpmac_hal_control(OS_DEVICE *p_dev, const char *key, 
++                    const char *action, void *value)
++{
++    CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv;
++    int ret_val = -1;
++
++    if(key == NULL)
++    {
++        dbgPrint("Encountered NULL key.\n");
++      return (-1);
++    }
++
++    if(cpmac_ci_strcmp(key, "Sleep") == 0 && value != NULL)
++    {
++        unsigned int clocks_per_tick  = cpmac_cpu_freq/HZ;
++      unsigned int requested_clocks = *(unsigned int*)value;
++      unsigned int requested_ticks  = (requested_clocks + clocks_per_tick - 1)/clocks_per_tick;
++        mdelay(requested_ticks); 
++      ret_val = 0;
++    }
++    else if(cpmac_ci_strcmp(key, "StateChange") == 0)
++    {
++        ret_val = cpmac_p_process_status_ind(p_cpmac_priv);
++    }
++    else if(cpmac_ci_strcmp(key, "Tick") == 0 && action != NULL)
++    {
++      if(cpmac_ci_strcmp(action, "Set") == 0 && value != NULL)
++      {
++            if(*(unsigned int*)value == 0)
++            {
++                cpmac_p_stop_timer(p_cpmac_priv->timer + TICK_TIMER);
++                ret_val = 0;
++            }
++            else
++            {
++                unsigned int clocks_per_tick  = cpmac_cpu_freq/HZ;
++              unsigned int requested_clocks = *(unsigned int*)value;
++              unsigned int requested_ticks  = (requested_clocks + clocks_per_tick - 1)/clocks_per_tick;
++
++                p_cpmac_priv->delay_ticks =  requested_ticks; /* save it for re-triggering */
++              ret_val = cpmac_p_start_timer(p_cpmac_priv->timer + TICK_TIMER, 
++                                            p_cpmac_priv->delay_ticks);
++            }
++      }
++        else if(cpmac_ci_strcmp(action, "Clear") == 0)
++        {
++            ret_val = cpmac_p_stop_timer(p_cpmac_priv->timer + TICK_TIMER);
++        }
++        else
++            ;
++    }
++    else if(cpmac_ci_strcmp(key, "MacAddr") == 0 && action != NULL)
++    {
++        if(cpmac_ci_strcmp(action, "Get") == 0 && value != NULL)
++      {
++            *(char **)value = p_cpmac_priv->mac_addr; 
++          ret_val = 0;
++      }
++    }
++    else if(cpmac_ci_strcmp(key, "CpuFreq") == 0)
++    {
++       if(cpmac_ci_strcmp(action, "Get") == 0 && value != NULL)
++       {
++           *(unsigned int *)value = cpmac_cpu_freq;
++           dbgPrint("Cpu frequency for cpmacs is %u\n",cpmac_cpu_freq);
++           ret_val = 0;
++       }
++    }
++    else if(cpmac_ci_strcmp(key, "SioFlush") == 0)
++    {
++       ret_val = 0;
++       dbgPrint("\n"); 
++    }
++    else if(cpmac_ci_strcmp(key, "CpmacFrequency") == 0)
++    {
++        /* For Sangam cpmac clock is off the PBUS */
++        /* OS Needs to supply CORRECT frequency */
++        if(cpmac_ci_strcmp(action, "Get") == 0 && value != NULL)
++        {
++            *(unsigned int *)value = avalanche_get_vbus_freq();
++            ret_val = 0;
++        }
++    }
++    /* For now, providing back the default values. */
++    else if(cpmac_ci_strcmp(key, "MdioClockFrequency") == 0)
++    {
++        if(cpmac_ci_strcmp(action, "Get") == 0 && value != NULL)
++        {
++            *(unsigned int *)value = 2200000;  /*DEFAULT */
++            ret_val = 0;
++        }
++    }
++    /* For now, providing back the default values. */
++    else if(cpmac_ci_strcmp(key, "MdioBusFrequency") == 0)
++    {
++        /* For Sangam MdioBusFreq is off the PBUS */
++        if(cpmac_ci_strcmp(action, "Get") == 0 && value != NULL)
++        {
++            *(unsigned int *)value = avalanche_get_vbus_freq();
++            ret_val = 0;
++        }
++    }
++  
++#if 0 
++#if defined(CONFIG_AVALANCHE_AUTO_MDIX) 
++    /* supporting Mdio Mdix switching */
++    else if(cpmac_ci_strcmp(key, hcMdioMdixSwitch) == 0)
++    {
++        /* For Sangam Mdio-switching  action should be always "set"*/
++        if(cpmac_ci_strcmp(action, hcSet) == 0 && value != NULL )
++        {
++           unsigned  int mdix =  *((unsigned int *) value) ;
++
++           if(mdix)
++              avalanche_set_phy_into_mdix_mode();
++
++           else
++              avalanche_set_phy_into_mdi_mode();  
++  
++           ret_val = 0;
++        } 
++
++    }
++#endif
++#endif
++    else if(cpmac_ci_strcmp(key, hcMdioMdixSwitch) == 0)
++    {
++        /* For Sangam Mdio-switching  action should be always "set"*/
++        if(cpmac_ci_strcmp(action, hcSet) == 0 && value != NULL )
++        {
++           unsigned  int mdix =  *((unsigned int *) value) ;
++
++           avalanche_set_mdix_on_chip(0xa8610000 , mdix ? 1: 0);
++  
++           ret_val = 0;
++        } 
++
++    }
++
++    return(ret_val);
++}
++
++
++int cpmac_hal_receive(OS_DEVICE *p_dev, FRAGLIST *fragList, 
++                             unsigned int fragCount,
++                             unsigned int packet_size, 
++                             HAL_RECEIVEINFO *hal_receive_info,
++                             unsigned int mode)
++{
++    CPMAC_PRIVATE_INFO_T *p_cpmac_priv  = p_dev->priv;
++    CPMAC_DRV_HAL_INFO_T *p_drv_hal     = p_cpmac_priv->drv_hal;
++    struct sk_buff       *p_skb         = fragList[0].OsInfo;
++    p_skb->len                          = fragList[0].len;    
++
++    /* invalidate the cache. */
++    dma_cache_inv((unsigned long)p_skb->data, fragList[0].len);    
++#ifdef CPMAC_TEST
++    xdump(p_skb->data, p_skb->len, "recv");
++#endif
++#ifdef CPMAC_8021Q_SUPPORT
++    /* 802.1q stuff, just does the basic checking here. */
++    if(!p_cpmac_priv->enable_802_1q      &&
++       p_skb->len > TCI_END_OFFSET       &&
++       IS_802_1Q_FRAME(p_skb->data + TPID_START_OFFSET))
++    {
++         goto cpmac_hal_recv_frame_mismatch;
++    }
++#endif
++    if(fragCount > 1)             
++    {     
++       int     len;
++       struct sk_buff *p_temp_skb;
++       CPMAC_RX_CHAN_INFO_T *p_rx_chan_info = p_cpmac_priv->rx_chan_info;
++       int     count;
++       
++       dbgPrint("Recv: It is multifragment for %s.\n", p_dev->name);
++       
++       p_skb = dev_alloc_skb(packet_size + 
++          p_rx_chan_info->chan->tot_reserve_bytes); 
++       if(p_skb == NULL) 
++       {
++          p_cpmac_priv->net_dev_stats.rx_errors++;
++          goto cpmac_hal_recv_alloc_failed;
++       }
++       
++       p_skb->dev = p_dev;
++       skb_reserve(p_skb, p_rx_chan_info->chan->tot_reserve_bytes);
++       
++       for(count = 0; count < fragCount; count++)
++       {
++          p_temp_skb = fragList[count].OsInfo;
++          len        = fragList[count].len;
++          
++          dma_cache_inv((unsigned long)p_temp_skb->data, len);
++          
++          memcpy(skb_put(p_skb, len), p_temp_skb->data, len);
++          dev_kfree_skb_any(p_temp_skb);
++       }
++    }
++    
++
++#if defined(CONFIG_MIPS_AVALANCHE_MARVELL)                                                                                                   
++ /* Fetch the receiving port information from EGRESS TRAILOR Bytes*/         
++     p_dev->if_port = (unsigned char)p_skb->data[packet_size -(EGRESS_TRAILOR_LEN-1)] + AVALANCHE_MARVELL_BASE_PORT_ID;
++    skb_trim(p_skb, packet_size - EGRESS_TRAILOR_LEN);                                                                       
++#else                                                                                                                        
++    /* set length & tail */                                                                                                  
++    skb_trim(p_skb, packet_size);                                                                                            
++#endif 
++ 
++#ifndef TI_SLOW_PATH
++    /* TI Optimization: This is NOT required if the ethernet resides below the bridge. But is
++    * required only if the ethernet is directly connected to the IP stack. */
++    if (p_dev->br_port == NULL)   
++#endif
++       p_skb->protocol = eth_type_trans(p_skb, p_dev);
++
++    netif_rx(p_skb);
++
++#if defined (CONFIG_MIPS_AVALANCHE_LED)
++    avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_RX_ACTIVITY);        
++#endif
++
++    p_cpmac_priv->net_dev_stats.rx_packets++;
++    p_cpmac_priv->net_dev_stats.rx_bytes += packet_size;
++
++    p_drv_hal->hal_funcs->RxReturn(hal_receive_info,1);
++
++    return(0);
++
++cpmac_hal_recv_alloc_failed:
++
++#ifdef CPMAC_8021Q_SUPPORT
++cpmac_hal_recv_frame_mismatch:
++#endif
++ 
++    fragCount--;
++
++    do
++    {
++        dev_kfree_skb_any(fragList[fragCount].OsInfo);
++    }
++    while(fragCount--);
++
++    p_cpmac_priv->net_dev_stats.rx_dropped++;
++
++    return(-1);
++} /*cpmac_receive*/
++
++
++void cpmac_hal_tear_down_complete(OS_DEVICE*a, int b, int ch)
++{
++    dbgPrint("what to do with this.\n");
++}
++
++
++int  cpmac_hal_send_complete(OS_SENDINFO *p_skb)
++{
++    CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_skb->dev->priv;
++
++    p_cpmac_priv->net_dev_stats.tx_packets++;
++    p_cpmac_priv->net_dev_stats.tx_bytes += p_skb->len;
++    
++    dev_kfree_skb_any(p_skb);
++
++    return(0);
++}
++
++
++int cpmac_reset(CPMAC_PRIVATE_INFO_T *p_cpmac_priv)
++{
++    // code here to reset the device/hal. Not now.
++
++   netif_wake_queue(p_cpmac_priv->owner);
++   return(0);
++}
++
++#ifdef CPMAC_TEST
++
++#define isprint(a) ((a >=' ')&&(a<= '~'))
++void xdump( u_char*  cp, int  length, char*  prefix )
++{
++    int col, count;
++    u_char prntBuf[120];
++    u_char*  pBuf = prntBuf;
++    count = 0;
++    while(count < length){
++        pBuf += sprintf( pBuf, "%s", prefix );
++        for(col = 0;count + col < length && col < 16; col++){
++            if (col != 0 && (col % 4) == 0)
++                pBuf += sprintf( pBuf, " " );
++            pBuf += sprintf( pBuf, "%02X ", cp[count + col] );
++        }
++        while(col++ < 16){      /* pad end of buffer with blanks */
++            if ((col % 4) == 0)
++                sprintf( pBuf, " " );
++            pBuf += sprintf( pBuf, "   " );
++        }
++        pBuf += sprintf( pBuf, "  " );
++        for(col = 0;count + col < length && col < 16; col++){
++            if (isprint((int)cp[count + col]))
++                pBuf += sprintf( pBuf, "%c", cp[count + col] );
++            else
++                pBuf += sprintf( pBuf, "." );
++                }
++        sprintf( pBuf, "\n" );
++        // SPrint(prntBuf);
++        printk(prntBuf);
++        count += col;
++        pBuf = prntBuf;
++    }
++
++}  /* close xdump(... */
++#endif
++
++
++static int __init cpmac_dev_probe(void)
++{
++    int     retVal         = 0;
++    int     unit;
++    int     instance_count = CONFIG_MIPS_CPMAC_PORTS;
++
++    //cpmac_cpu_freq = avalanche_clkc_get_freq(CLKC_MIPS);
++    cpmac_cpu_freq = tnetd73xx_clkc_get_freq(CLKC_MIPS);
++
++    build_psp_config();                       
++
++    for(unit = 0; unit < instance_count; unit++)
++    {
++        struct net_device             *p_dev;
++        CPMAC_PRIVATE_INFO_T            *p_cpmac_priv;
++        size_t                                dev_size;
++      int                             failed;
++
++        dev_size =    sizeof(struct net_device) 
++                  + sizeof(CPMAC_PRIVATE_INFO_T);
++
++
++        if((p_dev = (struct net_device *) kmalloc(dev_size, GFP_KERNEL)) == NULL)
++        {
++            dbgPrint( "Could not allocate memory for device.\n" );
++            retVal = -ENOMEM;
++            break;
++        }            
++               
++        memset(p_dev, 0, dev_size );
++
++        p_dev->priv                 = p_cpmac_priv
++                                    = (CPMAC_PRIVATE_INFO_T*)(((char *) p_dev) + sizeof(struct net_device));
++        p_cpmac_priv->owner         = p_dev;
++      
++        ether_setup(p_dev); 
++
++      p_cpmac_priv->instance_num  = unit;
++        p_dev->init                 = cpmac_dev_init;
++
++        g_dev_array[p_cpmac_priv->instance_num] = p_dev;
++        
++#if defined CONFIG_MIPS_CPMAC_INIT_BUF_MALLOC
++        g_init_enable_flag = 1;
++        printk("Cpmac driver is allocating buffer memory at init time.\n");
++#endif
++
++      /* This section gives a default value by the number of PHY in order to
++       * replace the default MACRO. */
++      {
++          char *mac_port = prom_getenv("MAC_PORT"); /* Internal: 0, External: 1 */
++          if(!mac_port || (0 != strcmp(mac_port, "0"))) {
++              printk("Using the MAC with external PHY\n");
++              cfg_start_link_speed = _CPMDIO_NOPHY;
++              cpmac_max_frame_size = CPMAC_MAX_FRAME_SIZE + 4;
++          }
++          else {
++              printk("Using the MAC with internal PHY\n");
++              cfg_start_link_speed = CFG_START_LINK_SPEED;
++              cpmac_max_frame_size = CPMAC_MAX_FRAME_SIZE;
++          }
++          g_cfg_start_link_params = cfg_start_link_speed;
++      }
++
++        cpmac_p_detect_manual_cfg(cfg_link_speed, cfg_link_mode, cpmac_debug_mode);
++
++      failed = register_netdev(p_dev);
++        if (failed)
++        {
++            dbgPrint("Could not register device for inst %d because of reason \
++                      code %d.\n", unit, failed);
++            retVal = -1;
++            kfree(p_dev);
++            break;
++        }           
++        else
++        {
++
++            char proc_name[100];
++            int  proc_category_name_len = 0;
++
++          p_cpmac_priv->next_device = last_cpmac_device;
++            last_cpmac_device         = p_dev;
++
++          dbgPrint(" %s irq=%2d io=%04x\n",p_dev->name, (int) p_dev->irq,
++                     (int) p_dev->base_addr);
++
++          strcpy(proc_name, "avalanche/");
++            strcat(proc_name, p_dev->name);
++            proc_category_name_len = strlen(proc_name);
++
++            strcpy(proc_name + proc_category_name_len, "_rfc2665_stats");
++            create_proc_read_entry(proc_name,0,NULL,cpmac_p_read_rfc2665_stats, p_dev);
++
++      }
++    }
++
++    if(retVal == 0)
++    {
++      /* To maintain backward compatibility with NSP. */
++        gp_stats_file = create_proc_entry("avalanche/cpmac_stats", 0644, NULL);
++        if(gp_stats_file)
++        {
++            gp_stats_file->read_proc  = cpmac_p_read_stats;
++            gp_stats_file->write_proc = cpmac_p_write_stats;
++        }
++      create_proc_read_entry("avalanche/cpmac_link", 0, NULL, cpmac_p_read_link, NULL);
++      create_proc_read_entry("avalanche/cpmac_ver", 0, NULL, cpmac_p_get_version, NULL);
++
++    }
++   
++    cpmac_devices_installed  = unit;
++    dbgPrint("Installed %d cpmac instances.\n", unit);
++    return ( (unit >= 0 ) ? 0 : -ENODEV );
++
++} /* init_module */
++
++
++/***************************************************************
++ *    cleanup_module
++ *
++ *    Returns:
++ *            Nothing
++ *    Parms:
++ *            None
++ *
++ *    Goes through the CpmacDevices list and frees the device
++ *    structs and memory associated with each device (lists
++ *    and buffers).  It also ureserves the IO port regions
++ *    associated with this device.
++ *
++ **************************************************************/
++
++void cpmac_exit(void)
++{
++    struct net_device       *p_dev;
++    CPMAC_PRIVATE_INFO_T    *p_cpmac_priv;
++
++    while (cpmac_devices_installed) 
++    {
++        char proc_name[100];
++        int  proc_category_name_len = 0;
++
++        p_dev = last_cpmac_device;
++        p_cpmac_priv = (CPMAC_PRIVATE_INFO_T *) p_dev->priv;
++
++      dbgPrint("Unloading %s irq=%2d io=%04x\n",p_dev->name, (int) p_dev->irq, (int) p_dev->base_addr);
++
++        if(g_init_enable_flag)
++            cpmac_p_dev_disable(p_dev);
++      
++        cpmac_drv_cleanup(p_cpmac_priv->drv_hal);
++
++#if defined (CONFIG_MIPS_AVALANCHE_LED)
++        avalanche_led_unregister(p_cpmac_priv->led_handle);
++#endif
++      strcpy(proc_name, "avalanche/");
++        strcat(proc_name, p_dev->name);
++        proc_category_name_len = strlen(proc_name);
++
++        strcpy(proc_name + proc_category_name_len, "_rfc2665_stats");
++        remove_proc_entry(proc_name, NULL);
++        
++        release_mem_region(p_dev->base_addr, p_cpmac_priv->dev_size);
++        unregister_netdev(p_dev);
++      last_cpmac_device = p_cpmac_priv->next_device;
++
++        kfree(p_cpmac_priv->drv_hal);
++        kfree(p_dev);
++     
++      cpmac_devices_installed--;
++    }
++
++    if(gp_stats_file)
++        remove_proc_entry("avalanche/cpmac_stats", NULL);
++
++    remove_proc_entry("avalanche/cpmac_link",  NULL);
++    remove_proc_entry("avalanche/cpmac_ver",   NULL);
++
++    psp_config_cleanup();
++}
++
++     
++module_init(cpmac_dev_probe);
++module_exit(cpmac_exit);
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/cpmac.h linux-2.4.30/drivers/net/avalanche_cpmac/cpmac.h
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/cpmac.h      1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/cpmac.h   2005-07-08 22:00:13.000000000 +0200
+@@ -0,0 +1,379 @@
++/******************************************************************************
++ * FILE PURPOSE:    CPMAC Linux Network Device Driver Header
++ ******************************************************************************
++ * FILE NAME:       cpmac.h
++ *
++ * DESCRIPTION:     CPMAC Network Device Driver Header
++ *
++ * REVISION HISTORY:
++ * Date            Name                   Details
++ *----------------------------------------------------------------------------- 
++ * 27 Nov 2002     Suraj S Iyer           Initial Create.
++ * 09 Jun 2003     Suraj S Iyer           Preparing for GA.
++ *
++ * (C) Copyright 2003, Texas Instruments, Inc
++ *******************************************************************************/
++
++#ifndef CPMAC_H
++#define CPMAC_H
++
++#include <linux/timer.h>
++#include <linux/netdevice.h>
++#include <asm/semaphore.h>
++#include <linux/ctype.h>
++#include <linux/interrupt.h>
++
++#include "cpmacHalLx.h"
++/*-----------------------------------------------------------------------------
++ * Config macros. Use these to config the driver.
++ *---------------------------------------------------------------------------*/
++#define CPMAC_MAX_FRAME_SIZE         1518
++
++#if defined(CONFIG_AR7WRD) || defined(CONFIG_AR7WI) || defined(CONFIG_AR7VWI)|| defined(CONFIG_AR7VW) 
++#define CFG_RX_NUM_BUF_DESC            64 
++#define CFG_RX_NUM_BUF_SERVICE         32 
++#else                                     
++#define CFG_RX_NUM_BUF_DESC            16 
++#define CFG_RX_NUM_BUF_SERVICE         8  
++#endif                                    
++
++#define CFG_RX_BUF_OFFSET              0
++
++#define CFG_TX_NUM_BUF_DESC            128
++#define CFG_TX_NUM_BUF_SERVICE         20 
++#define CFG_TX_BUF_OFFSET              0  /* Lets not change this. */
++#define CFG_TX_TIMEOUT                 2000 /* ticks*/
++#define CFG_TX_INT_DISABLE             1  /* Disable the Tx Complete interrupt */
++
++#define CFG_JUMBO_FRAMES               1
++#define CFG_SHORT_FRAMES               1
++#define CFG_PROMISCOUS                 1
++#define CFG_BROADCAST                  1
++#define CFG_MULTICAST                  1
++#define CFG_ALL_MULTI                  (1*(CFG_MULTICAST))
++#define CFG_AUTO_NEGOTIATION           1
++
++#if defined (CONFIG_MIPS_AVALANCHE_MARVELL)
++#define EGRESS_TRAILOR_LEN             4 
++#define CFG_START_LINK_SPEED           (_CPMDIO_NOPHY)
++#undef  CPMAC_MAX_FRAME_SIZE
++#define CPMAC_MAX_FRAME_SIZE          (1518 + EGRESS_TRAILOR_LEN)
++#else
++#define CFG_START_LINK_SPEED          (_CPMDIO_10 | _CPMDIO_100 | _CPMDIO_HD | _CPMDIO_FD) /* auto nego */
++#endif
++
++#define CFG_LOOP_BACK                  1
++#define CFG_TX_FLOW_CNTL               0
++#define CFG_RX_FLOW_CNTL               0
++#define CFG_TX_PACING                  0
++#define CFG_RX_PASS_CRC                0
++#define CFG_QOS_802_1Q                 0
++#define CFG_TX_NUM_CHAN                1
++
++
++/*-----------------------------------------------------------------------------
++ * Private macros.
++ *---------------------------------------------------------------------------*/
++#define MAX_TIMER               2
++#define TX_TIMER                0
++#define TICK_TIMER              0
++#define MAX_TX_CHAN             8
++
++#define CPMAC_LINK_OFF          0
++#define CPMAC_LINK_ON           1
++/*#define CPMAC_SPEED_100         2
++#define CPMAC_SPEED_10          3
++#define CPMAC_FULL_DPLX         4
++#define CPMAC_HALF_DPLX         5*/
++#define CPMAC_RX_ACTIVITY       2
++#define CPMAC_TX_ACTIVITY       3
++
++struct cpmac_timer_info;
++
++typedef int  (*CPMAC_HAL_ISR_FUNC_T)(HAL_DEVICE*, int*);
++typedef int  (*CPMAC_TIMEOUT_CB_T)(struct cpmac_timer_info*);
++
++typedef struct cpmac_ability_info
++{
++    int promiscous;
++    int broadcast;
++    int multicast;
++    int all_multi;
++    int loop_back;
++    int jumbo_frames;
++    int short_frames;
++    int auto_negotiation;
++    int tx_flow_control;
++    int rx_flow_control;
++    int tx_pacing;
++    int link_speed;
++    int rx_pass_crc;
++    int qos_802_1q;
++    int tx_num_chan;
++}
++CPMAC_ABILITY_INFO_T;
++
++#ifdef DEBUG
++typedef struct cpmac_timer_info
++{
++    void               *owner;
++    UINT32             delay_ticks;
++    WDOG_ID            timer_id;
++    UINT32             is_running;
++    UINT32             timer_set_at;
++    CPMAC_TIMEOUT_CB_T timeout_CB;
++} CPMAC_TIMER_INFO_T;
++
++typedef struct
++{
++    void               *owner;
++    unsigned int       num_cl_desc;
++    CL_DESC            *cl_desc_tbl;
++    M_CL_CONFIG        *m_cl_blk_config;
++    NET_POOL           *net_pool;
++    CL_POOL_ID         clPoolId;
++
++} CPMAC_NET_MEM_INFO_T;
++
++#endif
++
++typedef struct
++{
++    void                  *owner;
++    CPMAC_HAL_ISR_FUNC_T  hal_isr;
++    struct tasklet_struct tasklet;
++    int                   intr;
++
++} CPMAC_ISR_INFO_T;
++
++typedef struct cpmac_chan
++{
++   int num_BD;
++   int buffer_size;
++   int buffer_offset;
++   int service_max;
++   int state;
++   int tot_buf_size;
++   int tot_reserve_bytes;
++
++} CPMAC_CHAN_T;
++
++#define CHAN_CLOSE  0
++#define CHAN_OPENED 1
++
++typedef struct 
++{
++    int          cfg_chan;
++    int          dev_chan;
++    int          opened_chan;
++    CPMAC_CHAN_T chan[1];
++    int          enable_802_1q;
++
++} CPMAC_RX_CHAN_INFO_T;
++
++typedef struct
++{
++    int          cfg_chan;
++    int          dev_chan;
++    int          opened_chan;
++    int          tx_int_disable;
++    CPMAC_CHAN_T chan[MAX_TX_CHAN];
++   
++} CPMAC_TX_CHAN_INFO_T;
++
++
++
++typedef struct
++{
++   void                        *owner;
++   HAL_FUNCTIONS               *hal_funcs;
++   HAL_DEVICE                  *hal_dev;
++   OS_FUNCTIONS                *os_funcs; 
++//   SEM_ID                      chan_teardown_sem;
++   int                         non_data_irq_expected;
++} CPMAC_DRV_HAL_INFO_T;
++
++
++typedef struct
++{
++    unsigned long tx_discards;
++    unsigned long rx_discards;
++    unsigned long start_tick;
++
++} CPMAC_DRV_STATS_T;
++
++typedef struct 
++{
++    unsigned long   ifInGoodFrames;
++    unsigned long   ifInBroadcasts;
++    unsigned long   ifInMulticasts;
++    unsigned long   ifInPauseFrames;
++    unsigned long   ifInCRCErrors;
++    unsigned long   ifInAlignCodeErrors;
++    unsigned long   ifInOversizedFrames;
++    unsigned long   ifInJabberFrames;
++    unsigned long   ifInUndersizedFrames;
++    unsigned long   ifInFragments;
++    unsigned long   ifInFilteredFrames;
++    unsigned long   ifInQosFilteredFrames;
++    unsigned long   ifInOctets;
++    unsigned long   ifOutGoodFrames;
++    unsigned long   ifOutBroadcasts;
++    unsigned long   ifOutMulticasts;
++    unsigned long   ifOutPauseFrames;
++    unsigned long   ifDeferredTransmissions;
++    unsigned long   ifCollisionFrames;
++    unsigned long   ifSingleCollisionFrames;
++    unsigned long   ifMultipleCollisionFrames;
++    unsigned long   ifExcessiveCollisionFrames;
++    unsigned long   ifLateCollisions;
++    unsigned long   ifOutUnderrun;
++    unsigned long   ifCarrierSenseErrors;
++    unsigned long   ifOutOctets;
++    unsigned long   if64OctetFrames;
++    unsigned long   if65To127OctetFrames;
++    unsigned long   if128To255OctetFrames;
++    unsigned long   if256To511OctetFrames;
++    unsigned long   if512To1023OctetFrames;
++    unsigned long   if1024ToUPOctetFrames;
++    unsigned long   ifNetOctets;
++    unsigned long   ifRxSofOverruns;
++    unsigned long   ifRxMofOverruns;
++    unsigned long   ifRxDMAOverruns;
++
++} CPMAC_DEVICE_MIB_T;
++
++
++typedef struct
++{
++    void                         *owner;
++    int                          timer_count;
++    int                          timer_created;
++    struct timer_list            timer[1];
++    CPMAC_DRV_HAL_INFO_T         *drv_hal;
++    unsigned int                 num_of_intr;
++    CPMAC_ISR_INFO_T             cpmac_isr;
++    unsigned int                 link_speed;
++    unsigned int                 link_mode;
++    unsigned int                 enable_802_1q;
++    unsigned int                 timer_access_hal;
++    unsigned int                 loop_back;
++    CPMAC_RX_CHAN_INFO_T         *rx_chan_info;
++    CPMAC_TX_CHAN_INFO_T         *tx_chan_info;
++    CPMAC_ABILITY_INFO_T         *ability_info;
++    CPMAC_DEVICE_MIB_T           *device_mib;
++    CPMAC_DRV_STATS_T            *stats;
++    unsigned int                 flags;
++    unsigned int                 delay_ticks;
++    char                         mac_addr[6];
++    struct net_device_stats      net_dev_stats; 
++//    rwlock_t                     rw_lock;
++    int                          set_to_close;
++    struct net_device            *next_device;
++    unsigned int                 instance_num;
++    unsigned int                 non_data_irq_expected;
++    unsigned long                dev_size;
++    void*                        led_handle;
++} CPMAC_PRIVATE_INFO_T;
++
++
++/* Private flags */
++
++/* bit 0 to 31, bit 32 is used to indicate set or reset */
++
++#define IFF_PRIV_SHORT_FRAMES   0x00010000
++#define IFF_PRIV_JUMBO_FRAMES   0x00020000
++#define IFF_PRIV_AUTOSPEED      0x00080000
++#define IFF_PRIV_LINK10_HD      0x00100000
++#define IFF_PRIV_LINK10_FD      0x00200000
++#define IFF_PRIV_LINK100_HD     0x00400000
++#define IFF_PRIV_LINK100_FD     0x00800000
++#define IFF_PRIV_8021Q_EN       0x01000000
++#define IFF_PRIV_NUM_TX_CHAN    0x02000000
++#define IFF_PRIV_TX_FLOW_CNTL   0x04000000
++#define IFF_PRIV_RX_FLOW_CNTL   0x08000000
++#define IFF_PRIV_TX_PACING      0x10000000
++#define IFF_PRIV_RX_PASS_CRC    0x20000000
++
++#define PRIVCSFLAGS             0x200
++#define PRIVCGFLAGS             0x201
++
++
++#define BLOCKING      1
++#define CHAN_TEARDOWN 2
++#define CHAN_SETUP    4
++#define COMPLETE      8
++#define FREE_BUFFER   16
++
++
++static const char pszStats0[]            = "Stats0";
++static const char pszStats1[]            = "Stats1";
++static const char pszStats2[]            = "Stats2";
++static const char pszStats3[]            = "Stats3";
++static const char pszStats4[]            = "Stats4";
++static const char pszStatsDump[]         = "StatsDump";
++static const char pszStatsClear[]        = "StatsClear";
++static const char pszRX_PASS_CRC[]       = "RX_PASS_CRC";
++static const char pszRX_QOS_EN[]         = "RX_QOS_EN";
++static const char pszRX_NO_CHAIN[]       = "RX_NO_CHAIN";
++static const char pszRX_CMF_EN[]         = "RX_CMF_EN";
++static const char pszRX_CSF_EN[]         = "RX_CSF_EN";
++static const char pszRX_CEF_EN[]         = "RX_CEF_EN";
++static const char pszRX_CAF_EN[]         = "RX_CAF_EN";
++static const char pszRX_PROM_CH[]        = "RX_PROM_CH";
++static const char pszRX_BROAD_EN[]       = "RX_BROAD_EN";
++static const char pszRX_BROAD_CH[]       = "RX_BROAD_CH";
++static const char pszRX_MULT_EN[]        = "RX_MULT_EN";
++static const char pszRX_MULT_CH[]        = "RX_MULT_CH";
++static const char pszTX_PTYPE[]          = "TX_PTYPE";
++static const char pszTX_PACE[]           = "TX_PACE";
++static const char pszMII_EN[]            = "MII_EN";
++static const char pszTX_FLOW_EN[]        = "TX_FLOW_EN";
++static const char pszRX_FLOW_EN[]        = "RX_FLOW_EN";
++static const char pszRX_MAXLEN[]         = "RX_MAXLEN";
++static const char pszRX_FILTERLOWTHRESH[]   = "RX_FILTERLOWTHRESH";
++static const char pszRX0_FLOWTHRESH[]   = "RX0_FLOWTHRESH";
++static const char pszRX_UNICAST_SET[]    = "RX_UNICAST_SET";
++static const char pszRX_UNICAST_CLEAR[]  = "RX_UNICAST_CLEAR";
++static const char pszMdioConnect[]       = "MdioConnect";
++static const char pszMacAddr[]           = "MacAddr";
++static const char pszTick[]              = "Tick";
++static const char pszRX_MULTICAST[]      = "RX_MULTICAST";
++static const char pszRX_MULTI_ALL[]      = "RX_MULTI_ALL";
++static const char pszRX_MULTI_SINGLE[]   = "RX_MULTI_SINGLE";
++
++static const char pszSet[]               = "Set";
++static const char pszGet[]               = "Get";
++static const char pszClear[]             = "Clear";
++
++
++void *cpmac_hal_malloc_buffer(unsigned int size, void *MemBase, unsigned int MemRange,
++                              HAL_DEVICE *HalDev, HAL_RECEIVEINFO *HalReceiveInfo, 
++                              OS_RECEIVEINFO **OsReceiveInfo, OS_DEVICE *OsDev);
++
++void cpmac_hal_tear_down_complete(OS_DEVICE*, int, int);
++int  cpmac_hal_control(OS_DEVICE *p_END_obj, const char *key, 
++                   const char *action, void *value);
++int  cpmac_hal_receive(OS_DEVICE *p_END_obj, FRAGLIST *fragList, 
++               unsigned int FragCount, unsigned int pkt_len, 
++               HAL_RECEIVEINFO *halReceiveInfo, 
++               unsigned int mode);
++int  cpmac_hal_send_complete(OS_SENDINFO*);
++
++void  cpmac_hal_isr(int irq, void *p_param, struct pt_regs *p_cb_param);
++void  cpmac_handle_tasklet(unsigned long data);
++
++inline static int cpmac_ci_strcmp(const char *s1, const char *s2)
++{
++    while(*s1 && *s2)
++    {
++        if(tolower(*s1) != tolower(*s2))
++            break;
++        s1++;
++        s2++;
++    }
++
++    return(tolower(*s1) - tolower(*s2));
++}
++
++#endif
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/cpmacHalLx.c linux-2.4.30/drivers/net/avalanche_cpmac/cpmacHalLx.c
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/cpmacHalLx.c 1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/cpmacHalLx.c      2005-04-15 05:10:41.000000000 +0200
+@@ -0,0 +1,492 @@
++/******************************************************************************
++ * FILE PURPOSE:    CPMAC Net Driver HAL support Source
++ ******************************************************************************
++ * FILE NAME:       cpmacHalLx.c
++ *
++ * DESCRIPTION:     CPMAC Network Device Driver Source
++ *
++ * REVISION HISTORY:
++ *
++ * Date           Description                               Author
++ *-----------------------------------------------------------------------------
++ * 27 Nov 2002    Initial Creation                          Suraj S Iyer  
++ * 09 Jun 2003    Updates for GA                            Suraj S Iyer
++ * 18 Dec 2003    Updated for 5.7                           Suraj S Iyer
++ *
++ * (C) Copyright 2003, Texas Instruments, Inc
++ *******************************************************************************/
++#include <linux/kernel.h> 
++#include <linux/module.h> 
++#include <linux/init.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/delay.h>     
++#include <linux/spinlock.h>
++#include <linux/proc_fs.h>
++#include <asm/io.h>
++#include <linux/string.h>
++
++#include "cpmacHalLx.h"
++#include "cpmac.h"
++
++/* PSP config headers */
++#include "psp_config_parse.h"
++#include "psp_config_mgr.h"
++
++/* Probe Debug Section*/
++
++/* debug */                                 
++extern int cpmac_debug_mode;
++#define dbgPrint if (cpmac_debug_mode) printk
++#define errPrint printk
++
++char CpmacSignature[] = "Cpmac driver";
++static unsigned long irq_flags = 0;
++OS_SETUP *p_os_setup = NULL;
++
++extern int avalanche_request_intr_pacing(int, unsigned int, unsigned int);
++extern int avalanche_free_intr_pacing(unsigned int blk_num);
++
++/*----------------------------------------------------------------------------
++ * Parameter extracting functionalities.
++ *--------------------------------------------------------------------------*/
++static int os_find_parm_u_int(void *info_ptr, const char *param, unsigned int *val)
++{
++    int ret_val = 0;
++
++    if((ret_val = psp_config_get_param_uint(info_ptr, param, val)) == -1)
++    {
++        dbgPrint("Error: could not locate the requested \"%s\" param.\n",param);
++        ret_val = -1;
++    }
++
++    return(ret_val);
++}
++
++static int os_find_parm_val(void *info_ptr, const char *param, void *val)
++{
++    int ret_val = 0;
++
++    if(psp_config_get_param_string(info_ptr, param, val) == -1)
++    {
++        dbgPrint("Error: could not locate the requested \"%s\" param.\n",param);
++        ret_val = -1;
++    }
++
++    return(ret_val);
++}
++
++static int os_find_device(int unit, const char *find_name, void *device_info)
++{
++    int ret_val = 0;
++
++    if(psp_config_get((char *)find_name, unit, device_info) == -1)
++    {
++        dbgPrint("Error: could not locate the requested \"%s\" param.\n", find_name);
++        ret_val = -1;
++    }
++
++    return(ret_val);
++}
++
++/*---------------------------------------------------------------------------
++ * Memory related OS abstraction.
++ *--------------------------------------------------------------------------*/
++void os_free(void *mem_ptr)
++{
++    kfree(mem_ptr);
++}
++
++void  os_free_buffer(OS_RECEIVEINFO *osReceiveInfo, void *mem_ptr)
++{
++    dev_kfree_skb_any(osReceiveInfo);
++}
++
++void  os_free_dev(void *mem_ptr)
++{
++    kfree(mem_ptr);
++}
++
++void os_free_dma_xfer(void *mem_ptr)
++{
++    kfree(mem_ptr);
++}
++
++static void *os_malloc(unsigned int size)
++{
++    return(kmalloc(size, GFP_KERNEL));
++}
++
++static void *os_malloc_dma_xfer(unsigned int size, 
++                                void         *mem_base, 
++                                unsigned int mem_range)
++{
++    return(kmalloc(size, GFP_KERNEL));
++}
++
++static void *os_malloc_dev(unsigned int size)
++{
++    return(kmalloc(size, GFP_KERNEL));
++}
++
++
++/*----------------------------------------------------------------------------
++ * CRITICAL SECTION ENABLING/DISABLING.
++ *--------------------------------------------------------------------------*/
++static void os_critical_on(void)
++{
++    save_and_cli(irq_flags);
++}
++
++static void os_critical_off(void)
++{
++    restore_flags(irq_flags);
++}
++
++/*----------------------------------------------------------------------------
++ * Cache related abstraction
++ *--------------------------------------------------------------------------*/
++static void os_cache_invalidate(void *mem_ptr, int size)
++{
++    dma_cache_inv((unsigned long)mem_ptr, size);
++}
++
++static void os_cache_writeback(void *mem_ptr, int size)
++{
++    dma_cache_wback_inv((unsigned long)mem_ptr, size);
++}
++
++/*-----------------------------------------------------------------------------
++ * Support functions.
++ *---------------------------------------------------------------------------*/
++
++static void  hal_drv_unregister_isr(OS_DEVICE *p_dev, int intr)
++{
++    CPMAC_PRIVATE_INFO_T *p_cpmac_priv   = p_dev->priv;
++    CPMAC_ISR_INFO_T     *p_isr_cb_param = &p_cpmac_priv->cpmac_isr;
++    intr                                 = LNXINTNUM(intr);
++
++    free_irq(p_isr_cb_param->intr, p_isr_cb_param);
++
++    dbgPrint("cpmac_hal_unregister called for the intr %d for unit %x and isr_cb_param %x.\n", 
++             intr, p_cpmac_priv->instance_num, (unsigned int )&p_cpmac_priv->cpmac_isr);
++}
++
++
++static void hal_drv_register_isr(OS_DEVICE *p_dev, 
++                                 CPMAC_HAL_ISR_FUNC_T hal_isr, int intr)
++{
++    CPMAC_PRIVATE_INFO_T *p_cpmac_priv   = p_dev->priv;
++    CPMAC_DRV_HAL_INFO_T *p_drv_hal      = p_cpmac_priv->drv_hal;
++    CPMAC_ISR_INFO_T     *p_isr_cb_param = &p_cpmac_priv->cpmac_isr;
++    intr                                 = LNXINTNUM(intr);
++       
++    dbgPrint("osRegister called for the intr %d for device %x and p_isr_cb_param %x.\n", 
++             intr, (bit32u)p_dev, (bit32u)p_isr_cb_param);
++
++    p_isr_cb_param->owner       = p_drv_hal;
++    p_isr_cb_param->hal_isr     = hal_isr;
++    p_isr_cb_param->intr        = intr;
++
++    tasklet_init(&p_isr_cb_param->tasklet, cpmac_handle_tasklet, (unsigned long)p_isr_cb_param);
++    dbgPrint("Success in registering irq %d for Cpmac unit# %d.\n", intr, p_cpmac_priv->instance_num); 
++}
++
++/*---------------------------------------------------------------------------
++ * FUNCTIONS called by the CPMAC Net Device.
++ *-------------------------------------------------------------------------*/
++static int load_os_funcs(OS_FUNCTIONS *os_func)
++{
++    dbgPrint("os_init_module: Start\n"); 
++    if( os_func == 0 )
++    {
++        return(sizeof(OS_FUNCTIONS));   
++    }
++
++    os_func->Control                    = cpmac_hal_control;
++    os_func->CriticalOn                 = os_critical_on;
++    os_func->CriticalOff                = os_critical_off;
++    os_func->DataCacheHitInvalidate     = os_cache_invalidate;
++    os_func->DataCacheHitWriteback      = os_cache_writeback;       
++    os_func->DeviceFindInfo     = os_find_device;
++    os_func->DeviceFindParmUint = os_find_parm_u_int;
++    os_func->DeviceFindParmValue= os_find_parm_val;
++    os_func->Free               = os_free;
++    os_func->FreeRxBuffer       = os_free_buffer;
++    os_func->FreeDev            = os_free_dev;
++    os_func->FreeDmaXfer        = os_free_dma_xfer;
++    os_func->IsrRegister        = hal_drv_register_isr;
++    os_func->IsrUnRegister      = hal_drv_unregister_isr;
++    os_func->Malloc             = os_malloc;
++    os_func->MallocDev          = os_malloc_dev;
++    os_func->MallocDmaXfer      = os_malloc_dma_xfer;
++    os_func->MallocRxBuffer     = cpmac_hal_malloc_buffer;
++    os_func->Memset             = memset;
++    os_func->Printf             = printk;
++    os_func->Receive            = cpmac_hal_receive;
++    os_func->SendComplete       = cpmac_hal_send_complete;
++    os_func->Strcmpi            = cpmac_ci_strcmp;
++    os_func->TeardownComplete   = cpmac_hal_tear_down_complete;
++    os_func->Strstr             = strstr;
++    os_func->Strtoul            = simple_strtol;
++    os_func->Sprintf            = sprintf;
++    os_func->Strlen             = strlen;
++
++    dbgPrint("os_init_module: Leave\n");             
++  
++    return(0);
++}
++
++
++int cpmac_drv_init(CPMAC_DRV_HAL_INFO_T *p_drv_hal)
++{
++    HAL_DEVICE       *p_hal_dev    = p_drv_hal->hal_dev;
++    HAL_FUNCTIONS    *p_hal_funcs  = p_drv_hal->hal_funcs;
++
++    return(p_hal_funcs->Init(p_hal_dev));
++}
++
++int cpmac_drv_cleanup(CPMAC_DRV_HAL_INFO_T *p_drv_hal)
++{
++    HAL_DEVICE       *p_hal_dev    = p_drv_hal->hal_dev;
++    HAL_FUNCTIONS    *p_hal_funcs  = p_drv_hal->hal_funcs;
++
++    int              ret_val       = p_hal_funcs->Shutdown(p_hal_dev);
++
++#if 0
++    if(ret_val == 0)
++        kfree(p_hal_funcs);
++    else
++        ret_val = -1;
++#endif
++
++    kfree(p_drv_hal->os_funcs); 
++    
++    return (ret_val); 
++}
++
++int cpmac_drv_tx_setup(HAL_FUNCTIONS        *p_hal_funcs,
++                       HAL_DEVICE           *p_hal_dev,
++                       CPMAC_TX_CHAN_INFO_T *p_tx_chan_info)
++{
++    int ret_val = 0;
++    int count   = 0;
++    CHANNEL_INFO chan_info;
++
++    /* Let's setup the TX Channels. */
++    for(count=0; count < p_tx_chan_info->cfg_chan; count++)
++    {
++        chan_info.Channel        = count;
++        chan_info.Direction      = DIRECTION_TX;       
++        chan_info.TxNumBuffers   = p_tx_chan_info->chan[count].num_BD;
++        chan_info.TxServiceMax   = p_tx_chan_info->chan[count].service_max;
++        chan_info.TxNumQueues    = 0;
++        
++        if((ret_val = p_hal_funcs->ChannelSetup(p_hal_dev, &chan_info,
++                                                NULL)) != 0)
++        {
++            errPrint("Error in opening channel %d for TX.\n", count);
++            ret_val = -1;
++            break;
++        }
++
++        p_tx_chan_info->opened_chan++;
++    }
++
++    return(ret_val);
++}
++
++int cpmac_drv_rx_setup(HAL_FUNCTIONS         *p_hal_funcs,
++                       HAL_DEVICE            *p_hal_dev,
++                       CPMAC_RX_CHAN_INFO_T  *p_rx_chan_info)
++{
++    int ret_val = 0;
++    CHANNEL_INFO chan_info;
++
++    chan_info.Channel       = 0;
++    chan_info.Direction     = DIRECTION_RX;
++    chan_info.RxBufSize     = p_rx_chan_info->chan[0].buffer_size;
++    chan_info.RxBufferOffset= p_rx_chan_info->chan[0].buffer_offset;
++    chan_info.RxNumBuffers  = p_rx_chan_info->chan[0].num_BD;
++    chan_info.RxServiceMax  = p_rx_chan_info->chan[0].service_max;
++
++    if(p_hal_funcs->ChannelSetup(p_hal_dev, &chan_info, p_rx_chan_info) != 0) 
++    {
++        errPrint("Error in opening channel %d for RX.\n", 0);
++        ret_val = -1;
++    }
++
++    return(ret_val);
++}
++
++int cpmac_drv_start(CPMAC_DRV_HAL_INFO_T *p_drv_hal,
++                    CPMAC_TX_CHAN_INFO_T *p_tx_chan_info,
++                    CPMAC_RX_CHAN_INFO_T *p_rx_chan_info,
++                    unsigned int         flags)
++{
++    int ret_val = 0;
++    HAL_FUNCTIONS *p_hal_funcs = p_drv_hal->hal_funcs;
++    HAL_DEVICE    *p_hal_dev   = p_drv_hal->hal_dev;
++
++    dbgPrint("It is in cpmac_drv_start for %x.\n", (unsigned int)p_drv_hal);
++
++    if(flags & CHAN_SETUP)
++    {
++        if(cpmac_drv_tx_setup(p_hal_funcs, p_hal_dev, 
++                  p_tx_chan_info)!=0)
++        {
++            errPrint("Failed to set up tx channel(s).\n");
++            ret_val = -1;
++        }
++        else if(cpmac_drv_rx_setup(p_hal_funcs, p_hal_dev,
++                                   p_rx_chan_info)!=0)
++        {
++            errPrint("Failed to set up rx channel.\n");
++            ret_val = -1;
++        }
++        else
++        {
++            ret_val = 0;
++        }
++    }
++
++    /* Error in setting up the Channels, quit. */
++    if((ret_val == 0) && (ret_val = p_hal_funcs->Open(p_hal_dev)) != 0)
++    {
++        errPrint("failed to open the HAL!!!.\n");
++        ret_val = -1;
++    }
++
++    return (ret_val);
++} /* cpmac_drv_start */
++
++
++
++int cpmac_drv_tx_teardown(HAL_FUNCTIONS        *p_hal_funcs,
++                          HAL_DEVICE           *p_hal_dev,
++                          CPMAC_TX_CHAN_INFO_T *p_tx_chan_info,
++                          unsigned int         flags)
++{
++    int ret_val = 0;
++    int count   = 0;
++
++    /* Let's setup the TX Channels. */
++    for(;  p_tx_chan_info->opened_chan > 0; 
++        p_tx_chan_info->opened_chan--, count++)
++    {
++        if(p_hal_funcs->ChannelTeardown(p_hal_dev, count, flags) != 0)
++        {
++            errPrint("Error in tearing down channel %d for TX.\n", count);
++            ret_val = -1;
++            break;
++        }
++    }
++
++    return(ret_val);
++}
++
++
++int cpmac_drv_rx_teardown(HAL_FUNCTIONS *p_hal_funcs,
++                  HAL_DEVICE    *p_hal_dev,
++              unsigned int  flags)
++{
++    int ret_val = 0;
++
++    if(p_hal_funcs->ChannelTeardown(p_hal_dev, 0, flags) != 0) 
++    {
++        errPrint("Error in tearing down channel %d for RX.\n", 0);
++        ret_val = -1;
++    }
++
++    return(ret_val);
++}
++
++int cpmac_drv_stop(CPMAC_DRV_HAL_INFO_T    *p_drv_hal,
++                   CPMAC_TX_CHAN_INFO_T    *p_tx_chan_info,
++                   CPMAC_RX_CHAN_INFO_T    *p_rx_chan_info,
++                   unsigned int flags)
++{
++    HAL_DEVICE       *p_hal_dev    = p_drv_hal->hal_dev;
++    HAL_FUNCTIONS    *p_hal_funcs  = p_drv_hal->hal_funcs;
++    int ret_val                    = 0;
++
++    if(flags & CHAN_TEARDOWN)
++    {
++        unsigned int chan_flags = 0;
++
++        if(flags & FREE_BUFFER) chan_flags |= 0x4; /* full tear down */
++        if(flags & BLOCKING)    chan_flags |= 0x8; /* blocking call  */
++
++        dbgPrint("The teardown flags are %d.\n", flags);
++        dbgPrint("The teardown chan flags are %d.\n", chan_flags);
++
++        if(cpmac_drv_tx_teardown(p_hal_funcs, p_hal_dev, 
++                                 p_tx_chan_info, chan_flags | 0x1) != 0)
++        {
++            ret_val = -1;
++            errPrint("The tx channel teardown failed.\n");
++        }
++        else if(cpmac_drv_rx_teardown(p_hal_funcs, p_hal_dev, chan_flags | 0x2) != 0)
++        {
++            ret_val = -1;
++            errPrint("The rx channel teardown failed.\n");
++        }
++        else
++        {
++            ;
++        }
++    }
++
++    if(ret_val == 0)
++    {
++        int close_flags = 1;
++
++        if(flags & FREE_BUFFER)  close_flags = 2;
++//        if(flags & COMPLETE)     close_flags = 3;
++
++        if(p_hal_funcs->Close(p_hal_dev, close_flags) != 0)
++        {
++            ret_val = -1;
++        }
++    }
++        
++    return(ret_val);
++}
++
++int cpmac_drv_init_module(CPMAC_DRV_HAL_INFO_T *p_drv_hal, OS_DEVICE *p_os_dev, int inst)
++{
++    int ret_val = -1;
++    int hal_func_size;
++
++    dbgPrint("Entering the CpmacInitModule for the inst %d \n", inst);
++
++    if((p_drv_hal->os_funcs = kmalloc(sizeof(OS_FUNCTIONS), GFP_KERNEL)) == NULL)
++    {
++        errPrint("Failed to allocate memory for OS_FUNCTIONS.\n");
++    }
++    else if(load_os_funcs(p_drv_hal->os_funcs) != 0)
++    {
++        errPrint("Failed to load OS funcs.\n");
++        os_free(p_drv_hal->os_funcs);
++    }
++    else if(halCpmacInitModule(&p_drv_hal->hal_dev, p_os_dev,
++                               &p_drv_hal->hal_funcs, p_drv_hal->os_funcs, 
++                               sizeof(*p_drv_hal->os_funcs),
++                               &hal_func_size, inst) != 0)
++    {
++        errPrint("halCpmacInitModule failed for inst %d \n", inst);
++        os_free(p_drv_hal->os_funcs);
++    }
++    else if(p_drv_hal->hal_funcs->Probe(p_drv_hal->hal_dev) != 0)
++    {
++        errPrint("halCpmacProbe failed for inst %d \n", inst);       
++        os_free(p_drv_hal->os_funcs);
++    }
++    else
++    {
++        /* every thing went well. */
++        ret_val = 0;
++    }  
++
++    return (ret_val);  
++}
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/cpmacHalLx.h linux-2.4.30/drivers/net/avalanche_cpmac/cpmacHalLx.h
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/cpmacHalLx.h 1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/cpmacHalLx.h      2005-07-08 22:00:13.000000000 +0200
+@@ -0,0 +1,51 @@
++/******************************************************************************
++ * FILE PURPOSE:    CPMAC Linux Device Driver HAL support Header
++ ******************************************************************************
++ * FILE NAME:       cpmacHalVx.h
++ *
++ * DESCRIPTION:     CPMAC Linux Device Driver Header
++ *
++ * REVISION HISTORY:
++ *
++ * Date           Description                               Author
++ *-----------------------------------------------------------------------------
++ * 27 Nov 2002    Initial Creation                          Suraj S Iyer  
++ * 09 Jun 2003    Updates for GA                            Suraj S Iyer
++ * 
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++
++#ifndef __CPMAC_HAL_LX_H
++#define __CPMAC_HAL_LX_H
++
++
++typedef struct net_device         OS_DEVICE;
++typedef struct sk_buff            OS_RECEIVEINFO;
++typedef struct sk_buff            OS_SENDINFO;
++
++#ifdef DEBUG
++typedef void                      HAL_RECEIVEINFO;
++typedef void                      HAL_DEVICE;
++typedef void                      OS_SETUP;
++#endif
++
++#define OS_SETUP   void
++#define HAL_DEVICE void
++#define HAL_RECEIVEINFO void
++
++#define _CPHAL_CPMAC
++ 
++#include "cpswhal_cpmac.h"
++#include "cpmac.h"
++
++int cpmac_drv_start(CPMAC_DRV_HAL_INFO_T *, CPMAC_TX_CHAN_INFO_T*,
++                    CPMAC_RX_CHAN_INFO_T *, unsigned int);
++int cpmac_drv_cleanup(CPMAC_DRV_HAL_INFO_T *);
++int cpmac_drv_init(CPMAC_DRV_HAL_INFO_T*);
++int cpmac_drv_close(CPMAC_DRV_HAL_INFO_T*);
++int cpmac_drv_open(CPMAC_DRV_HAL_INFO_T*);
++int cpmac_drv_init_module(CPMAC_DRV_HAL_INFO_T*, OS_DEVICE*, int);
++int cpmac_drv_stop(CPMAC_DRV_HAL_INFO_T *p_drv_hal,CPMAC_TX_CHAN_INFO_T *p_tx_chan_info,
++                   CPMAC_RX_CHAN_INFO_T *p_rx_chan_info,unsigned int flags);
++
++#endif
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/cpmac_reg.h linux-2.4.30/drivers/net/avalanche_cpmac/cpmac_reg.h
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/cpmac_reg.h  1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/cpmac_reg.h       2005-07-08 22:08:52.149427385 +0200
+@@ -0,0 +1,406 @@
++/****************************************************************************
++        TNETD73xx Software Support
++        Copyright(c) 2000, Texas Instruments Incorporated. All Rights Reserved.
++
++        FILE: cpmac_reg.h   Register definitions for the CPMAC module
++
++         DESCRIPTION:
++                This include file contains register definitions for the
++                CPMAC module.
++
++         HISTORY:
++              15Nov00 BEGR Original version written
++              30May02 MICK Added bits for Int Vector
++              19Sep02 MICK Added INT_ACK per Channel
++              08Nov02 GDUN Updated to use base
++              12Nov02 MICK Incorporated into CPHAL 
++*****************************************************************************/
++#ifndef _INC_CPMAC_REG
++#define _INC_CPMAC_REG
++
++#ifndef MEM_PTR
++#define MEM_PTR volatile bit32u *
++#endif
++
++/***************************************************************************
++ *                                                                         
++ *         C P M A C  M E M O R Y  M A P 
++ *                                                                         
++ **************************************************************************/
++
++#define pCPMAC_TX_IDVER(base)                 ((MEM_PTR)(base+0x000))
++#define  CPMAC_TX_IDVER(base)                 (*pCPMAC_TX_IDVER(base))
++#define pCPMAC_TX_CONTROL(base)               ((MEM_PTR)(base+0x004))
++#define  CPMAC_TX_CONTROL(base)               (*pCPMAC_TX_CONTROL(base))
++#define pCPMAC_TX_TEARDOWN(base)              ((MEM_PTR)(base+0x008))
++#define  CPMAC_TX_TEARDOWN(base)              (*pCPMAC_TX_TEARDOWN(base))
++#define pCPMAC_RX_IDVER(base)                 ((MEM_PTR)(base+0x010))
++#define  CPMAC_RX_IDVER(base)                 (*pCPMAC_RX_IDVER(base))
++#define pCPMAC_RX_CONTROL(base)               ((MEM_PTR)(base+0x014))
++#define  CPMAC_RX_CONTROL(base)               (*pCPMAC_RX_CONTROL(base))
++#define pCPMAC_RX_TEARDOWN(base)              ((MEM_PTR)(base+0x018))
++#define  CPMAC_RX_TEARDOWN(base)              (*pCPMAC_RX_TEARDOWN(base))
++#define pCPMAC_RX_MBP_ENABLE(base)            ((MEM_PTR)(base+0x100))
++#define  CPMAC_RX_MBP_ENABLE(base)            (*pCPMAC_RX_MBP_ENABLE(base))
++#define pCPMAC_RX_UNICAST_SET(base)           ((MEM_PTR)(base+0x104))
++#define  CPMAC_RX_UNICAST_SET(base)           (*pCPMAC_RX_UNICAST_SET(base))
++#define pCPMAC_RX_UNICAST_CLEAR(base)         ((MEM_PTR)(base+0x108))
++#define  CPMAC_RX_UNICAST_CLEAR(base)         (*pCPMAC_RX_UNICAST_CLEAR(base))
++#define pCPMAC_RX_MAXLEN(base)                ((MEM_PTR)(base+0x10C))
++#define  CPMAC_RX_MAXLEN(base)                (*pCPMAC_RX_MAXLEN(base))
++#define pCPMAC_RX_BUFFER_OFFSET(base)         ((MEM_PTR)(base+0x110))
++#define  CPMAC_RX_BUFFER_OFFSET(base)         (*pCPMAC_RX_BUFFER_OFFSET(base))
++#define pCPMAC_RX_FILTERLOWTHRESH(base)       ((MEM_PTR)(base+0x114))
++#define  CPMAC_RX_FILTERLOWTHRESH(base)       (*pCPMAC_RX_FILTERLOWTHRESH(base))
++#define pCPMAC_RX0_FLOWTHRESH(base)           ((MEM_PTR)(base+0x120))
++#define  CPMAC_RX0_FLOWTHRESH(base)           (*pCPMAC_RX0_FLOWTHRESH(base))
++#define pCPMAC_RX1_FLOWTHRESH(base)           ((MEM_PTR)(base+0x124))
++#define  CPMAC_RX1_FLOWTHRESH(base)           (*pCPMAC_RX1_FLOWTHRESH(base))
++#define pCPMAC_RX2_FLOWTHRESH(base)           ((MEM_PTR)(base+0x128))
++#define  CPMAC_RX2_FLOWTHRESH(base)           (*pCPMAC_RX2_FLOWTHRESH(base))
++#define pCPMAC_RX3_FLOWTHRESH(base)           ((MEM_PTR)(base+0x12C))
++#define  CPMAC_RX3_FLOWTHRESH(base)           (*pCPMAC_RX3_FLOWTHRESH(base))
++#define pCPMAC_RX4_FLOWTHRESH(base)           ((MEM_PTR)(base+0x130))
++#define  CPMAC_RX4_FLOWTHRESH(base)           (*pCPMAC_RX4_FLOWTHRESH(base))
++#define pCPMAC_RX5_FLOWTHRESH(base)           ((MEM_PTR)(base+0x134))
++#define  CPMAC_RX5_FLOWTHRESH(base)           (*pCPMAC_RX5_FLOWTHRESH(base))
++#define pCPMAC_RX6_FLOWTHRESH(base)           ((MEM_PTR)(base+0x138))
++#define  CPMAC_RX6_FLOWTHRESH(base)           (*pCPMAC_RX6_FLOWTHRESH(base))
++#define pCPMAC_RX7_FLOWTHRESH(base)           ((MEM_PTR)(base+0x13C))
++#define  CPMAC_RX7_FLOWTHRESH(base)           (*pCPMAC_RX7_FLOWTHRESH(base))
++#define pCPMAC_RX0_FREEBUFFER(base)           ((MEM_PTR)(base+0x140))
++#define  CPMAC_RX0_FREEBUFFER(base)           (*pCPMAC_RX0_FREEBUFFER(base))
++#define pCPMAC_RX1_FREEBUFFER(base)           ((MEM_PTR)(base+0x144))
++#define  CPMAC_RX1_FREEBUFFER(base)           (*pCPMAC_RX1_FREEBUFFER(base))
++#define pCPMAC_RX2_FREEBUFFER(base)           ((MEM_PTR)(base+0x148))
++#define  CPMAC_RX2_FREEBUFFER(base)           (*pCPMAC_RX2_FREEBUFFER(base))
++#define pCPMAC_RX3_FREEBUFFER(base)           ((MEM_PTR)(base+0x14C))
++#define  CPMAC_RX3_FREEBUFFER(base)           (*pCPMAC_RX3_FREEBUFFER(base))
++#define pCPMAC_RX4_FREEBUFFER(base)           ((MEM_PTR)(base+0x150))
++#define  CPMAC_RX4_FREEBUFFER(base)           (*pCPMAC_RX4_FREEBUFFER(base))
++#define pCPMAC_RX5_FREEBUFFER(base)           ((MEM_PTR)(base+0x154))
++#define  CPMAC_RX5_FREEBUFFER(base)           (*pCPMAC_RX5_FREEBUFFER(base))
++#define pCPMAC_RX6_FREEBUFFER(base)           ((MEM_PTR)(base+0x158))
++#define  CPMAC_RX6_FREEBUFFER(base)           (*pCPMAC_RX6_FREEBUFFER(base))
++#define pCPMAC_RX7_FREEBUFFER(base)           ((MEM_PTR)(base+0x15C))
++#define  CPMAC_RX7_FREEBUFFER(base)           (*pCPMAC_RX7_FREEBUFFER(base))
++#define pCPMAC_MACCONTROL(base)               ((MEM_PTR)(base+0x160))
++#define  CPMAC_MACCONTROL(base)               (*pCPMAC_MACCONTROL(base))
++#define pCPMAC_MACSTATUS(base)                ((MEM_PTR)(base+0x164))
++#define  CPMAC_MACSTATUS(base)                (*pCPMAC_MACSTATUS(base))
++#define pCPMAC_EMCONTROL(base)                ((MEM_PTR)(base+0x168))
++#define  CPMAC_EMCONTROL(base)                (*pCPMAC_EMCONTROL(base))
++#define pCPMAC_TX_INTSTAT_RAW(base)           ((MEM_PTR)(base+0x170))
++#define  CPMAC_TX_INTSTAT_RAW(base)           (*pCPMAC_TX_INTSTAT_RAW(base))
++#define pCPMAC_TX_INTSTAT_MASKED(base)        ((MEM_PTR)(base+0x174))
++#define  CPMAC_TX_INTSTAT_MASKED(base)        (*pCPMAC_TX_INTSTAT_MASKED(base))
++#define pCPMAC_TX_INTMASK_SET(base)           ((MEM_PTR)(base+0x178))
++#define  CPMAC_TX_INTMASK_SET(base)           (*pCPMAC_TX_INTMASK_SET(base))
++#define pCPMAC_TX_INTMASK_CLEAR(base)         ((MEM_PTR)(base+0x17C))
++#define  CPMAC_TX_INTMASK_CLEAR(base)         (*pCPMAC_TX_INTMASK_CLEAR(base))
++#define pCPMAC_MAC_IN_VECTOR(base)            ((MEM_PTR)(base+0x180))
++#define  CPMAC_MAC_IN_VECTOR(base)            (*pCPMAC_MAC_IN_VECTOR(base))
++#define pCPMAC_MAC_EOI_VECTOR(base)           ((MEM_PTR)(base+0x184))
++#define  CPMAC_MAC_EOI_VECTOR(base)           (*pCPMAC_MAC_EOI_VECTOR(base))
++#define pCPMAC_RX_INTSTAT_RAW(base)           ((MEM_PTR)(base+0x190))
++#define  CPMAC_RX_INTSTAT_RAW(base)           (*pCPMAC_RX_INTSTAT_RAW(base))
++#define pCPMAC_RX_INTSTAT_MASKED(base)        ((MEM_PTR)(base+0x194))
++#define  CPMAC_RX_INTSTAT_MASKED(base)        (*pCPMAC_RX_INTSTAT_MASKED(base))
++#define pCPMAC_RX_INTMASK_SET(base)           ((MEM_PTR)(base+0x198))
++#define  CPMAC_RX_INTMASK_SET(base)           (*pCPMAC_RX_INTMASK_SET(base))
++#define pCPMAC_RX_INTMASK_CLEAR(base)         ((MEM_PTR)(base+0x19C))
++#define  CPMAC_RX_INTMASK_CLEAR(base)         (*pCPMAC_RX_INTMASK_CLEAR(base))
++#define pCPMAC_MAC_INTSTAT_RAW(base)          ((MEM_PTR)(base+0x1A0))
++#define  CPMAC_MAC_INTSTAT_RAW(base)          (*pCPMAC_MAC_INTSTAT_RAW(base))
++#define pCPMAC_MAC_INTSTAT_MASKED(base)       ((MEM_PTR)(base+0x1A4))
++#define  CPMAC_MAC_INTSTAT_MASKED(base)       (*pCPMAC_MAC_INTSTAT_MASKED(base))
++#define pCPMAC_MAC_INTMASK_SET(base)          ((MEM_PTR)(base+0x1A8))
++#define  CPMAC_MAC_INTMASK_SET(base)          (*pCPMAC_MAC_INTMASK_SET(base))
++#define pCPMAC_MAC_INTMASK_CLEAR(base)        ((MEM_PTR)(base+0x1AC))
++#define  CPMAC_MAC_INTMASK_CLEAR(base)        (*pCPMAC_MAC_INTMASK_CLEAR(base))
++#define pCPMAC_MACADDRLO_0(base)              ((MEM_PTR)(base+0x1B0))
++#define  CPMAC_MACADDRLO_0(base)              (*pCPMAC_MACADDRLO_0(base))
++#define pCPMAC_MACADDRLO_1(base)              ((MEM_PTR)(base+0x1B4))
++#define  CPMAC_MACADDRLO_1(base)              (*pCPMAC_MACADDRLO_1(base))
++#define pCPMAC_MACADDRLO_2(base)              ((MEM_PTR)(base+0x1B8))
++#define  CPMAC_MACADDRLO_2(base)              (*pCPMAC_MACADDRLO_2(base))
++#define pCPMAC_MACADDRLO_3(base)              ((MEM_PTR)(base+0x1BC))
++#define  CPMAC_MACADDRLO_3(base)              (*pCPMAC_MACADDRLO_3(base))
++#define pCPMAC_MACADDRLO_4(base)              ((MEM_PTR)(base+0x1C0))
++#define  CPMAC_MACADDRLO_4(base)              (*pCPMAC_MACADDRLO_4(base))
++#define pCPMAC_MACADDRLO_5(base)              ((MEM_PTR)(base+0x1C4))
++#define  CPMAC_MACADDRLO_5(base)              (*pCPMAC_MACADDRLO_5(base))
++#define pCPMAC_MACADDRLO_6(base)              ((MEM_PTR)(base+0x1C8))
++#define  CPMAC_MACADDRLO_6(base)              (*pCPMAC_MACADDRLO_6(base))
++#define pCPMAC_MACADDRLO_7(base)              ((MEM_PTR)(base+0x1CC))
++#define  CPMAC_MACADDRLO_7(base)              (*pCPMAC_MACADDRLO_7(base))
++#define pCPMAC_MACADDRMID(base)               ((MEM_PTR)(base+0x1D0))
++#define  CPMAC_MACADDRMID(base)               (*pCPMAC_MACADDRMID(base))
++#define pCPMAC_MACADDRHI(base)                ((MEM_PTR)(base+0x1D4))
++#define  CPMAC_MACADDRHI(base)                (*pCPMAC_MACADDRHI(base))
++#define pCPMAC_MACHASH1(base)                 ((MEM_PTR)(base+0x1D8))
++#define  CPMAC_MACHASH1(base)                 (*pCPMAC_MACHASH1(base))
++#define pCPMAC_MACHASH2(base)                 ((MEM_PTR)(base+0x1DC))
++#define  CPMAC_MACHASH2(base)                 (*pCPMAC_MACHASH2(base))
++#define pCPMAC_BOFFTEST(base)                 ((MEM_PTR)(base+0x1E0))
++#define  CPMAC_BOFFTEST(base)                 (*pCPMAC_BOFFTEST(base))
++#define pCPMAC_PACTEST(base)                  ((MEM_PTR)(base+0x1E4))
++#define  CPMAC_PACTEST(base)                  (*pCPMAC_PACTEST(base))
++#define pCPMAC_RXPAUSE(base)                  ((MEM_PTR)(base+0x1E8))
++#define  CPMAC_RXPAUSE(base)                  (*pCPMAC_RXPAUSE(base))
++#define pCPMAC_TXPAUSE(base)                  ((MEM_PTR)(base+0x1EC))
++#define  CPMAC_TXPAUSE(base)                  (*pCPMAC_TXPAUSE(base))
++/* STATISTICS */
++#define pCPMAC_RXGOODFRAMES(base)             ((MEM_PTR)(base+0x200))
++#define  CPMAC_RXGOODFRAMES(base)             (*pCPMAC_RXGOODFRAMES(base))
++#define pCPMAC_RXBROADCASTFRAMES(base)        ((MEM_PTR)(base+0x204))
++#define  CPMAC_RXBROADCASTFRAMES(base)        (*pCPMAC_RXBROADCASTFRAMES(base))
++#define pCPMAC_RXMULTICASTFRAMES(base)        ((MEM_PTR)(base+0x208))
++#define  CPMAC_RXMULTICASTFRAMES(base)        (*pCPMAC_RXMULTICASTFRAMES(base))
++#define pCPMAC_RXPAUSEFRAMES(base)            ((MEM_PTR)(base+0x20C))
++#define   CPMAC_RXPAUSEFRAMES(base)           (*pCPMAC_RXPAUSEFRAMES(base))
++#define pCPMAC_RXCRCERRORS(base)              ((MEM_PTR)(base+0x210))
++#define   CPMAC_RXCRCERRORS(base)             (*pCPMAC_RXCRCERRORS(base))
++#define pCPMAC_RXALIGNCODEERRORS(base)        ((MEM_PTR)(base+0x214))
++#define   CPMAC_RXALIGNCODEERRORS(base)       (*pCPMAC_RXALIGNCODEERRORS(base))
++#define pCPMAC_RXOVERSIZEDFRAMES(base)        ((MEM_PTR)(base+0x218))
++#define   CPMAC_RXOVERSIZEDFRAMES(base)       (*pCPMAC_RXOVERSIZEDFRAMES(base))
++#define pCPMAC_RXJABBERFRAMES(base)           ((MEM_PTR)(base+0x21C))
++#define  CPMAC_RXJABBERFRAMES(base)           (*pCPMAC_RXJABBERFRAMES(base))
++#define pCPMAC_RXUNDERSIZEDFRAMES(base)       ((MEM_PTR)(base+0x220))
++#define  CPMAC_RXUNDERSIZEDFRAMES(base)       (*pCPMAC_RXUNDERSIZEDFRAMES(base))
++#define pCPMAC_RXFRAGMENTS(base)              ((MEM_PTR)(base+0x224))
++#define  CPMAC_RXFRAGMENTS(base)              (*pCPMAC_RXFRAGMENTS(base))
++#define pCPMAC_RXFILTEREDFRAMES(base)         ((MEM_PTR)(base+0x228))
++#define  CPMAC_RXFILTEREDFRAMES(base)         (*pCPMAC_RXFILTEREDFRAMES(base))
++#define pCPMAC_RXQOSFILTEREDFRAMES(base)      ((MEM_PTR)(base+0x22C))
++#define  CPMAC_RXQOSFILTEREDFRAMES(base)      (*pCPMAC_RXQOSFILTEREDFRAMES(base))
++#define pCPMAC_RXOCTETS(base)                 ((MEM_PTR)(base+0x230))
++#define  CPMAC_RXOCTETS(base)                 (*pCPMAC_RXOCTETS(base))
++#define pCPMAC_TXGOODFRAMES(base)             ((MEM_PTR)(base+0x234))
++#define  CPMAC_TXGOODFRAMES(base)             (*pCPMAC_TXGOODFRAMES(base))
++#define pCPMAC_TXBROADCASTFRAMES(base)        ((MEM_PTR)(base+0x238))
++#define  CPMAC_TXBROADCASTFRAMES(base)        (*pCPMAC_TXBROADCASTFRAMES(base))
++#define pCPMAC_TXMULTICASTFRAMES(base)        ((MEM_PTR)(base+0x23C))
++#define  CPMAC_TXMULTICASTFRAMES(base)        (*pCPMAC_TXMULTICASTFRAMES(base))
++#define pCPMAC_TXPAUSEFRAMES(base)            ((MEM_PTR)(base+0x240))
++#define  CPMAC_TXPAUSEFRAMES(base)            (*pCPMAC_TXPAUSEFRAMES(base))
++#define pCPMAC_TXDEFERREDFRAMES(base)         ((MEM_PTR)(base+0x244))
++#define  CPMAC_TXDEFERREDFRAMES(base)         (*pCPMAC_TXDEFERREDFRAMES(base))
++#define pCPMAC_TXCOLLISIONFRAMES(base)        ((MEM_PTR)(base+0x248))
++#define  CPMAC_TXCOLLISIONFRAMES(base)        (*pCPMAC_TXCOLLISIONFRAMES(base))
++#define pCPMAC_TXSINGLECOLLFRAMES(base)       ((MEM_PTR)(base+0x24C))
++#define  CPMAC_TXSINGLECOLLFRAMES(base)       (*pCPMAC_TXSINGLECOLLFRAMES(base))
++#define pCPMAC_TXMULTCOLLFRAMES(base)         ((MEM_PTR)(base+0x250))
++#define  CPMAC_TXMULTCOLLFRAMES(base)         (*pCPMAC_TXMULTCOLLFRAMES(base))
++#define pCPMAC_TXEXCESSIVECOLLISIONS(base)    ((MEM_PTR)(base+0x254))
++#define  CPMAC_TXEXCESSIVECOLLISIONS(base)    (*pCPMAC_TXEXCESSIVECOLLISIONS(base))
++#define pCPMAC_TXLATECOLLISIONS(base)         ((MEM_PTR)(base+0x258))
++#define  CPMAC_TXLATECOLLISIONS(base)         (*pCPMAC_TXLATECOLLISIONS(base))
++#define pCPMAC_TXUNDERRUN(base)               ((MEM_PTR)(base+0x25C))
++#define  CPMAC_TXUNDERRUN(base)               (*pCPMAC_TXUNDERRUN(base))
++#define pCPMAC_TXCARRIERSENSEERRORS(base)     ((MEM_PTR)(base+0x260))
++#define  CPMAC_TXCARRIERSENSEERRORS(base)     (*pCPMAC_TXCARRIERSENSEERRORS(base))
++#define pCPMAC_TXOCTETS(base)                 ((MEM_PTR)(base+0x264))
++#define  CPMAC_TXOCTETS(base)                 (*pCPMAC_TXOCTETS(base))
++#define pCPMAC_64OCTETFRAMES(base)            ((MEM_PTR)(base+0x268))
++#define  CPMAC_64OCTETFRAMES(base)            (*pCPMAC_64OCTETFRAMES(base))
++#define pCPMAC_65T127OCTETFRAMES(base)        ((MEM_PTR)(base+0x26C))
++#define  CPMAC_65T127OCTETFRAMES(base)        (*pCPMAC_65T127OCTETFRAMES(base))
++#define pCPMAC_128T255OCTETFRAMES(base)       ((MEM_PTR)(base+0x270))
++#define  CPMAC_128T255OCTETFRAMES(base)       (*pCPMAC_128T255OCTETFRAMES(base))
++#define pCPMAC_256T511OCTETFRAMES(base)       ((MEM_PTR)(base+0x274))
++#define  CPMAC_256T511OCTETFRAMES(base)       (*pCPMAC_256T511OCTETFRAMES(base))
++#define pCPMAC_512T1023OCTETFRAMES(base)      ((MEM_PTR)(base+0x278))
++#define  CPMAC_512T1023OCTETFRAMES(base)      (*pCPMAC_512T1023OCTETFRAMES(base))
++#define pCPMAC_1024TUPOCTETFRAMES(base)       ((MEM_PTR)(base+0x27C))
++#define  CPMAC_1024TUPOCTETFRAMES(base)       (*pCPMAC_1024TUPOCTETFRAMES(base))
++#define pCPMAC_NETOCTETS(base)                ((MEM_PTR)(base+0x280))
++#define  CPMAC_NETOCTETS(base)                (*pCPMAC_NETOCTETS(base))
++#define pCPMAC_RXSOFOVERRUNS(base)            ((MEM_PTR)(base+0x284))
++#define  CPMAC_RXSOFOVERRUNS(base)            (*pCPMAC_RXSOFOVERRUNS(base))
++#define pCPMAC_RXMOFOVERRUNS(base)            ((MEM_PTR)(base+0x288))
++#define  CPMAC_RXMOFOVERRUNS(base)            (*pCPMAC_RXMOFOVERRUNS(base))
++#define pCPMAC_RXDMAOVERRUNS(base)            ((MEM_PTR)(base+0x28C))
++#define  CPMAC_RXDMAOVERRUNS(base)            (*pCPMAC_RXDMAOVERRUNS(base))
++
++#define  CPMAC_TX_HDP(base,ch)                (*(MEM_PTR)(base+0x600+(4*ch)))
++#define pCPMAC_TX0_HDP(base)                  ((MEM_PTR)(base+0x600))
++#define  CPMAC_TX0_HDP(base)                  (*pCPMAC_TX0_HDP(base))
++#define pCPMAC_TX1_HDP(base)                  ((MEM_PTR)(base+0x604))
++#define  CPMAC_TX1_HDP(base)                  (*pCPMAC_TX1_HDP(base))
++#define pCPMAC_TX2_HDP(base)                  ((MEM_PTR)(base+0x608))
++#define  CPMAC_TX2_HDP(base)                  (*pCPMAC_TX2_HDP(base))
++#define pCPMAC_TX3_HDP(base)                  ((MEM_PTR)(base+0x60C))
++#define  CPMAC_TX3_HDP(base)                  (*pCPMAC_TX3_HDP(base))
++#define pCPMAC_TX4_HDP(base)                  ((MEM_PTR)(base+0x610))
++#define  CPMAC_TX4_HDP(base)                  (*pCPMAC_TX4_HDP(base))
++#define pCPMAC_TX5_HDP(base)                  ((MEM_PTR)(base+0x614))
++#define  CPMAC_TX5_HDP(base)                  (*pCPMAC_TX5_HDP(base))
++#define pCPMAC_TX6_HDP(base)                  ((MEM_PTR)(base+0x618))
++#define  CPMAC_TX6_HDP(base)                  (*pCPMAC_TX6_HDP(base))
++#define pCPMAC_TX7_HDP(base)                  ((MEM_PTR)(base+0x61C))
++#define  CPMAC_TX7_HDP(base)                  (*pCPMAC_TX7_HDP(base))
++#define  CPMAC_RX_HDP(base,ch)                (*(MEM_PTR)(base+0x620+(4*ch)))
++#define pCPMAC_RX0_HDP(base)                  ((MEM_PTR)(base+0x620))
++#define  CPMAC_RX0_HDP(base)                  (*pCPMAC_RX0_HDP(base))
++#define pCPMAC_RX1_HDP(base)                  ((MEM_PTR)(base+0x624))
++#define  CPMAC_RX1_HDP(base)                  (*pCPMAC_RX1_HDP(base))
++#define pCPMAC_RX2_HDP(base)                  ((MEM_PTR)(base+0x628))
++#define  CPMAC_RX2_HDP(base)                  (*pCPMAC_RX2_HDP(base))
++#define pCPMAC_RX3_HDP(base)                  ((MEM_PTR)(base+0x62C))
++#define  CPMAC_RX3_HDP(base)                  (*pCPMAC_RX3_HDP(base))
++#define pCPMAC_RX4_HDP(base)                  ((MEM_PTR)(base+0x630))
++#define  CPMAC_RX4_HDP(base)                  (*pCPMAC_RX4_HDP(base))
++#define pCPMAC_RX5_HDP(base)                  ((MEM_PTR)(base+0x634))
++#define  CPMAC_RX5_HDP(base)                  (*pCPMAC_RX5_HDP(base))
++#define pCPMAC_RX6_HDP(base)                  ((MEM_PTR)(base+0x638))
++#define  CPMAC_RX6_HDP(base)                  (*pCPMAC_RX6_HDP(base))
++#define pCPMAC_RX7_HDP(base)                  ((MEM_PTR)(base+0x63C))
++#define  CPMAC_RX7_HDP(base)                  (*pCPMAC_RX7_HDP(base))
++
++
++#define CPMAC_TX_INT_ACK(base,ch)             (*(MEM_PTR)(base+0x640+(4*ch)))
++
++#define pCPMAC_TX0_INT_ACK(base)              ((MEM_PTR)(base+0x640))
++#define  CPMAC_TX0_INT_ACK(base)              (*pCPMAC_TX0_INT_ACK(base))
++#define pCPMAC_TX1_INT_ACK(base)              ((MEM_PTR)(base+0x644))
++#define  CPMAC_TX1_INT_ACK(base)              (*pCPMAC_TX1_INT_ACK(base))
++#define pCPMAC_TX2_INT_ACK(base)              ((MEM_PTR)(base+0x648))
++#define  CPMAC_TX2_INT_ACK(base)              (*pCPMAC_TX2_INT_ACK(base))
++#define pCPMAC_TX3_INT_ACK(base)              ((MEM_PTR)(base+0x64C))
++#define  CPMAC_TX3_INT_ACK(base)              (*pCPMAC_TX3_INT_ACK(base))
++#define pCPMAC_TX4_INT_ACK(base)              ((MEM_PTR)(base+0x650))
++#define  CPMAC_TX4_INT_ACK(base)              (*pCPMAC_TX4_INT_ACK(base))
++#define pCPMAC_TX5_INT_ACK(base)              ((MEM_PTR)(base+0x654))
++#define  CPMAC_TX5_INT_ACK(base)              (*pCPMAC_TX5_INT_ACK(base))
++#define pCPMAC_TX6_INT_ACK(base)              ((MEM_PTR)(base+0x658))
++#define  CPMAC_TX6_INT_ACK(base)              (*pCPMAC_TX6_INT_ACK(base))
++#define pCPMAC_TX7_INT_ACK(base)              ((MEM_PTR)(base+0x65C))
++#define  CPMAC_TX7_INT_ACK(base)              (*pCPMAC_TX7_INT_ACK(base))
++#define CPMAC_RX_INT_ACK(base,ch)             (*(MEM_PTR)(base+0x660+(4*ch)))
++         
++#define pCPMAC_RX0_INT_ACK(base)              ((MEM_PTR)(base+0x660))
++#define  CPMAC_RX0_INT_ACK(base)              (*pCPMAC_RX0_INT_ACK(base))
++#define pCPMAC_RX1_INT_ACK(base)              ((MEM_PTR)(base+0x664))
++#define  CPMAC_RX1_INT_ACK(base)              (*pCPMAC_RX1_INT_ACK(base))
++#define pCPMAC_RX2_INT_ACK(base)              ((MEM_PTR)(base+0x668))
++#define  CPMAC_RX2_INT_ACK(base)              (*pCPMAC_RX2_INT_ACK(base))
++#define pCPMAC_RX3_INT_ACK(base)              ((MEM_PTR)(base+0x66C))
++#define  CPMAC_RX3_INT_ACK(base)              (*pCPMAC_RX3_INT_ACK(base))
++#define pCPMAC_RX4_INT_ACK(base)              ((MEM_PTR)(base+0x670))
++#define  CPMAC_RX4_INT_ACK(base)              (*pCPMAC_RX4_INT_ACK(base))
++#define pCPMAC_RX5_INT_ACK(base)              ((MEM_PTR)(base+0x674))
++#define  CPMAC_RX5_INT_ACK(base)              (*pCPMAC_RX5_INT_ACK(base))
++#define pCPMAC_RX6_INT_ACK(base)              ((MEM_PTR)(base+0x678))
++#define  CPMAC_RX6_INT_ACK(base)              (*pCPMAC_RX6_INT_ACK(base))
++#define pCPMAC_RX7_INT_ACK(base)              ((MEM_PTR)(base+0x67C))
++#define  CPMAC_RX7_INT_ACK(base)              (*pCPMAC_RX7_INT_ACK(base))
++
++/****************************************************************************/
++/*                                                                          */
++/*         R E G I S T E R  B I T  D E F I N I T I O N S                    */
++/*                                                                          */
++/****************************************************************************/
++
++/* TX_CONTROL */
++
++#define TX_EN               (1 << 0)
++
++/* RX_CONTROL */
++
++#define RX_EN               (1 << 0)
++
++/* RX_MBP_ENABLE */
++
++#define RX_PASS_CRC         (1 << 30)
++#define RX_QOS_EN           (1 << 29)
++#define RX_NO_CHAIN         (1 << 28)
++
++#define RX_CMF_EN           (1 << 24)
++#define RX_CSF_EN           (1 << 23)
++#define RX_CEF_EN           (1 << 22)
++#define RX_CAF_EN           (1 << 21)
++
++#define RX_PROM_CH(n)       (n << 16)
++#define RX_PROM_CH_MASK     RX_PROM_CH(7)
++#define RX_PROM_CH_7        RX_PROM_CH(7)
++#define RX_PROM_CH_6        RX_PROM_CH(6)
++#define RX_PROM_CH_5        RX_PROM_CH(5)
++#define RX_PROM_CH_4        RX_PROM_CH(4)
++#define RX_PROM_CH_3        RX_PROM_CH(3)
++#define RX_PROM_CH_2        RX_PROM_CH(2)
++#define RX_PROM_CH_1        RX_PROM_CH(1)
++#define RX_PROM_CH_0        RX_PROM_CH(0)
++
++#define RX_BROAD_EN         (1 << 13)
++
++#define RX_BROAD_CH(n)       (n <<  8)
++#define RX_BROAD_CH_MASK     RX_BROAD_CH(7)
++#define RX_BROAD_CH_7        RX_BROAD_CH(7)
++#define RX_BROAD_CH_6        RX_BROAD_CH(6)
++#define RX_BROAD_CH_5        RX_BROAD_CH(5)
++#define RX_BROAD_CH_4        RX_BROAD_CH(4)
++#define RX_BROAD_CH_3        RX_BROAD_CH(3)
++#define RX_BROAD_CH_2        RX_BROAD_CH(2)
++#define RX_BROAD_CH_1        RX_BROAD_CH(1)
++#define RX_BROAD_CH_0        RX_BROAD_CH(0)
++
++#define RX_MULT_EN          (1 <<  5)
++
++#define RX_MULT_CH(n)       (n << 0)
++#define RX_MULT_CH_MASK     RX_MULT_CH(7)
++#define RX_MULT_CH_7        RX_MULT_CH(7)
++#define RX_MULT_CH_6        RX_MULT_CH(6)
++#define RX_MULT_CH_5        RX_MULT_CH(5)
++#define RX_MULT_CH_4        RX_MULT_CH(4)
++#define RX_MULT_CH_3        RX_MULT_CH(3)
++#define RX_MULT_CH_2        RX_MULT_CH(2)
++#define RX_MULT_CH_1        RX_MULT_CH(1)
++#define RX_MULT_CH_0        RX_MULT_CH(0)
++
++
++
++/* RX_UNICAST_SET */
++
++#define RX_CH7_EN        (1 <<  7)
++#define RX_CH6_EN        (1 <<  6)
++#define RX_CH5_EN        (1 <<  5)
++#define RX_CH4_EN        (1 <<  4)
++#define RX_CH3_EN        (1 <<  3)
++#define RX_CH2_EN        (1 <<  2)
++#define RX_CH1_EN        (1 <<  1)
++#define RX_CH0_EN        (1 <<  0)
++
++
++
++/*  MAC control */
++#define TX_PTYPE         (1 << 9)
++#define TX_PACE          (1 << 6)
++#define MII_EN           (1 << 5)
++#define TX_FLOW_EN       (1 << 4)
++#define RX_FLOW_EN       (1 << 3)
++#define MTEST            (1 << 2)
++#define CTRL_LOOPBACK    (1 << 1)
++#define FULLDUPLEX       (1 << 0)
++
++
++/* IntVec definitions  */
++#define MAC_IN_VECTOR_STATUS_INT   (1 << 19)
++#define MAC_IN_VECTOR_HOST_INT     (1 << 18)
++#define MAC_IN_VECTOR_RX_INT_OR    (1 << 17)
++#define MAC_IN_VECTOR_TX_INT_OR    (1 << 16)
++#define MAC_IN_VECTOR_RX_INT_VEC   (7 << 8)
++#define MAC_IN_VECTOR_TX_INT_VEC   (7)  
++
++
++/*  MacStatus */
++
++#define TX_HOST_ERR_CODE         (0xF << 20)
++#define TX_ERR_CH                (0x7 << 16)
++#define RX_HOST_ERR_CODE         (0xF << 12)
++#define RX_ERR_CH                (0x7 <<  8)
++#define RX_QOS_ACT               (1 << 2)
++#define RX_FLOW_ACT              (1 << 1)
++#define TX_FLOW_ACT              (1 << 0)
++#endif _INC_CPMAC_REG
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/cpmdio.c linux-2.4.30/drivers/net/avalanche_cpmac/cpmdio.c
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/cpmdio.c     1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/cpmdio.c  2005-04-15 05:10:41.000000000 +0200
+@@ -0,0 +1,960 @@
++/***************************************************************************
++**  TNETD53xx Software Support
++**  Copyright(c) 2002, Texas Instruments Incorporated. All Rights Reserved.
++**
++**  FILE: cpmdio.c
++**
++**  DESCRIPTION:
++**   MDIO Polling State Machine API. Functions will enable mii-Phy
++**   negotiation.
++**
++**  HISTORY:
++**    01Jan01 Denis, Bill      Original
++**      27Mar02 Michael Hanrahan (modified from emacmdio.c)
++**      07May02 Michael Hanrahan replaced clockwait for code delay
++**      10Jul02 Michael Hanrahan more debug, if fallback link is selected
++*****************************************************************************/
++#define __CPHAL_CPMDIO
++
++#include "mdio_reg.h"
++
++#ifdef _CPHAL_CPMAC
++#define mdioPrintf PhyDev->HalDev->OsFunc->Printf
++#else
++#define mdioPrintf printf
++#endif
++
++typedef struct _phy_device
++{
++   bit32u miibase;
++   bit32u inst;
++   bit32u PhyState;
++   bit32u MdixMask;
++   bit32u PhyMask;
++   bit32u MLinkMask;
++   bit32u PhyMode;
++#ifdef _CPHAL_CPMAC
++   HAL_DEVICE *HalDev;
++#endif
++} _PHY_DEVICE;
++
++static void   _mdioDelayEmulate(PHY_DEVICE *PhyDev, int ClockWait);
++static void   _mdioWaitForAccessComplete(PHY_DEVICE *PhyDev);
++static void   _mdioUserAccess(PHY_DEVICE *PhyDev, bit32u method, bit32u regadr, bit32u phyadr, bit32u data);
++static bit32u _mdioUserAccessRead(PHY_DEVICE *PhyDev, bit32u regadr, bit32u phyadr);
++static void   _mdioUserAccessWrite(PHY_DEVICE *PhyDev, bit32u regadr, bit32u phyadr, bit32u data);
++
++static void _mdioDisablePhy(PHY_DEVICE *PhyDev,bit32u PhyNum);
++static void _mdioPhyTimeOut(PHY_DEVICE *PhyDev);
++static void _mdioResetPhy(PHY_DEVICE *PhyDev,bit32u PhyNum);
++
++static void _mdioDumpPhy(PHY_DEVICE *PhyDev, bit32u p);
++static void _mdioDumpState(PHY_DEVICE *PhyDev);
++
++/* Auto Mdix */
++static void _mdioMdixDelay(PHY_DEVICE *PhyDev);
++static int  _mdioMdixSupported(PHY_DEVICE *PhyDev);
++
++static void _MdioDefaultState  (PHY_DEVICE *PhyDev);
++static void _MdioFindingState  (PHY_DEVICE *PhyDev);
++static void _MdioFoundState    (PHY_DEVICE *PhyDev);
++static void _MdioInitState     (PHY_DEVICE *PhyDev);
++static void _MdioLinkedState   (PHY_DEVICE *PhyDev);
++static void _MdioLinkWaitState (PHY_DEVICE *PhyDev);
++static void _MdioLoopbackState (PHY_DEVICE *PhyDev);
++static void _MdioNwayStartState(PHY_DEVICE *PhyDev);
++static void _MdioNwayWaitState (PHY_DEVICE *PhyDev);
++
++
++
++#ifndef TRUE
++#define TRUE (1==1)
++#endif
++
++#ifndef FALSE
++#define FALSE (1==2)
++#endif
++
++#define PHY_NOT_FOUND  0xFFFF    /*  Used in Phy Detection */
++
++/*PhyState breakout                                                          */
++
++#define PHY_DEV_OFFSET      (0)
++#define PHY_DEV_SIZE        (5)        /*  5 Bits used */
++#define PHY_DEV_MASK        (0x1f<<PHY_DEV_OFFSET)
++
++#define PHY_STATE_OFFSET    (PHY_DEV_SIZE+PHY_DEV_OFFSET)
++#define PHY_STATE_SIZE      (5)        /* 10 Bits used */
++#define PHY_STATE_MASK      (0x1f<<PHY_STATE_OFFSET)
++  #define INIT       (1<<PHY_STATE_OFFSET)
++  #define FINDING    (2<<PHY_STATE_OFFSET)
++  #define FOUND      (3<<PHY_STATE_OFFSET)
++  #define NWAY_START (4<<PHY_STATE_OFFSET)
++  #define NWAY_WAIT  (5<<PHY_STATE_OFFSET)
++  #define LINK_WAIT  (6<<PHY_STATE_OFFSET)
++  #define LINKED     (7<<PHY_STATE_OFFSET)
++  #define LOOPBACK   (8<<PHY_STATE_OFFSET)
++
++#define PHY_SPEED_OFFSET    (PHY_STATE_OFFSET+PHY_STATE_SIZE)
++#define PHY_SPEED_SIZE      (1)     /* 11 Bits used */
++#define PHY_SPEED_MASK      (1<<PHY_SPEED_OFFSET)
++
++#define PHY_DUPLEX_OFFSET   (PHY_SPEED_OFFSET+PHY_SPEED_SIZE)
++#define PHY_DUPLEX_SIZE     (1)     /* 12 Bits used */
++#define PHY_DUPLEX_MASK     (1<<PHY_DUPLEX_OFFSET)
++
++#define PHY_TIM_OFFSET      (PHY_DUPLEX_OFFSET+PHY_DUPLEX_SIZE)
++#define PHY_TIM_SIZE        (10)    /* 22 Bits used */
++#define PHY_TIM_MASK        (0x3ff<<PHY_TIM_OFFSET)
++  #define PHY_FIND_TO (  2<<PHY_TIM_OFFSET)
++  #define PHY_RECK_TO (200<<PHY_TIM_OFFSET)
++  #define PHY_LINK_TO (500<<PHY_TIM_OFFSET)
++  #define PHY_NWST_TO (500<<PHY_TIM_OFFSET)
++  #define PHY_NWDN_TO (800<<PHY_TIM_OFFSET)
++  #define PHY_MDIX_TO (274<<PHY_TIM_OFFSET) /* 2.74 Seconds <--Spec and empirical */
++
++#define PHY_SMODE_OFFSET    (PHY_TIM_OFFSET+PHY_TIM_SIZE)
++#define PHY_SMODE_SIZE      (5)     /* 27 Bits used */
++#define PHY_SMODE_MASK      (0x1f<<PHY_SMODE_OFFSET)
++  #define SMODE_AUTO   (0x10<<PHY_SMODE_OFFSET)
++  #define SMODE_FD100  (0x08<<PHY_SMODE_OFFSET)
++  #define SMODE_HD100  (0x04<<PHY_SMODE_OFFSET)
++  #define SMODE_FD10   (0x02<<PHY_SMODE_OFFSET)
++  #define SMODE_HD10   (0x01<<PHY_SMODE_OFFSET)
++  #define SMODE_ALL    (0x1f<<PHY_SMODE_OFFSET)
++
++#define PHY_CHNG_OFFSET    (PHY_SMODE_OFFSET+PHY_SMODE_SIZE)
++#define PHY_CHNG_SIZE      (1)     /* 28 Bits used */
++#define PHY_CHNG_MASK      (1<<PHY_CHNG_OFFSET)
++  #define PHY_CHANGE (1<<PHY_CHNG_OFFSET)
++
++#define PHY_TIMEDOUT_OFFSET    (PHY_CHNG_OFFSET+PHY_CHNG_SIZE)
++#define PHY_TIMEDOUT_SIZE      (1)     /*  29 Bits used */
++#define PHY_TIMEDOUT_MASK      (1<<PHY_TIMEDOUT_OFFSET)
++  #define PHY_MDIX_SWITCH  (1<<PHY_TIMEDOUT_OFFSET)
++
++#define PHY_MDIX_OFFSET    (PHY_TIMEDOUT_OFFSET+PHY_TIMEDOUT_SIZE)
++#define PHY_MDIX_SIZE      (1)     /*  30 Bits used */
++#define PHY_MDIX_MASK      (1<<PHY_MDIX_OFFSET)
++  #define PHY_MDIX     (1<<PHY_MDIX_OFFSET)
++
++static char *lstate[]={"NULL","INIT","FINDING","FOUND","NWAY_START","NWAY_WAIT","LINK_WAIT","LINKED", "LOOPBACK"};
++static int cpMacDebug;
++
++/*  Local MDIO Register Macros    */
++
++#define myMDIO_ALIVE           MDIO_ALIVE     (PhyDev->miibase)
++#define myMDIO_CONTROL         MDIO_CONTROL   (PhyDev->miibase)
++#define myMDIO_LINK            MDIO_LINK      (PhyDev->miibase)
++#define myMDIO_LINKINT         MDIO_LINKINT   (PhyDev->miibase)
++#define myMDIO_USERACCESS      MDIO_USERACCESS(PhyDev->miibase, PhyDev->inst)
++#define myMDIO_USERPHYSEL      MDIO_USERPHYSEL(PhyDev->miibase, PhyDev->inst)
++#define myMDIO_VER             MDIO_VER       (PhyDev->miibase)
++
++#ifndef VOLATILE32
++#define VOLATILE32(addr) (*((volatile bit32u *)(addr)))
++#endif
++
++/************************************
++***
++*** Delays at least ClockWait cylces
++*** before returning
++***
++**************************************/
++void _mdioDelayEmulate(PHY_DEVICE *PhyDev, int ClockWait)
++  {
++#ifdef _CPHAL_CPMAC                                                  /*+RC3.02*/
++  HAL_DEVICE *HalDev = PhyDev->HalDev;                               /*+RC3.02*/
++  osfuncSleep((int*)&ClockWait);                                     /*+RC3.02*/
++#else                                                                /*+RC3.02*/
++  volatile bit32u i=0;
++  while(ClockWait--)
++    {
++    i |= myMDIO_LINK; /*  MDIO register access to burn cycles */
++    }
++#endif
++  }
++
++void _mdioWaitForAccessComplete(PHY_DEVICE *PhyDev)
++  {
++  while((myMDIO_USERACCESS & MDIO_USERACCESS_GO)!=0)
++    {
++    }
++  }
++
++void _mdioUserAccess(PHY_DEVICE *PhyDev, bit32u method, bit32u regadr, bit32u phyadr, bit32u data)
++  {
++  bit32u  control;
++
++  control =  MDIO_USERACCESS_GO |
++             (method) |
++             (((regadr) << 21) & MDIO_USERACCESS_REGADR) |
++             (((phyadr) << 16) & MDIO_USERACCESS_PHYADR) |
++             ((data) & MDIO_USERACCESS_DATA);
++
++  myMDIO_USERACCESS = control;
++  }
++
++
++
++/************************************
++***
++*** Waits for MDIO_USERACCESS to be ready and reads data
++*** If 'WaitForData' set, waits for read to complete and returns Data,
++*** otherwise returns 0
++*** Note: 'data' is 16 bits but we use 32 bits
++***        to be consistent with rest of the code.
++***
++**************************************/
++bit32u _mdioUserAccessRead(PHY_DEVICE *PhyDev, bit32u regadr, bit32u phyadr)
++  {
++
++  _mdioWaitForAccessComplete(PhyDev);  /* Wait until UserAccess ready */
++  _mdioUserAccess(PhyDev, MDIO_USERACCESS_READ, regadr, phyadr, 0);
++  _mdioWaitForAccessComplete(PhyDev);  /* Wait for Read to complete */
++
++  return(myMDIO_USERACCESS & MDIO_USERACCESS_DATA);
++  }
++
++
++/************************************
++***
++*** Waits for MDIO_USERACCESS to be ready and writes data
++***
++**************************************/
++void _mdioUserAccessWrite(PHY_DEVICE *PhyDev, bit32u regadr, bit32u phyadr, bit32u data)
++  {
++  _mdioWaitForAccessComplete(PhyDev);  /* Wait until UserAccess ready */
++  _mdioUserAccess(PhyDev, MDIO_USERACCESS_WRITE, regadr, phyadr, data);
++  }
++
++void _mdioDumpPhyDetailed(PHY_DEVICE *PhyDev)
++{
++  bit32u *PhyState = &PhyDev->PhyState;
++  bit32u  PhyNum;
++  int     RegData;
++
++  PhyNum=(*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET;
++
++  RegData = _mdioUserAccessRead(PhyDev, 0, PhyNum);
++  mdioPrintf("PhyControl: %04X, Lookback=%s, Speed=%s, Duplex=%s\n",
++    RegData,
++    RegData&PHY_LOOP?"On":"Off",
++    RegData&PHY_100?"100":"10",
++    RegData&PHY_FD?"Full":"Half");
++  RegData = _mdioUserAccessRead(PhyDev, 1, PhyNum);
++  mdioPrintf("PhyStatus: %04X, AutoNeg=%s, Link=%s\n",
++    RegData,
++    RegData&NWAY_COMPLETE?"Complete":"NotComplete",
++    RegData&PHY_LINKED?"Up":"Down");
++  RegData = _mdioUserAccessRead(PhyDev, 4, PhyNum);
++  mdioPrintf("PhyMyCapability: %04X, 100FD=%s, 100HD=%s, 10FD=%s, 10HD=%s\n",
++    RegData,
++    RegData&NWAY_FD100?"Yes":"No",
++    RegData&NWAY_HD100?"Yes":"No",
++    RegData&NWAY_FD10?"Yes":"No",
++    RegData&NWAY_HD10?"Yes":"No");
++
++  RegData = _mdioUserAccessRead(PhyDev, 5, PhyNum);
++  mdioPrintf("PhyPartnerCapability: %04X, 100FD=%s, 100HD=%s, 10FD=%s, 10HD=%s\n",
++    RegData,
++    RegData&NWAY_FD100?"Yes":"No",
++    RegData&NWAY_HD100?"Yes":"No",
++    RegData&NWAY_FD10?"Yes":"No",
++    RegData&NWAY_HD10?"Yes":"No");
++}
++void _mdioDumpPhy(PHY_DEVICE *PhyDev, bit32u p)
++  {
++  bit32u j,n,PhyAcks;
++  bit32u PhyRegAddr;
++  bit32u phy_num;
++  bit32u PhyMask  = PhyDev->PhyMask;
++
++  PhyAcks=myMDIO_ALIVE;
++  PhyAcks&=PhyMask;   /* Only interested in 'our' Phys */
++
++  for(phy_num=0,j=1;phy_num<32;phy_num++,j<<=1)
++    {
++    if (PhyAcks&j)
++      {
++      mdioPrintf("%2d%s:",phy_num,(phy_num==p)?">":" ");
++      for(PhyRegAddr=0;PhyRegAddr<6;PhyRegAddr++)
++        {
++        n = _mdioUserAccessRead(PhyDev, PhyRegAddr, phy_num);
++        mdioPrintf(" %04x",n&0x0ffff);
++        }
++      mdioPrintf("\n");
++      }
++    }
++  _mdioDumpPhyDetailed(PhyDev);
++  }
++
++void _mdioDumpState(PHY_DEVICE *PhyDev)
++  {
++  bit32u state    = PhyDev->PhyState;
++
++  if (!cpMacDebug) return;
++
++  mdioPrintf("Phy: %d, ",(state&PHY_DEV_MASK)>>PHY_DEV_OFFSET);
++  mdioPrintf("State: %d/%s, ",(state&PHY_STATE_MASK)>>PHY_STATE_OFFSET,lstate[(state&PHY_STATE_MASK)>>PHY_STATE_OFFSET]);
++  mdioPrintf("Speed: %d, ",(state&PHY_SPEED_MASK)>>PHY_SPEED_OFFSET);
++  mdioPrintf("Dup: %d, ",(state&PHY_DUPLEX_MASK)>>PHY_DUPLEX_OFFSET);
++  mdioPrintf("Tim: %d, ",(state&PHY_TIM_MASK)>>PHY_TIM_OFFSET);
++  mdioPrintf("SMode: %d, ",(state&PHY_SMODE_MASK)>>PHY_SMODE_OFFSET);
++  mdioPrintf("Chng: %d",(state&PHY_CHNG_MASK)>>PHY_CHNG_OFFSET);
++  mdioPrintf("\n");
++
++  if (((state&PHY_STATE_MASK)!=FINDING)&&((state&PHY_STATE_MASK)!=INIT))
++    _mdioDumpPhy(PhyDev, (state&PHY_DEV_MASK)>>PHY_DEV_OFFSET);
++  }
++
++
++void _mdioResetPhy(PHY_DEVICE *PhyDev,bit32u PhyNum)
++  {
++  bit16u PhyControlReg;
++
++  _mdioUserAccessWrite(PhyDev, PHY_CONTROL_REG, PhyNum, PHY_RESET);
++  if (cpMacDebug)
++    mdioPrintf("cpMacMdioPhYReset(%d)\n",PhyNum);
++
++  /* Read control register until Phy Reset is complete */
++  do
++   {
++    PhyControlReg = _mdioUserAccessRead(PhyDev, PHY_CONTROL_REG, PhyNum);
++   }
++   while (PhyControlReg & PHY_RESET); /* Wait for Reset to clear */
++  }
++
++void _mdioDisablePhy(PHY_DEVICE *PhyDev,bit32u PhyNum)
++  {
++  _mdioUserAccessWrite(PhyDev, PHY_CONTROL_REG, PhyNum, PHY_ISOLATE|PHY_PDOWN);
++
++  if (cpMacDebug)
++    mdioPrintf("cpMacMdioDisablePhy(%d)\n",PhyNum);
++
++  }
++
++void _MdioInitState(PHY_DEVICE *PhyDev)
++  {
++  bit32u *PhyState = &PhyDev->PhyState;
++  bit32u CurrentState;
++
++  CurrentState=*PhyState;
++  CurrentState=(CurrentState&~PHY_TIM_MASK)|(PHY_FIND_TO);
++  CurrentState=(CurrentState&~PHY_STATE_MASK)|(FINDING);
++  CurrentState=(CurrentState&~PHY_SPEED_MASK);
++  CurrentState=(CurrentState&~PHY_DUPLEX_MASK);
++  CurrentState|=PHY_CHANGE;
++
++  *PhyState=CurrentState;
++
++  }
++
++void _MdioFindingState(PHY_DEVICE *PhyDev)
++  {
++  bit32u *PhyState = &PhyDev->PhyState;
++  bit32u  PhyMask  = PhyDev->PhyMask;
++  bit32u  PhyNum,i,j,PhyAcks;
++
++
++  PhyNum=PHY_NOT_FOUND;
++
++  if (*PhyState&PHY_TIM_MASK)
++    {
++    *PhyState=(*PhyState&~PHY_TIM_MASK)|((*PhyState&PHY_TIM_MASK)-(1<<PHY_TIM_OFFSET));
++    }
++   else
++    {
++    PhyAcks=myMDIO_ALIVE;
++    PhyAcks&=PhyMask;   /* Only interested in 'our' Phys */
++
++    for(i=0,j=1;(i<32)&&((j&PhyAcks)==0);i++,j<<=1);
++
++    if ((PhyAcks)&&(i<32)) PhyNum=i;
++    if (PhyNum!=PHY_NOT_FOUND)
++      {
++      /*  Phy Found! */
++      *PhyState=(*PhyState&~PHY_DEV_MASK)|((PhyNum&PHY_DEV_MASK)<<PHY_DEV_OFFSET);
++      *PhyState=(*PhyState&~PHY_STATE_MASK)|(FOUND);
++      *PhyState|=PHY_CHANGE;
++      if (cpMacDebug)
++        mdioPrintf("cpMacMdioFindingState: PhyNum: %d\n",PhyNum);
++      }
++     else
++      {
++      if (cpMacDebug)
++        mdioPrintf("cpMacMdioFindingState: Timed Out looking for a Phy!\n");
++      *PhyState|=PHY_RECK_TO;  /* This state currently has no support?*/
++      }
++    }
++  }
++
++void _MdioFoundState(PHY_DEVICE *PhyDev)
++  {
++  bit32u *PhyState  = &PhyDev->PhyState;
++  bit32u  PhyMask   = PhyDev->PhyMask;
++  bit32u  MLinkMask = PhyDev->MLinkMask;
++  bit32u  PhyNum,PhyStatus,NWAYadvertise,m,phynum,i,j,PhyAcks;
++  bit32u  PhySel;
++
++  if ((*PhyState&PHY_SMODE_MASK)==0) return;
++
++  PhyNum=(*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET;
++
++  PhyAcks=myMDIO_ALIVE;
++  PhyAcks&=PhyMask;   /* Only interested in 'our' Phys */
++
++  /* Will now isolate all our Phys, except the one we have decided to use */
++  for(phynum=0,j=1;phynum<32;phynum++,j<<=1)
++    {
++    if (PhyAcks&j)
++      {
++        if (phynum!=PhyNum)  /* Do not disabled Found Phy */
++          _mdioDisablePhy(PhyDev,phynum);
++      }
++    }
++
++  /*  Reset the Phy and proceed with auto-negotiation */
++  _mdioResetPhy(PhyDev,PhyNum);
++
++  /* Now setup the MDIOUserPhySel register */
++
++  PhySel=PhyNum;  /* Set the phy address */
++
++  /*  Set the way Link will be Monitored */
++  /* Check the Link Selection Method */
++  if ((1 << PhyNum) & MLinkMask)
++    PhySel |= MDIO_USERPHYSEL_LINKSEL;
++
++  myMDIO_USERPHYSEL = PhySel;  /* update PHYSEL */
++
++  /* Get the Phy Status */
++  PhyStatus = _mdioUserAccessRead(PhyDev, PHY_STATUS_REG, PhyNum);
++
++
++#ifdef _CPHAL_CPMAC
++  /*  For Phy Internal loopback test, need to wait until Phy
++      found, then set Loopback */
++  if (PhyDev->HalDev->MdioConnect & _CPMDIO_LOOPBK)
++    {
++    /* Set Phy in Loopback */
++    _mdioUserAccessWrite(PhyDev, PHY_CONTROL_REG, PhyNum, PHY_LOOP|PHY_FD);
++    /* Do a read to ensure PHY_LOOP has completed */
++    _mdioUserAccessRead(PhyDev, PHY_STATUS_REG, PhyNum);
++    *PhyState=(*PhyState&~PHY_STATE_MASK)|(LOOPBACK);
++    *PhyState|=PHY_CHANGE;
++    return;
++    }
++#endif
++
++
++  if (cpMacDebug)
++    mdioPrintf("Enable Phy to negotiate external connection\n");
++
++  NWAYadvertise=NWAY_SEL;
++  if (*PhyState&SMODE_FD100) NWAYadvertise|=NWAY_FD100;
++  if (*PhyState&SMODE_HD100) NWAYadvertise|=NWAY_HD100;
++  if (*PhyState&SMODE_FD10)  NWAYadvertise|=NWAY_FD10;
++  if (*PhyState&SMODE_HD10)  NWAYadvertise|=NWAY_HD10;
++
++  *PhyState&=~(PHY_TIM_MASK|PHY_STATE_MASK);
++  if ((PhyStatus&NWAY_CAPABLE)&&(*PhyState&SMODE_AUTO))   /*NWAY Phy Detected*/
++    {
++    /*For NWAY compliant Phys                                                */
++
++    _mdioUserAccessWrite(PhyDev, NWAY_ADVERTIZE_REG, PhyNum, NWAYadvertise);
++
++    if (cpMacDebug)
++      {
++      mdioPrintf("NWAY Advertising: ");
++      if (NWAYadvertise&NWAY_FD100) mdioPrintf("FullDuplex-100 ");
++      if (NWAYadvertise&NWAY_HD100) mdioPrintf("HalfDuplex-100 ");
++      if (NWAYadvertise&NWAY_FD10)  mdioPrintf("FullDuplex-10 ");
++      if (NWAYadvertise&NWAY_HD10)  mdioPrintf("HalfDuplex-10 ");
++      mdioPrintf("\n");
++      }
++
++    _mdioUserAccessWrite(PhyDev, PHY_CONTROL_REG, PhyNum, AUTO_NEGOTIATE_EN);
++
++    _mdioUserAccessWrite(PhyDev, PHY_CONTROL_REG, PhyNum, AUTO_NEGOTIATE_EN|RENEGOTIATE);
++
++    *PhyState|=PHY_CHANGE|PHY_NWST_TO|NWAY_START;
++    }
++   else
++    {
++    *PhyState&=~SMODE_AUTO;   /*The Phy is not capable of auto negotiation!  */
++    m=NWAYadvertise;
++    for(j=0x8000,i=0;(i<16)&&((j&m)==0);i++,j>>=1);
++    m=j;
++    j=0;
++    if (m&(NWAY_FD100|NWAY_HD100))
++      {
++      j=PHY_100;
++      m&=(NWAY_FD100|NWAY_HD100);
++      }
++    if (m&(NWAY_FD100|NWAY_FD10))
++      j |= PHY_FD;
++    if (cpMacDebug)
++      mdioPrintf("Requested PHY mode %s Duplex %s Mbps\n",(j&PHY_FD)?"Full":"Half",(j&PHY_100)?"100":"10");
++    _mdioUserAccessWrite(PhyDev, PHY_CONTROL_REG, PhyNum, j);
++    *PhyState&=~PHY_SPEED_MASK;
++    if (j&PHY_100)
++      *PhyState|=(1<<PHY_SPEED_OFFSET);
++    *PhyState&=~PHY_DUPLEX_MASK;
++    if (j&PHY_FD)
++      *PhyState|=(1<<PHY_DUPLEX_OFFSET);
++    *PhyState|=PHY_CHANGE|PHY_LINK_TO|LINK_WAIT;
++    }
++     _mdioMdixDelay(PhyDev);  /* If AutoMdix add delay */
++  }
++
++void _MdioNwayStartState(PHY_DEVICE *PhyDev)
++  {
++  bit32u *PhyState = &PhyDev->PhyState;
++  bit32u PhyNum,PhyMode;
++
++  PhyNum=(*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET;
++
++  /*Wait for Negotiation to start                                            */
++
++  PhyMode=_mdioUserAccessRead(PhyDev, PHY_CONTROL_REG, PhyNum);
++
++  if((PhyMode&RENEGOTIATE)==0)
++    {
++    _mdioUserAccessRead(PhyDev, PHY_STATUS_REG, PhyNum); /*Flush pending latch bits*/
++    *PhyState&=~(PHY_STATE_MASK|PHY_TIM_MASK);
++    *PhyState|=PHY_CHANGE|NWAY_WAIT|PHY_NWDN_TO;
++    _mdioMdixDelay(PhyDev);  /* If AutoMdix add delay */
++    }
++   else
++    {
++    if (*PhyState&PHY_TIM_MASK)
++      *PhyState=(*PhyState&~PHY_TIM_MASK)|((*PhyState&PHY_TIM_MASK)-(1<<PHY_TIM_OFFSET));
++     else
++      _mdioPhyTimeOut(PhyDev);
++    }
++  }
++
++void _MdioNwayWaitState(PHY_DEVICE *PhyDev)
++  {
++  bit32u *PhyState = &PhyDev->PhyState;
++  bit32u  PhyNum,PhyStatus,NWAYadvertise,NWAYREadvertise,NegMode,i,j;
++
++  PhyNum=(*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET;
++
++  PhyStatus=_mdioUserAccessRead(PhyDev, PHY_STATUS_REG, PhyNum);
++
++  if (PhyStatus&NWAY_COMPLETE)
++    {
++    *PhyState|=PHY_CHANGE;
++    *PhyState&=~PHY_SPEED_MASK;
++    *PhyState&=~PHY_DUPLEX_MASK;
++
++    NWAYadvertise   =_mdioUserAccessRead(PhyDev, NWAY_ADVERTIZE_REG, PhyNum);
++    NWAYREadvertise =_mdioUserAccessRead(PhyDev, NWAY_REMADVERTISE_REG, PhyNum);
++
++    /* Negotiated mode is we and the remote have in common */
++    NegMode = NWAYadvertise & NWAYREadvertise;
++
++    if (cpMacDebug)
++      {
++       mdioPrintf("Phy: %d, ",(*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET);
++       mdioPrintf("NegMode %04X, NWAYadvertise %04X, NWAYREadvertise %04X\n",
++         NegMode,  NWAYadvertise, NWAYREadvertise);
++      }
++
++    /* Limit negotiation to fields below */
++    NegMode &= (NWAY_FD100|NWAY_HD100|NWAY_FD10|NWAY_HD10);
++
++    if (NegMode==0)
++      {
++      NegMode=(NWAY_HD100|NWAY_HD10)&NWAYadvertise; /*or 10 ?? who knows, Phy is not MII compliant*/
++      if(cpMacDebug)
++        {
++         mdioPrintf("Mdio:WARNING: Negotiation complete but NO agreement, default is HD\n");
++         _mdioDumpPhyDetailed(PhyDev);
++        } 
++      }
++    for(j=0x8000,i=0;(i<16)&&((j&NegMode)==0);i++,j>>=1);
++
++
++    NegMode=j;
++    if (cpMacDebug)
++      {
++      mdioPrintf("Negotiated connection: ");
++      if (NegMode&NWAY_FD100) mdioPrintf("FullDuplex 100 Mbs\n");
++      if (NegMode&NWAY_HD100) mdioPrintf("HalfDuplex 100 Mbs\n");
++      if (NegMode&NWAY_FD10) mdioPrintf("FullDuplex 10 Mbs\n");
++      if (NegMode&NWAY_HD10) mdioPrintf("HalfDuplex 10 Mbs\n");
++      }
++    if (NegMode!=0)
++      {
++      if (PhyStatus&PHY_LINKED)
++        *PhyState=(*PhyState&~PHY_STATE_MASK)|LINKED;
++       else
++        *PhyState=(*PhyState&~PHY_STATE_MASK)|LINK_WAIT;
++      if (NegMode&(NWAY_FD100|NWAY_HD100))
++        *PhyState=(*PhyState&~PHY_SPEED_MASK)|(1<<PHY_SPEED_OFFSET);
++      if (NegMode&(NWAY_FD100|NWAY_FD10))
++        *PhyState=(*PhyState&~PHY_DUPLEX_MASK)|(1<<PHY_DUPLEX_OFFSET);
++      }
++    }
++   else
++    {
++    if (*PhyState&PHY_TIM_MASK)
++      *PhyState=(*PhyState&~PHY_TIM_MASK)|((*PhyState&PHY_TIM_MASK)-(1<<PHY_TIM_OFFSET));
++     else
++      _mdioPhyTimeOut(PhyDev);
++    }
++  }
++
++void _MdioLinkWaitState(PHY_DEVICE *PhyDev)
++  {
++  bit32u *PhyState = &PhyDev->PhyState;
++  bit32u  PhyStatus;
++  bit32u  PhyNum;
++
++  PhyNum=(*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET;
++
++  PhyStatus=_mdioUserAccessRead(PhyDev, PHY_STATUS_REG, PhyNum);
++
++  if (PhyStatus&PHY_LINKED)
++    {
++    *PhyState=(*PhyState&~PHY_STATE_MASK)|LINKED;
++    *PhyState|=PHY_CHANGE;
++    }
++   else
++    {
++    if (*PhyState&PHY_TIM_MASK)
++      *PhyState=(*PhyState&~PHY_TIM_MASK)|((*PhyState&PHY_TIM_MASK)-(1<<PHY_TIM_OFFSET));
++     else
++      _mdioPhyTimeOut(PhyDev);
++    }
++  }
++
++void _mdioPhyTimeOut(PHY_DEVICE *PhyDev)
++  {
++  bit32u *PhyState;
++
++  if(_mdioMdixSupported(PhyDev) == 0)
++    return;  /* AutoMdix not supported */
++
++  PhyState = &PhyDev->PhyState;
++
++  /*  Indicate MDI/MDIX mode switch is needed */
++  *PhyState|=PHY_MDIX_SWITCH;
++
++  /* Toggle the MDIX mode indicatir */
++  if(*PhyState & PHY_MDIX)
++    *PhyState &= ~PHY_MDIX_MASK;       /* Current State is MDIX, set to MDI */
++  else
++    *PhyState |=  PHY_MDIX_MASK;      /* Current State is MDI, set to MDIX */
++
++  /* Reset state machine to FOUND */
++  *PhyState=(*PhyState&~PHY_STATE_MASK)|(FOUND);
++  }
++
++void _MdioLoopbackState(PHY_DEVICE *PhyDev)
++  {
++  return;
++  }
++
++void _MdioLinkedState(PHY_DEVICE *PhyDev)
++  {
++  bit32u *PhyState = &PhyDev->PhyState;
++  bit32u  PhyNum   = (*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET;
++
++  if (myMDIO_LINK&(1<<PhyNum)) return;  /* if still Linked, exit*/
++
++  /* Not Linked */
++  *PhyState&=~(PHY_STATE_MASK|PHY_TIM_MASK);
++  if (*PhyState&SMODE_AUTO)
++    *PhyState|=PHY_CHANGE|NWAY_WAIT|PHY_NWDN_TO;
++   else
++    *PhyState|=PHY_CHANGE|PHY_LINK_TO|LINK_WAIT;
++    
++  _mdioMdixDelay(PhyDev);  /* If AutoMdix add delay */
++  }
++
++void _MdioDefaultState(PHY_DEVICE *PhyDev)
++  {
++  bit32u *PhyState = &PhyDev->PhyState;
++  /*Awaiting a cpMacMdioInit call                                             */
++  *PhyState|=PHY_CHANGE;
++  }
++
++
++/*User Calls*********************************************************       */
++
++void cpMacMdioClose(PHY_DEVICE *PhyDev, int Full)
++  {
++  }
++
++
++int cpMacMdioInit(PHY_DEVICE *PhyDev, bit32u miibase, bit32u inst, bit32u PhyMask, bit32u MLinkMask, bit32u MdixMask, bit32u ResetReg, bit32u ResetBit, bit32u MdioBusFreq, bit32u MdioClockFreq, int verbose, void *Info)
++  {
++  bit32u HighestChannel;
++  bit32u ControlState;
++  bit32u *PhyState = &PhyDev->PhyState;
++  bit32u clkdiv;                                                  /*MJH+030328*/
++
++  cpMacDebug=verbose;  
++ 
++  PhyDev->miibase   = miibase;
++  PhyDev->inst      = inst;
++  PhyDev->PhyMask   = PhyMask;
++  PhyDev->MLinkMask = MLinkMask;
++  PhyDev->MdixMask  = MdixMask;
++#ifdef _CPHAL_CPMAC
++  PhyDev->HalDev    = (HAL_DEVICE*) Info;
++#endif
++
++  *PhyState &= ~PHY_MDIX_MASK;   /* Set initial State to MDI */
++   
++  /* Check that the channel supplied is within range */
++  HighestChannel = (myMDIO_CONTROL & MDIO_CONTROL_HIGHEST_USER_CHANNEL) > 8;
++  if(inst > HighestChannel)
++    return(HighestChannel);
++
++  /*Setup MII MDIO access regs                                              */
++
++  /* Calculate the correct value for the mclkdiv */
++  /* See PITS #14 */
++  if (MdioClockFreq)                                              /*MJH+030402*/
++     clkdiv = (MdioBusFreq / MdioClockFreq) - 1;                  /*MJH+030402*/
++  else                                                            /*MJH+030402*/
++     clkdiv = 0xFF;                                               /*MJH+030402*/
++
++  ControlState  = MDIO_CONTROL_ENABLE;
++  ControlState |= (clkdiv & MDIO_CONTROL_CLKDIV);                 /*MJH+030328*/
++
++  /*
++      If mii is not out of reset or if the Control Register is not set correctly
++      then initalize
++  */
++  if( !(VOLATILE32(ResetReg) & (1 << ResetBit)) ||
++     ((myMDIO_CONTROL & (MDIO_CONTROL_CLKDIV | MDIO_CONTROL_ENABLE)) != ControlState) )/*GSG~030404*/
++    {
++    /*  MII not setup, Setup initial condition  */
++    VOLATILE32(ResetReg) &= ~(1 << ResetBit);
++    _mdioDelayEmulate(PhyDev, 64);
++    VOLATILE32(ResetReg) |= (1 << ResetBit);  /* take mii out of reset  */
++    _mdioDelayEmulate(PhyDev, 64);
++    myMDIO_CONTROL = ControlState;  /* Enable MDIO   */
++    }
++
++  *PhyState=INIT;
++
++  if (cpMacDebug)
++    mdioPrintf("cpMacMdioInit\n");
++  _mdioDumpState(PhyDev);
++  return(0);
++  }
++
++void cpMacMdioSetPhyMode(PHY_DEVICE *PhyDev,bit32u PhyMode)
++  {
++  bit32u *PhyState = &PhyDev->PhyState;
++  bit32u CurrentState;
++
++  PhyDev->PhyMode = PhyMode;   /* used for AUTOMIDX, planned to replace PhyState fields */
++
++  *PhyState&=~PHY_SMODE_MASK;
++
++  if (PhyMode&NWAY_AUTO)  *PhyState|=SMODE_AUTO;
++  if (PhyMode&NWAY_FD100) *PhyState|=SMODE_FD100;
++  if (PhyMode&NWAY_HD100) *PhyState|=SMODE_HD100;
++  if (PhyMode&NWAY_FD10)  *PhyState|=SMODE_FD10;
++  if (PhyMode&NWAY_HD10)  *PhyState|=SMODE_HD10;
++
++  CurrentState=*PhyState&PHY_STATE_MASK;
++  if ((CurrentState==NWAY_START)||
++      (CurrentState==NWAY_WAIT) ||
++      (CurrentState==LINK_WAIT) ||
++      (CurrentState==LINKED)      )
++    *PhyState=(*PhyState&~PHY_STATE_MASK)|FOUND|PHY_CHANGE;
++  if (cpMacDebug)
++    mdioPrintf("cpMacMdioSetPhyMode:%08X Auto:%d, FD10:%d, HD10:%d, FD100:%d, HD100:%d\n", PhyMode,
++     PhyMode&NWAY_AUTO, PhyMode&NWAY_FD10, PhyMode&NWAY_HD10, PhyMode&NWAY_FD100,
++     PhyMode&NWAY_HD100);
++  _mdioDumpState(PhyDev);
++  }
++
++/* cpMacMdioTic is called every 10 mili seconds to process Phy states         */
++
++int cpMacMdioTic(PHY_DEVICE *PhyDev)
++  {
++  bit32u *PhyState = &PhyDev->PhyState;
++  bit32u  CurrentState;
++
++  /*Act on current state of the Phy                                          */
++
++  CurrentState=*PhyState;
++  switch(CurrentState&PHY_STATE_MASK)
++    {
++    case INIT:       _MdioInitState(PhyDev);      break;
++    case FINDING:    _MdioFindingState(PhyDev);   break;
++    case FOUND:      _MdioFoundState(PhyDev);     break;
++    case NWAY_START: _MdioNwayStartState(PhyDev); break;
++    case NWAY_WAIT:  _MdioNwayWaitState(PhyDev);  break;
++    case LINK_WAIT:  _MdioLinkWaitState(PhyDev);  break;
++    case LINKED:     _MdioLinkedState(PhyDev);    break;
++    case LOOPBACK:   _MdioLoopbackState(PhyDev);  break;
++    default:         _MdioDefaultState(PhyDev);   break;
++    }
++
++  /*Dump state info if a change has been detected                            */
++
++  if ((CurrentState&~PHY_TIM_MASK)!=(*PhyState&~PHY_TIM_MASK))
++    _mdioDumpState(PhyDev);
++
++  /*  Check is MDI/MDIX mode switch is needed */
++  if(*PhyState & PHY_MDIX_SWITCH)
++    {
++    bit32u Mdix;
++
++    *PhyState &= ~PHY_MDIX_SWITCH;  /* Clear Mdix Flip indicator */
++
++    if(*PhyState & PHY_MDIX)
++      Mdix = 1;
++    else
++      Mdix = 0;
++    return(_MIIMDIO_MDIXFLIP|Mdix);
++    }
++
++  /*Return state change to user                                              */
++
++  if (*PhyState&PHY_CHNG_MASK)
++    {
++    *PhyState&=~PHY_CHNG_MASK;
++    return(1);
++    }
++   else
++    return(0);
++  }
++
++/* cpMacMdioGetDuplex is called to retrieve the Duplex info                   */
++
++int cpMacMdioGetDuplex(PHY_DEVICE *PhyDev)
++  {
++  bit32u *PhyState = &PhyDev->PhyState;
++  return((*PhyState&PHY_DUPLEX_MASK)?1:0);  /* return 0 or a 1  */
++  }
++
++/* cpMacMdioGetSpeed is called to retreive the Speed info                     */
++
++int cpMacMdioGetSpeed(PHY_DEVICE *PhyDev)
++  {
++  bit32u *PhyState = &PhyDev->PhyState;
++  return(*PhyState&PHY_SPEED_MASK);
++  }
++
++/* cpMacMdioGetPhyNum is called to retreive the Phy Device Adr info           */
++
++int cpMacMdioGetPhyNum(PHY_DEVICE *PhyDev)
++  {
++  bit32u *PhyState = &PhyDev->PhyState;
++  return((*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET);
++  }
++
++/* cpMacMdioGetLoopback is called to Determine if the LOOPBACK state has been reached*/
++
++int cpMacMdioGetLoopback(PHY_DEVICE *PhyDev)
++  {
++  bit32u *PhyState = &PhyDev->PhyState;
++  return((*PhyState&PHY_STATE_MASK)==LOOPBACK);
++  }
++/* cpMacMdioGetLinked is called to Determine if the LINKED state has been reached*/
++
++int cpMacMdioGetLinked(PHY_DEVICE *PhyDev)
++  {
++  bit32u *PhyState = &PhyDev->PhyState;
++  return((*PhyState&PHY_STATE_MASK)==LINKED);
++  }
++
++void cpMacMdioLinkChange(PHY_DEVICE *PhyDev)
++  {
++  bit32u *PhyState = &PhyDev->PhyState;
++  bit32u  PhyNum,PhyStatus;
++
++  PhyNum=(*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET;
++
++  if (cpMacMdioGetLinked(PhyDev))
++    {
++    PhyStatus=_mdioUserAccessRead(PhyDev, PHY_STATUS_REG, PhyNum);
++
++    if ((PhyStatus&PHY_LINKED)==0)
++      {
++      *PhyState&=~(PHY_TIM_MASK|PHY_STATE_MASK);
++      if (*PhyState&SMODE_AUTO)
++        {
++        _mdioUserAccessWrite(PhyDev, PHY_CONTROL_REG, PhyNum, AUTO_NEGOTIATE_EN|RENEGOTIATE);
++        *PhyState|=PHY_CHANGE|PHY_NWST_TO|NWAY_START;
++        }
++       else
++        {
++        *PhyState|=PHY_CHANGE|PHY_LINK_TO|LINK_WAIT;
++        }
++      }
++    }
++  }
++
++void cpMacMdioGetVer(bit32u miibase, bit32u *ModID,  bit32u *RevMaj,  bit32u *RevMin)
++  {
++  bit32u  Ver;
++
++  Ver = MDIO_VER(miibase);
++
++  *ModID  = (Ver & MDIO_VER_MODID) >> 16;
++  *RevMaj = (Ver & MDIO_VER_REVMAJ) >> 8;
++  *RevMin = (Ver & MDIO_VER_REVMIN);
++  }
++
++int cpMacMdioGetPhyDevSize(void)
++  {
++  return(sizeof(PHY_DEVICE));
++  }
++
++  /* returns 0 if current Phy has AutoMdix support, otherwise 0 */
++int _mdioMdixSupported(PHY_DEVICE *PhyDev)
++  {
++  bit32u *PhyState = &PhyDev->PhyState;
++  bit32u PhyNum;
++
++  if((PhyDev->PhyMode & NWAY_AUTOMDIX) == 0)
++    return(0);  /* AutoMdix not turned on */
++
++  PhyNum=(*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET;
++  if( ((1<<PhyNum) & PhyDev->MdixMask) == 0)
++    return(0);  /*  Phy does not support AutoMdix*/
++
++  return(1);
++  }
++
++/* If current Phy has AutoMdix support add Mdix Delay to the Timer State Value */
++void _mdioMdixDelay(PHY_DEVICE *PhyDev)
++  {
++  int Delay;
++  bit32u *PhyState = &PhyDev->PhyState;  
++#ifdef _CPHAL_CPMAC
++  HAL_DEVICE *HalDev = PhyDev->HalDev;
++#endif
++
++  if(_mdioMdixSupported(PhyDev) == 0)
++    return;  /* AutoMdix not supported */
++/* Currently only supported when used with the CPMAC */
++#ifdef _CPHAL_CPMAC
++  /* Get the Delay value in milli-seconds and convert to ten-milli second value */
++  Delay = cpmacRandomRange(HalDev, _AUTOMDIX_DELAY_MIN, _AUTOMDIX_DELAY_MAX);
++  Delay /= 10;
++
++  /*  Add AutoMidx Random Switch Delay to AutoMdix Link Delay */
++
++  Delay += (PHY_MDIX_TO>>PHY_TIM_OFFSET);
++
++  /* Change Timeout value to AutoMdix standard */
++  *PhyState &= ~(PHY_TIM_MASK);  /* Clear current Time out value */
++  *PhyState |=  (Delay<<PHY_TIM_OFFSET);     /* Set new value */
++#endif
++  }
++
++
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/cpmdio.h linux-2.4.30/drivers/net/avalanche_cpmac/cpmdio.h
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/cpmdio.h     1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/cpmdio.h  2005-04-15 05:10:41.000000000 +0200
+@@ -0,0 +1,73 @@
++/*****************************************************************************
++**      TNETD53xx Software Support
++**      Copyright(c) 2002, Texas Instruments Incorporated. All Rights Reserved.
++**
++**      FILE: cpmdio.h   User Include for MDIO API Access
++**
++**      DESCRIPTION:
++**              This include file contains definitions for the the MDIO API
++**
++**      HISTORY:
++**              27Mar02 Michael Hanrahan Original (modified from emacmdio.h)
++**              04Apr02 Michael Hanrahan Added Interrupt Support
++*****************************************************************************/
++#ifndef _INC_CPMDIO
++#define _INC_CPMDIO
++
++
++#ifndef __CPHAL_CPMDIO
++typedef void PHY_DEVICE;
++#endif
++
++
++/*Version Information */
++
++void cpMacMdioGetVer(bit32u miiBase, bit32u *ModID,  bit32u *RevMaj,  bit32u *RevMin);
++
++/*Called once at the begining of time                                        */
++
++int  cpMacMdioInit(PHY_DEVICE *PhyDev, bit32u miibase, bit32u inst, bit32u PhyMask, bit32u MLinkMask, bit32u MdixMask, bit32u ResetBase, bit32u ResetBit, bit32u MdioBusFreq, bit32u MdioClockFreq, int verbose, void *Info);
++int  cpMacMdioGetPhyDevSize(void);
++
++
++/*Called every 10 mili Seconds, returns TRUE if there has been a mode change */
++
++int cpMacMdioTic(PHY_DEVICE *PhyDev);
++
++/*Called to set Phy mode                                                     */
++
++void cpMacMdioSetPhyMode(PHY_DEVICE *PhyDev,bit32u PhyMode);
++
++/*Calls to retreive info after a mode change!                                */
++
++int  cpMacMdioGetDuplex(PHY_DEVICE *PhyDev);
++int  cpMacMdioGetSpeed(PHY_DEVICE *PhyDev);
++int  cpMacMdioGetPhyNum(PHY_DEVICE *PhyDev);
++int  cpMacMdioGetLinked(PHY_DEVICE *PhyDev);
++void cpMacMdioLinkChange(PHY_DEVICE *PhyDev);
++
++/*  Shot Down  */
++
++void cpMacMdioClose(PHY_DEVICE *PhyDev, int Full);
++
++
++/* Phy Mode Values  */
++#define NWAY_AUTOMDIX       (1<<16)
++#define NWAY_FD100          (1<<8)
++#define NWAY_HD100          (1<<7)
++#define NWAY_FD10           (1<<6)
++#define NWAY_HD10           (1<<5)
++#define NWAY_AUTO           (1<<0)
++
++/*
++ *
++ *    Tic() return values
++ *
++ */
++
++#define _MIIMDIO_MDIXFLIP (1<<28)
++
++#define _AUTOMDIX_DELAY_MIN  80  /* milli-seconds*/
++#define _AUTOMDIX_DELAY_MAX 200  /* milli-seconds*/
++
++#endif  /*  _INC_CPMDIO */
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/cppi_cpmac.c linux-2.4.30/drivers/net/avalanche_cpmac/cppi_cpmac.c
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/cppi_cpmac.c 1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/cppi_cpmac.c      2005-04-15 05:10:41.000000000 +0200
+@@ -0,0 +1,1345 @@
++/*************************************************************************
++ *  TNETDxxxx Software Support
++ *  Copyright (c) 2002,2003 Texas Instruments Incorporated. All Rights Reserved.
++ *
++ *  FILE: cppi.c
++ *
++ *  DESCRIPTION:
++ *      This file contains shared code for all CPPI modules.
++ *
++ *  HISTORY:
++ *   7Aug02 Greg RC1.00  Original Version created.
++ *  27Sep02 Mick RC1.01  Merged for use by CPMAC/CPSAR
++ *  16Oct02 Mick RC1.02  Performance Tweaks (see cppihist.txt)
++ *  12Nov02 Mick RC1.02  Updated to use cpmac_reg.h
++ *  09Jan03 Mick RC3.01  Removed modification to RxBuffer ptr
++ *  28Mar03 Mick 1.03    RxReturn now returns error if Malloc Fails
++ *  10Apr03 Mick 1.03.02 Added Needs Buffer Support
++ *  11Jun03 Mick 1.06.02 halSend() errors corrected
++ *  23Aug04 Mick 1.07.08 cpmac only - Send: bypass threshold check if TxInts re-enabled
++ *
++ *  @author  Greg Guyotte
++ *  @version 1.00
++ *  @date    7-Aug-2002
++ *****************************************************************************/
++/* each CPPI module must modify this file, the rest of the
++                     code in cppi.c should be totally shared *//* Each CPPI module MUST properly define all constants shown below */
++
++/* CPPI registers */
++
++/* the following defines are not CPPI specific */
++
++static int TxInt(HAL_DEVICE *HalDev, int Ch, int Queue, int *MoreWork);                     
++
++static void FreeRx(HAL_DEVICE *HalDev, int Ch)
++  {
++   HAL_RCB *rcb_ptr;                                                /*+GSG 030303*/
++   int rcbSize = (sizeof(HAL_RCB)+0xf)&~0xf;                        /*+GSG 030303*/
++   int Num = HalDev->ChData[Ch].RxNumBuffers, i;                    /*+GSG 030303*/
++
++   /* Free Rx data buffers attached to descriptors, if necessary */
++   if (HalDev->RcbStart[Ch] != 0)                                   /*+GSG 030303*/
++     {                                                              /*+GSG 030303*/
++      for(i=0;i<Num;i++)                                            /*+GSG 030303*/
++        {                                                           /*+GSG 030303*/
++         rcb_ptr = (HAL_RCB *)(HalDev->RcbStart[Ch] + (i*rcbSize)); /*+GSG 030303*/
++
++         /* free the data buffer */
++         if (rcb_ptr->DatPtr != 0)
++       {
++
++        HalDev->OsFunc->FreeRxBuffer((void *)rcb_ptr->OsInfo, (void *)rcb_ptr->DatPtr);
++        rcb_ptr->OsInfo=0;                                        /*MJH+030522*/
++        rcb_ptr->DatPtr=0;                                        /*MJH+030522*/
++       }
++    }                                                           /*+GSG 030303*/
++     }                                                              /*+GSG 030303*/
++
++   /* free up all desciptors at once */
++   HalDev->OsFunc->FreeDmaXfer(HalDev->RcbStart[Ch]);
++
++   /* mark buffers as freed */
++   HalDev->RcbStart[Ch] = 0;
++  }
++
++static void FreeTx(HAL_DEVICE *HalDev, int Ch, int Queue)
++  {
++
++/*+GSG 030303*/
++
++   /* free all descriptors at once */
++   HalDev->OsFunc->FreeDmaXfer(HalDev->TcbStart[Ch][Queue]);
++
++   HalDev->TcbStart[Ch][Queue] = 0;
++  }
++
++/* return of 0 means that this code executed, -1 means the interrupt was not
++   a teardown interrupt */
++static int RxTeardownInt(HAL_DEVICE *HalDev, int Ch)
++  {
++   bit32u base = HalDev->dev_base;
++
++   /* check to see if the interrupt is a teardown interrupt */
++   if (((CPMAC_RX_INT_ACK( base , Ch ))  & TEARDOWN_VAL) == TEARDOWN_VAL)
++     {
++      /* finish channel teardown */
++
++      /* Free channel resources on a FULL teardown */
++      if (HalDev->RxTeardownPending[Ch] & FULL_TEARDOWN)
++        {
++         FreeRx(HalDev, Ch);
++        }
++
++      /* bug fix - clear Rx channel pointers on teardown */
++      HalDev->RcbPool[Ch] = 0;
++      HalDev->RxActQueueHead[Ch]  = 0;
++      HalDev->RxActQueueCount[Ch] = 0;
++      HalDev->RxActive[Ch] = FALSE;
++
++      /* write completion pointer */
++      (CPMAC_RX_INT_ACK( base , Ch ))  = TEARDOWN_VAL;
++
++      /* use direction bit as a teardown pending bit! May be able to
++         use only one teardown pending integer in HalDev */
++
++      HalDev->RxTeardownPending[Ch] &= ~RX_TEARDOWN;
++
++      HalDev->ChIsOpen[Ch][DIRECTION_RX] = 0;
++
++      HalDev->ChIsOpen[Ch][DIRECTION_RX] = 0;
++      CPMAC_RX_INTMASK_CLEAR(HalDev->dev_base) = (1<<Ch);
++      if ((HalDev->RxTeardownPending[Ch] & BLOCKING_TEARDOWN) == 0)
++    {
++
++     HalDev->OsFunc->TeardownComplete(HalDev->OsDev, Ch, DIRECTION_RX);
++    }
++      HalDev->RxTeardownPending[Ch] = 0;
++
++      return (EC_NO_ERRORS);
++     }
++   return (-1);
++  }
++
++/* return of 0 means that this code executed, -1 means the interrupt was not
++   a teardown interrupt.  Note: this code is always called with Queue == 0 (hi priority). */
++static int TxTeardownInt(HAL_DEVICE *HalDev, int Ch, int Queue)
++  {
++   bit32u base = HalDev->dev_base;
++   HAL_TCB *Last, *Curr, *First;                                    /*+GSG 030303*/
++   int i;
++
++   if (((CPMAC_TX_INT_ACK( base , Ch ))  & TEARDOWN_VAL) == TEARDOWN_VAL)
++     {
++      /* perform all actions for both queues (+GSG 040212) */
++      for (i=0; i<HalDev->ChData[Ch].TxNumQueues; i++)
++        {
++         /* return outstanding buffers to OS                             +RC3.02*/
++         Curr = HalDev->TxActQueueHead[Ch][i];                     /*+GSG 030303*/
++         First = Curr;                                                 /*+GSG 030303*/
++         while (Curr)                                                  /*+GSG 030303*/
++           {                                                           /*+GSG 030303*/
++            /* Pop TCB(s) for packet from the stack */                 /*+GSG 030303*/
++            Last = Curr->Eop;                                          /*+GSG 030303*/
++            HalDev->TxActQueueHead[Ch][i] = Last->Next;            /*+GSG 030303*/
++                                                                    /*+GSG 030303*/
++            /* return to OS */                                         /*+GSG 030303*/
++            HalDev->OsFunc->SendComplete(Curr->OsInfo);                /*+GSG 030303*/
++                                                                    /*+GSG 030303*/
++            /* Push Tcb(s) back onto the stack */                      /*+GSG 030303*/
++            Curr = Last->Next;                                         /*+GSG 030303*/
++            Last->Next = HalDev->TcbPool[Ch][i];                   /*+GSG 030303*/
++            HalDev->TcbPool[Ch][i] = First;                        /*+GSG 030303*/
++                                                                    /*+GSG 030303*/
++            /* set the first(SOP) pointer for the next packet */       /*+GSG 030303*/
++            First = Curr;                                              /*+GSG 030303*/
++           }                                                           /*+GSG 030303*/
++        }
++
++      /* finish channel teardown */
++
++      if (HalDev->TxTeardownPending[Ch] & FULL_TEARDOWN)
++        {
++         FreeTx(HalDev, Ch, 0);
++
++         if (HalDev->ChData[Ch].TxNumQueues == 2)
++           FreeTx(HalDev, Ch, 1);
++        } /* if FULL teardown */
++
++      /* perform all actions for both queues (+GSG 040212) */
++      for (i=0; i<HalDev->ChData[Ch].TxNumQueues; i++)
++        {
++         /* bug fix - clear Tx channel pointers on teardown */
++         HalDev->TcbPool[Ch][i] = 0;
++         HalDev->TxActQueueHead[Ch][i]  = 0;
++         HalDev->TxActQueueCount[Ch][i] = 0;
++         HalDev->TxActive[Ch][i]        = FALSE;
++        }
++
++      /* write completion pointer, only needed for the high priority queue */
++      (CPMAC_TX_INT_ACK( base , Ch ))  = TEARDOWN_VAL;
++
++      /* no longer pending teardown */
++      HalDev->TxTeardownPending[Ch] &= ~TX_TEARDOWN;
++
++      HalDev->ChIsOpen[Ch][DIRECTION_TX] = 0;
++
++      HalDev->ChIsOpen[Ch][DIRECTION_TX] = 0;
++      CPMAC_TX_INTMASK_CLEAR(HalDev->dev_base) = (1<<Ch);
++      if ((HalDev->TxTeardownPending[Ch] & BLOCKING_TEARDOWN) == 0)
++        {
++
++         HalDev->OsFunc->TeardownComplete(HalDev->OsDev, Ch, DIRECTION_TX);
++        }
++      HalDev->TxTeardownPending[Ch] = 0;
++
++      return (EC_NO_ERRORS);
++     }
++   return (-1);
++  }
++
++/* +GSG 030421 */
++static void AddToRxQueue(HAL_DEVICE *HalDev, HAL_RCB *FirstRcb, HAL_RCB *LastRcb, int FragCount, int Ch)
++  {
++   if (HalDev->RxActQueueHead[Ch]==0)
++     {
++
++      HalDev->RxActQueueHead[Ch]=FirstRcb;
++      HalDev->RxActQueueTail[Ch]=LastRcb;
++      if (!HalDev->RxActive[Ch])
++        {
++         /* write Rx Queue Head Descriptor Pointer */
++         ((CPMAC_RX_HDP(  HalDev->dev_base  ,  Ch  )) )  = VirtToPhys(FirstRcb) - HalDev->offset;
++         HalDev->RxActive[Ch]=TRUE;
++        }
++     }
++    else
++     {
++      register HAL_RCB *OldTailRcb;
++      register bit32u rmode;
++      
++      HalDev->OsFunc->CriticalOn();
++      OldTailRcb=HalDev->RxActQueueTail[Ch];
++      OldTailRcb->Next=(void *)FirstRcb;
++      OldTailRcb=VirtToVirtNoCache(OldTailRcb);
++      OldTailRcb->HNext=VirtToPhys(FirstRcb) - HalDev->offset;
++      HalDev->RxActQueueTail[Ch]=LastRcb;
++      rmode=OldTailRcb->mode;
++      if (rmode&CB_EOQ_BIT)
++        {
++        rmode&=~CB_EOQ_BIT;
++        ((CPMAC_RX_HDP(  HalDev->dev_base  ,  Ch  )) )  = VirtToPhys(FirstRcb) - HalDev->offset;
++        OldTailRcb->mode=rmode;
++        }   
++      HalDev->OsFunc->CriticalOff();
++     }
++  }
++
++/**
++ *  @ingroup CPHAL_Functions
++ *  This function is called to indicate to the CPHAL that the upper layer
++ *  software has finished processing the receive data (given to it by
++ *  osReceive()).  The CPHAL will then return the appropriate receive buffers
++ *  and buffer descriptors to the available pool.
++ *
++ *  @param   HalReceiveInfo   Start of receive buffer descriptor chain returned to
++ *                      CPHAL.
++ *  @param   StripFlag  Flag indicating whether the upper layer software has
++ *                      retained ownership of the receive data buffers.
++ *<BR>
++ * 'FALSE' means  that the CPHAL can reuse the receive data buffers.
++ *<BR>
++ * 'TRUE' : indicates the data buffers were retained by the OS
++ *<BR>
++ * NOTE:  If StripFlag is TRUE, it is the responsibility of the upper layer software to free the buffers when they are no longer needed.
++ *
++ *  @return EC_NO_ERRORS (ok). <BR>
++ *          Possible Error Codes:<BR>
++ *          @ref EC_VAL_INVALID_STATE "EC_VAL_INVALID_STATE"<BR>
++ *          @ref EC_VAL_RCB_NEEDS_BUFFER "EC_VAL_RCB_NEEDS_BUFFER"<BR>
++ *          @ref EC_VAL_RCB_DROPPED "EC_VAL_RCB_DROPPED"<BR>
++ */
++static int halRxReturn(HAL_RECEIVEINFO *HalReceiveInfo,
++            int StripFlag)
++  {
++   int Ch, i;
++   HAL_RCB *LastRcb;
++   HAL_DEVICE *HalDev;
++   int RcbSize;
++   int FragCount;
++
++   Ch = HalReceiveInfo->mode&0x0ff;
++   HalDev = (HAL_DEVICE *)HalReceiveInfo->Off_BLen;
++   FragCount = HalReceiveInfo->mode>>8;
++      
++   if (HalDev->State != enOpened)
++     return(EC_CPMAC |EC_FUNC_RXRETURN|EC_VAL_INVALID_STATE);
++
++   LastRcb=(HAL_RCB *)HalReceiveInfo->Eop;
++   LastRcb->HNext=0;
++   LastRcb->Next=0;
++   RcbSize = HalDev->ChData[Ch].RxBufSize;
++
++   if (FragCount>1)
++     {
++      LastRcb->Off_BLen=RcbSize;
++      LastRcb->mode=CB_OWNERSHIP_BIT;
++     }
++
++   HalReceiveInfo->Off_BLen=RcbSize;
++   HalReceiveInfo->mode=CB_OWNERSHIP_BIT;
++
++   /* If OS has kept the buffers for this packet, attempt to alloc new buffers */
++   if (StripFlag)
++     {
++      int rc=0;                                                      /*MJH+030417*/
++      int GoodCount=0;                                               /*GSG+030421*/       
++      HAL_RCB *TempRcb;
++      char *pBuf;
++      HAL_RCB *CurrHeadRcb = HalReceiveInfo, *LastGoodRcb=0;         /* +GSG 030421 */
++
++      TempRcb = HalReceiveInfo;
++      for (i=0; i<FragCount; i++)
++        {
++         if (TempRcb == 0)
++           {
++            dbgPrintf("Rx Return error while allocating new buffers\n");
++            dbgPrintf("Rcb = %08x, Rcb->Eop = %08x, FragCount = %d:%d\n",
++              (bit32u)HalReceiveInfo, (bit32u)HalReceiveInfo->Eop, FragCount,i);
++            osfuncSioFlush();
++
++            return(EC_CPPI|EC_FUNC_RXRETURN|EC_VAL_CORRUPT_RCB_CHAIN);
++           }
++
++         pBuf= (char *) HalDev->OsFunc->MallocRxBuffer(RcbSize,0,
++                             0xF,HalDev->ChData[Ch].OsSetup,
++                             (void *)TempRcb,
++                             (void *)&TempRcb->OsInfo,
++                             (void *) HalDev->OsDev);
++         if (!pBuf)
++           {
++            /* malloc failed, add this RCB to Needs Buffer List */
++            (HAL_RCB *)TempRcb->Eop = TempRcb;                                  /* GSG +030430 */
++            TempRcb->mode=1<<8|Ch;
++            TempRcb->Off_BLen=(bit32u)HalDev;
++            
++            if(HalDev->NeedsCount < MAX_NEEDS)                                  /* +MJH 030410 */
++              {                                                                 /* +MJH 030410 */
++               HalDev->Needs[HalDev->NeedsCount] = (HAL_RECEIVEINFO *) TempRcb; /* +MJH 030410 */
++               HalDev->NeedsCount++;                                            /* +MJH 030410 */
++               rc = (EC_CPPI|EC_FUNC_RXRETURN|EC_VAL_RCB_NEEDS_BUFFER);         /* ~MJH 030417 */
++              }                                                                 /* +MJH 030410 */
++             else                                                               /* +MJH 030410 */
++               rc = (EC_CPPI|EC_FUNC_RXRETURN|EC_VAL_RCB_DROPPED);              /* ~MJH 030417 */
++
++            /* requeue any previous RCB's that were ready to go before this one */
++            if (GoodCount > 0)                                                  /* +GSG 030421 */
++              {                                                                 /* +GSG 030421 */
++               LastGoodRcb->HNext=0;                                            /* +GSG 030430 */
++               LastGoodRcb->Next=0;                                             /* +GSG 030430 */
++               osfuncDataCacheHitWritebackAndInvalidate((void *)LastGoodRcb, 16);            /* +GSG 030430 */
++
++               AddToRxQueue(HalDev, CurrHeadRcb, LastGoodRcb, GoodCount, Ch);   /* +GSG 030421 */
++               GoodCount = 0;                                                   /* +GSG 030421 */
++              }                                                                 /* +GSG 030421 */
++
++            CurrHeadRcb = TempRcb->Next;                                        /* +GSG 030421 */
++           }
++          else                                                                  /* +GSG 030421 */
++           {                                                                    /* +GSG 030421 */
++            /* malloc succeeded, requeue the RCB to the hardware */
++            TempRcb->BufPtr=VirtToPhys(pBuf) - HalDev->offset;
++            TempRcb->DatPtr=pBuf;
++            /* Emerald fix 10/29 */
++            osfuncDataCacheHitWritebackAndInvalidate((void *)TempRcb, 16);
++
++            /* i store the last good RCB in case the malloc fails for the
++               next fragment.  This ensures that I can go ahead and return
++               a partial chain of RCB's to the hardware */
++            LastGoodRcb = TempRcb;                                              /* +GSG 030421 */
++            GoodCount++;                                                        /* +GSG 030421 */
++           }                                                                    /* +GSG 030421 */
++         TempRcb = TempRcb->Next;
++        } /*  end of Frag loop */
++      /* if there any good RCB's to requeue, do so here */
++      if (GoodCount > 0)                                                        /* +GSG 030421 */
++        {
++         AddToRxQueue(HalDev, CurrHeadRcb, LastGoodRcb, GoodCount, Ch);          /* +GSG 030421 */
++        }
++      return(rc);                                                               /* ~GSG 030421 */
++     }
++   else
++     {
++      /*  Not Stripping */
++      /* Emerald */
++      /* Write Back SOP and last RCB */
++      osfuncDataCacheHitWritebackAndInvalidate((void *)HalReceiveInfo, 16);
++
++      if (FragCount > 1)
++        {
++         osfuncDataCacheHitWritebackAndInvalidate((void *)LastRcb, 16);
++        }
++      /* if not stripping buffers, always add to queue */
++      AddToRxQueue(HalDev, HalReceiveInfo, LastRcb, FragCount, Ch); /*MJH~030520*/
++     }
++
++   return(EC_NO_ERRORS);
++  }
++
++/* +MJH 030410
++   Trys to liberate an RCB until liberation fails.
++   Note: If liberation fails then RxReturn will re-add the RCB to the
++         Needs list.
++*/
++static void NeedsCheck(HAL_DEVICE *HalDev)
++{
++    HAL_RECEIVEINFO* HalRcb;
++    int rc;
++    HalDev->OsFunc->CriticalOn();
++    while(HalDev->NeedsCount)
++      {
++      HalDev->NeedsCount--;
++      HalRcb = HalDev->Needs[HalDev->NeedsCount];
++      rc =  halRxReturn(HalRcb, 1);
++      /* short circuit if RxReturn starts to fail */
++      if (rc != 0)
++        break;
++      }
++    HalDev->OsFunc->CriticalOff();
++}
++
++/*
++ *  This function allocates transmit buffer descriptors (internal CPHAL function).
++ *  It creates a high priority transmit queue by default for a single Tx
++ *  channel.  If QoS is enabled for the given CPHAL device, this function
++ *  will also allocate a low priority transmit queue.
++ *
++ *  @param   HalDev   CPHAL module instance. (set by cphalInitModule())
++ *  @param   Ch       Channel number.
++ *
++ *  @return  0 OK, Non-Zero Not OK
++ */
++static int InitTcb(HAL_DEVICE *HalDev, int Ch)
++  {
++   int i, Num = HalDev->ChData[Ch].TxNumBuffers;
++   HAL_TCB *pTcb=0;
++   char *AllTcb;
++   int  tcbSize, Queue;
++   int SizeMalloc;
++
++   tcbSize = (sizeof(HAL_TCB)+0xf)&~0xf;
++   SizeMalloc = (tcbSize*Num)+0xf;
++
++   for (Queue=0; Queue < HalDev->ChData[Ch].TxNumQueues; Queue++)
++     {
++      if (HalDev->TcbStart[Ch][Queue] == 0)
++        {
++
++         /* malloc all TCBs at once */
++         AllTcb = (char *)HalDev->OsFunc->MallocDmaXfer(SizeMalloc,0,0xffffffff);
++         if (!AllTcb)
++           {
++            return(EC_CPPI|EC_FUNC_HAL_INIT|EC_VAL_TCB_MALLOC_FAILED);
++           }
++
++         HalDev->OsFunc->Memset(AllTcb, 0, SizeMalloc);
++
++         /* keep this address for freeing later */
++         HalDev->TcbStart[Ch][Queue] = AllTcb;
++        }
++       else
++        {
++         /* if the memory has already been allocated, simply reuse it! */
++         AllTcb = HalDev->TcbStart[Ch][Queue];
++        }
++
++      /* align to cache line */
++      AllTcb = (char *)(((bit32u)AllTcb + 0xf) &~ 0xf); /*PITS #143  MJH~030522*/
++
++      /* default High priority transmit queue */
++      HalDev->TcbPool[Ch][Queue]=0;
++      for(i=0;i<Num;i++)
++        {
++         /*pTcb=(HAL_TCB *) OsFunc->MallocDmaXfer(sizeof(HAL_TCB),0,0xffffffff); */
++         pTcb= (HAL_TCB *)(AllTcb + (i*tcbSize));
++         pTcb->mode=0;
++         pTcb->BufPtr=0;
++         pTcb->Next=HalDev->TcbPool[Ch][Queue];
++         pTcb->Off_BLen=0;
++         HalDev->TcbPool[Ch][Queue]=pTcb;
++        }
++      /*HalDev->TcbEnd = pTcb;*/
++     }
++
++   return(EC_NO_ERRORS);
++  }
++
++/*
++ *  This function allocates receive buffer descriptors (internal CPHAL function).
++ *  After allocation, the function 'queues' (gives to the hardware) the newly
++ *  created receive buffers to enable packet reception.
++ *
++ *  @param   HalDev   CPHAL module instance. (set by cphalInitModule())
++ *  @param   Ch    Channel number.
++ *
++ *  @return  0 OK, Non-Zero Not OK
++ */
++static int InitRcb(HAL_DEVICE *HalDev, int Ch)
++  {
++   int i, Num = HalDev->ChData[Ch].RxNumBuffers;
++   int Size = HalDev->ChData[Ch].RxBufSize;
++   HAL_RCB *pRcb;
++   char *pBuf;
++   char *AllRcb;
++   int  rcbSize;
++   int  DoMalloc = 0;
++   int SizeMalloc;
++   int MallocSize;
++
++   rcbSize = (sizeof(HAL_RCB)+0xf)&~0xf;
++   SizeMalloc = (rcbSize*Num)+0xf;
++
++   if (HalDev->RcbStart[Ch] == 0)
++     {
++      DoMalloc = 1;
++
++      /* malloc all RCBs at once */
++      AllRcb= (char *)HalDev->OsFunc->MallocDmaXfer(SizeMalloc,0,0xffffffff);
++      if (!AllRcb)
++        {
++         return(EC_CPPI|EC_FUNC_HAL_INIT|EC_VAL_RCB_MALLOC_FAILED);
++        }
++
++      HalDev->OsFunc->Memset(AllRcb, 0, SizeMalloc);
++
++      /* keep this address for freeing later */
++      HalDev->RcbStart[Ch] = AllRcb;
++     }
++    else
++     {
++      /* if the memory has already been allocated, simply reuse it! */
++      AllRcb = HalDev->RcbStart[Ch];
++     }
++
++   /* align to cache line */
++   AllRcb = (char *)(((bit32u)AllRcb + 0xf)&~0xf);  /*PITS #143  MJH~030522*/
++
++   HalDev->RcbPool[Ch]=0;
++   for(i=0;i<Num;i++)
++     {
++      pRcb = (HAL_RCB *)(AllRcb + (i*rcbSize));
++
++      if (DoMalloc == 1)
++        {
++
++         MallocSize = Size;                                       /*~3.01 */
++         pBuf= (char *) HalDev->OsFunc->MallocRxBuffer(MallocSize,0,0xF,HalDev->ChData[Ch].OsSetup, (void *)pRcb, (void *)&pRcb->OsInfo, (void *) HalDev->OsDev);
++         if(!pBuf)
++             {
++            return(EC_CPPI|EC_FUNC_HAL_INIT|EC_VAL_RX_BUFFER_MALLOC_FAILED);
++             }
++           /* -RC3.01 pBuf = (char *)(((bit32u)pBuf+0xF) & ~0xF); */
++         pRcb->BufPtr=VirtToPhys(pBuf) - HalDev->offset;
++         pRcb->DatPtr=pBuf;
++        }
++      pRcb->mode=(1<<8)|Ch; /* One Frag for Ch */
++      pRcb->Next=(void *)HalDev->RcbPool[Ch];
++      pRcb->Off_BLen=(bit32u)HalDev;
++      HalDev->RcbPool[Ch]=pRcb;
++     }
++
++   /* Give all of the Rx buffers to hardware */
++
++   while(HalDev->RcbPool[Ch])
++     {
++      pRcb=HalDev->RcbPool[Ch];
++      HalDev->RcbPool[Ch]=pRcb->Next;
++      pRcb->Eop=(void*)pRcb;
++      pRcb->mode=(1<<8)|Ch;
++      halRxReturn((HAL_RECEIVEINFO *)pRcb, 0);
++     }
++
++   return(EC_NO_ERRORS);
++  }
++
++/**
++ *  @ingroup CPHAL_Functions
++ *  This function transmits the data in FragList using available transmit
++ *  buffer descriptors.  More information on the use of the Mode parameter
++ *  is available in the module-specific appendices.  Note:  The OS should
++ *  not call Send() for a channel that has been requested to be torndown.
++ *
++ *  @param   HalDev      CPHAL module instance. (set by cphalInitModule())
++ *  @param   FragList    Fragment List structure.
++ *  @param   FragCount   Number of fragments in FragList.
++ *  @param   PacketSize  Number of bytes to transmit.
++ *  @param   OsSendInfo  OS Send Information structure. <BR>
++ *  @param   Mode        32-bit value with the following bit fields: <BR>
++ *                       31-16: Mode  (used for module specific data). <BR>
++ *                       15-08: Queue (transmit queue to send on). <BR>
++ *                       07-00: Channel (channel number to send on).
++ *
++ *  @return  EC_NO_ERRORS (ok). <BR>
++ *           Possible Error Codes:<BR>
++ *           @ref EC_VAL_INVALID_STATE "EC_VAL_INVALID_STATE"<BR>
++ *           @ref EC_VAL_NOT_LINKED "EC_VAL_NOT_LINKED"<BR>
++ *           @ref EC_VAL_INVALID_CH "EC_VAL_INVALID_CH"<BR>
++ *           @ref EC_VAL_OUT_OF_TCBS "EC_VAL_OUT_OF_TCBS"<BR>
++ *           @ref EC_VAL_NO_TCBS "EC_VAL_NO_TCBS"<BR>
++ */
++static int halSend(HAL_DEVICE *HalDev,FRAGLIST *FragList,
++                      int FragCount,int PacketSize, OS_SENDINFO *OsSendInfo,
++                      bit32u Mode)
++  {
++  HAL_TCB *tcb_ptr, *head;
++  int i;
++  int rc = EC_NO_ERRORS;
++  int Ch = Mode & 0xFF;
++  int Queue = (Mode>>8)&0xFF;
++  /*int DoThresholdCheck=1;  */ /* Used when TxIntDisable is set and TxInts are re-enabled */
++  
++  if (HalDev->State != enOpened)
++     return(EC_CPPI|EC_FUNC_SEND|EC_VAL_INVALID_STATE);
++
++  if (!HalDev->Linked)
++    {
++     rc = EC_CPPI|EC_FUNC_SEND|EC_VAL_NOT_LINKED;
++     return(rc);
++    }
++
++  if (HalDev->ChIsOpen[Ch][DIRECTION_TX] == 0)                    /*MJH~030611*/ /*PITS 148*/
++    return(EC_CPMAC |EC_FUNC_SEND|EC_VAL_INVALID_CH);              /*+GSG 030303*/
++
++  HalDev->OsFunc->CriticalOn();
++
++  /* Setup Tx mode and size */
++  if (PacketSize<60)
++    {
++     FragList[FragCount-1].len += (60 - PacketSize);              /*MJH~030506*//*PITS 132*/
++     PacketSize = 60;                                             /*MJH~030506*/
++    }
++  Mode &= CB_PASSCRC_BIT;
++
++  tcb_ptr = head = HalDev->TcbPool[Ch][Queue];
++
++  if (tcb_ptr)
++    {
++
++     Mode|=PacketSize|CB_SOF_BIT|CB_OWNERSHIP_BIT;
++
++     for (i=0; i<FragCount; i++)
++
++       {
++        /* Setup Tx mode and size */
++        tcb_ptr->Off_BLen = FragList[i].len;
++        
++        tcb_ptr->mode     = Mode;
++        tcb_ptr->BufPtr   = VirtToPhys((bit32 *)FragList[i].data) - HalDev->offset;
++        tcb_ptr->OsInfo = OsSendInfo;
++
++        if (i == (FragCount - 1))
++          {
++           /* last fragment */
++           tcb_ptr->mode |= CB_EOF_BIT;
++
++           /* since this is the last fragment, set the TcbPool pointer before
++              nulling out the Next pointers */
++
++           HalDev->TcbPool[Ch][Queue] = tcb_ptr->Next;
++
++           tcb_ptr->Next = 0;
++           tcb_ptr->HNext = 0;
++
++           /* In the Tx Interrupt handler, we will need to know which TCB is EOP,
++              so we can save that information in the SOP */
++           head->Eop = tcb_ptr;
++
++           /* Emerald fix 10/29 */
++       osfuncDataCacheHitWritebackAndInvalidate((void *)tcb_ptr, 16);
++
++          }
++         else
++          {
++           Mode=CB_OWNERSHIP_BIT;
++           tcb_ptr->HNext    = VirtToPhys((bit32 *)tcb_ptr->Next) - HalDev->offset;
++        
++           /* Emerald fix 10/29 */
++           osfuncDataCacheHitWritebackAndInvalidate((void *)tcb_ptr, 16);
++
++           tcb_ptr = tcb_ptr->Next;  /* what about the end of TCB list?? */
++
++           if (tcb_ptr == 0)
++             {
++              rc = EC_CPPI|EC_FUNC_SEND|EC_VAL_OUT_OF_TCBS;
++              goto ExitSend;
++             }
++          }
++       } /* for */
++
++     /* put it on the high priority queue */
++     if (HalDev->TxActQueueHead[Ch][Queue] == 0)
++       {
++        HalDev->TxActQueueHead[Ch][Queue]=head;
++        HalDev->TxActQueueTail[Ch][Queue]=tcb_ptr;
++/*+GSG 030303*//*+GSG 030303*/
++        if (!HalDev->TxActive[Ch][Queue])
++          {
++
++              bit32u base = HalDev->dev_base;
++              
++              /* write CPPI TX HDP */
++              (CPMAC_TX_HDP( base , Ch ))  = VirtToPhys(head)  - HalDev->offset;
++              HalDev->TxActive[Ch][Queue]=TRUE;
++
++          }
++       }
++      else
++       {
++          register volatile HAL_TCB *pTailTcb;   
++        register bit32u tmode;
++        register bit32u pCurrentTcb;
++        
++        HalDev->TxActQueueTail[Ch][Queue]->Next=head;
++        /* Emerald fix 10/29 */
++        
++        pTailTcb=(HAL_TCB *)VirtToVirtNoCache(&HalDev->TxActQueueTail[Ch][Queue]->HNext);
++        pCurrentTcb=VirtToPhys(head)  - HalDev->offset;
++        pTailTcb->HNext=pCurrentTcb;
++        HalDev->TxActQueueTail[Ch][Queue]=tcb_ptr;
++/*+GSG 030303*/
++        tmode=pTailTcb->mode;  
++        if (tmode&CB_EOQ_BIT)
++          {
++           bit32u base = HalDev->dev_base;
++
++           tmode&=~CB_EOQ_BIT;
++           pTailTcb->mode=tmode;
++           ((CPMAC_TX_HDP( base , Ch )) )  = pCurrentTcb;
++          }
++
++        else
++          {
++           if(HalDev->TxIntDisable)
++             {
++              /*  Enable Interrupts, to ensure packet goes out on wire */
++              CPMAC_TX_INTMASK_SET(HalDev->dev_base) = (1<<Ch); 
++              halPacketProcessEnd(HalDev); /* Allow Interrupt to be seen at the OS */
++              /*DoThresholdCheck = 0; */       /* Disable Threshold Check */
++
++             }       
++          }
++
++       }
++     rc = EC_NO_ERRORS;
++     goto ExitSend;
++    } /* if (tcb_ptr) */
++   else
++    {
++     rc = EC_CPPI|EC_FUNC_SEND|EC_VAL_NO_TCBS;
++     goto ExitSend;
++    }
++ExitSend:
++
++/* 15 June 2004 - NSP Performance Update : If Tx Ints are disabled then process them here */
++/* 29 June 2004 - NSP Performance Update : Moved to end at request of BCIL */
++/* 23 Aug  2004 - NSP Performance Update : If Tx Ints are re-enabled do not do Threshold check */
++
++   if(HalDev->TxIntDisable /*&& DoThresholdCheck*/)
++   {
++      if(--HalDev->TxIntThreshold[Ch] <= 0)
++      {
++          int MoreWork;
++          TxInt(HalDev, Ch, 0, &MoreWork);
++          HalDev->TxIntThreshold[Ch] = HalDev->TxIntThresholdMaster[Ch];
++      }
++   }
++    HalDev->OsFunc->CriticalOff();
++
++   return(rc);
++  }
++
++/*
++ *  This function processes receive interrupts.  It traverses the receive
++ *  buffer queue, extracting the data and passing it to the upper layer software via
++ *  osReceive().  It handles all error conditions and fragments without valid data by
++ *  immediately returning the RCB's to the RCB pool.
++ *
++ *  @param   HalDev   CPHAL module instance. (set by cphalInitModule())
++ *  @param   Ch       Channel Number.
++ *  @param   MoreWork Flag that indicates that there is more work to do when set to 1.
++ *
++ *  @return  0 if OK, non-zero otherwise.
++ */
++static int RxInt(HAL_DEVICE *HalDev, int Ch, int *MoreWork)
++  {
++  HAL_RCB *CurrentRcb, *SopRcb, *EofRcb, *EopRcb;
++  bit32u RxBufStatus,PacketsServiced, RxPktLen = 0, RxSopStatus,
++    FrmFrags, TotalFrags, FrmLen;
++  int base = HalDev->dev_base, Ret;
++  OS_FUNCTIONS *OsFunc = HalDev->OsFunc;
++  int RxServiceMax = HalDev->ChData[Ch].RxServiceMax;
++  int FragIndex; /* +GSG 030508 */
++  
++  if(HalDev->NeedsCount) /* +MJH 030410 */
++    NeedsCheck(HalDev);  /* +MJH 030410 */
++
++  /* Handle case of teardown interrupt */
++  if (HalDev->RxTeardownPending[Ch] != 0)
++    {
++     Ret = RxTeardownInt(HalDev, Ch);
++     if (Ret == 0)
++       {                                                              /*+GSG 030303*/
++        *MoreWork = 0;
++        return (EC_NO_ERRORS);
++       }                                                              /*+GSG 030303*/
++    }
++
++  /* Examine first RCB on the software active queue */
++  CurrentRcb=HalDev->RxActQueueHead[Ch];
++  osfuncDataCacheHitInvalidate((void*)CurrentRcb, 16);
++  RxBufStatus=CurrentRcb->mode;
++  PacketsServiced=0;
++  
++  /* Process received packets until we find hardware owned descriptors
++     or until we hit RxServiceMax */
++  while((CurrentRcb)&&((RxBufStatus&CB_OWNERSHIP_BIT)==0)&&
++    (PacketsServiced<RxServiceMax)) /* ~GSG 030307 */
++    {
++
++     PacketsServiced++; /* ~GSG 030307 */
++     SopRcb=CurrentRcb;
++     RxSopStatus=RxBufStatus;
++     RxPktLen = RxSopStatus&CB_SIZE_MASK;
++    
++     FrmFrags=0;
++     TotalFrags=0;
++     FragIndex=0;
++     FrmLen=0;
++     EofRcb=0;
++
++/* +GSG 030508 *//* +GSG 030508 */
++
++     /* Loop through all fragments that comprise current packet.  Build
++        fraglist and exit when the end of the packet is reached, or the
++        end of the descriptor list is reached. */
++     do
++       {
++          bit32u DmaLen;
++         
++
++        DmaLen=CurrentRcb->Off_BLen;
++
++        FrmLen+=DmaLen;
++        TotalFrags++;
++        if (!EofRcb)
++          {
++           HalDev->fraglist[FragIndex].data=((char *)CurrentRcb->DatPtr);       /* ~GSG 030508 */
++
++           HalDev->fraglist[FragIndex].len=DmaLen;                              /* ~GSG 030508 */
++
++           /* GSG 12/9 */
++           HalDev->fraglist[FragIndex].OsInfo = CurrentRcb->OsInfo;             /* ~GSG 030508 */
++
++           /* Upper layer must do the data invalidate */ 
++
++           FrmFrags++;
++           FragIndex++;                                                         /* ~GSG 030508 */
++           if (FrmLen>=RxPktLen)
++             EofRcb=CurrentRcb;
++          }
++        EopRcb=CurrentRcb;
++        CurrentRcb=EopRcb->Next;
++        if (CurrentRcb)
++          {
++           osfuncDataCacheHitInvalidate((void*)CurrentRcb,16);
++          }
++       }while(((EopRcb->mode&CB_EOF_BIT)==0)&&(CurrentRcb));
++     
++     /* Write the completion pointer for interrupt acknowledgement*/
++     (CPMAC_RX_INT_ACK( base , Ch ))  = VirtToPhys(EopRcb) - HalDev->offset;
++
++     EopRcb->Next=0;
++
++     if (CurrentRcb == 0)
++       { 
++          /* If we are out of RCB's we must not send this packet
++             to the OS. */
++        int RcbSize = HalDev->ChData[Ch].RxBufSize;
++
++        if (TotalFrags>1)
++          {
++           EopRcb->Off_BLen=RcbSize;
++           EopRcb->mode=CB_OWNERSHIP_BIT;
++           osfuncDataCacheHitWritebackAndInvalidate((void *)EopRcb, 16);
++          }
++
++        SopRcb->Off_BLen=RcbSize;
++        SopRcb->mode=CB_OWNERSHIP_BIT;   
++        osfuncDataCacheHitWritebackAndInvalidate((void *)SopRcb, 16);
++      
++        ((CPMAC_RX_HDP( base , Ch )) )  = VirtToPhys(SopRcb);
++       }
++      else
++       { 
++          /* Dequeue packet and send to OS */
++        int mode;
++
++        /* setup SopRcb for the packet */
++        SopRcb->Eop=(void*)EopRcb;
++
++        /* dequeue packet */
++        HalDev->RxActQueueHead[Ch]=CurrentRcb;
++        
++        if (EopRcb->mode&CB_EOQ_BIT)
++          {
++             /* Next pointer is non-null and EOQ bit is set, which
++                indicates misqueue packet in CPPI protocol. */
++
++           ((CPMAC_RX_HDP( base , Ch )) )  = EopRcb->HNext;
++          }
++        
++        mode = (SopRcb->mode & 0xFFFF0000) | Ch;
++
++        SopRcb->mode=(FrmFrags<<8)|Ch;
++        SopRcb->Off_BLen=(bit32u)HalDev;
++        
++        /* send packet up the higher layer driver */
++        OsFunc->Receive(HalDev->OsDev,HalDev->fraglist,FragIndex,RxPktLen,             /* ~GSG 030508 */
++                       (HAL_RECEIVEINFO *)SopRcb,mode);
++    
++        RxBufStatus=CurrentRcb->mode;          
++       }
++    } /* while loop */
++      
++  if ((CurrentRcb)&&((RxBufStatus&CB_OWNERSHIP_BIT)==0)) /*~GSG 030307*/
++    {
++     *MoreWork = 1;
++    }
++   else
++    {
++     *MoreWork = 0;
++    }
++
++  return (EC_NO_ERRORS);
++}
++
++/*
++ *  This function processes transmit interrupts.  It traverses the
++ *  transmit buffer queue, detecting sent data buffers and notifying the upper
++ *  layer software via osSendComplete().  (for SAR, i originally had this split
++ *  into two functions, one for each queue, but joined them on 8/8/02)
++ *
++ *  @param   HalDev   CPHAL module instance. (set by cphalInitModule())
++ *  @param   Queue    Queue number to service (always 0 for MAC, Choose 1 for SAR to service low priority queue)
++ *  @param   MoreWork Flag that indicates that there is more work to do when set to 1.
++ *
++ *  @return  0 if OK, non-zero otherwise.
++ */
++int TxInt(HAL_DEVICE *HalDev, int Ch, int Queue, int *MoreWork)
++  {
++  HAL_TCB *CurrentTcb,*LastTcbProcessed,*FirstTcbProcessed;
++  int PacketsServiced;
++  bit32u TxFrameStatus;
++  int base;
++  int TxServiceMax = HalDev->ChData[Ch].TxServiceMax;
++  OS_FUNCTIONS *OsFunc = HalDev->OsFunc;
++
++/*+GSG 030303*//*+GSG 030303*/
++
++  /* load the module base address */
++  base = HalDev->dev_base;
++  
++  /* Handle case of teardown interrupt.  This must be checked at
++     the top of the function rather than the bottom, because
++     the normal data processing can wipe out the completion
++     pointer which is used to determine teardown complete. */
++  if (HalDev->TxTeardownPending[Ch] != 0)
++    {
++       int Ret;
++       
++     Ret = TxTeardownInt(HalDev, Ch, Queue);
++     if (Ret == 0)
++       {                                                              /*+GSG 030303*/
++        *MoreWork = 0; /* bug fix 1/6 */                              /*+GSG 030303*/
++        return (EC_NO_ERRORS);
++       }                                                              /*+GSG 030303*/
++    }
++
++  OsFunc->CriticalOn(); /*  240904 */
++
++  CurrentTcb = HalDev->TxActQueueHead[Ch][Queue];
++  FirstTcbProcessed=CurrentTcb;
++
++  if (CurrentTcb==0)
++    {
++     /* I saw this error a couple of times when multi-channels were added */
++     dbgPrintf("[cppi TxInt()]TxH int with no TCB in queue!\n");
++     dbgPrintf("              Ch=%d, CurrentTcb = 0x%08x\n", Ch, (bit32u)CurrentTcb);
++     dbgPrintf("              HalDev = 0x%08x\n", (bit32u)HalDev);
++     osfuncSioFlush();
++     OsFunc->CriticalOff(); 
++     return(EC_CPPI|EC_FUNC_TXINT|EC_VAL_NULL_TCB);
++    }
++
++  osfuncDataCacheHitInvalidate((void *)CurrentTcb, 16);
++  TxFrameStatus=CurrentTcb->mode;
++  PacketsServiced=0;
++
++  /* should the ownership bit check be inside of the loop?? could make it a
++     while-do loop and take this check away */
++  if ((TxFrameStatus&CB_OWNERSHIP_BIT)==0)
++    {
++    do
++      {
++      /* Pop TCB(s) for packet from the stack */
++      LastTcbProcessed=CurrentTcb->Eop;
++
++      /* new location for acknowledge */
++      /* Write the completion pointer */
++      (CPMAC_TX_INT_ACK( base , Ch ))  = VirtToPhys(LastTcbProcessed) - HalDev->offset;
++
++      HalDev->TxActQueueHead[Ch][Queue] = LastTcbProcessed->Next;
++
++/*+GSG 030303*//*+GSG 030303*/
++
++      osfuncDataCacheHitInvalidate((void *)LastTcbProcessed, 16);
++
++      if (LastTcbProcessed->mode&CB_EOQ_BIT)
++        {
++         if (LastTcbProcessed->Next)
++           {
++            /* Misqueued packet */
++
++               (CPMAC_TX_HDP( base , Ch ))  = LastTcbProcessed->HNext;
++
++           }
++          else
++           {
++       /* Tx End of Queue */
++
++            HalDev->TxActive[Ch][Queue]=FALSE;
++           }
++        }
++
++      OsFunc->SendComplete(CurrentTcb->OsInfo);
++
++      /* Push Tcb(s) back onto the stack */
++      CurrentTcb = LastTcbProcessed->Next;
++
++      LastTcbProcessed->Next=HalDev->TcbPool[Ch][Queue];
++
++      HalDev->TcbPool[Ch][Queue]=FirstTcbProcessed;
++
++      PacketsServiced++;
++
++      TxFrameStatus=CB_OWNERSHIP_BIT;
++      /* set the first(SOP) pointer for the next packet */
++      FirstTcbProcessed = CurrentTcb;
++      if (CurrentTcb)
++        {
++         osfuncDataCacheHitInvalidate((void *)CurrentTcb, 16);
++         TxFrameStatus=CurrentTcb->mode;
++        }
++
++      }while(((TxFrameStatus&CB_OWNERSHIP_BIT)==0)
++             &&(PacketsServiced<TxServiceMax));
++
++    if (((TxFrameStatus&CB_OWNERSHIP_BIT)==0)
++             &&(PacketsServiced==TxServiceMax))
++      {
++       *MoreWork = 1;
++      }
++     else
++      {
++       *MoreWork = 0;
++      }
++    }
++    OsFunc->CriticalOff(); 
++
++  return(EC_NO_ERRORS);
++  }
++
++/**
++ *  @ingroup CPHAL_Functions
++ *  This function performs a teardown for the given channel.  The value of the
++ *  Mode parameter controls the operation of the function, as documented below.
++ *
++ *  Note: If bit 3 of Mode is set, this call is blocking, and will not return
++ *  until the teardown interrupt has occurred and been processed. While waiting
++ *  for a blocking teardown to complete, ChannelTeardown() will signal the OS
++ *  (via Control(.."Sleep"..)) to allow the OS to perform other tasks if
++ *  necessary.  If and only if bit 3 of Mode is clear, the CPHAL will call the
++ *  OS TeardownComplete() function to indicate that the teardown has completed.
++ *
++ *  @param   HalDev  CPHAL module instance. (set by xxxInitModule())
++ *  @param   Ch      Channel number.
++ *  @param   Mode    Bit 0 (LSB): Perform Tx teardown (if set).<BR>
++ *                   Bit 1: Perform Rx teardown (if set). <BR>
++ *                   Bit 2: If set, perform full teardown (free buffers/descriptors).
++ *                          If clear, perform partial teardown (keep buffers). <BR>
++ *                   Bit 3 (MSB): If set, call is blocking.
++ *                            If clear, call is non-blocking.
++ *
++ *  @return  EC_NO_ERRORS (ok). <BR>
++ *           Possible Error Codes:<BR>
++ *           @ref EC_VAL_INVALID_STATE "EC_VAL_INVALID_STATE"<BR>
++ *           @ref EC_VAL_INVALID_CH "EC_VAL_INVALID_CH"<BR>
++ *           @ref EC_VAL_TX_TEARDOWN_ALREADY_PEND "EC_VAL_TX_TEARDOWN_ALREADY_PEND"<BR>
++ *           @ref EC_VAL_RX_TEARDOWN_ALREADY_PEND "EC_VAL_RX_TEARDOWN_ALREADY_PEND"<BR>
++ *           @ref EC_VAL_TX_CH_ALREADY_TORNDOWN "EC_VAL_TX_CH_ALREADY_TORNDOWN"<BR>
++ *           @ref EC_VAL_RX_CH_ALREADY_TORNDOWN "EC_VAL_RX_CH_ALREADY_TORNDOWN"<BR>
++ *           @ref EC_VAL_TX_TEARDOWN_TIMEOUT "EC_VAL_TX_TEARDOWN_TIMEOUT"<BR>
++ *           @ref EC_VAL_RX_TEARDOWN_TIMEOUT "EC_VAL_RX_TEARDOWN_TIMEOUT"<BR>
++ *           @ref EC_VAL_LUT_NOT_READY "EC_VAL_LUT_NOT_READY"<BR>
++ */
++static int halChannelTeardown(HAL_DEVICE *HalDev, int Ch, bit32 Mode)
++  {
++   int DoTx, DoRx, Sleep=2048, timeout=0;                         /*MJH~030306*/
++   bit32u base = HalDev->dev_base;
++
++/* Set the module, used for error returns */
++
++   DoTx = (Mode & TX_TEARDOWN);
++   DoRx = (Mode & RX_TEARDOWN);
++
++   if (HalDev->State < enInitialized)
++     return(EC_CPMAC |EC_FUNC_CHTEARDOWN|EC_VAL_INVALID_STATE);
++
++   if ((Ch < 0) || (Ch > (MAX_CHAN-1) ))
++     {
++     return(EC_CPMAC |EC_FUNC_CHTEARDOWN|EC_VAL_INVALID_CH);
++     }
++
++   /* set teardown pending bits before performing the teardown, because they
++      will be used in the int handler (this is done for AAL5) */
++   if (DoTx)
++     {
++      if (HalDev->TxTeardownPending[Ch] != 0)
++        return(EC_CPMAC |EC_FUNC_CHTEARDOWN|EC_VAL_TX_TEARDOWN_ALREADY_PEND);
++
++      /* If a full teardown, this also means that the user must
++      setup all channels again to use them */
++      if (Mode & FULL_TEARDOWN)
++        HalDev->ChIsSetup[Ch][DIRECTION_TX] = 0;
++
++      if (HalDev->State < enOpened)
++        {
++         /* if the hardware has never been opened, the channel has never actually
++         been setup in the hardware, so I just need to reset the software flag
++         and leave */
++         HalDev->ChIsSetup[Ch][DIRECTION_TX] = 0;
++         return (EC_NO_ERRORS);
++    }
++       else
++    {
++         if (HalDev->ChIsOpen[Ch][DIRECTION_TX] == 0)
++       {
++            return(EC_CPMAC |EC_FUNC_CHTEARDOWN|EC_VAL_TX_CH_ALREADY_TORNDOWN);
++       }
++
++         /* set teardown flag */
++         HalDev->TxTeardownPending[Ch] = Mode;
++    }
++     }
++
++   if (DoRx)
++     {
++      if (HalDev->RxTeardownPending[Ch] != 0)
++        return(EC_CPMAC |EC_FUNC_CHTEARDOWN|EC_VAL_RX_TEARDOWN_ALREADY_PEND);
++
++      if (Mode & FULL_TEARDOWN)
++        HalDev->ChIsSetup[Ch][DIRECTION_RX] = 0;
++
++      if (HalDev->State < enOpened)
++        {
++         HalDev->ChIsSetup[Ch][DIRECTION_RX] = 0;
++         return (EC_NO_ERRORS);
++    }
++       else
++    {
++         if (HalDev->ChIsOpen[Ch][DIRECTION_RX] == 0)
++           return(EC_CPMAC |EC_FUNC_CHTEARDOWN|EC_VAL_RX_CH_ALREADY_TORNDOWN);
++
++         HalDev->RxTeardownPending[Ch] = Mode;
++    }
++     }
++
++   /* Perform Tx Teardown Duties */
++   if ((DoTx) && (HalDev->State == enOpened))
++     {
++      /* Request TX channel teardown */
++      (CPMAC_TX_TEARDOWN( base ))  = Ch;
++
++      /* wait until teardown has completed */
++      if (Mode & BLOCKING_TEARDOWN)
++        {
++     timeout = 0;
++         while (HalDev->ChIsOpen[Ch][DIRECTION_TX] == TRUE)
++       {
++            osfuncSleep(&Sleep);
++
++            timeout++;
++        if (timeout > 100000)
++          {
++               return(EC_CPMAC |EC_FUNC_CHTEARDOWN|EC_VAL_TX_TEARDOWN_TIMEOUT);
++          }
++       }
++    }
++     } /* if DoTx */
++
++   /* Perform Rx Teardown Duties */
++   if ((DoRx) && (HalDev->State == enOpened))
++     {
++
++      /* perform CPMAC specific RX channel teardown */
++      CPMAC_RX_TEARDOWN(base) = Ch;
++
++      if (Mode & BLOCKING_TEARDOWN)
++        {
++     timeout = 0;
++         while (HalDev->ChIsOpen[Ch][DIRECTION_RX] == TRUE)
++       {
++            osfuncSleep(&Sleep);
++
++            timeout++;
++        if (timeout > 100000)
++          {
++               return(EC_CPMAC |EC_FUNC_CHTEARDOWN|EC_VAL_RX_TEARDOWN_TIMEOUT);
++          }
++       }
++        }
++     } /* if DoRx */
++
++   return (EC_NO_ERRORS);
++  }
++
++/**
++ *  @ingroup CPHAL_Functions
++ *  This function closes the CPHAL module.  The module will be reset.
++ *  The Mode parameter should be used to determine the actions taken by
++ *  Close().
++ *
++ *  @param   HalDev   CPHAL module instance. (set by xxxInitModule())
++ *  @param   Mode     Indicates actions to take on close.  The following integer
++ *                    values are valid: <BR>
++ *                    1:  Does not free buffer resources, init parameters remain
++ *                        intact.  User can then call Open() without calling Init()
++ *                        to attempt to reset the device and bring it back to the
++ *                        last known state.<BR>
++ *                    2:  Frees the buffer resources, but keeps init parameters.  This
++ *                        option is a more aggressive means of attempting a device reset.
++ *                    3:  Frees the buffer resources, and clears all init parameters. <BR>
++ *                        At this point, the caller would have to call to completely
++ *                        reinitialize the device (Init()) before being able to call
++ *                        Open().  Use this mode if you are shutting down the module
++ *                        and do not plan to restart.
++ *
++ *  @return  EC_NO_ERRORS (ok).<BR>
++ *           Possible Error Codes:<BR>
++ *           @ref EC_VAL_INVALID_STATE "EC_VAL_INVALID_STATE"<BR>
++ *           Any error code from halChannelTeardown().<BR>
++ */
++static int halClose(HAL_DEVICE *HalDev, bit32 Mode)
++  {
++   int Ch, Inst, Ret;
++   OS_DEVICE *TmpOsDev;
++   OS_FUNCTIONS *TmpOsFunc;
++   HAL_FUNCTIONS *TmpHalFunc;
++   char *TmpDeviceInfo;
++
++   int Ticks;                                                     /*MJH~030306*/
++
++   /* Verify proper device state */
++   if (HalDev->State != enOpened)
++     return (EC_CPMAC  | EC_FUNC_CLOSE|EC_VAL_INVALID_STATE);
++
++   /* Teardown all open channels */
++   for (Ch = 0; Ch <= (MAX_CHAN-1) ; Ch++)
++     {
++      if (HalDev->ChIsOpen[Ch][DIRECTION_TX] == TRUE)
++        {
++         if (Mode == 1)
++           {
++            Ret = halChannelTeardown(HalDev, Ch, TX_TEARDOWN | PARTIAL_TEARDOWN | BLOCKING_TEARDOWN);
++            if (Ret) return (Ret);
++           }
++          else
++           {
++            Ret = halChannelTeardown(HalDev, Ch, TX_TEARDOWN | FULL_TEARDOWN | BLOCKING_TEARDOWN);
++            if (Ret) return (Ret);
++           }
++        }
++
++      if (HalDev->ChIsOpen[Ch][DIRECTION_RX] == TRUE)
++        {
++         if (Mode == 1)
++           {
++            Ret = halChannelTeardown(HalDev, Ch, RX_TEARDOWN | PARTIAL_TEARDOWN | BLOCKING_TEARDOWN);
++            if (Ret) return (Ret);
++           }
++          else
++           {
++            Ret = halChannelTeardown(HalDev, Ch, RX_TEARDOWN | FULL_TEARDOWN | BLOCKING_TEARDOWN);
++            if (Ret) return (Ret);
++           }
++        }
++     }
++
++   /* free fraglist in HalDev */
++   HalDev->OsFunc->Free(HalDev->fraglist);
++   HalDev->fraglist = 0;
++
++   /* unregister the interrupt */
++   HalDev->OsFunc->IsrUnRegister(HalDev->OsDev, HalDev->interrupt);
++
++   Ticks = 0;    /* Disable Tick Timer */                           /*MJH+030306*/
++   HalDev->OsFunc->Control(HalDev->OsDev, hcTick, hcClear, &Ticks); /*MJH+030306*/
++
++   /* Free the Phy Information Structure */
++   if(HalDev->PhyDev)
++   {
++      HalDev->OsFunc->Free(HalDev->PhyDev);                               /*MJH+030513*/
++      HalDev->PhyDev = 0;                                         /*MJH+030522*/
++   }
++
++   /* Perform CPMAC specific closing functions */
++   CPMAC_MACCONTROL(HalDev->dev_base) &= ~MII_EN;
++   CPMAC_TX_CONTROL(HalDev->dev_base) &= ~TX_EN;
++   CPMAC_RX_CONTROL(HalDev->dev_base) &= ~RX_EN;
++
++   /* put device back into reset */
++   (*(volatile bit32u *)(HalDev->ResetBase)) &=~ (1<<HalDev->ResetBit);
++   Ticks = 64;                                                    /*MJH~030306*/
++   osfuncSleep(&Ticks);
++
++   /* If mode is 3, than clear the HalDev and set next state to DevFound*/
++   if (Mode == 3)
++     {
++      /* I need to keep the HalDev parameters that were setup in InitModule */
++      TmpOsDev = HalDev->OsDev;
++      TmpOsFunc = HalDev->OsFunc;
++      TmpDeviceInfo = HalDev->DeviceInfo;
++
++      TmpHalFunc = HalDev->HalFuncPtr;
++      Inst = HalDev->Inst;
++
++      /* Clear HalDev */
++
++      HalDev->OsFunc->Memset(HalDev, 0, sizeof(HAL_DEVICE));
++
++      /* Restore key parameters */
++      HalDev->OsDev = TmpOsDev;
++      HalDev->OsFunc = TmpOsFunc;
++      HalDev->DeviceInfo = TmpDeviceInfo;
++
++      HalDev->HalFuncPtr = TmpHalFunc;
++      HalDev->Inst = Inst;
++
++      HalDev->State = enDevFound;
++     }
++    else
++     {
++      HalDev->State = enInitialized;
++     }
++
++   return(EC_NO_ERRORS);
++  }
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/cpremap_cpmac.c linux-2.4.30/drivers/net/avalanche_cpmac/cpremap_cpmac.c
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/cpremap_cpmac.c      1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/cpremap_cpmac.c   2005-04-15 05:10:41.000000000 +0200
+@@ -0,0 +1,28 @@
++#ifndef _INC_CPREMAP_C
++#define _INC_CPREMAP_C
++
++#ifdef __ADAM2
++static inline void osfuncDataCacheHitInvalidate(void *ptr, int Size)
++  {
++  asm(" cache  17, (%0)" : : "r" (ptr));
++  }
++
++static inline void osfuncDataCacheHitWriteback(void *ptr, int Size)
++  { 
++  asm(" cache  25, (%0)" : : "r" (ptr));
++  }
++  
++static inline void osfuncDataCacheHitWritebackAndInvalidate(void *ptr, int Size)
++  { 
++  asm(" cache  21, (%0)" : : "r" (ptr));
++  }
++
++#else
++
++#define osfuncDataCacheHitInvalidate(MemPtr, Size)               __asm__(" .set mips3; cache  17, (%0); .set mips0" : : "r" (MemPtr))
++#define osfuncDataCacheHitWritebackAndInvalidate(MemPtr, Size)   __asm__(" .set mips3; cache  21, (%0); .set mips0" : : "r" (MemPtr))
++#define osfuncDataCacheHitWriteback(MemPtr, Size)                __asm__(" .set mips3; cache  25, (%0); .set mips0" : : "r" (MemPtr))      
++            
++#endif
++
++#endif
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/cpswhal_cpmac.h linux-2.4.30/drivers/net/avalanche_cpmac/cpswhal_cpmac.h
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/cpswhal_cpmac.h      1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/cpswhal_cpmac.h   2005-04-15 05:10:41.000000000 +0200
+@@ -0,0 +1,632 @@
++/************************************************************************
++ *  TNETDxxxx Software Support
++ *  Copyright (c) 2002 Texas Instruments Incorporated. All Rights Reserved.
++ *
++ *  FILE: cphal.h
++ *
++ *  DESCRIPTION:
++ *      User include file, contains data definitions shared between the CPHAL
++ *      and the upper-layer software.
++ *
++ *  HISTORY:
++ *      Date      Modifier  Ver    Notes
++ *      28Feb02   Greg      1.00   Original
++ *      06Mar02   Greg      1.01   Documentation enhanced
++ *      18Jul02   Greg      1.02   Many updates (OAM additions, general reorg)
++ *      22Nov02   Mick      RC2    Additions from Denis' input on Control
++ *
++ *  author  Greg Guyotte
++ *  version 1.02
++ *  date    18-Jul-2002
++ *****************************************************************************/
++#ifndef _INC_CPHAL_H
++#define _INC_CPHAL_H
++
++#ifdef _CPHAL_CPMAC
++#include "ec_errors_cpmac.h"
++#endif
++
++#ifdef _CPHAL_AAL5
++#include "ec_errors_cpaal5.h"
++#endif
++
++#ifdef _CPHAL_CPSAR
++#include "ec_errors_cpsar.h"
++#endif
++
++#ifdef _CPHAL_AAL2
++#include "ec_errors_cpaal2.h"
++#endif
++
++#ifndef __ADAM2
++typedef char           bit8;
++typedef short          bit16;
++typedef int            bit32;
++
++typedef unsigned char  bit8u;
++typedef unsigned short bit16u;
++typedef unsigned int   bit32u;
++
++/*
++typedef char           INT8;
++typedef short          INT16;
++typedef int            INT32;
++typedef unsigned char  UINT8;
++typedef unsigned short UINT16;
++typedef unsigned int   UINT32;
++*/
++/*typedef unsigned int   size_t;*/
++#endif
++
++#ifdef _CPHAL
++
++#ifndef TRUE
++#define TRUE (1==1)
++#endif
++
++#ifndef FALSE
++#define FALSE (1==2)
++#endif
++
++#ifndef NULL
++#define NULL 0
++#endif
++
++#endif
++
++#define        VirtToPhys(a)                 (((int)a)&~0xe0000000)
++#define        VirtToVirtNoCache(a)          ((void*)((VirtToPhys(a))|0xa0000000))
++#define        VirtToVirtCache(a)            ((void*)((VirtToPhys(a))|0x80000000))
++#define        PhysToVirtNoCache(a)          ((void*)(((int)a)|0xa0000000))
++#define        PhysToVirtCache(a)            ((void*)(((int)a)|0x80000000))
++/*
++#define        DataCacheHitInvalidate(a)     {__asm__(" cache  17, (%0)" :   : "r" (a));}
++#define        DataCacheHitWriteback(a)      {__asm__(" cache  25, (%0)" :   : "r" (a));}
++*/
++
++#define PARTIAL 1     /**< Used in @c Close() and @c ChannelTeardown() */
++#define FULL 2        /**< Used in @c Close() and @c ChannelTeardown() */
++
++/* Channel Teardown Defines */
++#define RX_TEARDOWN 2
++#define TX_TEARDOWN 1
++#define BLOCKING_TEARDOWN 8
++#define FULL_TEARDOWN 4
++#define PARTIAL_TEARDOWN 0
++
++#define MAX_DIR 2
++#define DIRECTION_TX 0
++#define DIRECTION_RX 1
++#define TX_CH 0
++#define RX_CH 1
++#define HAL_ERROR_DEVICE_NOT_FOUND    1
++#define HAL_ERROR_FAILED_MALLOC       2
++#define HAL_ERROR_OSFUNC_SIZE         3
++#define HAL_DEFAULT  0xFFFFFFFF
++#define VALID(val)    (val!=HAL_DEFAULT)
++
++/*
++ERROR REPORTING
++
++HAL Module Codes.  Each HAL module reporting an error code
++should OR the error code with the respective Module error code
++from the list below.
++*/
++#define EC_AAL5                                EC_HAL|EC_DEV_AAL5
++#define EC_AAL2                                EC_HAL|EC_DEV_AAL2
++#define EC_CPSAR                               EC_HAL|EC_DEV_CPSAR
++#define EC_CPMAC                               EC_HAL|EC_DEV_CPMAC
++#define EC_VDMA                                EC_HAL|EC_DEV_VDMA
++#define EC_VLYNQ                               EC_HAL|EC_DEV_VLYNQ
++#define EC_CPPI                                EC_HAL|EC_DEV_CPPI
++
++/*
++HAL Function Codes.  Each HAL module reporting an error code
++should OR the error code with one of the function codes from
++the list below.
++*/
++#define EC_FUNC_HAL_INIT                       EC_FUNC(1)
++#define EC_FUNC_CHSETUP                        EC_FUNC(2)
++#define EC_FUNC_CHTEARDOWN                     EC_FUNC(3)
++#define EC_FUNC_RXRETURN                       EC_FUNC(4)
++#define EC_FUNC_SEND                           EC_FUNC(5)
++#define EC_FUNC_RXINT                          EC_FUNC(6)
++#define EC_FUNC_TXINT                          EC_FUNC(7)
++#define EC_FUNC_AAL2_VDMA                      EC_FUNC(8)
++#define EC_FUNC_OPTIONS                        EC_FUNC(9)
++#define EC_FUNC_PROBE                          EC_FUNC(10)
++#define EC_FUNC_OPEN                           EC_FUNC(11)
++#define EC_FUNC_CONTROL                        EC_FUNC(12)
++#define EC_FUNC_DEVICE_INT                     EC_FUNC(13)
++#define EC_FUNC_STATUS                         EC_FUNC(14)
++#define EC_FUNC_TICK                           EC_FUNC(15)
++#define EC_FUNC_CLOSE                          EC_FUNC(16)
++#define EC_FUNC_SHUTDOWN                       EC_FUNC(17)
++#define EC_FUNC_DEVICE_INT_ALT                 EC_FUNC(18) /* +GSG 030306 */
++
++/*
++HAL Error Codes.  The list below defines every type of error
++used in all HAL modules. DO NOT CHANGE THESE VALUES!  Add new
++values in integer order to the bottom of the list.
++*/
++#define EC_VAL_PDSP_LOAD_FAIL                 EC_ERR(0x01)|EC_CRITICAL
++#define EC_VAL_FIRMWARE_TOO_LARGE             EC_ERR(0x02)|EC_CRITICAL
++#define EC_VAL_DEVICE_NOT_FOUND               EC_ERR(0x03)|EC_CRITICAL
++#define EC_VAL_BASE_ADDR_NOT_FOUND            EC_ERR(0x04)|EC_CRITICAL
++#define EC_VAL_RESET_BIT_NOT_FOUND            EC_ERR(0x05)|EC_CRITICAL
++#define EC_VAL_CH_INFO_NOT_FOUND              EC_ERR(0x06)
++#define EC_VAL_RX_STATE_RAM_NOT_CLEARED       EC_ERR(0x07)|EC_CRITICAL
++#define EC_VAL_TX_STATE_RAM_NOT_CLEARED       EC_ERR(0x08)|EC_CRITICAL
++#define EC_VAL_MALLOC_DEV_FAILED              EC_ERR(0x09)
++#define EC_VAL_OS_VERSION_NOT_SUPPORTED       EC_ERR(0x0A)|EC_CRITICAL
++#define EC_VAL_CPSAR_VERSION_NOT_SUPPORTED    EC_ERR(0x0B)|EC_CRITICAL
++#define EC_VAL_NULL_CPSAR_DEV                 EC_ERR(0x0C)|EC_CRITICAL
++
++#define EC_VAL_LUT_NOT_READY                  EC_ERR(0x0D)
++#define EC_VAL_INVALID_CH                     EC_ERR(0x0E)
++#define EC_VAL_NULL_CH_STRUCT                 EC_ERR(0x0F)
++#define EC_VAL_RX_TEARDOWN_ALREADY_PEND       EC_ERR(0x10)
++#define EC_VAL_TX_TEARDOWN_ALREADY_PEND       EC_ERR(0x11)
++#define EC_VAL_RX_CH_ALREADY_TORNDOWN         EC_ERR(0x12)
++#define EC_VAL_TX_CH_ALREADY_TORNDOWN         EC_ERR(0x13)
++#define EC_VAL_TX_TEARDOWN_TIMEOUT            EC_ERR(0x14)
++#define EC_VAL_RX_TEARDOWN_TIMEOUT            EC_ERR(0x15)
++#define EC_VAL_CH_ALREADY_TORNDOWN            EC_ERR(0x16)
++#define EC_VAL_VC_SETUP_NOT_READY             EC_ERR(0x17)
++#define EC_VAL_VC_TEARDOWN_NOT_READY          EC_ERR(0x18)
++#define EC_VAL_INVALID_VC                     EC_ERR(0x19)
++#define EC_VAL_INVALID_LC                     EC_ERR(0x20)
++#define EC_VAL_INVALID_VDMA_CH                EC_ERR(0x21)
++#define EC_VAL_INVALID_CID                    EC_ERR(0x22)
++#define EC_VAL_INVALID_UUI                    EC_ERR(0x23)
++#define EC_VAL_INVALID_UUI_DISCARD            EC_ERR(0x24)
++#define EC_VAL_CH_ALREADY_OPEN                EC_ERR(0x25)
++
++#define EC_VAL_RCB_MALLOC_FAILED              EC_ERR(0x26)
++#define EC_VAL_RX_BUFFER_MALLOC_FAILED        EC_ERR(0x27)
++#define EC_VAL_OUT_OF_TCBS                    EC_ERR(0x28)
++#define EC_VAL_NO_TCBS                        EC_ERR(0x29)
++#define EC_VAL_NULL_RCB                       EC_ERR(0x30)|EC_CRITICAL
++#define EC_VAL_SOP_ERROR                      EC_ERR(0x31)|EC_CRITICAL
++#define EC_VAL_EOP_ERROR                      EC_ERR(0x32)|EC_CRITICAL
++#define EC_VAL_NULL_TCB                       EC_ERR(0x33)|EC_CRITICAL
++#define EC_VAL_CORRUPT_RCB_CHAIN              EC_ERR(0x34)|EC_CRITICAL
++#define EC_VAL_TCB_MALLOC_FAILED              EC_ERR(0x35)
++
++#define EC_VAL_DISABLE_POLLING_FAILED         EC_ERR(0x36)
++#define EC_VAL_KEY_NOT_FOUND                  EC_ERR(0x37)
++#define EC_VAL_MALLOC_FAILED                  EC_ERR(0x38)
++#define EC_VAL_RESET_BASE_NOT_FOUND           EC_ERR(0x39)|EC_CRITICAL
++#define EC_VAL_INVALID_STATE                  EC_ERR(0x40)
++#define EC_VAL_NO_TXH_WORK_TO_DO              EC_ERR(0x41)
++#define EC_VAL_NO_TXL_WORK_TO_DO              EC_ERR(0x42)
++#define EC_VAL_NO_RX_WORK_TO_DO               EC_ERR(0x43)
++#define EC_VAL_NOT_LINKED                     EC_ERR(0x44)
++#define EC_VAL_INTERRUPT_NOT_FOUND            EC_ERR(0x45)
++#define EC_VAL_OFFSET_NOT_FOUND               EC_ERR(0x46)
++#define EC_VAL_MODULE_ALREADY_CLOSED          EC_ERR(0x47)
++#define EC_VAL_MODULE_ALREADY_SHUTDOWN        EC_ERR(0x48)
++#define EC_VAL_ACTION_NOT_FOUND               EC_ERR(0x49)
++#define EC_VAL_RX_CH_ALREADY_SETUP            EC_ERR(0x50)
++#define EC_VAL_TX_CH_ALREADY_SETUP            EC_ERR(0x51)
++#define EC_VAL_RX_CH_ALREADY_OPEN             EC_ERR(0x52)
++#define EC_VAL_TX_CH_ALREADY_OPEN             EC_ERR(0x53)
++#define EC_VAL_CH_ALREADY_SETUP               EC_ERR(0x54)
++#define EC_VAL_RCB_NEEDS_BUFFER               EC_ERR(0x55) /* +GSG 030410 */
++#define EC_VAL_RCB_DROPPED                    EC_ERR(0x56) /* +GSG 030410 */
++#define EC_VAL_INVALID_VALUE                  EC_ERR(0x57)
++
++/**
++@defgroup shared_data Shared Data Structures
++
++The data structures documented here are shared by all modules.
++*/
++
++/**
++ *  @ingroup shared_data
++ *  This is the fragment list structure.  Each fragment list entry contains a
++ *  length and a data buffer.
++ */
++typedef struct
++  {
++   bit32u   len;    /**< Length of the fragment in bytes (lower 16 bits are valid).  For SOP, upper 16 bits is the buffer offset. */
++   void     *data;  /**< Pointer to fragment data. */
++   void     *OsInfo; /**< Pointer to OS defined data. */
++  }FRAGLIST;
++
++#if defined (_CPHAL_CPMAC)
++#define CB_PASSCRC_BIT     (1<<26)
++
++/* CPMAC CPHAL STATUS */
++#define CPMAC_STATUS_LINK               (1 << 0)
++#define CPMAC_STATUS_LINK_DUPLEX        (1 << 1)  /* 0 - HD, 1 - FD */
++#define CPMAC_STATUS_LINK_SPEED         (1 << 2)  /* 0 - 10, 1 - 100 */
++
++/*   ADAPTER CHECK Codes */
++
++#define CPMAC_STATUS_ADAPTER_CHECK             (1 << 7)
++#define CPMAC_STATUS_HOST_ERR_DIRECTION        (1 << 8)
++#define CPMAC_STATUS_HOST_ERR_CODE             (0xF << 9)
++#define CPMAC_STATUS_HOST_ERR_CH               (0x7 << 13)
++
++#define _CPMDIO_DISABLE                 (1 << 0)
++#define _CPMDIO_HD                      (1 << 1)
++#define _CPMDIO_FD                      (1 << 2)
++#define _CPMDIO_10                      (1 << 3)
++#define _CPMDIO_100                     (1 << 4)
++#define _CPMDIO_NEG_OFF                 (1 << 5)
++#define _CPMDIO_LOOPBK                  (1 << 16)
++#define _CPMDIO_AUTOMDIX                (1 << 17)   /* Bit 16 and above not used by MII register */
++#define _CPMDIO_NOPHY                   (1 << 20)
++#endif
++
++/**
++ *  @ingroup shared_data
++ *  Channel specific configuration information.  This structure should be
++ *  populated by upper-layer software prior to calling @c ChannelSetup().  Any
++ *  configuration item that can be changed on a per channel basis should
++ *  be represented here.  Each module may define this structure with additional
++ *  module-specific members.
++ */
++typedef struct
++  {
++   int Channel;        /**< Channel number. */
++   int Direction;      /**< DIRECTION_RX(1) or DIRECTION_TX(0). */
++   OS_SETUP *OsSetup;  /**< OS defined information associated with this channel. */
++
++#if defined(_CPHAL_AAL5) || defined (_CPHAL_CPSAR) || defined (_CPHAL_CPMAC)
++   int RxBufSize;      /**< Size (in bytes) for each Rx buffer.*/
++   int RxBufferOffset; /**< Number of bytes to offset rx data from start of buffer (must be less than buffer size). */
++   int RxNumBuffers;   /**< The number of Rx buffer descriptors to allocate for Ch. */
++   int RxServiceMax;   /**< Maximum number of packets to service at one time. */
++
++   int TxNumBuffers;   /**< The number of Tx buffer descriptors to allocate for Ch. */
++   int TxNumQueues;    /**< Number of Tx queues for this channel (1-2). Choosing 2 enables a low priority SAR queue. */
++   int TxServiceMax;   /**< Maximum number of packets to service at one time. */
++#endif
++
++#if defined(_CPHAL_AAL5) || defined(_CPHAL_CPSAR)
++   int CpcsUU;      /**< The 2-byte CPCS UU and CPI information. */
++   int Gfc;         /**< Generic Flow Control. */
++   int Clp;         /**< Cell Loss Priority. */
++   int Pti;         /**< Payload Type Indication. */
++#endif
++
++#if defined(_CPHAL_AAL2) || defined(_CPHAL_AAL5) || defined(_CPHAL_CPSAR)
++   int DaMask;      /**< Specifies whether credit issuance is paused when Tx data not available. */
++   int Priority;    /**< Priority bin this channel will be scheduled within. */
++   int PktType;     /**< 0=AAL5,1=Null AAL,2=OAM,3=Transparent,4=AAL2. */
++   int Vci;         /**< Virtual Channel Identifier. */
++   int Vpi;         /**< Virtual Path Identifier. */
++   int FwdUnkVc;    /**< Enables forwarding of unknown VCI/VPI cells to host. 1=enable, 0=disable. */
++
++   /* Tx VC State */
++   int TxVc_CellRate;  /**< Tx rate, set as clock ticks between transmissions (SCR for VBR, CBR for CBR). */
++   int TxVc_QosType;   /**< 0=CBR,1=VBR,2=UBR,3=UBRmcr. */
++   int TxVc_Mbs;       /**< Min Burst Size in cells.*/
++   int TxVc_Pcr;       /**< Peak Cell Rate for VBR in clock ticks between transmissions. */
++
++   bit32 TxVc_AtmHeader; /**< ATM Header placed on firmware gen'd OAM cells for this Tx Ch (must be big endian with 0 PTI). */
++   int TxVc_OamTc;     /**< TC Path to transmit OAM cells for TX connection (0,1). */
++   int TxVc_VpOffset;  /**< Offset to the OAM VP state table. */
++   /* Rx VC State */
++   int RxVc_OamCh;     /**< Ch to terminate rx'd OAM cells to be forwarded to the host. */
++   int RxVc_OamToHost; /**< 0=do not pass, 1=pass. */
++   bit32 RxVc_AtmHeader; /**< ATM Header placed on firmware gen'd OAM cells for this Rx conn (must be big endian with 0 PTI). */
++   int RxVc_OamTc;     /**< TC Path to transmit OAM cells for RX connection (0,1). */
++   int RxVc_VpOffset;  /**< Offset to the OAM VP state table. */
++   /* Tx VP State */
++   int TxVp_OamTc;     /**< TC Path to transmit OAM cells for TX VP connection (0,1). */
++   bit32 TxVp_AtmHeader; /**< ATM Header placed on firmware gen'd VP OAM cells for this Tx VP conn (must be big endian with 0 VCI). */
++   /* Rx VP State  */
++   int RxVp_OamCh;     /**< Ch to terminate rx'd OAM cells to be forwarded to the host. */
++   int RxVp_OamToHost; /**< 0=do not pass, 1=pass. */
++   bit32 RxVp_AtmHeader; /**< ATM Header placed on firmware gen'd OAM cells for this Rx VP conn (must be big endian with 0 VCI). */
++   int RxVp_OamTc;     /**< TC Path to transmit OAM cells for RX VP connection (0,1). */
++   int RxVp_OamVcList; /**< Indicates all VC channels associated with this VP channel (one-hot encoded). */
++#endif
++
++
++#ifdef _CPHAL_VDMAVT
++   bit32u RemFifoAddr; /* Mirror mode only. */
++   bit32u FifoAddr;
++   bit32  PollInt;
++   bit32  FifoSize;
++   int    Ready;
++#endif
++
++  }CHANNEL_INFO;
++
++/*
++ *  This structure contains each statistic value gathered by the CPHAL.
++ *  Applications may access statistics data by using the @c StatsGet() routine.
++ */
++/* STATS */
++#if defined(_CPHAL_AAL2) || defined(_CPHAL_AAL5) || defined(_CPHAL_CPSAR)
++typedef struct
++  {
++   bit32u CrcErrors[16];
++   bit32u LenErrors[16];
++   bit32u DmaLenErrors[16];
++   bit32u AbortErrors[16];
++   bit32u StarvErrors[16];
++   bit32u TxMisQCnt[16][2];
++   bit32u RxMisQCnt[16];
++   bit32u RxEOQCnt[16];
++   bit32u TxEOQCnt[16][2];
++   bit32u RxPacketsServiced[16];
++   bit32u TxPacketsServiced[16][2];
++   bit32u RxMaxServiced;
++   bit32u TxMaxServiced[16][2];
++   bit32u RxTotal;
++   bit32u TxTotal;
++  } STAT_INFO;
++#endif
++
++/*
++ *  VDMA Channel specific configuration information
++ */
++#ifdef _CPHAL_AAL2
++typedef struct
++  {
++   int Ch;           /**< Channel Number */
++   int RemoteEndian; /**< Endianness of remote VDMA-VT device */
++   int CpsSwap;      /**< When 0, octet 0 in CPS pkt located in LS byte of 16-bit word sent to rem VDMA device.  When 1, in MS byte. */
++  }VdmaChInfo;
++#endif
++
++#ifndef _CPHAL
++  typedef void HAL_DEVICE;
++  typedef void HAL_PRIVATE;
++  typedef void HAL_RCB;
++  typedef void HAL_RECEIVEINFO;
++#endif
++
++/**
++ *  @ingroup shared_data
++ *  The HAL_FUNCTIONS struct defines the function pointers used by upper layer
++ *  software.  The upper layer software receives these pointers through the
++ *  call to xxxInitModule().
++ */
++typedef struct
++  {
++  int  (*ChannelSetup)    (HAL_DEVICE *HalDev, CHANNEL_INFO *Channel, OS_SETUP *OsSetup);
++  int  (*ChannelTeardown) (HAL_DEVICE *HalDev, int Channel, int Mode);
++  int  (*Close)           (HAL_DEVICE *HalDev, int Mode);
++  int  (*Control)         (HAL_DEVICE *HalDev, const char *Key, const char *Action, void *Value);
++  int  (*Init)            (HAL_DEVICE *HalDev);
++  int  (*Open)            (HAL_DEVICE *HalDev);
++  int  (*PacketProcessEnd) (HAL_DEVICE *HalDev);
++  int  (*Probe)           (HAL_DEVICE *HalDev);
++  int  (*RxReturn)        (HAL_RECEIVEINFO *HalReceiveInfo, int StripFlag);
++  int  (*Send)            (HAL_DEVICE *HalDev, FRAGLIST *FragList, int FragCount, int PacketSize, OS_SENDINFO *OsSendInfo, bit32u Mode);
++  int  (*Shutdown)        (HAL_DEVICE *HalDev);
++  int  (*Tick)            (HAL_DEVICE *HalDev);
++
++#ifdef _CPHAL_AAL5
++  int  (*Kick) (HAL_DEVICE *HalDev, int Queue);
++  void (*OamFuncConfig)   (HAL_DEVICE *HalDev, unsigned int OamConfig);
++  void (*OamLoopbackConfig)   (HAL_DEVICE *HalDev, unsigned int OamConfig, unsigned int *LLID, unsigned int CorrelationTag);
++  volatile bit32u* (*RegAccess)(HAL_DEVICE *HalDev, bit32u RegOffset);
++  STAT_INFO*  (*StatsGetOld)(HAL_DEVICE *HalDev);
++#endif
++  } HAL_FUNCTIONS;
++
++/**
++ *  @ingroup shared_data
++ *  The OS_FUNCTIONS struct defines the function pointers for all upper layer
++ *  functions accessible to the CPHAL.  The upper layer software is responsible
++ *  for providing the correct OS-specific implementations for the following
++ *  functions. It is populated by calling InitModule() (done by the CPHAL in
++ *  xxxInitModule().
++ */
++typedef struct
++  {
++  int   (*Control)(OS_DEVICE *OsDev, const char *Key, const char *Action, void *Value);
++  void  (*CriticalOn)(void);
++  void  (*CriticalOff)(void);
++  void  (*DataCacheHitInvalidate)(void *MemPtr, int Size);
++  void  (*DataCacheHitWriteback)(void *MemPtr, int Size);
++  int   (*DeviceFindInfo)(int Inst, const char *DeviceName, void *DeviceInfo);
++  int   (*DeviceFindParmUint)(void *DeviceInfo, const char *Parm, bit32u *Value);
++  int   (*DeviceFindParmValue)(void *DeviceInfo, const char *Parm, void *Value);
++  void  (*Free)(void *MemPtr);
++  void  (*FreeRxBuffer)(OS_RECEIVEINFO *OsReceiveInfo, void *MemPtr);
++  void  (*FreeDev)(void *MemPtr);
++  void  (*FreeDmaXfer)(void *MemPtr);
++  void  (*IsrRegister)(OS_DEVICE *OsDev, int (*halISR)(HAL_DEVICE*, int*), int InterruptBit);
++  void  (*IsrUnRegister)(OS_DEVICE *OsDev, int InterruptBit);
++  void* (*Malloc)(bit32u size);
++  void* (*MallocDev)(bit32u Size);
++  void* (*MallocDmaXfer)(bit32u size, void *MemBase, bit32u MemRange);
++  void* (*MallocRxBuffer)(bit32u size, void *MemBase, bit32u MemRange,
++                       OS_SETUP *OsSetup, HAL_RECEIVEINFO *HalReceiveInfo,
++                       OS_RECEIVEINFO **OsReceiveInfo, OS_DEVICE *OsDev);
++  void* (*Memset)(void *Dest, int C, bit32u N);
++  int   (*Printf)(const char *Format, ...);
++  int   (*Receive)(OS_DEVICE *OsDev,FRAGLIST *FragList,bit32u FragCount,
++                 bit32u PacketSize,HAL_RECEIVEINFO *HalReceiveInfo, bit32u Mode);
++  int   (*SendComplete)(OS_SENDINFO *OsSendInfo);
++  int   (*Sprintf)(char *S, const char *Format, ...);
++  int   (*Strcmpi)(const char *Str1, const char *Str2);
++  unsigned int (*Strlen)(const char *S);
++  char* (*Strstr)(const char *S1, const char *S2);
++  unsigned long  (*Strtoul)(const char *Str, char **Endptr, int Base);
++  void  (*TeardownComplete)(OS_DEVICE *OsDev, int Ch, int Direction);
++  } OS_FUNCTIONS;
++
++/************** MODULE SPECIFIC STUFF BELOW **************/
++
++#ifdef _CPHAL_CPMAC
++
++/*
++int halCpmacInitModule(HAL_DEVICE **HalDev, OS_DEVICE *OsDev, HAL_FUNCTIONS *HalFunc, int (*osBridgeInitModule)(OS_FUNCTIONS *), void* (*osMallocDev) (bit32u), int *Size, int inst);
++*/
++
++int halCpmacInitModule(HAL_DEVICE **HalDev,
++                 OS_DEVICE *OsDev,
++                 HAL_FUNCTIONS **HalFunc,
++                 OS_FUNCTIONS *OsFunc,
++                 int OsFuncSize,
++                 int *HalFuncSize,
++                 int Inst);
++#endif
++
++#ifdef _CPHAL_AAL5
++/*
++ *  @ingroup shared_data
++ *  The AAL5_FUNCTIONS struct defines the AAL5 function pointers used by upper layer
++ *  software.  The upper layer software receives these pointers through the
++ *  call to cphalInitModule().
++ */
++/*
++typedef struct
++  {
++  int  (*ChannelSetup)(HAL_DEVICE *HalDev, CHANNEL_INFO *HalCh, OS_SETUP *OsSetup);
++  int  (*ChannelTeardown)(HAL_DEVICE *HalDev, int Ch, int Mode);
++  int  (*Close)(HAL_DEVICE *HalDev, int Mode);
++  int  (*Init)(HAL_DEVICE *HalDev);
++  int  (*ModeChange)(HAL_DEVICE *HalDev, char *DeviceParms);
++  int  (*Open)(HAL_DEVICE *HalDev);
++  int  (*InfoGet)(HAL_DEVICE *HalDev, int Key, void *Value);
++  int  (*Probe)(HAL_DEVICE *HalDev);
++  int  (*RxReturn)(HAL_RECEIVEINFO *HalReceiveInfo, int StripFlag);
++  int  (*Send)(HAL_DEVICE *HalDev,FRAGLIST *FragList,int FragCount,
++                 int PacketSize,OS_SENDINFO *OsSendInfo,int Ch, int Queue,
++                 bit32u Mode);
++  int  (*StatsClear)(HAL_DEVICE *HalDev);
++  STAT_INFO*  (*StatsGet)(HAL_DEVICE *HalDev);
++  int  (*Status)(HAL_DEVICE *HalDev);
++  void (*Tick)(HAL_DEVICE *HalDev);
++  int  (*Kick)(HAL_DEVICE *HalDev, int Queue);
++  volatile bit32u* (*RegAccess)(HAL_DEVICE *HalDev, bit32u RegOffset);
++  } AAL5_FUNCTIONS;
++*/
++
++int cpaal5InitModule(HAL_DEVICE **HalDev,
++                 OS_DEVICE *OsDev,
++                 HAL_FUNCTIONS **HalFunc,
++                 OS_FUNCTIONS *OsFunc,
++                 int OsFuncSize,
++                 int *HalFuncSize,
++                 int Inst);
++#endif
++
++#ifdef _CPHAL_AAL2
++/**
++ *  @ingroup shared_data
++ *  The AAL2_FUNCTIONS struct defines the AAL2 function pointers used by upper layer
++ *  software.  The upper layer software receives these pointers through the
++ *  call to cphalInitModule().
++ */
++typedef struct
++  {
++  int  (*ChannelSetup)(HAL_DEVICE *HalDev, CHANNEL_INFO *HalCh, OS_SETUP *OsSetup);
++  int  (*ChannelTeardown)(HAL_DEVICE *HalDev, int Ch, int Mode);
++  int  (*Close)(HAL_DEVICE *HalDev, int Mode);
++  int  (*Init)(HAL_DEVICE *HalDev);
++  int  (*ModeChange)(HAL_DEVICE *HalDev, char *DeviceParms);
++  int  (*Open)(HAL_DEVICE *HalDev);
++  int  (*OptionsGet)(HAL_DEVICE *HalDev, char *Key, bit32u *Value);
++  int  (*Probe)(HAL_DEVICE *HalDev);
++
++  int  (*StatsClear)(HAL_DEVICE *HalDev);
++  STAT_INFO*  (*StatsGet)(HAL_DEVICE *HalDev);
++  int  (*Status)(HAL_DEVICE *HalDev);
++  void (*Tick)(HAL_DEVICE *HalDev);
++  int  (*Aal2UuiMappingSetup)(HAL_DEVICE *HalDev, int VC, int UUI,
++                                    int VdmaCh, int UUIDiscard);
++  int  (*Aal2RxMappingSetup)(HAL_DEVICE *HalDev, int VC, int CID,
++                                   int LC);
++  int  (*Aal2TxMappingSetup)(HAL_DEVICE *HalDev, int VC, int LC, int VdmaCh);
++  int  (*Aal2VdmaChSetup)(HAL_DEVICE *HalDev, bit32u RemVdmaVtAddr,
++                               VdmaChInfo *VdmaCh);
++  volatile bit32u* (*RegAccess)(HAL_DEVICE *HalDev, bit32u RegOffset);
++  int  (*Aal2ModeChange)(HAL_DEVICE *HalDev, int Vc, int RxCrossMode,
++                           int RxMultiMode, int TxMultiMode, int SchedMode,
++                           int TcCh);
++  void (*Aal2VdmaEnable)(HAL_DEVICE *HalDev, int Ch);
++  int  (*Aal2VdmaDisable)(HAL_DEVICE *HalDev, int Ch);
++  } AAL2_FUNCTIONS;
++
++int cpaal2InitModule(HAL_DEVICE **HalDev,
++                 OS_DEVICE *OsDev,
++                 AAL2_FUNCTIONS **HalFunc,
++                 OS_FUNCTIONS *OsFunc,
++                 int OsFuncSize,
++                 int *HalFuncSize,
++                 int Inst);
++#endif
++
++#ifdef _CPHAL_VDMAVT
++/**
++ *  @ingroup shared_data
++ *  The VDMA_FUNCTIONS struct defines the HAL function pointers used by upper layer
++ *  software.  The upper layer software receives these pointers through the
++ *  call to InitModule().
++ *
++ *  Note that this list is still under definition.
++ */
++typedef struct
++  {
++  bit32  (*Init)( HAL_DEVICE *VdmaVtDev);
++    /*  bit32  (*SetupTxFifo)(HAL_DEVICE *VdmaVtDev, bit32u LclRem,
++                  bit32u Addr, bit32u Size, bit32u PollInt);
++    bit32  (*SetupRxFifo)(HAL_DEVICE *VdmaVtDev, bit32u LclRem,
++                  bit32u Addr, bit32u Size, bit32u PollInt); */
++  bit32  (*Tx)(HAL_DEVICE *VdmaVtDev);
++  bit32  (*Rx)(HAL_DEVICE *VdmaVtDev);
++  bit32  (*SetRemoteChannel)(HAL_DEVICE *VdmaVtDev, bit32u RemAddr,
++                         bit32u RemDevID);
++  bit32  (*ClearRxInt)(HAL_DEVICE *VdmaVtDev);
++  bit32  (*ClearTxInt)(HAL_DEVICE *VdmaVtDev);
++  bit32  (*Open)(HAL_DEVICE *VdmaVtDev);
++  bit32  (*Close)(HAL_DEVICE *VdmaVtDev);
++  int    (*Control)         (HAL_DEVICE *HalDev, const char *Key, const char *Action, void *Value);
++  int    (*ChannelSetup)(HAL_DEVICE *VdmaVtDev, CHANNEL_INFO *HalCh, OS_SETUP *OsSetup);
++  int    (*ChannelTeardown)(HAL_DEVICE *VdmaVtDev, int Ch, int Mode);
++  int    (*Send)(HAL_DEVICE *VdmaVtDev,FRAGLIST *FragList,int FragCount,
++                 int PacketSize,OS_SENDINFO *OsSendInfo,bit32u Mode);
++  } VDMA_FUNCTIONS;
++
++int VdmaInitModule(HAL_DEVICE **VdmaVt,
++                 OS_DEVICE *OsDev,
++                 VDMA_FUNCTIONS **VdmaVtFunc,
++                 OS_FUNCTIONS *OsFunc,
++                 int OsFuncSize,
++                 int *HalFuncSize,
++                 int Inst);
++#endif
++
++/*
++extern int cphalInitModule(MODULE_TYPE ModuleType, HAL_DEVICE **HalDev, OS_DEVICE *OsDev, HAL_FUNCTIONS *HalFunc,
++                      int (*osInitModule)(OS_FUNCTIONS *), void* (*osMallocDev)(bit32u),
++                      int *Size, int Inst);
++*/
++
++
++#ifdef _CPHAL_AAL5
++extern const char hcSarFrequency[];
++#endif
++
++#ifdef _CPHAL_CPMAC
++/* following will be common, once 'utl' added */
++extern const char hcClear[];
++extern const char hcGet[];
++extern const char hcSet[];
++extern const char hcTick[];
++
++extern const char hcCpuFrequency[];
++extern const char hcCpmacFrequency[];
++extern const char hcMdioBusFrequency[];
++extern const char hcMdioClockFrequency[];
++extern const char hcCpmacBase[];
++extern const char hcPhyNum[];
++extern const char hcSize[];
++extern const char hcCpmacSize[];
++extern const char hcPhyAccess[];
++extern const char hcMdixMask[];
++extern const char hcMdioMdixSwitch[];
++#endif
++
++#endif  /*  end of _INC_    */
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/dox_cpmac.h linux-2.4.30/drivers/net/avalanche_cpmac/dox_cpmac.h
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/dox_cpmac.h  1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/dox_cpmac.h       2005-04-15 05:10:41.000000000 +0200
+@@ -0,0 +1,842 @@
++/*****************************************************************************
++ *  TNETDxxxx Software Support
++ *  Copyright (c) 2002,2003 Texas Instruments Incorporated. All Rights Reserved.
++ *
++ *  FILE:
++ *
++ *  DESCRIPTION:
++ *      This file contains documentation for the CPMAC
++ *
++ *  HISTORY:
++ *  @author Michael Hanrahan/Greg Guyotte
++ *  @version 1.00
++ *  @date    03-Dec-2002
++ *****************************************************************************/
++#ifndef _DOX_CPMAC_H
++#define _DOX_CPMAC_H
++/**
++@page CPMAC_Implementation_Details Version
++
++@copydoc CPMAC_Version
++*/
++
++/**
++@page cpmac_intro Introduction
++
++The CPMAC implementation will support 8 channels for transmit and 8 channel for
++receive.  Each of the 8 transmit channels has 1 queue associated with it.  It is
++recommended that only 1 channel is used for @c Receive() per processor.
++*/
++
++/**
++@page cpmac_details API Implementation Details
++@par osReceive
++@p Mode parameter
++- The Upper 16 bits of Mode match Word 3 of the Rx Buffer Descriptor
++
++@par halSend
++@p Mode parameter
++-  Bits 0-7 contain the Channel Number
++-  Bits 8-25 are reserved
++-  Bit  26 - if 0, the CRC will be calculated, if 1 the CRC will be Passed
++-  Bits 27-31 : reserved
++@section cpmac_keys Control Keys
++
++@par StateChange
++CPHAL calls the OS when a state change is detected.
++OS should check the CPMAC Status. See the Control Key 'Status' for more details.
++
++@par Status
++OS calls the CPHAL to obtain Status information. The Returned status is as follows
++
++@par MaxFrags
++The OS may "Set" or "Get" this value.  This defines the maximum
++number of fragments that can be received by the CPMAC Rx port.  The default
++value for CPMAC is 2.  This provides enough space to receive a maximum
++length packet (1,518 bytes) with the default buffer size of 1518 and any
++amount of RxBufferOffset.  If the buffer size is configured to be smaller,
++the OS *MUST* modify this parameter according to the following formula:
++((System Max packet length)/(RxBufSize)) + 1.  (The extra 1 fragment is to
++allow for RxBufferOffset)
++
++@code
++// Following defined in "cpswhal_cpmac.h"
++// CPMAC CPHAL STATUS
++#define CPMAC_STATUS_LINK               (1 << 0)
++#define CPMAC_STATUS_LINK_DUPLEX        (1 << 1)  // 0 - HD, 1 - FD
++#define CPMAC_STATUS_LINK_SPEED         (1 << 2)  // 0 - 10, 1 - 100
++
++// ADAPTER CHECK Codes
++#define CPMAC_STATUS_ADAPTER_CHECK             (1 << 7)
++#define CPMAC_STATUS_HOST_ERR_DIRECTION        (1 << 8)    // 0 - Tx, 1 - Rx
++#define CPMAC_STATUS_HOST_ERR_CODE             (0xF << 9)  See CPMAC Guide
++#define CPMAC_STATUS_HOST_ERR_CH               (0x7 << 13) See CPMAC Guide
++@endcode
++
++@code
++void osStateChange(OS_DEVICE *OsDev)
++  {
++  int status;
++  OsDev->HalFunc->Control(OsDev->HalDev, "Status", hcGet, &status);
++  if(status & CPMAC_STATUS_ADAPTER_CHECK)
++    {
++    printf("[osStateChange[%d]]  HAL notified OS of AdapterCheck (Link Status 0x%08X)\n", OsDev->port, status);
++    adaptercheck(OsDev->port);
++    }
++  else
++    {
++    printf("[osStateChange[%d]]  HAL notified OS of State Change (Link Status %s)\n", OsDev->port, (status & CPMAC_STATUS_LINK) ? "Up" : "Down");
++    if(status & CPMAC_STATUS_LINK)
++      {
++      printf("Speed %s, Duplex %s\n",
++      status & CPMAC_STATUS_LINK_SPEED ? "100" : "10",
++      status & CPMAC_STATUS_LINK_DUPLEX ? "FD" : "HD");
++      }
++    }
++@endcode
++
++@par Tick
++     The CPHAL calls the OS to set the interval for calling halTick()<BR>
++     Note: Predefined value hcTick now recommended for use.
++@code
++***  Example Code ***
++
++*** CPHAL code ***
++int Ticks;
++HalDev->OsFunc->Control(HalDev->OsDev, hcTick, hcSet, &Ticks);
++
++*** OS code ***
++  ..
++  if(osStrcmpi(pszKey, hcTick) == 0)
++  {
++    if(osStrcmpi(pszAction, hcSet) == 0)
++    {
++      // Enable the Tick Interval
++      if(*(unsigned int *) ParmValue)
++        printf("osTickSet: Interval = %d ticks\n", Interval);
++    }
++    else
++    if(osStrcmpi(pszAction, hcClear) == 0)
++    {
++        // Request disabling of the Tick Timer, ParmValue is ignored
++    }
++  }
++@endcode
++
++@par The following information can be obtained by the OS via 'Get'
++
++- StatsDump : OS supplies pointer to an 36 element unsigned int array
++CPHAL will populate the array with the current Statistics values.<BR>
++Note: all hcXXXX values are predefined and should be used by the OS.
++
++- hcPhyNum : Returns the PHY number.
++- hcCpmacBase : Returns the base-address of the CPMAC device
++- hcCpmacSize : Returns size of the CPMAC memory map
++
++
++@par Phy Register Communication
++
++halControl() is used to read and write the Phy Registers via the key hcPhyAccess
++
++Both reading and writing the Phy registers involve setting the Value parameter of halControl()
++<BR>
++Value is a 32-bit value with bits partioned as follows
++<BR>
++
++   0 -  4  Phy Number   <BR>
++   5 -  9  Phy Register <BR>
++  10 - 15  reserved     <BR>
++  16 - 31  Data  (write only)
++<BR>
++
++
++<B>Reading the Phy register</B>
++
++@code
++    bit32u Value;
++    bit32u RegAddr;
++    bit32u PhyNum;
++    bit32u PhyRegisterData;
++
++    //  Read Phy 31, register 20
++
++    PhyNum  = 31;
++    RegAddr = 20;
++
++    Value = (RegAddr << 5);
++    Value |= (PhyNum & 0x1F);
++
++    rc  = HalFunc->Control(HalDev, hcPhyAccess, hcGet, (bit32u *) &Value)
++    If(rc == 0)
++    {
++        // Value is overwriten with the value in Register 20 of Phy number 31.
++        PhyRegisterData = Value;
++    }
++@endcode
++
++<B>Writing the Phy register</B>
++@code
++    bit32u Value;
++    bit32u RegAddr;
++    bit32u PhyNum;
++    bit32u PhyRegisterData;
++
++    //  Reset Phy 23
++
++    PhyNum  = 23;
++    RegAddr = 0;
++    PhyRegisterData = 0x8000;  // Reset bit set
++
++    Value = (RegAddr << 5);
++    Value |= (PhyNum & 0x1F);
++    Value |= (PhyRegisterData << 16);
++
++    rc  = HalFunc->Control(HalDev, hcPhyAccess, hcSet, (bit32u *) &Value)
++
++    // Check is reset if done
++
++    PhyNum  = 23;
++    RegAddr = 0;
++
++    Value = (RegAddr << 5);
++    Value |= (PhyNum & 0x1F);
++
++    rc  = HalFunc->Control(HalDev, hcPhyAccess, hcGet, (bit32u *) &Value)
++
++    If(rc == 0)
++    {
++        // Value is overwriten with the value in Register 0 of Phy number 23.
++        PhyRegisterData = Value;
++        if((PhyRegisterData & 0x8000) == 0)
++           ResetIsComplete;
++    }
++
++@endcode
++<B>
++*** Example Showing turning values off/on ***
++<BR>
++</B>
++
++@code
++
++int On=1;
++int Off=0;
++   # Turn On loopback
++   OsDev->HalFunc->Control(OsDev->HalDev, "CTRL_LOOPBACK", hcSet, (int*) &On);
++
++   #  Turn off RX Flow
++   OsDev->HalFunc->Control(OsDev->HalDev, "RX_FLOW_EN", hcSet, (int*) &Off);
++@endcode
++
++@par CPMAC Configurable Parameters
++
++- RX_PASS_CRC        : See MBP_Enable description
++- RX_QOS_EN          : See MBP_Enable description
++- RX_NO_CHAIN        : See MBP_Enable description
++- RX_CMF_EN          : See MBP_Enable description
++- RX_CSF_EN          : See MBP_Enable description
++- RX_CEF_EN          : See MBP_Enable description
++- RX_CAF_EN          : See MBP_Enable description
++- RX_PROM_CH         : See MBP_Enable description
++- RX_BROAD_EN        : See MBP_Enable description
++- RX_BROAD_CH        : See MBP_Enable description
++- RX_MULT_EN         : See MBP_Enable description
++- RX_MULT_CH         : See MBP_Enable description
++
++- TX_PTYPE           : See MacControl description
++- TX_PACE            : See MacControl description
++- TX_FLOW_EN         : See MacControl description
++- RX_FLOW_EN         : See MacControl description
++- CTRL_LOOPBACK      : See MacControl description
++
++- RX_MAXLEN          : See CPMAC Guide
++- RX_FILTERLOWTHRESH : See CPMAC Guide
++- RX0_FLOWTHRESH     : See CPMAC Guide
++- RX_UNICAST_SET     : See CPMAC Guide
++- RX_UNICAST_CLEAR   : See CPMAC Guide
++
++@par Multicast Support
++- RX_MULTI_ALL       : When used with hcSet, sets all the Hash Bits. When used
++with hcClear clears all the Hash Bits.
++- RX_MULTI_SINGLE    : When used with hcSet, adds the Hashed Mac Address. When used
++with hcClear deletes the Hashed Mac Address.
++Note: Support will be added to keep track of Single additions and deletions.
++
++@code
++*** Example Code ***
++
++*** OS code ***
++  bit8u  MacAddress[6];
++  MacAddress[0] = 0x80;
++  MacAddress[1] = 0x12;
++  MacAddress[2] = 0x34;
++  MacAddress[3] = 0x56;
++  MacAddress[4] = 0x78;
++  MacAddress[5] = 0x78;
++  OsDev->HalFunc->Control(OsDev->HalDev, "RX_MULTI_SINGLE", hcSet, (bit8u*) &MacAddress);
++  OsDev->HalFunc->Control(OsDev->HalDev, "RX_MULTI_SINGLE", hcClear, (bit8u*) &MacAddress);
++  OsDev->HalFunc->Control(OsDev->HalDev, "RX_MULTI_ALL", hcSet, NULL);
++  OsDev->HalFunc->Control(OsDev->HalDev, "RX_MULTI_ALL", hcClear, NULL);
++@endcode
++@par MdioConnect Fields
++<BR>
++- "MdioConnect"     : The OS can set the Phy connection using this key. The default connection is Auto-Negotiation ON, All modes possible.
++
++
++- _CPMDIO_HD       <----- Allow Half Duplex, default is 1 (On)
++- _CPMDIO_FD       <----- Allow Full Duplex, default is 1 (On)
++- _CPMDIO_10       <----- Allow 10  Mbs, default is 1 (On)
++- _CPMDIO_100      <----- Allow 100 Mbs, default is 1 (On)
++- _CPMDIO_NEG_OFF  <----- Turn off Auto Negotiation, default is 0 (Auto Neg is on)
++- _CPMDIO_NOPHY    <----- Set for use with Marvel-type switch, default is 0 (Phy present)
++- _CPMDIO_AUTOMDIX  <---- Enables Auto Mdix (in conjunction with MdixMask), default is 1 (On)
++
++Note: When _CPMDIO_NOPHY is set, CPMAC will report being linked at 100/FD. Reported PhyNum will be 0xFFFFFFFF
++
++@par Setting CPMAC for use with a Marvel-type Switch
++@code
++     bit32u MdioConnect;
++
++     MdioConnect = _CPMDIO_NOPHY;
++     OsDev->HalFunc->Control(OsDev->HalDev, "MdioConnect", hcSet, (bit32u*) &MdioConnect);
++@endcode
++
++@par OS Support for MDIO
++@p The OS will need to supply the following values which the CPHAL will request via halControl()
++<BR>
++- MdioBusFrequency : The frequency of the BUS that MDIO is on (requested via hcMdioBusFrequency)
++<BR>
++- MdioClockFrequency : The desired Clock Frequency that MDIO qill operate at (requested via hcMdioClockFrequency)
++*/
++
++/**
++@page cpmac_conf DeviceFindxxx() Parameters
++
++These are some of the parameters that the CPMAC will request via the DeviceFindxxx() functions -
++<BR>
++- "Mlink"    : bit mask indicating what link status method Phy is using. Default is MDIO state machine (0x0)
++- "PhyMask"  : bit mask indicating PhyNums used by this CPMAC (e.g 0x8000000, PhyNum is 31)
++- "MdixMask" : bit mask indicating which Phys support AutoMdix. Default is 0x0 (None)
++<BR>
++@par Example cpmac definition from the options.conf for the Sangam VDB
++<BR>
++- cpmac( id=eth0, base=0xA8610000, size=0x800, reset_bit=17, int_line=19, PhyMask=0x80000000, MLink=0, MdixMask=0 )
++*/
++
++/**
++@page auto_mdix Auto Mdix Support
++
++Auto Mdix selection is controlled by two elements in the CPMAC. First the OS can turn Auto Midx On or Off by the use of the
++MdioConnect field, _CPMDIO_AUTOMDIX. This is defaulted ON.  For actual Auto Mdix operation the Phy must also be Auto Mdix capable.
++This is specified by the DeviceFindxxx() field, "MdixMask" (supplied as the variable hcMdixMask).
++If both these fields are set then the CPMDIO state machine will be enabled for Auto Mdix checking.
++If a switch to MDI or MDIX mode is needed, the CPMAC will signal this to the OS via Control() using
++the hcMdioMdixSwitch key.
++
++@par OS example for responding to a Mdix Switch Request
++<BR>
++@code
++if(osStrcmpi(pszKey, hcMdioMdixSwitch) == 0)  // See if key is Mdix Switch Request
++  {
++      if(osStrcmpi(pszAction, hcSet) == 0)   // Only respond to Set requests
++      {
++
++          bit32u Mdix;
++
++          Mdix = *(bit32u *) ParmValue;     // Extract requested Mode
++                                            // 0 : MDI
++                                            // 1 : MDIX
++          if(Mdix)
++            osSetPhyIntoMdixMode();         // Device specific logic
++          else
++            osSetPhyIntoMdiMode();          // Device specific logic
++          rc = 0;                           // Set return code as Successfull
++      }
++@endcode
++*/
++
++/**
++@page cpmac_stats CPMAC Specific Statistics
++
++Statistics level '0' contains all CPMAC specific statistics.
++
++
++*/
++
++/**
++@page Example_Driver_Code
++
++@section  example_intro Introduction
++This section provides an in-depth code example for driver implementations.  The code
++below illustrates the use of the CPMAC HAL, but is equally applicable to any CPHAL
++implementation. Note: the CPHAl constants hcGet, hcSet etc., are currently available for use with teh CPMAC module.
++Other modules should continue to use pszGET, etc. until these are made generally available.
++
++@par Pull Model Example
++
++@code
++
++#define _CPHAL_CPMAC
++
++typedef struct _os_device_s  OS_DEVICE;
++typedef struct _os_receive_s OS_RECEIVEINFO;
++typedef struct _os_send_s    OS_SENDINFO;
++typedef struct _os_setup_s   OS_SETUP;
++
++#include "cpswhal_cpmac.h"
++
++#define dbgPrintf printf
++
++typedef struct  _os_device_s
++{
++   HAL_DEVICE    *HalDev;
++   HAL_FUNCTIONS *HalFunc;
++   OS_FUNCTIONS  *OsFunc;
++   OS_SETUP      *OsSetup;
++   bit32u        Interrupt;
++   int           (*halIsr)(HAL_DEVICE  *HalDev, int*);
++   int           ModulePort;
++   int           Protocol;
++   int           LinkStatus;  // 0-> down, otherwise up
++}os_device_s;
++
++typedef struct  _os_receive_s
++{
++   HAL_RECEIVEINFO *HalReceiveInfo;
++   char   *ReceiveBuffer;
++   OS_DEVICE  *OsDev;
++}os_receive_s;
++
++typedef struct  _os_send_s
++{
++   OS_DEVICE  *OsDev;
++}os_send_s;
++
++typedef struct  _os_setup_s
++{
++   OS_DEVICE  *OsDev;
++}os_setup_s;
++
++
++
++void FlowForCphal(OS_DEVICE *OsDev)
++{
++  CHANNEL_INFO ChannelInfo;
++  int nChannels = 200;
++  int halFuncSize;
++  int rc;
++
++  //  Populate OsFunc structure
++  rc =  osInitModule(OsDev);
++
++  if(rc)
++  {
++    sprintf(bufTmp, "%s: return code from osInitModule:'0x%08X'", __FUNCTION__, rc);
++    errorout(bufTmp);
++  }
++
++
++  //  OS-Cphal handshake
++  rc = halCpmacInitModule(&OsDev->HalDev, OsDev, &OsDev->HalFunc, OsDev->OsFunc,
++                              sizeof(OS_FUNCTIONS), &halFuncSize, OsDev->ModulePort);
++
++  if(rc)
++  {
++    sprintf(bufTmp, "%s: return code from halCpmacInitModule:'0x%08X'", __FUNCTION__, rc);
++    errorout(bufTmp);
++  }
++
++  // See if hardware module exists
++  rc = OsDev->HalFunc->Probe(OsDev->HalDev);
++
++  if(rc)
++  {
++    sprintf(bufTmp, "%s: return code from Probe:'0x%08X'", __FUNCTION__, rc);
++    errorout(bufTmp);
++  }
++
++  // Initialize hardware module
++  rc = OsDev->HalFunc->Init(OsDev->HalDev);
++
++  if(rc)
++  {
++    sprintf(bufTmp, "%s: return code from Init:'0x%08X'", __FUNCTION__, rc);
++    errorout(bufTmp);
++  }
++
++  // Setup Channel Information (Tranmsit, channel 0)
++  ChannelInfo.Channel      = 0;
++  ChannelInfo.Direction    = DIRECTION_TX;
++  ChannelInfo.TxNumBuffers = nChannels;
++  ChannelInfo.TxNumQueues  = 1;
++  ChannelInfo.TxServiceMax = nChannels/3;
++
++  rc = OsDev->HalFunc->ChannelSetup(OsDev->HalDev, &ChannelInfo, OsDev->OsSetup);
++
++  // Setup Channel Information (Receive, channel 0)
++  ChannelInfo.Channel        = 0;
++  ChannelInfo.Direction      = DIRECTION_RX;
++  ChannelInfo.RxBufSize      = 1518;
++  ChannelInfo.RxBufferOffset = 0;
++  ChannelInfo.RxNumBuffers   = 2*nChannels;
++  ChannelInfo.RxServiceMax   = nChannels/3;
++
++  rc = OsDev->HalFunc->ChannelSetup(OsDev->HalDev, &ChannelInfo, OsDev->OsSetup);
++
++  // Open the hardware module
++  rc = OsDev->HalFunc->Open(OsDev->HalDev);
++
++  // Module now ready to Send/Receive data
++}
++
++
++int osInitModule(OS_FUNCTIONS **pOsFunc)
++  {
++   OS_FUNCTIONS *OsFunc;
++
++   OsFunc = (OS_FUNCTIONS *) malloc(sizeof(OS_FUNCTIONS));
++   if (!OsFunc)
++     return (-1);
++
++   *pOsFunc = OsFunc;
++
++   OsFunc->CriticalOff               = osCriticalOff;
++   OsFunc->CriticalOn                = osCriticalOn;
++   OsFunc->DataCacheHitInvalidate    = osDataCacheHitInvalidate;
++   OsFunc->DataCacheHitWriteback     = osDataCacheHitWriteback;
++   OsFunc->DeviceFindInfo            = osDeviceFindInfo;
++   OsFunc->DeviceFindParmUint        = osDeviceFindParmUint;
++   OsFunc->DeviceFindParmValue       = osDeviceFindParmValue;
++   OsFunc->Free                      = osFree;
++   OsFunc->FreeDev                   = osFreeDev;
++   OsFunc->FreeDmaXfer               = osFreeDmaXfer;
++   OsFunc->FreeRxBuffer              = osFreeRxBuffer;
++   OsFunc->IsrRegister               = osIsrRegister;
++   OsFunc->IsrUnRegister             = osIsrUnRegister;
++   OsFunc->Malloc                    = osMalloc;
++   OsFunc->MallocDev                 = osMallocDev;
++   OsFunc->MallocDmaXfer             = osMallocDmaXfer;
++   OsFunc->MallocRxBuffer            = osMallocRxBuffer;
++
++
++   OsFunc->Memset                    = memset;
++   OsFunc->Printf                    = printf;
++   OsFunc->Sprintf                   = sprintf;
++   OsFunc->Strcmpi                   = osStrcmpi;
++   OsFunc->Strlen                    = strlen;
++   OsFunc->Strstr                    = strstr;
++   OsFunc->Strtoul                   = strtoul;
++
++   OsFunc->Control                   = osControl;
++   OsFunc->Receive                   = osReceive;
++   OsFunc->SendComplete              = osSendComplete;
++   OsFunc->TeardownComplete          = osTearDownComplete;
++
++   return(0);
++  }
++
++
++int osReceive(OS_DEVICE *OsDev,FRAGLIST *Fraglist,bit32u FragCount,bit32u PacketSize,HAL_RECEIVEINFO *halInfo, bit32u mode)
++  {
++  OS_RECEIVEINFO *skb = (OS_RECEIVEINFO *)Fraglist[0].OsInfo;
++  dcache_i((char *)Fraglist->data, Fraglist->len);
++  OsDev->HalFunc->RxReturn(halInfo,0);
++  return(0);
++  }
++
++int osSendComplete(OS_SENDINFO *skb)
++  {
++  return(0);
++  }
++
++
++static void *osMallocRxBuffer(bit32u Size,void *MemBase, bit32u MemRange,
++                              OS_SETUP *OsSetup, HAL_RECEIVEINFO *HalReceiveInfo,
++                              OS_RECEIVEINFO **OsReceiveInfo, OS_DEVICE *OsDev )
++  {
++   void *HalBuffer;
++   OS_RECEIVEINFO *OsPriv;
++
++   HalBuffer=malloc(Size);
++   if (!HalBuffer)
++     {
++      return(0);
++     }
++
++   // Malloc the OS block
++   *OsReceiveInfo = malloc(sizeof(OS_RECEIVEINFO));
++   if (!*OsReceiveInfo)
++     {
++      free(HalBuffer);
++      return(0);
++     }
++
++   // Initialize the new buffer descriptor
++   OsPriv                 = *OsReceiveInfo;
++   OsPriv->OsDev          =  OsDev;
++   OsPriv->ReceiveBuffer  =  HalBuffer;
++   OsPriv->HalReceiveInfo =  HalReceiveInfo;
++
++   return(HalBuffer);
++  }
++
++
++void SendBuffer(OS_DEVICE *OsDev, char *Buffer, int Size)
++{
++  FRAGLIST Fraglist;
++  bit32u FragCount;
++
++  tcb_pending++;
++  Fraglist.len  = Size;
++  Fraglist.data = (unsigned *) Buffer;
++  FragCount     = 1;
++  mode          = 0;   //  Channel 0
++
++  dcache_wb(Fraglist.data, Fraglist.len);
++  OsDev->HalFunc->Send(OsDev->HalDev, &Fraglist, FragCount, Size, (OS_SENDINFO *) Buffer, mode);
++}
++
++
++void osStateChange(OS_DEVICE *OsDev)
++  {
++  int status;
++  int LinkStatus;
++  OsDev->HalFunc->Control(OsDev->HalDev, "Status", hcGet, &status);
++  if(status & CPMAC_STATUS_ADAPTER_CHECK)
++    {
++    //  Adapter Check, take appropiate action
++    }
++  else
++    {
++    LinkStatus = status & CPMAC_STATUS_LINK;
++    if(LinkStatus != OsDev->LinkStatus)
++      {
++      dbgPrintf("\n%s:Link %s for inst %d Speed %s, Duplex %s\n",
++                 __FUNCTION__,
++                 LinkStatus ? "up" : "down",
++                 OsDev->ModulePort,
++                 status & CPMAC_STATUS_LINK_SPEED ? "100" : "10",
++                 status & CPMAC_STATUS_LINK_DUPLEX ? "FD" : "HD");
++      OsDev->LinkStatus = LinkStatus;
++      }
++    }
++  }
++
++
++int osControl(OS_DEVICE *OsDev, const char *pszKey, const char* pszAction, void *ParmValue)
++  {
++  int rc=-1;
++
++  if (osStrcmpi(pszKey, hcCpuFrequency) == 0)
++   {
++   if(osStrcmpi(pszAction, hcGet) == 0)
++     {
++     *(bit32u*) ParmValue = cpufreq;
++     rc = 0;
++     }
++   }
++  if (osStrcmpi(pszKey, hcMdioBusFrequency) == 0)
++   {
++   if(osStrcmpi(pszAction, hcGet) == 0)
++     {
++     *(bit32u *)ParmValue = MdioBusFrequency;
++     rc = 0;
++     }
++   }
++if (osStrcmpi(pszKey, hcMdioClockFrequency) == 0)
++   {
++   if(osStrcmpi(pszAction, hcGet) == 0)
++     {
++     *(bit32u *)ParmValue = MdioClockFrequency;
++     rc = 0;
++     }
++   }
++
++  if (osStrcmpi(pszKey, hcTick) == 0)
++   {
++   if(osStrcmpi(pszAction, hcSet) == 0)
++     {
++       osTickSetInterval(OsDev, *(unsigned int *) ParmValue);
++       rc = 0;
++     }
++   else
++   if(osStrcmpi(pszAction, hcClear) == 0)
++     {
++       osTickDisable(OsDev);
++       rc = 0;
++     }
++   }
++
++  if (osStrcmpi(pszKey, "SioFlush") == 0)
++    {
++       MySioFlush();
++       rc = 0;
++    }
++
++  if (osStrcmpi(pszKey, "StateChange") == 0)
++    {
++       osStateChange(OsDev);
++       rc = 0;
++    }
++
++  if (osStrcmpi(pszKey, "Sleep") == 0)
++    {
++       osSleep(*(int *)ParmValue);
++       rc = 0;
++    }
++  return(rc);
++  }
++
++@endcode
++
++
++@par Push Model Example (Currently Eswitch ONLY)
++
++@code
++
++typedef struct _os_device_s  OS_DEVICE;
++typedef struct _os_receive_s OS_RECEIVEINFO;
++typedef struct _os_send_s    OS_SENDINFO;
++typedef struct _os_setup_s   OS_SETUP;
++
++#include "cpswhal.h"          //Get glogal HAL stuff
++#include "cpswhaleswitch.h"   //Get device specific hal stuff
++
++
++typedef struct  _os_device_s
++{
++   HAL_DEVICE    *HalDev;
++   HAL_FUNCTIONS *HalFunc;
++   OS_FUNCTIONS  *OsFunc;
++   OS_SETUP      *OsSetup;
++   bit32u        Interrupt;
++   int           (*halIsr)(HAL_DEVICE  *HalDev, int*);
++   int           ModulePort;
++   int           Protocol;
++   int           LinkStatus;  // 0-> down, otherwise up
++}os_device_s;
++
++typedef struct  _os_receive_s
++{
++   HAL_RECEIVEINFO *HalReceiveInfo;
++   char   *ReceiveBuffer;
++   OS_DEVICE  *OsDev;
++}os_receive_s;
++
++typedef struct  _os_send_s
++{
++   OS_DEVICE  *OsDev;
++}os_send_s;
++
++typedef struct  _os_setup_s
++{
++   OS_DEVICE  *OsDev;
++}os_setup_s;
++
++
++
++void FlowForCphal(OS_DEVICE *OsDev)
++{
++CHANNEL_INFO ChannelInfo;
++  int nChannels = 200;
++  int halFuncSize;
++  int rc;
++
++  //  Populate OsFunc structure
++  rc =  osInitModule(OsDev);
++
++  if(rc)
++  {
++    sprintf(bufTmp, "%s: return code from osInitModule:'0x%08X'", __FUNCTION__, rc);
++    errorout(bufTmp);
++  }
++
++
++  //  OS-Cphal handshake
++  rc = cpswHalEswitchInitModule(&OsDev->HalDev, OsDev, &OsDev->HalFunc, OsDev->OsFunc,
++                              sizeof(OS_FUNCTIONS), &halFuncSize, OsDev->ModulePort);
++
++  if(rc)
++  {
++    sprintf(bufTmp, "%s: return code from cpswHalEswitchInitModule:'0x%08X'", __FUNCTION__, rc);
++    errorout(bufTmp);
++  }
++
++
++  ChannelInfo.Channel      = 7;
++  ChannelInfo.Direction    = DIRECTION_RX;
++  ChanInfo.Receive = osReceiveSS;         //  Specify function to receive data for this channel
++
++  rc = OsDev->HalFunc->ChannelSetup(OsDev->HalDev, &ChannelInfo, OsDev->OsSetup);
++
++  MyConfig.debug=0;
++  MyConfig.CpuFrequency = CpuFreq;
++  MyConfig.EswitchFrequency = EswitchFreq;
++  MyConfig.ResetBase  = 0xa8611600;
++  MyConfig.MacAddress = MacAddr;
++
++  MyConfig.EswitchResetBit= 27;
++  MyConfig.Cpmac0ResetBit = 17;
++  MyConfig.Cpmac1ResetBit = 21;
++  MyConfig.MdioResetBit   = 22;
++  MyConfig.Phy0ResetBit   = 26;
++  MyConfig.Phy1ResetBit   = 28;
++  MyConfig.HdmaResetBit   = 13;
++  MyConfig.Cpmac0IntBit   = 19;
++  MyConfig.Cpmac1IntBit   = 33;
++  MyConfig.EswitchIntBit  = 27;
++  MyConfig.EswitchBase    = 0xa8640000;
++  MyConfig.EswitchBufferSize     = 64;
++  MyConfig.EswitchHostBufCount   = 0;
++  MyConfig.EswitchDefaultCamSize = 64;
++  MyConfig.EswitchOverFlowCount  = 200;
++  MyConfig.EswitchOverFlowSize   = 256;
++
++
++
++
++  rc=EswitchConfig(HalDev,HalFunc,&MyConfig);
++
++
++  // Open the hardware module
++  rc = OsDev->HalFunc->Open(OsDev->HalDev);
++
++  // Module now ready to Send/Receive data
++}
++
++
++int EswitchConfig(HAL_DEVICE *HalDev, HAL_FUNCTIONS *HalFunc, ESWITCH_CONFIG *Config)
++{
++  bit32u sts;
++  sts = 0;
++
++  sts |= cpswhalPushBin(hcdebug, Config->debug);
++  sts |= cpswhalPushBin(hcCpuFrequency     , Config->CpuFrequency );
++  sts |= cpswhalPushBin(hcEswitchFrequency , Config->EswitchFrequency );
++  sts |= cpswhalPushBin(hcResetBase        , Config->ResetBase  );
++  sts |= cpswhalPushBin(hcMacAddress       , Config->MacAddress );
++  sts |= cpswhalPushBin(hcEswitchResetBit, Config->EswitchResetBit);
++  sts |= cpswhalPushBin(hcCpmac0ResetBit , Config->Cpmac0ResetBit );
++  sts |= cpswhalPushBin(hcCpmac1ResetBit , Config->Cpmac1ResetBit );
++  sts |= cpswhalPushBin(hcMdioResetBit   , Config->MdioResetBit   );
++  sts |= cpswhalPushBin(hcPhy0ResetBit   , Config->Phy0ResetBit   );
++  sts |= cpswhalPushBin(hcPhy1ResetBit   , Config->Phy1ResetBit   );
++  sts |= cpswhalPushBin(hcHdmaResetBit   , Config->HdmaResetBit   );
++  sts |= cpswhalPushBin(hcCpmac0IntBit   , Config->Cpmac0IntBit   );
++  sts |= cpswhalPushBin(hcCpmac1IntBit   , Config->Cpmac1IntBit   );
++  sts |= cpswhalPushBin(hcEswitchIntBit  , Config->EswitchIntBit  );
++  sts |= cpswhalPushBin(hcEswitchBase           , Config->EswitchBase    );
++  sts |= cpswhalPushBin(hcEswitchBufferSize     , Config->EswitchBufferSize     );
++  sts |= cpswhalPushBin(hcEswitchHostBufCount   , Config->EswitchHostBufCount   );
++  sts |= cpswhalPushBin(hcEswitchDefaultCamSize , Config->EswitchDefaultCamSize );
++  sts |= cpswhalPushBin(hcEswitchOverFlowCount  , Config->EswitchOverFlowCount  );
++  sts |= cpswhalPushBin(hcEswitchOverFlowSize   , Config->EswitchOverFlowSize   );
++  return(sts);
++}
++
++
++
++@endcode
++*/
++
++#endif
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/ec_errors_cpmac.h linux-2.4.30/drivers/net/avalanche_cpmac/ec_errors_cpmac.h
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/ec_errors_cpmac.h    1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/ec_errors_cpmac.h 2005-04-15 05:10:41.000000000 +0200
+@@ -0,0 +1,118 @@
++/***************************************************************************
++ Copyright(c) 2001, Texas Instruments Incorporated. All Rights Reserved.
++
++ FILE:  ec_errors.h
++
++ DESCRIPTION:
++   This file contains definitions and function declarations for
++   error code support.
++
++ HISTORY:
++   14Dec00 MJH             Added masking to EC_CLASS etc macros
++   17Sep02 GSG             Added HAL support (new class&devices)
++   03Oct02 GSG             Removed C++ style comments
++***************************************************************************/
++#ifndef _INC_EC_ERRORS
++#define _INC_EC_ERRORS
++
++/*
++  31    - CRITICAL
++  30-28 - CLASS         (ie. DIAG, KERNEL, FLASH, etc)
++  27-24 - INSTANCE      (ie. 1, 2, 3, etc )
++  23-16 - DEVICE        (ie. EMAC, IIC, etc)
++  15-08 - FUNCTION      (ie. RX, TX, INIT, etc)
++  07-00 - ERROR CODE    (ie. NO_BASE, FILE_NOT_FOUND, etc )
++*/
++
++/*---------------------------------------------------------------------------
++  Useful defines for accessing fields within error code
++---------------------------------------------------------------------------*/
++#define CRITICAL_SHIFT    31
++#define CLASS_SHIFT       28
++#define INST_SHIFT        24
++#define DEVICE_SHIFT      16
++#define FUNCTION_SHIFT     8
++#define ERROR_CODE_SHIFT   0
++
++#define CRITICAL_MASK     1
++#define CLASS_MASK        0x07
++#define DEVICE_MASK       0xFF
++#define INST_MASK         0x0F
++#define FUNCTION_MASK     0xFF
++#define ERROR_CODE_MASK   0xFF
++
++#define EC_CLASS(val)     ((val&CLASS_MASK)      << CLASS_SHIFT)
++#define EC_DEVICE(val)    ((val&DEVICE_MASK)     << DEVICE_SHIFT)
++#define EC_INST(val)      ((val&INST_MASK)       << INST_SHIFT)
++#define EC_FUNC(val)      ((val&FUNCTION_MASK)   << FUNCTION_SHIFT)
++#define EC_ERR(val)       ((val&ERROR_CODE_MASK) << ERROR_CODE_SHIFT)
++
++/*---------------------------------------------------------------------------
++   Operation classes
++---------------------------------------------------------------------------*/
++#define EC_HAL              EC_CLASS(0)
++#define EC_DIAG             EC_CLASS(8)
++
++/*---------------------------------------------------------------------------
++   Device types
++---------------------------------------------------------------------------*/
++#define EC_DEV_EMAC         EC_DEVICE(1)
++#define EC_DEV_IIC          EC_DEVICE(2)
++#define EC_DEV_RESET        EC_DEVICE(3)
++#define EC_DEV_ATMSAR       EC_DEVICE(4)
++#define EC_DEV_MEM          EC_DEVICE(5)
++#define EC_DEV_DES          EC_DEVICE(6)
++#define EC_DEV_DMA          EC_DEVICE(7)
++#define EC_DEV_DSP          EC_DEVICE(8)
++#define EC_DEV_TMR          EC_DEVICE(9)
++#define EC_DEV_WDT          EC_DEVICE(10)
++#define EC_DEV_DCL          EC_DEVICE(11)
++#define EC_DEV_BBIF         EC_DEVICE(12)
++#define EC_DEV_PCI              EC_DEVICE(13)
++#define EC_DEV_XBUS         EC_DEVICE(14)
++#define EC_DEV_DSLIF            EC_DEVICE(15)
++#define EC_DEV_USB                      EC_DEVICE(16)
++#define EC_DEV_CLKC                     EC_DEVICE(17)
++#define EC_DEV_RAPTOR       EC_DEVICE(18)
++#define EC_DEV_DSPC                     EC_DEVICE(19)
++#define EC_DEV_INTC                     EC_DEVICE(20)
++#define EC_DEV_GPIO                     EC_DEVICE(21)
++#define EC_DEV_BIST                     EC_DEVICE(22)
++#define EC_DEV_HDLC                     EC_DEVICE(23)
++#define EC_DEV_UART                     EC_DEVICE(24)
++#define EC_DEV_VOIC                     EC_DEVICE(25)
++/* 9.17.02 (new HAL modules) */
++#define EC_DEV_CPSAR        EC_DEVICE(0x1A)
++#define EC_DEV_AAL5         EC_DEVICE(0x1B)
++#define EC_DEV_AAL2         EC_DEVICE(0x1C)
++#define EC_DEV_CPMAC        EC_DEVICE(0x1D)
++#define EC_DEV_VDMA         EC_DEVICE(0x1E)
++#define EC_DEV_VLYNQ        EC_DEVICE(0x1F)
++#define EC_DEV_CPPI         EC_DEVICE(0x20)
++#define EC_DEV_CPMDIO       EC_DEVICE(0x21)
++
++/*---------------------------------------------------------------------------
++   Function types
++---------------------------------------------------------------------------*/
++#define EC_FUNC_READ_CONF   EC_FUNC(1)
++#define EC_FUNC_INIT        EC_FUNC(2)
++
++/*---------------------------------------------------------------------------
++   Error codes
++---------------------------------------------------------------------------*/
++#define EC_CRITICAL         (1<<CRITICAL_SHIFT)
++#define EC_NO_ERRORS        0
++#define EC_VAL_NO_BASE      EC_ERR(1)
++#define EC_VAL_NO_RESET_BIT EC_ERR(2)
++#define EC_VAL_NO_RESET     EC_ERR(3)
++#define EC_VAL_BAD_BASE     EC_ERR(4)
++#define EC_VAL_MALLOCFAILED EC_ERR(5)
++#define EC_VAL_NO_RESETBASE EC_ERR(6)
++#define EC_DEVICE_NOT_FOUND EC_ERR(7)
++
++/*---------------------------------------------------------------------------
++   Function declarations
++---------------------------------------------------------------------------*/
++extern void ec_log_error( unsigned int );
++
++#endif /* _INC_EC_ERRORS */
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/hcpmac.c linux-2.4.30/drivers/net/avalanche_cpmac/hcpmac.c
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/hcpmac.c     1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/hcpmac.c  2005-07-08 22:08:07.755958806 +0200
+@@ -0,0 +1,1878 @@
++/******************************************************************************
++ *  TNETDxxxx Software Support
++ *  Copyright (c) 2002-2004 Texas Instruments Incorporated. All Rights Reserved.
++ *
++ *  FILE:
++ *
++ *  DESCRIPTION:
++ *      This file contains the code for the HAL EMAC Bridge Test
++ *
++ *  HISTORY:
++ *  xxXxx01 Denis            RC1.00  Original Version created.
++ *  22Jan02 Denis/Mick       RC1.01  Modified for HAL EMAC API
++ *  24Jan02 Denis/Mick       RC1.02  Speed Improvements
++ *  28Jan02 Denis/Mick       RC1.16  Made function calls pointers
++ *  28Jan02 Mick             RC1.18  Split into separate modules
++ *  29Jan02 Mick             RC1.19  Hal include file cleaned up
++ *  15Jul02 Michael Hanrahan RC1.20  Synch'd with Linux Version
++ *  23Sep02 Michael Hanrahan RC1.21  Added CPPI.C
++ *  16Oct02 Michael Hanrahan RC1.22  Added CAF etc to Options.Conf
++ *  09Jan03 Michael Hanrahan RC3.01  Fixed incorrect MDIO check
++ *  01Feb03 Michael Hanrahan RC3.02  Updated for GPIO/PBUSFREQ
++ *  29Mar03 Michael Hanrahan 1.03 Corrected  ChannelConfigGet
++ *  29Mar03 Michael Hanrahan 1.03 Removed user setting of TxNumQueues
++ *  23Aug04 Michael Hanrahan 1.7.8 Support for Setting Mac Address
++ *  @author Michael Hanrahan
++ *  @version 1.02
++ *  @date    24-Jan-2002
++ *****************************************************************************/
++#define _HAL_CPMAC
++#define _CPHAL_CPMAC
++#define _CPHAL
++#define __CPHAL_CPMDIO
++
++#include "dox_cpmac.h"  /*  Documentation information */
++
++/*  OS Data Structure definitions  */
++
++typedef void OS_PRIVATE;
++typedef void OS_DEVICE;
++typedef void OS_SENDINFO;
++typedef void OS_RECEIVEINFO;
++typedef void OS_SETUP;
++
++/*  HAL Data Structure definitions  */
++
++typedef struct _phy_device PHY_DEVICE;
++typedef struct hal_device  HAL_DEVICE;
++typedef struct hal_private HAL_PRIVATE;
++typedef struct hal_private HAL_RECEIVEINFO;
++
++#include "cpcommon_cpmac.h"
++#include "cpswhal_cpmac.h"
++#include "cpmdio.h"
++#include "hcpmac.h"
++#include "cpmac_reg.h"
++
++
++#define EC_MODULE
++
++/* MDIO Clock Frequency Default Value */
++
++/* Rcb/Tcb Constants */
++
++#define CB_SOF_BIT         (1<<31)
++#define CB_EOF_BIT         (1<<30)
++#define CB_SOF_AND_EOF_BIT (CB_SOF_BIT|CB_EOF_BIT)
++#define CB_OWNERSHIP_BIT   (1<<29)
++#define CB_EOQ_BIT         (1<<28)
++#define CB_SIZE_MASK       0x0000ffff
++#define RCB_ERRORS_MASK    0x03fe0000
++
++static char *channel_names[]   = CHANNEL_NAMES; /* GSG 11/22 (may change this implementation) */
++
++#define scFound(Module) if (HalDev->State != enDevFound)    return (Module|EC_FUNC_CHSETUP|EC_VAL_INVALID_STATE)
++#define scInit(Module)  if (HalDev->State <  enInitialized) return (Module|EC_FUNC_CHSETUP|EC_VAL_INVALID_STATE)
++#define scOpen(Module)  if (HalDev->State <  enOpened)      return (Module|EC_FUNC_CHSETUP|EC_VAL_INVALID_STATE)
++
++
++
++/********************************************************************
++**
++**  L O C A L  F U N C T I O N S
++**
++********************************************************************/
++static int halIsr(HAL_DEVICE *HalDev, int *MorePackets);
++static int cpmacRandom(HAL_DEVICE *HalDev);
++static int cpmacRandomRange(HAL_DEVICE *HalDev, int min, int max);
++static int halPacketProcessEnd(HAL_DEVICE *HalDev);
++
++#include "cpcommon_cpmac.c"                                                /*~RC3.02*/
++#include "cppi_cpmac.c"
++#include "cpmdio.c"                                                  /*~RC3.02*/
++
++static int MacAddressSave(HAL_DEVICE *HalDev, unsigned char *MacAddr)
++  {
++  int i;
++  int inst             = HalDev->inst;
++
++  HalDev->MacAddr = MacAddr;
++
++  if(HalDev->debug)
++    {
++    dbgPrintf("MacAddrSave[%d]: ", inst);
++    for (i=0;i<6;i++)
++       dbgPrintf("%X", HalDev->MacAddr[i]);
++    dbgPrintf("\n");
++    osfuncSioFlush();
++    }
++  return(EC_NO_ERRORS);
++  }
++static int MacAddressSet(HAL_DEVICE *HalDev)
++  {
++  unsigned char *macadr = &HalDev->MacAddr[0];
++  int base             = HalDev->dev_base;
++
++  scOpen(EC_CPMAC);
++  CPMAC_MACADDRLO_0(base) = macadr[5];
++  CPMAC_MACADDRMID(base)  = macadr[4];
++  CPMAC_MACADDRHI(base)   = (macadr[0])|(macadr[1]<<8)|(macadr[2]<<16)|(macadr[3]<<24);
++  if(HalDev->debug)
++    {
++     dbgPrintf("MacAddrSet: MacAddr(%d) %X %X %X\n", HalDev->inst, CPMAC_MACADDRLO_0(base),
++                                                     CPMAC_MACADDRMID(base),
++                                                     CPMAC_MACADDRHI(base));
++
++     dbgPrintf("Start MAC: %d\n",HalDev->dev_base);
++     osfuncSioFlush();
++    }
++  return(EC_NO_ERRORS);
++  }
++
++
++/*
++  Updates the MacHash registers
++*/
++static void MacHashSet(HAL_DEVICE *HalDev)
++  {
++  if(HalDev->State <  enOpened)
++    return;
++
++  CPMAC_MACHASH1(HalDev->dev_base) = HalDev->MacHash1;
++  CPMAC_MACHASH2(HalDev->dev_base) = HalDev->MacHash2;
++  if (DBG(11))
++    dbgPrintf("CPMAC[%X]: MacHash1 0x%08X, MacHash2 0x%08X\n", HalDev->dev_base, CPMAC_MACHASH1(HalDev->dev_base), CPMAC_MACHASH2(HalDev->dev_base));
++  }
++
++/*
++  Reads the MacControl register and updates
++  the changable bits. (See MACCONTROL_MASK)
++*/
++static void RxMBP_EnableSet(HAL_DEVICE *HalDev)
++  {
++   bit32u RxMbpEnable;
++   if(HalDev->State <  enOpened)
++     return;
++   RxMbpEnable  = CPMAC_RX_MBP_ENABLE(HalDev->dev_base);
++   RxMbpEnable &= ~RX_MBP_ENABLE_MASK; /* Clear out updatable bits */
++   RxMbpEnable |= HalDev->RxMbpEnable;
++   CPMAC_RX_MBP_ENABLE(HalDev->dev_base) = RxMbpEnable;
++  }
++/*
++  Reads the MacControl register and updates
++  the changable bits. (See MACCONTROL_MASK)
++*/
++static void MacControlSet(HAL_DEVICE *HalDev)
++  {
++   bit32u MacControl;
++   if(HalDev->State <  enOpened)
++     return;
++   MacControl  = CPMAC_MACCONTROL(HalDev->dev_base);
++   MacControl &= ~MACCONTROL_MASK; /* Clear out updatable bits */
++   MacControl |= HalDev->MacControl;
++   if(!(MacControl & MII_EN)) /* If Enable is not set just update register  */
++      CPMAC_MACCONTROL(HalDev->dev_base) = MacControl;
++   else
++     {
++     if(MacControl & CTRL_LOOPBACK)    /*  Loopback Set  */
++       {
++       /* mii_en is set and loopback is needed,
++          clear mii_en, set loopback, then set mii_en
++       */
++       MacControl &= ~MII_EN;  /* Clear MII_EN  */
++       CPMAC_MACCONTROL(HalDev->dev_base) = MacControl;
++       CPMAC_MACCONTROL(HalDev->dev_base) |= MII_EN; /* Set MII_EN  */
++       HalDev->Linked = 1; /* if in loopback the logically linked */
++       }
++     else  /* If Loopback not set just update */
++       {
++       CPMAC_MACCONTROL(HalDev->dev_base) = MacControl;
++       }
++     }
++    if(DBG(0))
++      dbgPrintf("[halMacControlSet]MacControl:%08X\n", CPMAC_MACCONTROL(HalDev->dev_base));
++  }
++static int UnicastSet(HAL_DEVICE *HalDev)
++  {
++  CPMAC_RX_UNICAST_SET(HalDev->dev_base)    = HalDev->RxUnicastSet;
++  CPMAC_RX_UNICAST_CLEAR(HalDev->dev_base)  = HalDev->RxUnicastClear;
++  return(EC_NO_ERRORS);
++  }
++
++  
++static bit32u HashGet(bit8u *Address)
++  {
++  bit32u hash;
++    bit8u  tmpval;
++    int    i;
++
++    hash = 0;
++    for( i=0; i<2; i++ )
++    {
++        tmpval = *Address++;
++        hash  ^= (tmpval>>2)^(tmpval<<4);
++        tmpval = *Address++;
++        hash  ^= (tmpval>>4)^(tmpval<<2);
++        tmpval = *Address++;
++        hash  ^= (tmpval>>6)^(tmpval);
++    }
++
++    return( hash & 0x3F );
++  }
++
++static void HashAdd(HAL_DEVICE *HalDev, bit8u *MacAddress)
++{
++  bit32u HashValue;
++  bit32u HashBit;
++
++  HashValue = HashGet(MacAddress);
++
++  if(HashValue < 32)
++    {
++    HashBit = (1 << HashValue);
++    HalDev->MacHash1 |= HashBit;
++    }
++    else
++    {
++    HashBit = (1 << (HashValue-32));
++    HalDev->MacHash2 |= HashBit;
++    }
++}
++
++static void HashDel(HAL_DEVICE *HalDev, bit8u *MacAddress)
++{
++  bit32u HashValue;
++  bit32u HashBit;
++
++  HashValue = HashGet(MacAddress);
++
++  if(HashValue < 32)
++    {
++    HashBit = (1 << HashValue);
++    HalDev->MacHash1 &= ~HashBit;
++    }
++    else
++    {
++    HashBit = (1 << (HashValue-32));
++    HalDev->MacHash2 &= ~HashBit;
++    }
++}
++
++/*  Replace with an array based on key, with a ptr to the code to do */
++/* e.g.  [enRX_PASS_CRC] = {Set, MBP_UPDATE() } */
++static void DuplexUpdate(HAL_DEVICE *HalDev)
++{
++  int base           = HalDev->dev_base;
++  PHY_DEVICE *PhyDev = HalDev->PhyDev;
++
++  if(HalDev->State <  enOpened)
++    return;
++
++   /* No Phy Condition */
++   if(HalDev->MdioConnect & _CPMDIO_NOPHY)                        /*MJH+030805*/
++   {
++       /*  No Phy condition, always linked */
++       HalDev->Linked     = 1;
++       HalDev->EmacSpeed  = 1;
++       HalDev->EmacDuplex = 1;
++       HalDev->PhyNum     = 0xFFFFFFFF;  /* No Phy Num */
++       CPMAC_MACCONTROL(base) |= FULLDUPLEX;                      /*MJH+030909*/
++       osfuncStateChange();
++       return;
++   }
++
++  if(HalDev->MacControl & CTRL_LOOPBACK)    /*  Loopback Set  */
++    {
++    HalDev->Linked = 1;
++    return;
++    }
++
++  if (HalDev->MdioConnect & _CPMDIO_LOOPBK)
++    {
++    HalDev->Linked = cpMacMdioGetLoopback(HalDev->PhyDev);
++    }
++  else
++    {
++    HalDev->Linked = cpMacMdioGetLinked(HalDev->PhyDev);
++    }
++  if (HalDev->Linked)
++    {
++     /*  Retreive Duplex and Speed and the Phy Number  */
++     if(HalDev->MdioConnect & _CPMDIO_LOOPBK)
++       HalDev->EmacDuplex = 1;
++     else
++       HalDev->EmacDuplex = cpMacMdioGetDuplex(PhyDev);
++     HalDev->EmacSpeed  = cpMacMdioGetSpeed(PhyDev);
++     HalDev->PhyNum     = cpMacMdioGetPhyNum(PhyDev);
++
++     if(HalDev->EmacDuplex)
++       CPMAC_MACCONTROL(base) |= FULLDUPLEX;
++     else
++       CPMAC_MACCONTROL(base) &= ~FULLDUPLEX;
++     if(HalDev->debug)
++        dbgPrintf("%d: Phy= %d, Speed=%s, Duplex=%s\n",HalDev->inst,HalDev->PhyNum,(HalDev->EmacSpeed)?"100":"10",(HalDev->EmacDuplex)?"Full":"Half");
++    }
++  if(HalDev->debug)
++     dbgPrintf("DuplexUpdate[%d]: MACCONTROL 0x%08X, %s\n", HalDev->inst, CPMAC_MACCONTROL(base),(HalDev->Linked)?"Linked":"Not Linked");
++}
++static void MdioSetPhyMode(HAL_DEVICE *HalDev)
++  {
++  unsigned int PhyMode;
++  /* Verify proper device state */
++  if (HalDev->State < enOpened)
++    return;
++
++  PhyMode = NWAY_AUTO|NWAY_FD100|NWAY_HD100|NWAY_FD10|NWAY_HD10;
++  if(DBG(0))
++    {
++    dbgPrintf("halSetPhyMode1: MdioConnect:%08X ,", HalDev->MdioConnect);
++    dbgPrintf("PhyMode:%08X Auto:%d, FD10:%d, HD10:%d, FD100:%d, HD100:%d\n", PhyMode,
++           PhyMode&NWAY_AUTO, PhyMode&NWAY_FD10, PhyMode&NWAY_HD10, PhyMode&NWAY_FD100,
++           PhyMode&NWAY_HD100);
++    }
++
++
++  if (  HalDev->MdioConnect & _CPMDIO_NEG_OFF)  /* ~RC3.01                */
++    PhyMode &= ~(NWAY_AUTO);                    /* Disable Auto Neg       */
++  if (!(HalDev->MdioConnect & _CPMDIO_HD))
++    PhyMode &= ~(NWAY_HD100|NWAY_HD10);         /* Cannot support HD      */
++  if (!(HalDev->MdioConnect & _CPMDIO_FD))
++    PhyMode &= ~(NWAY_FD100|NWAY_FD10);         /* Cannot support FD      */
++  if (!(HalDev->MdioConnect & _CPMDIO_10))
++    PhyMode &= ~(NWAY_HD10|NWAY_FD10);          /* Cannot support 10 Mbs  */
++  if (!(HalDev->MdioConnect & _CPMDIO_100))
++    PhyMode &= ~(NWAY_HD100|NWAY_FD100);        /* Cannot support 100 Mbs */
++
++  if(HalDev->MdioConnect & _CPMDIO_AUTOMDIX)   PhyMode |= NWAY_AUTOMDIX; /* Set AutoMdix */
++
++  if (HalDev->CpmacFrequency <= 50000000)
++    PhyMode &= ~(NWAY_FD100|NWAY_HD100); /* Cannot support 100 MBS */
++  if(DBG(7))
++    dbgPrintf("halNeg: PhyMode[0x%08X] %d\n", HalDev->dev_base, PhyMode);
++
++  if(DBG(0))
++    {
++    dbgPrintf("halSetPhyMode2: MdioConnect:%08X ,", HalDev->MdioConnect);
++    dbgPrintf("PhyMode:%08X Auto:%d, FD10:%d, HD10:%d, FD100:%d, HD100:%d\n", PhyMode,
++               PhyMode&NWAY_AUTO, PhyMode&NWAY_FD10, PhyMode&NWAY_HD10, PhyMode&NWAY_FD100,
++               PhyMode&NWAY_HD100);
++    }
++
++
++  cpMacMdioSetPhyMode(HalDev->PhyDev,PhyMode);
++  DuplexUpdate(HalDev);
++  }
++static int StatsClear(HAL_DEVICE *HalDev)
++{
++  int i;
++  MEM_PTR pStats;
++
++  scOpen(EC_CPMAC);
++
++  pStats = pCPMAC_RXGOODFRAMES(HalDev->dev_base);
++  for (i=0;i<STATS_MAX;i++)
++    {
++    *(MEM_PTR)(pStats) =  0xFFFFFFFF;
++    pStats++;
++    }
++
++  return(EC_NO_ERRORS);
++}
++static void StatsDump(HAL_DEVICE *HalDev, void *Value)
++ {
++ MEM_PTR ptrStats;
++ MEM_PTR ptrValue;
++ int i;
++ ptrStats = pCPMAC_RXGOODFRAMES(HalDev->dev_base);
++ ptrValue = (bit32u*) Value;
++ for (i=0; i<STATS_MAX; i++)
++  {
++     *ptrValue = *ptrStats;
++     if(DBG(4))
++      {
++      dbgPrintf("halStatsDump: Stat[%d:0x%08X] %d 0x%08X %d\n", i, ptrStats, *ptrStats, ptrValue, *ptrValue);
++      osfuncSioFlush();
++      }
++     ptrStats++;
++     ptrValue++;
++  }
++ }
++static void ConfigApply(HAL_DEVICE *HalDev)
++  {
++  CPMAC_RX_MAXLEN(HalDev->dev_base)          = HalDev->RxMaxLen;
++  CPMAC_RX_FILTERLOWTHRESH(HalDev->dev_base) = HalDev->RxFilterLowThresh;
++  CPMAC_RX0_FLOWTHRESH(HalDev->dev_base)     = HalDev->Rx0FlowThresh;
++  UnicastSet(HalDev);
++  MacAddressSet(HalDev);
++  RxMBP_EnableSet(HalDev);
++  MacHashSet(HalDev);
++  MacControlSet(HalDev);
++  if(DBG(0))
++     dbgPrintf("ValuesUpdate[%d]: MBP_ENABLE 0x%08X\n", HalDev->inst, CPMAC_RX_MBP_ENABLE(HalDev->dev_base));
++  }
++static int halStatus(HAL_DEVICE *HalDev)
++{
++   int status;
++
++    if(HalDev->State <  enOpened)
++      return (EC_CPMAC|EC_FUNC_STATUS|EC_VAL_INVALID_STATE);      /*MJH+030805*/
++
++   /* No Phy Condition */
++   if(HalDev->MdioConnect & _CPMDIO_NOPHY)                        /*MJH+030805*/
++   {
++       /*  No Phy condition, always linked */
++       status = HalDev->Linked;
++       status |= CPMAC_STATUS_LINK_DUPLEX;
++       status |= CPMAC_STATUS_LINK_SPEED;
++       return(status);
++   }
++
++
++   if (HalDev->HostErr)  /* Adapter Check  */
++    {
++    bit32u tmp;
++    status = CPMAC_STATUS_ADAPTER_CHECK;
++    if(HalDev->MacStatus & RX_HOST_ERR_CODE)
++      {
++      status |= CPMAC_STATUS_HOST_ERR_DIRECTION;
++      tmp     = (HalDev->MacStatus & RX_HOST_ERR_CODE) >> 12; /* Code */
++      status |= (tmp << 9); /* Code */
++      tmp     = (HalDev->MacStatus & RX_ERR_CH) >> 8; /* Channel */
++      status |= (tmp << 13);
++      }
++    else
++    if(HalDev->MacStatus & TX_HOST_ERR_CODE)
++      {
++      status |= CPMAC_STATUS_HOST_ERR_DIRECTION;
++      tmp     = (HalDev->MacStatus & TX_HOST_ERR_CODE) >> 20; /* Code */
++      status |= (tmp << 9); /* Code */
++      tmp     = (HalDev->MacStatus & TX_ERR_CH) >> 16; /* Channel */
++      status |= (tmp << 13);
++      }
++    }
++   else
++    {
++    status = HalDev->Linked;
++    if(status)
++      {
++      status = CPMAC_STATUS_LINK;
++      if(cpMacMdioGetDuplex(HalDev->PhyDev))
++        status |= CPMAC_STATUS_LINK_DUPLEX;
++      if(cpMacMdioGetSpeed(HalDev->PhyDev))
++        status |= CPMAC_STATUS_LINK_SPEED;
++      }
++    }
++   if(HalDev->debug)
++      dbgPrintf("[halStatus] Link Status is %d for 0x%X\n", status, HalDev->dev_base);
++   return(status);
++}
++static int InfoAccess(HAL_DEVICE *HalDev, int Key, int Action, void *ParmValue)
++  {
++  int rc = 0;
++  int Update=0;
++
++  switch (Key)
++  {
++    /********************************************************************/
++    /*                                                                  */
++    /*                      GENERAL                                     */
++    /*                                                                  */
++    /********************************************************************/
++
++    case enVersion :
++         if(Action==enGET)
++           {
++           *(const char **)ParmValue = pszVersion_CPMAC;
++           }
++    break;
++    case enDebug  :
++         if(Action==enSET)
++           {
++           HalDev->debug = *(unsigned int *)ParmValue;
++           }
++    break;
++
++    case enStatus      :
++         if(Action==enGET)
++           {
++           int status;
++           status = halStatus(HalDev);
++           *(int *)ParmValue = status;
++           }
++    break;
++    /********************************************************************/
++    /*                                                                  */
++    /*                      RX_MBP_ENABLE                               */
++    /*                                                                  */
++    /********************************************************************/
++
++    case enRX_PASS_CRC  :
++         if(Action==enSET)
++           {
++           UPDATE_RX_PASS_CRC(*(unsigned int *)ParmValue);
++           Update=1;
++           }
++    break;
++    case enRX_QOS_EN  :
++         if(Action==enSET)
++           {
++           UPDATE_RX_QOS_EN(*(unsigned int *)ParmValue);
++           Update=1;
++           }
++    break;
++    case enRX_NO_CHAIN :
++         if(Action==enSET)
++           {
++           UPDATE_RX_NO_CHAIN(*(unsigned int *)ParmValue);
++           Update=1;
++           }
++    break;
++    case enRX_CMF_EN :
++         if(Action==enSET)
++           {
++           UPDATE_RX_CMF_EN(*(unsigned int *)ParmValue);
++           Update=1;
++           }
++    break;
++    case enRX_CSF_EN :
++         if(Action==enSET)
++           {
++           UPDATE_RX_CSF_EN(*(unsigned int *)ParmValue);
++           Update=1;
++           }
++    break;
++    case enRX_CEF_EN :
++         if(Action==enSET)
++           {
++           UPDATE_RX_CEF_EN(*(unsigned int *)ParmValue);
++           Update=1;
++           }
++    break;
++    case enRX_CAF_EN :
++         if(Action==enSET)
++           {
++           UPDATE_RX_CAF_EN(*(unsigned int *)ParmValue);
++           Update=1;
++           }
++    break;
++    case enRX_PROM_CH :
++         if(Action==enSET)
++           {
++           UPDATE_RX_PROM_CH(*(unsigned int *)ParmValue);
++           Update=1;
++           }
++    break;
++    case enRX_BROAD_EN :
++         if(Action==enSET)
++           {
++           UPDATE_RX_BROAD_EN(*(unsigned int *)ParmValue);
++           Update=1;
++           }
++    break;
++    case enRX_BROAD_CH :
++         if(Action==enSET)
++           {
++           UPDATE_RX_BROAD_CH(*(unsigned int *)ParmValue);
++           Update=1;
++           }
++    break;
++    case enRX_MULT_EN :
++         if(Action==enSET)
++           {
++           UPDATE_RX_MULT_EN(*(unsigned int *)ParmValue);
++           Update=1;
++           }
++    break;
++    case enRX_MULT_CH :
++         if(Action==enSET)
++           {
++           UPDATE_RX_MULT_CH(*(unsigned int *)ParmValue);
++           Update=1;
++           }
++    break;
++
++    /********************************************************************/
++    /*                                                                  */
++    /*                      MAC_CONTROL                                 */
++    /*                                                                  */
++    /********************************************************************/
++
++    case enTX_PTYPE :
++         if(Action==enSET)
++           {
++           UPDATE_TX_PTYPE(*(unsigned int *)ParmValue);
++           Update=1;
++           }
++    break;
++    case enTX_PACE :
++         if(Action==enSET)
++           {
++           UPDATE_TX_PACE(*(unsigned int *)ParmValue);
++           Update=1;
++           }
++    break;
++    case enTX_FLOW_EN :
++         if(Action==enSET)
++           {
++           UPDATE_TX_FLOW_EN(*(unsigned int *)ParmValue);
++           Update=1;
++           }
++    break;
++    case enRX_FLOW_EN :
++         if(Action==enSET)
++           {
++           UPDATE_RX_FLOW_EN(*(unsigned int *)ParmValue);
++           Update=1;
++           }
++    break;
++
++    case enCTRL_LOOPBACK :
++         if(Action==enSET)
++           {
++           UPDATE_CTRL_LOOPBACK(*(unsigned int *)ParmValue);
++           Update=1;
++           }
++    break;
++    /********************************************************************/
++    /*                                                                  */
++    /*                      RX_UNICAST_SET                              */
++    /*                                                                  */
++    /********************************************************************/
++
++    case enRX_UNICAST_SET :
++         if(Action==enSET)
++          {
++           HalDev->RxUnicastSet   |=  (1 << *(unsigned int *)ParmValue);
++           HalDev->RxUnicastClear &= ~(1 << *(unsigned int *)ParmValue);
++           Update=1;
++          }
++    break;
++    case enRX_UNICAST_CLEAR :
++         if(Action==enSET)
++          {
++          HalDev->RxUnicastClear |=  (1 << *(unsigned int *)ParmValue);
++          HalDev->RxUnicastSet   &= ~(1 << *(unsigned int *)ParmValue);
++          Update=1;
++          }
++    break;
++
++    case enRX_MAXLEN :
++         if(Action==enSET)
++           {
++           HalDev->RxMaxLen    =   *(unsigned int *)ParmValue;
++           Update=1;
++           }
++    break;
++
++    case enRX_FILTERLOWTHRESH :
++         if(Action==enSET)
++           {
++           HalDev->RxFilterLowThresh  =   *(unsigned int *)ParmValue;
++           Update=1;
++           }
++    break;
++    case enRX0_FLOWTHRESH :
++         if(Action==enSET)
++           {
++           HalDev->Rx0FlowThresh =   *(unsigned int *)ParmValue;
++           Update=1;
++           }
++    break;
++    /********************************************************************/
++    /*                                                                  */
++    /*                      RX_MULTICAST                                */
++    /*                                                                  */
++    /********************************************************************/
++
++    case enRX_MULTICAST :
++    break;
++    case enRX_MULTI_SINGLE :
++         if(DBG(11))
++          {
++           int tmpi;
++           bit8u *MacAddress;
++           MacAddress = (bit8u *) ParmValue;
++           dbgPrintf("CPMAC[%X]:  MacAddress '", HalDev->dev_base);
++           for (tmpi=0; tmpi<6; tmpi++)
++             dbgPrintf("%02X:", MacAddress[tmpi]);
++             dbgPrintf("\n");
++          }
++         if(Action==enCLEAR)
++           {
++           HashDel(HalDev, ParmValue);
++           Update=1;
++           }
++         else
++         if(Action==enSET)
++           {
++           HashAdd(HalDev, ParmValue);
++           Update=1;
++           }
++    break;
++    case enRX_MULTI_ALL :
++         if(Action==enCLEAR)
++           {
++           HalDev->MacHash1 = 0;
++           HalDev->MacHash2 = 0;
++           Update=1;
++           }
++         else
++         if(Action==enSET)
++           {
++           HalDev->MacHash1 = 0xFFFFFFFF;
++           HalDev->MacHash2 = 0xFFFFFFFF;
++           Update=1;
++           }
++    break;
++
++    /********************************************************************/
++    /*                                                                  */
++    /*                      MDIO                                        */
++    /*                                                                  */
++    /********************************************************************/
++
++    case enMdioConnect :
++         if(Action==enSET)
++           {
++           HalDev->MdioConnect = *(unsigned int *)ParmValue;
++           MdioSetPhyMode(HalDev);
++           }
++           if(Action==enGET)
++           {
++           *(unsigned int *)ParmValue = HalDev->MdioConnect;
++           }
++    break;
++
++
++    /********************************************************************/
++    /*                                                                  */
++    /*                      STATISTICS                                  */
++    /*                                                                  */
++    /********************************************************************/
++    case enStatsClear :
++           StatsClear(HalDev);
++    break;
++    case enStatsDump :
++         if(Action==enGET)
++           {
++           StatsDump(HalDev, ParmValue);
++           }
++    break;
++
++/*  Not implemented
++    case enStats1 :
++         if(Action==enGET)
++           {
++           StatsGet(HalDev, ParmValue, 1);
++           }
++    break;
++
++    case enStats2 :
++         if(Action==enGET)
++           {
++           StatsGet(HalDev, ParmValue, 2);
++           }
++    break;
++    case enStats3 :
++         if(Action==enGET)
++           {
++           StatsGet(HalDev, ParmValue, 3);
++           }
++    break;
++    case enStats4 :
++         if(Action==enGET)
++           {
++           StatsGet(HalDev, ParmValue, 4);
++           }
++    break;
++
++*/
++
++    default:
++    rc = EC_CPMAC|EC_FUNC_OPTIONS|EC_VAL_KEY_NOT_FOUND;
++    break;
++  }
++
++  /* Verify proper device state */
++  if (HalDev->State == enOpened)
++    switch (Update)
++      {
++      case 1 :
++           ConfigApply(HalDev);
++      break;
++      default:
++      break;
++      }
++
++  return (rc);
++  }
++static const char pszStats[]       = "Stats;";
++
++static int halControl(HAL_DEVICE *HalDev, const char *pszKey, const char *pszAction, void *Value)
++  {
++  int i;
++  int rc=0;
++  int Action;
++  int ActionFound;
++  int KeyFound;
++
++#ifdef __CPHAL_DEBUG
++  if (DBG(1))
++    {
++    dbgPrintf("\nhalControl-HalDev:%08X,Action:%s,Key:%s\n", (bit32u)HalDev, pszAction, pszKey);
++    }
++#endif
++
++  /* 23Aug04 - BCIL needs to set Mac Address  */
++  if(HalDev->OsFunc->Strcmpi(pszKey, pszMacAddr) == 0)
++    {
++    KeyFound=1;
++    if(HalDev->OsFunc->Strcmpi(pszAction, hcSet) == 0)
++      {
++        unsigned char *MacAddr;  
++        MacAddr = (unsigned char *) Value;  
++        MacAddressSave(HalDev, MacAddr); 
++        MacAddressSet(HalDev);       
++        return(0);
++      }
++    else
++      {
++       return(-1);
++      }
++    }
++     
++  if(HalDev->OsFunc->Strcmpi(pszKey, hcLinked) == 0)
++    {
++    KeyFound=1;
++    if(HalDev->OsFunc->Strcmpi(pszAction, hcSet) == 0)
++      {
++        HalDev->Linked = *(int *)Value;
++        return(0);
++      }
++    else
++      {
++       return(-1);
++      }
++    }
++  
++  if(HalDev->OsFunc->Strcmpi(pszKey, "TxIntDisable") == 0)
++    {
++    KeyFound=1;
++    if(HalDev->OsFunc->Strcmpi(pszAction, hcSet) == 0)
++      {
++        HalDev->TxIntDisable = *(int *)Value;
++        if(HalDev->TxIntDisable && (HalDev->State == enOpened))
++          {
++              /* if Opened and need TxIntDisabled, clear Ints for Channel 0 */
++              CPMAC_TX_INTMASK_CLEAR(HalDev->dev_base) = 1;             
++          }        
++        return(0);
++      }
++    else
++      {
++       return(-1);
++      }
++    }
++
++  if(HalDev->OsFunc->Strcmpi(pszKey, hcPhyAccess) == 0)
++    {
++    bit32u RegAddr;
++    bit32u PhyNum;
++    bit32u Data;
++    bit32u ValueIn;
++
++    ValueIn = *(bit32u*) Value;
++
++    KeyFound=1;
++    /* Cannot access MII if not opended */
++
++    if(HalDev->State < enOpened)
++      return(-1);
++
++    if(HalDev->OsFunc->Strcmpi(pszAction, hcGet) == 0)
++      {
++
++      PhyNum  = (ValueIn & 0x1F);        /* Phynum 0-32 */
++      RegAddr = (ValueIn >> 5) & 0xFF;   /* RegAddr in upper 11 bits */
++
++      *(bit32u*)Value = _mdioUserAccessRead(HalDev->PhyDev, RegAddr, PhyNum);
++
++      return(0);
++      } /* end of hcGet */
++
++
++    if(HalDev->OsFunc->Strcmpi(pszAction, hcSet) == 0)
++      {
++      PhyNum  = (ValueIn & 0x1F);        /* Phynum 0-32 */
++      RegAddr = (ValueIn >> 5) & 0xFF;   /* RegAddr in upper 11 bits of lower 16 */
++
++      Data    = ValueIn >> 16;           /* Data store in upper 16 bits */
++
++      _mdioUserAccessWrite(HalDev->PhyDev, RegAddr, PhyNum, Data);
++      return(0);
++      }
++    } /*  End of hcPhyAccess */
++
++  if(HalDev->OsFunc->Strcmpi(pszKey, hcPhyNum) == 0)
++    {
++    KeyFound=1;
++    if(!HalDev->Linked)
++      return(-1);  /* if not linked the no Phy Connected */
++    if(HalDev->OsFunc->Strcmpi(pszAction, hcGet) == 0)
++      {
++        *(int *)Value = HalDev->PhyNum;
++      return(0);
++      }
++    }
++
++  if(HalDev->OsFunc->Strcmpi(pszKey, hcCpmacSize) == 0)
++    {
++    KeyFound=1;
++    if(HalDev->OsFunc->Strcmpi(pszAction, hcGet) == 0)
++      {
++        *(bit32u *)Value = HalDev->CpmacSize;
++      return(0);
++      }
++    }
++
++   if(HalDev->OsFunc->Strcmpi(pszKey, hcCpmacBase) == 0)
++    {
++    KeyFound=1;
++    if(HalDev->OsFunc->Strcmpi(pszAction, hcGet) == 0)
++      {
++        *(int *)Value = HalDev->dev_base;
++      return(0);
++      }
++    }
++
++  if(HalDev->OsFunc->Strcmpi(pszKey, hcFullDuplex) == 0)
++    {
++    KeyFound=1;
++    if(HalDev->OsFunc->Strcmpi(pszAction, hcSet) == 0)
++      {
++        UPDATE_FULLDUPLEX(*(unsigned int *)Value);
++        if(HalDev->State == enOpened)
++           ConfigApply(HalDev);
++      return(0);
++      }
++    else
++      return(-1);
++    }
++
++  if(HalDev->OsFunc->Strcmpi(pszKey, pszDebug) == 0)
++    {
++    KeyFound=1;
++    if(HalDev->OsFunc->Strcmpi(pszAction, hcSet) == 0)
++      {
++        ActionFound=1;
++        HalDev->debug = *(int *)Value;
++      }
++    }
++
++  if(HalDev->OsFunc->Strcmpi(pszKey, hcMaxFrags) == 0)
++    {
++     KeyFound=1;
++     if(HalDev->OsFunc->Strcmpi(pszAction, hcSet) == 0)
++       {
++        ActionFound=1;
++
++        if ((*(int *)Value) > 0)
++          HalDev->MaxFrags = *(int *)Value;
++         else
++          rc = (EC_AAL5|EC_FUNC_CONTROL|EC_VAL_INVALID_VALUE);
++      }
++
++     if (HalDev->OsFunc->Strcmpi(pszAction, hcGet) == 0)
++       {
++        ActionFound=1;
++
++        *(int *)Value = HalDev->MaxFrags;
++       }
++    }
++
++  if(HalDev->OsFunc->Strstr(pszKey, pszStats) != 0)
++    {
++     KeyFound=1;
++     if(HalDev->OsFunc->Strcmpi(pszAction, hcGet) == 0)
++         {
++       int Level;
++       int Ch;
++       char *TmpKey = (char *)pszKey;
++       ActionFound=1;
++       TmpKey += HalDev->OsFunc->Strlen(pszStats);
++       Level   = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++       TmpKey++;
++       Ch      = HalDev->OsFunc->Strtoul(TmpKey, &TmpKey, 10);
++       TmpKey++;
++       osfuncSioFlush();
++#ifdef __CPHAL_DEBUG
++  if (DBG(1))
++    {
++    dbgPrintf("\nhalControl-HalDev:%08X, Level:%d, Ch:%d\n", (bit32u)HalDev, Level, Ch);
++    }
++#endif
++         StatsGet(HalDev, (void **)Value, Level, Ch, 0);
++       osfuncSioFlush();
++         }
++    }
++
++
++  if(HalDev->OsFunc->Strcmpi(pszAction, hcSet) == 0)
++    Action = enSET;
++  else
++  if(HalDev->OsFunc->Strcmpi(pszAction, hcClear) == 0)
++    Action = enCLEAR;
++  else
++  if(HalDev->OsFunc->Strcmpi(pszAction, hcGet) == 0)
++    Action = enGET;
++  else
++    Action = enNULL;
++
++
++
++  for(i=enCommonStart+1;i<enCommonEnd;i++)
++    {
++    if(HalDev->OsFunc->Strcmpi(KeyCommon[i].strKey, pszKey)==0)
++      {
++      rc = InfoAccess(HalDev, KeyCommon[i].enKey, Action, Value);
++      }
++    }
++  for(i=enCpmacStart+1;i<enCpmacEnd;i++)
++    {
++    if(HalDev->OsFunc->Strcmpi(KeyCpmac[i].strKey, pszKey)==0)
++      {
++      rc = InfoAccess(HalDev, KeyCpmac[i].enKey, Action, Value);
++      }
++    }
++/*
++  if (KeyFound == 0)
++    rc = (EC_MODULE|EC_FUNC_CONTROL|EC_VAL_KEY_NOT_FOUND);
++
++  if (ActionFound == 0)
++    rc = (EC_MODULE|EC_FUNC_CONTROL|EC_VAL_ACTION_NOT_FOUND);
++*/
++
++  return(rc);
++  }
++static bit32u ConfigGet(HAL_DEVICE *HalDev)
++  {
++  OS_FUNCTIONS *OsFunc = HalDev->OsFunc;
++  char *DeviceInfo     = HalDev->DeviceInfo;
++  int i                = HalDev->inst;
++  bit32u Value;
++  int Error;
++
++  /* get the configuration parameters common to all modules */
++  Error = ConfigGetCommon(HalDev);
++  if (Error) return (EC_CPMAC|Error);
++
++  if (HalDev->debug)
++    {
++      dbgPrintf("ConfigGet: haldev:0x%08X inst:%d base:0x%08X reset:%d\n", (bit32u) &HalDev, HalDev->inst, HalDev->dev_base, HalDev->ResetBit);
++      osfuncSioFlush();
++    }
++
++  Error = OsFunc->DeviceFindParmUint(DeviceInfo, pszMdioConnect,&Value); /*MJH+030805*/
++  if(!Error) HalDev->MdioConnect = Value;
++
++  Error = OsFunc->DeviceFindParmUint(DeviceInfo, "PhyMask",&Value);
++  if(!Error) HalDev->PhyMask = Value;
++
++  Error = OsFunc->DeviceFindParmUint(DeviceInfo, "MLink",&Value);
++  if(!Error) HalDev->MLinkMask = Value;
++
++  Error = OsFunc->DeviceFindParmUint(DeviceInfo, hcMdixMask, &Value);
++  if(!Error)
++    HalDev->MdixMask = Value;
++  else
++    HalDev->MdixMask = 0;
++
++  Error = OsFunc->DeviceFindParmUint(DeviceInfo, hcSize, &Value); /*MJH+030425*/
++  if(!Error) HalDev->CpmacSize = Value;
++
++  for(i=enCommonStart+1;i<enCommonEnd;i++)
++    {
++    Error = OsFunc->DeviceFindParmUint(DeviceInfo, KeyCommon[i].strKey, (bit32u*)&Value);
++    if(!Error)
++      {
++      InfoAccess(HalDev, KeyCommon[i].enKey, enSET, (bit32u*)&Value);
++      }
++    }
++  for(i=enCpmacStart+1;i<enCpmacEnd;i++)
++    {
++    Error = OsFunc->DeviceFindParmUint(DeviceInfo, KeyCpmac[i].strKey, (bit32u*)&Value);
++    if(!Error)
++      {
++      InfoAccess(HalDev, KeyCpmac[i].enKey, enSET, (bit32u*)&Value);
++      }
++    }
++   return (EC_NO_ERRORS);
++  }
++
++
++static void ConfigInit(HAL_DEVICE *HalDev)
++  {
++  if(HalDev->inst == 0)
++    {
++     HalDev->dev_base  = 0xA8610000;
++     HalDev->ResetBit  = 17;
++     HalDev->interrupt = 19;
++     HalDev->MLinkMask = 0;
++     HalDev->PhyMask   = 0xAAAAAAAA;
++    }
++  else
++    {
++     HalDev->dev_base  = 0xA8612800;
++     HalDev->ResetBit  = 21;
++     HalDev->interrupt = 33;                                         /*~RC3.02*/
++     HalDev->MLinkMask = 0;
++     HalDev->PhyMask   = 0x55555555;
++    }
++  HalDev->RxMaxLen    = 1518;
++  HalDev->MaxFrags    = 2;
++  HalDev->MdioConnect = _CPMDIO_HD|_CPMDIO_FD|_CPMDIO_10|_CPMDIO_100|_CPMDIO_AUTOMDIX;
++  HalDev->debug=0xFFFFFFFF;
++  HalDev->debug=0;
++  }
++/* Shuts down the EMAC device
++ *
++ *@param HalDev EMAC instance. This was returned by halOpen()
++ *@param mode Indicates actions to tak on close.
++ <br>
++ *PARTIAL - Disable EMAC
++ <br>
++ *FULL    - Disable EMAC and call OS to free all allocated memory
++ *
++ *@retval
++ *        0 OK
++ <br>
++ *        Non-Zero Not OK
++ *
++ */
++static int halInit( HAL_DEVICE *HalDev)
++  {
++   int rc;
++
++  /* Verify proper device state */
++  if (HalDev->State != enDevFound)
++    return(EC_CPMAC|EC_FUNC_HAL_INIT|EC_VAL_INVALID_STATE);
++
++  /* Configure HAL defaults */
++  ConfigInit(HalDev);
++
++  /* Retrieve HAL configuration parameters from data store */
++  rc = ConfigGet(HalDev);
++  if (rc) return (rc);
++
++  /* Updated 030403*/
++  rc = HalDev->OsFunc->Control(HalDev->OsDev, hcCpuFrequency, hcGet, &HalDev->CpuFrequency); /*MJH+030403*/
++  if(rc)
++    HalDev->CpuFrequency = 20000000;  /*20 Mhz default */         /*MJH+030403*/
++
++  rc = HalDev->OsFunc->Control(HalDev->OsDev, hcCpmacFrequency, hcGet, &HalDev->CpmacFrequency); /*MJH+030331*/
++  if(rc)
++    HalDev->CpmacFrequency = HalDev->CpuFrequency/2;               /*MJH~030404*/
++
++  rc = HalDev->OsFunc->Control(HalDev->OsDev, hcMdioBusFrequency,  hcGet, &HalDev->MdioBusFrequency);  /*MJH+030402*/
++  if(rc)
++    HalDev->MdioBusFrequency = HalDev->CpmacFrequency;
++
++  rc = HalDev->OsFunc->Control(HalDev->OsDev, hcMdioClockFrequency,  hcGet, &HalDev->MdioClockFrequency);  /*MJH+030402*/
++  if(rc)
++    HalDev->MdioClockFrequency = 2200000; /* 2.2 Mhz PITS #14 */
++
++
++  /* update device state */
++  HalDev->State = enInitialized;
++
++  /* initialize statistics */
++  StatsInit(HalDev);                                                  /* +RC3.02 */
++
++  /*                                                                  -RC3.02
++  StatsTable3[0].StatPtr  = &HalDev->ChData[0].RxBufSize;
++  StatsTable3[1].StatPtr  = &HalDev->ChData[0].RxBufferOffset;
++  StatsTable3[2].StatPtr  = &HalDev->ChData[0].RxNumBuffers;
++  StatsTable3[3].StatPtr  = &HalDev->ChData[0].RxServiceMax;
++  StatsTable3[4].StatPtr  = &HalDev->ChData[0].TxNumBuffers;
++  StatsTable3[5].StatPtr  = &HalDev->ChData[0].TxNumQueues;
++  StatsTable3[6].StatPtr  = &HalDev->ChData[0].TxServiceMax;
++  */
++
++  return(EC_NO_ERRORS);
++  }
++static int halProbe(HAL_DEVICE *HalDev)
++  {
++  int inst             = HalDev->inst;
++  OS_FUNCTIONS *OsFunc = HalDev->OsFunc;
++  int error_code;
++
++  if (HalDev->State != enConnected)
++     return (EC_CPMAC|EC_FUNC_PROBE|EC_VAL_INVALID_STATE);
++
++  if(HalDev->debug) dbgPrintf("halProbe: %d ",inst);
++
++  error_code = OsFunc->DeviceFindInfo(inst,"cpmac",&HalDev->DeviceInfo);
++
++  if(error_code)
++     return (EC_CPMAC|EC_FUNC_PROBE|EC_VAL_DEVICE_NOT_FOUND );
++
++  /* Set device state to DevFound */
++  HalDev->State = enDevFound;
++  return(EC_NO_ERRORS);
++  }
++static void ChannelConfigInit(HAL_DEVICE *HalDev, CHANNEL_INFO *HalChn)
++  {
++  int Ch        = HalChn->Channel;
++  int Direction = HalChn->Direction;
++  int nTxBuffers = 256;
++
++  if (Direction == DIRECTION_TX)
++    {
++    HalDev->ChData[Ch].TxNumBuffers   = nTxBuffers;
++    HalDev->ChData[Ch].TxNumQueues    = 1;
++    HalDev->ChData[Ch].TxServiceMax   = nTxBuffers/3;
++    HalDev->TxIntThreshold[Ch]        = HalDev->ChData[Ch].TxServiceMax;
++    HalDev->TxIntThresholdMaster[Ch]  = HalDev->TxIntThreshold[Ch];
++    }
++
++  if (Direction == DIRECTION_RX)
++    {
++    HalDev->ChData[Ch].RxNumBuffers   = nTxBuffers*2;
++    HalDev->ChData[Ch].RxBufferOffset = 0;
++    HalDev->ChData[Ch].RxBufSize      = 1518;
++    HalDev->ChData[Ch].RxServiceMax   = nTxBuffers/3; /*Not a typo*/
++    }
++  }
++static int ChannelConfigApply(HAL_DEVICE *HalDev, CHANNEL_INFO *HalChn)
++  {
++   int Ch        = HalChn->Channel;
++   int Direction = HalChn->Direction;
++
++   if (DBG(11))
++     {
++      dbgPrintf("halChannelConfigApply[%d:%d] haldev:0x%08X inst:%d base:0x%08X reset:%d\n", Ch, Direction, (bit32u) &HalDev, HalDev->inst, HalDev->dev_base, HalDev->ResetBit);
++      osfuncSioFlush();
++     }
++
++   if (Direction == DIRECTION_TX)
++   {
++     if (HalDev->ChIsOpen[Ch][Direction] == TRUE)
++     {
++      return(EC_CPMAC|EC_FUNC_CHSETUP|EC_VAL_TX_CH_ALREADY_OPEN);
++     }
++
++     /* Initialize Queue Data */
++     HalDev->TxActQueueHead[Ch][0]  = 0;
++     HalDev->TxActQueueCount[Ch][0] = 0;
++     HalDev->TxActive[Ch][0]        = FALSE;
++
++     /* Need to use a macro that takes channel as input */
++     CPMAC_TX0_HDP(HalDev->dev_base)=0;
++
++     /* Initialize buffer memory for the channel */
++     InitTcb(HalDev, Ch);
++
++     if(!HalDev->TxIntDisable)
++       CPMAC_TX_INTMASK_SET(HalDev->dev_base) = (1<<Ch); /* GSG 11/22 */
++   }
++   else
++   {
++     if (HalDev->ChIsOpen[Ch][Direction] == TRUE)
++     {
++      return(EC_CPMAC|EC_FUNC_CHSETUP|EC_VAL_RX_CH_ALREADY_OPEN);
++     }
++
++     /* Initialize Queue Data */
++     HalDev->RxActQueueHead[Ch]     = 0;
++     HalDev->RxActQueueCount[Ch]    = 0;
++
++     HalDev->RxActive[Ch]           = FALSE;
++
++     /* Need to use a macro that takes channel as input */
++     CPMAC_RX0_HDP(HalDev->dev_base)=0;
++
++     /* Initialize buffer memory for the channel */
++     InitRcb(HalDev, Ch);
++
++     CPMAC_RX_INTMASK_SET(HalDev->dev_base)  = (1<<Ch); /* GSG 11/22 */
++   }
++
++   HalDev->ChIsOpen[Ch][Direction] = TRUE; /* channel is open */
++
++   return (EC_NO_ERRORS);
++  }
++
++/* GSG 11/22
++ * Retrieves channel parameters from configuration file.  Any parameters
++ * which are not found are ignored, and the HAL default value will apply,
++ * unless a new value is given through the channel structure in the call
++ * to ChannelSetup.
++ */
++static int ChannelConfigGet(HAL_DEVICE *HalDev, CHANNEL_INFO *HalChn)
++  {
++  int Ch        = HalChn->Channel;
++  int Direction = HalChn->Direction;
++  OS_FUNCTIONS *OsFunc = HalDev->OsFunc;
++  unsigned int rc, Value;
++  void *ChInfo;
++
++   rc=OsFunc->DeviceFindParmValue(HalDev->DeviceInfo, channel_names[Ch], &ChInfo);
++   /*  Do not fail if Channel Info not available for RC2 */
++   if (rc) return(0);
++/*   if (rc) return(EC_CPMAC|EC_FUNC_CHSETUP|EC_VAL_CH_INFO_NOT_FOUND);*/
++
++   /* i don't care if a value is not found because they are optional */
++   if(Direction == DIRECTION_TX)
++     {
++     rc=OsFunc->DeviceFindParmUint(ChInfo, "TxNumBuffers", &Value);
++     if (!rc) HalDev->ChData[Ch].TxNumBuffers = Value;
++
++     /*rc=OsFunc->DeviceFindParmUint(ChInfo, "TxNumQueues", &Value);*/ /*MJH-030329*/
++     /*if (!rc) HalDev->ChData[Ch].TxNumQueues = Value;*/              /*MJH-030329*/
++
++     rc=OsFunc->DeviceFindParmUint(ChInfo, "TxServiceMax", &Value);
++     if (!rc) 
++       {
++         HalDev->ChData[Ch].TxServiceMax = Value;
++         HalDev->TxIntThreshold[Ch]      = HalDev->ChData[Ch].TxServiceMax;
++         HalDev->TxIntThresholdMaster[Ch]  = HalDev->TxIntThreshold[Ch];
++       }
++     }
++   if(Direction == DIRECTION_RX)
++     {
++     rc=OsFunc->DeviceFindParmUint(ChInfo, "RxNumBuffers", &Value);
++     if (!rc) HalDev->ChData[Ch].RxNumBuffers = Value;
++
++     rc=OsFunc->DeviceFindParmUint(ChInfo, "RxBufferOffset", &Value);
++     if (!rc) HalDev->ChData[Ch].RxBufferOffset = Value;
++
++     rc=OsFunc->DeviceFindParmUint(ChInfo, "RxBufSize", &Value);
++     if (!rc) HalDev->ChData[Ch].RxBufSize = Value;
++
++     rc=OsFunc->DeviceFindParmUint(ChInfo, "RxServiceMax", &Value);
++     if (!rc) HalDev->ChData[Ch].RxServiceMax = Value;
++     }
++   return (EC_NO_ERRORS);
++  }
++#define ChannelUpdate(Field) if(HalChn->Field != 0xFFFFFFFF) HalDev->ChData[Ch].Field = HalChn->Field
++
++static void ChannelConfigUpdate(HAL_DEVICE *HalDev, CHANNEL_INFO *HalChn)
++  {
++  int Ch        = HalChn->Channel;
++  int Direction = HalChn->Direction;
++#ifdef __CPHAL_DEBUG
++  if (DBG(1))
++    {
++    dbgPrintf("\nChnUpd-HalDev:%08X,Chn:%d:%d\n", (bit32u)HalDev, Ch, Direction); osfuncSioFlush();
++    }
++#endif
++  if (Direction == DIRECTION_TX)
++    {
++    ChannelUpdate(TxNumBuffers);
++    /*ChannelUpdate(TxNumQueues);*/                               /*MJH~030329*/
++    ChannelUpdate(TxServiceMax);
++    HalDev->TxIntThreshold[Ch]        = HalDev->ChData[Ch].TxServiceMax;
++    HalDev->TxIntThresholdMaster[Ch]  = HalDev->TxIntThreshold[Ch];
++    }
++  else
++  if (Direction == DIRECTION_RX)
++    {
++    ChannelUpdate(RxBufferOffset);
++    ChannelUpdate(RxBufSize);
++    ChannelUpdate(RxNumBuffers);
++    ChannelUpdate(RxServiceMax);
++#ifdef __CPHAL_DEBUG
++  if (DBG(1))
++    {
++    dbgPrintf("\nRxNumBuffers %d\n",HalChn->RxNumBuffers); osfuncSioFlush();
++    }
++#endif
++    }
++  }
++static int halChannelSetup(HAL_DEVICE *HalDev, CHANNEL_INFO *HalChn, OS_SETUP *OsSetup)
++  {
++  int Direction;
++  int Ch;
++  int rc;
++
++  /* Verify proper device state */
++  if (HalDev->State < enInitialized)
++    return (EC_CPMAC|EC_FUNC_CHSETUP|EC_VAL_INVALID_STATE);
++
++  /* We require the channel structure to be passed, even if it only contains
++     the channel number */
++  if (HalChn == NULL)
++    {
++     return(EC_CPMAC|EC_FUNC_CHSETUP|EC_VAL_NULL_CH_STRUCT);
++    }
++
++  Ch        = HalChn->Channel;
++  Direction = HalChn->Direction;
++
++  /* This should check on Maximum Channels for RX or TX,
++     they might be different Mick 021124 */
++  if ((Ch < 0) || (Ch > (MAX_CHAN-1)))
++    {
++     return(EC_CPMAC|EC_FUNC_CHSETUP|EC_VAL_INVALID_CH);
++    }
++
++  /* if channel is already open, this call is invalid */
++  if (HalDev->ChIsOpen[Ch][Direction] == TRUE)
++    {
++     return(EC_CPMAC|EC_FUNC_CHSETUP|EC_VAL_CH_ALREADY_OPEN);
++    }
++
++  /* channel is closed, but might be setup.  If so, reopen the hardware channel. */
++  if (HalDev->ChIsSetup[Ch][Direction] == FALSE)
++    {
++     /* Setup channel configuration */
++     HalDev->ChData[Ch].Channel = Ch;
++
++     /* Store OS_SETUP */
++     HalDev->ChData[Ch].OsSetup = OsSetup;
++
++     /*  Framework :
++         Set Default Values
++         Update with options.conf
++     Apply driver updates
++     */
++     ChannelConfigInit(HalDev, HalChn);
++     ChannelConfigGet(HalDev, HalChn);
++     ChannelConfigUpdate(HalDev, HalChn);
++
++     /* cppi.c needs to use Rx/TxServiceMax */
++     HalDev->BuffersServicedMax  = 169;  /* TEMP */
++
++     HalDev->ChIsSetup[Ch][Direction] = TRUE;
++    }
++
++  rc = EC_NO_ERRORS;
++
++  /* If the hardware has been opened (is out of reset), then configure the channel
++     in the hardware. NOTE: ChannelConfigApply calls the CPSAR ChannelSetup()! */
++  if (HalDev->State == enOpened)
++    {
++     rc = ChannelConfigApply(HalDev, HalChn);
++    }
++
++  return (rc);
++  }
++
++
++static int miiInfoGet(HAL_DEVICE *HalDev, bit32u *miiBaseAddress, bit32u *miiResetBit)
++  {
++  int rc;
++  void *DeviceInfo;
++  OS_FUNCTIONS *OsFunc = HalDev->OsFunc;
++
++  /*  Only one instance of cpmdio   */
++  rc = OsFunc->DeviceFindInfo(0,"cpmdio",&DeviceInfo);               /*~RC3.02*/
++
++  if(rc)
++     return (EC_DEV_CPMDIO|EC_FUNC_OPEN|EC_VAL_DEVICE_NOT_FOUND );
++
++  rc = OsFunc->DeviceFindParmUint(DeviceInfo, "base",miiBaseAddress);
++  if(rc)
++      rc=EC_DEV_CPMDIO|EC_FUNC_OPEN|EC_VAL_NO_BASE;
++
++  rc = OsFunc->DeviceFindParmUint(DeviceInfo, "reset_bit",miiResetBit);
++  if(rc)
++      rc=EC_DEV_CPMDIO|EC_FUNC_OPEN|EC_VAL_NO_BASE;
++
++
++  /* See if need to make mdio functional in GPIO */
++  gpioCheck(HalDev, DeviceInfo);
++
++  if(DBG(0))
++    dbgPrintf("miiBase: 0x%08X %u\n", *miiBaseAddress, *miiResetBit);
++  return(rc);
++  }
++static void ephyCheck(HAL_DEVICE *HalDev)
++  {                                                                  /*+RC3.02*/
++  int rc;
++  void *DeviceInfo;
++  int mii_phy;
++  int reset_bit;
++  OS_FUNCTIONS *OsFunc = HalDev->OsFunc;
++
++  rc = OsFunc->DeviceFindInfo(0,"ephy",&DeviceInfo);
++  if(rc) return;
++
++  rc = OsFunc->DeviceFindParmUint(DeviceInfo, "mii_phy",&mii_phy);
++  if(rc) return;
++
++  rc = OsFunc->DeviceFindParmUint(DeviceInfo, "reset_bit",&reset_bit);
++  if(rc) return;
++
++  if (HalDev->PhyMask & (1 << mii_phy))
++    {
++    *(volatile bit32u *)(HalDev->ResetBase) |=  (1 << reset_bit);                      /*+RC3.02*/
++    resetWait(HalDev);
++    }
++  }                                                                  /*+RC3.02*/
++static void AutoNegotiate(HAL_DEVICE *HalDev)
++  {
++  int size;
++  bit32u ModID,  RevMaj,  RevMin;
++  PHY_DEVICE *PhyDev;
++  bit32u miiBaseAddress;
++  bit32u miiResetBit;
++
++  /* Verify proper device state */
++  if (HalDev->State < enOpened)
++    return;
++
++  miiInfoGet(HalDev, &miiBaseAddress, &miiResetBit);
++
++  cpMacMdioGetVer(miiBaseAddress, &ModID,  &RevMaj,  &RevMin);
++  if(HalDev->debug)
++     dbgPrintf("Mdio Module Id %d, Version %d.%d\n", ModID,  RevMaj,  RevMin);
++
++  size = cpMacMdioGetPhyDevSize();
++  PhyDev = (PHY_DEVICE *) HalDev->OsFunc->Malloc( size );
++
++  HalDev->PhyDev = PhyDev;
++
++  ephyCheck(HalDev);
++
++  cpMacMdioInit( PhyDev, miiBaseAddress, HalDev->inst, HalDev->PhyMask, HalDev->MLinkMask, HalDev->MdixMask, HalDev->ResetBase, miiResetBit, HalDev->MdioBusFrequency, HalDev->MdioClockFrequency, HalDev->debug, HalDev); /*MJH~030402*/
++  MdioSetPhyMode(HalDev);
++
++  return;
++  }
++static int halOpen(HAL_DEVICE *HalDev)
++  {
++  unsigned char *MacAddr;
++  int i;
++  int j;
++  int rc, Ticks;
++
++  if (HalDev->debug)
++    {
++      dbgPrintf("halOpen: haldev:0x%08X inst:%d base:0x%08X reset:%d\n", (bit32u) &HalDev, HalDev->inst, HalDev->dev_base, HalDev->ResetBit);
++      osfuncSioFlush();
++    }
++
++   /* Verify proper device state */
++   if (HalDev->State < enInitialized)
++     return (EC_CPMAC|EC_FUNC_OPEN|EC_VAL_INVALID_STATE);
++
++
++  /* take CPMAC out of reset - GSG 11/20*/
++  if ((VOLATILE32(HalDev->ResetBase) & (1 << HalDev->ResetBit)) != 0)
++    {
++     /* perform normal close duties */
++     CPMAC_MACCONTROL(HalDev->dev_base) &= ~MII_EN;
++     CPMAC_TX_CONTROL(HalDev->dev_base) &= ~TX_EN;
++     CPMAC_RX_CONTROL(HalDev->dev_base) &= ~RX_EN;
++
++     /* disable interrupt masks */
++     CPMAC_TX_INTMASK_CLEAR(HalDev->dev_base) = 0xFF;
++     CPMAC_RX_INTMASK_CLEAR(HalDev->dev_base) = 0xFF;
++    }
++
++   /* take CPMAC out of reset */
++   *(volatile bit32u *)(HalDev->ResetBase) &= ~(1 << HalDev->ResetBit);
++   resetWait(HalDev);
++   *(volatile bit32u *)(HalDev->ResetBase) |=  (1 << HalDev->ResetBit);
++   resetWait(HalDev);
++
++  /* After Reset clear the Transmit and Receive DMA Head Descriptor Pointers */
++
++  CPMAC_TX0_HDP(HalDev->dev_base)=0;
++  CPMAC_TX1_HDP(HalDev->dev_base)=0;
++  CPMAC_TX2_HDP(HalDev->dev_base)=0;
++  CPMAC_TX3_HDP(HalDev->dev_base)=0;
++  CPMAC_TX4_HDP(HalDev->dev_base)=0;
++  CPMAC_TX5_HDP(HalDev->dev_base)=0;
++  CPMAC_TX6_HDP(HalDev->dev_base)=0;
++  CPMAC_TX7_HDP(HalDev->dev_base)=0;
++
++  /* Rx Init  */
++
++  CPMAC_RX0_HDP(HalDev->dev_base) = 0;
++  CPMAC_RX1_HDP(HalDev->dev_base) = 0;
++  CPMAC_RX2_HDP(HalDev->dev_base) = 0;
++  CPMAC_RX3_HDP(HalDev->dev_base) = 0;
++  CPMAC_RX4_HDP(HalDev->dev_base) = 0;
++  CPMAC_RX5_HDP(HalDev->dev_base) = 0;
++  CPMAC_RX6_HDP(HalDev->dev_base) = 0;
++  CPMAC_RX7_HDP(HalDev->dev_base) = 0;
++
++  CPMAC_RX_BUFFER_OFFSET(HalDev->dev_base) = 0;
++
++  /* Init Tx and Rx DMA */
++
++  CPMAC_TX_CONTROL(HalDev->dev_base) |= TX_EN;
++  CPMAC_RX_CONTROL(HalDev->dev_base) |= RX_EN;
++
++  CPMAC_MAC_INTMASK_SET(HalDev->dev_base) |=2; /* Enable Adaptercheck Ints */
++  HalDev->OsFunc->Control(HalDev->OsDev, pszMacAddr, hcGet, &MacAddr); /* GSG 11/22 */
++  MacAddressSave(HalDev, MacAddr);
++
++  HalDev->HostErr = 0;      /* Clear Adapter Check indicator */
++  HalDev->State = enOpened; /* Change device state */
++
++  /* Start MDIO Negotiation */
++  AutoNegotiate(HalDev);
++
++  /*  Enable the Os Timer  */
++  Ticks = HalDev->CpuFrequency / 100;  /*  10 milli-secs */       /*MJH~030402*/
++  HalDev->OsFunc->Control(HalDev->OsDev, pszTick, hcSet, &Ticks); /* GSG 11/22 */
++  HalDev->OsFunc->IsrRegister(HalDev->OsDev, halIsr, HalDev->interrupt);
++
++  /* GSG +030523 Malloc space for the Rx fraglist */
++  HalDev->fraglist = HalDev->OsFunc->Malloc(HalDev->MaxFrags * sizeof(FRAGLIST));
++
++  /* Any pre-open configuration */
++
++  /* For any channels that have been pre-initialized, set them up now */
++  /* Note : This loop should not use MAX_CHN, it should only
++            loop through Channels Setup, memory should not be reserved
++            until Channel is Setup
++  */
++  for(i=0; i<MAX_CHAN; i++) /* i loops through Channels */
++  for(j=0; j<2; j++)        /* j loops through DIRECTION values, 0 and 1  */
++    {
++     if(HalDev->ChIsSetup[i][j]==TRUE)   /* If the Channel and Direction have been Setup */
++       if(HalDev->ChIsOpen[i][j]==FALSE) /* but not opened, then Apply Values now */
++         {
++          CHANNEL_INFO HalChn;
++          HalChn.Channel   = i;
++          HalChn.Direction = j;
++          rc = ChannelConfigApply(HalDev, &HalChn);
++          if(rc != EC_NO_ERRORS)
++            return(rc);
++         }
++    }  /* End of looping through Channel/Direction */
++
++  ConfigApply(HalDev);  /* Apply Configuration Values to Device */
++  CPMAC_MACCONTROL(HalDev->dev_base) |= MII_EN;  /* MAC_EN */
++  if(DBG(0))
++     dbgPrintf("[halOpen]MacControl:%08X\n", CPMAC_MACCONTROL(HalDev->dev_base));
++  return(EC_NO_ERRORS);
++  }
++
++#define INT_PENDING (MAC_IN_VECTOR_TX_INT_OR | MAC_IN_VECTOR_RX_INT_OR | MAC_IN_VECTOR_HOST_INT)
++static int halShutdown(HAL_DEVICE *HalDev)
++  {
++   int Ch, Queue;                                                  /*GSG+030514*/
++
++   /* Verify proper device state */
++   if (HalDev->State == enOpened)
++     halClose(HalDev, 3); /* GSG ~030429 */
++
++   /* Buffer/descriptor resources may still need to be freed if a Close
++      Mode 1 was performed prior to Shutdown - clean up here */    /*GSG+030514*/
++   for (Ch=0; Ch<MAX_CHAN; Ch++)
++     {
++      if (HalDev->RcbStart[Ch] != 0)
++        FreeRx(HalDev,Ch);
++
++      for(Queue=0; Queue<MAX_QUEUE; Queue++)
++        {
++         if (HalDev->TcbStart[Ch][Queue] != 0)
++           FreeTx(HalDev,Ch,Queue);
++        }
++     }
++
++   /* free the HalFunc */
++   HalDev->OsFunc->Free(HalDev->HalFuncPtr);
++
++   /* free the HAL device */
++   HalDev->OsFunc->Free(HalDev);
++
++   return(EC_NO_ERRORS);
++  }
++int halIsr(HAL_DEVICE *HalDev, int *MorePackets)
++{
++  bit32u IntVec;
++  int Serviced;
++  int PacketsServiced=0;
++  int Channel;
++  int TxMorePackets=0;
++  int RxMorePackets=0;
++
++  /* Verify proper device state - important because a call prior to Open would
++      result in a lockup */
++  if (HalDev->State != enOpened)
++     return(EC_CPMAC|EC_FUNC_DEVICE_INT|EC_VAL_INVALID_STATE);
++
++  IntVec = CPMAC_MAC_IN_VECTOR(HalDev->dev_base);
++
++#ifdef __CPHAL_DEBUG
++  if (DBG(0))
++    {
++    dbgPrintf("\nhalIsr: inst %d, IntVec 0x%X\n", HalDev->inst, IntVec); osfuncSioFlush();/* GSG 11/22 */
++    }
++#endif
++
++  HalDev->IntVec = IntVec;
++  if (IntVec & MAC_IN_VECTOR_TX_INT_OR)
++   {
++     int TxServiceMax=0;  /* Compiler complains if not initialized */
++      
++     Channel = (IntVec & 0x7);
++     
++     if(HalDev->TxIntDisable)
++       {
++         CPMAC_TX_INTMASK_CLEAR(HalDev->dev_base) = (1<<Channel);  /* Disable Interrupt for Channel */           
++         TxServiceMax = HalDev->ChData[Channel].TxServiceMax;  
++         HalDev->ChData[Channel].TxServiceMax = 10000;             /* Need to service all packets in the Queue */
++       }      
++     
++     PacketsServiced |= TxInt(HalDev, Channel, 0, &TxMorePackets);
++     
++     if(HalDev->TxIntDisable)        
++          HalDev->ChData[Channel].TxServiceMax  = TxServiceMax;         
++    }
++  
++  if (IntVec & MAC_IN_VECTOR_RX_INT_OR)
++    {
++     Channel = (IntVec >> 8) & 0x7;
++     Serviced = RxInt(HalDev, Channel, &RxMorePackets);
++     PacketsServiced |= (Serviced<<16);
++    }
++
++  if (IntVec & MAC_IN_VECTOR_HOST_INT)
++    {
++    /* Adaptercheck */
++    HalDev->HostErr = 1;
++    HalDev->MacStatus = CPMAC_MACSTATUS(HalDev->dev_base);
++    osfuncStateChange();                                          /*MJH+030328*/
++    if(DBG(0))
++      {
++      dbgPrintf("Adaptercheck: %08x for base:%X\n",HalDev->MacStatus, (bit32u)HalDev->dev_base);
++      osfuncSioFlush();
++      }
++    }
++  *MorePackets = (TxMorePackets | RxMorePackets);
++  return (PacketsServiced);
++}
++
++int halPacketProcessEnd(HAL_DEVICE *HalDev)
++{
++  int base             = HalDev->dev_base;
++  CPMAC_MAC_EOI_VECTOR(base) = 0;
++  return(0);
++}
++
++
++
++static int PhyCheck(HAL_DEVICE *HalDev)
++  {
++      return(cpMacMdioTic(HalDev->PhyDev));
++  }
++static int halTick(HAL_DEVICE *HalDev)
++{
++    int TickChange;
++
++    if(HalDev->State <  enOpened)
++      return (EC_CPMAC|EC_FUNC_TICK|EC_VAL_INVALID_STATE);
++
++    /* if NO Phy no need to check Link */
++    if(HalDev->MdioConnect & _CPMDIO_NOPHY)
++      return(EC_NO_ERRORS);  /* No change in Phy State detected */
++
++    TickChange = PhyCheck(HalDev);
++    /* Phy State Change Detected */
++    if(TickChange == 1)
++    {
++        /*  MDIO indicated a change  */
++        DuplexUpdate(HalDev);
++        osfuncStateChange();
++        return(EC_NO_ERRORS);
++    }
++
++    /* if in AutoMdix mode, and Flip request received, inform OS */
++    if( (HalDev->MdioConnect & _CPMDIO_AUTOMDIX)  &&
++        (TickChange & _MIIMDIO_MDIXFLIP))
++    {
++       bit32u Mdix;
++       Mdix = TickChange & 0x1;   /*  Mdix mode stored in bit 0 */
++       HalDev->OsFunc->Control(HalDev->OsDev, hcMdioMdixSwitch, hcSet, &Mdix);
++       return(EC_NO_ERRORS);
++    }
++
++    return(EC_NO_ERRORS);
++}
++
++int halCpmacInitModule(HAL_DEVICE **pHalDev, OS_DEVICE *OsDev, HAL_FUNCTIONS **pHalFunc,
++                       OS_FUNCTIONS *OsFunc, int OsFuncSize,     int *HalFuncSize, int Inst)
++  {
++    HAL_DEVICE *HalDev;
++    HAL_FUNCTIONS *HalFunc;
++
++    if (OsFuncSize < sizeof(OS_FUNCTIONS))
++      return (EC_CPMAC|EC_FUNC_HAL_INIT|EC_VAL_OS_VERSION_NOT_SUPPORTED);
++
++    HalDev = (HAL_DEVICE *) OsFunc->MallocDev(sizeof(HAL_DEVICE));
++    if (!HalDev)
++      return (EC_CPMAC|EC_FUNC_HAL_INIT|EC_VAL_MALLOC_DEV_FAILED);
++
++    /* clear the HalDev area */
++    OsFunc->Memset(HalDev, 0, sizeof(HAL_DEVICE));
++
++    /* Initialize the size of hal functions */
++    *HalFuncSize = sizeof (HAL_FUNCTIONS);
++
++    HalFunc = (HAL_FUNCTIONS *) OsFunc->Malloc(sizeof(HAL_FUNCTIONS));
++    if (!HalFunc)
++      return (EC_CPMAC|EC_FUNC_HAL_INIT|EC_VAL_MALLOC_FAILED);
++
++    /* clear the function pointers */
++    OsFunc->Memset(HalFunc, 0, sizeof(HAL_FUNCTIONS));
++
++    HalDev->OsDev   = OsDev;
++    HalDev->OsOpen  = OsDev;
++    HalDev->inst    = Inst;
++    HalDev->OsFunc  = OsFunc;
++    HalDev->HalFunc = HalFunc;
++    /* Remove the following from cppi, replace with HalFunc */
++    HalDev->HalFuncPtr = HalFunc; /* GSG 11/20 changed name to match cppi */
++
++    /****************************************************************/
++    /*                 POPULATE HALFUNC                             */
++    /****************************************************************/
++    HalFunc->ChannelSetup     = halChannelSetup;
++    HalFunc->ChannelTeardown  = halChannelTeardown; /* GSG 11/20 */
++    HalFunc->Close            = halClose; /* GSG 11/20 */
++    HalFunc->Control          = halControl; /* GSG 11/22 */
++    HalFunc->Init             = halInit;
++    HalFunc->Open             = halOpen;
++    HalFunc->PacketProcessEnd = halPacketProcessEnd;
++    HalFunc->Probe            = halProbe;
++    HalFunc->RxReturn         = halRxReturn;
++    HalFunc->Send             = halSend;
++    HalFunc->Shutdown         = halShutdown;
++    HalFunc->Tick             = halTick;
++
++    /* HalFunc->Status        = halStatus;*/ /* GSG 11/22 */
++    /* pass the HalDev and HalFunc back to the caller */
++
++    *pHalDev  = HalDev;
++    *pHalFunc = HalFunc;
++
++    HalDev->State = enConnected;   /* Initialize the hardware state */
++
++    if (HalDev->debug) HalDev->OsFunc->Printf("halCpmacInitModule: Leave\n");
++    return(0);
++  }
++
++int cpmacRandomRange(HAL_DEVICE *HalDev, int min, int max)
++{
++    int iTmp;
++    iTmp  = cpmacRandom(HalDev);
++    iTmp %= ((max-min)+1);
++    iTmp += min;
++    return(iTmp);
++}
++
++int cpmacRandom(HAL_DEVICE *HalDev)
++{
++    int iTmp;
++    iTmp = CPMAC_BOFFTEST(HalDev->dev_base);
++    iTmp >>= 16;      /*  get rndnum field */
++    iTmp &= (0x3FF); /* field is 10 bits wide */
++    return(iTmp);
++}
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/hcpmac.h linux-2.4.30/drivers/net/avalanche_cpmac/hcpmac.h
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/hcpmac.h     1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/hcpmac.h  2005-04-15 05:10:41.000000000 +0200
+@@ -0,0 +1,383 @@
++/** @file***********************************************************************
++ *  TNETDxxxx Software Support
++ *  Copyright (c) 2002 Texas Instruments Incorporated. All Rights Reserved.
++ *
++ *  FILE:
++ *
++ *  DESCRIPTION:
++ *      This file contains definitions for the HAL EMAC API
++ *
++ *  HISTORY:
++ *  xxXxx01 Denis      1.00  Original Version created.
++ *  22Jan02 Denis/Mick 1.01  Modified for HAL EMAC API
++ *  24Jan02 Denis/Mick 1.02  Speed Improvements
++ *  28Jan02 Denis/Mick 1.16  Made function calls pointers
++ *  28Jan02 Mick       1.18  Split into separate modules
++ *  @author Michael Hanrahan
++ *  @version 1.02
++ *  @date    24-Jan-2002
++ *****************************************************************************/
++#ifndef _INC_HCPMAC
++#define _INC_HCPMAC
++
++/** \namespace CPMAC_Version
++This documents version 01.07.04 of the CPMAC CPHAL.
++*/
++const char *pszVersion_CPMAC="CPMAC 01.07.08 "__DATE__" "__TIME__;
++
++/* CHECK THESE LOCATIONS */
++#define TEARDOWN_VAL       0xfffffffc
++#define CB_OFFSET_MASK     0xFFFF0000
++
++
++#define MAX_CHAN 8
++#define MAX_QUEUE 1
++
++typedef struct
++  {
++  bit32 HNext;      /*< Hardware's pointer to next buffer descriptor  */
++  bit32 BufPtr;     /*< Pointer to the data buffer                    */
++  bit32 Off_BLen;   /*< Contains buffer offset and buffer length      */
++  bit32 mode;       /*< SOP, EOP, Ownership, EOQ, Teardown, Q Starv, Length */
++  void *Next;
++  void *OsInfo;
++  void *Eop;
++#ifdef __CPHAL_DEBUG
++  bit32 DbgSop;
++  bit32 DbgData;
++  bit32 DbgFraglist;
++#endif
++  }HAL_TCB;
++
++typedef volatile struct hal_private
++  {
++  bit32 HNext;      /*< Hardware's pointer to next buffer descriptor     */
++  bit32 BufPtr;     /*< Pointer to the data buffer                       */
++  bit32 Off_BLen;   /*< Contains buffer offset and buffer length         */
++  bit32 mode;       /*< SOP, EOP, Ownership, EOQ, Teardown Complete bits */
++  void *DatPtr;
++  void *Next;
++  void *OsInfo;
++  void *Eop;
++  }HAL_RCB;
++
++#define MAX_NEEDS 512                                             /*MJH+030409*/
++/*  HAL  */
++
++typedef struct hal_device
++  {
++  OS_DEVICE *OsDev;
++  OS_FUNCTIONS *OsFunc;
++    /*OS_SETUP *OsSetup;*/                                     /* -GSG 030508 */
++  int inst;
++  bit32u rxbufseq;
++
++
++  bit32 dev_base;
++  bit32  offset;
++
++  bit32u ResetBase; /* GSG 10/20 */
++  int ResetBit;
++  void *OsOpen;
++  bit32u IntVec;
++  PHY_DEVICE *PhyDev;
++  bit32u EmacDuplex;
++  bit32u EmacSpeed;
++  bit32u PhyNum;
++  bit32u MLinkMask;
++  bit32u PhyMask;
++  bit32u MdixMask;
++
++  bit32u Linked;
++  DEVICE_STATE State;
++  unsigned char *MacAddr;
++  HAL_FUNCTIONS *HalFuncPtr; /* GSG 11/20 changed name to match cppi */
++  HAL_FUNCTIONS *HalFunc;
++/*  unsigned int CpuFreq;*/                                       /*MJH-030402*/
++  unsigned int MdioConnect;
++  unsigned int HostErr;
++
++/************************************************************************/
++/*                                                                      */
++/*      R E G I S T E R S                                               */
++/*                                                                      */
++/************************************************************************/
++
++  bit32u RxMbpEnable;
++  bit32u RxUnicastSet;
++  bit32u RxUnicastClear;
++  bit32u RxMaxLen;
++  bit32u RxFilterLowThresh;
++  bit32u Rx0FlowThresh;
++  bit32u MacControl;
++  bit32u MacStatus;
++  bit32u MacHash1;
++  bit32u MacHash2;
++
++/************************************************************************/
++/*                                                                      */
++/*      O P T I O N S                                                   */
++/*                                                                      */
++/************************************************************************/
++
++  char *DeviceInfo;
++  bit32u interrupt;
++
++
++  bit32u RxPassCrc;
++  bit32u RxCaf;
++  bit32u RxCef;
++  bit32u RxBcast;
++  bit32u RxBcastCh;
++  HAL_RCB *RcbPool[MAX_CHAN];
++  bit32 RxActQueueCount[MAX_CHAN];
++  HAL_RCB *RxActQueueHead[MAX_CHAN];
++  HAL_RCB *RxActQueueTail[MAX_CHAN];
++  bit32 RxActive[MAX_CHAN];
++  HAL_TCB *TcbPool[MAX_CHAN][MAX_QUEUE];
++  bit32 TxActQueueCount[MAX_CHAN][MAX_QUEUE];
++  HAL_TCB *TxActQueueHead[MAX_CHAN][MAX_QUEUE];
++  HAL_TCB *TxActQueueTail[MAX_CHAN][MAX_QUEUE];
++  bit32 TxActive[MAX_CHAN][MAX_QUEUE];
++  bit32 TxTeardownPending[MAX_CHAN];
++  bit32 RxTeardownPending[MAX_CHAN];
++  bit32 ChIsOpen[MAX_CHAN][2];
++  bit32 ChIsSetup[MAX_CHAN][2];
++  FRAGLIST *fraglist;
++  char *TcbStart[MAX_CHAN][MAX_QUEUE];
++  char *RcbStart[MAX_CHAN];
++  bit32 RcbSize[MAX_CHAN];
++/*  STAT_INFO Stats;  */
++  bit32  Inst;
++  bit32u BuffersServicedMax;
++  CHANNEL_INFO ChData[MAX_CHAN];
++  bit32u MdioClockFrequency;                                      /*MJH+030402*/
++  bit32u MdioBusFrequency;                                        /*MJH+030402*/
++  bit32u CpuFrequency;                                            /*MJH+030402*/
++  bit32u CpmacFrequency;                                          /*MJH+030403*/
++  bit32u CpmacSize;                                               /*MJH+030425*/
++  int debug;
++  bit32u NeedsCount;                                              /*MJH+030409*/
++  HAL_RECEIVEINFO *Needs[MAX_NEEDS];                              /*MJH+030409*/
++  int MaxFrags;
++  int TxIntThreshold[MAX_CHAN];                   /* MJH 040621  NSP Performance Update */
++  int TxIntThresholdMaster[MAX_CHAN];             /* MJH 040827  NSP Performance Update */
++  int TxIntDisable;                     /* MJH 040621  NSP Performance Update */  
++  }HALDEVICE;
++
++#define STATS_MAX 36
++
++#define MACCONTROL_MASK    (TX_PTYPE|TX_PACE|TX_FLOW_EN|RX_FLOW_EN|CTRL_LOOPBACK)
++#define RX_MBP_ENABLE_MASK                                       \
++        (RX_PASS_CRC|RX_QOS_EN|RX_NO_CHAIN|                      \
++         RX_CMF_EN|RX_CSF_EN|RX_CEF_EN|RX_CAF_EN|RX_PROM_CH_MASK|     \
++         RX_BROAD_EN|RX_BROAD_CH_MASK|RX_MULT_EN|RX_MULT_CH_MASK)
++
++
++#define MBP_UPDATE(Mask, On)                      \
++         if(On)   HalDev->RxMbpEnable |=  Mask;   \
++         else     HalDev->RxMbpEnable &= ~Mask
++
++#define CONTROL_UPDATE(Mask, On)                  \
++         if(On)   HalDev->MacControl |=  Mask;    \
++         else     HalDev->MacControl &= ~Mask
++
++
++#define UPDATE_TX_PTYPE(Value)       CONTROL_UPDATE(TX_PTYPE,Value)
++#define UPDATE_TX_PACE(Value)        CONTROL_UPDATE(TX_PACE,Value)
++#define UPDATE_MII_EN(Value)         CONTROL_UPDATE(MII_EN,Value)
++#define UPDATE_TX_FLOW_EN(Value)     CONTROL_UPDATE(TX_FLOW_EN,Value)
++#define UPDATE_RX_FLOW_EN(Value)     CONTROL_UPDATE(RX_FLOW_EN,Value)
++#define UPDATE_CTRL_LOOPBACK(Value)  CONTROL_UPDATE(CTRL_LOOPBACK,Value)
++#define UPDATE_FULLDUPLEX(Value)     CONTROL_UPDATE(FULLDUPLEX,(Value))
++
++#define UPDATE_RX_PASS_CRC(Value)    MBP_UPDATE(RX_PASS_CRC,  Value)
++#define UPDATE_RX_QOS_EN(Value)      MBP_UPDATE(RX_QOS_EN,    Value)
++#define UPDATE_RX_NO_CHAIN(Value)    MBP_UPDATE(RX_NO_CHAIN,  Value)
++#define UPDATE_RX_CMF_EN(Value)      MBP_UPDATE(RX_CMF_EN,    Value)
++#define UPDATE_RX_CSF_EN(Value)      MBP_UPDATE(RX_CSF_EN,    Value)
++#define UPDATE_RX_CEF_EN(Value)      MBP_UPDATE(RX_CEF_EN,    Value)
++#define UPDATE_RX_CAF_EN(Value)      MBP_UPDATE(RX_CAF_EN,    Value)
++#define UPDATE_RX_BROAD_EN(Value)    MBP_UPDATE(RX_BROAD_EN,  Value)
++#define UPDATE_RX_MULT_EN(Value)     MBP_UPDATE(RX_MULT_EN,   Value)
++
++#define UPDATE_RX_PROM_CH(Value)                         \
++        HalDev->RxMbpEnable &=  ~RX_PROM_CH_MASK;        \
++        HalDev->RxMbpEnable |=   RX_PROM_CH(Value)
++
++#define UPDATE_RX_BROAD_CH(Value)                        \
++           HalDev->RxMbpEnable &=  ~RX_BROAD_CH_MASK;    \
++           HalDev->RxMbpEnable |=   RX_BROAD_CH(Value)
++
++#define UPDATE_RX_MULT_CH(Value)                         \
++           HalDev->RxMbpEnable &=  ~RX_MULT_CH_MASK;     \
++           HalDev->RxMbpEnable |=   RX_MULT_CH(Value)
++
++
++
++typedef enum
++  {
++   /*  CPMAC */
++    enCpmacStart=0,
++    enStats0,
++    enStats1,
++    enStats2,
++    enStats3,
++    enStats4,
++    enStatsDump,
++    enStatsClear,
++    enRX_PASS_CRC,
++    enRX_QOS_EN,
++    enRX_NO_CHAIN,
++    enRX_CMF_EN,
++    enRX_CSF_EN,
++    enRX_CEF_EN,
++    enRX_CAF_EN,
++    enRX_PROM_CH,
++    enRX_BROAD_EN,
++    enRX_BROAD_CH,
++    enRX_MULT_EN,
++    enRX_MULT_CH,
++
++    enTX_PTYPE,
++    enTX_PACE,
++    enMII_EN,
++    enTX_FLOW_EN,
++    enRX_FLOW_EN,
++    enCTRL_LOOPBACK,
++
++    enRX_MAXLEN,
++    enRX_FILTERLOWTHRESH,
++    enRX0_FLOWTHRESH,
++    enRX_UNICAST_SET,
++    enRX_UNICAST_CLEAR,
++    enMdioConnect,
++    enMAC_ADDR_GET,
++    enTick,
++    enRX_MULTICAST,
++    enRX_MULTI_ALL,
++    enRX_MULTI_SINGLE,
++    enVersion,
++    enCpmacEnd                                   /* Last entry */
++  }INFO_KEY_CPMAC;
++
++static const char pszVersion[]                 = "Version";
++static const char pszStats0[]                  = "Stats0";
++static const char pszStats1[]                  = "Stats1";
++static const char pszStats2[]                  = "Stats2";
++static const char pszStats3[]                  = "Stats3";
++static const char pszStats4[]                  = "Stats4";
++static const char pszStatsDump[]               = "StatsDump";
++static const char pszStatsClear[]              = "StatsClear";
++
++/********************************************************************
++**
++**  RX MBP ENABLE
++**
++********************************************************************/
++static const char pszRX_PASS_CRC[]             = "RX_PASS_CRC";
++static const char pszRX_QOS_EN[]               = "RX_QOS_EN";
++static const char pszRX_NO_CHAIN[]             = "RX_NO_CHAIN";
++static const char pszRX_CMF_EN[]               = "RX_CMF_EN";
++static const char pszRX_CSF_EN[]               = "RX_CSF_EN";
++static const char pszRX_CEF_EN[]               = "RX_CEF_EN";
++static const char pszRX_CAF_EN[]               = "RX_CAF_EN";
++static const char pszRX_PROM_CH[]              = "RX_PROM_CH";
++static const char pszRX_BROAD_EN[]             = "RX_BROAD_EN";
++static const char pszRX_BROAD_CH[]             = "RX_BROAD_CH";
++static const char pszRX_MULT_EN[]              = "RX_MULT_EN";
++static const char pszRX_MULT_CH[]              = "RX_MULT_CH";
++
++
++/********************************************************************
++**
++**  MAC CONTROL
++**
++********************************************************************/
++static const char pszTX_PTYPE[]                = "TX_PTYPE";
++static const char pszTX_PACE[]                 = "TX_PACE";
++static const char pszMII_EN[]                  = "MII_EN";
++static const char pszTX_FLOW_EN[]              = "TX_FLOW_EN";
++static const char pszRX_FLOW_EN[]              = "RX_FLOW_EN";
++static const char pszCTRL_LOOPBACK[]           = "CTRL_LOOPBACK";
++
++static const char pszRX_MAXLEN[]               = "RX_MAXLEN";
++static const char pszRX_FILTERLOWTHRESH[]      = "RX_FILTERLOWTHRESH";
++static const char pszRX0_FLOWTHRESH[]          = "RX0_FLOWTHRESH";
++static const char pszRX_UNICAST_SET[]          = "RX_UNICAST_SET";
++static const char pszRX_UNICAST_CLEAR[]        = "RX_UNICAST_CLEAR";
++static const char pszMdioConnect[]             = "MdioConnect";
++static const char pszMacAddr[]                 = "MacAddr";
++static const char pszTick[]                    = "Tick";
++
++/********************************************************************
++**
++**  MULTICAST
++**
++********************************************************************/
++
++static const char pszRX_MULTICAST[]            = "RX_MULTICAST";
++static const char pszRX_MULTI_ALL[]            = "RX_MULTI_ALL";
++static const char pszRX_MULTI_SINGLE[]         = "RX_MULTI_SINGLE";
++
++/*
++static const char* pszGFHN = "GFHN";
++*/
++
++static const CONTROL_KEY KeyCpmac[] =
++   {
++     {""                           , enCpmacStart},
++     {pszStats0                    , enStats0},
++     {pszStats1                    , enStats1},
++     {pszStats2                    , enStats2},
++     {pszStats3                    , enStats3},
++     {pszStats4                    , enStats4},
++     {pszStatsClear                , enStatsClear},
++     {pszStatsDump                 , enStatsDump},
++     {pszRX_PASS_CRC               , enRX_PASS_CRC},
++     {pszRX_QOS_EN                 , enRX_QOS_EN},
++     {pszRX_NO_CHAIN               , enRX_NO_CHAIN},
++     {pszRX_CMF_EN                 , enRX_CMF_EN},
++     {pszRX_CSF_EN                 , enRX_CSF_EN},
++     {pszRX_CEF_EN                 , enRX_CEF_EN},
++     {pszRX_CAF_EN                 , enRX_CAF_EN},
++     {pszRX_PROM_CH                , enRX_PROM_CH},
++     {pszRX_BROAD_EN               , enRX_BROAD_EN},
++     {pszRX_BROAD_CH               , enRX_BROAD_CH},
++     {pszRX_MULT_EN                , enRX_MULT_EN},
++     {pszRX_MULT_CH                , enRX_MULT_CH},
++
++     {pszTX_PTYPE                  , enTX_PTYPE},
++     {pszTX_PACE                   , enTX_PACE},
++     {pszMII_EN                    , enMII_EN},
++     {pszTX_FLOW_EN                , enTX_FLOW_EN},
++     {pszRX_FLOW_EN                , enRX_FLOW_EN},
++     {pszCTRL_LOOPBACK             , enCTRL_LOOPBACK},
++     {pszRX_MAXLEN                 , enRX_MAXLEN},
++     {pszRX_FILTERLOWTHRESH        , enRX_FILTERLOWTHRESH},
++     {pszRX0_FLOWTHRESH            , enRX0_FLOWTHRESH},
++     {pszRX_UNICAST_SET            , enRX_UNICAST_SET},
++     {pszRX_UNICAST_CLEAR          , enRX_UNICAST_CLEAR},
++     {pszMdioConnect               , enMdioConnect},
++     {pszRX_MULTICAST              , enRX_MULTICAST},
++     {pszRX_MULTI_ALL              , enRX_MULTI_ALL},
++     {pszRX_MULTI_SINGLE           , enRX_MULTI_SINGLE},
++     {pszTick                      , enTick},
++     {pszVersion                   , enVersion},
++     {""                           , enCpmacEnd}
++   };
++
++const char hcCpuFrequency[]       = "CpuFreq";
++const char hcCpmacFrequency[]     = "CpmacFrequency";
++const char hcMdioBusFrequency[]   = "MdioBusFrequency";
++const char hcMdioClockFrequency[] = "MdioClockFrequency";
++const char hcCpmacBase[]          = "CpmacBase";
++const char hcPhyNum[]             = "PhyNum";
++const char hcSize[]               = "size";
++const char hcCpmacSize[]          = "CpmacSize";
++const char hcPhyAccess[]          = "PhyAccess";
++const char hcLinked[]             = "Linked";
++const char hcFullDuplex[]         = "FullDuplex";
++const char hcMdixMask[]           = "MdixMask";
++const char hcMdioMdixSwitch[]     = "MdixSet";
++#endif
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/Makefile linux-2.4.30/drivers/net/avalanche_cpmac/Makefile
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/Makefile     1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/Makefile  2005-04-15 05:10:40.000000000 +0200
+@@ -0,0 +1,26 @@
++# File: drivers/net/avalanche_cpmac/Makefile
++#
++# Makefile for the Linux network (CPMAC) device drivers.
++#
++
++O_TARGET := avalanche_cpmac.o
++
++
++list-multi := avalanche_cpmac.o
++obj-$(CONFIG_MIPS_AVALANCHE_CPMAC) := avalanche_cpmac.o
++
++avalanche_cpmac-objs += cpmac.o            cpmacHalLx.o       hcpmac.o \
++                                    psp_config_build.o psp_config_mgr.o            \
++                                    psp_config_parse.o psp_config_util.o
++
++
++include $(TOPDIR)/Rules.make
++
++
++avalanche_cpmac.o:        $(avalanche_cpmac-objs)
++      $(LD) -r -o $@ $(avalanche_cpmac-objs)
++
++
++
++clean:
++      rm -f core *.o *.a *.s
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/mdio_reg.h linux-2.4.30/drivers/net/avalanche_cpmac/mdio_reg.h
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/mdio_reg.h   1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/mdio_reg.h        2005-07-08 22:08:44.964969914 +0200
+@@ -0,0 +1,121 @@
++/****************************************************************************
++**      TNETD53xx Software Support
++**      Copyright(c) 2002, Texas Instruments Incorporated. All Rights Reserved.
++**
++**      FILE: mdio_reg.h   Register definitions for the VBUS MII module
++**
++**      DESCRIPTION:
++**              This include file contains register definitions for the
++**              VBUS MII module.
++**
++**      HISTORY:
++**              27Mar02 Michael Hanrahan Original (modified from emacmdio.h)
++**              01Apr02 Michael Hanrahan Modified to include all regs. in spec
++**              03Apr02 Michael Hanrahan Updated to Version 0.6 of spec
++**              05Apr02 Michael Hanrahan Moved Phy Mode values into here
++**              30Apr02 Michael Hanrahan Updated to Version 0.8 of spec
++**              30Apr02 Michael Hanrahan Updated to recommended format
++**              10May02 Michael Hanrahan Updated to Version 0.9 of spec
++*****************************************************************************/
++#ifndef _INC_MDIO_REG
++#define _INC_MDIO_REG
++
++/***************************************************************************
++**                                                                         
++**         M D I O  M E M O R Y  M A P 
++**                                                                         
++***************************************************************************/
++
++
++#define pMDIO_VER(base)                 ((volatile bit32u *)(base+0x00))
++#define pMDIO_CONTROL(base)             ((volatile bit32u *)(base+0x04))
++#define pMDIO_ALIVE(base)               ((volatile bit32u *)(base+0x08))
++#define pMDIO_LINK(base)                ((volatile bit32u *)(base+0x0C))
++#define pMDIO_LINKINTRAW(base)          ((volatile bit32u *)(base+0x10))
++#define pMDIO_LINKINTMASKED(base)       ((volatile bit32u *)(base+0x14))
++#define pMDIO_USERINTRAW(base)          ((volatile bit32u *)(base+0x20))
++#define pMDIO_USERINTMASKED(base)       ((volatile bit32u *)(base+0x24))
++#define pMDIO_USERINTMASKED_SET(base)   ((volatile bit32u *)(base+0x28))
++#define pMDIO_USERINTMASKED_CLR(base)   ((volatile bit32u *)(base+0x2C))
++#define pMDIO_USERACCESS(base, channel) ((volatile bit32u *)(base+(0x80+(channel*8))))
++#define pMDIO_USERPHYSEL(base, channel) ((volatile bit32u *)(base+(0x84+(channel*8))))
++
++
++/***************************************************************************
++**                                                                         
++**         M D I O  R E G I S T E R  A C C E S S  M A C R O S 
++**                                                                         
++***************************************************************************/
++
++
++#define MDIO_ALIVE(base)                    (*(pMDIO_ALIVE(base)))
++#define MDIO_CONTROL(base)                  (*(pMDIO_CONTROL(base)))
++#define         MDIO_CONTROL_IDLE                 (1 << 31)
++#define         MDIO_CONTROL_ENABLE               (1 << 30)
++#define         MDIO_CONTROL_PREAMBLE             (1 << 20)  
++#define         MDIO_CONTROL_FAULT                (1 << 19)
++#define         MDIO_CONTROL_FAULT_DETECT_ENABLE  (1 << 18)
++#define         MDIO_CONTROL_INT_TEST_ENABLE      (1 << 17)
++#define         MDIO_CONTROL_HIGHEST_USER_CHANNEL (0x1F << 8)
++#define         MDIO_CONTROL_CLKDIV               (0xFF)
++#define MDIO_LINK(base)                     (*(pMDIO_LINK(base)))
++#define MDIO_LINKINTRAW(base)               (*(pMDIO_LINKINTRAW(base)))
++#define MDIO_LINKINTMASKED(base)            (*(pMDIO_LINKINTMASKED(base)))
++#define MDIO_USERINTRAW(base)               (*(pMDIO_USERINTRAW(base)))
++#define MDIO_USERINTMASKED(base)            (*(pMDIO_USERINTMASKED(base)))
++#define MDIO_USERINTMASKED_CLR(base)        (*(pMDIO_USERINTMASKED_CLR(base)))
++#define MDIO_USERINTMASKED_SET(base)        (*(pMDIO_USERINTMASKED_SET(base)))
++#define MDIO_USERINTRAW(base)               (*(pMDIO_USERINTRAW(base)))
++#define MDIO_USERACCESS(base, channel)      (*(pMDIO_USERACCESS(base, channel)))
++#define         MDIO_USERACCESS_GO     (1 << 31)
++#define         MDIO_USERACCESS_WRITE  (1 << 30)
++#define         MDIO_USERACCESS_READ   (0 << 30)
++#define         MDIO_USERACCESS_ACK    (1 << 29)
++#define         MDIO_USERACCESS_REGADR (0x1F << 21)
++#define         MDIO_USERACCESS_PHYADR (0x1F << 16)
++#define         MDIO_USERACCESS_DATA   (0xFFFF)
++#define MDIO_USERPHYSEL(base, channel)      (*(pMDIO_USERPHYSEL(base, channel)))
++#define         MDIO_USERPHYSEL_LINKSEL         (1 << 7)
++#define         MDIO_USERPHYSEL_LINKINT_ENABLE  (1 << 6)
++#define         MDIO_USERPHYSEL_PHYADR_MON      (0x1F)
++#define MDIO_VER(base)                      (*(pMDIO_VER(base)))
++#define         MDIO_VER_MODID         (0xFFFF << 16)
++#define         MDIO_VER_REVMAJ        (0xFF   << 8)
++#define         MDIO_VER_REVMIN        (0xFF)
++
++
++
++
++/****************************************************************************/
++/*                                                                          */
++/*         P H Y   R E G I S T E R  D E F I N I T I O N S                   */
++/*                                                                          */
++/****************************************************************************/
++
++
++#define PHY_CONTROL_REG       0
++  #define PHY_RESET           (1<<15)
++  #define PHY_LOOP            (1<<14)
++  #define PHY_100             (1<<13)
++  #define AUTO_NEGOTIATE_EN   (1<<12)
++  #define PHY_PDOWN           (1<<11)
++  #define PHY_ISOLATE         (1<<10)
++  #define RENEGOTIATE         (1<<9)
++  #define PHY_FD              (1<<8)
++
++#define PHY_STATUS_REG        1
++  #define NWAY_COMPLETE       (1<<5)
++  #define NWAY_CAPABLE        (1<<3)
++  #define PHY_LINKED          (1<<2)
++
++#define NWAY_ADVERTIZE_REG    4
++#define NWAY_REMADVERTISE_REG 5
++  #define NWAY_FD100          (1<<8)
++  #define NWAY_HD100          (1<<7)
++  #define NWAY_FD10           (1<<6)
++  #define NWAY_HD10           (1<<5)
++  #define NWAY_SEL            (1<<0)
++  #define NWAY_AUTO           (1<<0)
++
++
++#endif _INC_MDIO_REG
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/psp_config_build.c linux-2.4.30/drivers/net/avalanche_cpmac/psp_config_build.c
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/psp_config_build.c   1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/psp_config_build.c        2005-07-08 22:09:17.761928277 +0200
+@@ -0,0 +1,336 @@
++/******************************************************************************
++ * FILE PURPOSE:    PSP Config Manager - Configuration Build Source
++ ******************************************************************************
++ * FILE NAME:       psp_config_build.c
++ *
++ * DESCRIPTION:     Configuration Build API Implementation
++ *
++ * REVISION HISTORY:
++ * 27 Nov 02 - PSP TII  
++ *
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++
++#ifdef INCLUDE_FFS
++#include "ffs.h"
++#endif /* INCLUDE_FFS */
++
++#include "psp_config_mgr.h"
++#include "psp_config_build.h"
++#include "psp_config_util.h"
++
++#define MAX_DEVICE_NAME_LEN     16
++#define MAX_DEVICE_STR_LEN      512
++
++#ifndef NULL
++#define NULL (char *)0
++#endif
++
++#include <asm/ar7/avalanche_misc.h>
++#include <asm/ar7/sangam.h>
++#include <linux/slab.h>
++#include <linux/config.h>
++
++
++#define os_malloc(size) kmalloc(size, GFP_KERNEL)
++
++int psp_run_enumerator(void)
++{
++    return(0);
++}
++
++#if defined (CONFIG_AVALANCHE_CPMAC_AUTO)
++
++static int auto_detect_cpmac_phy(void)
++{
++
++#define SELECT_INT_PHY_MAC 0
++#define SELECT_EXT_PHY_MAC 1
++
++    volatile unsigned long *reset_cntl = AVALANCHE_RESET_CONTROL_BASE, *mdio_cntl  = ((int)AVALANCHE_MDIO_BASE + 0x4);
++    unsigned int j= 0, detected_phy_map = 0, auto_select = SELECT_INT_PHY_MAC;
++                                                                                                                   
++    *reset_cntl |= (1 << AVALANCHE_MDIO_RESET_BIT) | (1 << AVALANCHE_LOW_CPMAC_RESET_BIT) | (1 << AVALANCHE_HIGH_CPMAC_RESET_BIT) | (1 << AVALANCHE_LOW_EPHY_RESET_BIT);                                 
++    *mdio_cntl   = (1 << 30) | (avalanche_get_vbus_freq()/2200000);                                              
++                                                                                                                   
++    for(j=0;j < 300000; j++) 
++    { 
++        if(j%100000) continue;
++
++        detected_phy_map = *(mdio_cntl + 1);
++        if(detected_phy_map) 
++        {
++            detected_phy_map &= ~AVALANCHE_LOW_CPMAC_PHY_MASK;
++                
++            if(detected_phy_map && !(detected_phy_map & (detected_phy_map - 1)))
++            {
++                auto_select = SELECT_EXT_PHY_MAC;
++                break;
++            }
++        } 
++    }
++
++    return(auto_select);
++
++}
++
++#endif
++
++
++#ifndef AVALANCHE_LOW_CPMAC_MDIX_MASK
++#define AVALANCHE_LOW_CPMAC_MDIX_MASK 0
++#endif
++
++void psp_load_default_static_cfg(void)
++{
++    char s2[100],  s3[100];
++    char s4[2000], s6[2000];
++    int threshold = 20;
++    char *tx_threshold_ptr = prom_getenv("threshold");
++    
++    if(tx_threshold_ptr)
++      threshold = simple_strtol(tx_threshold_ptr, (char **)NULL, 10);
++
++    /* Static configuration if options.conf not present */
++    sprintf(s3,"cpmdio(id=mii, base=%u, reset_bit=%d)", AVALANCHE_MDIO_BASE, 22);
++    sprintf(s2, "reset( id=[ResetRegister], base=%u)", AVALANCHE_RESET_CONTROL_BASE);
++
++    sprintf(s4, "cpmac(id=[cpmac], unit=0, base=%u, size=0x800, reset_bit=%d, PhyMask=%u, MdixMask=%u, MLink=0, int_line=%d, memory_offset=0, RX_CAF=1, RX_PASSCRC=0, RX_CEF=1, RX_BCAST=0, RX_BCASTCH=0, Ch0=[TxNumBuffers=256, TxNumQueues=1, TxServiceMax=%d, RxNumBuffers=256, RxBufferOffset=0, RxBufSize=1000, RxServiceMax=128], Ch1=[TxNumBuffers=256, TxNumQueues=1, TxServiceMax=%d, RxNumBuffers=256, RxBufferOffset=0, RxBufSize=1000, RxServiceMax=128], Ch2=[TxNumBuffers=256, TxNumQueues=1, TxServiceMax=%d, RxNumBuffers=256, RxBufferOffset=0, RxBufSize=1000, RxServiceMax=128])", AVALANCHE_LOW_CPMAC_BASE, AVALANCHE_LOW_CPMAC_RESET_BIT, AVALANCHE_LOW_CPMAC_PHY_MASK, AVALANCHE_LOW_CPMAC_MDIX_MASK, AVALANCHE_LOW_CPMAC_INT,threshold,threshold,threshold);
++
++    sprintf(s6, "cpmac(id=[cpmac], unit=1, base=%u, size=0x800, reset_bit=%d, PhyMask=%u, MLink=0, int_line=%d, memory_offset=0, RX_CAF=1, RX_PASSCRC=0, RX_CEF=1, RX_BCAST=0, RX_BCASTCH=0, Ch0=[TxNumBuffers=256, TxNumQueues=1, TxServiceMax=%d, RxNumBuffers=256, RxBufferOffset=0, RxBufSize=1000, RxServiceMax=128], Ch1=[TxNumBuffers=256, TxNumQueues=1, TxServiceMax=%d, RxNumBuffers=256, RxBufferOffset=0, RxBufSize=1000, RxServiceMax=128], Ch2=[TxNumBuffers=256, TxNumQueues=1, TxServiceMax=%d, RxNumBuffers=256, RxBufferOffset=0, RxBufSize=1000, RxServiceMax=128])", AVALANCHE_HIGH_CPMAC_BASE, AVALANCHE_HIGH_CPMAC_RESET_BIT, AVALANCHE_HIGH_CPMAC_PHY_MASK, AVALANCHE_HIGH_CPMAC_INT,threshold,threshold,threshold);
++
++    psp_config_add("reset", s2, psp_config_strlen(s2), en_compile);
++
++
++#if defined (CONFIG_AVALANCHE_LOW_CPMAC)
++
++    psp_config_add("cpmdio", s3, psp_config_strlen(s3), en_compile);
++    psp_config_add("cpmac", s4, psp_config_strlen(s4), en_compile);
++
++#endif
++
++
++#if defined (CONFIG_AVALANCHE_HIGH_CPMAC)
++
++    psp_config_add("cpmdio", s3, psp_config_strlen(s3), en_compile);
++    psp_config_add("cpmac", s6, psp_config_strlen(s6), en_compile);
++
++#endif
++
++#if defined (CONFIG_AVALANCHE_CPMAC_AUTO)
++    { 
++        char *phy_sel_ptr = prom_getenv("mac_phy_sel"); 
++        int   phy_sel = SELECT_EXT_PHY_MAC;
++        char *mac_port = prom_getenv("MAC_PORT"); /* Internal: 0, External: 1 */
++
++        if(phy_sel_ptr && (0 == strcmp(phy_sel_ptr, "int")))
++        {
++            phy_sel = SELECT_INT_PHY_MAC;
++        }
++
++        //if(phy_sel == auto_detect_cpmac_phy())
++        if(!mac_port || (0 != strcmp(mac_port, "0")))
++        {
++            printk("Using the MAC with external PHY\n");
++            psp_config_add("cpmdio", s3, psp_config_strlen(s3), en_compile);
++            psp_config_add("cpmac", s6, psp_config_strlen(s6), en_compile);
++        }
++        else
++        {
++            printk("Using the MAC with internal PHY\n");
++            psp_config_add("cpmdio", s3, psp_config_strlen(s3), en_compile);
++            psp_config_add("cpmac", s4, psp_config_strlen(s4), en_compile);
++        }
++    }
++                      
++#endif    
++
++}
++
++char* psp_conf_read_file(char *p_file_name)
++{
++#ifdef INCLUDE_FFS
++    
++    char        *p_file_data = NULL;
++    unsigned int file_size;
++    FFS_FILE    *p_file = NULL;
++
++    if(p_file_name == NULL)
++    {
++        return (NULL);
++    }
++
++    if(!(p_file = ffs_fopen(p_file_name, "r"))) 
++    {
++        return(NULL);
++    }
++
++    file_size = p_file->_AvailableBytes;
++
++    p_file_data = os_malloc(file_size + 1);
++    
++    if(ffs_fread(p_file_data, file_size, 1, p_file) == 0)
++    {
++        kfree(p_file_data);
++        return(NULL);
++    }
++
++    ffs_fclose(p_file);
++   
++    p_file_data[file_size] = '\0';
++
++    return(p_file_data);
++    
++#else /* NO FFS */
++    return(NULL);
++#endif /* INCLUDE_FFS */
++}
++
++int psp_conf_get_line(char *p_in_data, char **next_line)
++{
++    char *p       = p_in_data;
++
++    while(*p && *p++ != '\n')
++    {
++
++    } 
++   
++    *next_line = p;
++
++    return(p - 1 - p_in_data);
++}
++
++
++int psp_conf_is_data_line(char *line)
++{
++    int ret_val = 1;
++
++    if(*line == '\0' || *line == '\n' || *line == '#')
++        ret_val = 0;
++
++    return(ret_val);
++}
++
++int psp_conf_get_key_size(char *data)
++{
++    char *p = data;
++
++    while(*p && *p != '\n' && *p != '(' && *p != ' ')
++        p++;
++
++    return(p - data);
++}
++
++char* psp_conf_eat_white_spaces(char *p)
++{
++    while(*p && *p != '\n' && *p == ' ')
++        p++;
++
++    return (p);
++}
++
++int psp_build_from_opt_conf(void)
++{
++    char *data       = NULL;
++    char *data_hold  = NULL;
++    char *next_line  = NULL; 
++    int  line_size   = 0;
++
++    if((data = psp_conf_read_file("/etc/options.conf")) == NULL)
++        return(-1);
++
++    data_hold = data;
++
++    while((line_size=psp_conf_get_line(data, &next_line)) != -1)
++    {
++
++        char *name = NULL;
++        int  name_size; 
++ 
++    data = psp_conf_eat_white_spaces(data);
++
++        if(psp_conf_is_data_line(data))
++        {
++            data[line_size] = '\0';
++ 
++            name_size = psp_conf_get_key_size(data);
++           
++            if(name_size > 0) 
++            {
++                name = (char *) os_malloc(name_size + 1);
++                if(name == NULL) break;
++
++                psp_config_memcpy(name, data, name_size);
++                name[name_size] = '\0';
++
++                psp_config_add(name, data, line_size, en_opt_conf);
++            
++                kfree(name);
++            }
++
++            data[line_size] = '\n';
++        }
++
++        data = next_line;
++    }
++
++    kfree(data_hold);
++    return (0);
++}
++
++
++int psp_write_conf_file(char *p_write_file, char * dev_cfg_string)
++{
++#ifdef INCLUDE_FFS
++    int bytes_written=0;
++        FFS_FILE *file_ptr=NULL;    
++ 
++    /*
++     * NOTE: In current implementation of FFS in ADAM2 if the file exists beforehand, it
++     * can't be opened for write.
++     */
++        if(!(file_ptr=ffs_fopen(p_write_file, "w"))) {
++        return(-1);
++        }
++    
++    /* Write into the file "output.con" the character string */
++    /* write a \n before a writing a line */
++    if(!(bytes_written = ffs_fwrite("\n", 1, sizeof(char), file_ptr))) {
++        return (-1);
++    }
++    
++    if(!(bytes_written = ffs_fwrite(dev_cfg_string, psp_config_strlen(dev_cfg_string), sizeof(char), file_ptr))) {
++        return (-1);        
++    }
++    ffs_fclose(file_ptr);
++    return (bytes_written+1);
++#else /* NO FFS */
++    return(-1);
++#endif /* INCLUDE_FFS */
++}
++
++void build_psp_config(void)
++{
++
++    /* initialize the repository. */
++    psp_config_init();
++    
++#ifdef INCLUDE_FFS
++    ffs_init();
++#endif /* INCLUDE_FFS */
++
++    /* read the configuration from the options.conf to override default ones */
++    psp_build_from_opt_conf();
++
++    /* read the configuration which were not over ridden in options.conf */
++    psp_load_default_static_cfg();
++
++    /* let the vlynq be enumerated. Enumerator will add cfg info
++       of the discovered device instances to the repository.*/
++    psp_run_enumerator();
++
++    /* dump the repository*/
++    dump_device_cfg_pool();
++
++}
++
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/psp_config_build.h linux-2.4.30/drivers/net/avalanche_cpmac/psp_config_build.h
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/psp_config_build.h   1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/psp_config_build.h        2005-04-15 05:10:41.000000000 +0200
+@@ -0,0 +1,138 @@
++/******************************************************************************
++ * FILE PURPOSE:    PSP Config Manager - Configuration Build Header
++ ******************************************************************************
++ * FILE NAME:       psp_config_build.h
++ *
++ * DESCRIPTION:     Configuration Build API's.
++ *
++ * REVISION HISTORY:
++ * 27 Nov 02 - PSP TII  
++ *
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++
++#ifndef __PSP_CONF_BUILD_H__
++#define __PSP_CONF_BUILD_H__
++
++/*------------------------------------------------------------------------------
++ * Name: psp_conf_read_file
++ *
++ * Parameters: 
++ *         in: p_file_name - the name of the file to read from.
++ *
++ * Description:
++ *     Reads the entire file in one shot. This function opens  the 
++ *     file, determines the size of the data to be read, allocates 
++ *     the required memory, NULL terminates the data and closes the
++ *     file.
++ *
++ *     It is responsibily of the callee to free the memory after it is
++ *     done with that data.
++ *    
++ *
++ * Returns:
++ *     A NULL pointer, if failed to read the data otherwise, a valid
++ *     pointer referring to the data read from the file.
++ *
++ * Example: 
++ *   
++ *     psp_conf_read_file("/etc/options.conf");
++ *---------------------------------------------------------------------------*/
++ char *psp_conf_read_file(char *p_file_name);
++
++ /*----------------------------------------------------------------------------
++  * Function : psp_conf_write_file
++  *
++  * Parameters:
++  *         in: p_file_name - the file to which data is to be written.
++  *         in: data        - the NULL terminated data string.
++  *
++  * Description:
++  *     Write the indicated data into the file. This function opens the file,
++  *     appends the data to end of the file, closes the file. 
++  *
++  * Returns:
++  *
++  *     The number of bytes on success. 
++  *     0 on failure.
++  *
++  * Example:
++  *
++  *     psp_conf_write_file("/etc/outcon.conf", data);
++  *--------------------------------------------------------------------------*/
++ int   psp_conf_write_file(char *p_file_name, char *data);
++
++ /*----------------------------------------------------------------------------
++  * Function: psp_conf_get_line
++  *
++  * Parameters:
++  *         in: data      - the data from which the line is to identified.
++  *        out: next_line - the pointer to start of the next line. 
++  *
++  * Description:
++  *     Expects the data to be '\n' separated segments and data is NULL 
++  *     terminated. Parses the given data for '\n' or '\0'. Provides a pointer
++  *     to the start of next line in the next_line. 
++  *
++  * Returns:
++  *     -1 on error.
++  *      0 or more to indicate the number of bytes in the line starting at 
++  *      data.
++  *--------------------------------------------------------------------------*/
++ int psp_get_conf_line(char *p_in_data, char **next_line);
++
++ /*----------------------------------------------------------------------------
++  * Function: psp_conf_is_data_line
++  *
++  * Parameters:
++  *         in: line - the array of bytes.
++  *
++  * Description:
++  *     Tests the first byte in the array for '\0' or '\n' or '#'. Lines 
++  *     starting with these characters are not considered data.
++  *
++  * Returns:
++  *     1 if the line has data.
++  *     0 otherwise.
++  *
++  *--------------------------------------------------------------------------*/
++ int psp_conf_is_data_line(char *line);
++
++ /*----------------------------------------------------------------------------
++  * Function: psp_conf_eat_white_spaces
++  *
++  * Parameters:
++  *         in: line - the array of bytes.
++  *
++  * Description:
++  *     Eats white spaces at the begining of the line while looking out for 
++  *     '\0' or '\n' or ' '.
++  * 
++  * Returns:
++  *     Pointer to the begining of the non white space character. 
++  *     NULL if '\0' or '\n' is found.
++  *
++  *--------------------------------------------------------------------------*/
++  char *psp_conf_eat_white_spaces(char *line);
++
++  /*---------------------------------------------------------------------------
++   * Function: psp_conf_get_key_size
++   *
++   * Parameters:
++   *         in: line - the array of bytes.
++   *
++   * Description:
++   *     Identifies the size of the 'key' in array formatted as 
++   *     key(id=[key1]....). This function also checks out for '\0' and '\n'.
++   *
++   * Returns:
++   *     On success, The number of bytes that forms the key. 
++   *     0 otherwise. 
++   *     
++   *-------------------------------------------------------------------------*/
++  int psp_conf_get_key_size(char *line);
++
++
++
++#endif /* __PSP_CONF_BUILD_H__ */
++
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/psp_config_mgr.c linux-2.4.30/drivers/net/avalanche_cpmac/psp_config_mgr.c
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/psp_config_mgr.c     1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/psp_config_mgr.c  2005-04-15 05:10:41.000000000 +0200
+@@ -0,0 +1,464 @@
++/******************************************************************************
++ * FILE PURPOSE:    PSP Config Manager Source
++ ******************************************************************************
++ * FILE NAME:       psp_config_mgr.c
++ *
++ * DESCRIPTION:
++ *
++ * Manages configuration information. The repository is managed on the basis of 
++ * <key, info> pair. It is possible to have multiple occurrence of the same key. 
++ * Multiple occurences of the same keys are referred to as 'instances'. 
++ * 'instances' are assigned in the order of configuration arrival. The first 
++ * config for a 'key' added to the repository would be treated as instance 0 and
++ * next config to arrive for the same key would be treated as instance '1' and 
++ * so on.
++ * 
++ * Info is retrieved from the repository based on the 'key' and 'instance' value.
++ *
++ * No assumption is made about the format of the information that is put in the 
++ * repository. The only requirement is that 'key' should be NULL terminated 
++ * string.
++ *
++ * REVISION HISTORY:
++ * 27 Nov 02 - PSP TII  
++ *
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++
++//#include <stdio.h>
++//#include <stdlib.h>
++#include "psp_config_mgr.h"
++#include "psp_config_util.h"
++
++#include <linux/slab.h>
++
++/*-----------------------------------------------------------
++  Implemented elsewhere
++ -----------------------------------------------------------*/
++extern int sys_read_options_conf(void);
++extern int sys_write_options_conf(char *cfg_info);
++extern int sys_load_default_static_cfg(void);
++extern int sys_run_enumerator(void);
++
++#define os_malloc(size) kmalloc(size, GFP_KERNEL)
++
++/*---------------------------------------------------------
++ * Data structures.
++ *--------------------------------------------------------*/
++struct device_cfg_data;
++
++typedef struct device_instance_cfg_data
++{
++    struct device_instance_cfg_data       *next;
++    char                                  locale[100];
++    unsigned int                          data_size;
++    char                                  *data;
++
++} DEV_INSTANCE_CFG_DATA_T;
++
++struct device_cfg_collection;
++
++typedef struct device_cfg_collection
++{
++    struct device_cfg_collection *next;
++    char                         *device_name;
++    CFG_TYPE_T                   cfg_type;
++    int                          count;
++    DEV_INSTANCE_CFG_DATA_T      *dev_inst_list_begin;
++    DEV_INSTANCE_CFG_DATA_T      *dev_inst_list_end;
++} DEVICE_CFG_T;
++
++
++typedef struct device_cfg_list
++{
++    DEVICE_CFG_T   *device_cfg_begin;
++    int            count;
++} DEVICE_CFG_LIST_T;
++
++/*-----------------------------------------------------------------------------
++ * Functions used locally with in the file.
++ *---------------------------------------------------------------------------*/
++static void p_init_device_cfg_list(void);
++static int  p_add_instance_cfg_data(DEVICE_CFG_T            *p_dev_cfg,
++                                    DEV_INSTANCE_CFG_DATA_T *p_dev_inst_data);
++static DEVICE_CFG_T* p_create_dev_cfg(char *device_name);
++static DEVICE_CFG_T* p_get_dev_cfg(char *device_name);
++static int p_set_device_cfg_type(DEVICE_CFG_T     *p_dev_cfg,
++                                 CFG_TYPE_T       cfg_type);
++
++/* PSP Config manager debug */                                 
++#define PSP_CFG_MGR_DEBUG 0
++
++#define dbgPrint if (PSP_CFG_MGR_DEBUG) printk
++
++/*-----------------------------------------------------------------------------
++ * The repository.
++ *---------------------------------------------------------------------------*/
++static DEVICE_CFG_LIST_T g_device_cfg_list;
++
++/*---------------------------------------------
++ * Initialize the device collection pool.
++ *--------------------------------------------*/ 
++void p_init_device_cfg_list(void)
++{
++    g_device_cfg_list.count = 0;
++    g_device_cfg_list.device_cfg_begin = NULL;
++}
++
++/*----------------------------------------------------------------------
++ * Add the device cfg into the device linked list.
++ *---------------------------------------------------------------------*/
++int p_add_dev_cfg_to_list(DEVICE_CFG_LIST_T *p_dev_list,
++                          DEVICE_CFG_T      *p_dev_cfg)
++{
++    if(p_dev_list->count != 0)
++        p_dev_cfg->next            = p_dev_list->device_cfg_begin;
++
++    p_dev_list->device_cfg_begin   = p_dev_cfg;
++
++    p_dev_list->count++;
++
++    return (0);
++}
++
++/*------------------------------------------------------------------
++ * Add the cfg data into the cfg data linked list of the collection.
++ *------------------------------------------------------------------*/
++int p_add_instance_cfg_data(DEVICE_CFG_T                 *p_dev_cfg,
++                            DEV_INSTANCE_CFG_DATA_T      *p_dev_inst_data)
++{
++    if(p_dev_cfg->count == 0)
++        p_dev_cfg->dev_inst_list_begin     = p_dev_inst_data;
++    else
++        p_dev_cfg->dev_inst_list_end->next = p_dev_inst_data;
++        
++    p_dev_cfg->dev_inst_list_end           = p_dev_inst_data;
++
++    p_dev_cfg->count++;
++    
++    return (0);
++}
++
++/*-----------------------------------------------------------------------------
++ * Create the device cfg.
++ *---------------------------------------------------------------------------*/
++DEVICE_CFG_T *p_create_dev_cfg(char *device_name)
++{
++    DEVICE_CFG_T *p_dev_cfg = NULL;
++
++    if((p_dev_cfg = os_malloc(sizeof(DEVICE_CFG_T))) == NULL)
++    {
++        dbgPrint("Failed to allocate memory for DEVICE_CFG_T.\n");
++    }
++    else if((p_dev_cfg->device_name = os_malloc(psp_config_strlen(device_name) + 1))==NULL)
++    {
++        dbgPrint("Failed to allocate memory for device name.\n");
++    }
++    else
++    {
++        psp_config_strcpy(p_dev_cfg->device_name, device_name);
++        p_dev_cfg->cfg_type = en_raw;
++        p_dev_cfg->count = 0;
++        p_dev_cfg->dev_inst_list_begin = NULL;
++        p_dev_cfg->dev_inst_list_end   = NULL;
++        p_dev_cfg->next                = NULL;
++    }
++
++    return(p_dev_cfg);
++}
++
++/*------------------------------------------------------------------------------
++ * Get the device cfg collection.
++ *-----------------------------------------------------------------------------*/
++DEVICE_CFG_T *p_get_dev_cfg(char *device_name)
++{
++    int count               = 0;
++    DEVICE_CFG_T *p_dev_cfg = g_device_cfg_list.device_cfg_begin;
++
++    for(count=0; count < g_device_cfg_list.count; count++)
++    {
++        if(psp_config_strcmp(device_name, p_dev_cfg->device_name) == 0)
++        {
++            break;
++        }
++
++        p_dev_cfg = p_dev_cfg->next;
++    }
++    
++    return(p_dev_cfg); 
++}
++
++/*-------------------------------------------------------------------------
++ * Gets the name for the static cfg type. Utility function. Debug purposes.
++ *-------------------------------------------------------------------------*/
++char *p_get_cfg_type_name_for_en(CFG_TYPE_T  cfg_type)
++{
++    static char raw_str      [] = "still raw";
++    static char compile_str  [] = "configured at compile time";
++    static char optconf_str  [] = "configured by options.conf";
++    static char vlynq_str    [] = "configured by VLYNQ";
++    static char no_static_str[] = "no static configuration";
++
++    if(cfg_type == en_raw)
++        return (raw_str);
++    else if(cfg_type == en_compile)
++        return (compile_str);
++    else if(cfg_type == en_opt_conf)
++        return (optconf_str);
++    else if(cfg_type == en_vlynq)
++        return (vlynq_str);
++    else
++        return (no_static_str);
++
++}
++
++/*-----------------------------------------------------------------------------
++ * Sets the static cfg status of the device collection.
++ *
++ * If the collection is en_virgin then, the collection is assigned to cfg_type.
++ * If the cfg_type is en_vlynq then, the old cfg_type is retained. 
++ * en_compile and en_opt_conf are mutually exclusive. One of these can be 
++ * accomodated.
++ *
++ *---------------------------------------------------------------------------*/
++int p_set_device_cfg_type(DEVICE_CFG_T    *p_dev_cfg,
++                          CFG_TYPE_T      cfg_type)
++{
++    int ret_val = 0;
++
++    if(p_dev_cfg->cfg_type == en_raw)
++        p_dev_cfg->cfg_type = cfg_type;
++    else if((cfg_type == en_vlynq) || (p_dev_cfg->cfg_type == cfg_type))
++        ;
++    else
++    {
++        dbgPrint("Device %s has been %s which overrides %s.\n",
++                  p_dev_cfg->device_name,
++                  p_get_cfg_type_name_for_en(p_dev_cfg->cfg_type),
++                  p_get_cfg_type_name_for_en(cfg_type));
++        ret_val = -1;
++    }
++
++    return(ret_val);
++}
++
++/*------------------------------------------------------------------------
++ * Add the config str into the repository. The cfg type indicates
++ * whether the device has been configured statically, from options.conf or
++ * by vlynq enumeration.
++ *------------------------------------------------------------------------*/
++int psp_config_add(char *key, void *p_cfg_str, unsigned int cfg_len, 
++                   CFG_TYPE_T cfg_type)
++{
++    int                     ret_val           = -1;
++    DEVICE_CFG_T            *p_dev_cfg        = NULL;
++    DEV_INSTANCE_CFG_DATA_T *p_dev_inst_data  = NULL;  
++
++    if(p_cfg_str == NULL || key == NULL)
++    {
++        dbgPrint("Null input pointer(s).\n");
++    }
++    /* check if there exist a dev_cfg for the given key, if not,
++       then create one and add it to the device list. */
++    else if(((p_dev_cfg = p_get_dev_cfg(key)) == NULL) &&
++            (((p_dev_cfg = p_create_dev_cfg(key)) == NULL) ||
++               p_add_dev_cfg_to_list(&g_device_cfg_list, p_dev_cfg) != 0))
++    {
++        dbgPrint("Failed to allocate mem or add dev cfg for %s.\n", key);
++    }
++    /* make sure that we can add this cfg type to the repository */
++    else if(p_set_device_cfg_type(p_dev_cfg, cfg_type) == -1)
++    {
++        dbgPrint("Ignoring \"%s\" for device \"%s\".\n",
++                  p_get_cfg_type_name_for_en(cfg_type),  
++                  p_dev_cfg->device_name); 
++    }
++    else if((p_dev_inst_data = os_malloc(sizeof(DEV_INSTANCE_CFG_DATA_T)))== NULL)
++    {
++        dbgPrint("Failed to allocate memory for DEV_INSTANCE_CFG_DATA_T.\n");
++    }
++    else if((p_dev_inst_data->data = os_malloc(cfg_len) + 1) == NULL)
++    {
++        dbgPrint("Failed to allocate memory for the config data.\n");
++    }
++    else
++    {
++        p_dev_inst_data->next = NULL;
++
++        if(cfg_type == en_opt_conf || cfg_type == en_compile)
++            psp_config_strcpy(p_dev_inst_data->locale, "dev on chip ");
++        else if(cfg_type == en_vlynq)
++            psp_config_strcpy(p_dev_inst_data->locale, "dev on vlynq");
++        else 
++            psp_config_strcpy(p_dev_inst_data->locale, "dev locale ?");
++
++        psp_config_memcpy(p_dev_inst_data->data, p_cfg_str, cfg_len);
++        p_dev_inst_data->data_size = cfg_len;
++        *(p_dev_inst_data->data + cfg_len) = '\0';
++
++        ret_val = p_add_instance_cfg_data(p_dev_cfg, p_dev_inst_data);
++    } 
++
++    return(ret_val);
++}
++
++/*-------------------------------------------------------------
++ * Get the total number of device instances in the repository
++ *------------------------------------------------------------*/
++int psp_config_get_num_keys(void)
++{
++    return(g_device_cfg_list.count);
++}
++
++
++/*--------------------------------------------------------------------
++ * Get the device configuration info from the repository.
++ *-------------------------------------------------------------------*/
++int psp_config_get(char *key, int instance, char **cfg_data_out)
++{
++    int ret_val             = -1;
++    DEVICE_CFG_T *p_dev_cfg = NULL;
++    *cfg_data_out           = NULL;
++
++    if(key == NULL && cfg_data_out == NULL)
++    {
++        dbgPrint("Key has a NULL value.\n");
++    }
++    else if((p_dev_cfg = p_get_dev_cfg(key)) == NULL)
++    {
++        dbgPrint("cfg information for %s could not be found.\n", key);
++    }
++    else if(p_dev_cfg->count)
++    {
++         DEV_INSTANCE_CFG_DATA_T *p_dev_inst_data = 
++                                  p_dev_cfg->dev_inst_list_begin;
++         int index = 0;
++         for(index = 0; 
++             index != instance && index < p_dev_cfg->count; 
++             index++)
++         {
++             p_dev_inst_data = p_dev_inst_data->next;
++         }
++
++         if(p_dev_inst_data != NULL && p_dev_inst_data->data != NULL)
++         {
++             *cfg_data_out = p_dev_inst_data->data;
++             ret_val = p_dev_inst_data->data_size;
++         }
++    }
++
++    return (ret_val);
++}
++
++/*----------------------------------------------------------------
++ * Returns the number of instances found in the repository for the
++ * specified key.
++ *---------------------------------------------------------------*/
++int psp_config_get_num_instances(char *key)
++{
++    int ret_val             = 0;
++    DEVICE_CFG_T *p_dev_cfg = NULL;
++
++    if(key == NULL)
++    {
++        dbgPrint("Key has a NULL value.\n");
++    }
++    else if((p_dev_cfg = p_get_dev_cfg(key)) == NULL)
++    {
++        dbgPrint("cfg information for %s could not be found.\n", key);
++    }
++    else
++    {
++        ret_val = p_dev_cfg->count;
++    }
++    
++    return (ret_val);
++}
++
++/*------------------------------------------------------------------
++ * Dump the configuration repository. 
++ * Caution: DO NOT USE THIS FOR ANY NON NBU specified config format.
++ *-----------------------------------------------------------------*/
++void psp_config_print(char *key)
++{
++    DEVICE_CFG_T *p_dev_cfg = NULL;
++
++    if(key == NULL)
++    {
++        dbgPrint("Key has a NULL value.\n");
++    }
++    else if((p_dev_cfg = p_get_dev_cfg(key)) == NULL)
++    {
++        dbgPrint("cfg information for %s could not be found.\n", key);
++    }
++    else if(p_dev_cfg && p_dev_cfg->count)
++    {
++        DEV_INSTANCE_CFG_DATA_T   *p_dev_inst_data;
++
++        p_dev_inst_data = p_dev_cfg->dev_inst_list_begin;
++
++        do
++        {
++            dbgPrint("%s : %s\n", p_dev_inst_data->locale, 
++                      p_dev_inst_data->data);
++            p_dev_inst_data = p_dev_inst_data->next;
++
++        } while(p_dev_inst_data);
++    }
++    else
++    {
++        dbgPrint("Nothing was found for %s.\n", key);
++    }
++}
++
++void dump_device_cfg_pool(void)
++{
++    DEVICE_CFG_T *p_dev_cfg = g_device_cfg_list.device_cfg_begin;
++    
++    if(p_dev_cfg != NULL && g_device_cfg_list.count)
++    {
++        int index=0;
++
++        for(index=0; index < g_device_cfg_list.count; index++)
++        {
++            psp_config_print(p_dev_cfg->device_name);
++            p_dev_cfg = p_dev_cfg->next;
++        }
++    }
++    else
++    {
++        dbgPrint("repository is empty.\n");
++    }
++}
++
++void psp_config_init(void)
++{
++    p_init_device_cfg_list();
++}
++
++void psp_config_cleanup()                                                       
++{                                                                               
++    int dev_count              = 0;                                             
++    int inst_count             = 0;                                             
++    DEVICE_CFG_T            *p = g_device_cfg_list.device_cfg_begin;            
++    DEV_INSTANCE_CFG_DATA_T *q = NULL;                                          
++                                                                                
++    for(dev_count = 0; dev_count < g_device_cfg_list.count; dev_count++)        
++    {                                                                           
++        DEVICE_CFG_T            *p_temp = NULL;                                 
++        if(p) q = p->dev_inst_list_begin;                                       
++                                                                                
++        for(inst_count = 0; inst_count < p->count && q != NULL; inst_count++)   
++        {                                                                       
++            DEV_INSTANCE_CFG_DATA_T *q_temp = q;                                
++            q_temp = q->next;                                                   
++            kfree(q->data);                                                     
++            kfree(q);                                                           
++            q = q_temp;                                                         
++        }                                                                       
++                                                                                
++        p_temp = p->next;                                                       
++        kfree(p);                                                               
++        p = p_temp;                                                             
++    }                                                                           
++}                                                                               
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/psp_config_mgr.h linux-2.4.30/drivers/net/avalanche_cpmac/psp_config_mgr.h
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/psp_config_mgr.h     1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/psp_config_mgr.h  2005-04-15 05:10:41.000000000 +0200
+@@ -0,0 +1,110 @@
++/******************************************************************************
++ * FILE PURPOSE:    PSP Config Manager Header
++ ******************************************************************************
++ * FILE NAME:       psp_config_mgr.h
++ *
++ * DESCRIPTION:     Storing and retrieving the configuration based on key
++ * A set of APIs to be used by one and sundry (including drivers and enumerator) to build
++ * and read cfg information of the devices for an avalanche SOC.
++ *
++ * This set of APIs isolates the configuration management from the world and provides simple
++ * access convinience.
++ *
++ * Device in this set refers to the peripherals that can be found on the SOC or on VLYNQ.
++ * The configuration is stored in the form of string and drivers can use these APIs to get
++ * a particular parameter value.
++ *
++ * The memory allocation for the pass back parameters is done by the caller.
++ *
++ * 0 is returned for SUCCESS or TRUE.
++ *  -1 is returned for FAILURE or FALSE.
++ *
++ * REVISION HISTORY:
++ * 27 Nov 02 - PSP TII  
++ *
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++ 
++#ifndef __PSP_CONFIG_MGR_H__
++#define __PSP_CONFIG_MGR_H__
++
++typedef enum cfg_type
++{
++    en_raw     = 0,
++    en_compile,
++    en_opt_conf,
++    en_vlynq
++} CFG_TYPE_T;
++
++/* Build psp configuration */
++void build_psp_config(void);
++ 
++/********************************************************
++ * Access Operations.
++ ********************************************************/
++
++/*------------------------------------------------------------------------- 
++   initializes the configuration repository. 
++ -------------------------------------------------------------------------*/
++void  psp_config_init(void);
++
++/*-------------------------------------------------------------------------- 
++   Adds the configuration information into the repository. 'key' is required 
++   to be NULL terminated string. 'cfg_ptr' points to the configuration data.
++   'cfg_len' is the length of the data pointed to by 'cfg_ptr' in bytes. 
++   'cfg_type' indicates the type of config information.
++
++   psp_config_mgr copies the 'cfg_len' bytes of data pointed to by 'cfg_ptr' 
++   into its internal repository. 
++
++   Returns: 0 on success, -1 on failure.
++  -------------------------------------------------------------------------*/
++int   psp_config_add(char *key, void *cfg_ptr, 
++                     unsigned int cfg_len, CFG_TYPE_T cfg_type);
++
++
++/* --------------------------------------------------------------------------
++   Passes back, in "*cfg_out_val" a pointer to the config data in the repository
++   for the specified 'key' and 'instance'. It returns the size of the config
++   info
++
++   psp_config_mgr passes back a pointer in '*cfg_out_val' which refers to 
++   some location in its internal repository. It is strongly recommended that 
++   if the user intends to modify the contents of the config info for reasons 
++   whatsoever, then, user should allocate memory of size returned by this 
++   routine and copy the contents from '*cfg_out_val'.
++  
++   Any, modification carried out on the repository would lead to un-expected
++   results.
++
++   Returns: 0 or more for the size of config info, -1 on error.
++  --------------------------------------------------------------------------*/ 
++int   psp_config_get(char *key, int instance, char **cfg_out_val);
++
++
++/*--------------------------------------------------------------------------
++   Get the number of keys that have been added in the repository so far.
++
++   Returns: 0 or more for the num of keys, -1 on error.
++  -------------------------------------------------------------------------*/
++int   psp_config_get_num_keys(void);
++
++
++/*--------------------------------------------------------------------------
++   Get the number of instances that are present in the repository for the 
++   given 'key'.
++
++   Returns: 0 or more for the num of instances, -1 on error.
++  -------------------------------------------------------------------------*/  
++int   psp_config_get_num_instances(char *key);
++
++
++/*--------------------------------------------------------------------------
++   Prints the config data for all instances associated with the specified 
++   'key'.
++  -------------------------------------------------------------------------*/
++void  psp_config_print(char *key);
++
++void  dump_device_cfg_pool(void);
++
++#endif /* __PSP_CONFIG_MGR_H__ */
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/psp_config_parse.c linux-2.4.30/drivers/net/avalanche_cpmac/psp_config_parse.c
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/psp_config_parse.c   1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/psp_config_parse.c        2005-07-08 22:11:19.180858923 +0200
+@@ -0,0 +1,363 @@
++/******************************************************************************
++ * FILE PURPOSE:    PSP Config Manager - Parse API Source
++ ******************************************************************************
++ * FILE NAME:       psp_config_parse.c
++ *
++ * DESCRIPTION:     These APIs should be used only for scanvenging parameters which 
++ *                  are stored in the following format.
++ *
++ *                  str[] = "module(id=[module], k1=v1, k2=[k3=v3, k4=v4], k5=v5)"
++ *
++ * REVISION HISTORY:
++ * 27 Nov 02 - PSP TII  
++ *
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++
++//#include <stdio.h>
++//#include <ctype.h>
++#include <asm/ar7/hal/haltypes.h>
++
++/*--------------------------------------------------
++ * MACROS.
++ *-------------------------------------------------*/
++#define my_isdigit(c) (c >= '0' && c <= '9')
++#define my_isoct(c)   (c >= '0' && c <= '7')  
++#define my_xtod(c)    ((c) <= '9' ? (c) - '0' : (c) - 'a' +  10)
++#define my_ifupper(c)    (c >= 'A' && c <= 'F')
++#define XTOD(c)       ((c) - 'A' + 10)
++#define my_ishex(c)   ((c >= 'a' && c <='f') || (c >= 'A' && c<='F') || my_isdigit(c) ) 
++
++/*---------------------------------------------------
++ * Local Functions.
++ *--------------------------------------------------*/
++static int p_get_substr_from_str(char *p_in_str, char begin_delimiter,
++                                 char end_delimiter, int pair_flag,
++                                 char **p_out_str);
++static int p_get_u_int_from_str(char *p_in_str, char begin_delimiter,
++                                char end_delimiter, unsigned long *out_val);
++
++/*---------------------------------------------------
++ * Return pointer to first instance of the char.
++ *--------------------------------------------------*/
++static char* psp_config_strchr(char *str, char chr)
++{
++    while(*str)
++    {
++        if(*str == chr)
++            break;
++        str++;    
++    }
++    
++    return((*str) ? str : NULL);
++}
++
++/*------------------------------------------------------------------------
++ * Convert the string upto delimiter to unsigned long.
++ *-----------------------------------------------------------------------*/
++unsigned long my_atoul(char *p, char end_delimiter, unsigned long *out_val)
++{
++    unsigned long n;
++    int c;
++ 
++    /* check the for null input */    
++    if (!p)
++        return -1;
++     
++    c = *p;    
++    
++    /* pass through the leading spaces */
++    if (!my_isdigit(c)) 
++    {
++        while ( c == ' ')
++            c = *++p;
++            
++    }
++    
++    if (c == '0')
++    {
++        if(*(p + 1) == 'x' || *(p+1) == 'X' ) 
++        {
++            /* string is in hex format */
++
++            p += 2; 
++            c = *p;
++            
++            if(my_ishex(c))
++            {
++               if(my_ifupper(c))
++                   n = XTOD(c);
++               else         
++                       n = my_xtod(c);
++            }
++            else
++                return -1; /* invalid hex string format */
++                
++            while ((c = *++p) && my_ishex(c)) 
++            {
++                n *= 16; 
++                if(my_ifupper(c))
++                   n += XTOD(c);
++                else         
++                       n += my_xtod(c);
++            }
++         }
++        else
++        {
++            /* string is in octal format */
++
++            if( my_isoct(c) )
++            n = c - '0';
++            else
++                return -1; /* invalid octal string format */
++ 
++            while ((c = *++p) && my_isoct(c)) 
++            {
++                n *= 8; 
++                n += c - '0'; 
++            }
++        } 
++         
++    }      
++    else 
++    {
++        /* string is in decimal format */
++ 
++        if( my_isdigit(c) )
++            n = c - '0';
++        else
++            return -1; /* invalid decimal string format */
++
++        while ((c = *++p) && my_isdigit(c)) 
++        {
++            n *= 10; 
++            n += c - '0'; 
++        }
++    }
++   
++    /* move through the trailing spaces */ 
++    while(*p == ' ')
++        p++;
++        
++    if(*p == end_delimiter)
++       {
++           *out_val = n;
++           return 0;
++       }   
++        
++    else
++        return -1; /* invalid string format */
++}
++
++/*---------------------------------------------------------------------------------
++ * Gets the substring de-limited by the 'begin_delimiter' and 'end_delimiter'.
++ * and returns the size of the substring. 
++ *
++ * Parses the NULL terminated p_in_str for a character array delimited by 
++ * begin_delimiter and end_delimiter, passes back the pointer to the character 
++ * array in ' *p_out_str '. The passed pointer ' *p_out_str ' should point to 
++ * the location next (byte) to the begin_delimiter. The function routine returns 
++ * the number of characters excluding the begin_delimiter and end_delimiter, 
++ * found in the array delimited by the said delimiters.
++ *
++ * If the pair_flag is set to 1, then, number of begin_delimiter and end_delimiter
++ * found in the parsing should match (equal) and this routine passes back the 
++ * pointer to the character array, starting at a location next (byte) to the 
++ * first begin_delimiter,  inclusive of all intermediate matching delimiter 
++ * characters found between outer delimiters. If the pair flag is set and if 
++ * begin_delimiter and end_delimiter happens to be same, then error (-1) is 
++ * returned.
++ * 
++ * Return: 0 or more to indicate the size of the substring, -1 on error.
++ *-------------------------------------------------------------------------------*/
++int p_get_substr_from_str(char *p_in_str, char begin_delimiter, 
++                          char end_delimiter, int pair_flag, 
++                          char **p_out_str) 
++{
++    int cnt,pos;
++
++    if(pair_flag  && begin_delimiter == end_delimiter)
++        return -1;
++    
++    if((p_in_str = psp_config_strchr(p_in_str, begin_delimiter)) == 0)
++        return -1; /* no start delimiter found */
++    
++    p_in_str++;      
++    *p_out_str = p_in_str;
++     
++    for(pos = 0,cnt =1; cnt && p_in_str[pos] ; pos++)
++    {
++        if(p_in_str[pos] == end_delimiter)
++        {
++            if(pair_flag == 0)
++                return pos;
++               
++            cnt--;                  
++        }             
++        else if(p_in_str[pos] == begin_delimiter)
++            cnt++;
++        else 
++            ; /* We do nothing */
++      
++    }
++    
++    if( cnt == 0)   
++        return pos - 1;
++    else
++        return -1; /* no corresponding end delimiter found */
++}
++
++/*--------------------------------------------------------------------------    
++ * Parses the NULL terminated p_in_str for unsigned long value delimited by 
++ * begin_delimiter and end_delimiter, passes back the found in ' *out_val '.  
++ * The function routine returns 0 on success and returns -1 on failure. 
++ * The first instance of the de-limiter should be accounted for the parsing.
++ *
++ * The base for unsigned value would 10, octal and hex. The value passed back 
++ * would be of the base 10. Spaces at the begining of the byte array are valid  
++ * and should be ingnored in the calculation of the value. Space character in 
++ * the middle of the byte array or any character other than the valid ones 
++ * (based on base type) should return error. The octal value begins with '0', 
++ * the hex value begins with "0x" or "0X", the base value can begin with 
++ * '1' to '9'.
++ * 
++ * Returns: 0 on success, -1 on failure.
++ *-------------------------------------------------------------------------*/
++int p_get_u_int_from_str(char *p_in_str, char begin_delimiter, 
++                         char end_delimiter, unsigned long *out_val) 
++{
++    char *start;
++    unsigned long num;
++    
++    num = p_get_substr_from_str(p_in_str, begin_delimiter, end_delimiter,
++                                0, &start);
++
++    if(num == (unsigned long)-1)
++        return -1;
++    
++    return my_atoul(start,end_delimiter,out_val);
++}
++
++/*--------------------------------------------------------------------------
++ * Finds the first occurrence of the substring p_find_str in the string
++ * p_in_str. 
++ *-------------------------------------------------------------------------*/
++char *my_strstr(char *p_in_str, const char *p_find_str)
++{
++    char *p = (char *)p_find_str;
++    char *ret = NULL;
++
++    while(*p_in_str)
++    {
++        if(!(*p))
++            return (ret);
++        else if(*p_in_str == *p)
++        {
++            if(!ret) ret = p_in_str;
++            p++;
++            p_in_str++;
++        }
++        else if(ret)
++        {
++            p = (char *)p_find_str;
++            p_in_str = ret + 1;
++            ret = NULL;
++        }
++        else
++            p_in_str++;
++    }
++
++    if(*p_in_str != *p) ret = NULL;
++
++    return (ret);
++
++}
++
++/*------------------------------------------------------------------------------
++ * Gets the value of the config param in the unsigned int format. The value is 
++ * stored in the following format in the string.
++ * str[] = "module(id=[module], k1=v1, k2=[k3=v3, k4=v4], k5=v5)"
++ *-----------------------------------------------------------------------------*/
++int psp_config_get_param_uint(char *p_in_str, const char *param, unsigned int *out_val)
++{
++    int   ret_val = -1;
++    char *p_strstr;
++
++    if(!p_in_str || !param || !out_val) 
++    {
++        ;
++    } 
++    else if((p_strstr = my_strstr(p_in_str, param)) == NULL)
++    {
++        ;
++    }
++    else if(p_get_u_int_from_str(p_strstr, '=', ',', (unsigned long *)out_val) == 0)
++    {
++        ret_val = 0;
++    }
++    else if(p_get_u_int_from_str(p_strstr, '=', ']', (unsigned long*)out_val) == 0)
++    {
++        ret_val = 0;
++    }
++    else if(p_get_u_int_from_str(p_strstr, '=', ')', (unsigned long*)out_val) == 0)
++    {
++        ret_val = 0;
++    }
++    else
++    {
++        /* we failed */
++    }
++
++    return (ret_val);
++}
++ 
++/*------------------------------------------------------------------------------
++ * Gets the value of the config param in the Non NULL terminated format. The value 
++ * is stored in the following format in the string. 
++ * str[] = "module(id=[module], k1=v1, k2=[k3=v3, k4=v4], k5=v5)"
++ *-----------------------------------------------------------------------------*/
++int psp_config_get_param_string(char *p_in_str, const char *param, char **out_val)
++{
++    int ret_val = -1;
++    char *p_strstr;
++
++    if(!p_in_str || !param || !(out_val))
++        ;
++    else if((p_strstr = my_strstr(p_in_str, param)) == NULL)
++    {
++        ;
++    }
++    else if((ret_val = p_get_substr_from_str(p_strstr, '[', ']', 1, out_val)) == -1)
++    {
++        ;
++    }
++    else
++    {
++        ; /* we got the value */
++    }   
++ 
++    return (ret_val); 
++} 
++
++#ifdef PSP_CONFIG_MGR_DEBUG_TEST
++main()
++{
++    unsigned long num =999;
++    int ret = 0;
++    char *val1 = NULL;
++    char val[30];
++    char str1[] = "cpmac(id=[cpmac], k0=[a1=[a2=[test], a3=2], k1=100, k2=[k3=300, k4=200], k7=722)";
++
++    psp_config_get_param_uint(str1, "k7", &num);
++    printf("%u.\n", num);    
++    ret = psp_config_get_param_string(str1, "a1", &val1); 
++    if(ret >= 0) { printf("%d.\n", ret); strncpy(val, val1, ret); val[ret] = '\0';}
++    
++    printf("val = \"%s\", and size = %d \n", val, ret);
++
++    if(val[ret]) ; else printf("jeee.\n");
++}
++#endif /* PSP_CONFIG_MGR_DEBUG_TEST */
++
++
++
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/psp_config_parse.h linux-2.4.30/drivers/net/avalanche_cpmac/psp_config_parse.h
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/psp_config_parse.h   1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/psp_config_parse.h        2005-07-08 22:07:07.685855972 +0200
+@@ -0,0 +1,32 @@
++/******************************************************************************
++ * FILE PURPOSE:    PSP Config Manager - Parse API Header
++ ******************************************************************************
++ * FILE NAME:       psp_config_parse.h
++ *
++ * DESCRIPTION:     Parsing for params from string available in the NBU format.
++ *                  These APIs should be used only for scanvenging parameters which 
++ *                  are stored in the following format.
++ *                  
++ *                  str[] = "module(id=[module], k1=v1, k2=[k3=v3, k4=v4], k5=v5)"
++ *
++ * REVISION HISTORY:
++ * 27 Nov 02 - PSP TII  
++ *
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++
++#ifndef __PSP_CONFIG_PARSER_H__
++#define __PSP_CONFIG_PARSER_H__
++
++/*------------------------------------------------------------------
++ * These APIs should be used only for scanvenging parameters which 
++ * are stored in the following format.
++ *
++ * str[] = "module(id=[module], k1=v1, k2=[k3=v3, k4=v4], k5=v5)"
++ *-----------------------------------------------------------------*/
++int psp_config_get_param_uint(char *p_in_str, const char *param, 
++                              unsigned int *out_val);
++int psp_config_get_param_string(char *p_in_str, const char *param, 
++                                char **out_val);
++
++#endif /* __PSP_CONFIG_PARSER_H__ */
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/psp_config_util.c linux-2.4.30/drivers/net/avalanche_cpmac/psp_config_util.c
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/psp_config_util.c    1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/psp_config_util.c 2005-07-08 22:11:56.567831651 +0200
+@@ -0,0 +1,106 @@
++/******************************************************************************
++ * FILE PURPOSE:    PSP Config Manager - Utilities API Source
++ ******************************************************************************
++ * FILE NAME:       psp_config_util.c
++ *
++ * DESCRIPTION:     These APIs provide the standard "C" string interfaces. 
++ *                  Provided here to reduce dependencies on the standard libraries 
++ *                  and for cases where psp_config would required to run before 
++ *                  the whole system is loaded or outside the scope of the OS.
++ *
++ * REVISION HISTORY:
++ * 27 Nov 02 - PSP TII  
++ *
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++
++//#include <stdio.h>
++#include "psp_config_util.h"
++#include <asm/ar7/hal/haltypes.h>
++
++/*---------------------------------------------
++ * strlen.
++ *-------------------------------------------*/
++int psp_config_strlen(char *p)
++{
++    char *p_orig = p;
++    while(*p)
++        p++;
++    return(p - p_orig);
++}
++
++/*--------------------------------------------
++ * strcmp.
++ *-------------------------------------------*/
++int psp_config_strcmp(char *s1, char *s2)
++{
++    while(*s1 && *s2)
++    {
++        if(*s1 != *s2)
++            break;
++        s1++;
++        s2++;
++    }
++
++    return(*s1 - *s2);
++}
++
++/*--------------------------------------------
++ * strcpy.
++ *------------------------------------------*/
++char* psp_config_strcpy(char *dest, char *src)
++{
++    char *dest_orig = dest;
++
++    while(*src)
++    {
++        *dest++ = *src++;
++    }
++
++    *dest = '\0';
++
++    return(dest_orig);
++}
++
++/*----------------------------------------------
++ * psp_config_memcpy.
++ *--------------------------------------------*/
++void* psp_config_memcpy(void* dest, void* src, unsigned int n)
++{
++    void *dest_orig = dest;
++
++    while(n)
++    {
++        *(char *)dest++ = *(char *)src++;
++        n--;
++    }
++
++    return (dest_orig);
++}
++
++/*---------------------------------------------------
++ * Return pointer to first instance of the char.
++ *--------------------------------------------------*/
++char* psp_config_strchr(char *str, char chr)
++{
++    while(*str)
++    {
++        if(*str == chr)
++            break;
++        str++;    
++    }
++    
++    return((*str) ? str : NULL);
++}
++
++#ifdef PSP_CONFIG_MGR_DEBUG_TEST
++
++int main( )
++{
++    char s[] = "hello             ";
++    printf("%d.\n", psp_config_strlen("hello\n"));
++    printf("%d.\n", psp_config_strcmp("hells", "hellq"));
++    printf("%s %s.\n", psp_config_strcpy(s + 6, "test1"), s);
++}
++
++#endif /* PSP_CONFIG_MGR_DEBUG_TEST */
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/psp_config_util.h linux-2.4.30/drivers/net/avalanche_cpmac/psp_config_util.h
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/psp_config_util.h    1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/psp_config_util.h 2005-04-15 05:10:41.000000000 +0200
+@@ -0,0 +1,26 @@
++/******************************************************************************
++ * FILE PURPOSE:    PSP Config Manager - Utilities API Header
++ ******************************************************************************
++ * FILE NAME:       psp_config_util.h
++ *
++ * DESCRIPTION:     These APIs provide the standard "C" string interfaces. 
++ *                  Provided here to reduce dependencies on the standard libraries 
++ *                  and for cases where psp_config would required to run before 
++ *                  the whole system is loaded or outside the scope of the OS.
++ *
++ * REVISION HISTORY:
++ * 27 Nov 02 - PSP TII  
++ *
++ * (C) Copyright 2002, Texas Instruments, Inc
++ *******************************************************************************/
++ 
++#ifndef __PSP_CONFIG_UTIL_H__
++#define __PSP_CONFIG_UTIL_H__
++
++extern int   psp_config_strlen(char*);
++extern int   psp_config_strcmp(char*, char*);
++extern char* psp_config_strcpy(char*, char*);
++extern void* psp_config_memcpy(void*, void*, unsigned int n);
++extern char* psp_config_strchr(char*, char);
++
++#endif /* __PSP_CONFIG_UTIL_H__ */
+diff -ruN linux-2.4.30.orig/drivers/net/avalanche_cpmac/readme.txt linux-2.4.30/drivers/net/avalanche_cpmac/readme.txt
+--- linux-2.4.30.orig/drivers/net/avalanche_cpmac/readme.txt   1970-01-01 02:00:00.000000000 +0200
++++ linux-2.4.30/drivers/net/avalanche_cpmac/readme.txt        2005-04-15 05:10:41.000000000 +0200
+@@ -0,0 +1,545 @@
++23 August 2004      CPMAC 1.7.8 (NSP Performance Team Release)
++
++CC Labels: REL_20040823_HALdallas_cpmac_01.07.08
++
++New features:  Key "MacAddr" can now be used to set the Mac Address after Open. 
++
++ unsigned char MacAddr[6];
++
++  // Set Mac Address to "00.B0.D0.10.80.C1"     
++  MacAddr[0] = 0x00;
++  MacAddr[1] = 0xB0;
++  MacAddr[2] = 0xD0;
++  MacAddr[3] = 0x10;
++  MacAddr[4] = 0x80;
++  MacAddr[5] = 0xC1;
++      
++  HalFunc->Control(HalDev, "MacAddr", hcSet, &MacAddr);      
++
++Bug fixes: in Send(), Threshold is not checked if Tx Ints are re-enabled.
++
++Modules affected:  hcpmac.c, hcpmac.h, cppi_cpmac.c
++
++22 June 2004          CPMAC 1.7.6 (NSP Performance Team Release)
++
++CC Labels: REL_20040622_HALdallas_cpmac_01.07.06
++
++New features:  Key "TxIntDisable" used to disable Tx Interrupts. If it is set, then Tx Interrupts will be processed on Send() controlled by Tx ServiceMax Setting. 
++
++ int On = 1;
++ HalFunc->Control(HalDev, "TxIntDisable", "Set", &On);
++
++Bug fixes: NTR
++
++10 June 2004          CPMAC 1.7.5 (external release)
++
++CC Labels: REL_20040610_HALdallas_cpmac_01.07.05
++
++New features:  NTR
++
++Bug fixes: Fixed an issue with calculation for the multicast hash.
++
++27 May 2004          CPSAR 1.7.4, CPMAC 1.7.4 (external release)
++
++CC Labels: REL_20040527_HALdallas_cpsar_01.07.04
++           REL_20040527_HALdallas_cpmac_01.07.04
++
++New features:  NTR
++
++Bug fixes: A flaw was fixed in the critical sectioning of the CPPI file, affecting both
++           the MAC and the SAR releases.  This flaw was detected on Titan PSP 4.7 BFT2.
++
++05 May 2004          CPSAR 1.7.3, CPMAC 1.7.3 (external release)
++
++CC Labels: REL_20040505_HALdallas_cpsar_01.07.03
++                REL_20040505_HALdallas_cpmac_01.07.03
++
++New features:  NTR
++
++Bug fixes: 1) Firmware has been updated to fix a problem with Host OAM mode operation.  
++               2) Cache macros have been fixed.
++
++Notes:  This release contains all performance enhancements currently available for CPHAL 1.x.  
++
++19 April 2004          CPSAR 1.7.2, CPMAC 1.7.2 (external release)
++
++CC Labels: REL_20040419_HALdallas_cpsar_01.07.02
++                REL_20040419_HALdallas_cpmac_01.07.02
++
++New features:  NTR
++
++Bug fixes: Fixes merge problem in 1.7.1.
++
++Notes:  This is a branch release which contains only a subset of the performance improvements.
++            The remaining performance improvements are stiill being qualified at this time.
++
++1 April 2004          CPSAR 1.7.1, CPMAC 1.7.1 (external release)
++
++NOTICE: DO NOT USE 1.7.1.  It has a known problem (see 1.7.2 notes)
++
++CC Labels: REL_20040401_HALdallas_cpsar_01.07.01
++                REL_20040401_HALdallas_cpmac_01.07.01
++
++New features:  Performance improvement in CPPI layer, affecting both CPSAR and CPMAC.  
++
++Bug fixes: NTR
++
++17 Februrary 2004    CPSAR 1.7.0 (external release)
++
++CC Labels: REL_20040217_HALdallas_cpsar_01.07.00
++
++New features:  Added support for "TxFlush" feature.  This allows the upper
++               layer to flush all or part of a given Tx queue for a given
++               channel.  This is to be used during call setup for a voice
++               connection.
++
++30 January 2004      CPMAC 1.7.0 (external release)
++
++CC Labels: REL_20040130_HALdallas_cpmac_01.07.00
++
++Bug fixes:    CPMDIO - When in manual negotiate mode and linked, dropping link would move into NWAY state rather than manual state.
++              CPMDIO - Extraneous debug message corrected
++New features: CPMDIO - Support for AutoMdix usage added. 
++
++25 September 2003      CPSAR 1.6.6 (external release)
++
++CC Labels: REL_20030925_HALdallas_cpsar_01.06.06
++
++Bug fixes:   PDSP firmware has been updated to fix the OAM padding problem.  It previously
++             wrote pad bytes into a reserved field of the OAM cell.  There is a small
++             change to the CPSAR configuration code which corresponds to the PDSP spec
++             change.
++
++New features: NTR
++
++09 September 2003      CPMAC 1.6.6 (external release)
++
++CC Labels: REL_20030909_HALdallas_cpmac_01.06.06
++
++Bug fixes:   CPMAC : When _CPMDIO_NOPHY is set, Cpmac COntrol is set to Full Duplex
++             Bridge loopback test does not show a problem using 1.6.5 if packet rate is
++             below 50,000 pbs. Now testing with a 100% send from Ixia.
++
++New features: NTR
++
++05 August 2003         CPHAL 1.6.5 (external release)
++
++CC Labels: REL_20030805_HALdallas_cpmac_01.06.05
++
++Bug fixes: NTR
++
++New features:  CPMAC : Added support for CPMAC modules that do not have a Phy connected.
++               The CPMAC is informed of this by the MdioConnect option
++               _CPMDIO_NOPHY. This is the only driver change needed to
++               receive and transmit packets through the Marvel switch.
++               Note  In this mode Link status will reported linked at 100/FD to
++               PhyNum 0xFFFFFFFF.
++
++               ALL:  Cleaned up some Vlynq support logic.
++
++16 July 2003         CPSAR 1.6.3 (external release), no CPMAC release
++
++CC Labels: REL_20030716_HALdallas_cpsar_01.06.03
++
++Bug fixes: 1) Changed default value of CPCS_UU from 0x5aa5 to 0.  The old default value caused
++              problems with Cisco routers.
++
++New features:  NTR
++
++Known issues not addressed in this release: NTR.
++
++01 July 2003         CPHAL 1.6.2 (external release)
++
++CC Labels: REL_20030701_HALdallas_cpmac_01.06.02
++           REL_20030701_HALdallas_cpsar_01.06.02
++
++Bug fixes: 1) A previous firmware upgrade caused firmware OAM loopback cells to only work on every other
++              command.  This has been fixed in the new firmware version (0.47).
++           2) Problem with PTI values changing on transparent mode packets has been resolved.
++           3) Previously, successful firmware OAM loopback cells waited 5 seconds before notifying the
++              OS of success, rather that notifying immediately.  This has been resolved in firmware.
++           4) PITS #148 (MAC and SAR), #149 (MAC) have been fixed.
++
++New features: 1) AAL5 HAL now capable of receiving unknown VCI/VPI cells on a single transparent channel.
++                 See updated HAL document (AAL5 appendix) for implementation details.
++              2) AAL5 HAL now allows OS to modify the OAM loopback timeout window.  Previously, failed
++                 OAM loopback attempts timed out after a nominal 5 seconds (based on the SAR frequency
++                 provided by the OS).  Now, the default is 5 seconds, but the OS may change the
++                 value via halControl() to any integer number of milliseconds.  See updated HAL document
++                 (AAL5 appendix) for implementation details.
++              3) MAC (cpmdio): added loopback to Istate.  Used for debug.
++
++Known issues not addressed in this release: NTR.
++
++09 June 2003         CPSAR 1.6.1 (external release), CPMAC 1.6.1 (internal release - no functional change)
++
++Note: This is the same set of fixes being applied to 1.6.0 that were applied to 1.5.3.  The only difference
++      between 1.6.1 and 1.5.4 is that 1.6.1 has the TurboDSL fix.
++
++CC Labels: REL_20030609_HALdallas_cpmac_01.06.01
++           REL_20030609_HALdallas_cpsar_01.06.01
++
++Bug fixes: 1) Bug in OamLoopbackConfig fixed.
++           2) New firmware version (.43) to fix Westell issue of dropped downstream packets in
++              presence of OAM traffic when operating at or near line rate.
++
++New features: NTR.
++
++09 June 2003         CPSAR 1.5.4 (external release), CPMAC 1.5.4 (internal release - no functional change)
++
++Note:  This is a branch release from 1.5.3.  This does not contain anything from 1.6.0.  The CPMAC is
++only being labeled to keep the release flow consistent.
++
++CC Labels: REL_20030609_HALdallas_cpmac_01.05.04
++           REL_20030609_HALdallas_cpsar_01.05.04
++
++Bug fixes: 1) Bug in OamLoopbackConfig fixed.
++           2) New firmware version (.43) to fix Westell issue of dropped downstream packets in
++              presence of OAM traffic when operating at or near line rate.
++
++New features: NTR.
++
++30 May 2003         CPSAR 1.6.0 (external release), CPMAC 1.6.0 (internal release - no functional change)
++
++CC Labels: REL_20030530_HALdallas_cpmac_01.06.00
++           REL_20030530_HALdallas_cpsar_01.06.00
++
++Bug fixes: 1) TurboDSL issue has been fixed with a software workaround in TxInt.  This workaround
++              has been verified under Adam2 ONLY at this point.  Testing remains to be done on
++              Linux and VxWorks.
++
++New features: NTR.
++
++Known issues not addressed in this release: NTR.
++
++30 May 2003         CPSAR 1.5.3 (external release), CPMAC 1.5.3 (internal release - no functional change)
++
++CC Labels: REL_20030530_HALdallas_cpmac_01.05.03
++           REL_20030530_HALdallas_cpsar_01.05.03
++
++Bug fixes: NTR.
++
++New features: 1) AAL5 Send() has been modified to accept an ATM Header either in the first
++                 fragment by itself, or in the first fragment directly in front of payload data.
++                 The API() does not change.
++              2) Documentation updates throughout, reflected in latest version of CPHAL user's
++                 guide.
++              3) AAL5 MaxFrags default value is now 46.  This is based upon the default AAL5
++                 RxBufSize of 1518 (MaxFrags = (65568/1518) + 2).  IF THE OS CHOOSES A SMALLER
++                 RxBufSize, IT MUST INCREASE THE VALUE OF MaxFrags ACCORDINGLY.  This is done
++                 via halControl(), prior to Open().
++
++Known issues not addressed in this release:
++              1) The Linux SAR driver is seeing an issue in which it cannot
++                 reliably send traffic simultaneously on both the high and
++                 low priority queues of a single AAL5 channel. (TurboDSL)
++
++23 May 2003         CPHAL 1.5.2 (external release)
++
++CC Labels: REL_20030523_HALdallas_cpmac_01.05.02
++           REL_20030523_HALdallas_cpsar_01.05.02
++
++Bug fixes: 1) PITS #138: CPMAC flooding issue resolved.
++           2) PITS #142: OS may now set "MaxFrags" via Control().  This controls the
++              maximum number of fragments expected by the CPHAL.  The default value is 2 for
++              CPMAC and 1028 for AAL5.  If the OS chooses a RxBufSize that will cause more
++              fragments than the defaults, the OS must set "MaxFrags" to a correct value
++              ((maximum packet length / RxBufSize) + 2).
++           3) PITS #143: Fixed.
++           4) Firmware OAM bug fixed. (new firmware release in this version)
++
++New features: NTR.
++
++Known issues not addressed in this release:
++              1) The Linux SAR driver is seeing an issue in which it cannot
++                 reliably send traffic simultaneously on both the high and
++                 low priority queues of a single AAL5 channel. (TurboDSL)
++
++14 May 2003         CPHAL 1.5.1 (external release)
++
++CC Labels: REL_20030514_HALdallas_cpmac_01.05.01
++           REL_20030514_HALdallas_cpsar_01.05.01
++
++Bug fixes:    1) PITS 132 - (CPMAC) Frames < 60 bytes and split into
++                             multi-fragments.
++              2) BCIL MR PSP00000353 - (CPMAC) PhyDev not free'd on halClose()
++              3) PITS 113 - OsSetup bug in ChannelSetup fixed.
++              4) Fixed AAL5 to check return values of InitTcb/InitRcb.
++              5) Fixed Shutdown to properly free resources in the case of a Close
++                 mode 1 followed by Shutdown.  Previously, buffer and descriptor
++                 resources were left unfreed in this case.
++
++New features: 1) AAL5 Send() modified to be capable of accepting ATM header as first four
++                 bytes of first fragment.  This allows the OS to "override" the
++                 default ATM header which is constructed from preconfigured channel
++                 parameters.
++              2) AAL5 Receive() modified to be capable of passing the received ATM header (4 bytes, no HEC)
++                 in the first fragment (by itself).  It also passes up the OS an indication
++                 of what the received packet type was.  For Host OAM and transparent mode
++                 packets, the ATM header is passed in this manner, and for other types of packets
++                 (AAL5, NULL AAL) no ATM header is passed currently.
++
++Known issues not addressed in this release:
++              1) The Linux SAR driver is seeing an issue in which it cannot
++                 reliably send traffic simultaneously on both the high and
++                 low priority queues of a single AAL5 channel.
++
++30 April 2003         CPHAL 1.5.0 (external release)
++
++CC Labels: REL_20030430_HALdallas_cpmac_01.05.00
++           REL_20030430_HALdallas_cpsar_01.05.00
++
++Bug fixes:   1) Fixed AAL5 bug that rendered the low priority queue
++                unusable.
++             2) Fixed a bug in AAL5's Oam Rate calculations.
++             3) Fixed use of "DeviceCPID" key in AAL5's halControl().
++             4) Fixed RxReturn logic in HAL.  The HAL now can handle
++                failing MallocRxBuffer calls when multiple fragments
++                are being used.
++
++New features: 1) AAL5 Stats now available on a per queue basis.
++              2) AAL5 adds two new keys to halControl() for "Set" actions:
++                 RxVc_OamCh and RxVp_OamCh.
++              3) Shutdown() has been modified for both AAL5 and CPMAC to
++                 call Close() if the module is still in the Open state.
++              4) CPMAC adds the following access keys to halControl():
++                 hcPhyAccess,hcPhyNum,hcCpmacBase,hcSize,and hcCpmacSize.
++              5) CPHAL no longer requests an extra 15 bytes on data buffer
++                 mallocs.
++
++Known issues not addressed in this release:
++              1) The Linux SAR driver is seeing an issue in which it cannot
++                 reliably send traffic simultaneously on both the high and
++                 low priority queues of a single AAL5 channel.
++
++21 April 2003         CPHAL 1.4.1 (external release)
++
++CC Labels: REL_20030421_HALdallas_cpmac_01.04.01
++           REL_20030421_HALdallas_cpsar_01.04.01
++
++Bug fixes:   1) Fixed OAM logic in SAR portion of CPHAL.
++
++New features: 1) OAM loopback counters exposed through halControl.
++              2) Host OAM Send() can now use a single channel to send
++                 OAM cells on unlimited number of VP's/VC's.
++              3) CPHAL now requests "SarFreq" through osControl.
++              4) CPHAL now calculates all OAM function rates based on
++                 "SarFreq"; function OamRateConfig removed for API.
++              5) New OAM function OamLoopbackConfig, used for configuring
++                 loopback functions in firmware OAM mode.
++
++Known issues not addressed in this release:  Bug fix 1) in release 1.4
++             (see below) does not work properly for multiple fragments.
++
++10 April 2003         CPHAL 1.4 (external release)
++
++CC Labels: REL_20030410_HALdallas_cpmac_01.04.00
++           REL_20030410_HALdallas_cpsar_01.04.00
++
++This release is for SAR and MAC.
++
++  Bug fixes: 1) Implemented logic in HAL to re-request buffer mallocs
++                in the case of MallocRxBuffer failing.  The HAL now maintains
++                a NeedsBuffer queue of all RCB's that are without buffers.
++                On interrupts, or on Send(), the HAL checks to see if any
++                RCB's are on the queue, and if so, calls MallocRxBuffer
++                to attempt to get a new buffer and return the RCB to
++                circulation.
++             2) SAR now properly returns all error codes from halOpen and
++                halChannelSetup.
++
++  New features: NTR
++
++  Known issues not addressed in this release: NTR
++
++08 April 2003         CPHAL 1.3.1 (internal release - SAR only)
++
++  CC Labels: REL_20030408_HALdallas_cpsar_01.03.01
++
++  This is a SAR only release.  The current CPMAC release is still 1.3.
++
++  Bug fixes: 1) PDSP State RAM / Scratchpad RAM is now completely cleared after reset.
++                This resolves a stability issue.
++
++  New features: 1) OamMode is now a parameter in halControl().  Both "Set" and "Get"
++                   actions are available.  The value may be "0" (Host OAM), or "1"
++                   (Firmware OAM).
++
++  Known issues not addressed in this release:
++             1) Appropriate action for HAL in the case of MallocRxBuffer failing.  We
++                are investigating whether the HAL should implement a needs buffer
++                queue.
++
++04 April 2003         CPHAL 1.3 (external release)
++
++  CC Labels: REL_20030404_HALdallas_cpmac_01.03.00
++             REL_20030404_HALdallas_cpsar_01.03.00
++             REL_20030404_HALdallas_cpaal5_01.03.00
++             REL_20030404_HALdallas_cpaal2_01.03.00
++
++  This release requires no changes for the ethernet end driver.  The changes necessary
++  for the sar driver (firmware file name changes) have already been implemented.
++
++  Bug fixes: 1) RxReturn now returns an error if MallocRxBuffer fails.  On RxReturn error, the driver should
++                call RxReturn again at a later time (when the malloc may succeed) in order for the CPHAL
++                to maintain a full complement of Rx buffers.  We recommend holding off making this driver
++                change until we verify that this condition occurs.
++
++  New features: 1) Removed benign compiler warnings.
++                2) PITS 122: http://www.nbu.sc.ti.com/cgi-bin/pits/redisplay_archive?product=cphal_dev&report=122
++                3) Cpsar label (above) now is applied to everything
++                   beneath /cpsar.
++                4) PITS 14: http://www.nbu.sc.ti.com/cgi-bin/pits/redisplay_archive?product=cphal_dev&report=14
++                   Transferred to MR PSP 00000089.
++                5) PITS 120: http://www.nbu.sc.ti.com/cgi-bin/pits/redisplay_archive?product=cphal_dev&report=120
++
++  Known issues not addressed in this release:
++             1) PITS 102 (as relating to OamMode configuration):
++                http://www.nbu.sc.ti.com/cgi-bin/pits/redisplay_archive?product=cphal_dev&report=102
++                Future release will make OamMode configurable
++                through halControl(), not on per channel basis.
++
++20 March 2003         CPHAL 1.2.1 (internal release)
++
++  CC Labels: REL_20030320_HALdallas_cpmac_01.02.01
++             REL_20030320_HALdallas_cpsar_01.02.01
++             REL_20030320_HALdallas_cpaal5_01.02.01
++             REL_20030320_HALdallas_cpaal2_01.02.01
++
++  Bug fixes: 1. Fixed modification of buffer pointer following
++                MallocRxBuffer in cppi.c.
++             2. Removed extra firmware files from /cpsar.
++
++  New features: NTR.
++
++  Known issues not addressed in this release: NTR.
++
++07 March 2003         CPHAL 1.2 (external release)
++
++  CPMAC/CPSAR feature complete release.  SAR added
++  several features including full OAM support and various
++  other features and bug fixes to address PITS 99-106, and
++  114.  CPMAC cleaned up details raised by India PSP
++  team.
++
++29 January 2003       CPHAL RC 3.01a (external release)
++
++  Corrects non-static functions to be static in cppi.c.
++
++09 Janurary 2003      CPHAL RC 3.01 (external release)
++
++  PITS 88: Fixed MDIO re-connection problem (hcpmac.c)
++  PITS 90: Corrected Rx Buffer Pointer modification (cppi.c)
++
++  Corrected error in cpremap.c
++
++20 December 2002      CPHAL RC 3 (external release)
++
++  Statistics support via halControl().  See Appendix A of guide.
++  Fixed errors in ChannelTeardown/ChannelSetup CPHAL logic.
++  Added multicast support as requested.
++  Several new OS string functions added to OS_FUNCTIONS.
++  "DebugLevel" configuration parameter changed to "Debug".
++  "Stats0" changed to "StatsDump" for CPMAC.
++
++13 December 2002      CPHAL RC 2.03 (internal release)
++
++  Performance improvements.
++  More debug statements implemented (esp AAL5).
++  Updated makefile with "make debug" option.
++  Hbridge performance: [debug library] 15774 tps (53% line rate)
++                   [non-debug library] 13700 tps (46%)
++
++10 December 2002      CPHAL Release Candidate 2.02 (internal release)
++
++ Much of the configuration code internal to CPMAC and AAL5 has been made common.
++ [os]Receive API had been modified to remove OsReceiveInfo.  This information is now
++   available as third member of the FRAGLIST structure, on a per buffer basis.
++ Successfully tested multi-fragment support on CPMAC, using 32 byte buffers.
++ Code is now Emerald compliant - all buffer descriptors now aligned to cache-line
++   boundaries.
++
++2 December 2002      CPHAL Release Candidate 2.01
++
++ Updates to comments in hcpmac.c, cpmdio.c, hcpmac.h
++ Nested comment in hcpmac.c in RC2 can cause compile errors.
++
++25 November 2002      CPHAL Release Candidate 2
++
++Project Items not completed for RC2
++#6  Ship as Library -  Once under CC. Moved to RC3
++#8  Under Clearcase -  Moved to RC3
++#25 Emerald compliant - Moved to RC3
++#26 Statistics support - Moved to RC3 (some support in RC2)
++#36 Debug scheme implemented - Moved to RC3 (some support in RC2)
++
++8 November 2002       CPHAL Release Candidate 1
++
++Notes:
++
++Project Items not completed for RC1
++
++#8  Under Clearcase -  Clearcase server failure this week. Moved to RC2
++#6  Ship as Library -  Once under CC. Moved to RC2
++#13 Verify Datatypes. Moved to RC2
++#14 Review APIs.  Moved to RC2
++
++APIs under review for RC2
++
++halIsr()
++hslRxReturn()
++halSend()
++osSendComplete()
++osReceive()
++
++
++CPMAC Build Instructions
++
++Compile the file 'hcpmac.c'.
++
++
++AAL5 Build Instructions
++
++The AAL5 build is composed of the source files aal5sar.c and cpsar.c.
++Refer to the provided makefile for an example of compiling these files
++into a library.
++
++Example CPHAL Code
++
++CPMAC:
++
++Example CPMAC code is provided in the file hbridge.c.
++This program is provided simply as an example of using the CPHAL API.
++It is not intended to be compiled and executed in your environment.
++
++AAL5:
++
++Example AAL5 code is provided in the file loopback.c.  This program
++is provided simply as an example of using the CPHAL API.  It is not
++intended to be compiled and executed in your environment.
++
++
++Performance Baseline
++
++
++Cpmac
++
++RC1: hbridge.bin, running with IXIA cpahl_1.cfg.
++     This sends 64-byte packets from each Ixia port, with mac destination the other Ixia port.
++     MIPS core 4Kc.
++
++RC2: hbridge.bin, running with IXIA cpahl_1.cfg.
++     This sends 64-byte packets from each Ixia port, with mac destination the other Ixia port.
++     MIPS core 4Ke.
++     CPHAL now includes Emerald support, but this has been disabled by using 'cache -wt' to emulate 4Kc.
++
++RC3: hbridge.bin, running with IXIA cpahl_1.cfg.
++     This sends 64-byte packets from each Ixia port, with mac destination the other Ixia port.
++     MIPS core 4Ke.
++     Running as Emerald processor.
++
++Release  Total Receive Rate    Throughput Setting
++
++RC1             11300                 38%
++RC2              9524                 32%
++RC3             15190                 51%
+diff -ruN linux-2.4.30.orig/drivers/net/Config.in linux-2.4.30/drivers/net/Config.in
+--- linux-2.4.30.orig/drivers/net/Config.in    2005-07-07 20:49:04.000000000 +0200
++++ linux-2.4.30/drivers/net/Config.in 2005-07-08 21:52:27.000000000 +0200
+@@ -25,6 +25,24 @@
+ comment 'Ethernet (10 or 100Mbit)'
+ bool 'Ethernet (10 or 100Mbit)' CONFIG_NET_ETHERNET
+ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
++   if [ "$CONFIG_MIPS_TITAN" = "y" -o "$CONFIG_AR7" = "y" ]; then
++        tristate '  Texas Instruments Avalanche CPMAC support' CONFIG_MIPS_AVALANCHE_CPMAC    
++   fi
++   if [ "$CONFIG_MIPS_AVALANCHE_CPMAC" != "n" ]; then
++     if [ "$CONFIG_AR7WRD" = "y" -o "$CONFIG_AR7VWI" = "y" -o "$CONFIG_AR7VW" = "y" ]; then
++       define_bool  CONFIG_MIPS_CPMAC_INIT_BUF_MALLOC y
++         define_int CONFIG_MIPS_CPMAC_PORTS 1
++       if [ "$CONFIG_MIPS_AVALANCHE_MARVELL" = "y" ]; then
++             define_bool CONFIG_AVALANCHE_LOW_CPMAC  n
++             define_bool CONFIG_AVALANCHE_HIGH_CPMAC y
++       else
++             define_bool CONFIG_AVALANCHE_CPMAC_AUTO y
++             define_bool CONFIG_AVALANCHE_LOW_CPMAC n
++             define_bool CONFIG_AVALANCHE_HIGH_CPMAC n
++      fi
++     fi
++   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 -ruN linux-2.4.30.orig/drivers/net/Makefile linux-2.4.30/drivers/net/Makefile
+--- linux-2.4.30.orig/drivers/net/Makefile     2005-07-07 20:49:03.000000000 +0200
++++ linux-2.4.30/drivers/net/Makefile  2005-07-08 21:52:57.000000000 +0200
+@@ -56,6 +56,16 @@
+ subdir-$(CONFIG_BONDING) += bonding
+ #
++# Texas Instruments AVALANCHE CPMAC  driver
++#
++
++subdir-$(CONFIG_MIPS_AVALANCHE_CPMAC) += avalanche_cpmac
++#obj-$(CONFIG_MIPS_AVALANCHE_CPMAC) += avalanche_cpmac/avalanche_cpmac.o
++ifeq ($(CONFIG_MIPS_AVALANCHE_CPMAC),y)
++  obj-y += avalanche_cpmac/avalanche_cpmac.o
++endif
++
++#
+ # link order important here
+ #
+ obj-$(CONFIG_PLIP) += plip.o