1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2024-11-15 08:05:21 +02:00
openwrt-xburst/openwrt/target/linux/linux-2.4/patches/ar7/003-net_driver_cpmac.patch

13342 lines
466 KiB
Diff
Raw Normal View History

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;