13341 lines
466 KiB
Diff
13341 lines
466 KiB
Diff
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(0 == strcmp(mac_port, "1")) {
|
|
+ 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(0 == strcmp(mac_port, "1"))
|
|
+ {
|
|
+ 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;
|