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; iOsFunc->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 = ;;...*/ + 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, /**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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +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 "); +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: "); + +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",""); + printk("to set mac address\n"); + } + } + + str2eaddr(p_cpmac_priv->mac_addr,mac_string); + + for (i=0; i <= ETH_ALEN; i++) + { + /* This sets the hardware address */ + p_dev->dev_addr[i] = p_cpmac_priv->mac_addr[i]; + } + + p_cpmac_priv->set_to_close = 1; + p_cpmac_priv->non_data_irq_expected = 0; + +//#if defined (CONFIG_MIPS_AVALANCHE_LED) +// if((p_cpmac_priv->led_handle = avalanche_led_register("cpmac", instance_num)) == NULL) +// { +// errPrint("Could not allocate handle for CPMAC[%d] LED.\n", instance_num); +// goto cpmac_init_mod_error; +// } +//#endif + + if(cpmac_drv_init_module(p_drv_hal, p_dev, instance_num) != 0) + { + errPrint("Could not initialize the HAL for %s.\n", p_dev->name); + goto cpmac_init_mod_error; + } + + /* initialize the CPMAC device */ + if (cpmac_drv_init(p_drv_hal) == -1) + { + errPrint("HAL init failed for %s.\n", p_dev->name); + goto cpmac_init_device_error; + } + + if(cpmac_p_probe_and_setup_device(p_cpmac_priv, &net_flags) == -1) + { + errPrint("Failed to configure up %s.\n", p_dev->name); + goto cpmac_init_device_error; + } + + if(cpmac_p_setup_driver_params(p_cpmac_priv) == -1) + { + errPrint("Failed to set driver parameters for %s.\n", p_dev->name); + goto cpmac_init_device_error; + } + + cpmac_p_rx_buf_setup(p_rx_chan_info); + + /* initialize the timers for the net device */ + if(cpmac_p_timer_init(p_cpmac_priv) == -1) + { + errPrint("Failed to set timer(s) for %s.\n", p_dev->name); + goto cpmac_timer_init_error; + } + + p_dev->addr_len = 6; + + p_dev->open = &cpmac_dev_open; /* i.e. Start Device */ + p_dev->hard_start_xmit = &cpmac_dev_tx; + p_dev->stop = &cpmac_dev_close; + p_dev->get_stats = &cpmac_dev_get_net_stats; + + p_dev->set_multicast_list = &cpmac_dev_mcast_set; + p_dev->set_mac_address = cpmac_dev_set_mac_addr; + /* Knocking off the default broadcast and multicast flags. Allowing the + device configuration to control the flags. */ + p_dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST); + p_dev->flags |= net_flags; + + netif_carrier_off(p_dev); + +//#if defined (CONFIG_MIPS_AVALANCHE_LED) +// avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_LINK_OFF); +//#endif + + /* Tasklet is initialized at the isr registeration time. */ + p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "CpmacBase", "Get", &p_dev->base_addr); + p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "CpmacSize", "Get", &p_cpmac_priv->dev_size); + + request_mem_region(p_dev->base_addr, p_cpmac_priv->dev_size, p_dev->name); + + retVal = 0; + + if(g_init_enable_flag) + cpmac_p_dev_enable(p_dev); + + return(retVal); + +cpmac_timer_init_error: +cpmac_init_device_error : + cpmac_drv_cleanup(p_drv_hal); + +cpmac_init_mod_error: + kfree(p_drv_hal); + + return (retVal); + +} /* cpmac_dev_init */ + + +/*************************************************************** + * cpmac_p_dev_enable + * + * Returns: + * 0 on success, error code otherwise. + * Parms: + * dev Structure of device to be opened. + * + * This routine puts the driver and CPMAC adapter in a + * state where it is ready to send and receive packets. + * + * + **************************************************************/ +int cpmac_p_dev_enable( struct net_device *p_dev) +{ + int ret_val = 0; + int channel = 0; + + CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv; + CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal; + CPMAC_RX_CHAN_INFO_T *p_rx_chan_info = p_cpmac_priv->rx_chan_info; + int max_length = p_rx_chan_info->chan->tot_buf_size; + + p_cpmac_priv->set_to_close = 0; + + if((ret_val = cpmac_drv_start(p_drv_hal, p_cpmac_priv->tx_chan_info, + p_cpmac_priv->rx_chan_info, CHAN_SETUP))==-1) + { + errPrint("%s error: failed to start the device.\n", p_dev->name); + ret_val = -1; + } + else if(p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev,"RX_UNICAST_SET", + "Set", &channel)!=0) + { + errPrint("%s error: device chan 0 could not be enabled.\n", p_dev->name); + ret_val = -1; + } + else if(p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, pszRX_MAXLEN, pszSet, &max_length) != 0) + { + errPrint(" CPMAC registers can't be written \n"); + ret_val = -1; + } + else if(p_drv_hal->hal_funcs->Control(p_drv_hal->hal_dev, "TxIntDisable", "Set", + &p_cpmac_priv->tx_chan_info->tx_int_disable) != 0) + { + errPrint(" CPMAC registers can't be written \n"); + ret_val = -1; + } + else + { + ; // Every thing went OK. + } + + return(ret_val); +} /* cpmac_dev_enable */ + + +static int cpmac_dev_open(struct net_device *p_dev) +{ + CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv; + CPMAC_ISR_INFO_T *p_isr_cb_param = &p_cpmac_priv->cpmac_isr; + + if(!g_init_enable_flag) + cpmac_p_dev_enable(p_dev); + + if(request_irq(p_isr_cb_param->intr, cpmac_hal_isr, SA_INTERRUPT, + "Cpmac Driver", p_isr_cb_param)) + { + errPrint("Failed to register the irq %d for Cpmac %s.\n", + p_isr_cb_param->intr, p_dev->name); + return (-1); + } + + netif_start_queue(p_dev); + + MOD_INC_USE_COUNT; + p_cpmac_priv->stats->start_tick = jiffies; + dbgPrint("Started the network queue for %s.\n", p_dev->name); + return(0); +} + +/*************************************************************** + * cpmac_p_dev_disable + * + * Returns: + * An error code. + * Parms: + * dev The device structure of the device to + * close. + * + * This function shuts down the adapter. + * + **************************************************************/ +int cpmac_p_dev_disable(struct net_device *p_dev) +{ + int ret_val = 0; + CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv; + CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal; + + set_bit(0, &p_cpmac_priv->set_to_close); + set_bit(0, &p_cpmac_priv->non_data_irq_expected); + + /* The driver does not re-schedule the tasklet after kill is called. So, this + should take care of the bug in the kernel. */ + tasklet_kill(&p_cpmac_priv->cpmac_isr.tasklet); + + if(cpmac_drv_stop(p_drv_hal, p_cpmac_priv->tx_chan_info, + p_cpmac_priv->rx_chan_info, + CHAN_TEARDOWN | FREE_BUFFER | BLOCKING | COMPLETE) == -1) + { + ret_val = -1; + } + else + { + /* hope that the HAL closes down the tick timer.*/ + + dbgPrint("Device %s Closed.\n", p_dev->name); + p_cpmac_priv->stats->start_tick = jiffies; + + p_cpmac_priv->link_speed = 100000000; + p_cpmac_priv->link_mode = 1; + netif_carrier_off(p_dev); + +//#if defined (CONFIG_MIPS_AVALANCHE_LED) +// avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_LINK_OFF); +//#endif + + clear_bit(0, &p_cpmac_priv->non_data_irq_expected); + + } + + return (ret_val); + +} /* cpmac_dev_close */ + + +/*************************************************************** + * cpmac_dev_close + * + * Returns: + * An error code. + * Parms: + * dev The device structure of the device to + * close. + * + * This function shuts down the adapter. + * + **************************************************************/ +static int cpmac_dev_close(struct net_device *p_dev) +{ + CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv; + CPMAC_ISR_INFO_T *p_isr_cb_param = &p_cpmac_priv->cpmac_isr; + + /* inform the upper layers. */ + netif_stop_queue(p_dev); + + if(!g_init_enable_flag) + cpmac_p_dev_disable(p_dev); + else + free_irq(p_isr_cb_param->intr, p_isr_cb_param); + + MOD_DEC_USE_COUNT; + + return(0); +} + +static void cpmac_dev_mcast_set(struct net_device *p_dev) +{ + CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv; + CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal; + CPMAC_ABILITY_INFO_T *p_capability = p_cpmac_priv->ability_info; + HAL_FUNCTIONS *p_hal_funcs = p_drv_hal->hal_funcs; + HAL_DEVICE *p_hal_dev = p_drv_hal->hal_dev; + int val = 1; + int channel = 0; + +//#if defined (CONFIG_MIPS_AVALANCHE_LED) +// if(netif_carrier_ok(p_dev)) +// avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_LINK_ON); +//#endif + + if(p_dev->flags & IFF_PROMISC) + { + if(p_capability->promiscous) + { + /* multi mode in the HAL, check this */ + val = 0; + p_hal_funcs->Control(p_hal_dev, pszRX_MULTI_ALL, "Clear", &val); + + val = 1; + /* set the promiscous mode in the HAL */ + p_hal_funcs->Control(p_hal_dev, pszRX_CAF_EN, pszSet, &val); + p_hal_funcs->Control(p_hal_dev, pszRX_PROM_CH, pszSet, &channel); + + dbgPrint("%s set in the Promisc mode.\n", p_dev->name); + } + else + { + errPrint("%s not configured for Promisc mode.\n", p_dev->name); + } + } + else if(p_dev->flags & IFF_ALLMULTI) + { + if(p_capability->all_multi) + { + val = 0; + /* disable the promiscous mode in the HAL */ + p_hal_funcs->Control(p_hal_dev, pszRX_CAF_EN, "Clear", &val); + + val = 1; + /* set the all multi mode in the HAL */ + p_hal_funcs->Control(p_hal_dev, pszRX_MULTI_ALL, pszSet, &val); + p_hal_funcs->Control(p_hal_dev, pszRX_MULT_CH, pszSet, &channel); + + dbgPrint("%s has been set to the ALL_MULTI mode.\n", p_dev->name); + } + else + { + errPrint("%s not configured for ALL MULTI mode.\n", p_dev->name); + } + } + else if(p_dev->mc_count) + { + if(p_capability->multicast) + { + struct dev_mc_list *p_dmi = p_dev->mc_list; + int count; + + val = 0; + /* clear all the previous data, we are going to populate new ones.*/ + p_hal_funcs->Control(p_hal_dev, pszRX_MULTI_ALL, "Clear", &val); + /* disable the promiscous mode in the HAL */ + p_hal_funcs->Control(p_hal_dev, pszRX_CAF_EN, pszSet, &val); + + for(count = 0; count < p_dev->mc_count; count++, p_dmi = p_dmi->next) + { + p_hal_funcs->Control(p_hal_dev, "RX_MULTI_SINGLE", "Set", p_dmi->dmi_addr); + } + + dbgPrint("%s configured for %d multicast addresses.\n", p_dev->name, p_dev->mc_count); + } + else + { + errPrint("%s has not been configuted for multicast handling.\n", p_dev->name); + } + } + else + { + val = 0; + /* clear all the previous data, we are going to populate new ones.*/ + p_hal_funcs->Control(p_hal_dev, pszRX_MULTI_ALL, "Clear", &val); + /* disable the promiscous mode in the HAL */ + p_hal_funcs->Control(p_hal_dev, pszRX_CAF_EN, pszSet, &val); + dbgPrint("Dev set to Unicast mode.\n"); + } +} + +static int cpmac_dev_set_mac_addr(struct net_device *p_dev,void * addr) +{ + CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv; + CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal; + HAL_FUNCTIONS *p_hal_funcs = p_drv_hal->hal_funcs; + HAL_DEVICE *p_hal_dev = p_drv_hal->hal_dev; + struct sockaddr *sa = addr; + + memcpy(p_cpmac_priv->mac_addr,sa->sa_data,p_dev->addr_len); + memcpy(p_dev->dev_addr,sa->sa_data,p_dev->addr_len); + p_hal_funcs->Control(p_hal_dev, pszMacAddr, pszSet, p_cpmac_priv->mac_addr); + + return 0; + +} + +/* VLAN is handled by vlan/vconfig support. Here, we just check for the + * 802.1q configuration of the device and en-queue the packet accordingly. + * We do not do any 802.1q processing here. + */ +static int cpmac_dev_tx( struct sk_buff *skb, struct net_device *p_dev) +{ + CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv; + CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal; + int channel = 0; + int ret_val = 0; + FRAGLIST send_frag_list[1]; + +#ifdef CPMAC_8021Q_SUPPORT + if(skb->len < TCI_END_OFFSET) + { + /* Whee, frame shorter than 14 bytes !! We need to copy + * fragments to understand the frame. Too much work. + * Hmm, dump it. */ + + /* Free the buffer */ + goto cpmac_dev_tx_drop_pkt; + } + + /* 802.1p/q stuff */ + if(IS_802_1Q_FRAME(skb->data + TPID_START_OFFSET)) + { + /* IEEE 802.1q, section 8.8 and section 8.11.9 */ + if(!p_cpmac_priv->enable_802_1q) + { + /* free the buffer */ + goto cpmac_dev_tx_drop_pkt; + } + + channel = GET_802_1P_CHAN(p_cpmac_priv->tx_chan_info->opened_chan, + skb->data[TCI_START_OFFSET]); + + } + /* sending a non 802.1q frame, when configured for 802.1q: dump it.*/ + else if(p_cpmac_priv->enable_802_1q) + { + /* free the buffer */ + goto cpmac_dev_tx_drop_pkt; + } + else + { + ;/* it is the good old non 802.1q */ + } +#endif + + send_frag_list->len = skb->len; + send_frag_list->data = skb->data; + +#ifdef CPMAC_TEST + xdump(skb->data, skb->len, "send"); +#endif + + dma_cache_wback_inv((unsigned long)skb->data, skb->len); + + if(p_drv_hal->hal_funcs->Send(p_drv_hal->hal_dev, send_frag_list, 1, + skb->len, skb, channel) != 0) + { + /* code here to stop the queue, when allowing tx timeout, perhaps next release.*/ + p_cpmac_priv->net_dev_stats.tx_errors++; +#ifndef TI_SLOW_PATH + /* Free the skb in case of Send return error */ + dev_kfree_skb_any(skb); + p_cpmac_priv->net_dev_stats.tx_dropped++; + return 0; +#endif + goto cpmac_dev_tx_drop_pkt; + } + +//#if defined (CONFIG_MIPS_AVALANCHE_LED) +// avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_TX_ACTIVITY); +//#endif + + return(ret_val); + +cpmac_dev_tx_drop_pkt: + + p_cpmac_priv->net_dev_stats.tx_dropped++; + ret_val = -1; + return (ret_val); + +} /*cpmac_dev_tx */ + + +//------------------------------------------------------------------------------ +// Public functions : Called by outsiders to this file. +//------------------------------------------------------------------------------ + + +void *cpmac_hal_malloc_buffer(unsigned int size, void* mem_base, unsigned int mem_range, + OS_SETUP *p_os_setup, HAL_RECEIVEINFO *HalReceiveInfo, + OS_RECEIVEINFO **osReceiveInfo, OS_DEVICE *p_dev) +{ + CPMAC_RX_CHAN_INFO_T *p_rx_chan_info = (CPMAC_RX_CHAN_INFO_T *)p_os_setup; + int tot_buf_size = p_rx_chan_info->chan->tot_buf_size; + int tot_reserve_bytes = p_rx_chan_info->chan->tot_reserve_bytes; + struct sk_buff *p_skb; + void *ret_ptr; + + /* use TI SKB private pool */ + p_skb = dev_alloc_skb(tot_buf_size); + + if(p_skb == NULL) + { + errPrint("Failed to allocate skb for %s.\n", ((struct net_device*)p_dev)->name); + return (NULL); + } + + p_skb->dev = p_dev; + skb_reserve(p_skb, tot_reserve_bytes); + + *osReceiveInfo = p_skb; + + ret_ptr = skb_put(p_skb, p_rx_chan_info->chan->buffer_size); + + return(ret_ptr); +} + +void cpmac_hal_isr(int irq, void *p_param, struct pt_regs *regs) +{ + CPMAC_ISR_INFO_T *p_cb_param = (CPMAC_ISR_INFO_T*) p_param; + CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cb_param->owner; + CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_drv_hal->owner; + int pkts_to_handle = 0; + + if(p_cpmac_priv->non_data_irq_expected) + { + p_cb_param->hal_isr(p_drv_hal->hal_dev, &pkts_to_handle); + p_drv_hal->hal_funcs->PacketProcessEnd(p_drv_hal->hal_dev); + } + else if(!p_cpmac_priv->set_to_close) + tasklet_schedule(&((CPMAC_ISR_INFO_T*) p_param)->tasklet); + else + ; // back off from doing anything more. We are closing down. +} + +void cpmac_handle_tasklet(unsigned long data) +{ + CPMAC_ISR_INFO_T *p_cb_param = (CPMAC_ISR_INFO_T*) data; + CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cb_param->owner; + CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_drv_hal->owner; + int pkts_to_handle; + + p_cb_param->hal_isr(p_drv_hal->hal_dev, &pkts_to_handle); + + if(test_bit(0, &p_cpmac_priv->non_data_irq_expected) || !pkts_to_handle) + p_drv_hal->hal_funcs->PacketProcessEnd(p_drv_hal->hal_dev); + else if(!test_bit(0, &p_cpmac_priv->set_to_close)) + tasklet_schedule(&p_cb_param->tasklet); + else + ; // Back off from processing packets we are closing down. +} + +int cpmac_hal_control(OS_DEVICE *p_dev, const char *key, + const char *action, void *value) +{ + CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv; + int ret_val = -1; + + if(key == NULL) + { + dbgPrint("Encountered NULL key.\n"); + return (-1); + } + + if(cpmac_ci_strcmp(key, "Sleep") == 0 && value != NULL) + { + unsigned int clocks_per_tick = cpmac_cpu_freq/HZ; + unsigned int requested_clocks = *(unsigned int*)value; + unsigned int requested_ticks = (requested_clocks + clocks_per_tick - 1)/clocks_per_tick; + mdelay(requested_ticks); + ret_val = 0; + } + else if(cpmac_ci_strcmp(key, "StateChange") == 0) + { + ret_val = cpmac_p_process_status_ind(p_cpmac_priv); + } + else if(cpmac_ci_strcmp(key, "Tick") == 0 && action != NULL) + { + if(cpmac_ci_strcmp(action, "Set") == 0 && value != NULL) + { + if(*(unsigned int*)value == 0) + { + cpmac_p_stop_timer(p_cpmac_priv->timer + TICK_TIMER); + ret_val = 0; + } + else + { + unsigned int clocks_per_tick = cpmac_cpu_freq/HZ; + unsigned int requested_clocks = *(unsigned int*)value; + unsigned int requested_ticks = (requested_clocks + clocks_per_tick - 1)/clocks_per_tick; + + p_cpmac_priv->delay_ticks = requested_ticks; /* save it for re-triggering */ + ret_val = cpmac_p_start_timer(p_cpmac_priv->timer + TICK_TIMER, + p_cpmac_priv->delay_ticks); + } + } + else if(cpmac_ci_strcmp(action, "Clear") == 0) + { + ret_val = cpmac_p_stop_timer(p_cpmac_priv->timer + TICK_TIMER); + } + else + ; + } + else if(cpmac_ci_strcmp(key, "MacAddr") == 0 && action != NULL) + { + if(cpmac_ci_strcmp(action, "Get") == 0 && value != NULL) + { + *(char **)value = p_cpmac_priv->mac_addr; + ret_val = 0; + } + } + else if(cpmac_ci_strcmp(key, "CpuFreq") == 0) + { + if(cpmac_ci_strcmp(action, "Get") == 0 && value != NULL) + { + *(unsigned int *)value = cpmac_cpu_freq; + dbgPrint("Cpu frequency for cpmacs is %u\n",cpmac_cpu_freq); + ret_val = 0; + } + } + else if(cpmac_ci_strcmp(key, "SioFlush") == 0) + { + ret_val = 0; + dbgPrint("\n"); + } + else if(cpmac_ci_strcmp(key, "CpmacFrequency") == 0) + { + /* For Sangam cpmac clock is off the PBUS */ + /* OS Needs to supply CORRECT frequency */ + if(cpmac_ci_strcmp(action, "Get") == 0 && value != NULL) + { + *(unsigned int *)value = CONFIG_AR7_SYS * 1000 * 1000; + ret_val = 0; + } + } + /* For now, providing back the default values. */ + else if(cpmac_ci_strcmp(key, "MdioClockFrequency") == 0) + { + if(cpmac_ci_strcmp(action, "Get") == 0 && value != NULL) + { + *(unsigned int *)value = 2200000; /*DEFAULT */ + ret_val = 0; + } + } + /* For now, providing back the default values. */ + else if(cpmac_ci_strcmp(key, "MdioBusFrequency") == 0) + { + /* For Sangam MdioBusFreq is off the PBUS */ + if(cpmac_ci_strcmp(action, "Get") == 0 && value != NULL) + { + *(unsigned int *)value = CONFIG_AR7_SYS * 1000 * 1000; + ret_val = 0; + } + } + +#if 0 +#if defined(CONFIG_AVALANCHE_AUTO_MDIX) + /* supporting Mdio Mdix switching */ + else if(cpmac_ci_strcmp(key, hcMdioMdixSwitch) == 0) + { + /* For Sangam Mdio-switching action should be always "set"*/ + if(cpmac_ci_strcmp(action, hcSet) == 0 && value != NULL ) + { + unsigned int mdix = *((unsigned int *) value) ; + + if(mdix) + avalanche_set_phy_into_mdix_mode(); + + else + avalanche_set_phy_into_mdi_mode(); + + ret_val = 0; + } + + } +#endif +#endif + else if(cpmac_ci_strcmp(key, hcMdioMdixSwitch) == 0) + { + /* For Sangam Mdio-switching action should be always "set"*/ + if(cpmac_ci_strcmp(action, hcSet) == 0 && value != NULL ) + { + unsigned int mdix = *((unsigned int *) value) ; + +#ifdef CONFIG_AR7_MDIX + avalanche_set_mdix_on_chip(0xa8610000 , mdix ? 1: 0); +#endif + + ret_val = 0; + } + + } + + return(ret_val); +} + + +int cpmac_hal_receive(OS_DEVICE *p_dev, FRAGLIST *fragList, + unsigned int fragCount, + unsigned int packet_size, + HAL_RECEIVEINFO *hal_receive_info, + unsigned int mode) +{ + CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv; + CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal; + struct sk_buff *p_skb = fragList[0].OsInfo; + p_skb->len = fragList[0].len; + + /* invalidate the cache. */ + dma_cache_inv((unsigned long)p_skb->data, fragList[0].len); +#ifdef CPMAC_TEST + xdump(p_skb->data, p_skb->len, "recv"); +#endif +#ifdef CPMAC_8021Q_SUPPORT + /* 802.1q stuff, just does the basic checking here. */ + if(!p_cpmac_priv->enable_802_1q && + p_skb->len > TCI_END_OFFSET && + IS_802_1Q_FRAME(p_skb->data + TPID_START_OFFSET)) + { + goto cpmac_hal_recv_frame_mismatch; + } +#endif + if(fragCount > 1) + { + int len; + struct sk_buff *p_temp_skb; + CPMAC_RX_CHAN_INFO_T *p_rx_chan_info = p_cpmac_priv->rx_chan_info; + int count; + + dbgPrint("Recv: It is multifragment for %s.\n", p_dev->name); + + p_skb = dev_alloc_skb(packet_size + + p_rx_chan_info->chan->tot_reserve_bytes); + if(p_skb == NULL) + { + p_cpmac_priv->net_dev_stats.rx_errors++; + goto cpmac_hal_recv_alloc_failed; + } + + p_skb->dev = p_dev; + skb_reserve(p_skb, p_rx_chan_info->chan->tot_reserve_bytes); + + for(count = 0; count < fragCount; count++) + { + p_temp_skb = fragList[count].OsInfo; + len = fragList[count].len; + + dma_cache_inv((unsigned long)p_temp_skb->data, len); + + memcpy(skb_put(p_skb, len), p_temp_skb->data, len); + dev_kfree_skb_any(p_temp_skb); + } + } + + +#if defined(CONFIG_MIPS_AVALANCHE_MARVELL) + /* Fetch the receiving port information from EGRESS TRAILOR Bytes*/ + p_dev->if_port = (unsigned char)p_skb->data[packet_size -(EGRESS_TRAILOR_LEN-1)] + AVALANCHE_MARVELL_BASE_PORT_ID; + skb_trim(p_skb, packet_size - EGRESS_TRAILOR_LEN); +#else + /* set length & tail */ + skb_trim(p_skb, packet_size); +#endif + + p_skb->protocol = eth_type_trans(p_skb, p_dev); + + netif_rx(p_skb); + +//#if defined (CONFIG_MIPS_AVALANCHE_LED) +// avalanche_led_action(p_cpmac_priv->led_handle, CPMAC_RX_ACTIVITY); +//#endif + + p_cpmac_priv->net_dev_stats.rx_packets++; + p_cpmac_priv->net_dev_stats.rx_bytes += packet_size; + + p_drv_hal->hal_funcs->RxReturn(hal_receive_info,1); + + return(0); + +cpmac_hal_recv_alloc_failed: + +#ifdef CPMAC_8021Q_SUPPORT +cpmac_hal_recv_frame_mismatch: +#endif + + fragCount--; + + do + { + dev_kfree_skb_any(fragList[fragCount].OsInfo); + } + while(fragCount--); + + p_cpmac_priv->net_dev_stats.rx_dropped++; + + return(-1); +} /*cpmac_receive*/ + + +void cpmac_hal_tear_down_complete(OS_DEVICE*a, int b, int ch) +{ + dbgPrint("what to do with this.\n"); +} + + +int cpmac_hal_send_complete(OS_SENDINFO *p_skb) +{ + CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_skb->dev->priv; + + p_cpmac_priv->net_dev_stats.tx_packets++; + p_cpmac_priv->net_dev_stats.tx_bytes += p_skb->len; + + dev_kfree_skb_any(p_skb); + + return(0); +} + + +int cpmac_reset(CPMAC_PRIVATE_INFO_T *p_cpmac_priv) +{ + // code here to reset the device/hal. Not now. + + netif_wake_queue(p_cpmac_priv->owner); + return(0); +} + +#ifdef CPMAC_TEST + +#define isprint(a) ((a >=' ')&&(a<= '~')) +void xdump( u_char* cp, int length, char* prefix ) +{ + int col, count; + u_char prntBuf[120]; + u_char* pBuf = prntBuf; + count = 0; + while(count < length){ + pBuf += sprintf( pBuf, "%s", prefix ); + for(col = 0;count + col < length && col < 16; col++){ + if (col != 0 && (col % 4) == 0) + pBuf += sprintf( pBuf, " " ); + pBuf += sprintf( pBuf, "%02X ", cp[count + col] ); + } + while(col++ < 16){ /* pad end of buffer with blanks */ + if ((col % 4) == 0) + sprintf( pBuf, " " ); + pBuf += sprintf( pBuf, " " ); + } + pBuf += sprintf( pBuf, " " ); + for(col = 0;count + col < length && col < 16; col++){ + if (isprint((int)cp[count + col])) + pBuf += sprintf( pBuf, "%c", cp[count + col] ); + else + pBuf += sprintf( pBuf, "." ); + } + sprintf( pBuf, "\n" ); + // SPrint(prntBuf); + printk(prntBuf); + count += col; + pBuf = prntBuf; + } + +} /* close xdump(... */ +#endif + + +static int __init cpmac_dev_probe(void) +{ + int retVal = 0; + int unit; + int instance_count = CONFIG_MIPS_CPMAC_PORTS; + + //cpmac_cpu_freq = avalanche_clkc_get_freq(CLKC_MIPS); + cpmac_cpu_freq = CONFIG_AR7_CPU * 1000 * 1000; + + build_psp_config(); + + for(unit = 0; unit < instance_count; unit++) + { + struct net_device *p_dev; + CPMAC_PRIVATE_INFO_T *p_cpmac_priv; + size_t dev_size; + int failed; + + dev_size = sizeof(struct net_device) + + sizeof(CPMAC_PRIVATE_INFO_T); + + + if((p_dev = (struct net_device *) kmalloc(dev_size, GFP_KERNEL)) == NULL) + { + dbgPrint( "Could not allocate memory for device.\n" ); + retVal = -ENOMEM; + break; + } + + memset(p_dev, 0, dev_size ); + + p_dev->priv = p_cpmac_priv + = (CPMAC_PRIVATE_INFO_T*)(((char *) p_dev) + sizeof(struct net_device)); + p_cpmac_priv->owner = p_dev; + + ether_setup(p_dev); + + p_cpmac_priv->instance_num = unit; + p_dev->init = cpmac_dev_init; + + g_dev_array[p_cpmac_priv->instance_num] = p_dev; + +#if defined CONFIG_MIPS_CPMAC_INIT_BUF_MALLOC + g_init_enable_flag = 1; + printk("Cpmac driver is allocating buffer memory at init time.\n"); +#endif + + /* This section gives a default value by the number of PHY in order to + * replace the default MACRO. */ + { + char *mac_port = prom_getenv("MAC_PORT"); /* Internal: 0, External: 1 */ + if(!mac_port || (0 != strcmp(mac_port, "0"))) { + printk("Using the MAC with external PHY\n"); + cfg_start_link_speed = _CPMDIO_NOPHY; + cpmac_max_frame_size = CPMAC_MAX_FRAME_SIZE + 4; + } + else { + printk("Using the MAC with internal PHY\n"); + cfg_start_link_speed = CFG_START_LINK_SPEED; + cpmac_max_frame_size = CPMAC_MAX_FRAME_SIZE; + } + g_cfg_start_link_params = cfg_start_link_speed; + } + + cpmac_p_detect_manual_cfg(cfg_link_speed, cfg_link_mode, cpmac_debug_mode); + + failed = register_netdev(p_dev); + if (failed) + { + dbgPrint("Could not register device for inst %d because of reason \ + code %d.\n", unit, failed); + retVal = -1; + kfree(p_dev); + break; + } + else + { + + char proc_name[100]; + int proc_category_name_len = 0; + + p_cpmac_priv->next_device = last_cpmac_device; + last_cpmac_device = p_dev; + + dbgPrint(" %s irq=%2d io=%04x\n",p_dev->name, (int) p_dev->irq, + (int) p_dev->base_addr); + + strcpy(proc_name, "avalanche/"); + strcat(proc_name, p_dev->name); + proc_category_name_len = strlen(proc_name); + + strcpy(proc_name + proc_category_name_len, "_rfc2665_stats"); + create_proc_read_entry(proc_name,0,NULL,cpmac_p_read_rfc2665_stats, p_dev); + + } + } + + if(retVal == 0) + { + /* To maintain backward compatibility with NSP. */ + gp_stats_file = create_proc_entry("avalanche/cpmac_stats", 0644, NULL); + if(gp_stats_file) + { + gp_stats_file->read_proc = cpmac_p_read_stats; + gp_stats_file->write_proc = cpmac_p_write_stats; + } + create_proc_read_entry("avalanche/cpmac_link", 0, NULL, cpmac_p_read_link, NULL); + create_proc_read_entry("avalanche/cpmac_ver", 0, NULL, cpmac_p_get_version, NULL); + + } + + cpmac_devices_installed = unit; + dbgPrint("Installed %d cpmac instances.\n", unit); + return ( (unit >= 0 ) ? 0 : -ENODEV ); + +} /* init_module */ + + +/*************************************************************** + * cleanup_module + * + * Returns: + * Nothing + * Parms: + * None + * + * Goes through the CpmacDevices list and frees the device + * structs and memory associated with each device (lists + * and buffers). It also ureserves the IO port regions + * associated with this device. + * + **************************************************************/ + +void cpmac_exit(void) +{ + struct net_device *p_dev; + CPMAC_PRIVATE_INFO_T *p_cpmac_priv; + + while (cpmac_devices_installed) + { + char proc_name[100]; + int proc_category_name_len = 0; + + p_dev = last_cpmac_device; + p_cpmac_priv = (CPMAC_PRIVATE_INFO_T *) p_dev->priv; + + dbgPrint("Unloading %s irq=%2d io=%04x\n",p_dev->name, (int) p_dev->irq, (int) p_dev->base_addr); + + if(g_init_enable_flag) + cpmac_p_dev_disable(p_dev); + + cpmac_drv_cleanup(p_cpmac_priv->drv_hal); + +//#if defined (CONFIG_MIPS_AVALANCHE_LED) +// avalanche_led_unregister(p_cpmac_priv->led_handle); +//#endif + strcpy(proc_name, "avalanche/"); + strcat(proc_name, p_dev->name); + proc_category_name_len = strlen(proc_name); + + strcpy(proc_name + proc_category_name_len, "_rfc2665_stats"); + remove_proc_entry(proc_name, NULL); + + release_mem_region(p_dev->base_addr, p_cpmac_priv->dev_size); + unregister_netdev(p_dev); + last_cpmac_device = p_cpmac_priv->next_device; + + kfree(p_cpmac_priv->drv_hal); + kfree(p_dev); + + cpmac_devices_installed--; + } + + if(gp_stats_file) + remove_proc_entry("avalanche/cpmac_stats", NULL); + + remove_proc_entry("avalanche/cpmac_link", NULL); + remove_proc_entry("avalanche/cpmac_ver", NULL); + + psp_config_cleanup(); +} + + +module_init(cpmac_dev_probe); +module_exit(cpmac_exit); diff -urN linux.old/drivers/net/avalanche_cpmac/cpmac.h linux.dev/drivers/net/avalanche_cpmac/cpmac.h --- linux.old/drivers/net/avalanche_cpmac/cpmac.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.dev/drivers/net/avalanche_cpmac/cpmac.h 2005-07-12 02:48:42.043594000 +0200 @@ -0,0 +1,379 @@ +/****************************************************************************** + * FILE PURPOSE: CPMAC Linux Network Device Driver Header + ****************************************************************************** + * FILE NAME: cpmac.h + * + * DESCRIPTION: CPMAC Network Device Driver Header + * + * REVISION HISTORY: + * Date Name Details + *----------------------------------------------------------------------------- + * 27 Nov 2002 Suraj S Iyer Initial Create. + * 09 Jun 2003 Suraj S Iyer Preparing for GA. + * + * (C) Copyright 2003, Texas Instruments, Inc + *******************************************************************************/ + +#ifndef CPMAC_H +#define CPMAC_H + +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cpmacHalLx.h" +#include "cpmac.h" + +/* PSP config headers */ +#include "psp_config_parse.h" +#include "psp_config_mgr.h" + +/* Probe Debug Section*/ + +/* debug */ +extern int cpmac_debug_mode; +#define dbgPrint if (cpmac_debug_mode) printk +#define errPrint printk + +char CpmacSignature[] = "Cpmac driver"; +static unsigned long irq_flags = 0; +OS_SETUP *p_os_setup = NULL; + +extern int avalanche_request_intr_pacing(int, unsigned int, unsigned int); +extern int avalanche_free_intr_pacing(unsigned int blk_num); + +/*---------------------------------------------------------------------------- + * Parameter extracting functionalities. + *--------------------------------------------------------------------------*/ +static int os_find_parm_u_int(void *info_ptr, const char *param, unsigned int *val) +{ + int ret_val = 0; + + if((ret_val = psp_config_get_param_uint(info_ptr, param, val)) == -1) + { + dbgPrint("Error: could not locate the requested \"%s\" param.\n",param); + ret_val = -1; + } + + return(ret_val); +} + +static int os_find_parm_val(void *info_ptr, const char *param, void *val) +{ + int ret_val = 0; + + if(psp_config_get_param_string(info_ptr, param, val) == -1) + { + dbgPrint("Error: could not locate the requested \"%s\" param.\n",param); + ret_val = -1; + } + + return(ret_val); +} + +static int os_find_device(int unit, const char *find_name, void *device_info) +{ + int ret_val = 0; + + if(psp_config_get((char *)find_name, unit, device_info) == -1) + { + dbgPrint("Error: could not locate the requested \"%s\" param.\n", find_name); + ret_val = -1; + } + + return(ret_val); +} + +/*--------------------------------------------------------------------------- + * Memory related OS abstraction. + *--------------------------------------------------------------------------*/ +void os_free(void *mem_ptr) +{ + kfree(mem_ptr); +} + +void os_free_buffer(OS_RECEIVEINFO *osReceiveInfo, void *mem_ptr) +{ + dev_kfree_skb_any(osReceiveInfo); +} + +void os_free_dev(void *mem_ptr) +{ + kfree(mem_ptr); +} + +void os_free_dma_xfer(void *mem_ptr) +{ + kfree(mem_ptr); +} + +static void *os_malloc(unsigned int size) +{ + return(kmalloc(size, GFP_KERNEL)); +} + +static void *os_malloc_dma_xfer(unsigned int size, + void *mem_base, + unsigned int mem_range) +{ + return(kmalloc(size, GFP_KERNEL)); +} + +static void *os_malloc_dev(unsigned int size) +{ + return(kmalloc(size, GFP_KERNEL)); +} + + +/*---------------------------------------------------------------------------- + * CRITICAL SECTION ENABLING/DISABLING. + *--------------------------------------------------------------------------*/ +static void os_critical_on(void) +{ + save_and_cli(irq_flags); +} + +static void os_critical_off(void) +{ + restore_flags(irq_flags); +} + +/*---------------------------------------------------------------------------- + * Cache related abstraction + *--------------------------------------------------------------------------*/ +static void os_cache_invalidate(void *mem_ptr, int size) +{ + dma_cache_inv((unsigned long)mem_ptr, size); +} + +static void os_cache_writeback(void *mem_ptr, int size) +{ + dma_cache_wback_inv((unsigned long)mem_ptr, size); +} + +/*----------------------------------------------------------------------------- + * Support functions. + *---------------------------------------------------------------------------*/ + +static void hal_drv_unregister_isr(OS_DEVICE *p_dev, int intr) +{ + CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv; + CPMAC_ISR_INFO_T *p_isr_cb_param = &p_cpmac_priv->cpmac_isr; + intr = LNXINTNUM(intr); + + free_irq(p_isr_cb_param->intr, p_isr_cb_param); + + dbgPrint("cpmac_hal_unregister called for the intr %d for unit %x and isr_cb_param %x.\n", + intr, p_cpmac_priv->instance_num, (unsigned int )&p_cpmac_priv->cpmac_isr); +} + + +static void hal_drv_register_isr(OS_DEVICE *p_dev, + CPMAC_HAL_ISR_FUNC_T hal_isr, int intr) +{ + CPMAC_PRIVATE_INFO_T *p_cpmac_priv = p_dev->priv; + CPMAC_DRV_HAL_INFO_T *p_drv_hal = p_cpmac_priv->drv_hal; + CPMAC_ISR_INFO_T *p_isr_cb_param = &p_cpmac_priv->cpmac_isr; + intr = LNXINTNUM(intr); + + dbgPrint("osRegister called for the intr %d for device %x and p_isr_cb_param %x.\n", + intr, (bit32u)p_dev, (bit32u)p_isr_cb_param); + + p_isr_cb_param->owner = p_drv_hal; + p_isr_cb_param->hal_isr = hal_isr; + p_isr_cb_param->intr = intr; + + tasklet_init(&p_isr_cb_param->tasklet, cpmac_handle_tasklet, (unsigned long)p_isr_cb_param); + dbgPrint("Success in registering irq %d for Cpmac unit# %d.\n", intr, p_cpmac_priv->instance_num); +} + +/*--------------------------------------------------------------------------- + * FUNCTIONS called by the CPMAC Net Device. + *-------------------------------------------------------------------------*/ +static int load_os_funcs(OS_FUNCTIONS *os_func) +{ + dbgPrint("os_init_module: Start\n"); + if( os_func == 0 ) + { + return(sizeof(OS_FUNCTIONS)); + } + + os_func->Control = cpmac_hal_control; + os_func->CriticalOn = os_critical_on; + os_func->CriticalOff = os_critical_off; + os_func->DataCacheHitInvalidate = os_cache_invalidate; + os_func->DataCacheHitWriteback = os_cache_writeback; + os_func->DeviceFindInfo = os_find_device; + os_func->DeviceFindParmUint = os_find_parm_u_int; + os_func->DeviceFindParmValue= os_find_parm_val; + os_func->Free = os_free; + os_func->FreeRxBuffer = os_free_buffer; + os_func->FreeDev = os_free_dev; + os_func->FreeDmaXfer = os_free_dma_xfer; + os_func->IsrRegister = hal_drv_register_isr; + os_func->IsrUnRegister = hal_drv_unregister_isr; + os_func->Malloc = os_malloc; + os_func->MallocDev = os_malloc_dev; + os_func->MallocDmaXfer = os_malloc_dma_xfer; + os_func->MallocRxBuffer = cpmac_hal_malloc_buffer; + os_func->Memset = memset; + os_func->Printf = printk; + os_func->Receive = cpmac_hal_receive; + os_func->SendComplete = cpmac_hal_send_complete; + os_func->Strcmpi = cpmac_ci_strcmp; + os_func->TeardownComplete = cpmac_hal_tear_down_complete; + os_func->Strstr = strstr; + os_func->Strtoul = simple_strtol; + os_func->Sprintf = sprintf; + os_func->Strlen = strlen; + + dbgPrint("os_init_module: Leave\n"); + + return(0); +} + + +int cpmac_drv_init(CPMAC_DRV_HAL_INFO_T *p_drv_hal) +{ + HAL_DEVICE *p_hal_dev = p_drv_hal->hal_dev; + HAL_FUNCTIONS *p_hal_funcs = p_drv_hal->hal_funcs; + + return(p_hal_funcs->Init(p_hal_dev)); +} + +int cpmac_drv_cleanup(CPMAC_DRV_HAL_INFO_T *p_drv_hal) +{ + HAL_DEVICE *p_hal_dev = p_drv_hal->hal_dev; + HAL_FUNCTIONS *p_hal_funcs = p_drv_hal->hal_funcs; + + int ret_val = p_hal_funcs->Shutdown(p_hal_dev); + +#if 0 + if(ret_val == 0) + kfree(p_hal_funcs); + else + ret_val = -1; +#endif + + kfree(p_drv_hal->os_funcs); + + return (ret_val); +} + +int cpmac_drv_tx_setup(HAL_FUNCTIONS *p_hal_funcs, + HAL_DEVICE *p_hal_dev, + CPMAC_TX_CHAN_INFO_T *p_tx_chan_info) +{ + int ret_val = 0; + int count = 0; + CHANNEL_INFO chan_info; + + /* Let's setup the TX Channels. */ + for(count=0; count < p_tx_chan_info->cfg_chan; count++) + { + chan_info.Channel = count; + chan_info.Direction = DIRECTION_TX; + chan_info.TxNumBuffers = p_tx_chan_info->chan[count].num_BD; + chan_info.TxServiceMax = p_tx_chan_info->chan[count].service_max; + chan_info.TxNumQueues = 0; + + if((ret_val = p_hal_funcs->ChannelSetup(p_hal_dev, &chan_info, + NULL)) != 0) + { + errPrint("Error in opening channel %d for TX.\n", count); + ret_val = -1; + break; + } + + p_tx_chan_info->opened_chan++; + } + + return(ret_val); +} + +int cpmac_drv_rx_setup(HAL_FUNCTIONS *p_hal_funcs, + HAL_DEVICE *p_hal_dev, + CPMAC_RX_CHAN_INFO_T *p_rx_chan_info) +{ + int ret_val = 0; + CHANNEL_INFO chan_info; + + chan_info.Channel = 0; + chan_info.Direction = DIRECTION_RX; + chan_info.RxBufSize = p_rx_chan_info->chan[0].buffer_size; + chan_info.RxBufferOffset= p_rx_chan_info->chan[0].buffer_offset; + chan_info.RxNumBuffers = p_rx_chan_info->chan[0].num_BD; + chan_info.RxServiceMax = p_rx_chan_info->chan[0].service_max; + + if(p_hal_funcs->ChannelSetup(p_hal_dev, &chan_info, p_rx_chan_info) != 0) + { + errPrint("Error in opening channel %d for RX.\n", 0); + ret_val = -1; + } + + return(ret_val); +} + +int cpmac_drv_start(CPMAC_DRV_HAL_INFO_T *p_drv_hal, + CPMAC_TX_CHAN_INFO_T *p_tx_chan_info, + CPMAC_RX_CHAN_INFO_T *p_rx_chan_info, + unsigned int flags) +{ + int ret_val = 0; + HAL_FUNCTIONS *p_hal_funcs = p_drv_hal->hal_funcs; + HAL_DEVICE *p_hal_dev = p_drv_hal->hal_dev; + + dbgPrint("It is in cpmac_drv_start for %x.\n", (unsigned int)p_drv_hal); + + if(flags & CHAN_SETUP) + { + if(cpmac_drv_tx_setup(p_hal_funcs, p_hal_dev, + p_tx_chan_info)!=0) + { + errPrint("Failed to set up tx channel(s).\n"); + ret_val = -1; + } + else if(cpmac_drv_rx_setup(p_hal_funcs, p_hal_dev, + p_rx_chan_info)!=0) + { + errPrint("Failed to set up rx channel.\n"); + ret_val = -1; + } + else + { + ret_val = 0; + } + } + + /* Error in setting up the Channels, quit. */ + if((ret_val == 0) && (ret_val = p_hal_funcs->Open(p_hal_dev)) != 0) + { + errPrint("failed to open the HAL!!!.\n"); + ret_val = -1; + } + + return (ret_val); +} /* cpmac_drv_start */ + + + +int cpmac_drv_tx_teardown(HAL_FUNCTIONS *p_hal_funcs, + HAL_DEVICE *p_hal_dev, + CPMAC_TX_CHAN_INFO_T *p_tx_chan_info, + unsigned int flags) +{ + int ret_val = 0; + int count = 0; + + /* Let's setup the TX Channels. */ + for(; p_tx_chan_info->opened_chan > 0; + p_tx_chan_info->opened_chan--, count++) + { + if(p_hal_funcs->ChannelTeardown(p_hal_dev, count, flags) != 0) + { + errPrint("Error in tearing down channel %d for TX.\n", count); + ret_val = -1; + break; + } + } + + return(ret_val); +} + + +int cpmac_drv_rx_teardown(HAL_FUNCTIONS *p_hal_funcs, + HAL_DEVICE *p_hal_dev, + unsigned int flags) +{ + int ret_val = 0; + + if(p_hal_funcs->ChannelTeardown(p_hal_dev, 0, flags) != 0) + { + errPrint("Error in tearing down channel %d for RX.\n", 0); + ret_val = -1; + } + + return(ret_val); +} + +int cpmac_drv_stop(CPMAC_DRV_HAL_INFO_T *p_drv_hal, + CPMAC_TX_CHAN_INFO_T *p_tx_chan_info, + CPMAC_RX_CHAN_INFO_T *p_rx_chan_info, + unsigned int flags) +{ + HAL_DEVICE *p_hal_dev = p_drv_hal->hal_dev; + HAL_FUNCTIONS *p_hal_funcs = p_drv_hal->hal_funcs; + int ret_val = 0; + + if(flags & CHAN_TEARDOWN) + { + unsigned int chan_flags = 0; + + if(flags & FREE_BUFFER) chan_flags |= 0x4; /* full tear down */ + if(flags & BLOCKING) chan_flags |= 0x8; /* blocking call */ + + dbgPrint("The teardown flags are %d.\n", flags); + dbgPrint("The teardown chan flags are %d.\n", chan_flags); + + if(cpmac_drv_tx_teardown(p_hal_funcs, p_hal_dev, + p_tx_chan_info, chan_flags | 0x1) != 0) + { + ret_val = -1; + errPrint("The tx channel teardown failed.\n"); + } + else if(cpmac_drv_rx_teardown(p_hal_funcs, p_hal_dev, chan_flags | 0x2) != 0) + { + ret_val = -1; + errPrint("The rx channel teardown failed.\n"); + } + else + { + ; + } + } + + if(ret_val == 0) + { + int close_flags = 1; + + if(flags & FREE_BUFFER) close_flags = 2; +// if(flags & COMPLETE) close_flags = 3; + + if(p_hal_funcs->Close(p_hal_dev, close_flags) != 0) + { + ret_val = -1; + } + } + + return(ret_val); +} + +int cpmac_drv_init_module(CPMAC_DRV_HAL_INFO_T *p_drv_hal, OS_DEVICE *p_os_dev, int inst) +{ + int ret_val = -1; + int hal_func_size; + + dbgPrint("Entering the CpmacInitModule for the inst %d \n", inst); + + if((p_drv_hal->os_funcs = kmalloc(sizeof(OS_FUNCTIONS), GFP_KERNEL)) == NULL) + { + errPrint("Failed to allocate memory for OS_FUNCTIONS.\n"); + } + else if(load_os_funcs(p_drv_hal->os_funcs) != 0) + { + errPrint("Failed to load OS funcs.\n"); + os_free(p_drv_hal->os_funcs); + } + else if(halCpmacInitModule(&p_drv_hal->hal_dev, p_os_dev, + &p_drv_hal->hal_funcs, p_drv_hal->os_funcs, + sizeof(*p_drv_hal->os_funcs), + &hal_func_size, inst) != 0) + { + errPrint("halCpmacInitModule failed for inst %d \n", inst); + os_free(p_drv_hal->os_funcs); + } + else if(p_drv_hal->hal_funcs->Probe(p_drv_hal->hal_dev) != 0) + { + errPrint("halCpmacProbe failed for inst %d \n", inst); + os_free(p_drv_hal->os_funcs); + } + else + { + /* every thing went well. */ + ret_val = 0; + } + + return (ret_val); +} diff -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<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<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<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<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<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<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<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<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<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;iRcbStart[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<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; iChData[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; iChData[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<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. + *
+ * 'FALSE' means that the CPHAL can reuse the receive data buffers. + *
+ * 'TRUE' : indicates the data buffers were retained by the OS + *
+ * 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).
+ * Possible Error Codes:
+ * @ref EC_VAL_INVALID_STATE "EC_VAL_INVALID_STATE"
+ * @ref EC_VAL_RCB_NEEDS_BUFFER "EC_VAL_RCB_NEEDS_BUFFER"
+ * @ref EC_VAL_RCB_DROPPED "EC_VAL_RCB_DROPPED"
+ */ +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; iEop = %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;iMallocDmaXfer(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;iOsFunc->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.
+ * @param Mode 32-bit value with the following bit fields:
+ * 31-16: Mode (used for module specific data).
+ * 15-08: Queue (transmit queue to send on).
+ * 07-00: Channel (channel number to send on). + * + * @return EC_NO_ERRORS (ok).
+ * Possible Error Codes:
+ * @ref EC_VAL_INVALID_STATE "EC_VAL_INVALID_STATE"
+ * @ref EC_VAL_NOT_LINKED "EC_VAL_NOT_LINKED"
+ * @ref EC_VAL_INVALID_CH "EC_VAL_INVALID_CH"
+ * @ref EC_VAL_OUT_OF_TCBS "EC_VAL_OUT_OF_TCBS"
+ * @ref EC_VAL_NO_TCBS "EC_VAL_NO_TCBS"
+ */ +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; iOff_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<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)&& + (PacketsServicedOff_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) + &&(PacketsServicedCriticalOff(); + + 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).
+ * Bit 1: Perform Rx teardown (if set).
+ * Bit 2: If set, perform full teardown (free buffers/descriptors). + * If clear, perform partial teardown (keep buffers).
+ * Bit 3 (MSB): If set, call is blocking. + * If clear, call is non-blocking. + * + * @return EC_NO_ERRORS (ok).
+ * Possible Error Codes:
+ * @ref EC_VAL_INVALID_STATE "EC_VAL_INVALID_STATE"
+ * @ref EC_VAL_INVALID_CH "EC_VAL_INVALID_CH"
+ * @ref EC_VAL_TX_TEARDOWN_ALREADY_PEND "EC_VAL_TX_TEARDOWN_ALREADY_PEND"
+ * @ref EC_VAL_RX_TEARDOWN_ALREADY_PEND "EC_VAL_RX_TEARDOWN_ALREADY_PEND"
+ * @ref EC_VAL_TX_CH_ALREADY_TORNDOWN "EC_VAL_TX_CH_ALREADY_TORNDOWN"
+ * @ref EC_VAL_RX_CH_ALREADY_TORNDOWN "EC_VAL_RX_CH_ALREADY_TORNDOWN"
+ * @ref EC_VAL_TX_TEARDOWN_TIMEOUT "EC_VAL_TX_TEARDOWN_TIMEOUT"
+ * @ref EC_VAL_RX_TEARDOWN_TIMEOUT "EC_VAL_RX_TEARDOWN_TIMEOUT"
+ * @ref EC_VAL_LUT_NOT_READY "EC_VAL_LUT_NOT_READY"
+ */ +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:
+ * 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.
+ * 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.
+ * 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).
+ * Possible Error Codes:
+ * @ref EC_VAL_INVALID_STATE "EC_VAL_INVALID_STATE"
+ * Any error code from halChannelTeardown().
+ */ +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<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()
+ 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.
+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() +
+Value is a 32-bit value with bits partioned as follows +
+ + 0 - 4 Phy Number
+ 5 - 9 Phy Register
+ 10 - 15 reserved
+ 16 - 31 Data (write only) +
+ + +Reading the Phy register + +@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 + +Writing the Phy register +@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 + +*** Example Showing turning values off/on *** +
+
+ +@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 +
+- "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() +
+- MdioBusFrequency : The frequency of the BUS that MDIO is on (requested via hcMdioBusFrequency) +
+- 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 - +
+- "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) +
+@par Example cpmac definition from the options.conf for the Sangam VDB +
+- 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 +
+@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<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;idev_base); + ptrValue = (bit32u*) Value; + for (i=0; idev_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;iOsFunc->Strcmpi(KeyCommon[i].strKey, pszKey)==0) + { + rc = InfoAccess(HalDev, KeyCommon[i].enKey, Action, Value); + } + } + for(i=enCpmacStart+1;iOsFunc->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;iDeviceFindParmUint(DeviceInfo, KeyCommon[i].strKey, (bit32u*)&Value); + if(!Error) + { + InfoAccess(HalDev, KeyCommon[i].enKey, enSET, (bit32u*)&Value); + } + } + for(i=enCpmacStart+1;iDeviceFindParmUint(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. +
+ *PARTIAL - Disable EMAC +
+ *FULL - Disable EMAC and call OS to free all allocated memory + * + *@retval + * 0 OK +
+ * 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<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<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; iChIsSetup[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; ChRcbStart[Ch] != 0) + FreeRx(HalDev,Ch); + + for(Queue=0; QueueTcbStart[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<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 +#include +#include + + +#define os_malloc(size) kmalloc(size, GFP_KERNEL) + +int psp_run_enumerator(void) +{ + return(0); +} + +#if defined (CONFIG_AVALANCHE_CPMAC_AUTO) + +static int auto_detect_cpmac_phy(void) +{ + +#define SELECT_INT_PHY_MAC 0 +#define SELECT_EXT_PHY_MAC 1 + + volatile unsigned long *reset_cntl = AVALANCHE_RESET_CONTROL_BASE, *mdio_cntl = ((int)AVALANCHE_MDIO_BASE + 0x4); + unsigned int j= 0, detected_phy_map = 0, auto_select = SELECT_INT_PHY_MAC; + + *reset_cntl |= (1 << AVALANCHE_MDIO_RESET_BIT) | (1 << AVALANCHE_LOW_CPMAC_RESET_BIT) | (1 << AVALANCHE_HIGH_CPMAC_RESET_BIT) | (1 << AVALANCHE_LOW_EPHY_RESET_BIT); + *mdio_cntl = (1 << 30) | ((CONFIG_AR7_SYS * 1000)/2200); + + for(j=0;j < 300000; j++) + { + if(j%100000) continue; + + detected_phy_map = *(mdio_cntl + 1); + if(detected_phy_map) + { + detected_phy_map &= ~AVALANCHE_LOW_CPMAC_PHY_MASK; + + if(detected_phy_map && !(detected_phy_map & (detected_phy_map - 1))) + { + auto_select = SELECT_EXT_PHY_MAC; + break; + } + } + } + + return(auto_select); + +} + +#endif + + +#ifndef AVALANCHE_LOW_CPMAC_MDIX_MASK +#define AVALANCHE_LOW_CPMAC_MDIX_MASK 0 +#endif + +void psp_load_default_static_cfg(void) +{ + char s2[100], s3[100]; + char s4[2000], s6[2000]; + int threshold = 20; + char *tx_threshold_ptr = prom_getenv("threshold"); + + if(tx_threshold_ptr) + threshold = simple_strtol(tx_threshold_ptr, (char **)NULL, 10); + + /* Static configuration if options.conf not present */ + sprintf(s3,"cpmdio(id=mii, base=%u, reset_bit=%d)", AVALANCHE_MDIO_BASE, 22); + sprintf(s2, "reset( id=[ResetRegister], base=%u)", AVALANCHE_RESET_CONTROL_BASE); + + sprintf(s4, "cpmac(id=[cpmac], unit=0, base=%u, size=0x800, reset_bit=%d, PhyMask=%u, MdixMask=%u, MLink=0, int_line=%d, memory_offset=0, RX_CAF=1, RX_PASSCRC=0, RX_CEF=1, RX_BCAST=0, RX_BCASTCH=0, Ch0=[TxNumBuffers=256, TxNumQueues=1, TxServiceMax=%d, RxNumBuffers=256, RxBufferOffset=0, RxBufSize=1000, RxServiceMax=128], Ch1=[TxNumBuffers=256, TxNumQueues=1, TxServiceMax=%d, RxNumBuffers=256, RxBufferOffset=0, RxBufSize=1000, RxServiceMax=128], Ch2=[TxNumBuffers=256, TxNumQueues=1, TxServiceMax=%d, RxNumBuffers=256, RxBufferOffset=0, RxBufSize=1000, RxServiceMax=128])", AVALANCHE_LOW_CPMAC_BASE, AVALANCHE_LOW_CPMAC_RESET_BIT, AVALANCHE_LOW_CPMAC_PHY_MASK, AVALANCHE_LOW_CPMAC_MDIX_MASK, AVALANCHE_LOW_CPMAC_INT,threshold,threshold,threshold); + + sprintf(s6, "cpmac(id=[cpmac], unit=1, base=%u, size=0x800, reset_bit=%d, PhyMask=%u, MLink=0, int_line=%d, memory_offset=0, RX_CAF=1, RX_PASSCRC=0, RX_CEF=1, RX_BCAST=0, RX_BCASTCH=0, Ch0=[TxNumBuffers=256, TxNumQueues=1, TxServiceMax=%d, RxNumBuffers=256, RxBufferOffset=0, RxBufSize=1000, RxServiceMax=128], Ch1=[TxNumBuffers=256, TxNumQueues=1, TxServiceMax=%d, RxNumBuffers=256, RxBufferOffset=0, RxBufSize=1000, RxServiceMax=128], Ch2=[TxNumBuffers=256, TxNumQueues=1, TxServiceMax=%d, RxNumBuffers=256, RxBufferOffset=0, RxBufSize=1000, RxServiceMax=128])", AVALANCHE_HIGH_CPMAC_BASE, AVALANCHE_HIGH_CPMAC_RESET_BIT, AVALANCHE_HIGH_CPMAC_PHY_MASK, AVALANCHE_HIGH_CPMAC_INT,threshold,threshold,threshold); + + psp_config_add("reset", s2, psp_config_strlen(s2), en_compile); + + +#if defined (CONFIG_AVALANCHE_LOW_CPMAC) + + psp_config_add("cpmdio", s3, psp_config_strlen(s3), en_compile); + psp_config_add("cpmac", s4, psp_config_strlen(s4), en_compile); + +#endif + + +#if defined (CONFIG_AVALANCHE_HIGH_CPMAC) + + psp_config_add("cpmdio", s3, psp_config_strlen(s3), en_compile); + psp_config_add("cpmac", s6, psp_config_strlen(s6), en_compile); + +#endif + +#if defined (CONFIG_AVALANCHE_CPMAC_AUTO) + { + char *phy_sel_ptr = prom_getenv("mac_phy_sel"); + int phy_sel = SELECT_EXT_PHY_MAC; + char *mac_port = prom_getenv("MAC_PORT"); /* Internal: 0, External: 1 */ + + if(phy_sel_ptr && (0 == strcmp(phy_sel_ptr, "int"))) + { + phy_sel = SELECT_INT_PHY_MAC; + } + + //if(phy_sel == auto_detect_cpmac_phy()) + if(!mac_port || (0 != strcmp(mac_port, "0"))) + { + printk("Using the MAC with external PHY\n"); + psp_config_add("cpmdio", s3, psp_config_strlen(s3), en_compile); + psp_config_add("cpmac", s6, psp_config_strlen(s6), en_compile); + } + else + { + printk("Using the MAC with internal PHY\n"); + psp_config_add("cpmdio", s3, psp_config_strlen(s3), en_compile); + psp_config_add("cpmac", s4, psp_config_strlen(s4), en_compile); + } + } + +#endif + +} + +char* psp_conf_read_file(char *p_file_name) +{ +#ifdef INCLUDE_FFS + + char *p_file_data = NULL; + unsigned int file_size; + FFS_FILE *p_file = NULL; + + if(p_file_name == NULL) + { + return (NULL); + } + + if(!(p_file = ffs_fopen(p_file_name, "r"))) + { + return(NULL); + } + + file_size = p_file->_AvailableBytes; + + p_file_data = os_malloc(file_size + 1); + + if(ffs_fread(p_file_data, file_size, 1, p_file) == 0) + { + kfree(p_file_data); + return(NULL); + } + + ffs_fclose(p_file); + + p_file_data[file_size] = '\0'; + + return(p_file_data); + +#else /* NO FFS */ + return(NULL); +#endif /* INCLUDE_FFS */ +} + +int psp_conf_get_line(char *p_in_data, char **next_line) +{ + char *p = p_in_data; + + while(*p && *p++ != '\n') + { + + } + + *next_line = p; + + return(p - 1 - p_in_data); +} + + +int psp_conf_is_data_line(char *line) +{ + int ret_val = 1; + + if(*line == '\0' || *line == '\n' || *line == '#') + ret_val = 0; + + return(ret_val); +} + +int psp_conf_get_key_size(char *data) +{ + char *p = data; + + while(*p && *p != '\n' && *p != '(' && *p != ' ') + p++; + + return(p - data); +} + +char* psp_conf_eat_white_spaces(char *p) +{ + while(*p && *p != '\n' && *p == ' ') + p++; + + return (p); +} + +int psp_build_from_opt_conf(void) +{ + char *data = NULL; + char *data_hold = NULL; + char *next_line = NULL; + int line_size = 0; + + if((data = psp_conf_read_file("/etc/options.conf")) == NULL) + return(-1); + + data_hold = data; + + while((line_size=psp_conf_get_line(data, &next_line)) != -1) + { + + char *name = NULL; + int name_size; + + data = psp_conf_eat_white_spaces(data); + + if(psp_conf_is_data_line(data)) + { + data[line_size] = '\0'; + + name_size = psp_conf_get_key_size(data); + + if(name_size > 0) + { + name = (char *) os_malloc(name_size + 1); + if(name == NULL) break; + + psp_config_memcpy(name, data, name_size); + name[name_size] = '\0'; + + psp_config_add(name, data, line_size, en_opt_conf); + + kfree(name); + } + + data[line_size] = '\n'; + } + + data = next_line; + } + + kfree(data_hold); + return (0); +} + + +int psp_write_conf_file(char *p_write_file, char * dev_cfg_string) +{ +#ifdef INCLUDE_FFS + int bytes_written=0; + FFS_FILE *file_ptr=NULL; + + /* + * NOTE: In current implementation of FFS in ADAM2 if the file exists beforehand, it + * can't be opened for write. + */ + if(!(file_ptr=ffs_fopen(p_write_file, "w"))) { + return(-1); + } + + /* Write into the file "output.con" the character string */ + /* write a \n before a writing a line */ + if(!(bytes_written = ffs_fwrite("\n", 1, sizeof(char), file_ptr))) { + return (-1); + } + + if(!(bytes_written = ffs_fwrite(dev_cfg_string, psp_config_strlen(dev_cfg_string), sizeof(char), file_ptr))) { + return (-1); + } + ffs_fclose(file_ptr); + return (bytes_written+1); +#else /* NO FFS */ + return(-1); +#endif /* INCLUDE_FFS */ +} + +void build_psp_config(void) +{ + + /* initialize the repository. */ + psp_config_init(); + +#ifdef INCLUDE_FFS + ffs_init(); +#endif /* INCLUDE_FFS */ + + /* read the configuration from the options.conf to override default ones */ + psp_build_from_opt_conf(); + + /* read the configuration which were not over ridden in options.conf */ + psp_load_default_static_cfg(); + + /* let the vlynq be enumerated. Enumerator will add cfg info + of the discovered device instances to the repository.*/ + psp_run_enumerator(); + + /* dump the repository*/ + dump_device_cfg_pool(); + +} + diff -urN linux.old/drivers/net/avalanche_cpmac/psp_config_build.h linux.dev/drivers/net/avalanche_cpmac/psp_config_build.h --- linux.old/drivers/net/avalanche_cpmac/psp_config_build.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.dev/drivers/net/avalanche_cpmac/psp_config_build.h 2005-07-12 02:48:42.176573000 +0200 @@ -0,0 +1,138 @@ +/****************************************************************************** + * FILE PURPOSE: PSP Config Manager - Configuration Build Header + ****************************************************************************** + * FILE NAME: psp_config_build.h + * + * DESCRIPTION: Configuration Build API's. + * + * REVISION HISTORY: + * 27 Nov 02 - PSP TII + * + * (C) Copyright 2002, Texas Instruments, Inc + *******************************************************************************/ + +#ifndef __PSP_CONF_BUILD_H__ +#define __PSP_CONF_BUILD_H__ + +/*------------------------------------------------------------------------------ + * Name: psp_conf_read_file + * + * Parameters: + * in: p_file_name - the name of the file to read from. + * + * Description: + * Reads the entire file in one shot. This function opens the + * file, determines the size of the data to be read, allocates + * the required memory, NULL terminates the data and closes the + * file. + * + * It is responsibily of the callee to free the memory after it is + * done with that data. + * + * + * Returns: + * A NULL pointer, if failed to read the data otherwise, a valid + * pointer referring to the data read from the file. + * + * Example: + * + * psp_conf_read_file("/etc/options.conf"); + *---------------------------------------------------------------------------*/ + char *psp_conf_read_file(char *p_file_name); + + /*---------------------------------------------------------------------------- + * Function : psp_conf_write_file + * + * Parameters: + * in: p_file_name - the file to which data is to be written. + * in: data - the NULL terminated data string. + * + * Description: + * Write the indicated data into the file. This function opens the file, + * appends the data to end of the file, closes the file. + * + * Returns: + * + * The number of bytes on success. + * 0 on failure. + * + * Example: + * + * psp_conf_write_file("/etc/outcon.conf", data); + *--------------------------------------------------------------------------*/ + int psp_conf_write_file(char *p_file_name, char *data); + + /*---------------------------------------------------------------------------- + * Function: psp_conf_get_line + * + * Parameters: + * in: data - the data from which the line is to identified. + * out: next_line - the pointer to start of the next line. + * + * Description: + * Expects the data to be '\n' separated segments and data is NULL + * terminated. Parses the given data for '\n' or '\0'. Provides a pointer + * to the start of next line in the next_line. + * + * Returns: + * -1 on error. + * 0 or more to indicate the number of bytes in the line starting at + * data. + *--------------------------------------------------------------------------*/ + int psp_get_conf_line(char *p_in_data, char **next_line); + + /*---------------------------------------------------------------------------- + * Function: psp_conf_is_data_line + * + * Parameters: + * in: line - the array of bytes. + * + * Description: + * Tests the first byte in the array for '\0' or '\n' or '#'. Lines + * starting with these characters are not considered data. + * + * Returns: + * 1 if the line has data. + * 0 otherwise. + * + *--------------------------------------------------------------------------*/ + int psp_conf_is_data_line(char *line); + + /*---------------------------------------------------------------------------- + * Function: psp_conf_eat_white_spaces + * + * Parameters: + * in: line - the array of bytes. + * + * Description: + * Eats white spaces at the begining of the line while looking out for + * '\0' or '\n' or ' '. + * + * Returns: + * Pointer to the begining of the non white space character. + * NULL if '\0' or '\n' is found. + * + *--------------------------------------------------------------------------*/ + char *psp_conf_eat_white_spaces(char *line); + + /*--------------------------------------------------------------------------- + * Function: psp_conf_get_key_size + * + * Parameters: + * in: line - the array of bytes. + * + * Description: + * Identifies the size of the 'key' in array formatted as + * key(id=[key1]....). This function also checks out for '\0' and '\n'. + * + * Returns: + * On success, The number of bytes that forms the key. + * 0 otherwise. + * + *-------------------------------------------------------------------------*/ + int psp_conf_get_key_size(char *line); + + + +#endif /* __PSP_CONF_BUILD_H__ */ + diff -urN linux.old/drivers/net/avalanche_cpmac/psp_config_mgr.c linux.dev/drivers/net/avalanche_cpmac/psp_config_mgr.c --- linux.old/drivers/net/avalanche_cpmac/psp_config_mgr.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.dev/drivers/net/avalanche_cpmac/psp_config_mgr.c 2005-07-12 02:48:42.177573000 +0200 @@ -0,0 +1,464 @@ +/****************************************************************************** + * FILE PURPOSE: PSP Config Manager Source + ****************************************************************************** + * FILE NAME: psp_config_mgr.c + * + * DESCRIPTION: + * + * Manages configuration information. The repository is managed on the basis of + * 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 +//#include +#include "psp_config_mgr.h" +#include "psp_config_util.h" + +#include + +/*----------------------------------------------------------- + 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 +#include + +/*-------------------------------------------------- + * 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 +#include "psp_config_util.h" +#include + +/*--------------------------------------------- + * 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;