diff options
Diffstat (limited to 'target/linux/ar7-2.4/patches/003-net_driver_cpmac.patch')
-rw-r--r-- | target/linux/ar7-2.4/patches/003-net_driver_cpmac.patch | 13341 |
1 files changed, 13341 insertions, 0 deletions
diff --git a/target/linux/ar7-2.4/patches/003-net_driver_cpmac.patch b/target/linux/ar7-2.4/patches/003-net_driver_cpmac.patch new file mode 100644 index 0000000..06df07d --- /dev/null +++ b/target/linux/ar7-2.4/patches/003-net_driver_cpmac.patch @@ -0,0 +1,13341 @@ +diff -urN linux.old/drivers/net/avalanche_cpmac/cpcommon_cpmac.c linux.dev/drivers/net/avalanche_cpmac/cpcommon_cpmac.c +--- linux.old/drivers/net/avalanche_cpmac/cpcommon_cpmac.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/drivers/net/avalanche_cpmac/cpcommon_cpmac.c 2005-07-12 02:48:41.996601000 +0200 +@@ -0,0 +1,728 @@ ++#ifndef _INC_CPCOMMON_C ++#define _INC_CPCOMMON_C ++ ++#ifdef _CPHAL_CPMAC ++#include "cpremap_cpmac.c" ++#endif ++ ++#ifdef _CPHAL_AAL5 ++#include "cpremap_cpaal5.c" ++#endif ++ ++#ifdef _CPHAL_CPSAR ++#include "cpremap_cpsar.c" ++#endif ++ ++#ifdef _CPHAL_AAL2 ++#include "cpremap_cpaal2.c" ++#endif ++ ++/** ++@defgroup Common_Config_Params Common Configuration Parameters ++ ++This section documents the configuration parameters that are valid across ++all CPHAL devices. ++@{ ++*/ ++/** This is the debug level. The field is bit defined, such that the user ++should set to 1 all the bits corresponding to desired debug outputs. The following ++are the meanings for each debug bit: ++- bit0 (LSB): CPHAL Function Trace ++- b1 : OS Function call trace ++- b2 : Critical section entry/exit ++- b3 : Memory allocation/destruction ++- b4 : Detailed information in Rx path ++- b5 : Detailed information in Tx path ++- b6 : Extended error information ++- b7 : General info ++*/ ++static const char pszDebug[] = "debug"; ++/** CPU Frequency. */ ++/*static const char pszCpuFreq[] = "CpuFreq";*/ /*MJH-030403*/ ++/** Base address for the module. */ ++static const char pszBase[] = "base"; ++/** Reset bit for the module. */ ++static const char pszResetBit[] = "reset_bit"; ++/** Reset base address for the module. */ ++static const char pszResetBase[] = "ResetBase"; ++/** Interrupt line for the module. */ ++static const char pszIntLine[] = "int_line"; ++/** VLYNQ offset for the module. Disregard if not using VLYNQ. */ ++static const char pszOffset[] = "offset"; ++/** The OS may "Get" this parameter, which is a pointer ++ to a character string that indicates the version of CPHAL. */ ++static const char pszVer[] = "Version"; ++/*@}*/ ++ ++/** ++@defgroup Common_Control_Params Common Keys for [os]Control() ++ ++This section documents the keys used with the OS @c Control() interface that ++are required by CPHAL devices. ++ ++@{ ++*/ ++/** Used to wait for an integer number of clock ticks, given as an integer ++ pointer in the @p Value parameter. No actions are defined. */ ++static const char pszSleep[] = "Sleep"; ++/** Requests the OS to flush it's IO buffers. No actions are defined. */ ++static const char pszSioFlush[] = "SioFlush"; ++/*@}*/ ++ ++static const char pszStateChange[] = "StateChange"; ++static const char pszStatus[] = "Status"; ++ ++static const char pszGET[] = "Get"; ++static const char pszSET[] = "Set"; ++static const char pszCLEAR[] = "Clear"; ++static const char pszNULL[] = ""; ++static const char pszLocator[] = "Locator"; ++static const char pszOff[] = "Off"; ++static const char pszOn[] = "On"; ++static const char hcMaxFrags[] = "MaxFrags"; ++ ++#ifdef _CPHAL_CPMAC ++ ++/* New method for string constants */ ++const char hcClear[] = "Clear"; ++const char hcGet[] = "Get"; ++const char hcSet[] = "Set"; ++ ++const char hcTick[] = "Tick"; ++ ++static const CONTROL_KEY KeyCommon[] = ++ { ++ {"" , enCommonStart}, ++ {pszStatus , enStatus}, ++ {pszOff , enOff}, ++ {pszOn , enOn}, ++ {pszDebug , enDebug}, ++ {hcCpuFrequency , enCpuFreq}, /*MJH~030403*/ ++ {"" , enCommonEnd} ++ }; ++#endif ++ ++/** ++@defgroup Common_Statistics Statistics ++ ++A broad array of module statistics is available. Statistics values are accessed ++through the @c Control() interface of the CPHAL. There are 5 different levels ++of statistics, each of which correspond to a unique set of data. Furthermore, ++certain statistics data is indexed by using a channel number and Tx queue number. ++The following is a brief description of each statistics level, along with the ++indexes used for the level: ++ ++- Level 0: Hardware Statistics (index with channel) ++- Level 1: CPHAL Software Statistics (channel, queue) ++- Level 2: CPHAL Flags (channel, queue) ++- Level 3: CPHAL Channel Configuration (channel) ++- Level 4: CPHAL General Configuration (no index) ++ ++The caller requests statistics information by providing a Key string to the ++@c Control() API in the following format: "Stats;[Level #];[Ch #];[Queue #]". ++The only valid Action parameter for statistics usage is "Get". ++ ++Code Examples: ++@code ++unsigned int *StatsData; ++ ++# Get Level 0 stats for Channel 1 ++HalFunc->Control(OsDev->HalDev, "Stats;0;1", "Get", &StatsData); ++ ++# Get Level 2 stats for Channel 0, Queue 0 ++HalFunc->Control(OsDev->HalDev, "Stats;2;0;0", "Get", &StatsData); ++ ++# Get Level 4 stats ++HalFunc->Control(OsDev->HalDev, "Stats;4", "Get", &StatsData); ++@endcode ++ ++The information returned in the Value parameter of @c Control() is an ++array of pointers to strings. The pointers are arranged in pairs. ++The first pointer is a pointer to a name string for a particular statistic. ++The next pointer is a pointer to a string containing the representation of ++the integer statistic value corresponding to the first pointer. This is followed ++by another pair of pointers, and so on, until a NULL pointer is encountered. The ++following is example code for processing the statistics data. Note that the OS ++is responsible for freeing the memory passed back through the Value parameter of ++@c Control(). ++ ++@code ++unsigned int *StatsData; ++ ++# Get Level 0 stats for Channel 1 ++HalFunc->Control(OsDev->HalDev, "Stats;0;1", "Get", &StatsData); ++ ++# output Statistics data ++PrintStats(StatsData); ++ ++# the upper layer is responsible for freeing stats info ++free(&StatsPtr); ++ ++... ++ ++void PrintStats(unsigned int *StatsPtr) ++ { ++ while(*StatsPtr) ++ { ++ printf("%20s:", (char *)*StatsPtr); ++ StatsPtr++; ++ printf("%11s\n", (char *)*StatsPtr); ++ StatsPtr++; ++ } ++ MySioFlush(); ++ } ++@endcode ++ ++Within each statistics level, there are several statistics defined. The statistics that ++are common to every CPPI module are listed below. In addition, each module may define ++extra statistics in each level, which will be documented within the module-specific ++documentation appendices. ++ ++- Level 0 Statistics ++ - All level 0 statistics are module-specific. ++- Level 1 Statistics (CPHAL Software Statistics) ++ - DmaLenErrors: Incremented when the port DMA's more data than expected (per channel). (AAL5 Only) ++ - TxMisQCnt: Incremented when host queues a packet for transmission as the port finishes ++transmitting the previous last packet in the queue (per channel and queue). ++ - RxMisQCnt: Incremented when host queues adds buffers to a queue as the port finished the ++reception of the previous last packet in the queue (per channel). ++ - TxEOQCnt: Number of times the port has reached the end of the transmit queue (per channel and queue). ++ - RxEOQCnt: Number of times the port has reached the end of the receive queue (per channel). ++ - RxPacketsServiced: Number of received packets (per channel). ++ - TxPacketsServiced: Number of transmitted packets (per channel and queue). ++ - RxMaxServiced: Maximum number of packets that the CPHAL receive interrupt has serviced at a time (per channel). ++ - TxMaxServiced: Maximum number of packets that the CPHAL transmit interrupt has serviced at a time (per channel and queue). ++ - RxTotal: Total number of received packets, all channels. ++ - TxTotal: Total number of transmitted packets, all channels and queues. ++- Level 2 Statistics (CPHAL Flags) ++ - RcbPool: Pointer to receive descriptor pool (per channel). ++ - RxActQueueCount: Number of buffers currently available for receive (per channel). ++ - RxActQueueHead: Pointer to first buffer in receive queue (per channel). ++ - RxActQueueTail: Pointer to last buffer in receive queue (per channel). ++ - RxActive: 0 if inactive (no buffers available), or 1 if active (buffers available). ++ - RcbStart: Pointer to block of receive descriptors. ++ - RxTeardownPending: 1 if Rx teardown is pending but incomplete, 0 otherwise. ++ - TcbPool: Pointer to transmit descriptor pool (per channel and queue). ++ - TxActQueueCount: Number of buffers currently queued to be transmitted (per channel and queue). ++ - TxActQueueHead: Pointer to first buffer in transmit queue (per channel and queue). ++ - TxActQueueTail: Pointer to last buffer in transmit queue (per channel and queue). ++ - TxActive: 0 if inactive (no buffers to send), or 1 if active (buffers queued to send). ++ - TcbStart: Pointer to block of transmit descriptors. ++ - TxTeardownPending: 1 if Tx teardown is pending but incomplete, 0 otherwise. ++- Level 3 Statistics (CPHAL Channel Configuration) ++ - RxBufSize: Rx buffer size. ++ - RxBufferOffset: Rx buffer offset. ++ - RxNumBuffers: Number of Rx buffers. ++ - RxServiceMax: Maximum number of receive packets to service at a time. ++ - TxNumBuffers: Number of Tx buffer descriptors. ++ - TxNumQueues: Number of Tx queues to use. ++ - TxServiceMax: Maximum number of transmit packets to service at a time. ++- Level 4 Statistics (CPHAL General Configuration) ++ - Base Address: Base address of the module. ++ - Offset (VLYNQ): VLYNQ relative module offset. ++ - Interrupt Line: Interrupt number. ++ - Debug: Debug flag, 1 to enable debug. ++ - Inst: Instance number. ++*/ ++ ++/* ++ Data Type 0 = int display ++ Data Type 1 = hex display ++ Data Type 2 = channel structure, int display ++ Data Type 3 = queue index and int display ++ Data Type 4 = queue index and hex display ++*/ ++#if (defined(_CPHAL_AAL5) || defined(_CPHAL_CPMAC)) /* +GSG 030307 */ ++static STATS_TABLE StatsTable0[] = ++ { ++#ifdef _CPHAL_AAL5 ++ /* Name , Data Ptr, Data Type */ ++ {"Crc Errors", 0, 0}, ++ {"Len Errors", 0, 0}, ++ {"Abort Errors", 0, 0}, ++ {"Starv Errors", 0, 0} ++#endif ++#ifdef _CPHAL_CPMAC ++ {"Rx Good Frames", 0, 0} ++#endif ++ }; ++ ++static STATS_TABLE StatsTable1[] = ++ { ++ /* Name , Data Ptr, Data Type */ ++ {"DmaLenErrors", 0, 0}, ++ {"TxMisQCnt", 0, 3}, ++ {"RxMisQCnt", 0, 0}, ++ {"TxEOQCnt", 0, 3}, ++ {"RxEOQCnt", 0, 0}, ++ {"RxPacketsServiced", 0, 0}, ++ {"TxPacketsServiced", 0, 3}, ++ {"RxMaxServiced", 0, 0}, ++ {"TxMaxServiced", 0, 3}, ++ {"RxTotal", 0, 0}, ++ {"TxTotal", 0, 0}, ++ }; ++ ++static STATS_TABLE StatsTable2[] = ++ { ++ /* Name , Data Ptr, Data Type */ ++ {"RcbPool", 0, 1}, ++ {"RxActQueueCount", 0, 0}, ++ {"RxActQueueHead", 0, 1}, ++ {"RxActQueueTail", 0, 1}, ++ {"RxActive", 0, 0}, ++ {"RcbStart", 0, 1}, ++ {"RxTeardownPending", 0, 0}, ++ {"TcbPool", 0, 4}, ++ {"TxActQueueCount", 0, 3}, ++ {"TxActQueueHead", 0, 4}, ++ {"TxActQueueTail", 0, 4}, ++ {"TxActive", 0, 3}, ++ {"TcbStart", 0, 4}, ++ {"TxTeardownPending", 0, 0} ++ }; ++ ++static STATS_TABLE StatsTable3[] = ++ { ++ /* Name , Data Ptr, Data Type */ ++ {"RxBufSize", 0, 2}, ++ {"RxBufferOffset", 0, 2}, ++ {"RxNumBuffers", 0, 2}, ++ {"RxServiceMax", 0, 2}, ++ {"TxNumBuffers", 0, 2}, ++ {"TxNumQueues", 0, 2}, ++ {"TxServiceMax", 0, 2}, ++#ifdef _CPHAL_AAL5 ++ {"CpcsUU", 0, 2}, ++ {"Gfc", 0, 2}, ++ {"Clp", 0, 2}, ++ {"Pti", 0, 2}, ++ {"DaMask", 0, 2}, ++ {"Priority", 0, 2}, ++ {"PktType", 0, 2}, ++ {"Vci", 0, 2}, ++ {"Vpi", 0, 2}, ++ {"CellRate", 0, 2}, ++ {"QosType", 0, 2}, ++ {"Mbs", 0, 2}, ++ {"Pcr", 0, 2} ++#endif ++ }; ++ ++static STATS_TABLE StatsTable4[] = ++ { ++ {"Base Address", 0, 1}, ++ {"Offset (VLYNQ)", 0, 0}, ++ {"Interrupt Line", 0, 0}, ++ {"Debug", 0, 0}, ++ {"Instance", 0, 0}, ++#ifdef _CPHAL_AAL5 ++ {"UniNni", 0, 0} ++#endif ++ }; ++ ++static STATS_DB StatsDb[] = ++ { ++ {(sizeof(StatsTable0)/sizeof(STATS_TABLE)), StatsTable0}, ++ {(sizeof(StatsTable1)/sizeof(STATS_TABLE)), StatsTable1}, ++ {(sizeof(StatsTable2)/sizeof(STATS_TABLE)), StatsTable2}, ++ {(sizeof(StatsTable3)/sizeof(STATS_TABLE)), StatsTable3}, ++ {(sizeof(StatsTable4)/sizeof(STATS_TABLE)), StatsTable4} ++ }; ++#endif /* +GSG 030307 */ ++ ++#ifdef _CPHAL_CPMAC /* +RC 3.02 */ ++static void resetWait(HAL_DEVICE *HalDev) ++ { /*+RC3.02*/ ++ const int TickReset=64; ++ osfuncSleep((int*)&TickReset); ++ } /*+RC3.02*/ ++#endif /* +RC 3.02 */ ++ ++/* I only define the reset base function for the modules ++ that can perform a reset. The AAL5 and AAL2 modules ++ do not perform a reset, that is done by the shared module ++ CPSAR */ ++#if defined(_CPHAL_CPSAR) || defined(_CPHAL_CPMAC) || defined(_CPHAL_VDMAVT) ++/* ++ * Determines the reset register address to be used for a particular device. ++ * It will search the current device entry for Locator information. If the ++ * device is a root device, there will be no Locator information, and the ++ * function will find and return the root reset register. If a Locator value ++ * is found, the function will search each VLYNQ device entry in the system ++ * looking for a matching Locator. Once it finds a VLYNQ device entry with ++ * a matching Locator, it will extract the "ResetBase" parameter from that ++ * VLYNQ device entry (thus every VLYNQ entry must have the ResetBase parameter). ++ * ++ * @param HalDev CPHAL module instance. (set by xxxInitModule()) ++ * @param ResetBase Pointer to integer address of reset register. ++ * ++ * @return 0 OK, Non-zero not OK ++ */ ++static int ResetBaseGet(HAL_DEVICE *HalDev, bit32u *ResetBase) ++ { ++ char *DeviceInfo = HalDev->DeviceInfo; ++ char *MyLocator, *NextLocator; ++ int Inst=1; ++ bit32u error_code; ++ ++#ifdef __CPHAL_DEBUG ++ if (DBG(0)) ++ { ++ dbgPrintf("[cpcommon]ResetBaseGet(HalDev:%08x, ResetBase:%08x)\n", (bit32u)HalDev, ResetBase); ++ osfuncSioFlush(); ++ } ++#endif ++ ++ error_code = HalDev->OsFunc->DeviceFindParmValue(DeviceInfo, "Locator", &MyLocator); ++ if (error_code) ++ { ++ /* if no Locator value, device is on the root, so get the "reset" device */ ++ error_code = HalDev->OsFunc->DeviceFindInfo(0, "reset", &DeviceInfo); ++ if (error_code) ++ { ++ return(EC_VAL_DEVICE_NOT_FOUND); ++ } ++ ++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, "base", ResetBase); ++ if (error_code) ++ { ++ return(EC_VAL_BASE_ADDR_NOT_FOUND); ++ } ++ ++ *ResetBase = ((bit32u)PhysToVirtNoCache(*ResetBase)); ++ ++ /* found base address for root device, so we're done */ ++ return (EC_NO_ERRORS); ++ } ++ else ++ { ++ /* we have a Locator value, so the device is remote */ ++ ++ /* Find a vlynq device with a matching locator value */ ++ while ((HalDev->OsFunc->DeviceFindInfo(Inst, "vlynq", &DeviceInfo)) == EC_NO_ERRORS) ++ { ++ error_code = HalDev->OsFunc->DeviceFindParmValue(DeviceInfo, "Locator", &NextLocator); ++ if (error_code) ++ { ++ /* no Locator value for this VLYNQ, so move on */ ++ continue; ++ } ++ if (HalDev->OsFunc->Strcmpi(MyLocator, NextLocator)==0) ++ { ++ /* we have found a VLYNQ with a matching Locator, so extract the ResetBase */ ++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, "ResetBase", ResetBase); ++ if (error_code) ++ { ++ return(EC_VAL_BASE_ADDR_NOT_FOUND); ++ } ++ *ResetBase = ((bit32u)PhysToVirtNoCache(*ResetBase)); ++ ++ /* found base address for root device, so we're done */ ++ return (EC_NO_ERRORS); ++ } ++ Inst++; ++ } /* while */ ++ } /* else */ ++ ++ return (EC_NO_ERRORS); ++ } ++#endif ++ ++#ifndef _CPHAL_AAL2 /* + RC 3.02 */ ++static bit32u ConfigGetCommon(HAL_DEVICE *HalDev) ++ { ++ bit32u ParmValue; ++ bit32 error_code; ++ char *DeviceInfo = HalDev->DeviceInfo; ++ ++#ifdef __CPHAL_DEBUG ++ if (DBG(0)) ++ { ++ dbgPrintf("[cpcommon]ConfigGetCommon(HalDev:%08x)\n", (bit32u)HalDev); ++ osfuncSioFlush(); ++ } ++#endif ++ ++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszBase, &ParmValue); ++ if (error_code) ++ { ++ return(EC_FUNC_HAL_INIT|EC_VAL_BASE_ADDR_NOT_FOUND); ++ } ++ HalDev->dev_base = ((bit32u)PhysToVirtNoCache(ParmValue)); ++ ++#ifndef _CPHAL_AAL5 ++#ifndef _CPHAL_AAL2 ++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszResetBit, &ParmValue); ++ if(error_code) ++ { ++ return(EC_FUNC_HAL_INIT|EC_VAL_RESET_BIT_NOT_FOUND); ++ } ++ HalDev->ResetBit = ParmValue; ++ ++ /* Get reset base address */ ++ error_code = ResetBaseGet(HalDev, &ParmValue); ++ if (error_code) ++ return(EC_FUNC_HAL_INIT|EC_VAL_RESET_BASE_NOT_FOUND); ++ HalDev->ResetBase = ParmValue; ++#endif ++#endif ++ ++#ifndef _CPHAL_CPSAR ++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszIntLine,&ParmValue); ++ if (error_code) ++ { ++ return(EC_FUNC_HAL_INIT|EC_VAL_INTERRUPT_NOT_FOUND); ++ } ++ HalDev->interrupt = ParmValue; ++#endif ++ ++ /* only look for the offset if there is a Locator field, which indicates that ++ the module is a VLYNQ module */ ++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszLocator,&ParmValue); ++ if (!error_code) ++ { ++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszOffset,&ParmValue); ++ if (error_code) ++ { ++ return(EC_FUNC_HAL_INIT|EC_VAL_OFFSET_NOT_FOUND); ++ } ++ HalDev->offset = ParmValue; ++ } ++ else ++ HalDev->offset = 0; ++ ++ error_code = HalDev->OsFunc->DeviceFindParmUint(DeviceInfo, pszDebug, &ParmValue); ++ if (!error_code) HalDev->debug = ParmValue; ++ ++ return (EC_NO_ERRORS); ++ } ++#endif /* +RC 3.02 */ ++ ++#ifdef _CPHAL_CPMAC /* +RC 3.02 */ ++static void StatsInit(HAL_DEVICE *HalDev) /* +() RC3.02 */ ++ { ++ /* even though these statistics may be for multiple channels and ++ queues, i need only configure the pointer to the beginning ++ of the array, and I can index from there if necessary */ ++ ++#ifdef _CPHAL_AAL5 ++ StatsTable0[0].StatPtr = &HalDev->Stats.CrcErrors[0]; ++ StatsTable0[1].StatPtr = &HalDev->Stats.LenErrors[0]; ++ StatsTable0[2].StatPtr = &HalDev->Stats.AbortErrors[0]; ++ StatsTable0[3].StatPtr = &HalDev->Stats.StarvErrors[0]; ++ ++ StatsTable1[0].StatPtr = &HalDev->Stats.DmaLenErrors[0]; ++ StatsTable1[1].StatPtr = &HalDev->Stats.TxMisQCnt[0][0]; ++ StatsTable1[2].StatPtr = &HalDev->Stats.RxMisQCnt[0]; ++ StatsTable1[3].StatPtr = &HalDev->Stats.TxEOQCnt[0][0]; ++ StatsTable1[4].StatPtr = &HalDev->Stats.RxEOQCnt[0]; ++ StatsTable1[5].StatPtr = &HalDev->Stats.RxPacketsServiced[0]; ++ StatsTable1[6].StatPtr = &HalDev->Stats.TxPacketsServiced[0][0]; ++ StatsTable1[7].StatPtr = &HalDev->Stats.RxMaxServiced; ++ StatsTable1[8].StatPtr = &HalDev->Stats.TxMaxServiced[0][0]; ++ StatsTable1[9].StatPtr = &HalDev->Stats.RxTotal; ++ StatsTable1[10].StatPtr = &HalDev->Stats.TxTotal; ++#endif ++ ++#if (defined(_CPHAL_AAL5) || defined(_CPHAL_CPMAC)) ++ StatsTable2[0].StatPtr = (bit32u *)&HalDev->RcbPool[0]; ++ StatsTable2[1].StatPtr = &HalDev->RxActQueueCount[0]; ++ StatsTable2[2].StatPtr = (bit32u *)&HalDev->RxActQueueHead[0]; ++ StatsTable2[3].StatPtr = (bit32u *)&HalDev->RxActQueueTail[0]; ++ StatsTable2[4].StatPtr = &HalDev->RxActive[0]; ++ StatsTable2[5].StatPtr = (bit32u *)&HalDev->RcbStart[0]; ++ StatsTable2[6].StatPtr = &HalDev->RxTeardownPending[0]; ++ StatsTable2[7].StatPtr = (bit32u *)&HalDev->TcbPool[0][0]; ++ StatsTable2[8].StatPtr = &HalDev->TxActQueueCount[0][0]; ++ StatsTable2[9].StatPtr = (bit32u *)&HalDev->TxActQueueHead[0][0]; ++ StatsTable2[10].StatPtr = (bit32u *)&HalDev->TxActQueueTail[0][0]; ++ StatsTable2[11].StatPtr = &HalDev->TxActive[0][0]; ++ StatsTable2[12].StatPtr = (bit32u *)&HalDev->TcbStart[0][0]; ++ StatsTable2[13].StatPtr = &HalDev->TxTeardownPending[0]; ++ ++ StatsTable3[0].StatPtr = &HalDev->ChData[0].RxBufSize; ++ StatsTable3[1].StatPtr = &HalDev->ChData[0].RxBufferOffset; ++ StatsTable3[2].StatPtr = &HalDev->ChData[0].RxNumBuffers; ++ StatsTable3[3].StatPtr = &HalDev->ChData[0].RxServiceMax; ++ StatsTable3[4].StatPtr = &HalDev->ChData[0].TxNumBuffers; ++ StatsTable3[5].StatPtr = &HalDev->ChData[0].TxNumQueues; ++ StatsTable3[6].StatPtr = &HalDev->ChData[0].TxServiceMax; ++#ifdef _CPHAL_AAL5 ++ StatsTable3[7].StatPtr = &HalDev->ChData[0].CpcsUU; ++ StatsTable3[8].StatPtr = &HalDev->ChData[0].Gfc; ++ StatsTable3[9].StatPtr = &HalDev->ChData[0].Clp; ++ StatsTable3[10].StatPtr = &HalDev->ChData[0].Pti; ++ StatsTable3[11].StatPtr = &HalDev->ChData[0].DaMask; ++ StatsTable3[12].StatPtr = &HalDev->ChData[0].Priority; ++ StatsTable3[13].StatPtr = &HalDev->ChData[0].PktType; ++ StatsTable3[14].StatPtr = &HalDev->ChData[0].Vci; ++ StatsTable3[15].StatPtr = &HalDev->ChData[0].Vpi; ++ StatsTable3[16].StatPtr = &HalDev->ChData[0].TxVc_CellRate; ++ StatsTable3[17].StatPtr = &HalDev->ChData[0].TxVc_QosType; ++ StatsTable3[18].StatPtr = &HalDev->ChData[0].TxVc_Mbs; ++ StatsTable3[19].StatPtr = &HalDev->ChData[0].TxVc_Pcr; ++#endif ++#endif ++ ++ StatsTable4[0].StatPtr = &HalDev->dev_base; ++ StatsTable4[1].StatPtr = &HalDev->offset; ++ StatsTable4[2].StatPtr = &HalDev->interrupt; ++ StatsTable4[3].StatPtr = &HalDev->debug; ++ StatsTable4[4].StatPtr = &HalDev->Inst; ++ } ++#endif /* +RC 3.02 */ ++ ++#ifndef _CPHAL_CPSAR /* +RC 3.02 */ ++#ifndef _CPHAL_AAL2 /* +RC 3.02 */ ++/* ++ * Returns statistics information. ++ * ++ * @param HalDev CPHAL module instance. (set by xxxInitModule()) ++ * ++ * @return 0 ++ */ ++static int StatsGet(HAL_DEVICE *HalDev, void **StatPtr, int Index, int Ch, int Queue) ++ { ++ int Size; ++ bit32u *AddrPtr; ++ char *DataPtr; ++ STATS_TABLE *StatsTable; ++ int i, NumberOfStats; ++ ++#ifdef __CPHAL_DEBUG ++ if (DBG(0)) ++ { ++ dbgPrintf("[cpcommon]StatsGet(HalDev:%08x, StatPtr:%08x)\n", ++ (bit32u)HalDev, (bit32u)StatPtr); ++ osfuncSioFlush(); ++ } ++#endif ++ ++ StatsTable = StatsDb[Index].StatTable; ++ NumberOfStats = StatsDb[Index].NumberOfStats; ++ ++ Size = sizeof(bit32u)*((NumberOfStats*2)+1); ++ Size += (NumberOfStats*11); ++ *StatPtr = (bit32u *)HalDev->OsFunc->Malloc(Size); ++ ++ AddrPtr = (bit32u *) *StatPtr; ++ DataPtr = (char *)AddrPtr; ++ DataPtr += sizeof(bit32u)*((NumberOfStats*2)+1); ++ ++ for (i=0; i<NumberOfStats; i++) ++ { ++ *AddrPtr++ = (bit32u)StatsTable[i].StatName; ++ *AddrPtr++ = (bit32u)DataPtr; ++ if (&StatsTable[i].StatPtr[Ch] != 0) ++ { ++ switch(StatsTable[i].DataType) ++ { ++ case 0: ++ HalDev->OsFunc->Sprintf(DataPtr, "%d", (bit32u *)StatsTable[i].StatPtr[Ch]); ++ break; ++ case 1: ++ HalDev->OsFunc->Sprintf(DataPtr, "0x%x", (bit32u *)StatsTable[i].StatPtr[Ch]); ++ break; ++ case 2: ++ HalDev->OsFunc->Sprintf(DataPtr, "%d", *((bit32u *)StatsTable[i].StatPtr + (Ch * (sizeof(CHANNEL_INFO)/4)))); ++ break; ++ case 3: ++ HalDev->OsFunc->Sprintf(DataPtr, "%d", *((bit32u *)StatsTable[i].StatPtr + (Ch*MAX_QUEUE)+Queue)); ++ break; ++ case 4: ++ HalDev->OsFunc->Sprintf(DataPtr, "0x%x", *((bit32u *)StatsTable[i].StatPtr + (Ch*MAX_QUEUE)+Queue)); ++ break; ++ default: ++ /* invalid data type, due to CPHAL programming error */ ++ break; ++ } ++ } ++ else ++ { ++ /* invalid statistics pointer, probably was not initialized */ ++ } ++ DataPtr += HalDev->OsFunc->Strlen(DataPtr) + 1; ++ } ++ ++ *AddrPtr = (bit32u) 0; ++ ++ return (EC_NO_ERRORS); ++ } ++#endif /* +RC 3.02 */ ++#endif /* +RC 3.02 */ ++ ++#ifdef _CPHAL_CPMAC ++static void gpioFunctional(int base, int bit) ++ { /*+RC3.02*/ ++ bit32u GpioEnr = base + 0xC; ++ /* To make functional, set to zero */ ++ *(volatile bit32u *)(GpioEnr) &= ~(1 << bit); /*+RC3.02*/ ++ } /*+RC3.02*/ ++ ++ ++/*+RC3.02*/ ++/* Common function, Checks to see if GPIO should be in functional mode */ ++static void gpioCheck(HAL_DEVICE *HalDev, void *moduleDeviceInfo) ++ { /*+RC3.02*/ ++ int rc; ++ void *DeviceInfo; ++ char *pszMuxBits; ++ char pszMuxBit[20]; ++ char *pszTmp; ++ char szMuxBit[20]; ++ char *ptr; ++ int base; ++ int reset_bit; ++ int bit; ++ OS_FUNCTIONS *OsFunc = HalDev->OsFunc; ++ ++ rc = OsFunc->DeviceFindParmValue(moduleDeviceInfo, "gpio_mux",&pszTmp); ++ if(rc) return; ++ /* gpio entry found, get GPIO register info and make functional */ ++ ++ /* temp copy until FinParmValue fixed */ ++ ptr = &szMuxBit[0]; ++ while ((*ptr++ = *pszTmp++)); ++ ++ pszMuxBits = &szMuxBit[0]; ++ ++ rc = OsFunc->DeviceFindInfo(0,"gpio",&DeviceInfo); ++ if(rc) return; ++ ++ rc = OsFunc->DeviceFindParmUint(DeviceInfo, "base",&base); ++ if(rc) return; ++ ++ rc = OsFunc->DeviceFindParmUint(DeviceInfo, "reset_bit",&reset_bit); ++ if(rc) return; ++ ++ /* If GPIO still in reset, then exit */ ++ if((VOLATILE32(HalDev->ResetBase) & (1 << reset_bit)) == 0) ++ return; ++ /* format for gpio_mux is gpio_mux = <int>;<int>;<int>...*/ ++ while (*pszMuxBits) ++ { ++ pszTmp = &pszMuxBit[0]; ++ if(*pszMuxBits == ';') pszMuxBits++; ++ while ((*pszMuxBits != ';') && (*pszMuxBits != '\0')) ++ { ++ osfuncSioFlush(); ++ /*If value not a number, skip */ ++ if((*pszMuxBits < '0') || (*pszMuxBits > '9')) ++ pszMuxBits++; ++ else ++ *pszTmp++ = *pszMuxBits++; ++ } ++ *pszTmp = '\0'; ++ bit = OsFunc->Strtoul(pszMuxBit, &pszTmp, 10); ++ gpioFunctional(base, bit); ++ resetWait(HalDev); /* not sure if this is needed */ ++ } ++ } /*+RC3.02*/ ++#endif /* CPMAC */ ++ ++#ifdef _CPHAL_AAL5 ++const char hcSarFrequency[] = "SarFreq"; ++#endif ++ ++#endif /* _INC */ +diff -urN linux.old/drivers/net/avalanche_cpmac/cpcommon_cpmac.h linux.dev/drivers/net/avalanche_cpmac/cpcommon_cpmac.h +--- linux.old/drivers/net/avalanche_cpmac/cpcommon_cpmac.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/drivers/net/avalanche_cpmac/cpcommon_cpmac.h 2005-07-12 02:48:41.996601000 +0200 +@@ -0,0 +1,79 @@ ++#ifndef _INC_CPCOMMON_H ++#define _INC_CPCOMMON_H ++ ++#define VOLATILE32(addr) (*(volatile bit32u *)(addr)) ++#ifndef dbgPrintf ++#define dbgPrintf HalDev->OsFunc->Printf ++#endif ++ ++#define ChannelUpdate(Field) if(HalChn->Field != 0xFFFFFFFF) HalDev->ChData[Ch].Field = HalChn->Field ++ ++#define DBG(level) (HalDev->debug & (1<<(level))) ++/* ++#define DBG0() DBG(0) ++#define DBG1() DBG(1) ++#define DBG2() DBG(2) ++#define DBG3() DBG(3) ++#define DBG4() DBG(4) ++#define DBG5() DBG(5) ++#define DBG6() DBG(6) ++#define DBG7() DBG(7) ++*/ ++ ++/* ++ * List of defined actions for use with Control(). ++ */ ++typedef enum ++ { ++ enGET=0, /**< Get the value associated with a key */ ++ enSET, /**< Set the value associates with a key */ ++ enCLEAR, /**<Clear the value */ ++ enNULL /**< No data action, used to initiate a service or send a message */ ++ }ACTION; ++ ++/* ++ * Enumerated hardware states. ++ */ ++typedef enum ++ { ++ enConnected=1, enDevFound, enInitialized, enOpened ++ }DEVICE_STATE; ++ ++typedef enum ++ { ++ enCommonStart=0, ++ /* General */ ++ enOff, enOn, enDebug, ++ /* Module General */ ++ enCpuFreq, ++ enStatus, ++ enCommonEnd ++ }COMMON_KEY; ++ ++typedef struct ++ { ++ const char *strKey; ++ int enKey; ++ }CONTROL_KEY; ++ ++typedef struct ++ { ++ char *StatName; ++ unsigned int *StatPtr; ++ int DataType; /* 0: int, 1: hex int, 2:channel data */ ++ }STATS_TABLE; ++ ++typedef struct ++ { ++ int NumberOfStats; ++ STATS_TABLE *StatTable; ++ }STATS_DB; ++ ++#define osfuncSioFlush() HalDev->OsFunc->Control(HalDev->OsDev,"SioFlush",pszNULL,0) ++#define osfuncSleep(Ticks) HalDev->OsFunc->Control(HalDev->OsDev,pszSleep,pszNULL,Ticks) ++#define osfuncStateChange() HalDev->OsFunc->Control(HalDev->OsDev,pszStateChange,pszNULL,0) ++ ++#define CHANNEL_NAMES {"Ch0","Ch1","Ch2","Ch3","Ch4","Ch5","Ch6","Ch7","Ch8","Ch9","Ch10","Ch11","Ch12","Ch13","Ch14","Ch15"} ++ ++#endif ++ +diff -urN linux.old/drivers/net/avalanche_cpmac/cpmac.c linux.dev/drivers/net/avalanche_cpmac/cpmac.c +--- linux.old/drivers/net/avalanche_cpmac/cpmac.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/drivers/net/avalanche_cpmac/cpmac.c 2005-07-22 01:03:12.609318544 +0200 +@@ -0,0 +1,2504 @@ ++/****************************************************************************** ++ * FILE PURPOSE: CPMAC Linux Network Device Driver Source ++ ****************************************************************************** ++ * FILE NAME: cpmac.c ++ * ++ * DESCRIPTION: CPMAC Network Device Driver Source ++ * ++ * REVISION HISTORY: ++ * ++ * Date Description Author ++ *----------------------------------------------------------------------------- ++ * 27 Nov 2002 Initial Creation Suraj S Iyer ++ * 09 Jun 2003 Updates for GA Suraj S Iyer ++ * 30 Sep 2003 Updates for LED, Reset stats Suraj S Iyer ++ * ++ * (C) Copyright 2003, Texas Instruments, Inc ++ *******************************************************************************/ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/netdevice.h> ++#include <linux/etherdevice.h> ++#include <linux/delay.h> ++#include <linux/spinlock.h> ++#include <linux/proc_fs.h> ++#include <linux/ioport.h> ++#include <asm/io.h> ++ ++#include <linux/skbuff.h> ++ ++#include <asm/mips-boards/prom.h> ++#include <linux/string.h> ++#include <asm/uaccess.h> ++#include <linux/config.h> ++#include <asm/ar7/if_port.h> ++ ++extern void build_psp_config(void); ++extern void psp_config_cleanup(void); ++ ++#include "cpmacHalLx.h" ++#include "cpmac.h" ++ ++static struct net_device *last_cpmac_device = NULL; ++static int cpmac_devices_installed = 0; ++ ++void xdump( u_char* cp, int length, char* prefix ); ++ ++unsigned int cpmac_cpu_freq = 0; ++ ++char cpmac_version[] = "1.5"; ++ ++char l3_align_array[] = {0x02, 0x01, 0x00, 0x03}; ++#define L3_ALIGN(i) l3_align_array[i] ++ ++char add_for_4byte_align[] = {0x04, 0x03, 0x02, 0x05}; ++#define ADD_FOR_4BYTE_ALIGN(i) add_for_4byte_align[i] ++ ++ ++#define TPID 0x8100 ++#define IS_802_1Q_FRAME(byte_ptr) (*(unsigned short*)byte_ptr == TPID) ++#define TPID_START_OFFSET 12 ++#define TCI_START_OFFSET 14 ++#define TCI_LENGTH 2 ++#define TPID_LENGTH 2 ++#define TPID_END_OFFSET (TPID_START_OFFSET + TPID_LENGTH) ++#define TCI_END_OFFSET (TCI_START_OFFSET + TCI_LENGTH) ++#define IS_VALID_VLAN_ID(byte_ptr) ((*(unsigned short*)byte_ptr) && 0xfff != 0) ++#define MAX_CLASSES 8 ++#define MAX_USER_PRIORITY 8 ++#define CONTROL_802_1Q_SIZE (TCI_LENGTH + TPID_LENGTH) ++ ++unsigned char user_priority_to_traffic_class_map[MAX_CLASSES][MAX_USER_PRIORITY] = ++{ ++ {0, 0, 0, 1, 1, 1, 1, 2}, ++ {0, 0, 0, 0, 0, 0, 0, 0}, ++ {0, 0, 0, 0, 0, 0, 0, 1}, ++ {0, 0, 0, 1, 1, 2, 2, 3}, ++ {0, 1, 1, 2, 2, 3, 3, 4}, ++ {0, 1, 1, 2, 3, 4, 4, 5}, ++ {0, 1, 2, 3, 4, 5, 5, 6}, ++ {0, 1, 2, 3, 4, 5, 6, 7} ++}; ++ ++#define GET_802_1P_CHAN(x,y) user_priority_to_traffic_class_map[x][(y & 0xe0)] ++ ++#if defined(CONFIG_MIPS_SEAD2) ++unsigned long temp_base_address[2] = {0xa8610000, 0xa8612800}; ++unsigned long temp_reset_value[2] = { 1<< 17,1<<21}; ++#define RESET_REG_PRCR (*(volatile unsigned int *)((0xa8611600 + 0x0))) ++#define VERSION(base) (*(volatile unsigned int *)(((base)|0xa0000000) + 0x0)) ++#endif ++ ++MODULE_AUTHOR("Maintainer: Suraj S Iyer <ssiyer@ti.com>"); ++MODULE_DESCRIPTION("Driver for TI CPMAC"); ++ ++static int cfg_link_speed = 0; ++MODULE_PARM(cfg_link_speed, "i"); ++MODULE_PARM_DESC(cfg_link_speed, "Fixed speed of the Link: <100/10>"); ++ ++static char *cfg_link_mode = NULL; ++MODULE_PARM(cfg_link_mode, "1-3s"); ++MODULE_PARM_DESC(cfg_link_mode, "Fixed mode of the Link: <fd/hd>"); ++ ++int cpmac_debug_mode = 0; ++MODULE_PARM(debug_mode, "i"); ++MODULE_PARM_DESC(debug_mode, "Turn on the debug info: <0/1>. Default is 0 (off)"); ++ ++#define dbgPrint if (cpmac_debug_mode) printk ++#define errPrint printk ++ ++static int g_cfg_start_link_params = CFG_START_LINK_SPEED; ++static int g_init_enable_flag = 0; ++static int cfg_start_link_speed; ++static int cpmac_max_frame_size; ++ ++static struct net_device *g_dev_array[2]; ++static struct proc_dir_entry *gp_stats_file = NULL; ++ ++//----------------------------------------------------------------------------- ++// Statistics related private functions. ++//----------------------------------------------------------------------------- ++static int cpmac_p_update_statistics(struct net_device *p_dev, char *buf, int limit, int *len); ++static int cpmac_p_read_rfc2665_stats(char *buf, char **start, off_t offset, int count, int *eof, void *data); ++static int cpmac_p_read_link(char *buf, char **start, off_t offset, int count, int *eof, void *data); ++static int cpmac_p_read_stats(char* buf, char **start, off_t offset, int count, int *eof, void *data); ++static int cpmac_p_write_stats (struct file *fp, const char * buf, unsigned long count, void * data); ++static int cpmac_p_reset_statistics (struct net_device *p_dev); ++static int cpmac_p_get_version(char *buf, char **start, off_t offset, int count, int *eof, void *data); ++ ++static int cpmac_p_detect_manual_cfg(int, char*, int); ++static int cpmac_p_process_status_ind(CPMAC_PRIVATE_INFO_T *p_cpmac_priv); ++ ++//----------------------------------------------------------------------------- ++// Timer related private functions. ++//----------------------------------------------------------------------------- ++static int cpmac_p_timer_init(CPMAC_PRIVATE_INFO_T *p_cpmac_priv); ++// static int cpmac_timer_cleanup(CPMAC_PRIVATE_INFO_T *p_cpmac_priv); ++static void cpmac_p_tick_timer_expiry(unsigned long p_cb_param); ++inline static int cpmac_p_start_timer(struct timer_list *p_timer, unsigned int delay_ticks); ++static int cpmac_p_stop_timer(struct timer_list *p_timer); ++ ++//------------------------------------------------------------------------------ ++// Device configuration and setup related private functions. ++//------------------------------------------------------------------------------ ++static int cpmac_p_probe_and_setup_device(CPMAC_PRIVATE_INFO_T *p_cpmac_priv, unsigned long *p_dev_flags); ++static int cpmac_p_setup_driver_params(CPMAC_PRIVATE_INFO_T *p_cpmac_priv); ++inline static int cpmac_p_rx_buf_setup(CPMAC_RX_CHAN_INFO_T *p_rx_chan); ++ ++//----------------------------------------------------------------------------- ++// Net device related private functions. ++//----------------------------------------------------------------------------- ++static int cpmac_dev_init(struct net_device *p_dev); ++static int cpmac_dev_open( struct net_device *dev ); ++static int cpmac_dev_close(struct net_device *p_dev); ++static void cpmac_dev_mcast_set(struct net_device *p_dev); ++static int cpmac_dev_set_mac_addr(struct net_device *p_dev,void * addr); ++static int cpmac_dev_tx( struct sk_buff *skb, struct net_device *p_dev); ++static struct net_device_stats *cpmac_dev_get_net_stats (struct net_device *dev); ++ ++static int cpmac_p_dev_enable( struct net_device *p_dev); ++ ++ ++ ++/* Max. Reserved headroom in front of each packet so that the headers can be added to ++ * a packet. Worst case scenario would be PPPoE + 2684 LLC Encapsulation + Ethernet ++ * header. */ ++#define MAX_RESERVED_HEADROOM 20 ++ ++/* This is the MAX size of the static buffer for pure data. */ ++#define MAX_SIZE_STATIC_BUFFER 1600 ++ ++typedef struct DRIVER_BUFFER ++{ ++ /* Pointer to the allocated data buffer. This is the static data buffer ++ * allocated for the TI-Cache. 60 bytes out of the below buffer are required ++ * by the SKB shared info. We always reserve at least MAX_RESERVED_HEADROOM bytes ++ * so that the packets always have sufficient headroom. */ ++ char ptr_buffer[MAX_SIZE_STATIC_BUFFER + MAX_RESERVED_HEADROOM + 60]; ++ ++ /* List of the driver buffers. */ ++ struct DRIVER_BUFFER* ptr_next; ++}DRIVER_BUFFER; ++ ++typedef struct DRIVER_BUFFER_MCB ++{ ++ /* List of the driver buffers. */ ++ DRIVER_BUFFER* ptr_available_driver_buffers; ++ ++ /* The number of available buffers. */ ++ int num_available_buffers; ++}DRIVER_BUFFER_MCB; ++ ++DRIVER_BUFFER_MCB driver_mcb; ++int hybrid_mode = 0; ++ ++static union { ++ struct sk_buff_head list; ++ char pad[SMP_CACHE_BYTES]; ++} skb_head_pool[NR_CPUS]; ++ ++/************************************************************************** ++ * FUNCTION NAME : ti_release_skb ++ ************************************************************************** ++ * DESCRIPTION : ++ * This function is called from the ti_alloc_skb when there were no more ++ * data buffers available. The allocated SKB had to released back to the ++ * data pool. The reason why this function was moved from the fast path ++ * below was because '__skb_queue_head' is an inline function which adds ++ * a large code chunk on the fast path. ++ * ++ * NOTES : ++ * This function is called with interrupts disabled. ++ **************************************************************************/ ++static void ti_release_skb (struct sk_buff_head* list, struct sk_buff* skb) ++{ ++ __skb_queue_head(list, skb); ++ return; ++} ++ ++/************************************************************************** ++ * FUNCTION NAME : ti_alloc_skb ++ ************************************************************************** ++ * DESCRIPTION : ++ * The function is called to allocate memory from the static allocated ++ * TI-Cached memory pool. ++ * ++ * RETURNS : ++ * Allocated static memory buffer - Success ++ * NULL - Error. ++ **************************************************************************/ ++struct sk_buff *ti_alloc_skb(unsigned int size,int gfp_mask) ++{ ++ register struct sk_buff* skb; ++ unsigned long flags; ++ struct sk_buff_head* list; ++ DRIVER_BUFFER* ptr_node = NULL; ++ ++ /* Critical Section Begin: Lock out interrupts. */ ++ local_irq_save(flags); ++ ++ /* Get the SKB Pool list associated with the processor and dequeue the head. */ ++ list = &skb_head_pool[smp_processor_id()].list; ++ skb = __skb_dequeue(list); ++ ++ /* Align the data size. */ ++ size = SKB_DATA_ALIGN(size); ++ ++ /* Did we get one. */ ++ if (skb != NULL) ++ { ++ /* YES. Now get a data block from the head of statically allocated block. */ ++ ptr_node = driver_mcb.ptr_available_driver_buffers; ++ if (ptr_node != NULL) ++ { ++ /* YES. Got a data block. Advance the free list pointer to the next available buffer. */ ++ driver_mcb.ptr_available_driver_buffers = ptr_node->ptr_next; ++ ptr_node->ptr_next = NULL; ++ ++ /* Decrement the number of available data buffers. */ ++ driver_mcb.num_available_buffers = driver_mcb.num_available_buffers - 1; ++ } ++ else ++ { ++ /* NO. Was unable to get a data block. So put the SKB back on the free list. ++ * This is slow path. */ ++#ifdef DEBUG_SKB ++ printk ("DEBUG: No Buffer memory available: Number of free buffer:%d.\n", ++ driver_mcb.num_available_buffers); ++#endif ++ ti_release_skb (list, skb); ++ } ++ } ++ ++ /* Critical Section End: Unlock interrupts. */ ++ local_irq_restore(flags); ++ ++ /* Did we get an SKB and data buffer. Proceed only if we were succesful in getting both else drop */ ++ if (skb != NULL && ptr_node != NULL) ++ { ++ /* XXX: does not include slab overhead */ ++ skb->truesize = size + sizeof(struct sk_buff); ++ ++ /* Load the data pointers. */ ++ skb->head = ptr_node->ptr_buffer; ++ skb->data = ptr_node->ptr_buffer + MAX_RESERVED_HEADROOM; ++ skb->tail = ptr_node->ptr_buffer + MAX_RESERVED_HEADROOM; ++ skb->end = ptr_node->ptr_buffer + size + MAX_RESERVED_HEADROOM; ++ ++ /* Set up other state */ ++ skb->len = 0; ++ skb->cloned = 0; ++ skb->data_len = 0; ++ ++ /* Mark the SKB indicating that the SKB is from the TI cache. */ ++ skb->cb[45] = 1; ++ ++ atomic_set(&skb->users, 1); ++ atomic_set(&(skb_shinfo(skb)->dataref), 1); ++ skb_shinfo(skb)->nr_frags = 0; ++ skb_shinfo(skb)->frag_list = NULL; ++ return skb; ++ } ++ else ++ { ++ /* Control comes here only when there is no statically allocated data buffers ++ * available. This case is handled using the mode selected ++ * ++ * 1. Hybrid Mode. ++ * In that case lets jump to the old allocation code. This way we ++ * can allocate a small number of data buffers upfront and the rest will hit ++ * this portion of the code, which is slow path. Note the number of hits here ++ * should be kept as low as possible to satisfy performance requirements. ++ * ++ * 2. Pure Static Mode. ++ * Return NULL the user should have tuned the number of static buffers for ++ * worst case scenario. So return NULL and let the drivers handle the error. */ ++ if (hybrid_mode == 1) ++ { ++ /* Hybrid Mode: Old allocation. */ ++ return dev_alloc_skb(size); ++ } ++ else ++ { ++ /* Pure Static Mode: No buffers available. */ ++ return NULL; ++ } ++ } ++} ++ ++/************************************************************************** ++ * FUNCTION NAME : ti_skb_release_fragment ++ ************************************************************************** ++ * DESCRIPTION : ++ * This function is called to release fragmented packets. This is NOT in ++ * the fast path and this function requires some work. ++ **************************************************************************/ ++static void ti_skb_release_fragment(struct sk_buff *skb) ++{ ++ if (skb_shinfo(skb)->nr_frags) ++ { ++ /* PANKAJ TODO: This portion has not been tested. */ ++ int i; ++#ifdef DEBUG_SKB ++ printk ("DEBUG: Releasing fragments in TI-Cached code.\n"); ++#endif ++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) ++ printk ("DEBUG: Fragmented Page = 0x%p.\n", skb_shinfo(skb)->frags[i].page); ++ } ++ ++ /* Check if there were any fragments present and if so clean all the SKB's. ++ * This is required to recursivly clean the SKB's. */ ++ if (skb_shinfo(skb)->frag_list) ++ skb_drop_fraglist(skb); ++ ++ return; ++} ++ ++/************************************************************************** ++ * FUNCTION NAME : ti_skb_release_data ++ ************************************************************************** ++ * DESCRIPTION : ++ * The function is called to release the SKB back into the TI-Cached static ++ * memory pool. ++ **************************************************************************/ ++static void ti_skb_release_data(struct sk_buff *skb) ++{ ++ DRIVER_BUFFER* ptr_node; ++ unsigned long flags; ++ ++ /* The SKB data can be cleaned only if the packet has not been cloned and we ++ * are the only one holding a reference to the data. */ ++ if (!skb->cloned || atomic_dec_and_test(&(skb_shinfo(skb)->dataref))) ++ { ++ /* Are there any fragments associated with the SKB ?*/ ++ if ((skb_shinfo(skb)->nr_frags != 0) || (skb_shinfo(skb)->frag_list != NULL)) ++ { ++ /* Slow Path: Try and clean up the fragments. */ ++ ti_skb_release_fragment (skb); ++ } ++ ++ /* Cleanup the SKB data memory. This is fast path. */ ++ ptr_node = (DRIVER_BUFFER *)skb->head; ++ ++ /* Critical Section: Lock out interrupts. */ ++ local_irq_save(flags); ++ ++ /* Add the data buffer to the list of available buffers. */ ++ ptr_node->ptr_next = driver_mcb.ptr_available_driver_buffers; ++ driver_mcb.ptr_available_driver_buffers = ptr_node; ++ ++ /* Increment the number of available data buffers. */ ++ driver_mcb.num_available_buffers = driver_mcb.num_available_buffers + 1; ++ ++ /* Criticial Section: Unlock interrupts. */ ++ local_irq_restore(flags); ++ } ++ return; ++} ++ ++ ++ ++ ++static unsigned char str2hexnum(unsigned char c) ++{ ++ if(c >= '0' && c <= '9') ++ return c - '0'; ++ if(c >= 'a' && c <= 'f') ++ return c - 'a' + 10; ++ if(c >= 'A' && c <= 'F') ++ return c - 'A' + 10; ++ return 0; ++} ++ ++static void str2eaddr(unsigned char *ea, unsigned char *str) ++{ ++ int i; ++ unsigned char num; ++ for(i = 0; i < 6; i++) { ++ if((*str == '.') || (*str == ':')) ++ str++; ++ num = str2hexnum(*str++) << 4; ++ num |= (str2hexnum(*str++)); ++ ea[i] = num; ++ } ++} ++ ++//----------------------------------------------------------------------------- ++// Statistics related private functions. ++//----------------------------------------------------------------------------- ++static int cpmac_p_update_statistics(struct net_device *p_dev, char *buf, int limit, int *p_len) ++{ ++ int ret_val = -1; ++ unsigned long rx_hal_errors = 0; ++ unsigned long rx_hal_discards = 0; ++ unsigned long tx_hal_errors = 0; ++ unsigned long ifOutDiscards = 0; ++ unsigned long ifInDiscards = 0; ++ unsigned long ifOutErrors = 0; ++ unsigned long ifInErrors = 0; ++ ++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv; ++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal; ++ CPMAC_DEVICE_MIB_T *p_device_mib = p_cpmac_priv->device_mib; ++ CPMAC_DRV_STATS_T *p_stats = p_cpmac_priv->stats; ++ CPMAC_DEVICE_MIB_T local_mib; ++ CPMAC_DEVICE_MIB_T *p_local_mib = &local_mib; ++ ++ struct net_device_stats *p_net_dev_stats = &p_cpmac_priv->net_dev_stats; ++ ++ int len = 0; ++ int dev_mib_elem_count = 0; ++ ++ /* do not access the hardware if it is in the reset state. */ ++ if(!test_bit(0, &p_cpmac_priv->set_to_close)) ++ { ++ if(p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "StatsDump", "Get", ++ p_local_mib) != 0) ++ { ++ errPrint("The stats dump for %s is failing.\n", p_dev->name); ++ return(ret_val); ++ } ++ ++ p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "StatsClear", "Set", NULL); ++ ++ dev_mib_elem_count = sizeof(CPMAC_DEVICE_MIB_T)/sizeof(unsigned long); ++ ++ /* Update the history of the stats. This takes care of any reset of the ++ * device and stats that might have taken place during the life time of ++ * the driver. ++ */ ++ while(dev_mib_elem_count--) ++ { ++ *((unsigned long*) p_device_mib + dev_mib_elem_count) += ++ *((unsigned long*) p_local_mib + dev_mib_elem_count); ++ } ++ } ++ ++ /* RFC2665, section 3.2.7, page 9 */ ++ rx_hal_errors = p_device_mib->ifInFragments + ++ p_device_mib->ifInCRCErrors + ++ p_device_mib->ifInAlignCodeErrors + ++ p_device_mib->ifInJabberFrames; ++ ++ /* RFC2233 */ ++ rx_hal_discards = p_device_mib->ifRxDMAOverruns; ++ ++ /* RFC2665, section 3.2.7, page 9 */ ++ tx_hal_errors = p_device_mib->ifExcessiveCollisionFrames + ++ p_device_mib->ifLateCollisions + ++ p_device_mib->ifCarrierSenseErrors + ++ p_device_mib->ifOutUnderrun; ++ ++ /* if not set, the short frames (< 64 bytes) are considered as errors */ ++ if(!p_cpmac_priv->flags & IFF_PRIV_SHORT_FRAMES) ++ rx_hal_errors += p_device_mib->ifInUndersizedFrames; ++ ++ /* if not set, the long frames ( > 1518) are considered as errors ++ * RFC2665, section 3.2.7, page 9. */ ++ if(!p_cpmac_priv->flags & IFF_PRIV_JUMBO_FRAMES) ++ rx_hal_errors += p_device_mib->ifInOversizedFrames; ++ ++ /* if not in promiscous, then non addr matching frames are discarded */ ++ /* CPMAC 2.0 Manual Section 2.8.1.14 */ ++ if(!p_dev->flags & IFF_PROMISC) ++ { ++ ifInDiscards += p_device_mib->ifInFilteredFrames; ++ } ++ ++ /* total rx discards = hal discards + driver discards. */ ++ ifInDiscards = rx_hal_discards + p_net_dev_stats->rx_dropped; ++ ifInErrors = rx_hal_errors; ++ ++ ifOutErrors = tx_hal_errors; ++ ifOutDiscards = p_net_dev_stats->tx_dropped; ++ ++ /* Let us update the net device stats struct. To be updated in the later releases.*/ ++ p_cpmac_priv->net_dev_stats.rx_errors = ifInErrors; ++ p_cpmac_priv->net_dev_stats.collisions = p_device_mib->ifCollisionFrames; ++ ++ if(buf == NULL || limit == 0) ++ { ++ return(0); ++ } ++ ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %ld\n", "ifSpeed", (long)p_cpmac_priv->link_speed); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "dot3StatsDuplexStatus", (long)p_cpmac_priv->link_mode); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifAdminStatus", (long)(p_dev->flags & IFF_UP ? 1:2)); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifOperStatus", (long)(((p_dev->flags & IFF_UP) && netif_carrier_ok(p_dev)) ? 1:2)); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifLastChange", p_stats->start_tick); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInDiscards", ifInDiscards); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInErrors", ifInErrors); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifOutDiscards", ifOutDiscards); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifOutErrors", ifOutErrors); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInGoodFrames", p_device_mib->ifInGoodFrames); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInBroadcasts", p_device_mib->ifInBroadcasts); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInMulticasts", p_device_mib->ifInMulticasts); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInPauseFrames", p_device_mib->ifInPauseFrames); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInCRCErrors", p_device_mib->ifInCRCErrors); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInAlignCodeErrors", p_device_mib->ifInAlignCodeErrors); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInOversizedFrames", p_device_mib->ifInOversizedFrames); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInJabberFrames", p_device_mib->ifInJabberFrames); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInUndersizedFrames", p_device_mib->ifInUndersizedFrames); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInFragments", p_device_mib->ifInFragments); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInFilteredFrames", p_device_mib->ifInFilteredFrames); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInQosFilteredFrames", p_device_mib->ifInQosFilteredFrames); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifInOctets", p_device_mib->ifInOctets); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifOutGoodFrames", p_device_mib->ifOutGoodFrames); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifOutBroadcasts", p_device_mib->ifOutBroadcasts); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifOutMulticasts", p_device_mib->ifOutMulticasts); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifOutPauseFrames", p_device_mib->ifOutPauseFrames); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifDeferredTransmissions", p_device_mib->ifDeferredTransmissions); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifCollisionFrames", p_device_mib->ifCollisionFrames); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifSingleCollisionFrames", p_device_mib->ifSingleCollisionFrames); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifMultipleCollisionFrames", p_device_mib->ifMultipleCollisionFrames); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifExcessiveCollisionFrames", p_device_mib->ifExcessiveCollisionFrames); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifLateCollisions", p_device_mib->ifLateCollisions); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifOutUnderrun", p_device_mib->ifOutUnderrun); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifCarrierSenseErrors", p_device_mib->ifCarrierSenseErrors); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifOutOctets", p_device_mib->ifOutOctets); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "if64OctetFrames", p_device_mib->if64OctetFrames); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "if65To127POctetFrames", p_device_mib->if65To127OctetFrames); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "if128To255OctetFrames", p_device_mib->if128To255OctetFrames); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "if256To511OctetFrames", p_device_mib->if256To511OctetFrames); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "if512To1023OctetFrames", p_device_mib->if512To1023OctetFrames); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "if1024ToUpOctetFrames", p_device_mib->if1024ToUPOctetFrames); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifNetOctets", p_device_mib->ifNetOctets); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifRxSofOverruns", p_device_mib->ifRxSofOverruns); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifRxMofOverruns", p_device_mib->ifRxMofOverruns); ++ if(len <= limit) ++ len+= sprintf(buf + len, "%-35s: %lu\n", "ifRxDMAOverruns", p_device_mib->ifRxDMAOverruns); ++ ++ *p_len = len; ++ ++ return(0); ++} ++ ++ ++static int cpmac_p_read_rfc2665_stats(char* buf, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ int limit = count - 80; ++ int len = 0; ++ struct net_device *p_dev = (struct net_device*)data; ++ ++ cpmac_p_update_statistics(p_dev, buf, limit, &len); ++ ++ *eof = 1; ++ ++ return len; ++} ++ ++static int cpmac_p_read_link(char *buf, char **start, off_t offset, int count, ++ int *eof, void *data) ++{ ++ int len = 0; ++ ++ struct net_device *p_dev; ++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv; ++ struct net_device *cpmac_dev_list[cpmac_devices_installed]; ++ CPMAC_DRV_HAL_INFO_T *p_drv_hal; ++ ++ int i; ++ int phy; /* what phy are we using? */ ++ ++ len += sprintf(buf+len, "CPMAC devices = %d\n",cpmac_devices_installed); ++ ++ p_dev = last_cpmac_device; ++ ++ /* Reverse the the device link list to list eth0,eth1...in correct order */ ++ for(i=0; i< cpmac_devices_installed; i++) ++ { ++ cpmac_dev_list[cpmac_devices_installed -(i+1)] = p_dev; ++ p_cpmac_priv = p_dev->priv; ++ p_dev = p_cpmac_priv->next_device; ++ } ++ ++ for(i=0; i< cpmac_devices_installed; i++) ++ { ++ p_dev = cpmac_dev_list[i]; ++ p_cpmac_priv = p_dev->priv; ++ p_drv_hal = p_cpmac_priv->drv_hal; ++ ++ /* This prints them out from high to low because of how the devices are linked */ ++ if(netif_carrier_ok(p_dev)) ++ { ++ p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "PhyNum", "Get", &phy); ++ ++ ++ len += sprintf(buf+len,"eth%d: Link State: %s Phy:0x%x, Speed = %s, Duplex = %s\n", ++ p_cpmac_priv->instance_num, "UP", phy, ++ (p_cpmac_priv->link_speed == 100000000) ? "100":"10", ++ (p_cpmac_priv->link_mode == 2) ? "Half":"Full"); ++ ++ } ++ else ++ len += sprintf(buf+len,"eth%d: Link State: DOWN\n",p_cpmac_priv->instance_num); ++ ++ p_dev = p_cpmac_priv->next_device; ++ } ++ ++ return len; ++ ++} ++ ++static int cpmac_p_read_stats(char* buf, char **start, off_t offset, int count, ++ int *eof, void *data) ++{ ++ struct net_device *p_dev = last_cpmac_device; ++ int len = 0; ++ int limit = count - 80; ++ int i; ++ struct net_device *cpmac_dev_list[cpmac_devices_installed]; ++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv; ++ CPMAC_DEVICE_MIB_T *p_device_mib; ++ ++ /* Reverse the the device link list to list eth0,eth1...in correct order */ ++ for(i=0; i< cpmac_devices_installed; i++) ++ { ++ cpmac_dev_list[cpmac_devices_installed - (i+1)] = p_dev; ++ p_cpmac_priv = p_dev->priv; ++ p_dev = p_cpmac_priv->next_device; ++ } ++ ++ for(i=0; i< cpmac_devices_installed; i++) ++ { ++ p_dev = cpmac_dev_list[i]; ++ ++ if(!p_dev) ++ goto proc_error; ++ ++ /* Get Stats */ ++ cpmac_p_update_statistics(p_dev, NULL, 0, NULL); ++ ++ p_cpmac_priv = p_dev->priv; ++ p_device_mib = p_cpmac_priv->device_mib; ++ ++ /* Transmit stats */ ++ if(len<=limit) ++ len+= sprintf(buf+len, "\nCpmac %d, Address %lx\n",i+1, p_dev->base_addr); ++ if(len<=limit) ++ len+= sprintf(buf+len, " Transmit Stats\n"); ++ if(len<=limit) ++ len+= sprintf(buf+len, " Tx Valid Bytes Sent :%lu\n",p_device_mib->ifOutOctets); ++ if(len<=limit) ++ len+= sprintf(buf+len, " Good Tx Frames (Hardware) :%lu\n",p_device_mib->ifOutGoodFrames); ++ if(len<=limit) ++ len+= sprintf(buf+len, " Good Tx Frames (Software) :%lu\n",p_cpmac_priv->net_dev_stats.tx_packets); ++ if(len<=limit) ++ len+= sprintf(buf+len, " Good Tx Broadcast Frames :%lu\n",p_device_mib->ifOutBroadcasts); ++ if(len<=limit) ++ len+= sprintf(buf+len, " Good Tx Multicast Frames :%lu\n",p_device_mib->ifOutMulticasts); ++ if(len<=limit) ++ len+= sprintf(buf+len, " Pause Frames Sent :%lu\n",p_device_mib->ifOutPauseFrames); ++ if(len<=limit) ++ len+= sprintf(buf+len, " Collisions :%lu\n",p_device_mib->ifCollisionFrames); ++ if(len<=limit) ++ len+= sprintf(buf+len, " Tx Error Frames :%lu\n",p_cpmac_priv->net_dev_stats.tx_errors); ++ if(len<=limit) ++ len+= sprintf(buf+len, " Carrier Sense Errors :%lu\n",p_device_mib->ifCarrierSenseErrors); ++ if(len<=limit) ++ len+= sprintf(buf+len, "\n"); ++ ++ ++ /* Receive Stats */ ++ if(len<=limit) ++ len+= sprintf(buf+len, "\nCpmac %d, Address %lx\n",i+1,p_dev->base_addr); ++ if(len<=limit) ++ len+= sprintf(buf+len, " Receive Stats\n"); ++ if(len<=limit) ++ len+= sprintf(buf+len, " Rx Valid Bytes Received :%lu\n",p_device_mib->ifInOctets); ++ if(len<=limit) ++ len+= sprintf(buf+len, " Good Rx Frames (Hardware) :%lu\n",p_device_mib->ifInGoodFrames); ++ if(len<=limit) ++ len+= sprintf(buf+len, " Good Rx Frames (Software) :%lu\n",p_cpmac_priv->net_dev_stats.rx_packets); ++ if(len<=limit) ++ len+= sprintf(buf+len, " Good Rx Broadcast Frames :%lu\n",p_device_mib->ifInBroadcasts); ++ if(len<=limit) ++ len+= sprintf(buf+len, " Good Rx Multicast Frames :%lu\n",p_device_mib->ifInMulticasts); ++ if(len<=limit) ++ len+= sprintf(buf+len, " Pause Frames Received :%lu\n",p_device_mib->ifInPauseFrames); ++ if(len<=limit) ++ len+= sprintf(buf+len, " Rx CRC Errors :%lu\n",p_device_mib->ifInCRCErrors); ++ if(len<=limit) ++ len+= sprintf(buf+len, " Rx Align/Code Errors :%lu\n",p_device_mib->ifInAlignCodeErrors); ++ if(len<=limit) ++ len+= sprintf(buf+len, " Rx Jabbers :%lu\n",p_device_mib->ifInOversizedFrames); ++ if(len<=limit) ++ len+= sprintf(buf+len, " Rx Filtered Frames :%lu\n",p_device_mib->ifInFilteredFrames); ++ if(len<=limit) ++ len+= sprintf(buf+len, " Rx Fragments :%lu\n",p_device_mib->ifInFragments); ++ if(len<=limit) ++ len+= sprintf(buf+len, " Rx Undersized Frames :%lu\n",p_device_mib->ifInUndersizedFrames); ++ if(len<=limit) ++ len+= sprintf(buf+len, " Rx Overruns :%lu\n",p_device_mib->ifRxDMAOverruns); ++ } ++ ++ ++ return len; ++ ++ proc_error: ++ *eof=1; ++ return len; ++} ++ ++static int cpmac_p_write_stats (struct file *fp, const char * buf, unsigned long count, void * data) ++{ ++ char local_buf[31]; ++ int ret_val = 0; ++ ++ if(count > 30) ++ { ++ printk("Error : Buffer Overflow\n"); ++ printk("Use \"echo 0 > cpmac_stat\" to reset the statistics\n"); ++ return -EFAULT; ++ } ++ ++ copy_from_user(local_buf,buf,count); ++ local_buf[count-1]='\0'; /* Ignoring last \n char */ ++ ret_val = count; ++ ++ if(strcmp("0",local_buf)==0) ++ { ++ struct net_device *p_dev = last_cpmac_device; ++ int i; ++ struct net_device *cpmac_dev_list[cpmac_devices_installed]; ++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv; ++ ++ /* Valid command */ ++ printk("Resetting statistics for CPMAC interface.\n"); ++ ++ /* Reverse the the device link list to list eth0,eth1...in correct order */ ++ for(i=0; i< cpmac_devices_installed; i++) ++ { ++ cpmac_dev_list[cpmac_devices_installed - (i+1)] = p_dev; ++ p_cpmac_priv = p_dev->priv; ++ p_dev = p_cpmac_priv->next_device; ++ } ++ ++ for(i=0; i< cpmac_devices_installed; i++) ++ { ++ p_dev = cpmac_dev_list[i]; ++ if(!p_dev) ++ { ++ ret_val = -EFAULT; ++ break; ++ } ++ ++ cpmac_p_reset_statistics(p_dev); ++ } ++ } ++ else ++ { ++ printk("Error: Unknown operation on cpmac statistics\n"); ++ printk("Use \"echo 0 > cpmac_stats\" to reset the statistics\n"); ++ return -EFAULT; ++ } ++ ++ return ret_val; ++} ++ ++static int cpmac_p_reset_statistics(struct net_device *p_dev) ++{ ++ int ret_val = 0; ++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv; ++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal; ++ ++ memset(p_cpmac_priv->device_mib, 0, sizeof(CPMAC_DEVICE_MIB_T)); ++ memset(p_cpmac_priv->stats, 0, sizeof(CPMAC_DRV_STATS_T)); ++ memset(&p_cpmac_priv->net_dev_stats, 0, sizeof(struct net_device_stats)); ++ ++ p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "StatsClear", "Set", NULL); ++ ++ return(ret_val); ++} ++ ++static int cpmac_p_get_version(char* buf, char **start, off_t offset, int count,int *eof, void *data) ++{ ++ int len = 0; ++ int limit = count - 80; ++ char *hal_version = NULL; ++ struct net_device *p_dev = last_cpmac_device; ++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv; ++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal; ++ ++ p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "Version", "Get", &hal_version); ++ ++ len += sprintf(buf+len, "Texas Instruments CPMAC driver version: %s\n", cpmac_version); ++ ++ if(len <= limit && hal_version) ++ len += sprintf(buf+len, "Texas Instruments CPMAC HAL version: %s\n", hal_version); ++ ++ return len; ++} ++ ++static struct net_device_stats *cpmac_dev_get_net_stats (struct net_device *p_dev) ++{ ++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = (CPMAC_PRIVATE_INFO_T *) p_dev->priv; ++ ++ cpmac_p_update_statistics(p_dev, NULL, 0, NULL); ++ ++ return &p_cpmac_priv->net_dev_stats; ++} ++ ++static int cpmac_p_detect_manual_cfg(int link_speed, char* link_mode, int debug) ++{ ++ char *pSpeed = NULL; ++ ++ if(debug == 1) ++ { ++ cpmac_debug_mode = 1; ++ dbgPrint("Enabled the debug print.\n"); ++ } ++ ++ if(!link_speed && !link_mode) ++ { ++ dbgPrint("No manual link params, defaulting to auto negotiation.\n"); ++ return (0); ++ } ++ ++ if(!link_speed || (link_speed != 10 && link_speed != 100)) ++ { ++ dbgPrint("Invalid or No value of link speed specified, defaulting to auto speed.\n"); ++ pSpeed = "auto"; ++ } ++ else if(link_speed == 10) ++ { ++ g_cfg_start_link_params &= ~(_CPMDIO_100); ++ pSpeed = "10 Mbps"; ++ } ++ else ++ { ++ g_cfg_start_link_params &= ~(_CPMDIO_10); ++ pSpeed = "100 Mbps"; ++ } ++ ++ if(!link_mode || (!strcmp(link_mode, "fd") && !strcmp(link_mode, "hd"))) ++ { ++ dbgPrint("Invalid or No value of link mode specified, defaulting to auto mode.\n"); ++ } ++ else if(!strcmp(link_mode, "hd")) ++ { ++ g_cfg_start_link_params &= ~(_CPMDIO_FD); ++ } ++ else ++ { ++ g_cfg_start_link_params &= ~(_CPMDIO_HD); ++ } ++ ++ dbgPrint("Link is manually set to the speed of %s speed and %s mode.\n", ++ pSpeed, link_mode ? link_mode : "auto"); ++ ++ return(0); ++} ++ ++//------------------------------------------------------------------------------ ++// Call back from the HAL. ++//------------------------------------------------------------------------------ ++static int cpmac_p_process_status_ind(CPMAC_PRIVATE_INFO_T *p_cpmac_priv) ++{ ++ struct net_device *p_dev = p_cpmac_priv->owner; ++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal; ++ int status; ++ ++ p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "Status", "Get", &status); ++ ++ /* We do not reflect the real link status if in loopback. ++ * After all, we want the packets to reach the hardware so ++ * that Send() should work. */ ++ if(p_dev->flags & IFF_LOOPBACK) ++ { ++ dbgPrint("Maintaining the link up loopback for %s.\n", p_dev->name); ++ netif_carrier_on(p_dev); ++ ++//#if defined (CONFIG_MIPS_AVALANCHE_LED) ++// avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_LINK_ON); ++//#endif ++ ++ return(0); ++ } ++ ++ if(status & CPMAC_STATUS_ADAPTER_CHECK) /* ???? */ ++ { ++ ; /* what to do ? */ ++ } ++ else if(status) ++ { ++ if(!netif_carrier_ok(p_dev)) ++ { ++ netif_carrier_on(p_cpmac_priv->owner); ++ ++//#if defined (CONFIG_MIPS_AVALANCHE_LED) ++// avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_LINK_ON); ++//#endif ++ dbgPrint("Found the Link for the CPMAC instance %s.\n", p_dev->name); ++ } ++ ++ if(netif_running(p_dev) & netif_queue_stopped(p_dev)) ++ { ++ netif_wake_queue(p_dev); ++ } ++ ++ p_cpmac_priv->link_speed = status & CPMAC_STATUS_LINK_SPEED ? 100000000:10000000; ++ p_cpmac_priv->link_mode = status & CPMAC_STATUS_LINK_DUPLEX? 3:2; ++ ++ } ++ else ++ { ++ if(netif_carrier_ok(p_dev)) ++ { ++ /* do we need to register synchronization issues with stats here. */ ++ p_cpmac_priv->link_speed = 100000000; ++ p_cpmac_priv->link_mode = 1; ++ ++ netif_carrier_off(p_dev); ++ ++//#if defined (CONFIG_MIPS_AVALANCHE_LED) ++// avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_LINK_OFF); ++//#endif ++ ++ dbgPrint("Lost the Link for the CPMAC for %s.\n", p_dev->name); ++ } ++ ++ if(!netif_queue_stopped(p_dev)) ++ { ++ netif_stop_queue(p_dev); /* So that kernel does not keep on xmiting pkts. */ ++ } ++ } ++ ++ return(0); ++} ++ ++//----------------------------------------------------------------------------- ++// Timer related private functions. ++//----------------------------------------------------------------------------- ++static int cpmac_p_timer_init(CPMAC_PRIVATE_INFO_T *p_cpmac_priv) ++{ ++ struct timer_list *p_timer = p_cpmac_priv->timer; ++ ++ init_timer(p_timer); ++ ++ p_timer = p_cpmac_priv->timer + TICK_TIMER; ++ p_timer->expires = 0; ++ p_timer->data = (unsigned long)p_cpmac_priv; ++ p_timer->function = cpmac_p_tick_timer_expiry; ++ ++ return(0); ++} ++ ++#if 0 ++static int cpmac_timer_cleanup(CPMAC_PRIVATE_INFO_T *p_cpmac_priv) ++{ ++ struct timer_list *p_timer; ++ ++ p_timer = p_cpmac_priv->timer + TICK_TIMER; ++ ++ /* use spin lock to establish synchronization with the dispatch */ ++ if(p_timer->function) del_timer_sync(p_timer); ++ p_timer->function = NULL; ++ ++ return (0); ++} ++#endif ++ ++static int cpmac_p_start_timer(struct timer_list *p_timer, unsigned int delay_ticks) ++{ ++ p_timer->expires = jiffies + delay_ticks; ++ ++ if(p_timer->function) ++ { ++ add_timer(p_timer); ++ } ++ ++ return(0); ++} ++ ++static void cpmac_p_tick_timer_expiry(unsigned long p_cb_param) ++{ ++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = (CPMAC_PRIVATE_INFO_T*) p_cb_param; ++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal; ++ struct timer_list *p_timer = p_cpmac_priv->timer + TICK_TIMER; ++ ++ if(test_bit(0, &p_cpmac_priv->set_to_close)) ++ { ++ return; ++ } ++ ++ p_drv_hal->hal_funcs->Tick(p_drv_hal->hal_dev); ++ ++ cpmac_p_start_timer(p_timer, p_cpmac_priv->delay_ticks); ++} ++ ++static int cpmac_p_stop_timer(struct timer_list *p_timer) ++{ ++ /* Ideally we need to a set flag indicating not to start the timer again ++ before del_timer_sync() is called up. But here we assume that the ++ caller has set the p_cpmac_priv->set_to_close (ok for now). */ ++ del_timer_sync(p_timer); ++ ++ return(0); ++} ++ ++//------------------------------------------------------------------------------ ++// Device configuration and setup related private functions. ++//------------------------------------------------------------------------------ ++static int cpmac_p_probe_and_setup_device(CPMAC_PRIVATE_INFO_T *p_cpmac_priv, ++ unsigned long *p_dev_flags) ++{ ++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal; ++ HAL_FUNCTIONS *p_hal_funcs = p_drv_hal->hal_funcs; ++ HAL_DEVICE *p_hal_dev = p_drv_hal->hal_dev; ++ CPMAC_ABILITY_INFO_T *p_capability= p_cpmac_priv->ability_info; ++ unsigned int val = 0; ++ int channel = 0; ++ ++ p_cpmac_priv->flags = 0; ++ ++ p_capability->promiscous = CFG_PROMISCOUS; ++ p_capability->broadcast = CFG_BROADCAST; ++ p_capability->multicast = CFG_MULTICAST; ++ p_capability->all_multi = CFG_ALL_MULTI; ++ p_capability->jumbo_frames = CFG_JUMBO_FRAMES; ++ p_capability->short_frames = CFG_SHORT_FRAMES; ++ p_capability->auto_negotiation = CFG_AUTO_NEGOTIATION; ++ p_capability->link_speed = cfg_start_link_speed; ++ p_capability->loop_back = CFG_LOOP_BACK; ++ p_capability->tx_flow_control = CFG_TX_FLOW_CNTL; ++ p_capability->rx_flow_control = CFG_RX_FLOW_CNTL; ++ p_capability->tx_pacing = CFG_TX_PACING; ++ p_capability->rx_pass_crc = CFG_RX_PASS_CRC; ++ p_capability->qos_802_1q = CFG_QOS_802_1Q; ++ p_capability->tx_num_chan = CFG_TX_NUM_CHAN; ++ ++ /* Lets probe the device for the configured capabilities (netdev specific).*/ ++ ++ /* Following are set in the set_multi_list, when indicated by the kernel ++ * Promiscous and all multi. ++ */ ++ ++ if(p_capability->broadcast) ++ { ++ channel = 0; ++ val = 1; ++ if((p_hal_funcs->Control(p_hal_dev, pszRX_BROAD_EN, pszSet, &val) == 0) && ++ (p_hal_funcs->Control(p_hal_dev, pszRX_BROAD_CH, pszSet, &channel) == 0)) ++ *p_dev_flags |= IFF_BROADCAST; ++ else ++ p_capability->broadcast = 0; /* no broadcast capabilities */ ++ } ++ ++ if(p_capability->multicast) ++ { ++ val = 1; ++ channel = 0; ++ if((p_hal_funcs->Control(p_hal_dev, pszRX_MULT_EN, pszSet, &val) == 0) && ++ (p_hal_funcs->Control(p_hal_dev, pszRX_MULT_CH, pszSet, &channel) == 0)) ++ *p_dev_flags |= IFF_MULTICAST; ++ else ++ { ++ p_capability->multicast = 0; ++ p_capability->all_multi = 0; /* no multicast, no all-multi. */ ++ } ++ } ++ ++ if(p_capability->loop_back) ++ { ++ ; /* We do not put the device in loopback, if required use ioctl */ ++ } ++ ++ /* Lets probe the device for the configured capabilities (Non net device specific).*/ ++ ++ if(p_capability->jumbo_frames) ++ { ++ val = 0; ++ if(p_hal_funcs->Control(p_hal_dev, pszRX_NO_CHAIN, pszSet, &val) == 0) ++ p_cpmac_priv->flags |= IFF_PRIV_JUMBO_FRAMES; ++ else ++ p_capability->jumbo_frames = 0; ++ } ++ ++ if(p_capability->short_frames) ++ { ++ val = 1; ++ if(p_hal_funcs->Control(p_hal_dev, pszRX_CSF_EN, pszSet, &val) == 0) ++ p_cpmac_priv->flags |= IFF_PRIV_SHORT_FRAMES; ++ else ++ p_capability->short_frames = 0; ++ } ++ ++ val = g_cfg_start_link_params; ++ ++#ifdef CONFIG_AR7_MDIX ++ if( avalanche_is_mdix_on_chip() ) ++ { ++ val |= _CPMDIO_AUTOMDIX; ++ } ++#endif ++ ++ if(p_hal_funcs->Control(p_hal_dev,pszMdioConnect,pszSet, &val) !=0) ++ { ++ p_capability->link_speed = 0; ++ } ++ else ++ { ++ if(g_cfg_start_link_params & (_CPMDIO_100 | _CPMDIO_HD | _CPMDIO_FD | _CPMDIO_10)) ++ p_cpmac_priv->flags |= IFF_PRIV_AUTOSPEED; ++ else if(g_cfg_start_link_params & (_CPMDIO_100 | _CPMDIO_HD)) ++ p_cpmac_priv->flags |= IFF_PRIV_LINK100_HD; ++ else if(g_cfg_start_link_params & (_CPMDIO_100 | _CPMDIO_FD)) ++ p_cpmac_priv->flags |= IFF_PRIV_LINK100_FD; ++ else if(g_cfg_start_link_params & (_CPMDIO_10 | _CPMDIO_HD)) ++ p_cpmac_priv->flags |= IFF_PRIV_LINK10_HD; ++ else if(g_cfg_start_link_params & (_CPMDIO_10 | _CPMDIO_FD)) ++ p_cpmac_priv->flags |= IFF_PRIV_LINK10_FD; ++ else ++ ; ++ } ++ ++ if(p_capability->tx_flow_control) ++ { ++ val = 1; ++ if(p_hal_funcs->Control(p_hal_dev,pszTX_FLOW_EN, pszSet, &val) ==0) ++ p_cpmac_priv->flags |= IFF_PRIV_TX_FLOW_CNTL; ++ else ++ p_capability->tx_flow_control = 0; ++ } ++ ++ if(p_capability->rx_flow_control) ++ { ++ val = 1; ++ if(p_hal_funcs->Control(p_hal_dev, pszRX_FLOW_EN, pszSet, &val) ==0) ++ p_cpmac_priv->flags |= IFF_PRIV_RX_FLOW_CNTL; ++ else ++ p_capability->rx_flow_control = 0; ++ } ++ ++ if(p_capability->tx_pacing) ++ { ++ val = 1; ++ if(p_hal_funcs->Control(p_hal_dev, pszTX_PACE, pszSet, &val) ==0) ++ p_cpmac_priv->flags |= IFF_PRIV_TX_PACING; ++ else ++ p_capability->tx_pacing = 0; ++ } ++ ++ if(p_capability->rx_pass_crc) ++ { ++ val = 1; ++ if(p_hal_funcs->Control(p_hal_dev, pszRX_PASS_CRC, pszSet, &val) == 0) ++ p_cpmac_priv->flags |= IFF_PRIV_RX_PASS_CRC; ++ else ++ p_capability->rx_pass_crc = 0; ++ } ++ ++ if(p_capability->qos_802_1q) ++ { ++ val = 1; ++ if(p_hal_funcs->Control(p_hal_dev, pszRX_QOS_EN, pszSet, &val) == 0) ++ p_cpmac_priv->flags |= IFF_PRIV_8021Q_EN; ++ else ++ { ++ p_capability->qos_802_1q = 0; ++ p_capability->tx_num_chan= 1; ++ } ++ } ++ ++ if(p_capability->tx_num_chan > 1) ++ { ++ int cfg_tx_num_chan = p_capability->tx_num_chan; ++ val = 0; ++#ifdef TEST ++ if(p_hal_funcs->Control(p_hal_dev, pszTX_NUM_CH, pszGet, &val) == 0) ++ cfg_tx_num_chan = cfg_tx_num_chan > val ? val : cfg_tx_num_chan; ++ else ++ cfg_tx_num_chan = 1; ++#endif ++ p_capability->tx_num_chan = cfg_tx_num_chan; ++ } ++ ++ return(0); ++} ++ ++static int cpmac_p_setup_driver_params(CPMAC_PRIVATE_INFO_T *p_cpmac_priv) ++{ ++ int i=0; ++ int threshold = CFG_TX_NUM_BUF_SERVICE; ++ ++ char *tx_threshold_ptr = prom_getenv("threshold"); ++ ++ CPMAC_TX_CHAN_INFO_T *p_tx_chan_info = p_cpmac_priv->tx_chan_info; ++ CPMAC_RX_CHAN_INFO_T *p_rx_chan_info = p_cpmac_priv->rx_chan_info; ++ CPMAC_ABILITY_INFO_T *p_capability = p_cpmac_priv->ability_info; ++ ++ /* Timer stuff */ ++ p_cpmac_priv->timer_count = 1; /* should be < or = the MAX TIMER */ ++ p_cpmac_priv->timer_created = 0; ++ p_cpmac_priv->timer_access_hal = 1; ++ ++ for(i=0; i < MAX_TIMER; i++) ++ p_cpmac_priv->timer[i].function = NULL; ++ ++ p_cpmac_priv->enable_802_1q = p_capability->qos_802_1q; ++ ++ /* Tx channel related.*/ ++ p_tx_chan_info->cfg_chan = p_capability->tx_num_chan; ++ p_tx_chan_info->opened_chan = 0; ++ ++ if(tx_threshold_ptr) ++ threshold = simple_strtol(tx_threshold_ptr, (char **)NULL, 10); ++ ++ if((threshold <= 0) && tx_threshold_ptr) /* If threshold set to 0 then Enable the TX interrupt */ ++ { ++ threshold = CFG_TX_NUM_BUF_SERVICE; ++ p_tx_chan_info->tx_int_disable = 0; ++ ++ } ++ else ++ { ++ p_tx_chan_info->tx_int_disable = CFG_TX_INT_DISABLE; ++ } ++ ++ for(i=0; i < MAX_TX_CHAN; i++) ++ { ++ ++ ++ ++ p_tx_chan_info->chan[i].state = CHAN_CLOSE; ++ p_tx_chan_info->chan[i].num_BD = CFG_TX_NUM_BUF_DESC; ++ p_tx_chan_info->chan[i].buffer_size = cpmac_max_frame_size; ++ p_tx_chan_info->chan[i].buffer_offset = CFG_TX_BUF_OFFSET; ++ ++ ++ ++ p_tx_chan_info->chan[i].service_max = threshold; ++ } ++ ++ if (p_tx_chan_info->tx_int_disable) ++ printk("Cpmac driver Disable TX complete interrupt setting threshold to %d.\n",threshold); ++ else ++ printk("Cpmac driver Enable TX complete interrupt\n"); ++ ++ ++ /* Assuming just one rx channel for now */ ++ p_rx_chan_info->cfg_chan = 1; ++ p_rx_chan_info->opened_chan = 0; ++ p_rx_chan_info->chan->state = CHAN_CLOSE; ++ p_rx_chan_info->chan->num_BD = CFG_RX_NUM_BUF_DESC; ++ p_rx_chan_info->chan->buffer_size = cpmac_max_frame_size; ++ p_rx_chan_info->chan->buffer_offset = CFG_RX_BUF_OFFSET; ++ p_rx_chan_info->chan->service_max = CFG_RX_NUM_BUF_SERVICE; ++ ++ /* Set as per RFC 2665 */ ++ p_cpmac_priv->link_speed = 100000000; ++ p_cpmac_priv->link_mode = 1; ++ ++ p_cpmac_priv->loop_back = 0; ++ ++ return(0); ++} ++ ++inline static int cpmac_p_rx_buf_setup(CPMAC_RX_CHAN_INFO_T *p_rx_chan) ++{ ++ /* Number of ethernet packets & max pkt length */ ++ p_rx_chan->chan->tot_buf_size = p_rx_chan->chan->buffer_size + ++ 2*(CONTROL_802_1Q_SIZE) + ++ p_rx_chan->chan->buffer_offset + ++ ADD_FOR_4BYTE_ALIGN(p_rx_chan->chan->buffer_offset & 0x3); ++ ++ p_rx_chan->chan->tot_reserve_bytes = CONTROL_802_1Q_SIZE + ++ p_rx_chan->chan->buffer_offset + ++ L3_ALIGN(p_rx_chan->chan->buffer_offset & 0x3); ++ ++ return(0); ++} ++ ++//----------------------------------------------------------------------------- ++// Net device related private functions. ++//----------------------------------------------------------------------------- ++ ++/*************************************************************** ++ * cpmac_dev_init ++ * ++ * Returns: ++ * 0 on success, error code otherwise. ++ * Parms: ++ * dev The structure of the device to be ++ * init'ed. ++ * ++ * This function completes the initialization of the ++ * device structure and driver. It reserves the IO ++ * addresses and assignes the device's methods. ++ * ++ * ++ **************************************************************/ ++ ++static int cpmac_dev_init(struct net_device *p_dev) ++{ ++ int retVal = -1; ++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv; ++ int instance_num = p_cpmac_priv->instance_num; ++ unsigned long net_flags = 0; ++ char *mac_name = NULL; ++ char *mac_string = NULL; ++ ++ CPMAC_TX_CHAN_INFO_T *p_tx_chan_info; ++ CPMAC_RX_CHAN_INFO_T *p_rx_chan_info; ++ CPMAC_DRV_HAL_INFO_T *p_drv_hal; ++ int i; ++ ++ int mem_size = sizeof(CPMAC_DRV_HAL_INFO_T) ++ + sizeof(CPMAC_TX_CHAN_INFO_T) ++ + sizeof(CPMAC_RX_CHAN_INFO_T) ++ + sizeof(CPMAC_ABILITY_INFO_T) ++ + sizeof(CPMAC_DEVICE_MIB_T) ++ + sizeof(CPMAC_DRV_STATS_T); ++ ++ ++#if defined(CONFIG_MIPS_SEAD2) ++ int prev_reset_val = RESET_REG_PRCR; ++ /* Bring the module out of reset */ ++ RESET_REG_PRCR |= temp_reset_value[p_cpmac_priv->instance_num]; ++ ++ /* Read the version id of the device to check if the device really exists */ ++ if( VERSION(temp_base_address[p_cpmac_priv->instance_num]) == 0) ++ { ++ printk(" CPMAC:Device not found\n"); ++ RESET_REG_PRCR = prev_reset_val; ++ return -ENODEV; ++ } ++ ++ RESET_REG_PRCR = prev_reset_val; ++#endif ++ ++ ++ if((p_drv_hal = kmalloc(mem_size, GFP_KERNEL)) == NULL) ++ { ++ errPrint("Failed to allocate memory; rewinding.\n"); ++ return(-1); ++ } ++ ++ memset(p_drv_hal, 0, mem_size); ++ ++ /* build the cpmac private object */ ++ p_cpmac_priv->drv_hal = p_drv_hal; ++ p_cpmac_priv->tx_chan_info = p_tx_chan_info ++ = (CPMAC_TX_CHAN_INFO_T*)((char*)p_drv_hal ++ + sizeof(CPMAC_DRV_HAL_INFO_T)); ++ p_cpmac_priv->rx_chan_info = p_rx_chan_info ++ = (CPMAC_RX_CHAN_INFO_T*)((char *)p_tx_chan_info ++ + sizeof(CPMAC_TX_CHAN_INFO_T)); ++ p_cpmac_priv->ability_info = (CPMAC_ABILITY_INFO_T *)((char *)p_rx_chan_info ++ + sizeof(CPMAC_RX_CHAN_INFO_T)); ++ p_cpmac_priv->device_mib = (CPMAC_DEVICE_MIB_T *)((char *)p_cpmac_priv->ability_info ++ + sizeof(CPMAC_ABILITY_INFO_T)); ++ p_cpmac_priv->stats = (CPMAC_DRV_STATS_T *)((char *)p_cpmac_priv->device_mib ++ + sizeof(CPMAC_DEVICE_MIB_T)); ++ ++ p_drv_hal->owner = p_cpmac_priv; ++ ++ ++ switch(instance_num) ++ { ++ ++ case 0: ++ mac_name="maca"; ++ ++ /* Also setting port information */ ++ p_dev->if_port = AVALANCHE_CPMAC_LOW_PORT_ID; ++ ++ break; ++ ++ case 1: ++ mac_name="macb"; ++ ++ /* Also setting port information */ ++ p_dev->if_port = AVALANCHE_CPMAC_HIGH_PORT_ID; ++ ++ break; ++ } ++ ++ if(mac_name) ++ mac_string=prom_getenv(mac_name); ++ ++ if(!mac_string) ++ { ++ mac_string="08.00.28.32.06.02"; ++ printk("Error getting mac from Boot enviroment for %s\n",p_dev->name); ++ printk("Using default mac address: %s\n",mac_string); ++ if(mac_name) ++ { ++ printk("Use Bootloader command:\n"); ++ printk(" setenv %s xx.xx.xx.xx.xx.xx\n","<env_name>"); ++ printk("to set mac address\n"); ++ } ++ } ++ ++ str2eaddr(p_cpmac_priv->mac_addr,mac_string); ++ ++ for (i=0; i <= ETH_ALEN; i++) ++ { ++ /* This sets the hardware address */ ++ p_dev->dev_addr[i] = p_cpmac_priv->mac_addr[i]; ++ } ++ ++ p_cpmac_priv->set_to_close = 1; ++ p_cpmac_priv->non_data_irq_expected = 0; ++ ++//#if defined (CONFIG_MIPS_AVALANCHE_LED) ++// if((p_cpmac_priv->led_handle = avalanche_led_register("cpmac", instance_num)) == NULL) ++// { ++// errPrint("Could not allocate handle for CPMAC[%d] LED.\n", instance_num); ++// goto cpmac_init_mod_error; ++// } ++//#endif ++ ++ if(cpmac_drv_init_module(p_drv_hal, p_dev, instance_num) != 0) ++ { ++ errPrint("Could not initialize the HAL for %s.\n", p_dev->name); ++ goto cpmac_init_mod_error; ++ } ++ ++ /* initialize the CPMAC device */ ++ if (cpmac_drv_init(p_drv_hal) == -1) ++ { ++ errPrint("HAL init failed for %s.\n", p_dev->name); ++ goto cpmac_init_device_error; ++ } ++ ++ if(cpmac_p_probe_and_setup_device(p_cpmac_priv, &net_flags) == -1) ++ { ++ errPrint("Failed to configure up %s.\n", p_dev->name); ++ goto cpmac_init_device_error; ++ } ++ ++ if(cpmac_p_setup_driver_params(p_cpmac_priv) == -1) ++ { ++ errPrint("Failed to set driver parameters for %s.\n", p_dev->name); ++ goto cpmac_init_device_error; ++ } ++ ++ cpmac_p_rx_buf_setup(p_rx_chan_info); ++ ++ /* initialize the timers for the net device */ ++ if(cpmac_p_timer_init(p_cpmac_priv) == -1) ++ { ++ errPrint("Failed to set timer(s) for %s.\n", p_dev->name); ++ goto cpmac_timer_init_error; ++ } ++ ++ p_dev->addr_len = 6; ++ ++ p_dev->open = &cpmac_dev_open; /* i.e. Start Device */ ++ p_dev->hard_start_xmit = &cpmac_dev_tx; ++ p_dev->stop = &cpmac_dev_close; ++ p_dev->get_stats = &cpmac_dev_get_net_stats; ++ ++ p_dev->set_multicast_list = &cpmac_dev_mcast_set; ++ p_dev->set_mac_address = cpmac_dev_set_mac_addr; ++ /* Knocking off the default broadcast and multicast flags. Allowing the ++ device configuration to control the flags. */ ++ p_dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST); ++ p_dev->flags |= net_flags; ++ ++ netif_carrier_off(p_dev); ++ ++//#if defined (CONFIG_MIPS_AVALANCHE_LED) ++// avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_LINK_OFF); ++//#endif ++ ++ /* Tasklet is initialized at the isr registeration time. */ ++ p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "CpmacBase", "Get", &p_dev->base_addr); ++ p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "CpmacSize", "Get", &p_cpmac_priv->dev_size); ++ ++ request_mem_region(p_dev->base_addr, p_cpmac_priv->dev_size, p_dev->name); ++ ++ retVal = 0; ++ ++ if(g_init_enable_flag) ++ cpmac_p_dev_enable(p_dev); ++ ++ return(retVal); ++ ++cpmac_timer_init_error: ++cpmac_init_device_error : ++ cpmac_drv_cleanup(p_drv_hal); ++ ++cpmac_init_mod_error: ++ kfree(p_drv_hal); ++ ++ return (retVal); ++ ++} /* cpmac_dev_init */ ++ ++ ++/*************************************************************** ++ * cpmac_p_dev_enable ++ * ++ * Returns: ++ * 0 on success, error code otherwise. ++ * Parms: ++ * dev Structure of device to be opened. ++ * ++ * This routine puts the driver and CPMAC adapter in a ++ * state where it is ready to send and receive packets. ++ * ++ * ++ **************************************************************/ ++int cpmac_p_dev_enable( struct net_device *p_dev) ++{ ++ int ret_val = 0; ++ int channel = 0; ++ ++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv; ++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal; ++ CPMAC_RX_CHAN_INFO_T *p_rx_chan_info = p_cpmac_priv->rx_chan_info; ++ int max_length = p_rx_chan_info->chan->tot_buf_size; ++ ++ p_cpmac_priv->set_to_close = 0; ++ ++ if((ret_val = cpmac_drv_start(p_drv_hal, p_cpmac_priv->tx_chan_info, ++ p_cpmac_priv->rx_chan_info, CHAN_SETUP))==-1) ++ { ++ errPrint("%s error: failed to start the device.\n", p_dev->name); ++ ret_val = -1; ++ } ++ else if(p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev,"RX_UNICAST_SET", ++ "Set", &channel)!=0) ++ { ++ errPrint("%s error: device chan 0 could not be enabled.\n", p_dev->name); ++ ret_val = -1; ++ } ++ else if(p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, pszRX_MAXLEN, pszSet, &max_length) != 0) ++ { ++ errPrint(" CPMAC registers can't be written \n"); ++ ret_val = -1; ++ } ++ else if(p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "TxIntDisable", "Set", ++ &p_cpmac_priv->tx_chan_info->tx_int_disable) != 0) ++ { ++ errPrint(" CPMAC registers can't be written \n"); ++ ret_val = -1; ++ } ++ else ++ { ++ ; // Every thing went OK. ++ } ++ ++ return(ret_val); ++} /* cpmac_dev_enable */ ++ ++ ++static int cpmac_dev_open(struct net_device *p_dev) ++{ ++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv; ++ CPMAC_ISR_INFO_T *p_isr_cb_param = &p_cpmac_priv->cpmac_isr; ++ ++ if(!g_init_enable_flag) ++ cpmac_p_dev_enable(p_dev); ++ ++ if(request_irq(p_isr_cb_param->intr, cpmac_hal_isr, SA_INTERRUPT, ++ "Cpmac Driver", p_isr_cb_param)) ++ { ++ errPrint("Failed to register the irq %d for Cpmac %s.\n", ++ p_isr_cb_param->intr, p_dev->name); ++ return (-1); ++ } ++ ++ netif_start_queue(p_dev); ++ ++ MOD_INC_USE_COUNT; ++ p_cpmac_priv->stats->start_tick = jiffies; ++ dbgPrint("Started the network queue for %s.\n", p_dev->name); ++ return(0); ++} ++ ++/*************************************************************** ++ * cpmac_p_dev_disable ++ * ++ * Returns: ++ * An error code. ++ * Parms: ++ * dev The device structure of the device to ++ * close. ++ * ++ * This function shuts down the adapter. ++ * ++ **************************************************************/ ++int cpmac_p_dev_disable(struct net_device *p_dev) ++{ ++ int ret_val = 0; ++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv; ++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal; ++ ++ set_bit(0, &p_cpmac_priv->set_to_close); ++ set_bit(0, &p_cpmac_priv->non_data_irq_expected); ++ ++ /* The driver does not re-schedule the tasklet after kill is called. So, this ++ should take care of the bug in the kernel. */ ++ tasklet_kill(&p_cpmac_priv->cpmac_isr.tasklet); ++ ++ if(cpmac_drv_stop(p_drv_hal, p_cpmac_priv->tx_chan_info, ++ p_cpmac_priv->rx_chan_info, ++ CHAN_TEARDOWN | FREE_BUFFER | BLOCKING | COMPLETE) == -1) ++ { ++ ret_val = -1; ++ } ++ else ++ { ++ /* hope that the HAL closes down the tick timer.*/ ++ ++ dbgPrint("Device %s Closed.\n", p_dev->name); ++ p_cpmac_priv->stats->start_tick = jiffies; ++ ++ p_cpmac_priv->link_speed = 100000000; ++ p_cpmac_priv->link_mode = 1; ++ netif_carrier_off(p_dev); ++ ++//#if defined (CONFIG_MIPS_AVALANCHE_LED) ++// avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_LINK_OFF); ++//#endif ++ ++ clear_bit(0, &p_cpmac_priv->non_data_irq_expected); ++ ++ } ++ ++ return (ret_val); ++ ++} /* cpmac_dev_close */ ++ ++ ++/*************************************************************** ++ * cpmac_dev_close ++ * ++ * Returns: ++ * An error code. ++ * Parms: ++ * dev The device structure of the device to ++ * close. ++ * ++ * This function shuts down the adapter. ++ * ++ **************************************************************/ ++static int cpmac_dev_close(struct net_device *p_dev) ++{ ++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv; ++ CPMAC_ISR_INFO_T *p_isr_cb_param = &p_cpmac_priv->cpmac_isr; ++ ++ /* inform the upper layers. */ ++ netif_stop_queue(p_dev); ++ ++ if(!g_init_enable_flag) ++ cpmac_p_dev_disable(p_dev); ++ else ++ free_irq(p_isr_cb_param->intr, p_isr_cb_param); ++ ++ MOD_DEC_USE_COUNT; ++ ++ return(0); ++} ++ ++static void cpmac_dev_mcast_set(struct net_device *p_dev) ++{ ++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv; ++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal; ++ CPMAC_ABILITY_INFO_T *p_capability = p_cpmac_priv->ability_info; ++ HAL_FUNCTIONS *p_hal_funcs = p_drv_hal->hal_funcs; ++ HAL_DEVICE *p_hal_dev = p_drv_hal->hal_dev; ++ int val = 1; ++ int channel = 0; ++ ++//#if defined (CONFIG_MIPS_AVALANCHE_LED) ++// if(netif_carrier_ok(p_dev)) ++// avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_LINK_ON); ++//#endif ++ ++ if(p_dev->flags & IFF_PROMISC) ++ { ++ if(p_capability->promiscous) ++ { ++ /* multi mode in the HAL, check this */ ++ val = 0; ++ p_hal_funcs->Control(p_hal_dev, pszRX_MULTI_ALL, "Clear", &val); ++ ++ val = 1; ++ /* set the promiscous mode in the HAL */ ++ p_hal_funcs->Control(p_hal_dev, pszRX_CAF_EN, pszSet, &val); ++ p_hal_funcs->Control(p_hal_dev, pszRX_PROM_CH, pszSet, &channel); ++ ++ dbgPrint("%s set in the Promisc mode.\n", p_dev->name); ++ } ++ else ++ { ++ errPrint("%s not configured for Promisc mode.\n", p_dev->name); ++ } ++ } ++ else if(p_dev->flags & IFF_ALLMULTI) ++ { ++ if(p_capability->all_multi) ++ { ++ val = 0; ++ /* disable the promiscous mode in the HAL */ ++ p_hal_funcs->Control(p_hal_dev, pszRX_CAF_EN, "Clear", &val); ++ ++ val = 1; ++ /* set the all multi mode in the HAL */ ++ p_hal_funcs->Control(p_hal_dev, pszRX_MULTI_ALL, pszSet, &val); ++ p_hal_funcs->Control(p_hal_dev, pszRX_MULT_CH, pszSet, &channel); ++ ++ dbgPrint("%s has been set to the ALL_MULTI mode.\n", p_dev->name); ++ } ++ else ++ { ++ errPrint("%s not configured for ALL MULTI mode.\n", p_dev->name); ++ } ++ } ++ else if(p_dev->mc_count) ++ { ++ if(p_capability->multicast) ++ { ++ struct dev_mc_list *p_dmi = p_dev->mc_list; ++ int count; ++ ++ val = 0; ++ /* clear all the previous data, we are going to populate new ones.*/ ++ p_hal_funcs->Control(p_hal_dev, pszRX_MULTI_ALL, "Clear", &val); ++ /* disable the promiscous mode in the HAL */ ++ p_hal_funcs->Control(p_hal_dev, pszRX_CAF_EN, pszSet, &val); ++ ++ for(count = 0; count < p_dev->mc_count; count++, p_dmi = p_dmi->next) ++ { ++ p_hal_funcs->Control(p_hal_dev, "RX_MULTI_SINGLE", "Set", p_dmi->dmi_addr); ++ } ++ ++ dbgPrint("%s configured for %d multicast addresses.\n", p_dev->name, p_dev->mc_count); ++ } ++ else ++ { ++ errPrint("%s has not been configuted for multicast handling.\n", p_dev->name); ++ } ++ } ++ else ++ { ++ val = 0; ++ /* clear all the previous data, we are going to populate new ones.*/ ++ p_hal_funcs->Control(p_hal_dev, pszRX_MULTI_ALL, "Clear", &val); ++ /* disable the promiscous mode in the HAL */ ++ p_hal_funcs->Control(p_hal_dev, pszRX_CAF_EN, pszSet, &val); ++ dbgPrint("Dev set to Unicast mode.\n"); ++ } ++} ++ ++static int cpmac_dev_set_mac_addr(struct net_device *p_dev,void * addr) ++{ ++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv; ++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal; ++ HAL_FUNCTIONS *p_hal_funcs = p_drv_hal->hal_funcs; ++ HAL_DEVICE *p_hal_dev = p_drv_hal->hal_dev; ++ struct sockaddr *sa = addr; ++ ++ memcpy(p_cpmac_priv->mac_addr,sa->sa_data,p_dev->addr_len); ++ memcpy(p_dev->dev_addr,sa->sa_data,p_dev->addr_len); ++ p_hal_funcs->Control(p_hal_dev, pszMacAddr, pszSet, p_cpmac_priv->mac_addr); ++ ++ return 0; ++ ++} ++ ++/* VLAN is handled by vlan/vconfig support. Here, we just check for the ++ * 802.1q configuration of the device and en-queue the packet accordingly. ++ * We do not do any 802.1q processing here. ++ */ ++static int cpmac_dev_tx( struct sk_buff *skb, struct net_device *p_dev) ++{ ++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv; ++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal; ++ int channel = 0; ++ int ret_val = 0; ++ FRAGLIST send_frag_list[1]; ++ ++#ifdef CPMAC_8021Q_SUPPORT ++ if(skb->len < TCI_END_OFFSET) ++ { ++ /* Whee, frame shorter than 14 bytes !! We need to copy ++ * fragments to understand the frame. Too much work. ++ * Hmm, dump it. */ ++ ++ /* Free the buffer */ ++ goto cpmac_dev_tx_drop_pkt; ++ } ++ ++ /* 802.1p/q stuff */ ++ if(IS_802_1Q_FRAME(skb->data + TPID_START_OFFSET)) ++ { ++ /* IEEE 802.1q, section 8.8 and section 8.11.9 */ ++ if(!p_cpmac_priv->enable_802_1q) ++ { ++ /* free the buffer */ ++ goto cpmac_dev_tx_drop_pkt; ++ } ++ ++ channel = GET_802_1P_CHAN(p_cpmac_priv->tx_chan_info->opened_chan, ++ skb->data[TCI_START_OFFSET]); ++ ++ } ++ /* sending a non 802.1q frame, when configured for 802.1q: dump it.*/ ++ else if(p_cpmac_priv->enable_802_1q) ++ { ++ /* free the buffer */ ++ goto cpmac_dev_tx_drop_pkt; ++ } ++ else ++ { ++ ;/* it is the good old non 802.1q */ ++ } ++#endif ++ ++ send_frag_list->len = skb->len; ++ send_frag_list->data = skb->data; ++ ++#ifdef CPMAC_TEST ++ xdump(skb->data, skb->len, "send"); ++#endif ++ ++ dma_cache_wback_inv((unsigned long)skb->data, skb->len); ++ ++ if(p_drv_hal->hal_funcs->Send(p_drv_hal->hal_dev, send_frag_list, 1, ++ skb->len, skb, channel) != 0) ++ { ++ /* code here to stop the queue, when allowing tx timeout, perhaps next release.*/ ++ p_cpmac_priv->net_dev_stats.tx_errors++; ++#ifndef TI_SLOW_PATH ++ /* Free the skb in case of Send return error */ ++ dev_kfree_skb_any(skb); ++ p_cpmac_priv->net_dev_stats.tx_dropped++; ++ return 0; ++#endif ++ goto cpmac_dev_tx_drop_pkt; ++ } ++ ++//#if defined (CONFIG_MIPS_AVALANCHE_LED) ++// avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_TX_ACTIVITY); ++//#endif ++ ++ return(ret_val); ++ ++cpmac_dev_tx_drop_pkt: ++ ++ p_cpmac_priv->net_dev_stats.tx_dropped++; ++ ret_val = -1; ++ return (ret_val); ++ ++} /*cpmac_dev_tx */ ++ ++ ++//------------------------------------------------------------------------------ ++// Public functions : Called by outsiders to this file. ++//------------------------------------------------------------------------------ ++ ++ ++void *cpmac_hal_malloc_buffer(unsigned int size, void* mem_base, unsigned int mem_range, ++ OS_SETUP *p_os_setup, HAL_RECEIVEINFO *HalReceiveInfo, ++ OS_RECEIVEINFO **osReceiveInfo, OS_DEVICE *p_dev) ++{ ++ CPMAC_RX_CHAN_INFO_T *p_rx_chan_info = (CPMAC_RX_CHAN_INFO_T *)p_os_setup; ++ int tot_buf_size = p_rx_chan_info->chan->tot_buf_size; ++ int tot_reserve_bytes = p_rx_chan_info->chan->tot_reserve_bytes; ++ struct sk_buff *p_skb; ++ void *ret_ptr; ++ ++ /* use TI SKB private pool */ ++ p_skb = dev_alloc_skb(tot_buf_size); ++ ++ if(p_skb == NULL) ++ { ++ errPrint("Failed to allocate skb for %s.\n", ((struct net_device*)p_dev)->name); ++ return (NULL); ++ } ++ ++ p_skb->dev = p_dev; ++ skb_reserve(p_skb, tot_reserve_bytes); ++ ++ *osReceiveInfo = p_skb; ++ ++ ret_ptr = skb_put(p_skb, p_rx_chan_info->chan->buffer_size); ++ ++ return(ret_ptr); ++} ++ ++void cpmac_hal_isr(int irq, void *p_param, struct pt_regs *regs) ++{ ++ CPMAC_ISR_INFO_T *p_cb_param = (CPMAC_ISR_INFO_T*) p_param; ++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cb_param->owner; ++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_drv_hal->owner; ++ int pkts_to_handle = 0; ++ ++ if(p_cpmac_priv->non_data_irq_expected) ++ { ++ p_cb_param->hal_isr(p_drv_hal->hal_dev, &pkts_to_handle); ++ p_drv_hal->hal_funcs->PacketProcessEnd(p_drv_hal->hal_dev); ++ } ++ else if(!p_cpmac_priv->set_to_close) ++ tasklet_schedule(&((CPMAC_ISR_INFO_T*) p_param)->tasklet); ++ else ++ ; // back off from doing anything more. We are closing down. ++} ++ ++void cpmac_handle_tasklet(unsigned long data) ++{ ++ CPMAC_ISR_INFO_T *p_cb_param = (CPMAC_ISR_INFO_T*) data; ++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cb_param->owner; ++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_drv_hal->owner; ++ int pkts_to_handle; ++ ++ p_cb_param->hal_isr(p_drv_hal->hal_dev, &pkts_to_handle); ++ ++ if(test_bit(0, &p_cpmac_priv->non_data_irq_expected) || !pkts_to_handle) ++ p_drv_hal->hal_funcs->PacketProcessEnd(p_drv_hal->hal_dev); ++ else if(!test_bit(0, &p_cpmac_priv->set_to_close)) ++ tasklet_schedule(&p_cb_param->tasklet); ++ else ++ ; // Back off from processing packets we are closing down. ++} ++ ++int cpmac_hal_control(OS_DEVICE *p_dev, const char *key, ++ const char *action, void *value) ++{ ++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv; ++ int ret_val = -1; ++ ++ if(key == NULL) ++ { ++ dbgPrint("Encountered NULL key.\n"); ++ return (-1); ++ } ++ ++ if(cpmac_ci_strcmp(key, "Sleep") == 0 && value != NULL) ++ { ++ unsigned int clocks_per_tick = cpmac_cpu_freq/HZ; ++ unsigned int requested_clocks = *(unsigned int*)value; ++ unsigned int requested_ticks = (requested_clocks + clocks_per_tick - 1)/clocks_per_tick; ++ mdelay(requested_ticks); ++ ret_val = 0; ++ } ++ else if(cpmac_ci_strcmp(key, "StateChange") == 0) ++ { ++ ret_val = cpmac_p_process_status_ind(p_cpmac_priv); ++ } ++ else if(cpmac_ci_strcmp(key, "Tick") == 0 && action != NULL) ++ { ++ if(cpmac_ci_strcmp(action, "Set") == 0 && value != NULL) ++ { ++ if(*(unsigned int*)value == 0) ++ { ++ cpmac_p_stop_timer(p_cpmac_priv->timer + TICK_TIMER); ++ ret_val = 0; ++ } ++ else ++ { ++ unsigned int clocks_per_tick = cpmac_cpu_freq/HZ; ++ unsigned int requested_clocks = *(unsigned int*)value; ++ unsigned int requested_ticks = (requested_clocks + clocks_per_tick - 1)/clocks_per_tick; ++ ++ p_cpmac_priv->delay_ticks = requested_ticks; /* save it for re-triggering */ ++ ret_val = cpmac_p_start_timer(p_cpmac_priv->timer + TICK_TIMER, ++ p_cpmac_priv->delay_ticks); ++ } ++ } ++ else if(cpmac_ci_strcmp(action, "Clear") == 0) ++ { ++ ret_val = cpmac_p_stop_timer(p_cpmac_priv->timer + TICK_TIMER); ++ } ++ else ++ ; ++ } ++ else if(cpmac_ci_strcmp(key, "MacAddr") == 0 && action != NULL) ++ { ++ if(cpmac_ci_strcmp(action, "Get") == 0 && value != NULL) ++ { ++ *(char **)value = p_cpmac_priv->mac_addr; ++ ret_val = 0; ++ } ++ } ++ else if(cpmac_ci_strcmp(key, "CpuFreq") == 0) ++ { ++ if(cpmac_ci_strcmp(action, "Get") == 0 && value != NULL) ++ { ++ *(unsigned int *)value = cpmac_cpu_freq; ++ dbgPrint("Cpu frequency for cpmacs is %u\n",cpmac_cpu_freq); ++ ret_val = 0; ++ } ++ } ++ else if(cpmac_ci_strcmp(key, "SioFlush") == 0) ++ { ++ ret_val = 0; ++ dbgPrint("\n"); ++ } ++ else if(cpmac_ci_strcmp(key, "CpmacFrequency") == 0) ++ { ++ /* For Sangam cpmac clock is off the PBUS */ ++ /* OS Needs to supply CORRECT frequency */ ++ if(cpmac_ci_strcmp(action, "Get") == 0 && value != NULL) ++ { ++ *(unsigned int *)value = CONFIG_AR7_SYS * 1000 * 1000; ++ ret_val = 0; ++ } ++ } ++ /* For now, providing back the default values. */ ++ else if(cpmac_ci_strcmp(key, "MdioClockFrequency") == 0) ++ { ++ if(cpmac_ci_strcmp(action, "Get") == 0 && value != NULL) ++ { ++ *(unsigned int *)value = 2200000; /*DEFAULT */ ++ ret_val = 0; ++ } ++ } ++ /* For now, providing back the default values. */ ++ else if(cpmac_ci_strcmp(key, "MdioBusFrequency") == 0) ++ { ++ /* For Sangam MdioBusFreq is off the PBUS */ ++ if(cpmac_ci_strcmp(action, "Get") == 0 && value != NULL) ++ { ++ *(unsigned int *)value = CONFIG_AR7_SYS * 1000 * 1000; ++ ret_val = 0; ++ } ++ } ++ ++#if 0 ++#if defined(CONFIG_AVALANCHE_AUTO_MDIX) ++ /* supporting Mdio Mdix switching */ ++ else if(cpmac_ci_strcmp(key, hcMdioMdixSwitch) == 0) ++ { ++ /* For Sangam Mdio-switching action should be always "set"*/ ++ if(cpmac_ci_strcmp(action, hcSet) == 0 && value != NULL ) ++ { ++ unsigned int mdix = *((unsigned int *) value) ; ++ ++ if(mdix) ++ avalanche_set_phy_into_mdix_mode(); ++ ++ else ++ avalanche_set_phy_into_mdi_mode(); ++ ++ ret_val = 0; ++ } ++ ++ } ++#endif ++#endif ++ else if(cpmac_ci_strcmp(key, hcMdioMdixSwitch) == 0) ++ { ++ /* For Sangam Mdio-switching action should be always "set"*/ ++ if(cpmac_ci_strcmp(action, hcSet) == 0 && value != NULL ) ++ { ++ unsigned int mdix = *((unsigned int *) value) ; ++ ++#ifdef CONFIG_AR7_MDIX ++ avalanche_set_mdix_on_chip(0xa8610000 , mdix ? 1: 0); ++#endif ++ ++ ret_val = 0; ++ } ++ ++ } ++ ++ return(ret_val); ++} ++ ++ ++int cpmac_hal_receive(OS_DEVICE *p_dev, FRAGLIST *fragList, ++ unsigned int fragCount, ++ unsigned int packet_size, ++ HAL_RECEIVEINFO *hal_receive_info, ++ unsigned int mode) ++{ ++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv; ++ CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal; ++ struct sk_buff *p_skb = fragList[0].OsInfo; ++ p_skb->len = fragList[0].len; ++ ++ /* invalidate the cache. */ ++ dma_cache_inv((unsigned long)p_skb->data, fragList[0].len); ++#ifdef CPMAC_TEST ++ xdump(p_skb->data, p_skb->len, "recv"); ++#endif ++#ifdef CPMAC_8021Q_SUPPORT ++ /* 802.1q stuff, just does the basic checking here. */ ++ if(!p_cpmac_priv->enable_802_1q && ++ p_skb->len > TCI_END_OFFSET && ++ IS_802_1Q_FRAME(p_skb->data + TPID_START_OFFSET)) ++ { ++ goto cpmac_hal_recv_frame_mismatch; ++ } ++#endif ++ if(fragCount > 1) ++ { ++ int len; ++ struct sk_buff *p_temp_skb; ++ CPMAC_RX_CHAN_INFO_T *p_rx_chan_info = p_cpmac_priv->rx_chan_info; ++ int count; ++ ++ dbgPrint("Recv: It is multifragment for %s.\n", p_dev->name); ++ ++ p_skb = dev_alloc_skb(packet_size + ++ p_rx_chan_info->chan->tot_reserve_bytes); ++ if(p_skb == NULL) ++ { ++ p_cpmac_priv->net_dev_stats.rx_errors++; ++ goto cpmac_hal_recv_alloc_failed; ++ } ++ ++ p_skb->dev = p_dev; ++ skb_reserve(p_skb, p_rx_chan_info->chan->tot_reserve_bytes); ++ ++ for(count = 0; count < fragCount; count++) ++ { ++ p_temp_skb = fragList[count].OsInfo; ++ len = fragList[count].len; ++ ++ dma_cache_inv((unsigned long)p_temp_skb->data, len); ++ ++ memcpy(skb_put(p_skb, len), p_temp_skb->data, len); ++ dev_kfree_skb_any(p_temp_skb); ++ } ++ } ++ ++ ++#if defined(CONFIG_MIPS_AVALANCHE_MARVELL) ++ /* Fetch the receiving port information from EGRESS TRAILOR Bytes*/ ++ p_dev->if_port = (unsigned char)p_skb->data[packet_size -(EGRESS_TRAILOR_LEN-1)] + AVALANCHE_MARVELL_BASE_PORT_ID; ++ skb_trim(p_skb, packet_size - EGRESS_TRAILOR_LEN); ++#else ++ /* set length & tail */ ++ skb_trim(p_skb, packet_size); ++#endif ++ ++ p_skb->protocol = eth_type_trans(p_skb, p_dev); ++ ++ netif_rx(p_skb); ++ ++//#if defined (CONFIG_MIPS_AVALANCHE_LED) ++// avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_RX_ACTIVITY); ++//#endif ++ ++ p_cpmac_priv->net_dev_stats.rx_packets++; ++ p_cpmac_priv->net_dev_stats.rx_bytes += packet_size; ++ ++ p_drv_hal->hal_funcs->RxReturn(hal_receive_info,1); ++ ++ return(0); ++ ++cpmac_hal_recv_alloc_failed: ++ ++#ifdef CPMAC_8021Q_SUPPORT ++cpmac_hal_recv_frame_mismatch: ++#endif ++ ++ fragCount--; ++ ++ do ++ { ++ dev_kfree_skb_any(fragList[fragCount].OsInfo); ++ } ++ while(fragCount--); ++ ++ p_cpmac_priv->net_dev_stats.rx_dropped++; ++ ++ return(-1); ++} /*cpmac_receive*/ ++ ++ ++void cpmac_hal_tear_down_complete(OS_DEVICE*a, int b, int ch) ++{ ++ dbgPrint("what to do with this.\n"); ++} ++ ++ ++int cpmac_hal_send_complete(OS_SENDINFO *p_skb) ++{ ++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_skb->dev->priv; ++ ++ p_cpmac_priv->net_dev_stats.tx_packets++; ++ p_cpmac_priv->net_dev_stats.tx_bytes += p_skb->len; ++ ++ dev_kfree_skb_any(p_skb); ++ ++ return(0); ++} ++ ++ ++int cpmac_reset(CPMAC_PRIVATE_INFO_T *p_cpmac_priv) ++{ ++ // code here to reset the device/hal. Not now. ++ ++ netif_wake_queue(p_cpmac_priv->owner); ++ return(0); ++} ++ ++#ifdef CPMAC_TEST ++ ++#define isprint(a) ((a >=' ')&&(a<= '~')) ++void xdump( u_char* cp, int length, char* prefix ) ++{ ++ int col, count; ++ u_char prntBuf[120]; ++ u_char* pBuf = prntBuf; ++ count = 0; ++ while(count < length){ ++ pBuf += sprintf( pBuf, "%s", prefix ); ++ for(col = 0;count + col < length && col < 16; col++){ ++ if (col != 0 && (col % 4) == 0) ++ pBuf += sprintf( pBuf, " " ); ++ pBuf += sprintf( pBuf, "%02X ", cp[count + col] ); ++ } ++ while(col++ < 16){ /* pad end of buffer with blanks */ ++ if ((col % 4) == 0) ++ sprintf( pBuf, " " ); ++ pBuf += sprintf( pBuf, " " ); ++ } ++ pBuf += sprintf( pBuf, " " ); ++ for(col = 0;count + col < length && col < 16; col++){ ++ if (isprint((int)cp[count + col])) ++ pBuf += sprintf( pBuf, "%c", cp[count + col] ); ++ else ++ pBuf += sprintf( pBuf, "." ); ++ } ++ sprintf( pBuf, "\n" ); ++ // SPrint(prntBuf); ++ printk(prntBuf); ++ count += col; ++ pBuf = prntBuf; ++ } ++ ++} /* close xdump(... */ ++#endif ++ ++ ++static int __init cpmac_dev_probe(void) ++{ ++ int retVal = 0; ++ int unit; ++ int instance_count = CONFIG_MIPS_CPMAC_PORTS; ++ ++ //cpmac_cpu_freq = avalanche_clkc_get_freq(CLKC_MIPS); ++ cpmac_cpu_freq = CONFIG_AR7_CPU * 1000 * 1000; ++ ++ build_psp_config(); ++ ++ for(unit = 0; unit < instance_count; unit++) ++ { ++ struct net_device *p_dev; ++ CPMAC_PRIVATE_INFO_T *p_cpmac_priv; ++ size_t dev_size; ++ int failed; ++ ++ dev_size = sizeof(struct net_device) ++ + sizeof(CPMAC_PRIVATE_INFO_T); ++ ++ ++ if((p_dev = (struct net_device *) kmalloc(dev_size, GFP_KERNEL)) == NULL) ++ { ++ dbgPrint( "Could not allocate memory for device.\n" ); ++ retVal = -ENOMEM; ++ break; ++ } ++ ++ memset(p_dev, 0, dev_size ); ++ ++ p_dev->priv = p_cpmac_priv ++ = (CPMAC_PRIVATE_INFO_T*)(((char *) p_dev) + sizeof(struct net_device)); ++ p_cpmac_priv->owner = p_dev; ++ ++ ether_setup(p_dev); ++ ++ p_cpmac_priv->instance_num = unit; ++ p_dev->init = cpmac_dev_init; ++ ++ g_dev_array[p_cpmac_priv->instance_num] = p_dev; ++ ++#if defined CONFIG_MIPS_CPMAC_INIT_BUF_MALLOC ++ g_init_enable_flag = 1; ++ printk("Cpmac driver is allocating buffer memory at init time.\n"); ++#endif ++ ++ /* This section gives a default value by the number of PHY in order to ++ * replace the default MACRO. */ ++ { ++ char *mac_port = prom_getenv("MAC_PORT"); /* Internal: 0, External: 1 */ ++ if(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; |