Other Parts Discussed in Thread: SYSBIOS
Greetings TI-Community,
First of all can a TI-Employee confirm that the NDK ndk_2_21_01_38 is not compatible to multicore usage with the c6678? I read about this problem (depending on including nimu driver) in this forum but I cannot read any hint or warning in the offical documents.
Second I tested the PA_multicoreExample in default state on the EVM6678 sucessfully.
Now I modified the example to fit the following:
Each core should send his packets to a fixed MAC and IP address on an connected PC-NIC where a UDP server listen for the packets but receives nothing. I also failed to send packets to each core.
First of all I got some problems in understanding the principle. The help writes that every core gets the same MAC,IP and port on which he listen on. Why are there multiple unique sockets (MAC same, IP same, port same) allowed in this network configuration even if each core got his own queue he polls for entries?
In this thread I read that the phy is not initialized by the example:
http://e2e.ti.com/support/dsp/c6000_multi-core_dsps/f/639/p/196299/700615.aspx#700615
I checked that but with this configuration the RJ-Plug port on the EVM should work fine:
#define SIMULATOR_SUPPORT #ifdef SIMULATOR_SUPPORT Int cpswSimTest = 1; Int cpswEvm6678 = 1; Int cpswLpbkMode = CPSW_LOOPBACK_EXTERNAL;
Here are my modified files:
/**
* @file multicore_example.c
*
* @brief
* Example to illustrate the usage of EMAC CPSW3G switch using CPPI, QMSS
* low level drivers and CSL.
*
* This example application does the following:
* (1) Initializes:
* (a) Queue Manager (QM) Subsystem
* (b) Packet Accelerator (PA) CPPI DMA
* (c) Ethernet Subsystem (Ethernet switch + SGMII + MDIO)
* (d) PA Subsystem + PDSP
*
* (2) Sets up the CPPI descriptors and Queues required for sending and
* receiving data using Ethernet.
* (a) Uses Host descriptors
* (b) Uses High Priority Accumulation interrupts
*
* (3) Sets up the example application's configuration (MAC address
* it uses to send/recv data; IP address and port number it's listening
* on) in PA Subsystem so as to enable the PASS to forward all packets
* matching this configuration onto the application for processing.
* (a) Switch MAC address configured = 0x10:0x11:0x12:0x13:0x14:0x15
* (b) Example's IP address = 192.168.1.10
* (c) Example App's listening port = 0x5678
*
* (4) Sends packets onto wire
* (constructed manually in code here with following settings):
* (a) Source MAC = 0x00:0x01:0x02:0x03:0x04:0x05
* Destination MAC = 0x10:0x11:0x12:0x13:0x14:0x15
* (b) Source IP = 192.168.1.1
* Destination IP = 192.168.1.10
* (c) Source Port = 0x1234
* Destination Port= 0x5678
* (d) Payload Data (80 bytes)
*
* The packets sent by the application are sent onto wire and
* since the destination MAC on the packet is the Ethernet Switch
* MAC address, the packets are received by simulator and passed
* back up to the example application for processing.
*
* (5) Application receives all packets using QM High priority interrupt
* registered; Validates received packet against data sent.
*
* Example application Setup:
*
* PC Running Simulator using CCS connected to a
* Switch/Hub. You could put another PC on the Hub to observe packets
* being sent onto wire.
*
* Please consult the Readme.txt packaged with the example to
* setup the CCS simulator configuration required to run this example
* succesfully.
*
* \par
* ============================================================================
* @n (C) Copyright 2009, Texas Instruments, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <multicore_example.h>
#include <ti/csl/cslr_device.h>
#include <ti/csl/csl_psc.h>
#include <ti/csl/csl_pscAux.h>
/* PA LLD include */
#include <ti/drv/pa/pa.h>
/**************************************************************
************************** DEFINITIONS ************************
***************************************************************/
/* Number of packets to be used for testing the example. */
#define MAX_NUM_PACKETS 10u
#define SIMULATOR_SUPPORT
/**************************************************************
************************* GLOBAL VARIABLES ********************
***************************************************************/
/* Counters to track number of packets sent/received by this application */
extern volatile UInt32 gRxCounter, gTxCounter;
/*
* Default test configuration for the silicon
*
* To run test at the CCS simulator
* cpswSimTest = 1
* cpswLpbkMode = CPSW_LOOPBACK_EXTERNAL
*/
#ifdef SIMULATOR_SUPPORT
Int cpswSimTest = 1;
Int cpswEvm6678 = 1;
Int cpswLpbkMode = CPSW_LOOPBACK_EXTERNAL;
//Int cpswLpbkMode = CPSW_LOOPBACK_NONE;
#else
Int cpswSimTest = 0;
Int cpswLpbkMode = CPSW_LOOPBACK_INTERNAL;
#endif
void mdebugHaltPdsp (Int pdspNum);
volatile Int mdebugWait = 1;
/* multicore sync up variables */
#pragma DATA_ALIGN (globalCfgDone, 128)
#pragma DATA_SECTION(globalCfgDone, ".sharedDDR")
volatile UInt32 globalCfgDone = FALSE;
#pragma DATA_ALIGN (localCfgDone, 128)
#pragma DATA_SECTION(localCfgDone, ".sharedDDR")
/* number of local configuration completed */
volatile UInt32 localCfgDone = 0;
#pragma DATA_ALIGN (readyToSendPkts, 128)
#pragma DATA_SECTION(readyToSendPkts, ".sharedDDR")
volatile UInt32 readyToSendPkts = FALSE;
/* multicore results */
#define TEST_NOT_COMPLETED 0
#define TEST_PASSED 1
#define TEST_FAILED 2
#pragma DATA_ALIGN (testResult, 128)
#pragma DATA_SECTION(testResult, ".sharedDDR")
volatile UInt32 testResult[NUM_CORES];
/**************************************************************
**************** EXAMPLE APP FUNCTIONS ************************
***************************************************************/
Void MultiCoreApp ();
/***************************************************************************************
* FUNCTION PURPOSE: Power up PA subsystem
***************************************************************************************
* DESCRIPTION: this function powers up the PA subsystem domains
***************************************************************************************/
void passPowerUp (void)
{
/* PASS power domain is turned OFF by default. It needs to be turned on before doing any
* PASS device register access. This not required for the simulator. */
/* Set PASS Power domain to ON */
CSL_PSC_enablePowerDomain (CSL_PSC_PD_PASS);
/* Enable the clocks for PASS modules */
CSL_PSC_setModuleNextState (CSL_PSC_LPSC_PKTPROC, PSC_MODSTATE_ENABLE);
CSL_PSC_setModuleNextState (CSL_PSC_LPSC_CPGMAC, PSC_MODSTATE_ENABLE);
CSL_PSC_setModuleNextState (CSL_PSC_LPSC_Crypto, PSC_MODSTATE_ENABLE);
/* Start the state transition */
CSL_PSC_startStateTransition (CSL_PSC_PD_PASS);
/* Wait until the state transition process is completed. */
while (!CSL_PSC_isStateTransitionDone (CSL_PSC_PD_PASS));
}
/** ============================================================================
* @n@b MultiCoreApp
*
* @b Description
* @n Example application that sets up the application, sends, receives
* data.
*
* @param[in]
* @n None
*
* @return
* @n None
*
* =============================================================================
*/
Void MultiCoreApp (Void)
{
Int32 i;
UInt32 coreNum;
Int32 rxStatus=0;
volatile UInt32 testComplete=FALSE;
/* Get the core number. */
coreNum = CSL_chipReadReg(CSL_CHIP_DNUM);
System_printf ("************************************************\n");
System_printf ("*** PA Multi Core Example Started on Core %d ***\n",coreNum);
System_printf ("************************************************\n");
/* Init internal cycle counter */
TSCL = 1;
/* Disable L1 and L2 Cache */
//CACHE_wbAllL1d (CACHE_WAIT);
//CACHE_setL1DSize(CACHE_L1_0KCACHE);
//CACHE_setL1PSize(CACHE_L1_0KCACHE);
#ifndef L2_CACHE
CACHE_setL2Size(CACHE_0KCACHE);
#endif
/* Adjust the data packet as a function of the core number */
ModifyPacket();
/* All other cores wait for core 0 to finish the global config
and setup the QMSS/CPPI/PASS */
if(coreNum)
{
System_printf ("Waiting for global config...\n");
while(!globalCfgDone)
SYS_CACHE_INV ((void *) &globalCfgDone, 128, CACHE_WAIT);
}
/* Core 0 does the global initialization */
if(!coreNum)
{
/* Initialize local sync flags for all cores
Initialize test result for all cores */
for(i=0; i<NUM_CORES; i++)
{
testResult[i] =TEST_NOT_COMPLETED;
}
SYS_CACHE_WB ((void *) testResult, 128, CACHE_WAIT);
/* Enable PASS power domain */
passPowerUp();
/* Initialize the components required to run the example:
* (1) QMSS
* (2) CPPI
* (3) Ethernet switch subsystem + MDIO + SGMII
*/
/* Initialize QMSS */
if (Init_Qmss () != 0)
{
System_printf ("QMSS Global init failed \n");
BIOS_exit (-1);
}
else
{
System_printf ("QMSS successfully initialized \n");
}
/* Initialize CPPI */
if (Init_Cppi () != 0)
{
System_printf ("CPPI init failed \n");
BIOS_exit (-1);
}
else
{
System_printf ("CPPI successfully initialized \n");
}
/* Init PA LLD */
if (Init_PASS () != 0)
{
System_printf ("PASS init failed \n");
BIOS_exit (-1);
}
else
{
System_printf ("PASS successfully initialized \n");
}
/* Initialize the CPSW switch */
if (Init_Cpsw () != 0)
{
System_printf ("Ethernet subsystem init failed \n");
BIOS_exit (-1);
}
else
{
System_printf ("Ethernet subsystem successfully initialized \n");
}
/* Setup Tx */
if (Setup_Tx () != 0)
{
System_printf ("Tx setup failed \n");
BIOS_exit (-1);
}
else
{
System_printf ("Tx setup successfully done \n");
}
}
else
{
/* Cores other than 0 do local QMSS initialization */
if (Init_Qmss_Local () != 0)
{
System_printf ("QMSS Local init failed \n");
BIOS_exit (-1);
}
else
{
System_printf ("QMSS Local successfully initialized \n");
}
/*
* read the actual value from memory which have been initialized by core 0
*/
SYS_CACHE_INV ((void *) &gRxFreeQHnd, 128, CACHE_WAIT);
SYS_CACHE_INV ((void *) &gTxFreeQHnd, 128, CACHE_WAIT);
SYS_CACHE_INV ((void *) gPaTxQHnd, 128, CACHE_WAIT);
SYS_CACHE_INV ((void *) gPaL3Handles, 128, CACHE_WAIT);
SYS_CACHE_INV ((void *) &gPAInstHnd, 128, CACHE_WAIT);
}
/* Setup Rx */
if (Setup_Rx () != 0)
{
System_printf ("Rx setup failed \n");
BIOS_exit (-1);
}
else
{
System_printf ("Rx setup successfully done \n");
}
/* Setup PA */
if (Setup_PASS () != 0)
{
System_printf ("PASS setup failed \n");
BIOS_exit (-1);
}
else
{
System_printf ("PASS setup successfully done \n");
}
/* Core 0 finished the global config. Set flag so other
cores can start their local config. */
if (!coreNum)
{
globalCfgDone=TRUE;
SYS_CACHE_WB ((void *) &globalCfgDone, 128, CACHE_WAIT);
}
/* All cores update the counter informing that they finished their setup */
/* The global variable is a shared resource which is being accessed from multiple cores.
* So here we need to protect it and ensure that there is only 1 core which is accessing
* it at a time. We use a Hardware Semaphore to protect this. */
while ((CSL_semAcquireDirect (PA_APP_HW_SEM_SYS)) == 0);
/* Invalidate the cache and make sure you get the latest from the memory. */
SYS_CACHE_INV ((void *) &localCfgDone, 128, CACHE_WAIT);
/* The core has completed local initialization */
localCfgDone++;
/* The SRIO Socket has been created. Writeback the contents to the cache. */
SYS_CACHE_WB ((void *) &localCfgDone, 128, CACHE_WAIT);
/* Release the hardware semaphore. */
CSL_semReleaseSemaphore (PA_APP_HW_SEM_SYS);
/* All cores wait here to sync up and send packets to PA
at the same time. */
System_printf ("Waiting for all cores to reach the barrier before transmission starts ... \n");
while (localCfgDone != NUM_CORES)
SYS_CACHE_INV ((void *) &localCfgDone, 128, CACHE_WAIT);
/* Send data towards switch */
System_printf ("Packet Transmission Start ... \n");
for (i = 0; i < MAX_NUM_PACKETS; i ++)
{
if (SendPacket () != 0)
{
System_printf ("Packet %d send failed \n", i);
BIOS_exit (-1);
}
}
/* Wait until all packet reception is done */
System_printf ("Packet Transmission Done.\nWait for all packets to be Received ... \n");
/*
while (gRxCounter < gTxCounter)
{
if(ReceivePacket() != 0)
rxStatus=-1;
}
*/
while (1)
{
ReceivePacket();
}
System_printf ("Core %d: Packets Sent\t\t=\t%d \nCore %d: Packets Received\t=\t%d \n",coreNum, gTxCounter, coreNum, gRxCounter);
/* The global variable is a shared resource which is being accessed from multiple cores.
* So here we need to protect it and ensure that there is only 1 core which is accessing
* it at a time. We use a Hardware Semaphore to protect this. */
while ((CSL_semAcquireDirect (PA_APP_HW_SEM_SYS)) == 0);
/* Invalidate the cache and make sure you get the latest from the memory. */
SYS_CACHE_INV ((void *) testResult, 128, CACHE_WAIT);
if(rxStatus == 0)
testResult[coreNum]=TEST_PASSED;
else
testResult[coreNum]=TEST_FAILED;
/* Write the result back to the memory */
SYS_CACHE_WB ((void *) testResult, 128, CACHE_WAIT);
/* Release the hardware semaphore. */
CSL_semReleaseSemaphore (PA_APP_HW_SEM_SYS);
/* Core 0 collects all the results and declare PASS or Fail */
if(!coreNum)
{
System_printf ("Wait for all packets to be Received in all cores... \n");
/* Wait until all cores have completed the test */
while(!testComplete)
{
/* Give some time for the other cores to process the packet */
CycleDelay (10000);
testComplete=TRUE;
/* Invalidate the cache and make sure you get the latest from the memory. */
SYS_CACHE_INV ((void *) testResult, 128, CACHE_WAIT);
for(i=0; i<NUM_CORES; i++)
{
if(testResult[i]==TEST_NOT_COMPLETED)
testComplete=FALSE;
}
}
for(i=0; i<NUM_CORES; i++)
{
if(testResult[i]==TEST_PASSED)
System_printf ("Test passed on core %d\n",i);
else
System_printf ("Test failed on core %d\n",i);
}
}
System_printf ("**********************************************\n");
System_printf ("*** PA Multi Core Example Ended on Core %d ***\n",coreNum);
System_printf ("**********************************************\n");
/* Example application done. Return success */
//BIOS_exit (0);
}
/** ============================================================================
* @n@b main
*
* @b Description
* @n Entry point for single core example application.
*
* @param[in]
* @n None
*
* @return
* @n None
* =============================================================================
*/
Int32 main (Void)
{
//Task_Params cpswTaskParams;
/* Initialize the task params */
//Task_Params_init(&cpswTaskParams);
/* Create the CPSW single core example task */
//Task_create((Task_FuncPtr)&MultiCoreApp, &cpswTaskParams, NULL);
MultiCoreApp ();
/* Start the BIOS Task scheduler */
BIOS_start ();
return 0;
}
I changed the defines, disabled the task and let the MultiCoreApp() run once until catch in a receive loop for debug purposes.
/**
* @file cppi_qmss_mgmt.c
*
* @brief
* This file holds all the APIs required to configure CPPI/QMSS LLDs and
* to send/receive data using PA/QM.
*
* \par
* ============================================================================
* @n (C) Copyright 2009, Texas Instruments, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <multicore_example.h>
#include <ti/drv/qmss/qmss_firmware.h>
/* QMSS device specific configuration */
extern Qmss_GlobalConfigParams qmssGblCfgParams;
/* CPPI device specific configuration */
extern Cppi_GlobalConfigParams cppiGblCfgParams;
#if ( !defined( _LITTLE_ENDIAN ) && !defined( _BIG_ENDIAN ) ) \
|| ( defined(_LITTLE_ENDIAN ) && defined( _BIG_ENDIAN ) )
#error either _LITTLE_ENDIAN or _BIG_ENDIAN must be defined
#endif
/* Number of Tx Free descriptors to allocate */
#define NUM_TX_DESC NUM_HOST_DESC/2
/* Number of Rx Free descriptors to allocate */
#define NUM_RX_DESC NUM_HOST_DESC/2
/* Buffer sizes configured for
* - maximum command size to PA
* - Maximum size of the control messages
* from DSP
* - Maximum size of the packets being transmitted
*/
#define TX_BUF_SIZE (((300+15)/16)*16)
#define RX_BUF_SIZE TX_BUF_SIZE
/* Host Descriptor Region - [Size of descriptor * Number of descriptors]
*
* MUST be 16 byte aligned.
*/
#pragma DATA_SECTION(gHostDesc, ".sharedDDR")
#pragma DATA_ALIGN (gHostDesc, 16)
UInt8 gHostDesc[SIZE_HOST_DESC * NUM_HOST_DESC];
/* Buffers to be used for TX */
#pragma DATA_SECTION (cppiMemTX, ".cppiMemTX");
#pragma DATA_ALIGN(cppiMemTX, 16)
Uint8 cppiMemTX[NUM_TX_DESC][TX_BUF_SIZE];
/* Buffers to be used for RX */
#pragma DATA_SECTION (cppiMemRX, ".cppiMemRX");
#pragma DATA_ALIGN(cppiMemRX, 16)
Uint8 cppiMemRX[NUM_RX_DESC][RX_BUF_SIZE];
/* QMSS queue handles */
/* Queue with free descriptors */
#pragma DATA_SECTION(gGlobalFreeQHnd, ".sharedDDR")
Qmss_QueueHnd gGlobalFreeQHnd;
/* TX queues used to send data to PA PDSP/CPSW.*/
#pragma DATA_ALIGN (gPaTxQHnd, 128)
#pragma DATA_SECTION(gPaTxQHnd, ".sharedDDR")
Qmss_QueueHnd gPaTxQHnd [NUM_PA_TX_QUEUES];
/* TX queue with free decriptors attached to data buffers for transmission.*/
#pragma DATA_ALIGN (gTxFreeQHnd, 128)
#pragma DATA_SECTION(gTxFreeQHnd, ".sharedDDR")
Qmss_QueueHnd gTxFreeQHnd;
/* RX queue with free decriptors attached to data buffers to be used
by the PASS CPDMA to hold the received data.*/
#pragma DATA_ALIGN (gRxFreeQHnd, 128)
#pragma DATA_SECTION(gRxFreeQHnd, ".sharedDDR")
Qmss_QueueHnd gRxFreeQHnd;
/* RX queue used by the application to receive packets from PASS/CPSW.
Each core has an independent RX queue. */
#pragma DATA_SECTION(gRxQHnd, ".sharedDDR")
Qmss_QueueHnd gRxQHnd[NUM_CORES];
/* CPPI Handles used by the application */
#pragma DATA_SECTION(gCpdmaHnd, ".sharedDDR")
Cppi_Handle gCpdmaHnd;
#pragma DATA_SECTION(gCpdmaTxChanHnd, ".sharedDDR")
Cppi_ChHnd gCpdmaTxChanHnd [NUM_PA_TX_QUEUES];
#pragma DATA_SECTION(gCpdmaRxChanHnd, ".sharedDDR")
Cppi_ChHnd gCpdmaRxChanHnd [NUM_PA_RX_CHANNELS];
Cppi_FlowHnd gRxFlowHnd;
/* Constructed data packet to send.
Each core will have a slightly modified version
of this packet which is stored in the core's local memory. */
#define PACKET_UDP_DEST_PORT_SHIFT 36
#define PACKET_PAYLOAD_SHIFT 42
#pragma DATA_ALIGN(pktMatch, 16)
UInt8 pktMatch[] = {
0x2C, 0x44, 0xFD, 0x18, 0xF8, 0xC3, /* Dest MAC */ //0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, /* Src MAC */
0x08, 0x00, /* Ethertype = IPv4 */
0x45, 0x00, 0x00, 0x6c, /* IP version, services, total length */
0x00, 0x00, 0x00, 0x00, /* IP ID, flags, fragment offset */
0x05, 0x11, 0x32, 0x26, /* IP ttl, protocol (UDP), header checksum */
0xc0, 0xa8, 0x01, 0x01, /* Source IP address */
0xc0, 0xa8, 0x01, 0x16, /* Destination IP address */ //0xc0, 0xa8, 0x01, 0x0a,
0x12, 0x34, 0x56, 0x78, /* UDP source port, dest port */
0x00, 0x58, 0x1d, 0x18, /* UDP len, UDP checksum */
0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, /* 80 bytes of payload data */
0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41,
0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51,
0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61,
0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71,
0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81 };
/* Tx/Rx packet counters */
volatile UInt32 gTxCounter = 0, gRxCounter = 0;
/* High Priority Accumulation Interrupt Service Handler for this application */
Void Cpsw_RxISR (Void);
/** ============================================================================
* @n@b Convert_CoreLocal2GlobalAddr
*
* @b Description
* @n This API converts a core local L2 address to a global L2 address.
*
* @param[in]
* @n addr L2 address to be converted to global.
*
* @return UInt32
* @n >0 Global L2 address
* =============================================================================
*/
UInt32 Convert_CoreLocal2GlobalAddr (UInt32 addr)
{
UInt32 coreNum;
/* Get the core number. */
coreNum = CSL_chipReadReg(CSL_CHIP_DNUM);
/* Compute the global address. */
return ((1 << 28) | (coreNum << 24) | (addr & 0x00ffffff));
}
/** ============================================================================
* @n@b Init_Qmss
*
* @b Description
* @n This API initializes the QMSS LLD on core 0 only.
*
* @param[in]
* @n None
*
* @return Int32
* -1 - Error
* 0 - Success
* =============================================================================
*/
Int32 Init_Qmss (Void)
{
Int32 result;
Qmss_MemRegInfo memCfg;
Qmss_InitCfg qmssInitConfig;
Cppi_DescCfg cppiDescCfg;
UInt32 numAllocated;
/* Initialize QMSS */
memset (&qmssInitConfig, 0, sizeof (Qmss_InitCfg));
/* Set up QMSS configuration */
/* Use internal linking RAM */
qmssInitConfig.linkingRAM0Base = 0;
qmssInitConfig.linkingRAM0Size = 0;
qmssInitConfig.linkingRAM1Base = 0x0;
qmssInitConfig.maxDescNum = NUM_HOST_DESC;
qmssInitConfig.pdspFirmware[0].pdspId = Qmss_PdspId_PDSP1;
#ifdef _LITTLE_ENDIAN
qmssInitConfig.pdspFirmware[0].firmware = (void *) &acc48_le;
qmssInitConfig.pdspFirmware[0].size = sizeof (acc48_le);
#else
qmssInitConfig.pdspFirmware[0].firmware = (void *) &acc48_be;
qmssInitConfig.pdspFirmware[0].size = sizeof (acc48_be);
#endif
/* Initialize the Queue Manager */
result = Qmss_init (&qmssInitConfig, &qmssGblCfgParams);
if (result != QMSS_SOK)
{
System_printf ("Error initializing Queue Manager SubSystem, Error code : %d\n", result);
return -1;
}
/* Start Queue manager on this core */
Qmss_start ();
/* Setup the descriptor memory regions.
*
* The Descriptor base addresses MUST be global addresses and
* all memory regions MUST be setup in ascending order of the
* descriptor base addresses.
*/
/* Initialize and setup CPSW Host Descriptors required for example */
memset (gHostDesc, 0, SIZE_HOST_DESC * NUM_HOST_DESC);
memCfg.descBase = (UInt32 *) gHostDesc;
memCfg.descSize = SIZE_HOST_DESC;
memCfg.descNum = NUM_HOST_DESC;
memCfg.manageDescFlag = Qmss_ManageDesc_MANAGE_DESCRIPTOR;
memCfg.memRegion = Qmss_MemRegion_MEMORY_REGION0;
memCfg.startIndex = 0;
/* Insert Host Descriptor memory region */
result = Qmss_insertMemoryRegion(&memCfg);
if (result == QMSS_MEMREGION_ALREADY_INITIALIZED)
{
System_printf ("Memory Region %d already Initialized \n", memCfg.memRegion);
}
else if (result < QMSS_SOK)
{
System_printf ("Error: Inserting memory region %d, Error code : %d\n", memCfg.memRegion, result);
return -1;
}
/* Initialize all the descriptors we just allocated on the
* memory region above. Setup the descriptors with some well
* known values before we use them for data transfers.
*/
memset (&cppiDescCfg, 0, sizeof (cppiDescCfg));
cppiDescCfg.memRegion = Qmss_MemRegion_MEMORY_REGION0;
cppiDescCfg.descNum = NUM_HOST_DESC;
cppiDescCfg.destQueueNum = QMSS_PARAM_NOT_SPECIFIED;
cppiDescCfg.queueType = Qmss_QueueType_GENERAL_PURPOSE_QUEUE;
cppiDescCfg.initDesc = Cppi_InitDesc_INIT_DESCRIPTOR;
cppiDescCfg.descType = Cppi_DescType_HOST;
/* By default:
* (1) Return descriptors to tail of queue
* (2) Always return entire packet to this free queue
* (3) Set that PS Data is always present in start of SOP buffer
* (4) Configure free q num < 4K, hence qMgr = 0
* (5) Recycle back to the same Free queue by default.
*/
cppiDescCfg.returnPushPolicy = Qmss_Location_TAIL;
cppiDescCfg.cfg.host.returnPolicy = Cppi_ReturnPolicy_RETURN_ENTIRE_PACKET;
cppiDescCfg.cfg.host.psLocation = Cppi_PSLoc_PS_IN_DESC;
cppiDescCfg.returnQueue.qMgr = 0;
cppiDescCfg.returnQueue.qNum = QMSS_PARAM_NOT_SPECIFIED;
cppiDescCfg.epibPresent = Cppi_EPIB_EPIB_PRESENT;
/* Initialize the descriptors, create a free queue and push descriptors to a global free queue */
if ((gGlobalFreeQHnd = Cppi_initDescriptor (&cppiDescCfg, &numAllocated)) <= 0)
{
System_printf ("Error Initializing Free Descriptors, Error: %d \n", gGlobalFreeQHnd);
return -1;
}
else
{
System_printf ("Initializing Free Descriptors. \n");
}
/* Queue Manager Initialization Done */
return 0;
}
/** ============================================================================
* @n@b Init_Qmss_Local
*
* @b Description
* @n This API initializes the QMSS LLD in cores other than core 0.
*
* @param[in]
* @n None
*
* @return Int32
* -1 - Error
* 0 - Success
* =============================================================================
*/
Int32 Init_Qmss_Local (Void)
{
Int32 result;
while(1)
{
/* Block until Qmss_init() has completed by core 0 */
result = Qmss_start();
if(result == QMSS_NOT_INITIALIZED)
{
System_printf ("QMSS Not yet Initialized\n");
continue;
}
else if (result != QMSS_SOK) {
System_printf ("Qmss_start failed with error code %d\n", result);
return (-1);
}
if (result == QMSS_SOK)
{
break;
}
}
return 0;
}
/** ============================================================================
* @n@b Init_Cppi
*
* @b Description
* @n This API initializes the CPPI LLD, opens the PASS CPDMA and opens up
* the Tx, Rx channels required for data transfers.
*
* @param[in]
* @n None
*
* @return Int32
* -1 - Error
* 0 - Success
* =============================================================================
*/
Int32 Init_Cppi (Void)
{
Int32 result, i;
Cppi_CpDmaInitCfg cpdmaCfg;
UInt8 isAllocated;
Cppi_TxChInitCfg txChCfg;
Cppi_RxChInitCfg rxChInitCfg;
/* Initialize CPPI LLD */
result = Cppi_init (&cppiGblCfgParams);
if (result != CPPI_SOK)
{
System_printf ("Error initializing CPPI LLD, Error code : %d\n", result);
return -1;
}
/* Initialize PASS CPDMA */
memset (&cpdmaCfg, 0, sizeof (Cppi_CpDmaInitCfg));
cpdmaCfg.dmaNum = Cppi_CpDma_PASS_CPDMA;
if ((gCpdmaHnd = Cppi_open (&cpdmaCfg)) == NULL)
{
System_printf ("Error initializing CPPI for PASS CPDMA %d \n", cpdmaCfg.dmaNum);
return -1;
}
/* Open all CPPI Tx Channels. These will be used to send data to PASS/CPSW */
for (i = 0; i < NUM_PA_TX_QUEUES; i ++)
{
txChCfg.channelNum = i; /* CPPI channels are mapped one-one to the PA Tx queues */
txChCfg.txEnable = Cppi_ChState_CHANNEL_DISABLE; /* Disable the channel for now. */
txChCfg.filterEPIB = 0;
txChCfg.filterPS = 0;
txChCfg.aifMonoMode = 0;
txChCfg.priority = 2;
if ((gCpdmaTxChanHnd[i] = Cppi_txChannelOpen (gCpdmaHnd, &txChCfg, &isAllocated)) == NULL)
{
System_printf ("Error opening Tx channel %d\n", txChCfg.channelNum);
return -1;
}
Cppi_channelEnable (gCpdmaTxChanHnd[i]);
}
/* Open all CPPI Rx channels. These will be used by PA to stream data out. */
for (i = 0; i < NUM_PA_RX_CHANNELS; i++)
{
/* Open a CPPI Rx channel that will be used by PA to stream data out. */
rxChInitCfg.channelNum = i;
rxChInitCfg.rxEnable = Cppi_ChState_CHANNEL_DISABLE;
if ((gCpdmaRxChanHnd[i] = Cppi_rxChannelOpen (gCpdmaHnd, &rxChInitCfg, &isAllocated)) == NULL)
{
System_printf ("Error opening Rx channel: %d \n", rxChInitCfg.channelNum);
return -1;
}
/* Also enable Rx Channel */
Cppi_channelEnable (gCpdmaRxChanHnd[i]);
}
/* Clear CPPI Loobpack bit in PASS CDMA Global Emulation Control Register */
Cppi_setCpdmaLoopback(gCpdmaHnd, 0);
/* CPPI Init Done. Return success */
return 0;
}
/** ============================================================================
* @n@b Setup_Tx
*
* @b Description
* @n This API sets up all relevant data structures and configuration required
* for sending data to PASS/Ethernet. It sets up a Tx free descriptor queue,
* PASS Tx queues required for send.
*
* @param[in]
* @n None
*
* @return Int32
* -1 - Error
* 0 - Success
* =============================================================================
*/
Int32 Setup_Tx (Void)
{
UInt8 isAllocated, i;
Qmss_Queue qInfo;
Ptr pCppiDesc;
/* Open all Transmit (Tx) queues.
*
* These queues are used to send data to PA PDSP/CPSW.
*/
for (i = 0; i < NUM_PA_TX_QUEUES; i ++)
{
if ((gPaTxQHnd[i] = Qmss_queueOpen (Qmss_QueueType_PASS_QUEUE, QMSS_PARAM_NOT_SPECIFIED, &isAllocated)) < 0)
{
System_printf ("Error opening PA Tx queue \n");
return -1;
}
}
SYS_CACHE_WB ((void *)gPaTxQHnd, 128, CACHE_WAIT);
/* Open a Tx Free Descriptor Queue (Tx FDQ).
*
* This queue will be used to hold Tx free decriptors that can be filled
* later with data buffers for transmission onto wire.
*/
if ((gTxFreeQHnd = Qmss_queueOpen (Qmss_QueueType_STARVATION_COUNTER_QUEUE, QMSS_PARAM_NOT_SPECIFIED, &isAllocated)) < 0)
{
System_printf ("Error opening Tx Free descriptor queue \n");
return -1;
}
SYS_CACHE_WB ((void *)&gTxFreeQHnd, 128, CACHE_WAIT);
qInfo = Qmss_getQueueNumber (gTxFreeQHnd);
/* Attach some free descriptors to the Tx free queue we just opened. */
for (i = 0; i < NUM_TX_DESC; i++)
{
/* Get a free descriptor from the global free queue we setup
* during initialization.
*/
if ((pCppiDesc = Qmss_queuePop (gGlobalFreeQHnd)) == NULL)
{
break;
}
/* The descriptor address returned from the hardware has the
* descriptor size appended to the address in the last 4 bits.
*
* To get the true descriptor size, always mask off the last
* 4 bits of the address.
*/
pCppiDesc = (Ptr) ((UInt32) pCppiDesc & 0xFFFFFFF0);
/* Populate the Tx free descriptor with the buffer. */
Cppi_setData (Cppi_DescType_HOST, pCppiDesc, (Uint8 *)(&cppiMemTX[i]), TX_BUF_SIZE);
/* Save original buffer information */
Cppi_setOriginalBufInfo (Cppi_DescType_HOST, pCppiDesc, (Uint8 *)(&cppiMemTX[i]), TX_BUF_SIZE);
/* Setup the Completion queue:
*
* Setup the return policy for this desc to return to the free q we just
* setup instead of the global free queue.
*/
Cppi_setReturnQueue ((Cppi_DescType) Cppi_DescType_HOST, pCppiDesc, qInfo);
Cppi_setPacketLen (Cppi_DescType_HOST, pCppiDesc, TX_BUF_SIZE);
SYS_CACHE_WB (pCppiDesc, SIZE_HOST_DESC, CACHE_FENCE_WAIT);
/* Push descriptor to Tx free queue */
Qmss_queuePushDescSize (gTxFreeQHnd, pCppiDesc, SIZE_HOST_DESC);
}
if (i != NUM_TX_DESC)
{
System_printf ("Error allocating Tx free descriptors \n");
return -1;
}
/* All done with Rx configuration. Return success. */
return 0;
}
/** ============================================================================
* @n@b Setup_Rx
*
* @b Description
* @n This API sets up all relevant data structures and configuration required
* for receiving data from PASS/Ethernet. It sets up a Rx free descriptor queue
* with some empty pre-allocated buffers to receive data, and an Rx queue
* to which the Rxed data is streamed for the example application.
*
* @param[in]
* @n None
*
* @return Int32
* -1 - Error
* 0 - Success
* =============================================================================
*/
Int32 Setup_Rx (Void)
{
UInt8 isAllocated, i;
Qmss_Queue rxFreeQInfo, rxQInfo;
Ptr pCppiDesc;
Cppi_RxFlowCfg rxFlowCfg;
Ptr pDataBuffer;
Uint32 mySWInfo[] = {0x11112222, 0x33334444};
UInt32 coreNum;
/* Get the core number. */
coreNum = CSL_chipReadReg(CSL_CHIP_DNUM);
/* Open a Receive (Rx) queue.
*
* This queue will be used to hold all the packets received by PASS/CPSW
*
*/
if ((gRxQHnd[coreNum] = Qmss_queueOpen (Qmss_QueueType_GENERAL_PURPOSE_QUEUE, RX_QUEUE_NUM_INIT+coreNum, &isAllocated)) < 0)
{
System_printf ("Error opening gRxQHnd queue \n");
return -1;
}
rxQInfo = Qmss_getQueueNumber (gRxQHnd[coreNum]);
/* The following RX queues are shared between cores, so their
initialization is done by core zero only*/
if(!coreNum)
{
/* Open a Rx Free Descriptor Queue (Rx FDQ).
*
* This queue will hold all the Rx free decriptors. These descriptors will be
* used by the PASS CPDMA to hold data received via CPSW.
*/
if ((gRxFreeQHnd = Qmss_queueOpen (Qmss_QueueType_STARVATION_COUNTER_QUEUE, QMSS_PARAM_NOT_SPECIFIED, &isAllocated)) < 0)
{
System_printf ("Error opening Rx Free descriptor queue \n");
return -1;
}
SYS_CACHE_WB ((void *)&gRxFreeQHnd, 128, CACHE_WAIT);
rxFreeQInfo = Qmss_getQueueNumber (gRxFreeQHnd);
/* Attach some free descriptors to the Rx free queue we just opened. */
for (i = 0; i < NUM_RX_DESC; i++)
{
/* Get a free descriptor from the global free queue we setup
* during initialization.
*/
if ((pCppiDesc = Qmss_queuePop (gGlobalFreeQHnd)) == NULL)
{
System_printf ("Error poping descriptor.\n");
break;
}
/* The descriptor address returned from the hardware has the
* descriptor size appended to the address in the last 4 bits.
*
* To get the true descriptor size, always mask off the last
* 4 bits of the address.
*/
pCppiDesc = (Ptr) ((UInt32) pCppiDesc & 0xFFFFFFF0);
pDataBuffer = (Uint8 *)(&cppiMemRX[i]);
/* Populate the Rx free descriptor with the buffer we just allocated. */
Cppi_setData (Cppi_DescType_HOST, pCppiDesc, (UInt8 *)pDataBuffer, RX_BUF_SIZE);
/* Save original buffer information */
Cppi_setOriginalBufInfo (Cppi_DescType_HOST, pCppiDesc, (UInt8 *)pDataBuffer, RX_BUF_SIZE);
/* Setup the Completion queue:
*
* Setup the return policy for this desc to return to the free q we just
* setup instead of the global free queue.
*/
Cppi_setReturnQueue (Cppi_DescType_HOST, pCppiDesc, rxFreeQInfo);
Cppi_setSoftwareInfo (Cppi_DescType_HOST, pCppiDesc, (UInt8 *) mySWInfo);
Cppi_setPacketLen (Cppi_DescType_HOST, pCppiDesc, RX_BUF_SIZE);
SYS_CACHE_WB (pCppiDesc, SIZE_HOST_DESC, CACHE_FENCE_WAIT);
/* Push descriptor to Tx free queue */
Qmss_queuePushDescSize (gRxFreeQHnd, pCppiDesc, SIZE_HOST_DESC);
}
if (i != NUM_RX_DESC)
{
System_printf ("Error allocating Rx free descriptors \n");
return -1;
}
}
/* Setup a Rx Flow on each core. The only difference among the cores is the rxQInfo.
*
* A Rx flow encapsulates all relevant data properties that CPDMA would
* have to know in order to succefully receive data.
*/
/* Initialize the flow configuration */
memset (&rxFlowCfg, 0, sizeof(Cppi_RxFlowCfg));
rxFreeQInfo = Qmss_getQueueNumber (gRxFreeQHnd);
/* Let CPPI pick the next available flow */
rxFlowCfg.flowIdNum = CPPI_PARAM_NOT_SPECIFIED;
rxFlowCfg.rx_dest_qmgr = rxQInfo.qMgr;
rxFlowCfg.rx_dest_qnum = rxQInfo.qNum;
rxFlowCfg.rx_desc_type = Cppi_DescType_HOST;
rxFlowCfg.rx_ps_location = Cppi_PSLoc_PS_IN_DESC;
rxFlowCfg.rx_psinfo_present = 1; /* Enable PS info */
rxFlowCfg.rx_error_handling = 0; /* Drop the packet, do not retry on starvation by default */
rxFlowCfg.rx_einfo_present = 1; /* EPIB info present */
rxFlowCfg.rx_dest_tag_lo_sel = 0; /* Disable tagging */
rxFlowCfg.rx_dest_tag_hi_sel = 0;
rxFlowCfg.rx_src_tag_lo_sel = 0;
rxFlowCfg.rx_src_tag_hi_sel = 0;
rxFlowCfg.rx_size_thresh0_en = 0; /* By default, we disable Rx Thresholds */
rxFlowCfg.rx_size_thresh1_en = 0; /* By default, we disable Rx Thresholds */
rxFlowCfg.rx_size_thresh2_en = 0; /* By default, we disable Rx Thresholds */
rxFlowCfg.rx_size_thresh0 = 0x0;
rxFlowCfg.rx_size_thresh1 = 0x0;
rxFlowCfg.rx_size_thresh2 = 0x0;
rxFlowCfg.rx_fdq0_sz0_qmgr = rxFreeQInfo.qMgr; /* Setup the Receive free queue for the flow */
rxFlowCfg.rx_fdq0_sz0_qnum = rxFreeQInfo.qNum;
rxFlowCfg.rx_fdq0_sz1_qnum = 0x0;
rxFlowCfg.rx_fdq0_sz1_qmgr = 0x0;
rxFlowCfg.rx_fdq0_sz2_qnum = 0x0;
rxFlowCfg.rx_fdq0_sz2_qmgr = 0x0;
rxFlowCfg.rx_fdq0_sz3_qnum = 0x0;
rxFlowCfg.rx_fdq0_sz3_qmgr = 0x0;
rxFlowCfg.rx_fdq1_qnum = rxFreeQInfo.qNum; /* Use the Rx Queue to pick descriptors */
rxFlowCfg.rx_fdq1_qmgr = rxFreeQInfo.qMgr;
rxFlowCfg.rx_fdq2_qnum = rxFreeQInfo.qNum; /* Use the Rx Queue to pick descriptors */
rxFlowCfg.rx_fdq2_qmgr = rxFreeQInfo.qMgr;
rxFlowCfg.rx_fdq3_qnum = rxFreeQInfo.qNum; /* Use the Rx Queue to pick descriptors */
rxFlowCfg.rx_fdq3_qmgr = rxFreeQInfo.qMgr;
/* Configure the Rx flow */
if ((gRxFlowHnd = Cppi_configureRxFlow (gCpdmaHnd, &rxFlowCfg, &isAllocated)) == NULL)
{
System_printf ("Error configuring Rx flow \n");
return -1;
}
/* All done with Rx configuration. Return success. */
return 0;
}
/** ============================================================================
* @n@b SendPacket
*
* @b Description
* @n This API is called to actually send out data onto wire using ethernet.
* On success, this API increments a global Tx counter to indicate the same.
*
* @param[in]
* @n None
*
* @return Int32
* -1 - Error
* 0 - Success
* =============================================================================
*/
Int32 SendPacket (Void)
{
Cppi_HostDesc* pCppiDesc;
UInt32 dataBufferSize;
uint32_t key;
char psFlags = (cpswSimTest)?pa_EMAC_PORT_0:pa_EMAC_PORT_1;
/* Get a free descriptor from the global free queue we setup
* during initialization.
*/
if ((pCppiDesc = Qmss_queuePop (gTxFreeQHnd)) == NULL)
{
System_printf ("No Tx free descriptor. Cant run send/rcv test \n");
return -1;
}
/* The descriptor address returned from the hardware has the
* descriptor size appended to the address in the last 4 bits.
*
* To get the true descriptor size, always mask off the last
* 4 bits of the address.
*/
pCppiDesc = (Ptr) ((UInt32) pCppiDesc & 0xFFFFFFF0);
dataBufferSize = sizeof (pktMatch);
/* Disable Interrupts */
key = Hwi_disable();
/* Cleanup the prefetch buffer also. */
CSL_XMC_invalidatePrefetchBuffer();
SYS_CACHE_INV (pCppiDesc, SIZE_HOST_DESC, CACHE_FENCE_WAIT);
Cppi_setData ( Cppi_DescType_HOST,
(Cppi_Desc *) pCppiDesc,
(UInt8 *) Convert_CoreLocal2GlobalAddr((UInt32)pktMatch),
dataBufferSize
);
Cppi_setPacketLen (Cppi_DescType_HOST, (Cppi_Desc *)pCppiDesc, dataBufferSize);
if (cpswLpbkMode != CPSW_LOOPBACK_NONE)
{
/* Force the packet to specific EMAC port if loopback is enabled */
Cppi_setPSFlags(Cppi_DescType_HOST, (Cppi_Desc *)pCppiDesc, psFlags);
}
else
{
Cppi_setPSFlags(Cppi_DescType_HOST, (Cppi_Desc *)pCppiDesc, 0);
}
/* Clear PS Data */
Cppi_setPSLen (Cppi_DescType_HOST, (Cppi_Desc *)pCppiDesc, 0);
SYS_CACHE_WB (pCppiDesc, SIZE_HOST_DESC, CACHE_FENCE_WAIT);
/* Reenable Interrupts. */
Hwi_restore(key);
/* Send the packet out the mac. It will loop back to PA if the mac/switch
* have been configured properly
*/
Qmss_queuePushDescSize (gPaTxQHnd[8], pCppiDesc, SIZE_HOST_DESC);
/* Increment the application transmit counter */
gTxCounter ++;
/* Give some time for the PA to process the packet */
CycleDelay (10000);
return 0;
}
/** ============================================================================
* @n@b ReceivePacket
*
* @b Description
* @n This API is called to Receive packets.
*
* @param[in]
* @n None
*
* @return Int32
* -1 - Error
* 0 - Success
* =============================================================================
*/
Int32 ReceivePacket (void)
{
Cppi_Desc *hd;
Int j;
UInt32 coreNum;
Int32 status=0;
/* Get the core number. */
coreNum = CSL_chipReadReg(CSL_CHIP_DNUM);
/* Wait for a data packet from PA */
for (j = 0; j < 100; j++)
{
CycleDelay (1000);
if (Qmss_getQueueEntryCount (gRxQHnd[coreNum]) > 0)
{
hd = (Cppi_Desc *)(((UInt32)Qmss_queuePop (gRxQHnd[coreNum])) & ~0xf);
if(VerifyPacket(hd) != 0)
status=-1;
}
}
return (status);
}
/** ============================================================================
* @n@b VerifyPacket
*
* @b Description
* @n This API verifies a packet received against the expected data and
* returns 0 to inidcate success and -1 to indicate a mismatch.
*
* @param[in]
* @n pCppiDesc Packet descriptor received.
*
* @return Int32
* -1 - Error
* 0 - Success
* =============================================================================
*/
Int32 VerifyPacket (Cppi_Desc* pCppiDesc)
{
Cppi_HostDesc *pHostDesc;
UInt8 *pDataBuffer;
Int32 i;
pHostDesc = (Cppi_HostDesc *)pCppiDesc;
/* Cleanup the prefetch buffer also. */
CSL_XMC_invalidatePrefetchBuffer();
SYS_CACHE_INV (pHostDesc, SIZE_HOST_DESC, CACHE_FENCE_WAIT);
SYS_CACHE_INV ((Ptr)(pHostDesc->buffPtr), pHostDesc->buffLen, CACHE_FENCE_WAIT);
/* Verify the application software info we received is same
* as what we had sent earlier.
*/
if (pHostDesc->softwareInfo0 != 0xaaaaaaaa)
{
System_printf ("VerifyPacket: Found an entry in receive queue with swinfo0 = 0x%08x, expected 0x%08x\n",
pHostDesc->softwareInfo0, 0xaaaaaaaa);
pHostDesc->buffLen = pHostDesc->origBufferLen;
SYS_CACHE_WB (pHostDesc, SIZE_HOST_DESC, CACHE_FENCE_WAIT);
Qmss_queuePush (gRxFreeQHnd, (Ptr)pHostDesc, pHostDesc->buffLen, SIZE_HOST_DESC, Qmss_Location_TAIL);
return -1;
}
/* Verify the packet matches what we had sent */
pDataBuffer = (UInt8 *) pHostDesc->buffPtr;
for (i = 0; i < sizeof (pktMatch); i++)
{
if (pktMatch[i] != pDataBuffer[i])
{
System_printf ("VerifyPacket: Byte %d expected 0x%02x, found 0x%02x\n", i, pktMatch[i], pDataBuffer[i]);
System_flush();
/* Free the packet back to the Rx FDQ */
pHostDesc->buffLen = pHostDesc->origBufferLen;
SYS_CACHE_WB (pHostDesc, SIZE_HOST_DESC, CACHE_FENCE_WAIT);
Qmss_queuePush (gRxFreeQHnd, (Ptr)pHostDesc, pHostDesc->buffLen, SIZE_HOST_DESC, Qmss_Location_TAIL);
return -1;
}
}
/* Increment Rx counter to indicate the number of successfully
* received packets by the example app.
*/
gRxCounter ++;
/* Reset the buffer lenght and put the descriptor back on the free queue */
pHostDesc->buffLen = pHostDesc->origBufferLen;
SYS_CACHE_WB (pHostDesc, SIZE_HOST_DESC, CACHE_FENCE_WAIT);
Qmss_queuePush (gRxFreeQHnd, (Ptr)pHostDesc, pHostDesc->buffLen, SIZE_HOST_DESC, Qmss_Location_TAIL);
/* Verify packet done. Return success. */
return 0;
}
/** ============================================================================
* @n@b ModifyPacket
*
* @b Description
* @n This API modifies the data packet as a function on the core number.
* Each core will be associated with a different UDP port.
*
* @param[in]
* @n None
*
* @return Int32
* -1 - Error
* 0 - Success
* =============================================================================
*/
Void ModifyPacket (Void)
{
UInt32 coreNum;
/* Get the core number. */
coreNum = CSL_chipReadReg(CSL_CHIP_DNUM);
/* Modify UDP destination port so that the packet is
routed to the correct core*/
pktMatch[PACKET_UDP_DEST_PORT_SHIFT+1] += coreNum;
/* Modify first byte of the packet payload to have
an unique packet payload per core */
pktMatch[PACKET_PAYLOAD_SHIFT] += coreNum;
}
I changed the pktMatch[] array with the destination MAC of my PC-NIC and with my static IP from the PC.
/**
* @file pa_mgmt.c
*
* @brief
* Packet accelerator subsystem management functions.
*
* \par
* ============================================================================
* @n (C) Copyright 2009-2012, Texas Instruments, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <multicore_example.h>
/* PASS RL file */
#include <ti/csl/cslr_device.h>
#include <ti/csl/cslr_pa_ss.h>
/* Firmware images */
#include <ti/drv/pa/fw/pafw.h>
/* PA command response queue handle */
#pragma DATA_SECTION (gPaCfgCmdRespQHnd, ".sharedDDR")
Qmss_QueueHnd gPaCfgCmdRespQHnd;
/* Number of PA internal buffers to allocate */
#define PA_NUM_BUFFERS 3
/* PA definitions */
#define MAX_NUM_L2_HANDLES 10
#define MAX_NUM_L3_HANDLES 20
#define MAX_NUM_L4_HANDLES 40
#define BUFSIZE_PA_INST 256
#define BUFSIZE_L2_TABLE 1000
#define BUFSIZE_L3_TABLE 4000
/* PA instance */
#pragma DATA_SECTION (gPAInst, ".sharedDDR")
#pragma DATA_ALIGN(gPAInst, CACHE_LINESZ)
UInt8 gPAInst[SYS_ROUND_UP(BUFSIZE_PA_INST, CACHE_LINESZ)];
/* PA Driver Handle */
#pragma DATA_ALIGN (gPAInstHnd, CACHE_LINESZ)
#pragma DATA_SECTION (gPAInstHnd, ".sharedDDR")
Pa_Handle gPAInstHnd;
/* Memory used for PA handles */
#pragma DATA_SECTION (gMemL2Ram, ".sharedDDR")
#pragma DATA_ALIGN(gMemL2Ram, CACHE_LINESZ)
UInt8 gMemL2Ram[SYS_ROUND_UP(BUFSIZE_L2_TABLE, CACHE_LINESZ)];
#pragma DATA_SECTION (gMemL3Ram, ".sharedDDR")
#pragma DATA_ALIGN(gMemL3Ram, CACHE_LINESZ)
UInt8 gMemL3Ram[SYS_ROUND_UP(BUFSIZE_L3_TABLE, CACHE_LINESZ)];
#pragma DATA_ALIGN (gPaL2Handles, CACHE_LINESZ)
#pragma DATA_SECTION (gPaL2Handles, ".sharedDDR")
paHandleL2L3_t gPaL2Handles[SYS_ROUND_UP(MAX_NUM_L2_HANDLES, CACHE_LINESZ)];
#pragma DATA_ALIGN (gPaL3Handles, CACHE_LINESZ)
#pragma DATA_SECTION (gPaL3Handles, ".sharedDDR")
paHandleL2L3_t gPaL3Handles[SYS_ROUND_UP(MAX_NUM_L3_HANDLES, CACHE_LINESZ)];
#pragma DATA_ALIGN (gPaL4Handles, CACHE_LINESZ)
#pragma DATA_SECTION (gPaL4Handles, ".sharedDDR")
paHandleL4_t gPaL4Handles[SYS_ROUND_UP(MAX_NUM_L4_HANDLES, CACHE_LINESZ)];
extern volatile unsigned int cregister TSCL;
extern Qmss_QueueHnd gPaTxQHnd [NUM_PA_TX_QUEUES], gTxFreeQHnd, gRxFreeQHnd, gRxQHnd[NUM_CORES];
extern Cppi_FlowHnd gRxFlowHnd;
/** ============================================================================
* @n@b CycleDelay
*
* @b Description
* @n This API implements a clock delay logic using the Time Stamp Counter (TSC)
* of the DSP.
*
* @param[in]
* @n count Number of delay cycles to wait.
*
* @return
* @n None
* =============================================================================
*/
Void CycleDelay (Int32 count)
{
UInt32 TSCLin;
if (count <= 0)
return;
/* Get the current TSC */
TSCLin = TSCL;
while ((TSCL - TSCLin) < (UInt32)count);
}
/** ============================================================================
* @n@b Download_PAFirmware
*
* @b Description
* @n This API downloads the PA firmware required for PDSP operation.
*
* @param[in]
* @n None
*
* @return Int32
* -1 - Error
* 0 - Success
* =============================================================================
*/
Int32 Download_PAFirmware (Void)
{
Int32 i;
/* Hold the PA in reset state during download */
Pa_resetControl (gPAInstHnd, pa_STATE_RESET);
/* PDPSs 0-2 use image c1 */
for (i = 0; i < 3; i++)
{
Pa_downloadImage (gPAInstHnd, i, (Ptr)c1, c1Size);
}
/* PDSP 3 uses image c2 */
Pa_downloadImage (gPAInstHnd, 3, (Ptr)c2, c2Size);
/* PDSPs 4-5 use image m */
for (i = 4; i < 6; i++)
{
Pa_downloadImage (gPAInstHnd, i, (Ptr)m, mSize);
}
/* Enable the PA back */
Pa_resetControl (gPAInstHnd, pa_STATE_ENABLE);
return 0;
}
/** ============================================================================
* @n@b Add_MACAddress
*
* @b Description
* @n This API adds the switch MAC address to the PA PDSP Lookup table. This
* ensures that all packets destined for this MAC address get processed
* for forwarding to the host.
*
* @param[in]
* @n None
*
* @return Int32
* -1 - Error
* 0 - Success
* =============================================================================
*/
Int32 Add_MACAddress (Void)
{
Int32 j;
UInt16 cmdSize;
Qmss_Queue cmdReplyQInfo;
paEthInfo_t ethInfo = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Src mac = dont care */
{ 0x2C, 0x44, 0xFD, 0x18, 0xF8, 0xC3 }, /* Dest mac */ //0x10, 0x11, 0x12, 0x13, 0x14, 0x15
0, /* vlan = dont care */
0x0800, /* ether type = IPv4 */
0, /* MPLS tag = dont care */
0 /* Input EMAC port = dont care */
};
paRouteInfo_t routeInfo = { pa_DEST_CONTINUE_PARSE_LUT1, /* Continue parsing */
0, /* Flow Id = dont care */
0, /* queue = dont care */
0, /* multi route = dont care */
0, /* swinfo0 = dont care */
0, /* SwInfo 1 is dont care */
0, /* customType = pa_CUSTOM_TYPE_NONE */ \
0, /* customIndex: not used */ \
0, /* pkyType: for SRIO only */ \
NULL /* No commands */
};
paRouteInfo_t nFailInfo = { pa_DEST_DISCARD, /* Toss the packet */
0, /* Flow Id = dont care */
0, /* queue = dont care */
0, /* mutli route = dont care */
0, /* swinfo0 = dont care */
0, /* SwInfo 1 is dont care */
0, /* customType = pa_CUSTOM_TYPE_NONE */ \
0, /* customIndex: not used */ \
0, /* pkyType: for SRIO only */ \
NULL /* No commands */
};
paCmdReply_t cmdReplyInfo = { pa_DEST_HOST, /* Replies go to the host */
0, /* User chosen ID to go to swinfo0 */
0, /* Destination queue */
0 /* Flow ID */
};
paReturn_t retVal;
paEntryHandle_t retHandle;
Int32 handleType, cmdDest;
UInt32 psCmd = ((UInt32)(4 << 5) << 24);
UInt32 myswinfo[] = {0x11112222, 0x33334444};
Cppi_HostDesc* pHostDesc;
/* Get a Tx free descriptor to send a command to the PA PDSP */
if ((pHostDesc = Qmss_queuePop (gTxFreeQHnd)) == NULL)
{
System_printf ("Error obtaining a Tx free descriptor \n");
return -1;
}
/* The descriptor address returned from the hardware has the
* descriptor size appended to the address in the last 4 bits.
*
* To get the true descriptor pointer, always mask off the last
* 4 bits of the address.
*/
pHostDesc = (Ptr) ((UInt32) pHostDesc & 0xFFFFFFF0);
CSL_XMC_invalidatePrefetchBuffer();
SYS_CACHE_INV (pHostDesc, SIZE_HOST_DESC, CACHE_FENCE_WAIT);
SYS_CACHE_INV ((Ptr)pHostDesc->buffPtr, pHostDesc->buffLen, CACHE_FENCE_WAIT);
pHostDesc->buffLen = pHostDesc->origBufferLen;
cmdSize = pHostDesc->buffLen;
cmdReplyInfo.replyId = 0x55550000; /* unique for each add mac command */
/* Get the PA response queue number and populate the destination queue number
* in the PA response configuration.
*/
cmdReplyQInfo = Qmss_getQueueNumber (gPaCfgCmdRespQHnd);
cmdReplyInfo.queue = cmdReplyQInfo.qNum;
cmdReplyInfo.flowId = (uint8_t)Cppi_getFlowId(gRxFlowHnd);
retVal = Pa_addMac (gPAInstHnd,
pa_LUT1_INDEX_NOT_SPECIFIED,
ðInfo,
&routeInfo,
&nFailInfo,
&gPaL2Handles[0],
(paCmd_t) pHostDesc->buffPtr,
&cmdSize,
&cmdReplyInfo,
&cmdDest);
if (retVal != pa_OK)
{
System_printf ("Pa_addMac returned error %d\n", retVal);
return -1;
}
/* This sets the extended info for descriptors, and this is required so PS info
* goes to the right spot
*/
Cppi_setSoftwareInfo (Cppi_DescType_HOST, (Cppi_Desc *)pHostDesc, (UInt8 *)myswinfo);
/* Set the buffer length to the size used. It will be restored when the descriptor
* is returned
*/
Cppi_setPacketLen (Cppi_DescType_HOST, (Cppi_Desc *)pHostDesc, cmdSize);
pHostDesc->buffLen = cmdSize;
/* Mark the packet as a configuration packet */
Cppi_setPSData (Cppi_DescType_HOST, (Cppi_Desc *)pHostDesc, (UInt8 *)&psCmd, 4);
/* Send the command to the PA and wait for the return */
SYS_CACHE_WB (pHostDesc, SIZE_HOST_DESC, CACHE_FENCE_WAIT);
SYS_CACHE_WB ((Ptr)pHostDesc->buffPtr, pHostDesc->buffLen, CACHE_FENCE_WAIT);
Qmss_queuePush (gPaTxQHnd[cmdDest - pa_CMD_TX_DEST_0],
pHostDesc,
pHostDesc->buffLen,
SIZE_HOST_DESC,
Qmss_Location_TAIL
);
/* Poll on the PA response queue to see if response from PA has come */
for (j = 0; j < 100; j++)
{
CycleDelay (1000);
if (Qmss_getQueueEntryCount (gPaCfgCmdRespQHnd) > 0)
{
/* We have a response from PA PDSP for the command we submitted earlier for
* MAC address addition.
*/
pHostDesc = Qmss_queuePop (gPaCfgCmdRespQHnd);
/* Clear the size bytes */
pHostDesc = (Ptr) ((UInt32) pHostDesc & 0xFFFFFFF0);
SYS_CACHE_INV (pHostDesc, SIZE_HOST_DESC, CACHE_FENCE_WAIT);
SYS_CACHE_INV ((Ptr)pHostDesc->buffPtr, pHostDesc->buffLen, CACHE_FENCE_WAIT);
if (pHostDesc->softwareInfo0 != cmdReplyInfo.replyId)
{
System_printf ("Add_MACAddress: Found an entry in PA response queue with swinfo0 = 0x%08x, expected 0x%08x\n",
pHostDesc->softwareInfo0, cmdReplyInfo.replyId);
pHostDesc->buffLen = pHostDesc->origBufferLen;
SYS_CACHE_WB (pHostDesc, SIZE_HOST_DESC, CACHE_FENCE_WAIT);
Qmss_queuePush (gRxFreeQHnd, pHostDesc, pHostDesc->buffLen, SIZE_HOST_DESC, Qmss_Location_TAIL);
return -1;
}
retVal = Pa_forwardResult (gPAInstHnd, (Ptr)pHostDesc->buffPtr, &retHandle, &handleType, &cmdDest);
if (retVal != pa_OK)
{
System_printf ("PA sub-system rejected Pa_addMac command\n");
return -1;
}
/* Reset the buffer lenght and put the descriptor back on the Tx free queue */
pHostDesc->buffLen = pHostDesc->origBufferLen;
SYS_CACHE_WB (pHostDesc, SIZE_HOST_DESC, CACHE_FENCE_WAIT);
Qmss_queuePush (gRxFreeQHnd, pHostDesc, pHostDesc->buffLen, SIZE_HOST_DESC, Qmss_Location_TAIL);
break;
}
}
if (j == 100)
{
System_printf ("Timeout waiting for reply from PA to Pa_addMac command\n");
return -1;
}
return 0;
}
/** ============================================================================
* @n@b Add_IPAddress
*
* @b Description
* @n This API adds the IP Address the application's using to the PA PDSP
* Lookup table. This ensures that all packets destined for this
* IP address get forwarded up to the host.
*
* @param[in]
* @n None
*
* @return Int32
* -1 - Error
* 0 - Success
* =============================================================================
*/
Int32 Add_IPAddress (Void)
{
Int32 j;
UInt16 cmdSize;
Qmss_Queue cmdReplyQInfo;
paIpInfo_t ipInfo = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* IP source = dont care */
{ 0xc0, 0xa8, 0x01, 0x16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* IP dest */ //0xc0, 0xa8, 0x01, 0xa,
0, /* SPI = dont care */
0, /* flow = dont care */
pa_IPV4, /* IP type */
0, /* GRE protocol */
0, /* Ip protocol = dont care (TCP or UDP or anything else) */
0, /* TOS */
FALSE, /* TOS = dont care (seperate field since TOS=0 is valid */
0 /* SCTP destination port = dont care */
};
Int32 macLink = 0; /* Link this with the first MAC address created */
paRouteInfo_t routeInfo = { pa_DEST_CONTINUE_PARSE_LUT2, /* Continue parsing */
0, /* Flow Id = dont care */
0, /* queue = dont care */
0, /* multi route = dont care */
0, /* swinfo0 = dont care */
0, /* SwInfo 1 is dont care */
0, /* customType = pa_CUSTOM_TYPE_NONE */ \
0, /* customIndex: not used */ \
0, /* pkyType: for SRIO only */ \
NULL /* No commands */
};
paRouteInfo_t nFailInfo = { pa_DEST_DISCARD, /* Toss the packet */
0, /* Flow Id = dont care */
0, /* queue = dont care */
0, /* mutli route = dont care */
0, /* swinfo0 = dont care */
0, /* SwInfo 1 is dont care */
0, /* customType = pa_CUSTOM_TYPE_NONE */ \
0, /* customIndex: not used */ \
0, /* pkyType: for SRIO only */ \
NULL /* No commands */
};
paCmdReply_t cmdReplyInfo = { pa_DEST_HOST, /* Replies go to the host */
0, /* User chosen ID to go to swinfo0 */
0, /* Destination queue */
0 /* Flow ID */
};
paReturn_t retVal;
paEntryHandle_t retHandle;
Int32 handleType, cmdDest;
UInt32 psCmd = ((UInt32)(4 << 5) << 24);
UInt32 myswinfo[] = {0x11112222, 0x33334444};
Cppi_HostDesc* pHostDesc;
/* Get a Tx free descriptor to send a command to the PA PDSP */
if ((pHostDesc = Qmss_queuePop (gTxFreeQHnd)) == NULL)
{
System_printf ("Error obtaining a Tx free descriptor \n");
return -1;
}
/* The descriptor address returned from the hardware has the
* descriptor size appended to the address in the last 4 bits.
*
* To get the true descriptor pointer, always mask off the last
* 4 bits of the address.
*/
pHostDesc = (Ptr) ((UInt32) pHostDesc & 0xFFFFFFF0);
CSL_XMC_invalidatePrefetchBuffer();
SYS_CACHE_INV (pHostDesc, SIZE_HOST_DESC, CACHE_FENCE_WAIT);
SYS_CACHE_INV ((Ptr)pHostDesc->buffPtr, pHostDesc->buffLen, CACHE_FENCE_WAIT);
pHostDesc->buffLen = pHostDesc->origBufferLen;
cmdSize = pHostDesc->buffLen;
cmdReplyInfo.replyId = 0x55550001; /* unique for each add mac command */
/* Get the PA response queue number and populate the destination queue number
* in the PA response configuration.
*/
cmdReplyQInfo = Qmss_getQueueNumber (gPaCfgCmdRespQHnd);
cmdReplyInfo.queue = cmdReplyQInfo.qNum;
cmdReplyInfo.flowId = (uint8_t)Cppi_getFlowId(gRxFlowHnd);
retVal = Pa_addIp (gPAInstHnd,
pa_LUT_INST_NOT_SPECIFIED,
pa_LUT1_INDEX_NOT_SPECIFIED,
&ipInfo,
gPaL2Handles [macLink],
&routeInfo,
&nFailInfo,
&gPaL3Handles[0],
(paCmd_t) pHostDesc->buffPtr,
&cmdSize,
&cmdReplyInfo,
&cmdDest);
if (retVal != pa_OK)
{
System_printf ("Pa_addIp returned error %d\n", retVal);
return -1;
}
/* This sets the extended info for descriptors, and this is required so PS info
* goes to the right spot
*/
Cppi_setSoftwareInfo (Cppi_DescType_HOST, (Cppi_Desc *)pHostDesc, (UInt8 *)myswinfo);
/* Set the buffer length to the size used. It will be restored when the descriptor
* is returned
*/
Cppi_setPacketLen (Cppi_DescType_HOST, (Cppi_Desc *)pHostDesc, cmdSize);
pHostDesc->buffLen = cmdSize;
/* Mark the packet as a configuration packet */
Cppi_setPSData (Cppi_DescType_HOST, (Cppi_Desc *)pHostDesc, (UInt8 *)&psCmd, 4);
/* Send the command to the PA and wait for the return */
SYS_CACHE_WB (pHostDesc, SIZE_HOST_DESC, CACHE_FENCE_WAIT);
SYS_CACHE_WB ((Ptr)pHostDesc->buffPtr, pHostDesc->buffLen, CACHE_FENCE_WAIT);
Qmss_queuePush (gPaTxQHnd[cmdDest - pa_CMD_TX_DEST_0],
pHostDesc,
pHostDesc->buffLen,
SIZE_HOST_DESC,
Qmss_Location_TAIL
);
/* Poll on the PA response queue to see if response from PA has come */
for (j = 0; j < 100; j++)
{
CycleDelay (1000);
if (Qmss_getQueueEntryCount (gPaCfgCmdRespQHnd) > 0)
{
/* We have a response from PA PDSP for the command we submitted earlier for
* MAC address addition.
*/
pHostDesc = Qmss_queuePop (gPaCfgCmdRespQHnd);
/* Clear the size bytes */
pHostDesc = (Ptr) ((UInt32) pHostDesc & 0xFFFFFFF0);
SYS_CACHE_INV (pHostDesc, SIZE_HOST_DESC, CACHE_FENCE_WAIT);
SYS_CACHE_INV ((Ptr)pHostDesc->buffPtr, pHostDesc->buffLen, CACHE_FENCE_WAIT);
if (pHostDesc->softwareInfo0 != cmdReplyInfo.replyId)
{
System_printf ("Add_IPAddress:Found an entry in PA response queue with swinfo0 = 0x%08x, expected 0x%08x\n",
pHostDesc->softwareInfo0, cmdReplyInfo.replyId);
pHostDesc->buffLen = pHostDesc->origBufferLen;
SYS_CACHE_WB (pHostDesc, SIZE_HOST_DESC, CACHE_FENCE_WAIT);
Qmss_queuePush (gRxFreeQHnd, pHostDesc, pHostDesc->buffLen, SIZE_HOST_DESC, Qmss_Location_TAIL);
return -1;
}
retVal = Pa_forwardResult (gPAInstHnd, (Ptr)pHostDesc->buffPtr, &retHandle, &handleType, &cmdDest);
if (retVal != pa_OK)
{
System_printf ("PA sub-system rejected Pa_addIp command\n");
return -1;
}
/* Reset the buffer lenght and put the descriptor back on the Tx free queue */
pHostDesc->buffLen = pHostDesc->origBufferLen;
SYS_CACHE_WB (pHostDesc, SIZE_HOST_DESC, CACHE_FENCE_WAIT);
Qmss_queuePush (gRxFreeQHnd, pHostDesc, pHostDesc->buffLen, SIZE_HOST_DESC, Qmss_Location_TAIL);
break;
}
}
if (j == 100)
{
System_printf ("Timeout waiting for reply from PA to Pa_addIP command\n");
return -1;
}
return 0;
}
/** ============================================================================
* @n@b Add_Port
*
* @b Description
* @n This API adds the UDP port the application's using to the PA PDSP
* Lookup table. This ensures that all packets destined for this
* UDP port get forwarded up to the host.
*
* @param[in]
* @n None
*
* @return Int32
* -1 - Error
* 0 - Success
* =============================================================================
*/
Int32 Add_Port (Void)
{
Int32 j;
UInt16 cmdSize;
Qmss_Queue cmdReplyQInfo;
Qmss_Queue rxQInfo;
UInt16 ports = {0x5678};
Int32 ipLink = {0}; /* Link this with the first IP address created */
paRouteInfo_t routeInfo = { pa_DEST_HOST, /* Route a match to the host */
0, /* Flow ID 0 */
0, /* Destination queue */
-1, /* Multi route disabled */
0xaaaaaaaa, /* SwInfo 0 */
0, /* SwInfo 1 is dont care */
0, /* customType = pa_CUSTOM_TYPE_NONE */ \
0, /* customIndex: not used */ \
0, /* pkyType: for SRIO only */ \
NULL /* No commands */
};
paCmdReply_t cmdReplyInfo = { pa_DEST_HOST, /* Replies go to the host */
0, /* User chosen ID to go to swinfo0 */
0, /* Destination queue */
0 /* Flow ID */
};
paReturn_t retVal;
paEntryHandle_t retHandle;
Int32 handleType, cmdDest;
UInt32 psCmd = ((UInt32)(4 << 5) << 24);
UInt32 myswinfo[] = {0x11112220, 0x33334444};
Cppi_HostDesc* pHostDesc;
UInt32 coreNum;
/* Get the core number. */
coreNum = CSL_chipReadReg(CSL_CHIP_DNUM);
/* update UDP port as a function of the core number*/
ports += coreNum;
/* Get a Tx free descriptor to send a command to the PA PDSP */
if ((pHostDesc = Qmss_queuePop (gTxFreeQHnd)) == NULL)
{
System_printf ("Error obtaining a Tx free descriptor \n");
return -1;
}
/* The descriptor address returned from the hardware has the
* descriptor size appended to the address in the last 4 bits.
*
* To get the true descriptor pointer, always mask off the last
* 4 bits of the address.
*/
pHostDesc = (Ptr) ((UInt32) pHostDesc & 0xFFFFFFF0);
CSL_XMC_invalidatePrefetchBuffer();
SYS_CACHE_INV (pHostDesc, SIZE_HOST_DESC, CACHE_FENCE_WAIT);
SYS_CACHE_INV ((Ptr)pHostDesc->buffPtr, pHostDesc->buffLen, CACHE_FENCE_WAIT);
pHostDesc->buffLen = pHostDesc->origBufferLen;
cmdSize = pHostDesc->buffLen;
cmdReplyInfo.replyId = 0x55550002; /* unique for each add mac command */
/* Get the PA response queue number and populate the destination queue number
* in the PA response configuration.
*/
cmdReplyQInfo = Qmss_getQueueNumber (gPaCfgCmdRespQHnd);
cmdReplyInfo.queue = cmdReplyQInfo.qNum;
cmdReplyInfo.flowId = (uint8_t)Cppi_getFlowId(gRxFlowHnd);
/* Setup the Rx queue as destination for the packets */
rxQInfo = Qmss_getQueueNumber (gRxQHnd[coreNum]);
routeInfo.queue = rxQInfo.qNum;
routeInfo.flowId = (uint8_t)Cppi_getFlowId(gRxFlowHnd);
retVal = Pa_addPort (gPAInstHnd,
pa_LUT2_PORT_SIZE_16,
ports,
gPaL3Handles [ipLink],
FALSE, /* New Entry required */
pa_PARAMS_NOT_SPECIFIED, /* No queue diversion */
&routeInfo,
gPaL4Handles[0],
(paCmd_t) pHostDesc->buffPtr,
&cmdSize,
&cmdReplyInfo,
&cmdDest);
if (retVal != pa_OK)
{
System_printf ("Pa_addPort returned error %d\n", retVal);
return -1;
}
/* This sets the extended info for descriptors, and this is required so PS info
* goes to the right spot
*/
Cppi_setSoftwareInfo (Cppi_DescType_HOST, (Cppi_Desc *)pHostDesc, (UInt8 *)myswinfo);
/* Set the buffer length to the size used. It will be restored when the descriptor
* is returned
*/
Cppi_setPacketLen (Cppi_DescType_HOST, (Cppi_Desc *)pHostDesc, cmdSize);
pHostDesc->buffLen = cmdSize;
/* Mark the packet as a configuration packet */
Cppi_setPSData (Cppi_DescType_HOST, (Cppi_Desc *)pHostDesc, (UInt8 *)&psCmd, 4);
/* Send the command to the PA and wait for the return */
SYS_CACHE_WB ((Ptr)pHostDesc->buffPtr, pHostDesc->buffLen, CACHE_WAIT);
SYS_CACHE_WB (pHostDesc, SIZE_HOST_DESC, CACHE_FENCE_WAIT);
Qmss_queuePush (gPaTxQHnd[cmdDest - pa_CMD_TX_DEST_0],
pHostDesc,
pHostDesc->buffLen,
SIZE_HOST_DESC,
Qmss_Location_TAIL
);
/* Poll on the PA response queue to see if response from PA has come */
for (j = 0; j < 100; j++)
{
CycleDelay (1000);
if (Qmss_getQueueEntryCount (gPaCfgCmdRespQHnd) > 0)
{
/* We have a response from PA PDSP for the command we submitted earlier for
* MAC address addition.
*/
pHostDesc = Qmss_queuePop (gPaCfgCmdRespQHnd);
/* Clear the size bytes */
pHostDesc = (Ptr) ((UInt32) pHostDesc & 0xFFFFFFF0);
SYS_CACHE_INV (pHostDesc, SIZE_HOST_DESC, CACHE_FENCE_WAIT);
SYS_CACHE_INV ((Ptr)pHostDesc->buffPtr, pHostDesc->buffLen, CACHE_FENCE_WAIT);
if (pHostDesc->softwareInfo0 != cmdReplyInfo.replyId)
{
System_printf ("Add_Port: Found an entry in PA response queue with swinfo0 = 0x%08x, expected 0x%08x\n",
pHostDesc->softwareInfo0, cmdReplyInfo.replyId);
pHostDesc->buffLen = pHostDesc->origBufferLen;
SYS_CACHE_WB (pHostDesc, SIZE_HOST_DESC, CACHE_FENCE_WAIT);
Qmss_queuePush (gRxFreeQHnd, pHostDesc, pHostDesc->buffLen, SIZE_HOST_DESC, Qmss_Location_TAIL);
return -1;
}
retVal = Pa_forwardResult (gPAInstHnd, (Ptr)pHostDesc->buffPtr, &retHandle, &handleType, &cmdDest);
if (retVal != pa_OK)
{
System_printf ("PA sub-system rejected Pa_addPort command\n");
return -1;
}
/* Reset the buffer lenght and put the descriptor back on the Tx free queue */
pHostDesc->buffLen = pHostDesc->origBufferLen;
SYS_CACHE_WB (pHostDesc, SIZE_HOST_DESC, CACHE_FENCE_WAIT);
Qmss_queuePush (gRxFreeQHnd, pHostDesc, pHostDesc->buffLen, SIZE_HOST_DESC, Qmss_Location_TAIL);
break;
}
}
if (j == 100)
{
System_printf ("Timeout waiting for reply from PA to Pa_addPort command\n");
return -1;
}
return 0;
}
/** ============================================================================
* @n@b Init_PASS
*
* @b Description
* @n This API initializes the PASS/PDSP and opens a queue that the application
* can use to receive command responses from the PASS.
*
* @param[in]
* @n None
*
* @return Int32
* -1 - Error
* 0 - Success
* =============================================================================
*/
Int32 Init_PASS (Void)
{
UInt8 isAllocated;
paSizeInfo_t paSize;
paConfig_t paCfg;
Int32 retVal;
Int32 sizes[pa_N_BUFS];
Int32 aligns[pa_N_BUFS];
Void* bases[pa_N_BUFS];
memset(&paSize, 0, sizeof(paSizeInfo_t));
memset(&paCfg, 0, sizeof(paConfig_t));
/* Allocate space for the PA LLD buffers. The buffers we need to
* allocate space are:
* (1) PA LLD Instance Info Handle
* (2) PA LLD L2 Handle database
* (3) PA LLD L3 Handle database
* (4) PA LLD Usr Stats database
*/
paSize.nMaxL2 = MAX_NUM_L2_HANDLES;
paSize.nMaxL3 = MAX_NUM_L3_HANDLES;
paSize.nUsrStats = 0;
if ((retVal = Pa_getBufferReq(&paSize, sizes, aligns)) != pa_OK)
{
System_printf ("Pa_getBufferReq returned error %d\n", retVal);
return -1;
}
/* Validate the buffer allocations */
/* The first buffer is always the instance buffer */
if ((UInt32)gPAInst & (aligns[0] - 1))
{
System_printf ("Pa_getBufferReq requires %d alignment for instance buffer, but address is 0x%08x\n", aligns[0], (UInt32)gPAInst);
return -1;
}
if (sizeof(gPAInst) < sizes[0])
{
System_printf ("Pa_getBufferReq requires %d bytes for instance buffer, have only %d\n", sizes[0], sizeof(gPAInst));
return -1;
}
bases[0] = (Void *)gPAInst;
/* The second buffer is the L2 table */
if ((UInt32)gMemL2Ram & (aligns[1] - 1))
{
System_printf ("Pa_getBufferReq requires %d alignment for buffer 1, but address is 0x%08x\n", aligns[1], (UInt32)gMemL2Ram);
return (-1);
}
if (sizeof(gMemL2Ram) < sizes[1])
{
System_printf ("Pa_getBufferReq requires %d bytes for buffer 1, have only %d\n", sizes[1], sizeof(gMemL2Ram));
return -1;
}
bases[1] = (Void *)gMemL2Ram;
/* The third buffer is the L3 table */
if ((UInt32)gMemL3Ram & (aligns[2] - 1))
{
System_printf ("Pa_alloc requires %d alignment for buffer 1, but address is 0x%08x\n", aligns[2], (UInt32)gMemL3Ram);
return (-1);
}
if (sizeof(gMemL3Ram) < sizes[2])
{
System_printf ("Pa_alloc requires %d bytes for buffer 1, have only %d\n", sizes[2], sizeof(gMemL3Ram));
return (-1);
}
bases[2] = (Void *)gMemL3Ram;
/* Number of user statistics is set to 0 */
bases[3] = NULL;
/* Finally initialize the PA LLD */
paCfg.initTable = TRUE;
paCfg.initDefaultRoute = TRUE;
paCfg.baseAddr = CSL_PA_SS_CFG_REGS;
paCfg.sizeCfg = &paSize;
if ((retVal = Pa_create (&paCfg, bases, &gPAInstHnd)) != pa_OK)
{
System_printf ("Pa_create returned with error code %d\n", retVal);
return -1;
}
SYS_CACHE_WB( (Void *)gPAInst, BUFSIZE_PA_INST, CACHE_WAIT);
/* Download the PASS PDSP firmware */
if (Download_PAFirmware ())
{
return -1;
}
/* Open a PA Command Response Queue.
*
* This queue will be used to hold responses from the PA PDSP for all the
* commands issued by the example application.
*
* This queue is used only at configuration time to setup the PA PDSP.
*/
if ((gPaCfgCmdRespQHnd = Qmss_queueOpen (Qmss_QueueType_GENERAL_PURPOSE_QUEUE, QMSS_PARAM_NOT_SPECIFIED, &isAllocated)) < 0)
{
System_printf ("Error opening a PA Command Response queue \n");
return -1;
}
/* Init done. Return success. */
return 0;
}
/** ============================================================================
* @n@b Setup_PASS
*
* @b Description
* @n This API sets up the PA LLD/PDSP with MAC/IP/UDP configuration used by
* the example application.
*
* @param[in]
* @n None
*
* @return Int32
* -1 - Error
* 0 - Success
* =============================================================================
*/
Int32 Setup_PASS (Void)
{
UInt32 coreNum;
/* Get the core number. */
coreNum = CSL_chipReadReg(CSL_CHIP_DNUM);
/* All cores use same MAC and IP.
Let core 0 setup MAC and IP. All cores set
their own UDP port */
if(!coreNum)
{
/* Setup the PA PDSP to forward packets matching our switch MAC
* address up to the host onto the example application.
*/
if (Add_MACAddress () != 0)
{
return -1;
}
/* Add the IP address the example uses */
if (Add_IPAddress () != 0)
{
return -1;
}
}
/* Add the port number on which our application is going to listen on */
if (Add_Port () != 0)
{
return -1;
}
/* Return success */
return 0;
}
void mdebugHaltPdsp (Int pdspNum)
{
CSL_Pa_ssRegs *passRegs = (CSL_Pa_ssRegs *)CSL_PA_SS_CFG_REGS;
passRegs->PDSP_CTLSTAT[pdspNum].PDSP_CONTROL &= ~(CSL_PA_SS_PDSP_CONTROL_PDSP_ENABLE_MASK);
}
Here I changed the MAC in Add_MACAddress () and IP in Add_IPAddress () to fit my PC-NIC configuration.
/**
* @file cpsw_mgmt.c
*
* @brief
* This file holds all the Ethernet subsystem (CPSW + MDIO + SGMII) components
* initialization and setup code.
*
* \par
* ============================================================================
* @n (C) Copyright 2009, Texas Instruments, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/* C Standard library Include */
#include <string.h>
/* XDC types include */
#include <xdc/std.h>
/* Chip Level definitions include */
#include <ti/csl/csl_chip.h>
#include <ti/csl/csl_bootcfgAux.h>
/* CSL EMAC include */
#include <ti/csl/csl_cpsw.h>
#include <ti/csl/csl_cpsgmii.h>
#include <ti/csl/csl_cpsgmiiAux.h>
#include <ti/csl/cslr_cpsgmii.h>
#include <ti/csl/csl_mdio.h>
#include <ti/csl/csl_mdioAux.h>
/* BootCfg module include */
#include <ti/csl/csl_bootcfg.h>
#include <ti/csl/csl_bootcfgAux.h>
#include <multicore_example.h>
/** Number of ports in the ethernet subsystem */
#define NUM_PORTS 3u
/** Number of MAC/GMII ports in the ethernet switch */
#define NUM_MAC_PORTS 2u
/** ============================================================================
* @n@b Init_SGMII
*
* @b Description
* @n SGMII peripheral initialization code.
*
* @param[in]
* @n macPortNum MAC port number for which the SGMII port setup must
* be performed.
*
* @return
* @n None
* =============================================================================
*/
Int32 Init_SGMII (UInt32 macPortNum)
{
CSL_SGMII_ADVABILITY sgmiiCfg;
CSL_SGMII_STATUS sgmiiStatus;
/* Configure SGMII Port 1 only since it is connected to RJ45 at all known EVMs */
if(cpswSimTest || (macPortNum == 1))
{
/* Reset the port before configuring it */
CSL_SGMII_doSoftReset (macPortNum);
while (CSL_SGMII_getSoftResetStatus (macPortNum) != 0);
/* Hold the port in soft reset and set up
* the SGMII control register:
* (1) Enable Master Mode (default)
* (2) Enable Auto-negotiation
*/
CSL_SGMII_startRxTxSoftReset (macPortNum);
if (cpswLpbkMode == CPSW_LOOPBACK_NONE)
{
CSL_SGMII_disableMasterMode (macPortNum);
}
else
{
CSL_SGMII_enableMasterMode (macPortNum);
if (cpswLpbkMode == CPSW_LOOPBACK_INTERNAL)
{
CSL_SGMII_enableLoopback (macPortNum);
}
}
/* Setup the Advertised Ability register for this port:
* (1) Enable Full duplex mode
* (2) Enable Auto Negotiation
*/
sgmiiCfg.linkSpeed = CSL_SGMII_1000_MBPS;
sgmiiCfg.duplexMode = CSL_SGMII_FULL_DUPLEX;
CSL_SGMII_setAdvAbility (macPortNum, &sgmiiCfg);
CSL_SGMII_enableAutoNegotiation (macPortNum);
CSL_SGMII_endRxTxSoftReset (macPortNum);
/* Wait for SGMII Link */
if (!cpswSimTest)
{
do
{
CSL_SGMII_getStatus(macPortNum, &sgmiiStatus);
} while (sgmiiStatus.bIsLinkUp != 1);
/* Wait for SGMII Autonegotiation to complete without error */
do
{
CSL_SGMII_getStatus(macPortNum, &sgmiiStatus);
if (sgmiiStatus.bIsAutoNegError != 0)
return -1;
} while (sgmiiStatus.bIsAutoNegComplete != 1);
/*
* May need to wait some more time for the external PHY to be ready to transmit packets reliabily.
* It is possible to access the PHY status register through the MDIO interface to check when
* the PHY is ready.
* To avoid platform-dependent code, we just introduce about 2ms wait here
*/
if((cpswLpbkMode == CPSW_LOOPBACK_EXTERNAL) || (cpswLpbkMode == CPSW_LOOPBACK_NONE))
CycleDelay(2000000);
}
}
/* All done with configuration. Return Now. */
return 0;
}
/** ============================================================================
* @n@b Init_MAC
*
* @b Description
* @n This API initializes the CPGMAC Sliver (MAC Port) port.
*
* @param[in]
* @n macPortNum MAC port number for which the initialization must be done.
*
* @param[in]
* @n macAddress MAC address to configure on this port.
*
* @param[in]
* @n mtu Maximum Frame length to configure on this port.
*
* @return
* @n None
* =============================================================================
*/
int Init_MAC (UInt32 macPortNum, UInt8 macAddress[6], UInt32 mtu)
{
/* Reset MAC Sliver 0 */
CSL_CPGMAC_SL_resetMac (macPortNum);
while (CSL_CPGMAC_SL_isMACResetDone (macPortNum) != TRUE);
/* Setup the MAC Control Register for this port:
* (1) Enable Full duplex
* (2) Enable GMII
* (3) Enable Gigabit
* (4) Enable External Configuration. This enables
* the "Full duplex" and "Gigabit" settings to be
* controlled externally from SGMII
* (5) Don't enable any control/error/short frames
*/
CSL_CPGMAC_SL_enableFullDuplex (macPortNum);
CSL_CPGMAC_SL_enableGMII (macPortNum);
CSL_CPGMAC_SL_enableGigabit (macPortNum);
CSL_CPGMAC_SL_enableExtControl (macPortNum);
/* Configure the MAC address for this port */
//CSL_CPSW_3GF_setPortMACAddress (macPortNum, macAddress);
/* Configure VLAN ID/CFI/Priority.
*
* For now, we are not using VLANs so just configure them
* to all zeros.
*/
CSL_CPSW_3GF_setPortVlanReg (macPortNum, 0, 0, 0);
/* Configure the Receive Maximum length on this port,
* i.e., the maximum size the port can receive without
* any errors.
*
* Set the Rx Max length to the MTU configured for the
* interface.
*/
CSL_CPGMAC_SL_setRxMaxLen (macPortNum, mtu);
/* Done setting up the MAC port */
return 0;
}
/** ============================================================================
* @n@b Init_MDIO
*
* @b Description
* @n Not supported at moment. MDIO is not simulated yet.
*
* @param[in]
* @n None
*
* @return
* @n None
* =============================================================================
*/
Void Init_MDIO (Void)
{
/* Return success. */
return;
}
/** ============================================================================
* @n@b Init_Switch
*
* @b Description
* @n This API sets up the ethernet switch subsystem and its Address Lookup
* Engine (ALE) in "Switch" mode.
*
* @param[in]
* @n mtu Maximum Frame length to configure on the switch.
*
* @return
* @n None
* =============================================================================
*/
Void Init_Switch (UInt32 mtu)
{
CSL_CPSW_3GF_PORTSTAT portStatCfg;
/* Enable the CPPI port, i.e., port 0 that does all
* the data streaming in/out of EMAC.
*/
CSL_CPSW_3GF_enablePort0 ();
CSL_CPSW_3GF_disableVlanAware ();
CSL_CPSW_3GF_setPort0VlanReg (0, 0, 0);
CSL_CPSW_3GF_setPort0RxMaxLen (mtu);
/* Enable statistics on both the port groups:
*
* MAC Sliver ports - Port 1, Port 2
* CPPI Port - Port 0
*/
portStatCfg.p0AStatEnable = 1;
portStatCfg.p0BStatEnable = 1;
portStatCfg.p1StatEnable = 1;
portStatCfg.p2StatEnable = 1;
CSL_CPSW_3GF_setPortStatsEnableReg (&portStatCfg);
/* Setup the Address Lookup Engine (ALE) Configuration:
* (1) Enable ALE.
* (2) Clear stale ALE entries.
* (3) Disable VLAN Aware lookups in ALE since
* we are not using VLANs by default.
* (4) No Flow control
* (5) Configure the Unknown VLAN processing
* properties for the switch, i.e., which
* ports to send the packets to.
*/
CSL_CPSW_3GF_enableAle ();
CSL_CPSW_3GF_clearAleTable ();
CSL_CPSW_3GF_disableAleVlanAware ();
CSL_CPSW_3GF_disableAleTxRateLimit ();
CSL_CPSW_3GF_setAlePrescaleReg (125000000u/1000u);
CSL_CPSW_3GF_setAleUnkownVlanReg (7, 3, 3, 7);
if(cpswLpbkMode != CPSW_LOOPBACK_NONE)
CSL_CPSW_3GF_enableAleBypass();
/* Done with switch configuration */
return;
}
/** ============================================================================
* @n@b Switch_update_addr
*
* @b Description
* @n This API add/delete entries in the Address Lookup Engine (ALE) in "Switch" mode.
*
* @param[in]
* @n portNum Switch port number.
* @param[in]
* @n macAddress MAC address to configure on the switch.
*
* @param[in]
* @n add 0:add; 1:delete.
*
* @return
* @n None
*
* @Note It supports "add" operation only now.
* =============================================================================
*/
int Switch_update_addr (Uint32 portNum, UInt8 macAddress[6], Uint16 add)
{
Uint32 i;
CSL_CPSW_3GF_ALE_PORTCONTROL alePortControlCfg;
CSL_CPSW_3GF_ALE_UNICASTADDR_ENTRY ucastAddrCfg;
/* Configure the address in "Learning"/"Forward" state */
alePortControlCfg.portState = ALE_PORTSTATE_FORWARD;
alePortControlCfg.dropUntaggedEnable = 0;
alePortControlCfg.vidIngressCheckEnable = 0;
alePortControlCfg.noLearnModeEnable = (cpswLpbkMode != CPSW_LOOPBACK_NONE)?1:0;
alePortControlCfg.mcastLimit = 0;
alePortControlCfg.bcastLimit = 0;
CSL_CPSW_3GF_setAlePortControlReg (portNum, &alePortControlCfg);
/*
* The following code is required for device simulator only.
* It is also served as an example of adding MAC address to the ALE table manually
*/
if (cpswSimTest)
{
/* Program the ALE with the MAC address.
*
* The ALE entries determine the switch port to which any
* matching received packet must be forwarded to.
*/
/* Get the next free ALE entry to program */
for (i = 0; i < CSL_CPSW_3GF_NUMALE_ENTRIES; i++)
{
if (CSL_CPSW_3GF_getALEEntryType (i) == ALE_ENTRYTYPE_FREE)
{
/* Found a free entry */
break;
}
}
if (i == CSL_CPSW_3GF_NUMALE_ENTRIES)
{
/* No free ALE entry found. return error. */
return -1;
}
else
{
/* Found a free ALE entry to program our MAC address */
memcpy (ucastAddrCfg.macAddress, macAddress, 6); // Set the MAC address
ucastAddrCfg.ucastType = ALE_UCASTTYPE_UCAST_NOAGE; // Add a permanent unicast address entryALE_UCASTTYPE_UCAST_NOAGE.
ucastAddrCfg.secureEnable = FALSE;
ucastAddrCfg.blockEnable = FALSE;
ucastAddrCfg.portNumber = portNum; // Add the ALE entry for this port
/* Setup the ALE entry for this port's MAC address */
CSL_CPSW_3GF_setAleUnicastAddrEntry (i, &ucastAddrCfg);
}
}
/* Done with upading address */
return 0;
}
/** ============================================================================
* @n@b Init_SGMII_SERDES
*
* @b Description
* @n This API sets up the configuration for the SGMII SERDES. Assumes a 125 MHz
* reference clock.
*
* @param[in]
* @n None
*
* @return
* @n None
* =============================================================================
*/
Int32 Init_SGMII_SERDES(Void)
{
/*
* The following SERDES configuration is required for chip simulator only.
* The platform-dependent SERDES configuration should be done by the corresponding
* CCS GEL scripts or platformLib
*/
if (cpswSimTest)
{
/* Unlock the chip configuration registers to allow SGMII SERDES registers to
* be written */
CSL_BootCfgUnlockKicker();
CSL_BootCfgSetSGMIIConfigPLL (0x00000041);
CSL_BootCfgSetSGMIIRxConfig (0, 0x00700621);
CSL_BootCfgSetSGMIITxConfig (0, 0x000108A1);
CSL_BootCfgSetSGMIIRxConfig (1, 0x00700621);
CSL_BootCfgSetSGMIITxConfig (1, 0x000108A1);
/* Re-lock the chip configuration registers to prevent unintentional writes */
CSL_BootCfgLockKicker();
}
/* SGMII SERDES Configuration complete. Return. */
return 0;
}
/** ============================================================================
* @n@b Init_Cpsw
*
* @b Description
* @n This API sets up the entire ethernet subsystem and all its associated
* components.
*
* @param[in]
* @n None
*
* @return
* @n None
* =============================================================================
*/
Int32 Init_Cpsw (Void)
{
Uint32 macPortNum, mtu = 1518;
Uint8 macSrcAddress [2][6] = {{0x10, 0x11, 0x12, 0x13, 0x14, 0x15},
{0x20, 0x21, 0x22, 0x23, 0x24, 0x25}}; //Setup the MAC per physical port
Uint8 macAddress0 [6] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}; /* MAC address for (CPPI) Port 0 */
Uint8 macAddress1 [6] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15}; /* MAC address for (EMAC1) Port 1 */
Uint8 macAddress2 [6] = {0x2C, 0x44, 0xFD, 0x18, 0xF8, 0xC3}; /* MAC address for (EMAC2) Port 2 */ // 0x20, 0x21, 0x22, 0x23, 0x24, 0x25
/* Initialize the SERDES modules */
Init_SGMII_SERDES();
/* Initialize the SGMII/Sliver submodules for the
* two corresponding MAC ports.
*/
for (macPortNum = 0; macPortNum < NUM_MAC_PORTS; macPortNum++)
{
if (Init_SGMII (macPortNum))
return -1;
Init_MAC (macPortNum, &macSrcAddress[macPortNum][0], mtu);
}
/* Setup the Phys by initializing the MDIO */
Init_MDIO ();
/* Setup the Ethernet switch finally. */
Init_Switch (mtu);
if(cpswLpbkMode == CPSW_LOOPBACK_NONE)
Switch_update_addr(0, macAddress0, 0);
else
Switch_update_addr(0, macAddress1, 0);
Switch_update_addr(1, macAddress1, 0);
Switch_update_addr(2, macAddress2, 0);
/* CPSW subsystem setup done. Return success */
return 0;
}
Here the ethernet port for the RJ-plug should be done right and I changed the entrie in macAddress2 to fit my PC-NIC.
Nothing helped so far.
Thank your for your help.
Patrick