EtherZBlockCommands
Edit this on GitLab
EtherZBlockCommands
Explanation
About the Sample Application Code
This C program demonstrates how to interact with North Atlantic Industries (NAI) embedded function modules using various functions for Ethernet Z-Block commands. Below is a detailed explanation of the provided sample code.
Included Header Files
The program starts by including various standard C library headers and NAI-specific headers:
- Standard C Library Headers:
- stdio.h
, stdlib.h
, string.h
, time.h
, ctype.h
- NAI Sample Program Headers:
- naiapp_boardaccess_menu.h
, naiapp_boardaccess_query.h
, naiapp_boardaccess_access.h
, naiapp_boardaccess_display.h
, naiapp_boardaccess_utils.h
- NAI Board-Specific Headers:
- nai.h
, naibrd.h
, naibrd_ether.h
, nai_ether_adv.h
, naibrd_gen5.h
Constants and Data Structures
-
CONFIG_FILE: The path to the default configuration file for Ethernet Z-Block.
-
Function Prototypes: Prototypes for internal program functions that handle different Z-Block operations.
-
Enum
eth_zblock_commands
: Enumerates commands related to Ethernet Z-Block: Set, Get, Clear, Read, Write. -
Command Table (
ETH_ZBlockcmdMenuCmds
): Holds command names, descriptions, and associated function pointers.
Memory Allocation and Definitions
-
MB_SCRATCHPAD_START_ADDRESS: Specifies the start address of the motherboard scratchpad area.
-
DEF_REGISTER_SIZE: Defines the size of a 32-bit register.
-
Global Variables:
-
g_bGen4ZBlockCommands
: A flag to determine the support for Generation 4 Ethernet commands. -
g_zblockRegCnt
: An array to keep track of the register count for each Ethernet block. -
g_writeDataCnt
: A global counter for the data written to the Z-Block registers.
Main Function
The main entry point depends on the defined platform:
- For VxWorks (VXWORKS), the entry function is EtherZBlockCommands
.
- For other platforms, such as Windows, the entry function is main
.
Main Function Workflow:
-
Initialization: Runs the board menu using
naiapp_RunBoardMenu
with the CONFIG_FILE. -
User Interaction Loop: Continuously queries the user for card index and executes Z-Block commands until the user opts to quit.
-
Card Access Closure: Closes all open cards before exiting.
Functional Description
Run_EtherZBlockCommands
Runs the Ethernet Z-Block commands for a specified card index: - Checks if the board supports Generation 4 Ethernet commands. - Displays a command menu and waits for user input to execute corresponding functions.
QueryEthZBlockID
Queries the user for the Z-Block ID and validates the input.
InitZBlockRegisters
Initializes the list of register addresses and their flags for a specified Z-Block: - If Gen4 commands are supported, assigns address values and flags. - For unsupported generations, it displays an error message.
InitZBlockRegistersData
Initializes the data to write to the list of register addresses for the Write Z-Block command.
Command-Specific Functions
-
SetEthZBlockConfig
-
Queries Z-Block ID and initializes register addresses.
-
Calls
naibrd_Ether_SetZBlock
to set the Z-Block configuration.
-
-
GetEthZBlockConfig
-
Queries Z-Block ID and retrieves register addresses.
-
Calls
naibrd_Ether_GetZBlock
to get the Z-Block configuration.
-
-
ClearEthZBlockConfig
-
Queries Z-Block ID and clears register addresses.
-
Calls
naibrd_Ether_ClearZBlock
for the clear command.
-
-
ReadEthZBlockRegisters
-
Queries Z-Block ID and reads register data.
-
Calls
naibrd_Ether_ReadZBlock
to read the register values.
-
-
WriteEthZBlockRegisters
-
Queries Z-Block ID, initializes data, and writes to registers.
-
Calls
naibrd_Ether_WriteZBlock
to write data to the registers.
-
This sample code effectively demonstrates configuring and interacting with NAI Ethernet Z-Block commands, enabling the user to set, get, clear, read, and write Ethernet Z-Block configurations on a specified card.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
/* Common Sample Program include files */
#include "include/naiapp_boardaccess_menu.h"
#include "include/naiapp_boardaccess_query.h"
#include "include/naiapp_boardaccess_access.h"
#include "include/naiapp_boardaccess_display.h"
#include "include/naiapp_boardaccess_utils.h"
/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
#include "naibrd_ether.h"
#include "advanced/nai_ether_adv.h"
#include "boards/naibrd_gen5.h"
static const int8_t *CONFIG_FILE = (const int8_t *)"default_Ether_ZBlock.txt";
/* Function prototypes */
static bool_t Run_EtherZBlockCommands(int32_t cardIndex);
static bool_t QueryEthZBlockID(int32_t* p_outblockid);
static void InitZBlockRegisters(uint32_t* p_outcount, uint16_t addrflag[], uint32_t address[]);
static void InitZBlockRegistersData(uint32_t count, uint32_t data[]);
static nai_status_t SetEthZBlockConfig(int32_t paramCount, int32_t* p_params);
static nai_status_t GetEthZBlockConfig(int32_t paramCount, int32_t* p_params);
static nai_status_t ClearEthZBlockConfig(int32_t paramCount, int32_t* p_params);
static nai_status_t ReadEthZBlockRegisters(int32_t paramCount, int32_t* p_params);
static nai_status_t WriteEthZBlockRegisters(int32_t paramCount, int32_t* p_params);
/****** Command Table *******/
enum eth_zblock_commands
{
ETH_ZBLOCK_CMD_SET,
ETH_ZBLOCK_CMD_GET,
ETH_ZBLOCK_CMD_CLEAR,
ETH_ZBLOCK_CMD_READ,
ETH_ZBLOCK_CMD_WRITE,
ETH_ZBLOCK_CMD_COUNT
};
/****** Command Tables *******/
naiapp_cmdtbl_params_t ETH_ZBlockcmdMenuCmds[] = {
{"Set", "Set Z-Block Configuration", ETH_ZBLOCK_CMD_SET, SetEthZBlockConfig},
{"Get", "Get Z-Block Configuration", ETH_ZBLOCK_CMD_GET, GetEthZBlockConfig},
{"Clear", "Clear Z-Block Configuration", ETH_ZBLOCK_CMD_CLEAR, ClearEthZBlockConfig},
{"Read", "Read Z-Block Registers", ETH_ZBLOCK_CMD_READ, ReadEthZBlockRegisters},
{"Write", "Write to Z-Block Registers", ETH_ZBLOCK_CMD_WRITE, WriteEthZBlockRegisters},
};
/* Gen 5 Motherboard Scratchpad Area (Note: for Reference only Scratchpad area may vary on different Gen 5 boards */
#define MB_SCRATCHPAD_START_ADDRESS 0x00003800 /* Motherboard Scratchpad Area: 0x00003800 - 0x00003BFF */
#define DEF_REGISTER_SIZE 4 /* Number of bytes for 32-bit Register */
static bool_t g_bGen4ZBlockCommands = FALSE;
/* ZBlock Register Count */
static uint32_t g_zblockRegCnt[MAX_ETHER_BLOCK_ID] =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
static int32_t g_writeDataCnt = 0; /* Global counter to change data written to z-block */
/**************************************************************************************************************/
/**
<summary>
The purpose of the EtherZBlockCommands is to illustrate the methods to call in the naibrd library to handle the
Ethernet Z-Block Commands.
The following system configuration routines from the nai_sys_cfg.c file are called to assist with the configuration
setup for this program prior to calling the naibrd Ethernet routines.
- ConfigDevice
- DisplayDeviceCfg
- GetBoardSNModCfg
</summary>
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t EtherZBlockCommands(void)
#else
int32_t main(void)
#endif
{
bool_t stop = FALSE;
int32_t cardIndex;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
{
while (stop != TRUE)
{
/* Query the user for the card index */
stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
if (stop != TRUE)
{
Run_EtherZBlockCommands(cardIndex);
}
printf("\nType Q to quit or Enter key to restart application:\n");
stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
}
}
printf("\nType the Enter key to exit the program: ");
naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
naiapp_access_CloseAllOpenCards();
return 0;
}
/**************************************************************************************************************/
/**
<summary>
This function runs the Ethernet Z-Block Commands program.
</summary>
*/
/**************************************************************************************************************/
static bool_t Run_EtherZBlockCommands(int32_t cardIndex)
{
bool_t bQuit = FALSE;
bool_t bContinue = TRUE;
bool_t bCmdFound = FALSE;
int32_t cmd;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
naiapp_AppParameters_t zblock_params;
p_naiapp_AppParameters_t p_eth_zblock_params = &zblock_params;
p_eth_zblock_params->cardIndex = cardIndex;
/* Determine if the board selected supports the Generation 4 Ethernet Commands */
g_bGen4ZBlockCommands = SupportsGen4Ether(cardIndex);
while (bContinue)
{
naiapp_utils_LoadParamMenuCommands(ETH_ZBLOCK_CMD_COUNT, ETH_ZBlockcmdMenuCmds); /* reload main menu */
naiapp_display_ParamMenuCommands((int8_t *)"Ethernet Z-Block Command Menu");
printf("\nType Ethernet Z-Block command or %c to quit : ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt > 0)
{
bCmdFound = naiapp_utils_GetParamMenuCmdNum(inputResponseCnt, inputBuffer, &cmd);
if (bCmdFound)
{
switch (cmd)
{
case ETH_ZBLOCK_CMD_SET:
case ETH_ZBLOCK_CMD_GET:
case ETH_ZBLOCK_CMD_CLEAR:
case ETH_ZBLOCK_CMD_READ:
case ETH_ZBLOCK_CMD_WRITE:
ETH_ZBlockcmdMenuCmds[cmd].func(APP_PARAM_COUNT, (int32_t*)p_eth_zblock_params);
break;
default:
printf("Invalid command entered\n");
break;
}
}
else
printf("Invalid command entered\n");
}
}
else
bContinue = FALSE;
}
return bQuit;
}
/**************************************************************************************************************/
/**
<summary>
This function queries the user to enter the block id to apply the Set, Get, Clear, Read and Write Block
commands.
</summary>
*/
/**************************************************************************************************************/
static bool_t QueryEthZBlockID(int32_t* p_outblockid)
{
bool_t bQuit = FALSE;
int32_t valueread = 0;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
printf("Enter the Z-Block ID: (default: 1) > ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt == 0)
valueread = 1;
else
{
valueread = atol((const char *)inputBuffer);
if ((valueread < 0) || (valueread > MAX_ETHER_BLOCK_ID))
{
printf("Error: Z-BlockID is invalid\n");
bQuit = TRUE;
}
}
*p_outblockid = valueread;
}
return bQuit;
}
/**************************************************************************************************************/
/**
<summary>
This function sets up the list of register addresses to included for the Set Z-Block command.
</summary>
*/
/**************************************************************************************************************/
static void InitZBlockRegisters(uint32_t* p_outcount, uint16_t addrflag[], uint32_t address[])
{
int32_t index = 0;
int32_t flgindex = 0;
int32_t boardindex;
uint16_t inf;
uint32_t baseaddr;
if (g_bGen4ZBlockCommands)
{
/* Note: the address specified below is for the Motherboard Scratchpad Area.
For addrflag settings: 0 = Onboard, 1 = Offboard.
*/
for (boardindex = 0; boardindex < naiapp_GetBoardCnt(); boardindex++)
{
if (boardindex == 0)
{
inf = ETHER_GEN4_ONBOARD; /* Onboard */
baseaddr = 0;
}
else
{
inf = ETHER_GEN4_OFFBOARD; /* Offboard */
if (g_NAISysCfgAccess[boardindex].comm == NAIBRD_COMM_VME)
baseaddr = g_NAISysCfgAccess[boardindex].vmeCfg.boardAddress;
else if (g_NAISysCfgAccess[boardindex].comm == NAIBRD_COMM_PCI)
baseaddr = g_NAISysCfgAccess[boardindex].pciCfg.boardAddress;
else
baseaddr = 0;
}
/* Motherboard Common area */
address[index++] = baseaddr + MB_SCRATCHPAD_START_ADDRESS + 0x0000; /* 1 */
addrflag[flgindex++] = inf;
address[index++] = baseaddr + MB_SCRATCHPAD_START_ADDRESS + 0x0010; /* 2 */
addrflag[flgindex++] = inf;
address[index++] = baseaddr + MB_SCRATCHPAD_START_ADDRESS + 0x0050; /* 3 */
addrflag[flgindex++] = inf;
address[index++] = baseaddr + MB_SCRATCHPAD_START_ADDRESS + 0x0100; /* 4 */
addrflag[flgindex++] = inf;
address[index++] = baseaddr + MB_SCRATCHPAD_START_ADDRESS + 0x0110; /* 5 */
addrflag[flgindex++] = inf;
}
*p_outcount = index;
}
else
{
printf("Ethernet Z-Block Command Support Prior to Generation 4 Ethernet commands currently not supported\n");
}
}
/**************************************************************************************************************/
/**
<summary>
This function sets up the data to write to list of register addresses for the Write Z-Block command.
</summary>
*/
/**************************************************************************************************************/
static void InitZBlockRegistersData(uint32_t count, uint32_t data[])
{
uint32_t index = 0;
for (index = 0; index < count; index++)
{
if (g_bGen4ZBlockCommands)
{
data[index] = g_writeDataCnt++;
}
}
}
/**************************************************************************************************************/
/**
<summary>
This function calls InitZBlockRegisters() to sets up the list of register addresses for the Set Z-Block command
and calls naibrd_Ether_SetZBlock() to send the SetZBlock command to the board for the Block ID specified.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t SetEthZBlockConfig(int32_t paramCount, int32_t* p_params)
{
bool_t bQuit = FALSE;
nai_status_t status;
uint16_t addrflag[MAX_ETHER_BLOCK_REG_CNT];
uint32_t address[MAX_ETHER_BLOCK_REG_CNT];
p_naiapp_AppParameters_t p_ether_params = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = p_ether_params->cardIndex;
int32_t blockid = 0;
int32_t regwidth = DEF_REGISTER_SIZE;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
bQuit = QueryEthZBlockID(&blockid);
if (!bQuit)
{
InitZBlockRegisters(&g_zblockRegCnt[blockid-1], &addrflag[0], &address[0]);
status = check_status(naibrd_Ether_SetZBlock(cardIndex, (uint16_t)blockid, (uint32_t)regwidth, g_zblockRegCnt[blockid-1], addrflag, address));
if (status == NAI_SUCCESS)
{
printf("Block ID = %d configured.\n", blockid);
}
}
return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}
/**************************************************************************************************************/
/**
<summary>
This function calls naibrd_Ether_GetZBlock() to send the GetZBlock command to the board to retrieve the list of
register addresses specified for the Block ID specified.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t GetEthZBlockConfig(int32_t paramCount, int32_t* p_params)
{
bool_t bQuit = FALSE;
nai_status_t status;
uint32_t arraysize = MAX_ETHER_BLOCK_REG_CNT;
uint16_t addrflag[MAX_ETHER_BLOCK_REG_CNT];
uint32_t address[MAX_ETHER_BLOCK_REG_CNT];
int32_t i;
p_naiapp_AppParameters_t p_ether_params = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = p_ether_params->cardIndex;
int32_t blockid = 0;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
bQuit = QueryEthZBlockID(&blockid);
if (!bQuit)
{
status = check_status(naibrd_Ether_GetZBlock(cardIndex, (uint16_t)blockid, arraysize, addrflag, address, &g_zblockRegCnt[blockid-1]));
if (status == NAI_SUCCESS)
{
if (g_zblockRegCnt[blockid-1] > 0)
{
printf("\n\nBlock ID = %d - %d Registers with Addresses:\n", blockid, g_zblockRegCnt[blockid-1]);
for (i = 0; i < (int32_t)g_zblockRegCnt[blockid-1]; i++)
{
printf("%3d: 0x%08X", i+1, address[i]);
if (addrflag[i] == 0)
printf(" Onboard\n");
else
printf(" Offboard\n");
}
}
else
printf("\n\nNo Registers configured for Block ID = %d\n", blockid);
}
}
return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}
/**************************************************************************************************************/
/**
<summary>
This function calls naibrd_Ether_ClearZBlock() to send the ClearZBlock command to the board to remove the list of
register addresses specified for the Block ID specified.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t ClearEthZBlockConfig(int32_t paramCount, int32_t* p_params)
{
bool_t bQuit = FALSE;
nai_status_t status;
p_naiapp_AppParameters_t p_ether_params = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = p_ether_params->cardIndex;
int32_t blockid = 0;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
bQuit = QueryEthZBlockID(&blockid);
if (!bQuit)
{
status = check_status(naibrd_Ether_ClearZBlock(cardIndex, (uint16_t)blockid));
if (status == NAI_SUCCESS)
{
printf("Block ID = %d cleared\n", blockid);
}
}
return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}
/**************************************************************************************************************/
/**
<summary>
This function calls naibrd_Ether_ReadZBlock() to send the ReadZBlock command to the board to retrieve the data
for the list of register addresses specified for the Block ID specified.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t ReadEthZBlockRegisters(int32_t paramCount, int32_t* p_params)
{
bool_t bQuit = FALSE;
nai_status_t status;
uint32_t arraysize = MAX_ETHER_BLOCK_REG_CNT;
uint32_t data[MAX_ETHER_BLOCK_REG_CNT];
uint32_t datacount = 0;
int32_t i;
p_naiapp_AppParameters_t p_ether_params = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = p_ether_params->cardIndex;
int32_t blockid = 0;
int32_t regwidth = DEF_REGISTER_SIZE;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
bQuit = QueryEthZBlockID(&blockid);
if (!bQuit)
{
status = check_status(naibrd_Ether_ReadZBlock(cardIndex, (uint16_t)blockid, (uint32_t)regwidth, arraysize, data, &datacount));
if (status == NAI_SUCCESS)
{
if (datacount > 0)
{
printf("\n\nBlock ID = %d - %d Register Values:\n", blockid, datacount);
for (i = 0; i < (int32_t)datacount; i++)
{
printf("%3d: 0x%08X\n", i+1, data[i]);
}
}
else
printf("\n\nNo Registers read for Block ID = %d\n", blockid);
}
}
return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}
/**************************************************************************************************************/
/**
<summary>
This function calls InitZBlockRegistersData() to set up the data to write to the list of registers and calls
naibrd_Ether_WriteZBlock() to send the WriteZBlock command to the board to write the data to the list of register
addresses specified for the Block ID specified.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t WriteEthZBlockRegisters(int32_t paramCount, int32_t* p_params)
{
bool_t bQuit = FALSE;
nai_status_t status;
uint32_t data[MAX_ETHER_BLOCK_REG_CNT];
p_naiapp_AppParameters_t p_ether_params = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = p_ether_params->cardIndex;
int32_t blockid = 0;
int32_t regwidth = DEF_REGISTER_SIZE;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
bQuit = QueryEthZBlockID(&blockid);
if (!bQuit)
{
InitZBlockRegistersData(g_zblockRegCnt[blockid-1], &data[0]);
status = check_status(naibrd_Ether_WriteZBlock(cardIndex, (uint16_t)blockid, (uint32_t)regwidth, g_zblockRegCnt[blockid-1], data));
if (status == NAI_SUCCESS)
{
printf("Block ID = %d Data written.\n", blockid);
}
}
return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}