summaryrefslogtreecommitdiff
path: root/openwrt/target/linux/ar7-2.4/patches/003-net_driver_cpmac.patch
diff options
context:
space:
mode:
authornbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>2006-01-10 19:43:00 +0000
committernbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>2006-01-10 19:43:00 +0000
commit489f9455f265caba0edd3488fe9580e36418eb32 (patch)
tree227994a76fef5a3c7c651667756984dc69bddb2d /openwrt/target/linux/ar7-2.4/patches/003-net_driver_cpmac.patch
parent3224e1420fd9c58ce5bf3b67e871730be18f8fdd (diff)
large target/linux cleanup
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@2877 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'openwrt/target/linux/ar7-2.4/patches/003-net_driver_cpmac.patch')
-rw-r--r--openwrt/target/linux/ar7-2.4/patches/003-net_driver_cpmac.patch13341
1 files changed, 13341 insertions, 0 deletions
diff --git a/openwrt/target/linux/ar7-2.4/patches/003-net_driver_cpmac.patch b/openwrt/target/linux/ar7-2.4/patches/003-net_driver_cpmac.patch
new file mode 100644
index 0000000000..42b64584da
--- /dev/null
+++ b/openwrt/target/linux/ar7-2.4/patches/003-net_driver_cpmac.patch
@@ -0,0 +1,13341 @@
+diff -urN linux.old/drivers/net/avalanche_cpmac/cpcommon_cpmac.c linux.dev/drivers/net/avalanche_cpmac/cpcommon_cpmac.c
+--- linux.old/drivers/net/avalanche_cpmac/cpcommon_cpmac.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/cpcommon_cpmac.c 2005-07-12 02:48:41.996601000 +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 -urN linux.old/drivers/net/avalanche_cpmac/cpcommon_cpmac.h linux.dev/drivers/net/avalanche_cpmac/cpcommon_cpmac.h
+--- linux.old/drivers/net/avalanche_cpmac/cpcommon_cpmac.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/cpcommon_cpmac.h 2005-07-12 02:48:41.996601000 +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 -urN linux.old/drivers/net/avalanche_cpmac/cpmac.c linux.dev/drivers/net/avalanche_cpmac/cpmac.c
+--- linux.old/drivers/net/avalanche_cpmac/cpmac.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/cpmac.c 2005-07-22 01:03:12.609318544 +0200
+@@ -0,0 +1,2504 @@
++/******************************************************************************
++ * 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/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;
++
++#ifdef CONFIG_AR7_MDIX
++ if( avalanche_is_mdix_on_chip() )
++ {
++ val |= _CPMDIO_AUTOMDIX;
++ }
++#endif
++
++ 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 = CONFIG_AR7_SYS * 1000 * 1000;
++ 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 = CONFIG_AR7_SYS * 1000 * 1000;
++ 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) ;
++
++#ifdef CONFIG_AR7_MDIX
++ avalanche_set_mdix_on_chip(0xa8610000 , mdix ? 1: 0);
++#endif
++
++ 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
++
++ 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 = CONFIG_AR7_CPU * 1000 * 1000;
++
++ 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 -urN linux.old/drivers/net/avalanche_cpmac/cpmac.h linux.dev/drivers/net/avalanche_cpmac/cpmac.h
+--- linux.old/drivers/net/avalanche_cpmac/cpmac.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/cpmac.h 2005-07-12 02:48:42.043594000 +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 -urN linux.old/drivers/net/avalanche_cpmac/cpmacHalLx.c linux.dev/drivers/net/avalanche_cpmac/cpmacHalLx.c
+--- linux.old/drivers/net/avalanche_cpmac/cpmacHalLx.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/cpmacHalLx.c 2005-07-12 02:48:42.044593000 +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 <asm/ar7/avalanche_intc.h>
++
++#include "cpmacHalLx.h"
++#include "cpmac.h"
++
++/* PSP config headers */
++#include "psp_config_parse.h"
++#include "psp_config_mgr.h"
++
++/* 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 -urN linux.old/drivers/net/avalanche_cpmac/cpmacHalLx.h linux.dev/drivers/net/avalanche_cpmac/cpmacHalLx.h
+--- linux.old/drivers/net/avalanche_cpmac/cpmacHalLx.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/cpmacHalLx.h 2005-07-12 02:48:42.044593000 +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 -urN linux.old/drivers/net/avalanche_cpmac/cpmac_reg.h linux.dev/drivers/net/avalanche_cpmac/cpmac_reg.h
+--- linux.old/drivers/net/avalanche_cpmac/cpmac_reg.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/cpmac_reg.h 2005-07-12 02:48:42.045593000 +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 -urN linux.old/drivers/net/avalanche_cpmac/cpmdio.c linux.dev/drivers/net/avalanche_cpmac/cpmdio.c
+--- linux.old/drivers/net/avalanche_cpmac/cpmdio.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/cpmdio.c 2005-07-12 02:48:42.046593000 +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 -urN linux.old/drivers/net/avalanche_cpmac/cpmdio.h linux.dev/drivers/net/avalanche_cpmac/cpmdio.h
+--- linux.old/drivers/net/avalanche_cpmac/cpmdio.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/cpmdio.h 2005-07-12 02:48:42.047593000 +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 -urN linux.old/drivers/net/avalanche_cpmac/cppi_cpmac.c linux.dev/drivers/net/avalanche_cpmac/cppi_cpmac.c
+--- linux.old/drivers/net/avalanche_cpmac/cppi_cpmac.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/cppi_cpmac.c 2005-07-12 02:48:42.048593000 +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 -urN linux.old/drivers/net/avalanche_cpmac/cpremap_cpmac.c linux.dev/drivers/net/avalanche_cpmac/cpremap_cpmac.c
+--- linux.old/drivers/net/avalanche_cpmac/cpremap_cpmac.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/cpremap_cpmac.c 2005-07-12 02:48:42.049593000 +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 -urN linux.old/drivers/net/avalanche_cpmac/cpswhal_cpmac.h linux.dev/drivers/net/avalanche_cpmac/cpswhal_cpmac.h
+--- linux.old/drivers/net/avalanche_cpmac/cpswhal_cpmac.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/cpswhal_cpmac.h 2005-07-12 02:48:42.050593000 +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 -urN linux.old/drivers/net/avalanche_cpmac/dox_cpmac.h linux.dev/drivers/net/avalanche_cpmac/dox_cpmac.h
+--- linux.old/drivers/net/avalanche_cpmac/dox_cpmac.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/dox_cpmac.h 2005-07-12 02:48:42.050593000 +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 -urN linux.old/drivers/net/avalanche_cpmac/ec_errors_cpmac.h linux.dev/drivers/net/avalanche_cpmac/ec_errors_cpmac.h
+--- linux.old/drivers/net/avalanche_cpmac/ec_errors_cpmac.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/ec_errors_cpmac.h 2005-07-12 02:48:42.051592000 +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 -urN linux.old/drivers/net/avalanche_cpmac/hcpmac.c linux.dev/drivers/net/avalanche_cpmac/hcpmac.c
+--- linux.old/drivers/net/avalanche_cpmac/hcpmac.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/hcpmac.c 2005-07-12 02:48:42.174574000 +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 -urN linux.old/drivers/net/avalanche_cpmac/hcpmac.h linux.dev/drivers/net/avalanche_cpmac/hcpmac.h
+--- linux.old/drivers/net/avalanche_cpmac/hcpmac.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/hcpmac.h 2005-07-12 02:48:42.175574000 +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 -urN linux.old/drivers/net/avalanche_cpmac/Makefile linux.dev/drivers/net/avalanche_cpmac/Makefile
+--- linux.old/drivers/net/avalanche_cpmac/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/Makefile 2005-07-12 02:48:42.175574000 +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 -urN linux.old/drivers/net/avalanche_cpmac/mdio_reg.h linux.dev/drivers/net/avalanche_cpmac/mdio_reg.h
+--- linux.old/drivers/net/avalanche_cpmac/mdio_reg.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/mdio_reg.h 2005-07-12 02:48:42.176573000 +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 -urN linux.old/drivers/net/avalanche_cpmac/psp_config_build.c linux.dev/drivers/net/avalanche_cpmac/psp_config_build.c
+--- linux.old/drivers/net/avalanche_cpmac/psp_config_build.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/psp_config_build.c 2005-07-12 02:48:42.176573000 +0200
+@@ -0,0 +1,335 @@
++/******************************************************************************
++ * 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/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) | ((CONFIG_AR7_SYS * 1000)/2200);
++
++ 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 -urN linux.old/drivers/net/avalanche_cpmac/psp_config_build.h linux.dev/drivers/net/avalanche_cpmac/psp_config_build.h
+--- linux.old/drivers/net/avalanche_cpmac/psp_config_build.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/psp_config_build.h 2005-07-12 02:48:42.176573000 +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 -urN linux.old/drivers/net/avalanche_cpmac/psp_config_mgr.c linux.dev/drivers/net/avalanche_cpmac/psp_config_mgr.c
+--- linux.old/drivers/net/avalanche_cpmac/psp_config_mgr.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/psp_config_mgr.c 2005-07-12 02:48:42.177573000 +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 -urN linux.old/drivers/net/avalanche_cpmac/psp_config_mgr.h linux.dev/drivers/net/avalanche_cpmac/psp_config_mgr.h
+--- linux.old/drivers/net/avalanche_cpmac/psp_config_mgr.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/psp_config_mgr.h 2005-07-12 02:48:42.177573000 +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 -urN linux.old/drivers/net/avalanche_cpmac/psp_config_parse.c linux.dev/drivers/net/avalanche_cpmac/psp_config_parse.c
+--- linux.old/drivers/net/avalanche_cpmac/psp_config_parse.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/psp_config_parse.c 2005-07-12 02:48:42.178573000 +0200
+@@ -0,0 +1,362 @@
++/******************************************************************************
++ * 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 <linux/stddef.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 -urN linux.old/drivers/net/avalanche_cpmac/psp_config_parse.h linux.dev/drivers/net/avalanche_cpmac/psp_config_parse.h
+--- linux.old/drivers/net/avalanche_cpmac/psp_config_parse.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/psp_config_parse.h 2005-07-12 02:48:42.178573000 +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 -urN linux.old/drivers/net/avalanche_cpmac/psp_config_util.c linux.dev/drivers/net/avalanche_cpmac/psp_config_util.c
+--- linux.old/drivers/net/avalanche_cpmac/psp_config_util.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/psp_config_util.c 2005-07-12 02:48:42.178573000 +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 <linux/stddef.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 -urN linux.old/drivers/net/avalanche_cpmac/psp_config_util.h linux.dev/drivers/net/avalanche_cpmac/psp_config_util.h
+--- linux.old/drivers/net/avalanche_cpmac/psp_config_util.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/psp_config_util.h 2005-07-12 02:48:42.179573000 +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 -urN linux.old/drivers/net/avalanche_cpmac/readme.txt linux.dev/drivers/net/avalanche_cpmac/readme.txt
+--- linux.old/drivers/net/avalanche_cpmac/readme.txt 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/avalanche_cpmac/readme.txt 2005-07-12 02:48:42.179573000 +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 -urN linux.old/drivers/net/Config.in linux.dev/drivers/net/Config.in
+--- linux.old/drivers/net/Config.in 2005-07-12 03:20:45.726149872 +0200
++++ linux.dev/drivers/net/Config.in 2005-07-12 02:48:42.180573000 +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 -urN linux.old/drivers/net/Makefile linux.dev/drivers/net/Makefile
+--- linux.old/drivers/net/Makefile 2005-07-12 03:20:45.726149872 +0200
++++ linux.dev/drivers/net/Makefile 2005-07-12 02:48:42.181573000 +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
+--- linux.old/drivers/net/avalanche_cpmac/cpmac.c 2005-08-25 10:56:33.702931008 +0200
++++ linux.dev/drivers/net/avalanche_cpmac/cpmac.c 2005-08-25 11:08:45.027451520 +0200
+@@ -2158,17 +2158,16 @@
+ 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");
++ xdump(p_skb->data, fragList[0].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 &&
++ fragList[0].len > TCI_END_OFFSET &&
+ IS_802_1Q_FRAME(p_skb->data + TPID_START_OFFSET))
+ {
+ goto cpmac_hal_recv_frame_mismatch;