Merge branch 'master' of http://www.denx.de/git/u-boot
This commit is contained in:
commit
72ed528a94
74
CHANGELOG
74
CHANGELOG
@ -2,6 +2,80 @@
|
||||
Changes since U-Boot 1.1.4:
|
||||
======================================================================
|
||||
|
||||
* Minor cleanup for PCS440EP board
|
||||
|
||||
* Update PCS440EP port to fit into one flash device (incl. environment)
|
||||
Patch by Stefan Roese, 06 Jun 2006
|
||||
|
||||
* Add support for PCS440EP board
|
||||
Patch by Stefan Roese, 02 Jun 2006
|
||||
|
||||
* Fix examples/Makefile; some build targets were lost
|
||||
|
||||
* Fix watchdog handling in CFI flash driver
|
||||
Just use udelay() when waiting for status changes which will
|
||||
implicitely trigger the watchdog.
|
||||
|
||||
* Fix PCI to memory window size problems on PM82x boards
|
||||
We use the "automatic" mode that was used for the MPC8266ADS and
|
||||
MPC8272 boards. Eventually this should be used on all boards?]
|
||||
Patch by Wolfgang Grandegger, 17 Jan 2006
|
||||
|
||||
* Correct GPIO setup (UART1/IRQ's) on yosemite & yellowstone
|
||||
Patch by Stefan Roese, 29 May 2006
|
||||
|
||||
* Update Intel IXP4xx support
|
||||
- Add IXP4xx NPE ethernet MAC support
|
||||
- Add support for Intel IXDPG425 board
|
||||
- Add support for Prodrive PDNB3 board
|
||||
- Add IRQ support
|
||||
Patch by Stefan Roese, 23 May 2006
|
||||
|
||||
* Fix problem in PVR detection for 440GR
|
||||
Patch by Stefan Roese, 18 May 2006
|
||||
|
||||
* Fix gcc 3.4.x AFLAGS setting for m68k platform.
|
||||
|
||||
* Enable autoboot for M5271EVB board.
|
||||
|
||||
* Changed default ramdisk addr in yosemite/yellowstone ports
|
||||
Patch by Stefan Roese, 15 May 2006
|
||||
|
||||
* Fix PCMCIA support on virtlab2
|
||||
|
||||
* Add support for VirtLab2 board
|
||||
(needed because of differences in the PCMCIA hardware).
|
||||
|
||||
* Minor cleanup.
|
||||
|
||||
* Update yosemite configuration to enable flash write buffer support
|
||||
Patch by Stefan Roese, 10 May 2006
|
||||
|
||||
* Fix compile warnings in common/xyzModem.c
|
||||
Patch by Stefan Roese, 10 May 2006
|
||||
|
||||
* Add support for AMCC 440EP Rev C and 440GR Rev B
|
||||
Patch by John Otken, 08 May 2006
|
||||
|
||||
* OMAP 5912/OSK: update EMIFS CS1 timings:
|
||||
Problems have been seen in the linux kernel's smc91x network driver
|
||||
due to improper bus timings. The latest 2.6 OMAP kernels currently
|
||||
have a workaround, but this fix belongs in u-boot.
|
||||
Patch by Kevin Hilman, 13 Oct 2005
|
||||
|
||||
* Fix REG_MPU_LOAD_TIMER definition in multiple OMAP ports
|
||||
Patch by Hiroki Kaminaga, 11 Mar 2006
|
||||
|
||||
* Update omap5912osk board support
|
||||
- Fix OMAP support that omap5912osk compiles in current source tree
|
||||
- Update with code from "http://omap.spectrumdigital.com/osk5912"
|
||||
to fix problems with DDR initialization
|
||||
- Fix timer setup
|
||||
- Use CFI flash driver and support complete 32MB of onboard flash
|
||||
- Add "print_cpuinfo()" and "checkboard()" functions to display
|
||||
CPU (with frequency) and Board infos
|
||||
Patch by Stefan Roese, 10 May 2006
|
||||
|
||||
* Fix watchdog issues for ColdFire boards.
|
||||
|
||||
* Add M5271EVB board support.
|
||||
|
@ -283,6 +283,7 @@ Stefan Roese <sr@denx.de>
|
||||
ebony PPC440GP
|
||||
ocotea PPC440GX
|
||||
p3p440 PPC440GP
|
||||
pcs440ep PPC440EP
|
||||
sycamore PPC405GPr
|
||||
walnut PPC405GP
|
||||
yellowstone PPC440GR
|
||||
@ -434,6 +435,11 @@ Dave Peverley <dpeverley@mpc-data.co.uk>
|
||||
|
||||
omap730p2 ARM926EJS
|
||||
|
||||
Stefan Roese <sr@denx.de>
|
||||
|
||||
ixdpg425 xscale
|
||||
pdnb3 xscale
|
||||
|
||||
Robert Schwebel <r.schwebel@pengutronix.de>
|
||||
|
||||
csb226 xscale
|
||||
|
12
MAKEALL
12
MAKEALL
@ -71,11 +71,11 @@ LIST_4xx=" \
|
||||
HH405 HUB405 JSE KAREF \
|
||||
luan METROBOX MIP405 MIP405T \
|
||||
ML2 ml300 ocotea OCRTC \
|
||||
ORSG p3p440 PCI405 PIP405 \
|
||||
PLU405 PMC405 PPChameleonEVB sbc405 \
|
||||
VOH405 VOM405 W7OLMC W7OLMG \
|
||||
walnut WUH405 XPEDITE1K yellowstone \
|
||||
yosemite \
|
||||
ORSG p3p440 PCI405 pcs440ep \
|
||||
PIP405 PLU405 PMC405 PPChameleonEVB \
|
||||
sbc405 VOH405 VOM405 W7OLMC \
|
||||
W7OLMG walnut WUH405 XPEDITE1K \
|
||||
yellowstone yosemite \
|
||||
"
|
||||
|
||||
#########################################################################
|
||||
@ -209,7 +209,7 @@ LIST_pxa=" \
|
||||
zylonite \
|
||||
"
|
||||
|
||||
LIST_ixp="ixdp425"
|
||||
LIST_ixp="ixdp425 ixdpg425 pdnb3"
|
||||
|
||||
|
||||
LIST_arm=" \
|
||||
|
12
Makefile
12
Makefile
@ -759,7 +759,8 @@ TQM850M_config \
|
||||
TQM855M_config \
|
||||
TQM860M_config \
|
||||
TQM862M_config \
|
||||
TQM866M_config: unconfig
|
||||
TQM866M_config \
|
||||
virtlab2_config: unconfig
|
||||
@ >include/config.h
|
||||
@[ -z "$(findstring _LCD,$@)" ] || \
|
||||
{ echo "#define CONFIG_LCD" >>include/config.h ; \
|
||||
@ -921,6 +922,9 @@ p3p440_config: unconfig
|
||||
PCI405_config: unconfig
|
||||
@./mkconfig $(@:_config=) ppc ppc4xx pci405 esd
|
||||
|
||||
pcs440ep_config: unconfig
|
||||
@./mkconfig $(@:_config=) ppc ppc4xx pcs440ep
|
||||
|
||||
PIP405_config: unconfig
|
||||
@./mkconfig $(@:_config=) ppc ppc4xx pip405 mpl
|
||||
|
||||
@ -1718,12 +1722,18 @@ innokom_config : unconfig
|
||||
ixdp425_config : unconfig
|
||||
@./mkconfig $(@:_config=) arm ixp ixdp425
|
||||
|
||||
ixdpg425_config : unconfig
|
||||
@./mkconfig $(@:_config=) arm ixp ixdp425
|
||||
|
||||
lubbock_config : unconfig
|
||||
@./mkconfig $(@:_config=) arm pxa lubbock
|
||||
|
||||
logodl_config : unconfig
|
||||
@./mkconfig $(@:_config=) arm pxa logodl
|
||||
|
||||
pdnb3_config : unconfig
|
||||
@./mkconfig $(@:_config=) arm ixp pdnb3 prodrive
|
||||
|
||||
pxa255_idp_config: unconfig
|
||||
@./mkconfig $(@:_config=) arm pxa pxa255_idp
|
||||
|
||||
|
@ -79,8 +79,8 @@ int board_early_init_f(void)
|
||||
out32(GPIO1_ISR2L, in32(GPIO1_ISR2L) | 0x00010000);
|
||||
|
||||
/* external interrupts IRQ0...3 */
|
||||
out32(GPIO1_TCR, in32(GPIO1_TCR) & ~0x0f000000);
|
||||
out32(GPIO1_TSRL, in32(GPIO1_TSRL) & ~0x00005500);
|
||||
out32(GPIO1_TCR, in32(GPIO1_TCR) & ~0x00f00000);
|
||||
out32(GPIO1_TSRL, in32(GPIO1_TSRL) & ~0x0000ff00);
|
||||
out32(GPIO1_ISR1L, in32(GPIO1_ISR1L) | 0x00005500);
|
||||
|
||||
#if 0 /* test-only */
|
||||
|
@ -79,8 +79,8 @@ int board_early_init_f(void)
|
||||
out32(GPIO1_ISR2L, in32(GPIO1_ISR2L) | 0x00010000);
|
||||
|
||||
/* external interrupts IRQ0...3 */
|
||||
out32(GPIO1_TCR, in32(GPIO1_TCR) & ~0x0f000000);
|
||||
out32(GPIO1_TSRL, in32(GPIO1_TSRL) & ~0x00005500);
|
||||
out32(GPIO1_TCR, in32(GPIO1_TCR) & ~0x00f00000);
|
||||
out32(GPIO1_TSRL, in32(GPIO1_TSRL) & ~0x0000ff00);
|
||||
out32(GPIO1_ISR1L, in32(GPIO1_ISR1L) | 0x00005500);
|
||||
|
||||
/*setup USB 2.0 */
|
||||
|
@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk
|
||||
|
||||
LIB = lib$(BOARD).a
|
||||
|
||||
OBJS := ixdp425.o flash.o
|
||||
OBJS := ixdp425.o
|
||||
|
||||
$(LIB): $(OBJS) $(SOBJS)
|
||||
$(AR) crv $@ $^
|
||||
|
@ -1,2 +1,4 @@
|
||||
#TEXT_BASE = 0x00100000
|
||||
TEXT_BASE = 0x00f80000
|
||||
|
||||
# include NPE ethernet driver
|
||||
BOARDLIBS = cpu/ixp/npe/libnpe.a
|
||||
|
@ -1,4 +1,7 @@
|
||||
/*
|
||||
* (C) Copyright 2006
|
||||
* Stefan Roese, DENX Software Engineering, sr@denx.de.
|
||||
*
|
||||
* (C) Copyright 2002
|
||||
* Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
|
||||
*
|
||||
@ -25,24 +28,21 @@
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <asm/arch/ixp425.h>
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <malloc.h>
|
||||
#include <asm/arch/ixp425.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/*
|
||||
* Miscelaneous platform dependent initialisations
|
||||
*/
|
||||
|
||||
/**********************************************************/
|
||||
|
||||
int board_post_init (void)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**********************************************************/
|
||||
|
||||
int board_init (void)
|
||||
{
|
||||
/* arch number of IXDP */
|
||||
@ -51,10 +51,58 @@ int board_init (void)
|
||||
/* adress of boot parameters */
|
||||
gd->bd->bi_boot_params = 0x00000100;
|
||||
|
||||
#ifdef CONFIG_IXDPG425
|
||||
/* arch number of IXDP */
|
||||
gd->bd->bi_arch_number = MACH_TYPE_IXDPG425;
|
||||
|
||||
/*
|
||||
* Get realtek RTL8305 switch and SLIC out of reset
|
||||
*/
|
||||
GPIO_OUTPUT_SET(CFG_GPIO_SWITCH_RESET_N);
|
||||
GPIO_OUTPUT_ENABLE(CFG_GPIO_SWITCH_RESET_N);
|
||||
GPIO_OUTPUT_SET(CFG_GPIO_SLIC_RESET_N);
|
||||
GPIO_OUTPUT_ENABLE(CFG_GPIO_SLIC_RESET_N);
|
||||
|
||||
/*
|
||||
* Setup GPIO's for PCI INTA & INTB
|
||||
*/
|
||||
GPIO_OUTPUT_DISABLE(CFG_GPIO_PCI_INTA_N);
|
||||
GPIO_INT_ACT_LOW_SET(CFG_GPIO_PCI_INTA_N);
|
||||
GPIO_OUTPUT_DISABLE(CFG_GPIO_PCI_INTB_N);
|
||||
GPIO_INT_ACT_LOW_SET(CFG_GPIO_PCI_INTB_N);
|
||||
|
||||
/*
|
||||
* Setup GPIO's for 33MHz clock output
|
||||
*/
|
||||
*IXP425_GPIO_GPCLKR = 0x01FF01FF;
|
||||
GPIO_OUTPUT_ENABLE(CFG_GPIO_PCI_CLK);
|
||||
GPIO_OUTPUT_ENABLE(CFG_GPIO_EXTBUS_CLK);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**********************************************************/
|
||||
/*
|
||||
* Check Board Identity
|
||||
*/
|
||||
int checkboard(void)
|
||||
{
|
||||
char *s = getenv("serial#");
|
||||
|
||||
#ifdef CONFIG_IXDPG425
|
||||
puts("Board: IXDPG425 - Intel Network Gateway Reference Platform");
|
||||
#else
|
||||
puts("Board: IXDP425 - Intel Development Platform");
|
||||
#endif
|
||||
|
||||
if (s != NULL) {
|
||||
puts(", serial# ");
|
||||
puts(s);
|
||||
}
|
||||
putc('\n');
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int dram_init (void)
|
||||
{
|
||||
@ -64,8 +112,7 @@ int dram_init (void)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**********************************************************/
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_PCI) || defined(CONFIG_PCI)
|
||||
extern struct pci_controller hose;
|
||||
extern void pci_ixp_init(struct pci_controller * hose);
|
||||
|
||||
@ -75,3 +122,4 @@ void pci_init_board(void)
|
||||
|
||||
pci_ixp_init(&hose);
|
||||
}
|
||||
#endif
|
||||
|
@ -53,10 +53,9 @@ long int initdram (int board_type) {
|
||||
* Check to see if the SDRAM has already been initialized
|
||||
* by a run control tool
|
||||
*/
|
||||
if (!(mbar_readLong(MCF_SDRAMC_DACR0) & MCF_SDRAMC_DACRn_RE))
|
||||
{
|
||||
if (!(mbar_readLong(MCF_SDRAMC_DACR0) & MCF_SDRAMC_DACRn_RE)) {
|
||||
/* Initialize DRAM Control Register: DCR */
|
||||
mbar_writeShort(MCF_SDRAMC_DCR,
|
||||
mbar_writeShort(MCF_SDRAMC_DCR,
|
||||
MCF_SDRAMC_DCR_RTIM(0x01)
|
||||
| MCF_SDRAMC_DCR_RC(0x30));
|
||||
|
||||
@ -74,7 +73,7 @@ long int initdram (int board_type) {
|
||||
| MCF_SDRAMC_DACRn_PS(0));
|
||||
|
||||
/* Initialize DMR0 */
|
||||
mbar_writeLong(MCF_SDRAMC_DMR0,
|
||||
mbar_writeLong(MCF_SDRAMC_DMR0,
|
||||
MCF_SDRAMC_DMRn_BAM_16M
|
||||
| MCF_SDRAMC_DMRn_V);
|
||||
|
||||
|
@ -382,7 +382,7 @@ REG_WATCHDOG:
|
||||
.word 0xfffec808
|
||||
|
||||
REG_MPU_LOAD_TIMER:
|
||||
.word 0xfffec600
|
||||
.word 0xfffec504
|
||||
REG_MPU_CNTL_TIMER:
|
||||
.word 0xfffec500
|
||||
|
||||
|
@ -41,6 +41,13 @@ _TEXT_BASE:
|
||||
.globl lowlevel_init
|
||||
lowlevel_init:
|
||||
|
||||
/*------------------------------------------------------*
|
||||
* Ensure i-cache is enabled *
|
||||
* To configure TC regs without fetching instruction *
|
||||
*------------------------------------------------------*/
|
||||
mrc p15, 0, r0, c1, c0
|
||||
orr r0, r0, #0x1000
|
||||
mcr p15, 0, r0, c1, c0
|
||||
|
||||
/*------------------------------------------------------*
|
||||
*mask all IRQs by setting all bits in the INTMR default*
|
||||
@ -59,33 +66,34 @@ lowlevel_init:
|
||||
str r1, [r0]
|
||||
|
||||
/*------------------------------------------------------*
|
||||
* Set up ARM CLM registers (IDLECT2) *
|
||||
* Set up ARM CLM registers (IDLECT2) *
|
||||
*------------------------------------------------------*/
|
||||
ldr r0, REG_ARM_IDLECT2
|
||||
ldr r1, VAL_ARM_IDLECT2
|
||||
str r1, [r0]
|
||||
|
||||
/*------------------------------------------------------*
|
||||
* Set up ARM CLM registers (IDLECT3) *
|
||||
* Set up ARM CLM registers (IDLECT3) *
|
||||
*------------------------------------------------------*/
|
||||
ldr r0, REG_ARM_IDLECT3
|
||||
ldr r1, VAL_ARM_IDLECT3
|
||||
str r1, [r0]
|
||||
|
||||
|
||||
mov r1, #0x01 /* PER_EN bit */
|
||||
mov r1, #0x01 /* PER_EN bit */
|
||||
ldr r0, REG_ARM_RSTCT2
|
||||
strh r1, [r0] /* CLKM; Peripheral reset. */
|
||||
strh r1, [r0] /* CLKM; Peripheral reset. */
|
||||
|
||||
/* Set CLKM to Sync-Scalable */
|
||||
/* I supposedly need to enable the dsp clock before switching */
|
||||
mov r1, #0x0000
|
||||
/* Set CLKM to Sync-Scalable */
|
||||
mov r1, #0x1000
|
||||
ldr r0, REG_ARM_SYSST
|
||||
strh r1, [r0]
|
||||
mov r0, #0x400
|
||||
1:
|
||||
subs r0, r0, #0x1 /* wait for any bubbles to finish */
|
||||
|
||||
mov r2, #0
|
||||
1: cmp r2, #1
|
||||
streqh r1, [r0]
|
||||
add r2, r2, #1
|
||||
cmp r2, #0x100 /* wait for any bubbles to finish */
|
||||
bne 1b
|
||||
|
||||
ldr r1, VAL_ARM_CKCTL
|
||||
ldr r0, REG_ARM_CKCTL
|
||||
strh r1, [r0]
|
||||
@ -107,17 +115,16 @@ lowlevel_init:
|
||||
ldr r1, VAL_DPLL1_CTL
|
||||
ldr r0, REG_DPLL1_CTL
|
||||
strh r1, [r0]
|
||||
ands r1, r1, #0x10 /* Check if PLL is enabled. */
|
||||
beq lock_end /* Do not look for lock if BYPASS selected */
|
||||
ands r1, r1, #0x10 /* Check if PLL is enabled. */
|
||||
beq lock_end /* Do not look for lock if BYPASS selected */
|
||||
2:
|
||||
ldrh r1, [r0]
|
||||
ands r1, r1, #0x01 /* Check the LOCK bit.*/
|
||||
beq 2b /* loop until bit goes hi. */
|
||||
ands r1, r1, #0x01 /* Check the LOCK bit.*/
|
||||
beq 2b /* loop until bit goes hi. */
|
||||
lock_end:
|
||||
|
||||
|
||||
/*------------------------------------------------------*
|
||||
* Turn off the watchdog during init... *
|
||||
* Turn off the watchdog during init... *
|
||||
*------------------------------------------------------*/
|
||||
ldr r0, REG_WATCHDOG
|
||||
ldr r1, WATCHDOG_VAL1
|
||||
@ -143,30 +150,49 @@ watch2Wait:
|
||||
tst r1, #0x10
|
||||
bne watch2Wait
|
||||
|
||||
|
||||
/* Set memory timings corresponding to the new clock speed */
|
||||
ldr r3, VAL_SDRAM_CONFIG_SDF0
|
||||
|
||||
/* Check execution location to determine current execution location
|
||||
* and branch to appropriate initialization code.
|
||||
*/
|
||||
/* Load physical SDRAM base. */
|
||||
mov r0, #0x10000000
|
||||
/* Get current execution location. */
|
||||
mov r1, pc
|
||||
/* Compare. */
|
||||
cmp r1, r0
|
||||
/* Skip over EMIF-fast initialization if running from SDRAM. */
|
||||
bge skip_sdram
|
||||
mov r0, #0x10000000 /* Load physical SDRAM base. */
|
||||
mov r1, pc /* Get current execution location. */
|
||||
cmp r1, r0 /* Compare. */
|
||||
bge skip_sdram /* Skip over EMIF-fast initialization if running from SDRAM. */
|
||||
|
||||
/* identify the device revision, -- TMX or TMP(TMS) */
|
||||
ldr r0, REG_DEVICE_ID
|
||||
ldr r1, [r0]
|
||||
|
||||
ldr r0, VAL_DEVICE_ID_TMP
|
||||
mov r1, r1, lsl #15
|
||||
mov r1, r1, lsr #16
|
||||
cmp r0, r1
|
||||
bne skip_TMP_Patch
|
||||
|
||||
/* Enable TMP/TMS device new features */
|
||||
mov r0, #1
|
||||
ldr r1, REG_TC_EMIFF_DOUBLER
|
||||
str r0, [r1]
|
||||
|
||||
/* Enable new ac parameters */
|
||||
mov r0, #0x0b
|
||||
ldr r1, REG_SDRAM_CONFIG2
|
||||
str r0, [r1]
|
||||
|
||||
ldr r3, VAL_SDRAM_CONFIG_SDF1
|
||||
|
||||
skip_TMP_Patch:
|
||||
|
||||
/*
|
||||
* Delay for SDRAM initialization.
|
||||
*/
|
||||
mov r3, #0x1800 /* value should be checked */
|
||||
mov r0, #0x1800 /* value should be checked */
|
||||
3:
|
||||
subs r3, r3, #0x1 /* Decrement count */
|
||||
subs r0, r0, #0x1 /* Decrement count */
|
||||
bne 3b
|
||||
|
||||
|
||||
/*
|
||||
* Set SDRAM control values. Disable refresh before MRS command.
|
||||
*/
|
||||
@ -178,14 +204,15 @@ watch2Wait:
|
||||
|
||||
/* config register */
|
||||
ldr r0, REG_SDRAM_CONFIG
|
||||
ldr r1, SDRAM_CONFIG_VAL
|
||||
str r1, [r0]
|
||||
str r3, [r0]
|
||||
|
||||
/* manual command register */
|
||||
ldr r0, REG_SDRAM_MANUAL_CMD
|
||||
|
||||
/* issue set cke high */
|
||||
mov r1, #CMD_SDRAM_CKE_SET_HIGH
|
||||
str r1, [r0]
|
||||
|
||||
/* issue nop */
|
||||
mov r1, #CMD_SDRAM_NOP
|
||||
str r1, [r0]
|
||||
@ -228,25 +255,23 @@ waitMDDR1:
|
||||
str r1, [r0]
|
||||
|
||||
/* delay loop */
|
||||
mov r2, #0x0100
|
||||
mov r0, #0x0100
|
||||
waitMDDR2:
|
||||
subs r2, r2, #1
|
||||
subs r0, r0, #1
|
||||
bne waitMDDR2
|
||||
|
||||
/*
|
||||
* Delay for SDRAM initialization.
|
||||
*/
|
||||
mov r3, #0x1800
|
||||
mov r0, #0x1800
|
||||
4:
|
||||
subs r3, r3, #1 /* Decrement count. */
|
||||
subs r0, r0, #1 /* Decrement count. */
|
||||
bne 4b
|
||||
b common_tc
|
||||
|
||||
skip_sdram:
|
||||
|
||||
ldr r0, REG_SDRAM_CONFIG
|
||||
ldr r1, SDRAM_CONFIG_VAL
|
||||
str r1, [r0]
|
||||
str r3, [r0]
|
||||
|
||||
common_tc:
|
||||
/* slow interface */
|
||||
@ -257,10 +282,15 @@ common_tc:
|
||||
ldr r1, VAL_TC_EMIFS_CS1_CONFIG
|
||||
ldr r0, REG_TC_EMIFS_CS1_CONFIG
|
||||
str r1, [r0] /* Chip Select 1 */
|
||||
|
||||
ldr r1, VAL_TC_EMIFS_CS3_CONFIG
|
||||
ldr r0, REG_TC_EMIFS_CS3_CONFIG
|
||||
str r1, [r0] /* Chip Select 3 */
|
||||
|
||||
ldr r1, VAL_TC_EMIFS_DWS
|
||||
ldr r0, REG_TC_EMIFS_DWS
|
||||
str r1, [r0] /* Enable EMIFS.RDY for CS1 (ether) */
|
||||
|
||||
#ifdef CONFIG_H2_OMAP1610
|
||||
/* inserting additional 2 clock cycle hold time for LAN */
|
||||
ldr r0, REG_TC_EMIFS_CS1_ADVANCED
|
||||
@ -282,8 +312,9 @@ common_tc:
|
||||
/* the literal pools origin */
|
||||
.ltorg
|
||||
|
||||
|
||||
REG_TC_EMIFS_CONFIG: /* 32 bits */
|
||||
REG_DEVICE_ID: /* 32 bits */
|
||||
.word 0xfffe2004
|
||||
REG_TC_EMIFS_CONFIG:
|
||||
.word 0xfffecc0c
|
||||
REG_TC_EMIFS_CS0_CONFIG: /* 32 bits */
|
||||
.word 0xfffecc10
|
||||
@ -293,7 +324,8 @@ REG_TC_EMIFS_CS2_CONFIG: /* 32 bits */
|
||||
.word 0xfffecc18
|
||||
REG_TC_EMIFS_CS3_CONFIG: /* 32 bits */
|
||||
.word 0xfffecc1c
|
||||
|
||||
REG_TC_EMIFS_DWS: /* 32 bits */
|
||||
.word 0xfffecc40
|
||||
#ifdef CONFIG_H2_OMAP1610
|
||||
REG_TC_EMIFS_CS1_ADVANCED: /* 32 bits */
|
||||
.word 0xfffecc54
|
||||
@ -302,18 +334,17 @@ REG_TC_EMIFS_CS1_ADVANCED: /* 32 bits */
|
||||
/* MPU clock/reset/power mode control registers */
|
||||
REG_ARM_CKCTL: /* 16 bits */
|
||||
.word 0xfffece00
|
||||
|
||||
REG_ARM_IDLECT3: /* 16 bits */
|
||||
.word 0xfffece24
|
||||
REG_ARM_IDLECT2: /* 16 bits */
|
||||
.word 0xfffece08
|
||||
REG_ARM_IDLECT1: /* 16 bits */
|
||||
.word 0xfffece04
|
||||
|
||||
REG_ARM_RSTCT2: /* 16 bits */
|
||||
.word 0xfffece14
|
||||
REG_ARM_SYSST: /* 16 bits */
|
||||
.word 0xfffece18
|
||||
|
||||
/* DPLL control registers */
|
||||
REG_DPLL1_CTL: /* 16 bits */
|
||||
.word 0xfffecf00
|
||||
@ -335,6 +366,10 @@ WSPRDOG_VAL2:
|
||||
counter @8192 rows, 10 ns, 8 burst */
|
||||
REG_SDRAM_CONFIG:
|
||||
.word 0xfffecc20
|
||||
REG_SDRAM_CONFIG2:
|
||||
.word 0xfffecc3c
|
||||
REG_TC_EMIFF_DOUBLER: /* 32 bits */
|
||||
.word 0xfffecc60
|
||||
|
||||
/* Operation register */
|
||||
REG_SDRAM_OPERATION:
|
||||
@ -356,35 +391,47 @@ REG_SDRAM_EMRS1:
|
||||
REG_DLL_WRT_CONTROL:
|
||||
.word 0xfffecc68
|
||||
DLL_WRT_CONTROL_VAL:
|
||||
.word 0x03f00002
|
||||
.word 0x03f00002 /* Phase of 72deg, write offset +31 */
|
||||
|
||||
/* URD DLL register */
|
||||
REG_DLL_URD_CONTROL:
|
||||
.word 0xfffeccc0
|
||||
DLL_URD_CONTROL_VAL:
|
||||
.word 0x00800002
|
||||
.word 0x00800002 /* Phase of 72deg, read offset +31 */
|
||||
|
||||
/* LRD DLL register */
|
||||
REG_DLL_LRD_CONTROL:
|
||||
.word 0xfffecccc
|
||||
DLL_LRD_CONTROL_VAL:
|
||||
.word 0x00800002 /* read offset +31 */
|
||||
|
||||
REG_WATCHDOG:
|
||||
.word 0xfffec808
|
||||
WATCHDOG_VAL1:
|
||||
.word 0x000000f5
|
||||
WATCHDOG_VAL2:
|
||||
.word 0x000000a0
|
||||
|
||||
REG_MPU_LOAD_TIMER:
|
||||
.word 0xfffec600
|
||||
.word 0xfffec504
|
||||
REG_MPU_CNTL_TIMER:
|
||||
.word 0xfffec500
|
||||
VAL_MPU_LOAD_TIMER:
|
||||
.word 0xffffffff
|
||||
VAL_MPU_CNTL_TIMER:
|
||||
.word 0xffffffa1
|
||||
|
||||
/* 96 MHz Samsung Mobile DDR */
|
||||
SDRAM_CONFIG_VAL:
|
||||
.word 0x001200f4
|
||||
/* Original setting for TMX device */
|
||||
VAL_SDRAM_CONFIG_SDF0:
|
||||
.word 0x0014e6fe
|
||||
|
||||
DLL_LRD_CONTROL_VAL:
|
||||
.word 0x00800002
|
||||
/* NEW_SYS_FREQ mode (valid only TMP/TMS devices) */
|
||||
VAL_SDRAM_CONFIG_SDF1:
|
||||
.word 0x0114e6fe
|
||||
|
||||
VAL_ARM_CKCTL:
|
||||
.word 0x3000
|
||||
.word 0x2000 /* was: 0x3000, now use CLK_REF for timer input */
|
||||
VAL_DPLL1_CTL:
|
||||
.word 0x2830
|
||||
|
||||
@ -392,11 +439,15 @@ VAL_DPLL1_CTL:
|
||||
VAL_TC_EMIFS_CS0_CONFIG:
|
||||
.word 0x002130b0
|
||||
VAL_TC_EMIFS_CS1_CONFIG:
|
||||
.word 0x00001131
|
||||
.word 0x00001133
|
||||
VAL_TC_EMIFS_CS2_CONFIG:
|
||||
.word 0x000055f0
|
||||
VAL_TC_EMIFS_CS3_CONFIG:
|
||||
.word 0x88011131
|
||||
.word 0x88013141
|
||||
VAL_TC_EMIFS_DWS: /* Enable EMIFS.RDY for CS1 access (ether) */
|
||||
.word 0x000000c0
|
||||
VAL_DEVICE_ID_TMP: /* TMP/TMS=0xb65f, TMX=0xb58c */
|
||||
.word 0xb65f
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_H2_OMAP1610
|
||||
@ -407,36 +458,20 @@ VAL_TC_EMIFS_CS1_CONFIG:
|
||||
VAL_TC_EMIFS_CS2_CONFIG:
|
||||
.word 0xf800f22a
|
||||
VAL_TC_EMIFS_CS3_CONFIG:
|
||||
.word 0x88011131
|
||||
.word 0x88013141
|
||||
VAL_TC_EMIFS_CS1_ADVANCED:
|
||||
.word 0x00000022
|
||||
#endif
|
||||
|
||||
VAL_TC_EMIFF_SDRAM_CONFIG:
|
||||
.word 0x010290fc
|
||||
VAL_TC_EMIFF_MRS:
|
||||
.word 0x00000027
|
||||
|
||||
VAL_ARM_IDLECT1:
|
||||
.word 0x00000400
|
||||
|
||||
VAL_ARM_IDLECT2:
|
||||
.word 0x00000886
|
||||
VAL_ARM_IDLECT3:
|
||||
.word 0x00000015
|
||||
|
||||
WATCHDOG_VAL1:
|
||||
.word 0x000000f5
|
||||
WATCHDOG_VAL2:
|
||||
.word 0x000000a0
|
||||
|
||||
VAL_MPU_LOAD_TIMER:
|
||||
.word 0xffffffff
|
||||
VAL_MPU_CNTL_TIMER:
|
||||
.word 0xffffffa1
|
||||
|
||||
/* command values */
|
||||
.equ CMD_SDRAM_NOP, 0x00000000
|
||||
.equ CMD_SDRAM_PRECHARGE, 0x00000001
|
||||
.equ CMD_SDRAM_AUTOREFRESH, 0x00000002
|
||||
.equ CMD_SDRAM_CKE_SET_HIGH, 0x00000007
|
||||
.equ CMD_SDRAM_NOP, 0x00000000
|
||||
.equ CMD_SDRAM_PRECHARGE, 0x00000001
|
||||
.equ CMD_SDRAM_AUTOREFRESH, 0x00000002
|
||||
.equ CMD_SDRAM_CKE_SET_HIGH, 0x00000007
|
||||
|
@ -288,3 +288,21 @@ void peripheral_power_enable (void)
|
||||
|
||||
*SW_CLOCK_REQUEST |= UART1_48MHZ_ENABLE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check Board Identity
|
||||
*/
|
||||
int checkboard(void)
|
||||
{
|
||||
char *s = getenv("serial#");
|
||||
|
||||
puts("Board: OSK5912");
|
||||
|
||||
if (s != NULL) {
|
||||
puts(", serial# ");
|
||||
puts(s);
|
||||
}
|
||||
putc('\n');
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -317,7 +317,7 @@ REG_WATCHDOG:
|
||||
.word 0xfffec808
|
||||
|
||||
REG_MPU_LOAD_TIMER:
|
||||
.word 0xfffec600
|
||||
.word 0xfffec504
|
||||
REG_MPU_CNTL_TIMER:
|
||||
.word 0xfffec500
|
||||
|
||||
|
47
board/pcs440ep/Makefile
Normal file
47
board/pcs440ep/Makefile
Normal file
@ -0,0 +1,47 @@
|
||||
#
|
||||
# (C) Copyright 2006
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
#
|
||||
# See file CREDITS for list of people who contributed to this
|
||||
# project.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of
|
||||
# the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
# MA 02111-1307 USA
|
||||
#
|
||||
|
||||
include $(TOPDIR)/config.mk
|
||||
|
||||
LIB = lib$(BOARD).a
|
||||
|
||||
OBJS = $(BOARD).o flash.o
|
||||
SOBJS = init.o
|
||||
|
||||
$(LIB): $(OBJS) $(SOBJS)
|
||||
$(AR) crv $@ $(OBJS)
|
||||
|
||||
clean:
|
||||
rm -f $(SOBJS) $(OBJS)
|
||||
|
||||
distclean: clean
|
||||
rm -f $(LIB) core *.bak .depend
|
||||
|
||||
#########################################################################
|
||||
|
||||
.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
|
||||
$(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
|
||||
|
||||
sinclude .depend
|
||||
|
||||
#########################################################################
|
44
board/pcs440ep/config.mk
Normal file
44
board/pcs440ep/config.mk
Normal file
@ -0,0 +1,44 @@
|
||||
#
|
||||
# (C) Copyright 2006
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
#
|
||||
# See file CREDITS for list of people who contributed to this
|
||||
# project.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of
|
||||
# the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
# MA 02111-1307 USA
|
||||
#
|
||||
|
||||
#
|
||||
# PCS440EP board
|
||||
#
|
||||
|
||||
#TEXT_BASE = 0x00001000
|
||||
|
||||
ifeq ($(ramsym),1)
|
||||
TEXT_BASE = 0xFBD00000
|
||||
else
|
||||
TEXT_BASE = 0xFFFA0000
|
||||
endif
|
||||
|
||||
PLATFORM_CPPFLAGS += -DCONFIG_440=1
|
||||
|
||||
ifeq ($(debug),1)
|
||||
PLATFORM_CPPFLAGS += -DDEBUG
|
||||
endif
|
||||
|
||||
ifeq ($(dbcr),1)
|
||||
PLATFORM_CPPFLAGS += -DCFG_INIT_DBCR=0x8cff0000
|
||||
endif
|
608
board/pcs440ep/flash.c
Normal file
608
board/pcs440ep/flash.c
Normal file
@ -0,0 +1,608 @@
|
||||
/*
|
||||
* (C) Copyright 2006
|
||||
* Stefan Roese, DENX Software Engineering, sr@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
#ifndef CFG_FLASH_READ0
|
||||
#define CFG_FLASH_READ0 0x0000 /* 0 is standard */
|
||||
#define CFG_FLASH_READ1 0x0001 /* 1 is standard */
|
||||
#define CFG_FLASH_READ2 0x0002 /* 2 is standard */
|
||||
#endif
|
||||
|
||||
flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
|
||||
|
||||
/*
|
||||
* Functions
|
||||
*/
|
||||
static int write_word(flash_info_t *info, ulong dest, ulong data);
|
||||
static ulong flash_get_size(vu_long *addr, flash_info_t *info);
|
||||
|
||||
unsigned long flash_init(void)
|
||||
{
|
||||
unsigned long size_b0, size_b1;
|
||||
int i;
|
||||
unsigned long base_b0, base_b1;
|
||||
|
||||
/* Init: no FLASHes known */
|
||||
for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
|
||||
flash_info[i].flash_id = FLASH_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Static FLASH Bank configuration here - FIXME XXX */
|
||||
|
||||
base_b0 = FLASH_BASE0_PRELIM;
|
||||
size_b0 = flash_get_size ((vu_long *) base_b0, &flash_info[0]);
|
||||
|
||||
if (flash_info[0].flash_id == FLASH_UNKNOWN) {
|
||||
printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
|
||||
size_b0, size_b0 << 20);
|
||||
}
|
||||
|
||||
base_b1 = FLASH_BASE1_PRELIM;
|
||||
size_b1 = flash_get_size ((vu_long *) base_b1, &flash_info[1]);
|
||||
|
||||
return (size_b0 + size_b1);
|
||||
}
|
||||
|
||||
void flash_print_info(flash_info_t *info)
|
||||
{
|
||||
int i;
|
||||
int k;
|
||||
int size;
|
||||
int erased;
|
||||
volatile unsigned long *flash;
|
||||
|
||||
if (info->flash_id == FLASH_UNKNOWN) {
|
||||
printf ("missing or unknown FLASH type\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (info->flash_id & FLASH_VENDMASK) {
|
||||
case FLASH_MAN_AMD: printf ("AMD "); break;
|
||||
case FLASH_MAN_FUJ: printf ("FUJITSU "); break;
|
||||
case FLASH_MAN_SST: printf ("SST "); break;
|
||||
case FLASH_MAN_EXCEL: printf ("Excel Semiconductor "); break;
|
||||
default: printf ("Unknown Vendor "); break;
|
||||
}
|
||||
|
||||
switch (info->flash_id & FLASH_TYPEMASK) {
|
||||
case FLASH_AM400B: printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
|
||||
break;
|
||||
case FLASH_AM400T: printf ("AM29LV400T (4 Mbit, top boot sector)\n");
|
||||
break;
|
||||
case FLASH_AM040: printf ("AM29LV040B (4 Mbit, uniform sector size)\n");
|
||||
break;
|
||||
case FLASH_AM800B: printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
|
||||
break;
|
||||
case FLASH_AM800T: printf ("AM29LV800T (8 Mbit, top boot sector)\n");
|
||||
break;
|
||||
case FLASH_AM160B: printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
|
||||
break;
|
||||
case FLASH_AM160T: printf ("AM29LV160T (16 Mbit, top boot sector)\n");
|
||||
break;
|
||||
case FLASH_AM320T: printf ("AM29LV320T (32 M, top sector)\n");
|
||||
break;
|
||||
case FLASH_AM320B: printf ("AM29LV320B (32 M, bottom sector)\n");
|
||||
break;
|
||||
case FLASH_AMDL322T: printf ("AM29DL322T (32 M, top sector)\n");
|
||||
break;
|
||||
case FLASH_AMDL322B: printf ("AM29DL322B (32 M, bottom sector)\n");
|
||||
break;
|
||||
case FLASH_AMDL323T: printf ("AM29DL323T (32 M, top sector)\n");
|
||||
break;
|
||||
case FLASH_AMDL323B: printf ("AM29DL323B (32 M, bottom sector)\n");
|
||||
break;
|
||||
case FLASH_SST020: printf ("SST39LF/VF020 (2 Mbit, uniform sector size)\n");
|
||||
break;
|
||||
case FLASH_SST040: printf ("SST39LF/VF040 (4 Mbit, uniform sector size)\n");
|
||||
break;
|
||||
default: printf ("Unknown Chip Type\n");
|
||||
break;
|
||||
}
|
||||
|
||||
printf (" Size: %ld MB in %d Sectors\n",
|
||||
info->size >> 20, info->sector_count);
|
||||
|
||||
printf (" Sector Start Addresses:");
|
||||
for (i=0; i<info->sector_count; ++i) {
|
||||
#ifdef CFG_FLASH_EMPTY_INFO
|
||||
/*
|
||||
* Check if whole sector is erased
|
||||
*/
|
||||
if (i != (info->sector_count-1))
|
||||
size = info->start[i+1] - info->start[i];
|
||||
else
|
||||
size = info->start[0] + info->size - info->start[i];
|
||||
erased = 1;
|
||||
flash = (volatile unsigned long *)info->start[i];
|
||||
size = size >> 2; /* divide by 4 for longword access */
|
||||
for (k=0; k<size; k++) {
|
||||
if (*flash++ != 0xffffffff) {
|
||||
erased = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((i % 5) == 0)
|
||||
printf ("\n ");
|
||||
/* print empty and read-only info */
|
||||
printf (" %08lX%s%s",
|
||||
info->start[i],
|
||||
erased ? " E" : " ",
|
||||
info->protect[i] ? "RO " : " ");
|
||||
#else
|
||||
if ((i % 5) == 0)
|
||||
printf ("\n ");
|
||||
printf (" %08lX%s",
|
||||
info->start[i],
|
||||
info->protect[i] ? " (RO)" : " ");
|
||||
#endif
|
||||
|
||||
}
|
||||
printf ("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following code cannot be run from FLASH!
|
||||
*/
|
||||
static ulong flash_get_size(vu_long *addr, flash_info_t *info)
|
||||
{
|
||||
short i;
|
||||
short n;
|
||||
volatile CFG_FLASH_WORD_SIZE value;
|
||||
ulong base = (ulong)addr;
|
||||
volatile CFG_FLASH_WORD_SIZE *addr2 = (volatile CFG_FLASH_WORD_SIZE *)addr;
|
||||
|
||||
/* Write auto select command: read Manufacturer ID */
|
||||
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
|
||||
addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
|
||||
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00900090;
|
||||
|
||||
value = addr2[CFG_FLASH_READ0];
|
||||
|
||||
switch (value) {
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_MANUFACT:
|
||||
info->flash_id = FLASH_MAN_AMD;
|
||||
break;
|
||||
case (CFG_FLASH_WORD_SIZE)FUJ_MANUFACT:
|
||||
info->flash_id = FLASH_MAN_FUJ;
|
||||
break;
|
||||
case (CFG_FLASH_WORD_SIZE)SST_MANUFACT:
|
||||
info->flash_id = FLASH_MAN_SST;
|
||||
break;
|
||||
case (CFG_FLASH_WORD_SIZE)EXCEL_MANUFACT:
|
||||
info->flash_id = FLASH_MAN_EXCEL;
|
||||
break;
|
||||
default:
|
||||
info->flash_id = FLASH_UNKNOWN;
|
||||
info->sector_count = 0;
|
||||
info->size = 0;
|
||||
return (0); /* no or unknown flash */
|
||||
}
|
||||
|
||||
value = addr2[CFG_FLASH_READ1]; /* device ID */
|
||||
|
||||
switch (value) {
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV400T:
|
||||
info->flash_id += FLASH_AM400T;
|
||||
info->sector_count = 11;
|
||||
info->size = 0x00080000;
|
||||
break; /* => 0.5 MB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV400B:
|
||||
info->flash_id += FLASH_AM400B;
|
||||
info->sector_count = 11;
|
||||
info->size = 0x00080000;
|
||||
break; /* => 0.5 MB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV040B:
|
||||
info->flash_id += FLASH_AM040;
|
||||
info->sector_count = 8;
|
||||
info->size = 0x0080000; /* => 0.5 MB */
|
||||
break;
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV800T:
|
||||
info->flash_id += FLASH_AM800T;
|
||||
info->sector_count = 19;
|
||||
info->size = 0x00100000;
|
||||
break; /* => 1 MB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV800B:
|
||||
info->flash_id += FLASH_AM800B;
|
||||
info->sector_count = 19;
|
||||
info->size = 0x00100000;
|
||||
break; /* => 1 MB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV160T:
|
||||
info->flash_id += FLASH_AM160T;
|
||||
info->sector_count = 35;
|
||||
info->size = 0x00200000;
|
||||
break; /* => 2 MB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV160B:
|
||||
info->flash_id += FLASH_AM160B;
|
||||
info->sector_count = 35;
|
||||
info->size = 0x00200000;
|
||||
break; /* => 2 MB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV320T:
|
||||
info->flash_id += FLASH_AM320T;
|
||||
info->sector_count = 71;
|
||||
info->size = 0x00400000;
|
||||
break; /* => 4 MB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV320B:
|
||||
info->flash_id += FLASH_AM320B;
|
||||
info->sector_count = 71;
|
||||
info->size = 0x00400000;
|
||||
break; /* => 4 MB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_DL322T:
|
||||
info->flash_id += FLASH_AMDL322T;
|
||||
info->sector_count = 71;
|
||||
info->size = 0x00400000;
|
||||
break; /* => 4 MB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_DL322B:
|
||||
info->flash_id += FLASH_AMDL322B;
|
||||
info->sector_count = 71;
|
||||
info->size = 0x00400000;
|
||||
break; /* => 4 MB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_DL323T:
|
||||
info->flash_id += FLASH_AMDL323T;
|
||||
info->sector_count = 71;
|
||||
info->size = 0x00400000;
|
||||
break; /* => 4 MB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_DL323B:
|
||||
info->flash_id += FLASH_AMDL323B;
|
||||
info->sector_count = 71;
|
||||
info->size = 0x00400000;
|
||||
break; /* => 4 MB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)SST_ID_xF020:
|
||||
info->flash_id += FLASH_SST020;
|
||||
info->sector_count = 64;
|
||||
info->size = 0x00040000;
|
||||
break; /* => 256 kB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)SST_ID_xF040:
|
||||
info->flash_id += FLASH_SST040;
|
||||
info->sector_count = 128;
|
||||
info->size = 0x00080000;
|
||||
break; /* => 512 kB */
|
||||
|
||||
default:
|
||||
info->flash_id = FLASH_UNKNOWN;
|
||||
return (0); /* => no or unknown flash */
|
||||
|
||||
}
|
||||
|
||||
/* set up sector start address table */
|
||||
if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||
|
||||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AM640U)) {
|
||||
for (i = 0; i < info->sector_count; i++)
|
||||
info->start[i] = base + (i * 0x00001000);
|
||||
} else if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040) {
|
||||
for (i = 0; i < info->sector_count; i++)
|
||||
info->start[i] = base + (i * 0x00010000);
|
||||
} else if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL322B) ||
|
||||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL323B) ||
|
||||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320B) ||
|
||||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL324B)) {
|
||||
/* set sector offsets for bottom boot block type */
|
||||
for (i=0; i<8; ++i) { /* 8 x 8k boot sectors */
|
||||
info->start[i] = base;
|
||||
base += 8 << 10;
|
||||
}
|
||||
while (i < info->sector_count) { /* 64k regular sectors */
|
||||
info->start[i] = base;
|
||||
base += 64 << 10;
|
||||
++i;
|
||||
}
|
||||
} else if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL322T) ||
|
||||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL323T) ||
|
||||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320T) ||
|
||||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL324T)) {
|
||||
/* set sector offsets for top boot block type */
|
||||
base += info->size;
|
||||
i = info->sector_count;
|
||||
for (n=0; n<8; ++n) { /* 8 x 8k boot sectors */
|
||||
base -= 8 << 10;
|
||||
--i;
|
||||
info->start[i] = base;
|
||||
}
|
||||
while (i > 0) { /* 64k regular sectors */
|
||||
base -= 64 << 10;
|
||||
--i;
|
||||
info->start[i] = base;
|
||||
}
|
||||
} else {
|
||||
if (info->flash_id & FLASH_BTYPE) {
|
||||
/* set sector offsets for bottom boot block type */
|
||||
info->start[0] = base + 0x00000000;
|
||||
info->start[1] = base + 0x00004000;
|
||||
info->start[2] = base + 0x00006000;
|
||||
info->start[3] = base + 0x00008000;
|
||||
for (i = 4; i < info->sector_count; i++) {
|
||||
info->start[i] = base + (i * 0x00010000) - 0x00030000;
|
||||
}
|
||||
} else {
|
||||
/* set sector offsets for top boot block type */
|
||||
i = info->sector_count - 1;
|
||||
info->start[i--] = base + info->size - 0x00004000;
|
||||
info->start[i--] = base + info->size - 0x00006000;
|
||||
info->start[i--] = base + info->size - 0x00008000;
|
||||
for (; i >= 0; i--) {
|
||||
info->start[i] = base + i * 0x00010000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check for protected sectors */
|
||||
for (i = 0; i < info->sector_count; i++) {
|
||||
/* read sector protection at sector address, (A7 .. A0) = 0x02 */
|
||||
/* D0 = 1 if protected */
|
||||
addr2 = (volatile CFG_FLASH_WORD_SIZE *)(info->start[i]);
|
||||
if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_AMD)
|
||||
info->protect[i] = 0;
|
||||
else
|
||||
info->protect[i] = addr2[CFG_FLASH_READ2] & 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prevent writes to uninitialized FLASH.
|
||||
*/
|
||||
if (info->flash_id != FLASH_UNKNOWN) {
|
||||
addr2 = (CFG_FLASH_WORD_SIZE *)info->start[0];
|
||||
*addr2 = (CFG_FLASH_WORD_SIZE)0x00F000F0; /* reset bank */
|
||||
}
|
||||
|
||||
return (info->size);
|
||||
}
|
||||
|
||||
|
||||
int flash_erase(flash_info_t *info, int s_first, int s_last)
|
||||
{
|
||||
volatile CFG_FLASH_WORD_SIZE *addr = (CFG_FLASH_WORD_SIZE *)(info->start[0]);
|
||||
volatile CFG_FLASH_WORD_SIZE *addr2;
|
||||
int flag, prot, sect, l_sect;
|
||||
ulong start, now, last;
|
||||
|
||||
if ((s_first < 0) || (s_first > s_last)) {
|
||||
if (info->flash_id == FLASH_UNKNOWN)
|
||||
printf ("- missing\n");
|
||||
else
|
||||
printf ("- no sectors to erase\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (info->flash_id == FLASH_UNKNOWN) {
|
||||
printf ("Can't erase unknown flash type - aborted\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
prot = 0;
|
||||
for (sect=s_first; sect<=s_last; ++sect)
|
||||
if (info->protect[sect])
|
||||
prot++;
|
||||
|
||||
if (prot)
|
||||
printf ("- Warning: %d protected sectors will not be erased!\n", prot);
|
||||
else
|
||||
printf ("\n");
|
||||
|
||||
l_sect = -1;
|
||||
|
||||
/* Disable interrupts which might cause a timeout here */
|
||||
flag = disable_interrupts();
|
||||
|
||||
/* Start erase on unprotected sectors */
|
||||
for (sect = s_first; sect<=s_last; sect++) {
|
||||
if (info->protect[sect] == 0) { /* not protected */
|
||||
addr2 = (CFG_FLASH_WORD_SIZE *)(info->start[sect]);
|
||||
if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
|
||||
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
|
||||
addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
|
||||
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00800080;
|
||||
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
|
||||
addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
|
||||
addr2[0] = (CFG_FLASH_WORD_SIZE)0x00300030; /* sector erase */
|
||||
|
||||
/* re-enable interrupts if necessary */
|
||||
if (flag) {
|
||||
enable_interrupts();
|
||||
flag = 0;
|
||||
}
|
||||
|
||||
/* data polling for D7 */
|
||||
start = get_timer (0);
|
||||
while ((addr2[0] & (CFG_FLASH_WORD_SIZE)0x00800080) !=
|
||||
(CFG_FLASH_WORD_SIZE)0x00800080) {
|
||||
if (get_timer(start) > CFG_FLASH_WRITE_TOUT)
|
||||
return (1);
|
||||
}
|
||||
} else {
|
||||
if (sect == s_first) {
|
||||
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
|
||||
addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
|
||||
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00800080;
|
||||
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
|
||||
addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
|
||||
}
|
||||
addr2[0] = (CFG_FLASH_WORD_SIZE)0x00300030; /* sector erase */
|
||||
}
|
||||
l_sect = sect;
|
||||
}
|
||||
}
|
||||
|
||||
/* re-enable interrupts if necessary */
|
||||
if (flag)
|
||||
enable_interrupts();
|
||||
|
||||
/* wait at least 80us - let's wait 1 ms */
|
||||
udelay (1000);
|
||||
|
||||
/*
|
||||
* We wait for the last triggered sector
|
||||
*/
|
||||
if (l_sect < 0)
|
||||
goto DONE;
|
||||
|
||||
start = get_timer (0);
|
||||
last = start;
|
||||
addr = (CFG_FLASH_WORD_SIZE *)(info->start[l_sect]);
|
||||
while ((addr[0] & (CFG_FLASH_WORD_SIZE)0x00800080) != (CFG_FLASH_WORD_SIZE)0x00800080) {
|
||||
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
|
||||
printf ("Timeout\n");
|
||||
return 1;
|
||||
}
|
||||
/* show that we're waiting */
|
||||
if ((now - last) > 1000) { /* every second */
|
||||
putc ('.');
|
||||
last = now;
|
||||
}
|
||||
}
|
||||
|
||||
DONE:
|
||||
/* reset to read mode */
|
||||
addr = (CFG_FLASH_WORD_SIZE *)info->start[0];
|
||||
addr[0] = (CFG_FLASH_WORD_SIZE)0x00F000F0; /* reset bank */
|
||||
|
||||
printf (" done\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy memory to flash, returns:
|
||||
* 0 - OK
|
||||
* 1 - write timeout
|
||||
* 2 - Flash not erased
|
||||
*/
|
||||
int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
|
||||
{
|
||||
ulong cp, wp, data;
|
||||
int i, l, rc;
|
||||
|
||||
wp = (addr & ~3); /* get lower word aligned address */
|
||||
|
||||
/*
|
||||
* handle unaligned start bytes
|
||||
*/
|
||||
if ((l = addr - wp) != 0) {
|
||||
data = 0;
|
||||
for (i=0, cp=wp; i<l; ++i, ++cp) {
|
||||
data = (data << 8) | (*(uchar *)cp);
|
||||
}
|
||||
for (; i<4 && cnt>0; ++i) {
|
||||
data = (data << 8) | *src++;
|
||||
--cnt;
|
||||
++cp;
|
||||
}
|
||||
for (; cnt==0 && i<4; ++i, ++cp) {
|
||||
data = (data << 8) | (*(uchar *)cp);
|
||||
}
|
||||
|
||||
if ((rc = write_word(info, wp, data)) != 0) {
|
||||
return (rc);
|
||||
}
|
||||
wp += 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* handle word aligned part
|
||||
*/
|
||||
while (cnt >= 4) {
|
||||
data = 0;
|
||||
for (i=0; i<4; ++i)
|
||||
data = (data << 8) | *src++;
|
||||
if ((rc = write_word(info, wp, data)) != 0)
|
||||
return (rc);
|
||||
wp += 4;
|
||||
cnt -= 4;
|
||||
}
|
||||
|
||||
if (cnt == 0)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* handle unaligned tail bytes
|
||||
*/
|
||||
data = 0;
|
||||
for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
|
||||
data = (data << 8) | *src++;
|
||||
--cnt;
|
||||
}
|
||||
for (; i<4; ++i, ++cp)
|
||||
data = (data << 8) | (*(uchar *)cp);
|
||||
|
||||
return (write_word(info, wp, data));
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a word to Flash, returns:
|
||||
* 0 - OK
|
||||
* 1 - write timeout
|
||||
* 2 - Flash not erased
|
||||
*/
|
||||
static int write_word(flash_info_t *info, ulong dest, ulong data)
|
||||
{
|
||||
volatile CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *)(info->start[0]);
|
||||
volatile CFG_FLASH_WORD_SIZE *dest2 = (CFG_FLASH_WORD_SIZE *)dest;
|
||||
volatile CFG_FLASH_WORD_SIZE *data2 = (CFG_FLASH_WORD_SIZE *)&data;
|
||||
ulong start;
|
||||
int flag;
|
||||
int i;
|
||||
|
||||
/* Check if Flash is (sufficiently) erased */
|
||||
if ((*((vu_long *)dest) & data) != data)
|
||||
return (2);
|
||||
|
||||
/* Disable interrupts which might cause a timeout here */
|
||||
flag = disable_interrupts();
|
||||
|
||||
for (i=0; i<4/sizeof(CFG_FLASH_WORD_SIZE); i++) {
|
||||
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
|
||||
addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
|
||||
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00A000A0;
|
||||
|
||||
dest2[i] = data2[i];
|
||||
|
||||
/* re-enable interrupts if necessary */
|
||||
if (flag)
|
||||
enable_interrupts();
|
||||
|
||||
/* data polling for D7 */
|
||||
start = get_timer (0);
|
||||
while ((dest2[i] & (CFG_FLASH_WORD_SIZE)0x00800080) !=
|
||||
(data2[i] & (CFG_FLASH_WORD_SIZE)0x00800080)) {
|
||||
if (get_timer(start) > CFG_FLASH_WRITE_TOUT)
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
113
board/pcs440ep/init.S
Normal file
113
board/pcs440ep/init.S
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* (C) Copyright 2006
|
||||
* Stefan Roese, DENX Software Engineering, sr@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <ppc_asm.tmpl>
|
||||
#include <config.h>
|
||||
|
||||
/* General */
|
||||
#define TLB_VALID 0x00000200
|
||||
|
||||
/* Supported page sizes */
|
||||
|
||||
#define SZ_1K 0x00000000
|
||||
#define SZ_4K 0x00000010
|
||||
#define SZ_16K 0x00000020
|
||||
#define SZ_64K 0x00000030
|
||||
#define SZ_256K 0x00000040
|
||||
#define SZ_1M 0x00000050
|
||||
#define SZ_8M 0x00000060
|
||||
#define SZ_16M 0x00000070
|
||||
#define SZ_256M 0x00000090
|
||||
|
||||
/* Storage attributes */
|
||||
#define SA_W 0x00000800 /* Write-through */
|
||||
#define SA_I 0x00000400 /* Caching inhibited */
|
||||
#define SA_M 0x00000200 /* Memory coherence */
|
||||
#define SA_G 0x00000100 /* Guarded */
|
||||
#define SA_E 0x00000080 /* Endian */
|
||||
|
||||
/* Access control */
|
||||
#define AC_X 0x00000024 /* Execute */
|
||||
#define AC_W 0x00000012 /* Write */
|
||||
#define AC_R 0x00000009 /* Read */
|
||||
|
||||
/* Some handy macros */
|
||||
|
||||
#define EPN(e) ((e) & 0xfffffc00)
|
||||
#define TLB0(epn,sz) ( (EPN((epn)) | (sz) | TLB_VALID ) )
|
||||
#define TLB1(rpn,erpn) ( ((rpn)&0xfffffc00) | (erpn) )
|
||||
#define TLB2(a) ( (a)&0x00000fbf )
|
||||
|
||||
#define tlbtab_start\
|
||||
mflr r1 ;\
|
||||
bl 0f ;
|
||||
|
||||
#define tlbtab_end\
|
||||
.long 0, 0, 0 ; \
|
||||
0: mflr r0 ; \
|
||||
mtlr r1 ; \
|
||||
blr ;
|
||||
|
||||
#define tlbentry(epn,sz,rpn,erpn,attr)\
|
||||
.long TLB0(epn,sz),TLB1(rpn,erpn),TLB2(attr)
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* TLB TABLE
|
||||
*
|
||||
* This table is used by the cpu boot code to setup the initial tlb
|
||||
* entries. Rather than make broad assumptions in the cpu source tree,
|
||||
* this table lets each board set things up however they like.
|
||||
*
|
||||
* Pointer to the table is returned in r1
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
.section .bootpg,"ax"
|
||||
.globl tlbtab
|
||||
|
||||
tlbtab:
|
||||
tlbtab_start
|
||||
|
||||
/*
|
||||
* BOOT_CS (FLASH) must be first. Before relocation SA_I can be off to use the
|
||||
* speed up boot process. It is patched after relocation to enable SA_I
|
||||
*/
|
||||
tlbentry( CFG_BOOT_BASE_ADDR, SZ_256M, CFG_BOOT_BASE_ADDR, 0, AC_R|AC_W|AC_X|SA_G/*|SA_I*/)
|
||||
|
||||
/* TLB-entry for init-ram in dcache (SA_I must be turned off!) */
|
||||
tlbentry( CFG_INIT_RAM_ADDR, SZ_64K, CFG_INIT_RAM_ADDR, 0, AC_R|AC_W|AC_X|SA_G )
|
||||
|
||||
tlbentry( CFG_SDRAM_BASE, SZ_256M, CFG_SDRAM_BASE, 0, AC_R|AC_W|AC_X|SA_G|SA_I )
|
||||
tlbentry( CFG_PCI_BASE, SZ_256M, CFG_PCI_BASE, 0, AC_R|AC_W|SA_G|SA_I )
|
||||
|
||||
/* PCI */
|
||||
tlbentry( CFG_PCI_MEMBASE, SZ_256M, CFG_PCI_MEMBASE, 0, AC_R|AC_W|SA_G|SA_I )
|
||||
tlbentry( CFG_PCI_MEMBASE1, SZ_256M, CFG_PCI_MEMBASE1, 0, AC_R|AC_W|SA_G|SA_I )
|
||||
tlbentry( CFG_PCI_MEMBASE2, SZ_256M, CFG_PCI_MEMBASE2, 0, AC_R|AC_W|SA_G|SA_I )
|
||||
tlbentry( CFG_PCI_MEMBASE3, SZ_256M, CFG_PCI_MEMBASE3, 0, AC_R|AC_W|SA_G|SA_I )
|
||||
|
||||
/* USB 2.0 Device */
|
||||
tlbentry( CFG_USB_DEVICE, SZ_1K, 0x50000000, 0, AC_R|AC_W|SA_G|SA_I )
|
||||
|
||||
tlbtab_end
|
379
board/pcs440ep/pcs440ep.c
Normal file
379
board/pcs440ep/pcs440ep.c
Normal file
@ -0,0 +1,379 @@
|
||||
/*
|
||||
* (C) Copyright 2006
|
||||
* Stefan Roese, DENX Software Engineering, sr@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <ppc4xx.h>
|
||||
#include <asm/processor.h>
|
||||
#include <spd_sdram.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
|
||||
|
||||
static void set_leds(int val)
|
||||
{
|
||||
unsigned char led[16] = {0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
|
||||
0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf};
|
||||
out32(GPIO0_OR, (in32(GPIO0_OR) & ~0x78000000) | (led[val] << 27));
|
||||
}
|
||||
|
||||
int board_early_init_f(void)
|
||||
{
|
||||
register uint reg;
|
||||
|
||||
set_leds(0); /* display boot info counter */
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* Setup the external bus controller/chip selects
|
||||
*-------------------------------------------------------------------*/
|
||||
mtdcr(ebccfga, xbcfg);
|
||||
reg = mfdcr(ebccfgd);
|
||||
mtdcr(ebccfgd, reg | 0x04000000); /* Set ATC */
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* GPIO's are alreay setup in cpu/ppc4xx/cpu_init.c
|
||||
* via define from board config file.
|
||||
*-------------------------------------------------------------------*/
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* Setup the interrupt controller polarities, triggers, etc.
|
||||
*-------------------------------------------------------------------*/
|
||||
mtdcr(uic0sr, 0xffffffff); /* clear all */
|
||||
mtdcr(uic0er, 0x00000000); /* disable all */
|
||||
mtdcr(uic0cr, 0x00000001); /* UIC1 crit is critical */
|
||||
mtdcr(uic0pr, 0xfffffe1f); /* per ref-board manual */
|
||||
mtdcr(uic0tr, 0x01c00000); /* per ref-board manual */
|
||||
mtdcr(uic0vr, 0x00000001); /* int31 highest, base=0x000 */
|
||||
mtdcr(uic0sr, 0xffffffff); /* clear all */
|
||||
|
||||
mtdcr(uic1sr, 0xffffffff); /* clear all */
|
||||
mtdcr(uic1er, 0x00000000); /* disable all */
|
||||
mtdcr(uic1cr, 0x00000000); /* all non-critical */
|
||||
mtdcr(uic1pr, 0xffffe0ff); /* per ref-board manual */
|
||||
mtdcr(uic1tr, 0x00ffc000); /* per ref-board manual */
|
||||
mtdcr(uic1vr, 0x00000001); /* int31 highest, base=0x000 */
|
||||
mtdcr(uic1sr, 0xffffffff); /* clear all */
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* Setup other serial configuration
|
||||
*-------------------------------------------------------------------*/
|
||||
mfsdr(sdr_pci0, reg);
|
||||
mtsdr(sdr_pci0, 0x80000000 | reg); /* PCI arbiter enabled */
|
||||
mtsdr(sdr_pfc0, 0x00000100); /* Pin function: enable GPIO49-63 */
|
||||
mtsdr(sdr_pfc1, 0x00048000); /* Pin function: UART0 has 4 pins, select IRQ5 */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int misc_init_r (void)
|
||||
{
|
||||
uint pbcr;
|
||||
int size_val = 0;
|
||||
|
||||
/* Re-do sizing to get full correct info */
|
||||
mtdcr(ebccfga, pb0cr);
|
||||
pbcr = mfdcr(ebccfgd);
|
||||
switch (gd->bd->bi_flashsize) {
|
||||
case 1 << 20:
|
||||
size_val = 0;
|
||||
break;
|
||||
case 2 << 20:
|
||||
size_val = 1;
|
||||
break;
|
||||
case 4 << 20:
|
||||
size_val = 2;
|
||||
break;
|
||||
case 8 << 20:
|
||||
size_val = 3;
|
||||
break;
|
||||
case 16 << 20:
|
||||
size_val = 4;
|
||||
break;
|
||||
case 32 << 20:
|
||||
size_val = 5;
|
||||
break;
|
||||
case 64 << 20:
|
||||
size_val = 6;
|
||||
break;
|
||||
case 128 << 20:
|
||||
size_val = 7;
|
||||
break;
|
||||
}
|
||||
pbcr = (pbcr & 0x0001ffff) | gd->bd->bi_flashstart | (size_val << 17);
|
||||
mtdcr(ebccfga, pb0cr);
|
||||
mtdcr(ebccfgd, pbcr);
|
||||
|
||||
/* adjust flash start and offset */
|
||||
gd->bd->bi_flashstart = 0 - gd->bd->bi_flashsize;
|
||||
gd->bd->bi_flashoffset = 0;
|
||||
|
||||
/* Monitor protection ON by default */
|
||||
(void)flash_protect(FLAG_PROTECT_SET,
|
||||
-CFG_MONITOR_LEN,
|
||||
0xffffffff,
|
||||
&flash_info[1]);
|
||||
|
||||
/* Env protection ON by default */
|
||||
(void)flash_protect(FLAG_PROTECT_SET,
|
||||
CFG_ENV_ADDR_REDUND,
|
||||
CFG_ENV_ADDR_REDUND + 2*CFG_ENV_SECT_SIZE - 1,
|
||||
&flash_info[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int checkboard(void)
|
||||
{
|
||||
char *s = getenv("serial#");
|
||||
|
||||
printf("Board: PCS440EP");
|
||||
if (s != NULL) {
|
||||
puts(", serial# ");
|
||||
puts(s);
|
||||
}
|
||||
putc('\n');
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
long int initdram (int board_type)
|
||||
{
|
||||
long dram_size = 0;
|
||||
|
||||
set_leds(1); /* display boot info counter */
|
||||
dram_size = spd_sdram();
|
||||
set_leds(2); /* display boot info counter */
|
||||
|
||||
return dram_size;
|
||||
}
|
||||
|
||||
#if defined(CFG_DRAM_TEST)
|
||||
int testdram(void)
|
||||
{
|
||||
unsigned long *mem = (unsigned long *)0;
|
||||
const unsigned long kend = (1024 / sizeof(unsigned long));
|
||||
unsigned long k, n;
|
||||
|
||||
mtmsr(0);
|
||||
|
||||
for (k = 0; k < CFG_KBYTES_SDRAM;
|
||||
++k, mem += (1024 / sizeof(unsigned long))) {
|
||||
if ((k & 1023) == 0) {
|
||||
printf("%3d MB\r", k / 1024);
|
||||
}
|
||||
|
||||
memset(mem, 0xaaaaaaaa, 1024);
|
||||
for (n = 0; n < kend; ++n) {
|
||||
if (mem[n] != 0xaaaaaaaa) {
|
||||
printf("SDRAM test fails at: %08x\n",
|
||||
(uint) & mem[n]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
memset(mem, 0x55555555, 1024);
|
||||
for (n = 0; n < kend; ++n) {
|
||||
if (mem[n] != 0x55555555) {
|
||||
printf("SDRAM test fails at: %08x\n",
|
||||
(uint) & mem[n]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("SDRAM test passes\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
* pci_pre_init
|
||||
*
|
||||
* This routine is called just prior to registering the hose and gives
|
||||
* the board the opportunity to check things. Returning a value of zero
|
||||
* indicates that things are bad & PCI initialization should be aborted.
|
||||
*
|
||||
* Different boards may wish to customize the pci controller structure
|
||||
* (add regions, override default access routines, etc) or perform
|
||||
* certain pre-initialization actions.
|
||||
*
|
||||
************************************************************************/
|
||||
#if defined(CONFIG_PCI) && defined(CFG_PCI_PRE_INIT)
|
||||
int pci_pre_init(struct pci_controller *hose)
|
||||
{
|
||||
unsigned long addr;
|
||||
|
||||
/*-------------------------------------------------------------------------+
|
||||
| Set priority for all PLB3 devices to 0.
|
||||
| Set PLB3 arbiter to fair mode.
|
||||
+-------------------------------------------------------------------------*/
|
||||
mfsdr(sdr_amp1, addr);
|
||||
mtsdr(sdr_amp1, (addr & 0x000000FF) | 0x0000FF00);
|
||||
addr = mfdcr(plb3_acr);
|
||||
mtdcr(plb3_acr, addr | 0x80000000);
|
||||
|
||||
/*-------------------------------------------------------------------------+
|
||||
| Set priority for all PLB4 devices to 0.
|
||||
+-------------------------------------------------------------------------*/
|
||||
mfsdr(sdr_amp0, addr);
|
||||
mtsdr(sdr_amp0, (addr & 0x000000FF) | 0x0000FF00);
|
||||
addr = mfdcr(plb4_acr) | 0xa0000000; /* Was 0x8---- */
|
||||
mtdcr(plb4_acr, addr);
|
||||
|
||||
/*-------------------------------------------------------------------------+
|
||||
| Set Nebula PLB4 arbiter to fair mode.
|
||||
+-------------------------------------------------------------------------*/
|
||||
/* Segment0 */
|
||||
addr = (mfdcr(plb0_acr) & ~plb0_acr_ppm_mask) | plb0_acr_ppm_fair;
|
||||
addr = (addr & ~plb0_acr_hbu_mask) | plb0_acr_hbu_enabled;
|
||||
addr = (addr & ~plb0_acr_rdp_mask) | plb0_acr_rdp_4deep;
|
||||
addr = (addr & ~plb0_acr_wrp_mask) | plb0_acr_wrp_2deep;
|
||||
mtdcr(plb0_acr, addr);
|
||||
|
||||
/* Segment1 */
|
||||
addr = (mfdcr(plb1_acr) & ~plb1_acr_ppm_mask) | plb1_acr_ppm_fair;
|
||||
addr = (addr & ~plb1_acr_hbu_mask) | plb1_acr_hbu_enabled;
|
||||
addr = (addr & ~plb1_acr_rdp_mask) | plb1_acr_rdp_4deep;
|
||||
addr = (addr & ~plb1_acr_wrp_mask) | plb1_acr_wrp_2deep;
|
||||
mtdcr(plb1_acr, addr);
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif /* defined(CONFIG_PCI) && defined(CFG_PCI_PRE_INIT) */
|
||||
|
||||
/*************************************************************************
|
||||
* pci_target_init
|
||||
*
|
||||
* The bootstrap configuration provides default settings for the pci
|
||||
* inbound map (PIM). But the bootstrap config choices are limited and
|
||||
* may not be sufficient for a given board.
|
||||
*
|
||||
************************************************************************/
|
||||
#if defined(CONFIG_PCI) && defined(CFG_PCI_TARGET_INIT)
|
||||
void pci_target_init(struct pci_controller *hose)
|
||||
{
|
||||
/*--------------------------------------------------------------------------+
|
||||
* Set up Direct MMIO registers
|
||||
*--------------------------------------------------------------------------*/
|
||||
/*--------------------------------------------------------------------------+
|
||||
| PowerPC440 EP PCI Master configuration.
|
||||
| Map one 1Gig range of PLB/processor addresses to PCI memory space.
|
||||
| PLB address 0xA0000000-0xDFFFFFFF ==> PCI address 0xA0000000-0xDFFFFFFF
|
||||
| Use byte reversed out routines to handle endianess.
|
||||
| Make this region non-prefetchable.
|
||||
+--------------------------------------------------------------------------*/
|
||||
out32r(PCIX0_PMM0MA, 0x00000000); /* PMM0 Mask/Attribute - disabled b4 setting */
|
||||
out32r(PCIX0_PMM0LA, CFG_PCI_MEMBASE); /* PMM0 Local Address */
|
||||
out32r(PCIX0_PMM0PCILA, CFG_PCI_MEMBASE); /* PMM0 PCI Low Address */
|
||||
out32r(PCIX0_PMM0PCIHA, 0x00000000); /* PMM0 PCI High Address */
|
||||
out32r(PCIX0_PMM0MA, 0xE0000001); /* 512M + No prefetching, and enable region */
|
||||
|
||||
out32r(PCIX0_PMM1MA, 0x00000000); /* PMM0 Mask/Attribute - disabled b4 setting */
|
||||
out32r(PCIX0_PMM1LA, CFG_PCI_MEMBASE2); /* PMM0 Local Address */
|
||||
out32r(PCIX0_PMM1PCILA, CFG_PCI_MEMBASE2); /* PMM0 PCI Low Address */
|
||||
out32r(PCIX0_PMM1PCIHA, 0x00000000); /* PMM0 PCI High Address */
|
||||
out32r(PCIX0_PMM1MA, 0xE0000001); /* 512M + No prefetching, and enable region */
|
||||
|
||||
out32r(PCIX0_PTM1MS, 0x00000001); /* Memory Size/Attribute */
|
||||
out32r(PCIX0_PTM1LA, 0); /* Local Addr. Reg */
|
||||
out32r(PCIX0_PTM2MS, 0); /* Memory Size/Attribute */
|
||||
out32r(PCIX0_PTM2LA, 0); /* Local Addr. Reg */
|
||||
|
||||
/*--------------------------------------------------------------------------+
|
||||
* Set up Configuration registers
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/* Program the board's subsystem id/vendor id */
|
||||
pci_write_config_word(0, PCI_SUBSYSTEM_VENDOR_ID,
|
||||
CFG_PCI_SUBSYS_VENDORID);
|
||||
pci_write_config_word(0, PCI_SUBSYSTEM_ID, CFG_PCI_SUBSYS_ID);
|
||||
|
||||
/* Configure command register as bus master */
|
||||
pci_write_config_word(0, PCI_COMMAND, PCI_COMMAND_MASTER);
|
||||
|
||||
/* 240nS PCI clock */
|
||||
pci_write_config_word(0, PCI_LATENCY_TIMER, 1);
|
||||
|
||||
/* No error reporting */
|
||||
pci_write_config_word(0, PCI_ERREN, 0);
|
||||
|
||||
pci_write_config_dword(0, PCI_BRDGOPT2, 0x00000101);
|
||||
|
||||
}
|
||||
#endif /* defined(CONFIG_PCI) && defined(CFG_PCI_TARGET_INIT) */
|
||||
|
||||
/*************************************************************************
|
||||
* pci_master_init
|
||||
*
|
||||
************************************************************************/
|
||||
#if defined(CONFIG_PCI) && defined(CFG_PCI_MASTER_INIT)
|
||||
void pci_master_init(struct pci_controller *hose)
|
||||
{
|
||||
unsigned short temp_short;
|
||||
|
||||
/*--------------------------------------------------------------------------+
|
||||
| Write the PowerPC440 EP PCI Configuration regs.
|
||||
| Enable PowerPC440 EP to be a master on the PCI bus (PMM).
|
||||
| Enable PowerPC440 EP to act as a PCI memory target (PTM).
|
||||
+--------------------------------------------------------------------------*/
|
||||
pci_read_config_word(0, PCI_COMMAND, &temp_short);
|
||||
pci_write_config_word(0, PCI_COMMAND,
|
||||
temp_short | PCI_COMMAND_MASTER |
|
||||
PCI_COMMAND_MEMORY);
|
||||
}
|
||||
#endif /* defined(CONFIG_PCI) && defined(CFG_PCI_MASTER_INIT) */
|
||||
|
||||
/*************************************************************************
|
||||
* is_pci_host
|
||||
*
|
||||
* This routine is called to determine if a pci scan should be
|
||||
* performed. With various hardware environments (especially cPCI and
|
||||
* PPMC) it's insufficient to depend on the state of the arbiter enable
|
||||
* bit in the strap register, or generic host/adapter assumptions.
|
||||
*
|
||||
* Rather than hard-code a bad assumption in the general 440 code, the
|
||||
* 440 pci code requires the board to decide at runtime.
|
||||
*
|
||||
* Return 0 for adapter mode, non-zero for host (monarch) mode.
|
||||
*
|
||||
*
|
||||
************************************************************************/
|
||||
#if defined(CONFIG_PCI)
|
||||
int is_pci_host(struct pci_controller *hose)
|
||||
{
|
||||
/* PCS440EP is always configured as host. */
|
||||
return (1);
|
||||
}
|
||||
#endif /* defined(CONFIG_PCI) */
|
||||
|
||||
/*************************************************************************
|
||||
* hw_watchdog_reset
|
||||
*
|
||||
* This routine is called to reset (keep alive) the watchdog timer
|
||||
*
|
||||
************************************************************************/
|
||||
#if defined(CONFIG_HW_WATCHDOG)
|
||||
void hw_watchdog_reset(void)
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
141
board/pcs440ep/u-boot.lds
Normal file
141
board/pcs440ep/u-boot.lds
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* (C) Copyright 2006
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
OUTPUT_ARCH(powerpc)
|
||||
SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
|
||||
/* Do we need any of these for elf?
|
||||
__DYNAMIC = 0; */
|
||||
SECTIONS
|
||||
{
|
||||
.resetvec 0xFFFFFFFC :
|
||||
{
|
||||
*(.resetvec)
|
||||
} = 0xffff
|
||||
|
||||
.bootpg 0xFFFFF000 :
|
||||
{
|
||||
cpu/ppc4xx/start.o (.bootpg)
|
||||
} = 0xffff
|
||||
|
||||
/* Read-only sections, merged into text segment: */
|
||||
. = + SIZEOF_HEADERS;
|
||||
.interp : { *(.interp) }
|
||||
.hash : { *(.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.rel.text : { *(.rel.text) }
|
||||
.rela.text : { *(.rela.text) }
|
||||
.rel.data : { *(.rel.data) }
|
||||
.rela.data : { *(.rela.data) }
|
||||
.rel.rodata : { *(.rel.rodata) }
|
||||
.rela.rodata : { *(.rela.rodata) }
|
||||
.rel.got : { *(.rel.got) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rel.ctors : { *(.rel.ctors) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rel.dtors : { *(.rel.dtors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rel.bss : { *(.rel.bss) }
|
||||
.rela.bss : { *(.rela.bss) }
|
||||
.rel.plt : { *(.rel.plt) }
|
||||
.rela.plt : { *(.rela.plt) }
|
||||
.init : { *(.init) }
|
||||
.plt : { *(.plt) }
|
||||
.text :
|
||||
{
|
||||
cpu/ppc4xx/start.o (.text)
|
||||
board/pcs440ep/init.o (.text)
|
||||
|
||||
*(.text)
|
||||
*(.fixup)
|
||||
*(.got1)
|
||||
}
|
||||
_etext = .;
|
||||
PROVIDE (etext = .);
|
||||
.rodata :
|
||||
{
|
||||
*(.rodata)
|
||||
*(.rodata1)
|
||||
*(.rodata.str1.4)
|
||||
*(.eh_frame)
|
||||
}
|
||||
.fini : { *(.fini) } =0
|
||||
.ctors : { *(.ctors) }
|
||||
.dtors : { *(.dtors) }
|
||||
|
||||
/* Read-write section, merged into data segment: */
|
||||
. = (. + 0x00FF) & 0xFFFFFF00;
|
||||
_erotext = .;
|
||||
PROVIDE (erotext = .);
|
||||
.reloc :
|
||||
{
|
||||
*(.got)
|
||||
_GOT2_TABLE_ = .;
|
||||
*(.got2)
|
||||
_FIXUP_TABLE_ = .;
|
||||
*(.fixup)
|
||||
}
|
||||
__got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
|
||||
__fixup_entries = (. - _FIXUP_TABLE_) >> 2;
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.data)
|
||||
*(.data1)
|
||||
*(.sdata)
|
||||
*(.sdata2)
|
||||
*(.dynamic)
|
||||
CONSTRUCTORS
|
||||
}
|
||||
_edata = .;
|
||||
PROVIDE (edata = .);
|
||||
|
||||
. = .;
|
||||
__u_boot_cmd_start = .;
|
||||
.u_boot_cmd : { *(.u_boot_cmd) }
|
||||
__u_boot_cmd_end = .;
|
||||
|
||||
. = .;
|
||||
__start___ex_table = .;
|
||||
__ex_table : { *(__ex_table) }
|
||||
__stop___ex_table = .;
|
||||
|
||||
. = ALIGN(256);
|
||||
__init_begin = .;
|
||||
.text.init : { *(.text.init) }
|
||||
.data.init : { *(.data.init) }
|
||||
. = ALIGN(256);
|
||||
__init_end = .;
|
||||
|
||||
__bss_start = .;
|
||||
.bss :
|
||||
{
|
||||
*(.sbss) *(.scommon)
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
}
|
||||
|
||||
_end = . ;
|
||||
PROVIDE (end = .);
|
||||
}
|
556
board/prodrive/common/flash.c
Normal file
556
board/prodrive/common/flash.c
Normal file
@ -0,0 +1,556 @@
|
||||
/*
|
||||
* (C) Copyright 2006
|
||||
* Stefan Roese, DENX Software Engineering, sr@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
|
||||
|
||||
/*
|
||||
* Functions
|
||||
*/
|
||||
static int write_word(flash_info_t *info, ulong dest, ulong data);
|
||||
|
||||
void flash_print_info(flash_info_t *info)
|
||||
{
|
||||
int i;
|
||||
int k;
|
||||
int size;
|
||||
int erased;
|
||||
volatile unsigned long *flash;
|
||||
|
||||
if (info->flash_id == FLASH_UNKNOWN) {
|
||||
printf ("missing or unknown FLASH type\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (info->flash_id & FLASH_VENDMASK) {
|
||||
case FLASH_MAN_AMD: printf ("AMD "); break;
|
||||
case FLASH_MAN_FUJ: printf ("FUJITSU "); break;
|
||||
case FLASH_MAN_SST: printf ("SST "); break;
|
||||
case FLASH_MAN_EXCEL: printf ("Excel Semiconductor "); break;
|
||||
default: printf ("Unknown Vendor "); break;
|
||||
}
|
||||
|
||||
switch (info->flash_id & FLASH_TYPEMASK) {
|
||||
case FLASH_AM400B: printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
|
||||
break;
|
||||
case FLASH_AM400T: printf ("AM29LV400T (4 Mbit, top boot sector)\n");
|
||||
break;
|
||||
case FLASH_AM800B: printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
|
||||
break;
|
||||
case FLASH_AM800T: printf ("AM29LV800T (8 Mbit, top boot sector)\n");
|
||||
break;
|
||||
case FLASH_AM160B: printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
|
||||
break;
|
||||
case FLASH_AM160T: printf ("AM29LV160T (16 Mbit, top boot sector)\n");
|
||||
break;
|
||||
case FLASH_AM320T: printf ("AM29LV320T (32 M, top sector)\n");
|
||||
break;
|
||||
case FLASH_AM320B: printf ("AM29LV320B (32 M, bottom sector)\n");
|
||||
break;
|
||||
case FLASH_AMDL322T: printf ("AM29DL322T (32 M, top sector)\n");
|
||||
break;
|
||||
case FLASH_AMDL322B: printf ("AM29DL322B (32 M, bottom sector)\n");
|
||||
break;
|
||||
case FLASH_AMDL323T: printf ("AM29DL323T (32 M, top sector)\n");
|
||||
break;
|
||||
case FLASH_AMDL323B: printf ("AM29DL323B (32 M, bottom sector)\n");
|
||||
break;
|
||||
case FLASH_SST020: printf ("SST39LF/VF020 (2 Mbit, uniform sector size)\n");
|
||||
break;
|
||||
case FLASH_SST040: printf ("SST39LF/VF040 (4 Mbit, uniform sector size)\n");
|
||||
break;
|
||||
default: printf ("Unknown Chip Type\n");
|
||||
break;
|
||||
}
|
||||
|
||||
printf (" Size: %ld MB in %d Sectors\n",
|
||||
info->size >> 20, info->sector_count);
|
||||
|
||||
printf (" Sector Start Addresses:");
|
||||
for (i=0; i<info->sector_count; ++i) {
|
||||
#ifdef CFG_FLASH_EMPTY_INFO
|
||||
/*
|
||||
* Check if whole sector is erased
|
||||
*/
|
||||
if (i != (info->sector_count-1))
|
||||
size = info->start[i+1] - info->start[i];
|
||||
else
|
||||
size = info->start[0] + info->size - info->start[i];
|
||||
erased = 1;
|
||||
flash = (volatile unsigned long *)info->start[i];
|
||||
size = size >> 2; /* divide by 4 for longword access */
|
||||
for (k=0; k<size; k++) {
|
||||
if (*flash++ != 0xffffffff) {
|
||||
erased = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((i % 5) == 0)
|
||||
printf ("\n ");
|
||||
/* print empty and read-only info */
|
||||
printf (" %08lX%s%s",
|
||||
info->start[i],
|
||||
erased ? " E" : " ",
|
||||
info->protect[i] ? "RO " : " ");
|
||||
#else
|
||||
if ((i % 5) == 0)
|
||||
printf ("\n ");
|
||||
printf (" %08lX%s",
|
||||
info->start[i],
|
||||
info->protect[i] ? " (RO)" : " ");
|
||||
#endif
|
||||
|
||||
}
|
||||
printf ("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following code cannot be run from FLASH!
|
||||
*/
|
||||
static ulong flash_get_size(vu_long *addr, flash_info_t *info)
|
||||
{
|
||||
short i;
|
||||
short n;
|
||||
CFG_FLASH_WORD_SIZE value;
|
||||
ulong base = (ulong)addr;
|
||||
volatile CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *)addr;
|
||||
|
||||
/* Write auto select command: read Manufacturer ID */
|
||||
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
|
||||
addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
|
||||
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00900090;
|
||||
|
||||
value = addr2[CFG_FLASH_READ0];
|
||||
|
||||
switch (value) {
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_MANUFACT:
|
||||
info->flash_id = FLASH_MAN_AMD;
|
||||
break;
|
||||
case (CFG_FLASH_WORD_SIZE)FUJ_MANUFACT:
|
||||
info->flash_id = FLASH_MAN_FUJ;
|
||||
break;
|
||||
case (CFG_FLASH_WORD_SIZE)SST_MANUFACT:
|
||||
info->flash_id = FLASH_MAN_SST;
|
||||
break;
|
||||
case (CFG_FLASH_WORD_SIZE)EXCEL_MANUFACT:
|
||||
info->flash_id = FLASH_MAN_EXCEL;
|
||||
break;
|
||||
default:
|
||||
info->flash_id = FLASH_UNKNOWN;
|
||||
info->sector_count = 0;
|
||||
info->size = 0;
|
||||
return (0); /* no or unknown flash */
|
||||
}
|
||||
|
||||
value = addr2[CFG_FLASH_READ1]; /* device ID */
|
||||
|
||||
switch (value) {
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV400T:
|
||||
info->flash_id += FLASH_AM400T;
|
||||
info->sector_count = 11;
|
||||
info->size = 0x00080000;
|
||||
break; /* => 0.5 MB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV400B:
|
||||
info->flash_id += FLASH_AM400B;
|
||||
info->sector_count = 11;
|
||||
info->size = 0x00080000;
|
||||
break; /* => 0.5 MB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV800T:
|
||||
info->flash_id += FLASH_AM800T;
|
||||
info->sector_count = 19;
|
||||
info->size = 0x00100000;
|
||||
break; /* => 1 MB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV800B:
|
||||
info->flash_id += FLASH_AM800B;
|
||||
info->sector_count = 19;
|
||||
info->size = 0x00100000;
|
||||
break; /* => 1 MB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV160T:
|
||||
info->flash_id += FLASH_AM160T;
|
||||
info->sector_count = 35;
|
||||
info->size = 0x00200000;
|
||||
break; /* => 2 MB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV160B:
|
||||
info->flash_id += FLASH_AM160B;
|
||||
info->sector_count = 35;
|
||||
info->size = 0x00200000;
|
||||
break; /* => 2 MB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV320T:
|
||||
info->flash_id += FLASH_AM320T;
|
||||
info->sector_count = 71;
|
||||
info->size = 0x00400000; break; /* => 4 MB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV320B:
|
||||
info->flash_id += FLASH_AM320B;
|
||||
info->sector_count = 71;
|
||||
info->size = 0x00400000; break; /* => 4 MB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_DL322T:
|
||||
info->flash_id += FLASH_AMDL322T;
|
||||
info->sector_count = 71;
|
||||
info->size = 0x00400000; break; /* => 4 MB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_DL322B:
|
||||
info->flash_id += FLASH_AMDL322B;
|
||||
info->sector_count = 71;
|
||||
info->size = 0x00400000; break; /* => 4 MB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_DL323T:
|
||||
info->flash_id += FLASH_AMDL323T;
|
||||
info->sector_count = 71;
|
||||
info->size = 0x00400000; break; /* => 4 MB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)AMD_ID_DL323B:
|
||||
info->flash_id += FLASH_AMDL323B;
|
||||
info->sector_count = 71;
|
||||
info->size = 0x00400000; break; /* => 4 MB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)SST_ID_xF020:
|
||||
info->flash_id += FLASH_SST020;
|
||||
info->sector_count = 64;
|
||||
info->size = 0x00040000;
|
||||
break; /* => 256 kB */
|
||||
|
||||
case (CFG_FLASH_WORD_SIZE)SST_ID_xF040:
|
||||
info->flash_id += FLASH_SST040;
|
||||
info->sector_count = 128;
|
||||
info->size = 0x00080000;
|
||||
break; /* => 512 kB */
|
||||
|
||||
default:
|
||||
info->flash_id = FLASH_UNKNOWN;
|
||||
return (0); /* => no or unknown flash */
|
||||
|
||||
}
|
||||
|
||||
/* set up sector start address table */
|
||||
if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
|
||||
for (i = 0; i < info->sector_count; i++)
|
||||
info->start[i] = base + (i * 0x00001000);
|
||||
} else if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL322B) ||
|
||||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL323B) ||
|
||||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320B) ||
|
||||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL324B)) {
|
||||
/* set sector offsets for bottom boot block type */
|
||||
for (i=0; i<8; ++i) { /* 8 x 8k boot sectors */
|
||||
info->start[i] = base;
|
||||
base += 8 << 10;
|
||||
}
|
||||
while (i < info->sector_count) { /* 64k regular sectors */
|
||||
info->start[i] = base;
|
||||
base += 64 << 10;
|
||||
++i;
|
||||
}
|
||||
} else if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL322T) ||
|
||||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL323T) ||
|
||||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320T) ||
|
||||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL324T)) {
|
||||
/* set sector offsets for top boot block type */
|
||||
base += info->size;
|
||||
i = info->sector_count;
|
||||
for (n=0; n<8; ++n) { /* 8 x 8k boot sectors */
|
||||
base -= 8 << 10;
|
||||
--i;
|
||||
info->start[i] = base;
|
||||
}
|
||||
while (i > 0) { /* 64k regular sectors */
|
||||
base -= 64 << 10;
|
||||
--i;
|
||||
info->start[i] = base;
|
||||
}
|
||||
} else {
|
||||
if (info->flash_id & FLASH_BTYPE) {
|
||||
/* set sector offsets for bottom boot block type */
|
||||
info->start[0] = base + 0x00000000;
|
||||
info->start[1] = base + 0x00004000;
|
||||
info->start[2] = base + 0x00006000;
|
||||
info->start[3] = base + 0x00008000;
|
||||
for (i = 4; i < info->sector_count; i++) {
|
||||
info->start[i] = base + (i * 0x00010000) - 0x00030000;
|
||||
}
|
||||
} else {
|
||||
/* set sector offsets for top boot block type */
|
||||
i = info->sector_count - 1;
|
||||
info->start[i--] = base + info->size - 0x00004000;
|
||||
info->start[i--] = base + info->size - 0x00006000;
|
||||
info->start[i--] = base + info->size - 0x00008000;
|
||||
for (; i >= 0; i--) {
|
||||
info->start[i] = base + i * 0x00010000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check for protected sectors */
|
||||
for (i = 0; i < info->sector_count; i++) {
|
||||
/* read sector protection at sector address, (A7 .. A0) = 0x02 */
|
||||
/* D0 = 1 if protected */
|
||||
addr2 = (volatile CFG_FLASH_WORD_SIZE *)(info->start[i]);
|
||||
if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_AMD)
|
||||
info->protect[i] = 0;
|
||||
else
|
||||
info->protect[i] = addr2[CFG_FLASH_READ2] & 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prevent writes to uninitialized FLASH.
|
||||
*/
|
||||
if (info->flash_id != FLASH_UNKNOWN) {
|
||||
addr2 = (CFG_FLASH_WORD_SIZE *)info->start[0];
|
||||
*addr2 = (CFG_FLASH_WORD_SIZE)0x00F000F0; /* reset bank */
|
||||
}
|
||||
|
||||
return (info->size);
|
||||
}
|
||||
|
||||
|
||||
int flash_erase(flash_info_t *info, int s_first, int s_last)
|
||||
{
|
||||
volatile CFG_FLASH_WORD_SIZE *addr = (CFG_FLASH_WORD_SIZE *)(info->start[0]);
|
||||
volatile CFG_FLASH_WORD_SIZE *addr2;
|
||||
int flag, prot, sect, l_sect;
|
||||
ulong start, now, last;
|
||||
|
||||
if ((s_first < 0) || (s_first > s_last)) {
|
||||
if (info->flash_id == FLASH_UNKNOWN)
|
||||
printf ("- missing\n");
|
||||
else
|
||||
printf ("- no sectors to erase\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (info->flash_id == FLASH_UNKNOWN) {
|
||||
printf ("Can't erase unknown flash type - aborted\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
prot = 0;
|
||||
for (sect=s_first; sect<=s_last; ++sect)
|
||||
if (info->protect[sect])
|
||||
prot++;
|
||||
|
||||
if (prot)
|
||||
printf ("- Warning: %d protected sectors will not be erased!\n", prot);
|
||||
else
|
||||
printf ("\n");
|
||||
|
||||
l_sect = -1;
|
||||
|
||||
/* Disable interrupts which might cause a timeout here */
|
||||
flag = disable_interrupts();
|
||||
|
||||
/* Start erase on unprotected sectors */
|
||||
for (sect = s_first; sect<=s_last; sect++) {
|
||||
if (info->protect[sect] == 0) { /* not protected */
|
||||
addr2 = (CFG_FLASH_WORD_SIZE *)(info->start[sect]);
|
||||
if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
|
||||
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
|
||||
addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
|
||||
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00800080;
|
||||
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
|
||||
addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
|
||||
addr2[0] = (CFG_FLASH_WORD_SIZE)0x00300030; /* sector erase */
|
||||
|
||||
/* re-enable interrupts if necessary */
|
||||
if (flag) {
|
||||
enable_interrupts();
|
||||
flag = 0;
|
||||
}
|
||||
|
||||
/* data polling for D7 */
|
||||
start = get_timer (0);
|
||||
while ((addr2[0] & (CFG_FLASH_WORD_SIZE)0x00800080) !=
|
||||
(CFG_FLASH_WORD_SIZE)0x00800080) {
|
||||
if (get_timer(start) > CFG_FLASH_WRITE_TOUT)
|
||||
return (1);
|
||||
}
|
||||
} else {
|
||||
if (sect == s_first) {
|
||||
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
|
||||
addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
|
||||
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00800080;
|
||||
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
|
||||
addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
|
||||
}
|
||||
addr2[0] = (CFG_FLASH_WORD_SIZE)0x00300030; /* sector erase */
|
||||
}
|
||||
l_sect = sect;
|
||||
}
|
||||
}
|
||||
|
||||
/* re-enable interrupts if necessary */
|
||||
if (flag)
|
||||
enable_interrupts();
|
||||
|
||||
/* wait at least 80us - let's wait 1 ms */
|
||||
udelay (1000);
|
||||
|
||||
/*
|
||||
* We wait for the last triggered sector
|
||||
*/
|
||||
if (l_sect < 0)
|
||||
goto DONE;
|
||||
|
||||
start = get_timer (0);
|
||||
last = start;
|
||||
addr = (CFG_FLASH_WORD_SIZE *)(info->start[l_sect]);
|
||||
while ((addr[0] & (CFG_FLASH_WORD_SIZE)0x00800080) != (CFG_FLASH_WORD_SIZE)0x00800080) {
|
||||
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
|
||||
printf ("Timeout\n");
|
||||
return 1;
|
||||
}
|
||||
/* show that we're waiting */
|
||||
if ((now - last) > 1000) { /* every second */
|
||||
putc ('.');
|
||||
last = now;
|
||||
}
|
||||
}
|
||||
|
||||
DONE:
|
||||
/* reset to read mode */
|
||||
addr = (CFG_FLASH_WORD_SIZE *)info->start[0];
|
||||
addr[0] = (CFG_FLASH_WORD_SIZE)0x00F000F0; /* reset bank */
|
||||
|
||||
printf (" done\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy memory to flash, returns:
|
||||
* 0 - OK
|
||||
* 1 - write timeout
|
||||
* 2 - Flash not erased
|
||||
*/
|
||||
int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
|
||||
{
|
||||
ulong cp, wp, data;
|
||||
int i, l, rc;
|
||||
|
||||
wp = (addr & ~3); /* get lower word aligned address */
|
||||
|
||||
/*
|
||||
* handle unaligned start bytes
|
||||
*/
|
||||
if ((l = addr - wp) != 0) {
|
||||
data = 0;
|
||||
for (i=0, cp=wp; i<l; ++i, ++cp) {
|
||||
data = (data << 8) | (*(uchar *)cp);
|
||||
}
|
||||
for (; i<4 && cnt>0; ++i) {
|
||||
data = (data << 8) | *src++;
|
||||
--cnt;
|
||||
++cp;
|
||||
}
|
||||
for (; cnt==0 && i<4; ++i, ++cp) {
|
||||
data = (data << 8) | (*(uchar *)cp);
|
||||
}
|
||||
|
||||
if ((rc = write_word(info, wp, data)) != 0) {
|
||||
return (rc);
|
||||
}
|
||||
wp += 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* handle word aligned part
|
||||
*/
|
||||
while (cnt >= 4) {
|
||||
data = 0;
|
||||
for (i=0; i<4; ++i)
|
||||
data = (data << 8) | *src++;
|
||||
if ((rc = write_word(info, wp, data)) != 0)
|
||||
return (rc);
|
||||
wp += 4;
|
||||
cnt -= 4;
|
||||
}
|
||||
|
||||
if (cnt == 0)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* handle unaligned tail bytes
|
||||
*/
|
||||
data = 0;
|
||||
for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
|
||||
data = (data << 8) | *src++;
|
||||
--cnt;
|
||||
}
|
||||
for (; i<4; ++i, ++cp)
|
||||
data = (data << 8) | (*(uchar *)cp);
|
||||
|
||||
return (write_word(info, wp, data));
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a word to Flash, returns:
|
||||
* 0 - OK
|
||||
* 1 - write timeout
|
||||
* 2 - Flash not erased
|
||||
*/
|
||||
static int write_word(flash_info_t *info, ulong dest, ulong data)
|
||||
{
|
||||
volatile CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *)(info->start[0]);
|
||||
volatile CFG_FLASH_WORD_SIZE *dest2 = (CFG_FLASH_WORD_SIZE *)dest;
|
||||
volatile CFG_FLASH_WORD_SIZE *data2 = (CFG_FLASH_WORD_SIZE *)&data;
|
||||
ulong start;
|
||||
int flag;
|
||||
int i;
|
||||
|
||||
/* Check if Flash is (sufficiently) erased */
|
||||
if ((*((vu_long *)dest) & data) != data)
|
||||
return (2);
|
||||
|
||||
/* Disable interrupts which might cause a timeout here */
|
||||
flag = disable_interrupts();
|
||||
|
||||
for (i=0; i<4/sizeof(CFG_FLASH_WORD_SIZE); i++) {
|
||||
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
|
||||
addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
|
||||
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00A000A0;
|
||||
|
||||
dest2[i] = data2[i];
|
||||
|
||||
/* re-enable interrupts if necessary */
|
||||
if (flag)
|
||||
enable_interrupts();
|
||||
|
||||
/* data polling for D7 */
|
||||
start = get_timer (0);
|
||||
while ((dest2[i] & (CFG_FLASH_WORD_SIZE)0x00800080) !=
|
||||
(data2[i] & (CFG_FLASH_WORD_SIZE)0x00800080)) {
|
||||
if (get_timer(start) > CFG_FLASH_WRITE_TOUT)
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
183
board/prodrive/common/fpga.c
Normal file
183
board/prodrive/common/fpga.c
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* (C) Copyright 2006
|
||||
* Stefan Roese, DENX Software Engineering, sr@denx.de.
|
||||
*
|
||||
* (C) Copyright 2001-2004
|
||||
* Matthias Fuchs, esd gmbh germany, matthias.fuchs@esd-electronics.com
|
||||
* Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/processor.h>
|
||||
#include <command.h>
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef FPGA_DEBUG
|
||||
#define DBG(x...) printf(x)
|
||||
#else
|
||||
#define DBG(x...)
|
||||
#endif /* DEBUG */
|
||||
|
||||
#define FPGA_PRG CFG_FPGA_PRG /* FPGA program pin (cpu output)*/
|
||||
#define FPGA_CLK CFG_FPGA_CLK /* FPGA clk pin (cpu output) */
|
||||
#define FPGA_DATA CFG_FPGA_DATA /* FPGA data pin (cpu output) */
|
||||
#define FPGA_DONE CFG_FPGA_DONE /* FPGA done pin (cpu input) */
|
||||
#define FPGA_INIT CFG_FPGA_INIT /* FPGA init pin (cpu input) */
|
||||
|
||||
#define ERROR_FPGA_PRG_INIT_LOW -1 /* Timeout after PRG* asserted */
|
||||
#define ERROR_FPGA_PRG_INIT_HIGH -2 /* Timeout after PRG* deasserted */
|
||||
#define ERROR_FPGA_PRG_DONE -3 /* Timeout after programming */
|
||||
|
||||
#ifndef OLD_VAL
|
||||
# define OLD_VAL 0
|
||||
#endif
|
||||
|
||||
#if 0 /* test-only */
|
||||
#define FPGA_WRITE_1 { \
|
||||
SET_FPGA(OLD_VAL | FPGA_PRG | 0 | FPGA_DATA); /* set clock to 0 */ \
|
||||
SET_FPGA(OLD_VAL | FPGA_PRG | 0 | FPGA_DATA); /* set data to 1 */ \
|
||||
SET_FPGA(OLD_VAL | FPGA_PRG | FPGA_CLK | FPGA_DATA); /* set clock to 1 */ \
|
||||
SET_FPGA(OLD_VAL | FPGA_PRG | FPGA_CLK | FPGA_DATA);} /* set data to 1 */
|
||||
|
||||
#define FPGA_WRITE_0 { \
|
||||
SET_FPGA(OLD_VAL | FPGA_PRG | 0 | FPGA_DATA); /* set clock to 0 */ \
|
||||
SET_FPGA(OLD_VAL | FPGA_PRG | 0 | 0 ); /* set data to 0 */ \
|
||||
SET_FPGA(OLD_VAL | FPGA_PRG | FPGA_CLK | 0 ); /* set clock to 1 */ \
|
||||
SET_FPGA(OLD_VAL | FPGA_PRG | FPGA_CLK | FPGA_DATA);} /* set data to 1 */
|
||||
#else
|
||||
#define FPGA_WRITE_1 { \
|
||||
SET_FPGA(OLD_VAL | FPGA_PRG | 0 | FPGA_DATA); /* set data to 1 */ \
|
||||
SET_FPGA(OLD_VAL | FPGA_PRG | FPGA_CLK | FPGA_DATA);} /* set data to 1 */
|
||||
|
||||
#define FPGA_WRITE_0 { \
|
||||
SET_FPGA(OLD_VAL | FPGA_PRG | 0 | 0 ); /* set data to 0 */ \
|
||||
SET_FPGA(OLD_VAL | FPGA_PRG | FPGA_CLK | 0 );} /* set data to 1 */
|
||||
#endif
|
||||
|
||||
static int fpga_boot(unsigned char *fpgadata, int size)
|
||||
{
|
||||
int i,index,len;
|
||||
int count;
|
||||
int j;
|
||||
|
||||
/* display infos on fpgaimage */
|
||||
index = 15;
|
||||
for (i=0; i<4; i++) {
|
||||
len = fpgadata[index];
|
||||
DBG("FPGA: %s\n", &(fpgadata[index+1]));
|
||||
index += len+3;
|
||||
}
|
||||
|
||||
/* search for preamble 0xFFFFFFFF */
|
||||
while (1) {
|
||||
if ((fpgadata[index] == 0xff) && (fpgadata[index+1] == 0xff) &&
|
||||
(fpgadata[index+2] == 0xff) && (fpgadata[index+3] == 0xff))
|
||||
break; /* preamble found */
|
||||
else
|
||||
index++;
|
||||
}
|
||||
|
||||
DBG("FPGA: configdata starts at position 0x%x\n",index);
|
||||
DBG("FPGA: length of fpga-data %d\n", size-index);
|
||||
|
||||
/*
|
||||
* Setup port pins for fpga programming
|
||||
*/
|
||||
SET_FPGA(FPGA_PRG | FPGA_CLK | FPGA_DATA); /* set pins to high */
|
||||
|
||||
DBG("%s, ",(FPGA_DONE_STATE == 0) ? "NOT DONE" : "DONE" );
|
||||
DBG("%s\n",(FPGA_INIT_STATE == 0) ? "NOT INIT" : "INIT" );
|
||||
|
||||
/*
|
||||
* Init fpga by asserting and deasserting PROGRAM*
|
||||
*/
|
||||
SET_FPGA(0 | FPGA_CLK | FPGA_DATA); /* set prog active */
|
||||
|
||||
/* Wait for FPGA init line low */
|
||||
count = 0;
|
||||
while (FPGA_INIT_STATE) {
|
||||
udelay(1000); /* wait 1ms */
|
||||
/* Check for timeout - 100us max, so use 3ms */
|
||||
if (count++ > 3) {
|
||||
DBG("FPGA: Booting failed!\n");
|
||||
return ERROR_FPGA_PRG_INIT_LOW;
|
||||
}
|
||||
}
|
||||
|
||||
DBG("%s, ",(FPGA_DONE_STATE == 0) ? "NOT DONE" : "DONE" );
|
||||
DBG("%s\n",(FPGA_INIT_STATE == 0) ? "NOT INIT" : "INIT" );
|
||||
|
||||
/* deassert PROGRAM* */
|
||||
SET_FPGA(FPGA_PRG | FPGA_CLK | FPGA_DATA); /* set prog inactive */
|
||||
|
||||
/* Wait for FPGA end of init period . */
|
||||
count = 0;
|
||||
while (!(FPGA_INIT_STATE)) {
|
||||
udelay(1000); /* wait 1ms */
|
||||
/* Check for timeout */
|
||||
if (count++ > 3) {
|
||||
DBG("FPGA: Booting failed!\n");
|
||||
return ERROR_FPGA_PRG_INIT_HIGH;
|
||||
}
|
||||
}
|
||||
|
||||
DBG("%s, ",(FPGA_DONE_STATE == 0) ? "NOT DONE" : "DONE" );
|
||||
DBG("%s\n",(FPGA_INIT_STATE == 0) ? "NOT INIT" : "INIT" );
|
||||
|
||||
DBG("write configuration data into fpga\n");
|
||||
/* write configuration-data into fpga... */
|
||||
|
||||
/*
|
||||
* Load uncompressed image into fpga
|
||||
*/
|
||||
for (i=index; i<size; i++) {
|
||||
for (j=0; j<8; j++) {
|
||||
if ((fpgadata[i] & 0x80) == 0x80) {
|
||||
FPGA_WRITE_1;
|
||||
} else {
|
||||
FPGA_WRITE_0;
|
||||
}
|
||||
fpgadata[i] <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
DBG("%s, ",(FPGA_DONE_STATE == 0) ? "NOT DONE" : "DONE" );
|
||||
DBG("%s\n",(FPGA_INIT_STATE == 0) ? "NOT INIT" : "INIT" );
|
||||
|
||||
/*
|
||||
* Check if fpga's DONE signal - correctly booted ?
|
||||
*/
|
||||
|
||||
/* Wait for FPGA end of programming period . */
|
||||
count = 0;
|
||||
while (!(FPGA_DONE_STATE)) {
|
||||
udelay(1000); /* wait 1ms */
|
||||
/* Check for timeout */
|
||||
if (count++ > 3) {
|
||||
DBG("FPGA: Booting failed!\n");
|
||||
return ERROR_FPGA_PRG_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
DBG("FPGA: Booting successful!\n");
|
||||
return 0;
|
||||
}
|
46
board/prodrive/pdnb3/Makefile
Normal file
46
board/prodrive/pdnb3/Makefile
Normal file
@ -0,0 +1,46 @@
|
||||
#
|
||||
# (C) Copyright 2006
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
#
|
||||
# See file CREDITS for list of people who contributed to this
|
||||
# project.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of
|
||||
# the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
# MA 02111-1307 USA
|
||||
#
|
||||
|
||||
include $(TOPDIR)/config.mk
|
||||
|
||||
LIB = lib$(BOARD).a
|
||||
|
||||
OBJS := flash.o pdnb3.o nand.o
|
||||
|
||||
$(LIB): $(OBJS) $(SOBJS)
|
||||
$(AR) crv $@ $^
|
||||
|
||||
clean:
|
||||
rm -f $(SOBJS) $(OBJS)
|
||||
|
||||
distclean: clean
|
||||
rm -f $(LIB) core *.bak .depend
|
||||
|
||||
#########################################################################
|
||||
|
||||
.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
|
||||
$(CC) -M $(CPPFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
|
||||
|
||||
-include .depend
|
||||
|
||||
#########################################################################
|
4
board/prodrive/pdnb3/config.mk
Normal file
4
board/prodrive/pdnb3/config.mk
Normal file
@ -0,0 +1,4 @@
|
||||
TEXT_BASE = 0x01f00000
|
||||
|
||||
# include NPE ethernet driver
|
||||
BOARDLIBS = cpu/ixp/npe/libnpe.a
|
85
board/prodrive/pdnb3/flash.c
Normal file
85
board/prodrive/pdnb3/flash.c
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* (C) Copyright 2006
|
||||
* Stefan Roese, DENX Software Engineering, sr@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/arch/ixp425.h>
|
||||
|
||||
/*
|
||||
* include common flash code (for esd boards)
|
||||
*/
|
||||
#include "../common/flash.c"
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
static ulong flash_get_size (vu_long * addr, flash_info_t * info);
|
||||
|
||||
static inline ulong ld(ulong x)
|
||||
{
|
||||
ulong k = 0;
|
||||
|
||||
while (x >>= 1)
|
||||
++k;
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
unsigned long flash_init(void)
|
||||
{
|
||||
unsigned long size;
|
||||
int i;
|
||||
|
||||
/* Init: no FLASHes known */
|
||||
for (i=0; i<CFG_MAX_FLASH_BANKS; i++)
|
||||
flash_info[i].flash_id = FLASH_UNKNOWN;
|
||||
|
||||
size = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
|
||||
|
||||
if (flash_info[0].flash_id == FLASH_UNKNOWN)
|
||||
printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
|
||||
size, size<<20);
|
||||
|
||||
/* Reconfigure CS0 to actual FLASH size */
|
||||
*IXP425_EXP_CS0 = (*IXP425_EXP_CS0 & ~0x00003C00) | ((ld(size) - 9) << 10);
|
||||
|
||||
/* Monitor protection ON by default */
|
||||
flash_protect(FLAG_PROTECT_SET,
|
||||
CFG_MONITOR_BASE, CFG_MONITOR_BASE + monitor_flash_len - 1,
|
||||
&flash_info[CFG_MAX_FLASH_BANKS - 1]);
|
||||
|
||||
/* Environment protection ON by default */
|
||||
flash_protect(FLAG_PROTECT_SET,
|
||||
CFG_ENV_ADDR,
|
||||
CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1,
|
||||
&flash_info[CFG_MAX_FLASH_BANKS - 1]);
|
||||
|
||||
/* Redundant environment protection ON by default */
|
||||
flash_protect(FLAG_PROTECT_SET,
|
||||
CFG_ENV_ADDR_REDUND,
|
||||
CFG_ENV_ADDR_REDUND + CFG_ENV_SIZE_REDUND - 1,
|
||||
&flash_info[CFG_MAX_FLASH_BANKS - 1]);
|
||||
|
||||
flash_info[0].size = size;
|
||||
|
||||
return size;
|
||||
}
|
171
board/prodrive/pdnb3/nand.c
Normal file
171
board/prodrive/pdnb3/nand.c
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* (C) Copyright 2006
|
||||
* Stefan Roese, DENX Software Engineering, sr@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
|
||||
|
||||
#include <nand.h>
|
||||
|
||||
struct pdnb3_ndfc_regs {
|
||||
uchar cmd;
|
||||
uchar wait;
|
||||
uchar addr;
|
||||
uchar term;
|
||||
uchar data;
|
||||
};
|
||||
|
||||
static u8 hwctl;
|
||||
static struct pdnb3_ndfc_regs *pdnb3_ndfc;
|
||||
|
||||
#define readb(addr) *(volatile u_char *)(addr)
|
||||
#define readl(addr) *(volatile u_long *)(addr)
|
||||
#define writeb(d,addr) *(volatile u_char *)(addr) = (d)
|
||||
|
||||
/*
|
||||
* The PDNB3 has a NAND Flash Controller (NDFC) that handles all accesses to
|
||||
* the NAND devices. The NDFC has command, address and data registers that
|
||||
* when accessed will set up the NAND flash pins appropriately. We'll use the
|
||||
* hwcontrol function to save the configuration in a global variable.
|
||||
* We can then use this information in the read and write functions to
|
||||
* determine which NDFC register to access.
|
||||
*
|
||||
* There is one NAND devices on the board, a Hynix HY27US08561A (32 MByte).
|
||||
*/
|
||||
static void pdnb3_nand_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
{
|
||||
switch (cmd) {
|
||||
case NAND_CTL_SETCLE:
|
||||
hwctl |= 0x1;
|
||||
break;
|
||||
case NAND_CTL_CLRCLE:
|
||||
hwctl &= ~0x1;
|
||||
break;
|
||||
|
||||
case NAND_CTL_SETALE:
|
||||
hwctl |= 0x2;
|
||||
break;
|
||||
case NAND_CTL_CLRALE:
|
||||
hwctl &= ~0x2;
|
||||
break;
|
||||
|
||||
case NAND_CTL_SETNCE:
|
||||
break;
|
||||
case NAND_CTL_CLRNCE:
|
||||
writeb(0x00, &(pdnb3_ndfc->term));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void pdnb3_nand_write_byte(struct mtd_info *mtd, u_char byte)
|
||||
{
|
||||
if (hwctl & 0x1)
|
||||
writeb(byte, &(pdnb3_ndfc->cmd));
|
||||
else if (hwctl & 0x2)
|
||||
writeb(byte, &(pdnb3_ndfc->addr));
|
||||
else
|
||||
writeb(byte, &(pdnb3_ndfc->data));
|
||||
}
|
||||
|
||||
static u_char pdnb3_nand_read_byte(struct mtd_info *mtd)
|
||||
{
|
||||
return readb(&(pdnb3_ndfc->data));
|
||||
}
|
||||
|
||||
static void pdnb3_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (hwctl & 0x1)
|
||||
writeb(buf[i], &(pdnb3_ndfc->cmd));
|
||||
else if (hwctl & 0x2)
|
||||
writeb(buf[i], &(pdnb3_ndfc->addr));
|
||||
else
|
||||
writeb(buf[i], &(pdnb3_ndfc->data));
|
||||
}
|
||||
}
|
||||
|
||||
static void pdnb3_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (len % 4) {
|
||||
for (i = 0; i < len; i++)
|
||||
buf[i] = readb(&(pdnb3_ndfc->data));
|
||||
} else {
|
||||
ulong *ptr = (ulong *)buf;
|
||||
int count = len >> 2;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
*ptr++ = readl(&(pdnb3_ndfc->data));
|
||||
}
|
||||
}
|
||||
|
||||
static int pdnb3_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
if (buf[i] != readb(&(pdnb3_ndfc->data)))
|
||||
return i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pdnb3_nand_dev_ready(struct mtd_info *mtd)
|
||||
{
|
||||
volatile u_char val;
|
||||
|
||||
/*
|
||||
* Blocking read to wait for NAND to be ready
|
||||
*/
|
||||
val = readb(&(pdnb3_ndfc->wait));
|
||||
|
||||
/*
|
||||
* Return always true
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
void board_nand_init(struct nand_chip *nand)
|
||||
{
|
||||
pdnb3_ndfc = (struct pdnb3_ndfc_regs *)CFG_NAND_BASE;
|
||||
|
||||
nand->eccmode = NAND_ECC_SOFT;
|
||||
|
||||
/* Set address of NAND IO lines (Using Linear Data Access Region) */
|
||||
nand->IO_ADDR_R = (void __iomem *) ((ulong) pdnb3_ndfc + 0x4);
|
||||
nand->IO_ADDR_W = (void __iomem *) ((ulong) pdnb3_ndfc + 0x4);
|
||||
/* Reference hardware control function */
|
||||
nand->hwcontrol = pdnb3_nand_hwcontrol;
|
||||
/* Set command delay time */
|
||||
nand->hwcontrol = pdnb3_nand_hwcontrol;
|
||||
nand->write_byte = pdnb3_nand_write_byte;
|
||||
nand->read_byte = pdnb3_nand_read_byte;
|
||||
nand->write_buf = pdnb3_nand_write_buf;
|
||||
nand->read_buf = pdnb3_nand_read_buf;
|
||||
nand->verify_buf = pdnb3_nand_verify_buf;
|
||||
nand->dev_ready = pdnb3_nand_dev_ready;
|
||||
}
|
||||
#endif
|
249
board/prodrive/pdnb3/pdnb3.c
Normal file
249
board/prodrive/pdnb3/pdnb3.c
Normal file
@ -0,0 +1,249 @@
|
||||
/*
|
||||
* (C) Copyright 2006
|
||||
* Stefan Roese, DENX Software Engineering, sr@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <malloc.h>
|
||||
#include <asm/arch/ixp425.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/* Prototypes */
|
||||
int gunzip(void *, int, unsigned char *, unsigned long *);
|
||||
int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
|
||||
|
||||
/* predefine these here for FPGA programming (before including fpga.c) */
|
||||
#define SET_FPGA(data) *IXP425_GPIO_GPOUTR = (data)
|
||||
#define FPGA_DONE_STATE (*IXP425_GPIO_GPINR & CFG_FPGA_DONE)
|
||||
#define FPGA_INIT_STATE (*IXP425_GPIO_GPINR & CFG_FPGA_INIT)
|
||||
#define OLD_VAL old_val
|
||||
|
||||
static unsigned long old_val = 0;
|
||||
|
||||
/*
|
||||
* include common fpga code (for prodrive boards)
|
||||
*/
|
||||
#include "../common/fpga.c"
|
||||
|
||||
/*
|
||||
* Miscelaneous platform dependent initialisations
|
||||
*/
|
||||
int board_post_init(void)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
int board_init(void)
|
||||
{
|
||||
/* arch number of PDNB3 */
|
||||
gd->bd->bi_arch_number = MACH_TYPE_PDNB3;
|
||||
|
||||
/* adress of boot parameters */
|
||||
gd->bd->bi_boot_params = 0x00000100;
|
||||
|
||||
GPIO_OUTPUT_SET(CFG_GPIO_FPGA_RESET);
|
||||
GPIO_OUTPUT_ENABLE(CFG_GPIO_FPGA_RESET);
|
||||
|
||||
GPIO_OUTPUT_SET(CFG_GPIO_SYS_RUNNING);
|
||||
GPIO_OUTPUT_ENABLE(CFG_GPIO_SYS_RUNNING);
|
||||
|
||||
/*
|
||||
* Setup GPIO's for FPGA programming
|
||||
*/
|
||||
GPIO_OUTPUT_CLEAR(CFG_GPIO_PRG);
|
||||
GPIO_OUTPUT_CLEAR(CFG_GPIO_CLK);
|
||||
GPIO_OUTPUT_CLEAR(CFG_GPIO_DATA);
|
||||
GPIO_OUTPUT_ENABLE(CFG_GPIO_PRG);
|
||||
GPIO_OUTPUT_ENABLE(CFG_GPIO_CLK);
|
||||
GPIO_OUTPUT_ENABLE(CFG_GPIO_DATA);
|
||||
GPIO_OUTPUT_DISABLE(CFG_GPIO_INIT);
|
||||
GPIO_OUTPUT_DISABLE(CFG_GPIO_DONE);
|
||||
|
||||
/*
|
||||
* Setup GPIO's for interrupts
|
||||
*/
|
||||
GPIO_OUTPUT_DISABLE(CFG_GPIO_PCI_INTA);
|
||||
GPIO_INT_ACT_LOW_SET(CFG_GPIO_PCI_INTA);
|
||||
GPIO_OUTPUT_DISABLE(CFG_GPIO_PCI_INTB);
|
||||
GPIO_INT_ACT_LOW_SET(CFG_GPIO_PCI_INTB);
|
||||
GPIO_OUTPUT_DISABLE(CFG_GPIO_RESTORE_INT);
|
||||
GPIO_INT_ACT_LOW_SET(CFG_GPIO_RESTORE_INT);
|
||||
GPIO_OUTPUT_DISABLE(CFG_GPIO_RESTART_INT);
|
||||
GPIO_INT_ACT_LOW_SET(CFG_GPIO_RESTART_INT);
|
||||
|
||||
/*
|
||||
* Setup GPIO's for 33MHz clock output
|
||||
*/
|
||||
*IXP425_GPIO_GPCLKR = 0x01FF0000;
|
||||
GPIO_OUTPUT_ENABLE(CFG_GPIO_CLK_33M);
|
||||
|
||||
/*
|
||||
* Setup other chip select's
|
||||
*/
|
||||
*IXP425_EXP_CS1 = CFG_EXP_CS1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check Board Identity
|
||||
*/
|
||||
int checkboard(void)
|
||||
{
|
||||
char *s = getenv("serial#");
|
||||
|
||||
puts("Board: PDNB3");
|
||||
|
||||
if (s != NULL) {
|
||||
puts(", serial# ");
|
||||
puts(s);
|
||||
}
|
||||
putc('\n');
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int dram_init(void)
|
||||
{
|
||||
gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
|
||||
gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int do_fpga_boot(unsigned char *fpgadata)
|
||||
{
|
||||
unsigned char *dst;
|
||||
int status;
|
||||
int index;
|
||||
int i;
|
||||
ulong len = CFG_MALLOC_LEN;
|
||||
|
||||
/*
|
||||
* Setup GPIO's for FPGA programming
|
||||
*/
|
||||
GPIO_OUTPUT_CLEAR(CFG_GPIO_PRG);
|
||||
GPIO_OUTPUT_CLEAR(CFG_GPIO_CLK);
|
||||
GPIO_OUTPUT_CLEAR(CFG_GPIO_DATA);
|
||||
|
||||
/*
|
||||
* Save value so no readback is required upon programming
|
||||
*/
|
||||
old_val = *IXP425_GPIO_GPOUTR;
|
||||
|
||||
/*
|
||||
* First try to decompress fpga image (gzip compressed?)
|
||||
*/
|
||||
dst = malloc(CFG_FPGA_MAX_SIZE);
|
||||
if (gunzip(dst, CFG_FPGA_MAX_SIZE, (uchar *)fpgadata, &len) != 0) {
|
||||
printf("Error: Image has to be gzipp'ed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = fpga_boot(dst, len);
|
||||
if (status != 0) {
|
||||
printf("\nFPGA: Booting failed ");
|
||||
switch (status) {
|
||||
case ERROR_FPGA_PRG_INIT_LOW:
|
||||
printf("(Timeout: INIT not low after asserting PROGRAM*)\n ");
|
||||
break;
|
||||
case ERROR_FPGA_PRG_INIT_HIGH:
|
||||
printf("(Timeout: INIT not high after deasserting PROGRAM*)\n ");
|
||||
break;
|
||||
case ERROR_FPGA_PRG_DONE:
|
||||
printf("(Timeout: DONE not high after programming FPGA)\n ");
|
||||
break;
|
||||
}
|
||||
|
||||
/* display infos on fpgaimage */
|
||||
index = 15;
|
||||
for (i=0; i<4; i++) {
|
||||
len = dst[index];
|
||||
printf("FPGA: %s\n", &(dst[index+1]));
|
||||
index += len+3;
|
||||
}
|
||||
putc ('\n');
|
||||
/* delayed reboot */
|
||||
for (i=5; i>0; i--) {
|
||||
printf("Rebooting in %2d seconds \r",i);
|
||||
for (index=0;index<1000;index++)
|
||||
udelay(1000);
|
||||
}
|
||||
putc('\n');
|
||||
do_reset(NULL, 0, 0, NULL);
|
||||
}
|
||||
|
||||
puts("FPGA: ");
|
||||
|
||||
/* display infos on fpgaimage */
|
||||
index = 15;
|
||||
for (i=0; i<4; i++) {
|
||||
len = dst[index];
|
||||
printf("%s ", &(dst[index+1]));
|
||||
index += len+3;
|
||||
}
|
||||
putc('\n');
|
||||
|
||||
free(dst);
|
||||
|
||||
/*
|
||||
* Reset FPGA
|
||||
*/
|
||||
GPIO_OUTPUT_CLEAR(CFG_GPIO_FPGA_RESET);
|
||||
udelay(10);
|
||||
GPIO_OUTPUT_SET(CFG_GPIO_FPGA_RESET);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
ulong addr;
|
||||
|
||||
if (argc < 2) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
addr = simple_strtoul(argv[1], NULL, 16);
|
||||
|
||||
return do_fpga_boot((unsigned char *)addr);
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
fpga, 2, 0, do_fpga,
|
||||
"fpga - boot FPGA\n",
|
||||
"address size\n - boot FPGA with gzipped image at <address>\n"
|
||||
);
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_PCI) || defined(CONFIG_PCI)
|
||||
extern struct pci_controller hose;
|
||||
extern void pci_ixp_init(struct pci_controller * hose);
|
||||
|
||||
void pci_init_board(void)
|
||||
{
|
||||
extern void pci_ixp_init (struct pci_controller *hose);
|
||||
|
||||
pci_ixp_init(&hose);
|
||||
}
|
||||
#endif
|
56
board/prodrive/pdnb3/u-boot.lds
Normal file
56
board/prodrive/pdnb3/u-boot.lds
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* (C) Copyright 2006
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
OUTPUT_FORMAT("elf32-bigarm", "elf32-bigarm", "elf32-bigarm")
|
||||
OUTPUT_ARCH(arm)
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x00000000;
|
||||
|
||||
. = ALIGN(4);
|
||||
.text :
|
||||
{
|
||||
cpu/ixp/start.o (.text)
|
||||
*(.text)
|
||||
}
|
||||
|
||||
. = ALIGN(4);
|
||||
.rodata : { *(.rodata) }
|
||||
|
||||
. = ALIGN(4);
|
||||
.data : { *(.data) }
|
||||
|
||||
. = ALIGN(4);
|
||||
.got : { *(.got) }
|
||||
|
||||
. = .;
|
||||
__u_boot_cmd_start = .;
|
||||
.u_boot_cmd : { *(.u_boot_cmd) }
|
||||
__u_boot_cmd_end = .;
|
||||
|
||||
. = ALIGN(4);
|
||||
__bss_start = .;
|
||||
.bss : { *(.bss) }
|
||||
_end = .;
|
||||
}
|
@ -47,8 +47,7 @@ long int initdram (int board_type) {
|
||||
* Check to see if the SDRAM has already been initialized
|
||||
* by a run control tool
|
||||
*/
|
||||
if (!(mbar_readLong(MCF_SDRAMC_DACR0) & MCF_SDRAMC_DACRn_RE))
|
||||
{
|
||||
if (!(mbar_readLong(MCF_SDRAMC_DACR0) & MCF_SDRAMC_DACRn_RE)) {
|
||||
/*
|
||||
* Initialize DRAM Control Register: DCR
|
||||
*/
|
||||
@ -67,7 +66,7 @@ long int initdram (int board_type) {
|
||||
/*
|
||||
* Initialize DMR0
|
||||
*/
|
||||
mbar_writeLong(MCF_SDRAMC_DMR0,
|
||||
mbar_writeLong(MCF_SDRAMC_DMR0,
|
||||
MCF_SDRAMC_DMRn_BAM_8M
|
||||
| MCF_SDRAMC_DMRn_V);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* (C) Copyright 2000-2004
|
||||
* (C) Copyright 2000-2006
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
@ -124,6 +124,9 @@ int checkboard (void)
|
||||
break;
|
||||
putc (*s);
|
||||
}
|
||||
#ifdef CONFIG_VIRTLAB2
|
||||
puts (" (Virtlab2)");
|
||||
#endif
|
||||
putc ('\n');
|
||||
|
||||
return (0);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* (C) Copyright 2000-2004
|
||||
* (C) Copyright 2000-2006
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
@ -718,7 +718,8 @@ static int hardware_disable(int slot)
|
||||
/* SC8xx Boards by SinoVee Microsystems */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
#if defined(CONFIG_TQM8xxL) || defined(CONFIG_SVM_SC8xx)
|
||||
#if (defined(CONFIG_TQM8xxL) || defined(CONFIG_SVM_SC8xx)) \
|
||||
&& !defined(CONFIG_VIRTLAB2)
|
||||
|
||||
#if defined(CONFIG_TQM8xxL)
|
||||
#define PCMCIA_BOARD_MSG "TQM8xxL"
|
||||
@ -1021,6 +1022,183 @@ done:
|
||||
|
||||
#endif /* TQM8xxL */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Virtlab2 Board by TQ Components */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
#if defined(CONFIG_VIRTLAB2)
|
||||
#define PCMCIA_BOARD_MSG "Virtlab2"
|
||||
|
||||
static int hardware_enable(int slot)
|
||||
{
|
||||
volatile pcmconf8xx_t *pcmp =
|
||||
(pcmconf8xx_t *)&(((immap_t *)CFG_IMMR)->im_pcmcia);
|
||||
volatile unsigned char *powerctl =
|
||||
(volatile unsigned char *)PCMCIA_CTRL;
|
||||
volatile sysconf8xx_t *sysp =
|
||||
(sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf));
|
||||
unsigned int reg, mask;
|
||||
|
||||
debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
|
||||
|
||||
udelay(10000);
|
||||
|
||||
/*
|
||||
* Configure SIUMCR to enable PCMCIA port B
|
||||
*/
|
||||
sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */
|
||||
|
||||
/* clear interrupt state, and disable interrupts */
|
||||
pcmp->pcmc_pscr = PCMCIA_MASK(slot);
|
||||
pcmp->pcmc_per &= ~PCMCIA_MASK(slot);
|
||||
|
||||
/*
|
||||
* Disable interrupts, DMA, and PCMCIA buffers
|
||||
* (isolate the interface) and assert RESET signal
|
||||
*/
|
||||
debug ("Disable PCMCIA buffers and assert RESET\n");
|
||||
reg = __MY_PCMCIA_GCRX_CXRESET; /* active high */
|
||||
reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
|
||||
|
||||
PCMCIA_PGCRX(slot) = reg;
|
||||
udelay(500);
|
||||
|
||||
/* remove all power */
|
||||
*powerctl = 0;
|
||||
|
||||
/*
|
||||
* Make sure there is a card in the slot, then configure the interface.
|
||||
*/
|
||||
udelay(10000);
|
||||
debug ("[%d] %s: PIPR(%p)=0x%x\n", __LINE__,__FUNCTION__,
|
||||
&(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
|
||||
|
||||
if (pcmp->pcmc_pipr & (0x18000000 >> (slot << 4))) {
|
||||
printf (" No Card found\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Power On.
|
||||
*/
|
||||
mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
|
||||
reg = pcmp->pcmc_pipr;
|
||||
debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n", reg,
|
||||
(reg&PCMCIA_VS1(slot))?"n":"ff",
|
||||
(reg&PCMCIA_VS2(slot))?"n":"ff");
|
||||
|
||||
if ((reg & mask) == mask) {
|
||||
*powerctl = 2; /* Enable 5V Vccout */
|
||||
puts (" 5.0V card found: ");
|
||||
} else {
|
||||
*powerctl = 1; /* Enable 3.3 V Vccout */
|
||||
puts (" 3.3V card found: ");
|
||||
}
|
||||
|
||||
udelay(1000);
|
||||
debug ("Enable PCMCIA buffers and stop RESET\n");
|
||||
reg = PCMCIA_PGCRX(slot);
|
||||
reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
|
||||
reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
|
||||
|
||||
PCMCIA_PGCRX(slot) = reg;
|
||||
|
||||
udelay(250000); /* some cards need >150 ms to come up :-( */
|
||||
|
||||
debug ("# hardware_enable done\n");
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
|
||||
static int hardware_disable(int slot)
|
||||
{
|
||||
volatile unsigned char *powerctl =
|
||||
(volatile unsigned char *)PCMCIA_CTRL;
|
||||
unsigned long reg;
|
||||
|
||||
debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
|
||||
|
||||
/* remove all power */
|
||||
*powerctl = 0;
|
||||
|
||||
debug ("Disable PCMCIA buffers and assert RESET\n");
|
||||
reg = __MY_PCMCIA_GCRX_CXRESET; /* active high */
|
||||
reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
|
||||
|
||||
PCMCIA_PGCRX(slot) = reg;
|
||||
|
||||
udelay(10000);
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int voltage_set(int slot, int vcc, int vpp)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
volatile pcmconf8xx_t *pcmp =
|
||||
(pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
|
||||
#endif
|
||||
volatile unsigned char *powerctl =
|
||||
(volatile unsigned char *)PCMCIA_CTRL;
|
||||
unsigned long reg;
|
||||
|
||||
debug ("voltage_set: " PCMCIA_BOARD_MSG
|
||||
" Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
|
||||
'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
|
||||
|
||||
/*
|
||||
* Disable PCMCIA buffers (isolate the interface)
|
||||
* and assert RESET signal
|
||||
*/
|
||||
debug ("Disable PCMCIA buffers and assert RESET\n");
|
||||
reg = PCMCIA_PGCRX(slot);
|
||||
reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
|
||||
reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
|
||||
|
||||
PCMCIA_PGCRX(slot) = reg;
|
||||
udelay(500);
|
||||
|
||||
/*
|
||||
* Configure pins for 5 Volts Enable and 3 Volts enable,
|
||||
* Turn off all power.
|
||||
*/
|
||||
debug ("PCMCIA power OFF\n");
|
||||
reg = 0;
|
||||
switch(vcc) {
|
||||
case 0: break;
|
||||
case 33: reg = 0x0001; break;
|
||||
case 50: reg = 0x0002; break;
|
||||
default: goto done;
|
||||
}
|
||||
|
||||
/* Checking supported voltages */
|
||||
|
||||
debug ("PIPR: 0x%x --> %s\n", pcmp->pcmc_pipr,
|
||||
(pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V");
|
||||
|
||||
*powerctl = reg;
|
||||
|
||||
if (reg) {
|
||||
debug ("PCMCIA powered at %sV\n", (reg&0x0004) ? "5.0" : "3.3");
|
||||
} else {
|
||||
debug ("PCMCIA powered down\n");
|
||||
}
|
||||
|
||||
done:
|
||||
debug ("Enable PCMCIA buffers and stop RESET\n");
|
||||
reg = PCMCIA_PGCRX(slot);
|
||||
reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
|
||||
reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
|
||||
|
||||
PCMCIA_PGCRX(slot) = reg;
|
||||
udelay(500);
|
||||
|
||||
debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n", slot+'A');
|
||||
return (0);
|
||||
}
|
||||
#endif /* CONFIG_VIRTLAB2 */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* LWMON Board */
|
||||
|
@ -33,6 +33,9 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
#endif
|
||||
#ifdef CONFIG_IXP425 /* only valid for IXP425 */
|
||||
#include <asm/arch/ixp425.h>
|
||||
#endif
|
||||
#include <i2c.h>
|
||||
|
||||
#if defined(CONFIG_SOFT_I2C)
|
||||
|
@ -379,13 +379,13 @@ xyzModem_get_hdr(void)
|
||||
}
|
||||
|
||||
/* Header found, now read the data */
|
||||
res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, &xyz.blk);
|
||||
res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, (char *)&xyz.blk);
|
||||
ZM_DEBUG(zm_save(xyz.blk));
|
||||
if (!res) {
|
||||
ZM_DEBUG(zm_dump(__LINE__));
|
||||
return xyzModem_timeout;
|
||||
}
|
||||
res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, &xyz.cblk);
|
||||
res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, (char *)&xyz.cblk);
|
||||
ZM_DEBUG(zm_save(xyz.cblk));
|
||||
if (!res) {
|
||||
ZM_DEBUG(zm_dump(__LINE__));
|
||||
@ -403,14 +403,14 @@ xyzModem_get_hdr(void)
|
||||
return xyzModem_timeout;
|
||||
}
|
||||
}
|
||||
res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, &xyz.crc1);
|
||||
res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, (char *)&xyz.crc1);
|
||||
ZM_DEBUG(zm_save(xyz.crc1));
|
||||
if (!res) {
|
||||
ZM_DEBUG(zm_dump(__LINE__));
|
||||
return xyzModem_timeout;
|
||||
}
|
||||
if (xyz.crc_mode) {
|
||||
res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, &xyz.crc2);
|
||||
res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, (char *)&xyz.crc2);
|
||||
ZM_DEBUG(zm_save(xyz.crc2));
|
||||
if (!res) {
|
||||
ZM_DEBUG(zm_dump(__LINE__));
|
||||
@ -450,7 +450,10 @@ xyzModem_get_hdr(void)
|
||||
int
|
||||
xyzModem_stream_open(connection_info_t *info, int *err)
|
||||
{
|
||||
int console_chan, stat=0;
|
||||
#ifdef REDBOOT
|
||||
int console_chan;
|
||||
#endif
|
||||
int stat = 0;
|
||||
int retries = xyzModem_MAX_RETRIES;
|
||||
int crc_retries = xyzModem_MAX_RETRIES_WITH_CRC;
|
||||
|
||||
@ -510,7 +513,7 @@ xyzModem_stream_open(connection_info_t *info, int *err)
|
||||
/* skip filename */
|
||||
while (*xyz.bufp++);
|
||||
/* get the length */
|
||||
parse_num(xyz.bufp, &xyz.file_length, NULL, " ");
|
||||
parse_num((char *)xyz.bufp, &xyz.file_length, NULL, " ");
|
||||
#endif
|
||||
/* The rest of the file name data block quietly discarded */
|
||||
xyz.tx_ack = true;
|
||||
|
@ -143,14 +143,15 @@ CFLAGS := $(CPPFLAGS) -Wall -Wno-trigraphs
|
||||
endif
|
||||
endif
|
||||
|
||||
AFLAGS_DEBUG := -Wa,-gstabs
|
||||
|
||||
# turn jbsr into jsr for m68k
|
||||
ifeq ($(ARCH),m68k)
|
||||
ifeq ($(findstring 3.4,$(shell $(CC) --version)),3.4)
|
||||
AFLAGS_DEBUG := -Wa,-gstabs,-S
|
||||
endif
|
||||
else
|
||||
AFLAGS_DEBUG := -Wa,-gstabs
|
||||
endif
|
||||
|
||||
AFLAGS := $(AFLAGS_DEBUG) -D__ASSEMBLY__ $(CPPFLAGS)
|
||||
|
||||
LDFLAGS += -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS)
|
||||
|
@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk
|
||||
LIB = lib$(CPU).a
|
||||
|
||||
START = start.o
|
||||
OBJS = interrupts.o cpu.o
|
||||
OBJS = interrupts.o cpu.o cpuinfo.o
|
||||
|
||||
all: .depend $(START) $(LIB)
|
||||
|
||||
|
244
cpu/arm926ejs/cpuinfo.c
Normal file
244
cpu/arm926ejs/cpuinfo.c
Normal file
@ -0,0 +1,244 @@
|
||||
/*
|
||||
* OMAP1 CPU identification code
|
||||
*
|
||||
* Copyright (C) 2004 Nokia Corporation
|
||||
* Written by Tony Lindgren <tony@atomide.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <arm926ejs.h>
|
||||
|
||||
#if defined(CONFIG_DISPLAY_CPUINFO) && defined(CONFIG_OMAP)
|
||||
|
||||
#define omap_readw(x) *(volatile unsigned short *)(x)
|
||||
#define omap_readl(x) *(volatile unsigned long *)(x)
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
#define OMAP_DIE_ID_0 0xfffe1800
|
||||
#define OMAP_DIE_ID_1 0xfffe1804
|
||||
#define OMAP_PRODUCTION_ID_0 0xfffe2000
|
||||
#define OMAP_PRODUCTION_ID_1 0xfffe2004
|
||||
#define OMAP32_ID_0 0xfffed400
|
||||
#define OMAP32_ID_1 0xfffed404
|
||||
|
||||
struct omap_id {
|
||||
u16 jtag_id; /* Used to determine OMAP type */
|
||||
u8 die_rev; /* Processor revision */
|
||||
u32 omap_id; /* OMAP revision */
|
||||
u32 type; /* Cpu id bits [31:08], cpu class bits [07:00] */
|
||||
};
|
||||
|
||||
/* Register values to detect the OMAP version */
|
||||
static struct omap_id omap_ids[] = {
|
||||
{ .jtag_id = 0xb574, .die_rev = 0x2, .omap_id = 0x03310315, .type = 0x03100000},
|
||||
{ .jtag_id = 0x355f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300100},
|
||||
{ .jtag_id = 0xb55f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300300},
|
||||
{ .jtag_id = 0xb470, .die_rev = 0x0, .omap_id = 0x03310100, .type = 0x15100000},
|
||||
{ .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x16100000},
|
||||
{ .jtag_id = 0xb576, .die_rev = 0x2, .omap_id = 0x03320100, .type = 0x16110000},
|
||||
{ .jtag_id = 0xb576, .die_rev = 0x3, .omap_id = 0x03320100, .type = 0x16100c00},
|
||||
{ .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320200, .type = 0x16100d00},
|
||||
{ .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00},
|
||||
{ .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00},
|
||||
{ .jtag_id = 0xb576, .die_rev = 0x1, .omap_id = 0x03320100, .type = 0x16110000},
|
||||
{ .jtag_id = 0xb58c, .die_rev = 0x2, .omap_id = 0x03320200, .type = 0x16110b00},
|
||||
{ .jtag_id = 0xb58c, .die_rev = 0x3, .omap_id = 0x03320200, .type = 0x16110c00},
|
||||
{ .jtag_id = 0xb65f, .die_rev = 0x0, .omap_id = 0x03320400, .type = 0x16212300},
|
||||
{ .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320400, .type = 0x16212300},
|
||||
{ .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320500, .type = 0x16212300},
|
||||
{ .jtag_id = 0xb5f7, .die_rev = 0x0, .omap_id = 0x03330000, .type = 0x17100000},
|
||||
{ .jtag_id = 0xb5f7, .die_rev = 0x1, .omap_id = 0x03330100, .type = 0x17100000},
|
||||
{ .jtag_id = 0xb5f7, .die_rev = 0x2, .omap_id = 0x03330100, .type = 0x17100000},
|
||||
};
|
||||
|
||||
/*
|
||||
* Get OMAP type from PROD_ID.
|
||||
* 1710 has the PROD_ID in bits 15:00, not in 16:01 as documented in TRM.
|
||||
* 1510 PROD_ID is empty, and 1610 PROD_ID does not make sense.
|
||||
* Undocumented register in TEST BLOCK is used as fallback; This seems to
|
||||
* work on 1510, 1610 & 1710. The official way hopefully will work in future
|
||||
* processors.
|
||||
*/
|
||||
static u16 omap_get_jtag_id(void)
|
||||
{
|
||||
u32 prod_id, omap_id;
|
||||
|
||||
prod_id = omap_readl(OMAP_PRODUCTION_ID_1);
|
||||
omap_id = omap_readl(OMAP32_ID_1);
|
||||
|
||||
/* Check for unusable OMAP_PRODUCTION_ID_1 on 1611B/5912 and 730 */
|
||||
if (((prod_id >> 20) == 0) || (prod_id == omap_id))
|
||||
prod_id = 0;
|
||||
else
|
||||
prod_id &= 0xffff;
|
||||
|
||||
if (prod_id)
|
||||
return prod_id;
|
||||
|
||||
/* Use OMAP32_ID_1 as fallback */
|
||||
prod_id = ((omap_id >> 12) & 0xffff);
|
||||
|
||||
return prod_id;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get OMAP revision from DIE_REV.
|
||||
* Early 1710 processors may have broken OMAP_DIE_ID, it contains PROD_ID.
|
||||
* Undocumented register in the TEST BLOCK is used as fallback.
|
||||
* REVISIT: This does not seem to work on 1510
|
||||
*/
|
||||
static u8 omap_get_die_rev(void)
|
||||
{
|
||||
u32 die_rev;
|
||||
|
||||
die_rev = omap_readl(OMAP_DIE_ID_1);
|
||||
|
||||
/* Check for broken OMAP_DIE_ID on early 1710 */
|
||||
if (((die_rev >> 12) & 0xffff) == omap_get_jtag_id())
|
||||
die_rev = 0;
|
||||
|
||||
die_rev = (die_rev >> 17) & 0xf;
|
||||
if (die_rev)
|
||||
return die_rev;
|
||||
|
||||
die_rev = (omap_readl(OMAP32_ID_1) >> 28) & 0xf;
|
||||
|
||||
return die_rev;
|
||||
}
|
||||
|
||||
static unsigned long dpll1(void)
|
||||
{
|
||||
unsigned short pll_ctl_val = omap_readw(DPLL_CTL_REG);
|
||||
unsigned long rate;
|
||||
|
||||
rate = CONFIG_SYS_CLK_FREQ; /* Base xtal rate */
|
||||
if (pll_ctl_val & 0x10) {
|
||||
/* PLL enabled, apply multiplier and divisor */
|
||||
if (pll_ctl_val & 0xf80)
|
||||
rate *= (pll_ctl_val & 0xf80) >> 7;
|
||||
rate /= ((pll_ctl_val & 0x60) >> 5) + 1;
|
||||
} else {
|
||||
/* PLL disabled, apply bypass divisor */
|
||||
switch (pll_ctl_val & 0xc) {
|
||||
case 0:
|
||||
break;
|
||||
case 0x4:
|
||||
rate /= 2;
|
||||
break;
|
||||
default:
|
||||
rate /= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
static unsigned long armcore(void)
|
||||
{
|
||||
unsigned short arm_ckctl = omap_readw(ARM_CKCTL);
|
||||
|
||||
return (dpll1() >> ((arm_ckctl & 0x0030) >> 4));
|
||||
}
|
||||
|
||||
int print_cpuinfo (void)
|
||||
{
|
||||
int i;
|
||||
u16 jtag_id;
|
||||
u8 die_rev;
|
||||
u32 omap_id;
|
||||
u8 cpu_type;
|
||||
u32 system_serial_high;
|
||||
u32 system_serial_low;
|
||||
u32 system_rev = 0;
|
||||
|
||||
jtag_id = omap_get_jtag_id();
|
||||
die_rev = omap_get_die_rev();
|
||||
omap_id = omap_readl(OMAP32_ID_0);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("OMAP_DIE_ID_0: 0x%08x\n", omap_readl(OMAP_DIE_ID_0));
|
||||
printf("OMAP_DIE_ID_1: 0x%08x DIE_REV: %i\n",
|
||||
omap_readl(OMAP_DIE_ID_1),
|
||||
(omap_readl(OMAP_DIE_ID_1) >> 17) & 0xf);
|
||||
printf("OMAP_PRODUCTION_ID_0: 0x%08x\n", omap_readl(OMAP_PRODUCTION_ID_0));
|
||||
printf("OMAP_PRODUCTION_ID_1: 0x%08x JTAG_ID: 0x%04x\n",
|
||||
omap_readl(OMAP_PRODUCTION_ID_1),
|
||||
omap_readl(OMAP_PRODUCTION_ID_1) & 0xffff);
|
||||
printf("OMAP32_ID_0: 0x%08x\n", omap_readl(OMAP32_ID_0));
|
||||
printf("OMAP32_ID_1: 0x%08x\n", omap_readl(OMAP32_ID_1));
|
||||
printf("JTAG_ID: 0x%04x DIE_REV: %i\n", jtag_id, die_rev);
|
||||
#endif
|
||||
|
||||
system_serial_high = omap_readl(OMAP_DIE_ID_0);
|
||||
system_serial_low = omap_readl(OMAP_DIE_ID_1);
|
||||
|
||||
/* First check only the major version in a safe way */
|
||||
for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
|
||||
if (jtag_id == (omap_ids[i].jtag_id)) {
|
||||
system_rev = omap_ids[i].type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we can find the die revision */
|
||||
for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
|
||||
if (jtag_id == omap_ids[i].jtag_id && die_rev == omap_ids[i].die_rev) {
|
||||
system_rev = omap_ids[i].type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally check also the omap_id */
|
||||
for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
|
||||
if (jtag_id == omap_ids[i].jtag_id
|
||||
&& die_rev == omap_ids[i].die_rev
|
||||
&& omap_id == omap_ids[i].omap_id) {
|
||||
system_rev = omap_ids[i].type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add the cpu class info (7xx, 15xx, 16xx, 24xx) */
|
||||
cpu_type = system_rev >> 24;
|
||||
|
||||
switch (cpu_type) {
|
||||
case 0x07:
|
||||
system_rev |= 0x07;
|
||||
break;
|
||||
case 0x03:
|
||||
case 0x15:
|
||||
system_rev |= 0x15;
|
||||
break;
|
||||
case 0x16:
|
||||
case 0x17:
|
||||
system_rev |= 0x16;
|
||||
break;
|
||||
case 0x24:
|
||||
system_rev |= 0x24;
|
||||
break;
|
||||
default:
|
||||
printf("Unknown OMAP cpu type: 0x%02x\n", cpu_type);
|
||||
}
|
||||
|
||||
printf("CPU: OMAP%04x", system_rev >> 16);
|
||||
if ((system_rev >> 8) & 0xff)
|
||||
printf("%x", (system_rev >> 8) & 0xff);
|
||||
#ifdef DEBUG
|
||||
printf(" revision %i handled as %02xxx id: %08x%08x",
|
||||
die_rev, system_rev & 0xff, system_serial_low, system_serial_high);
|
||||
#endif
|
||||
printf(" at %ld.%01ld MHz (DPLL1=%ld.%01ld MHz)\n",
|
||||
armcore() / 1000000, (armcore() / 100000) % 10,
|
||||
dpll1() / 1000000, (dpll1() / 100000) % 10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* #if defined(CONFIG_DISPLAY_CPUINFO) && defined(CONFIG_OMAP) */
|
@ -27,7 +27,7 @@ BIG_ENDIAN = y
|
||||
PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 \
|
||||
-msoft-float -mbig-endian
|
||||
|
||||
PLATFORM_CPPFLAGS += -mbig-endian -march=armv4 -mtune=strongarm1100
|
||||
PLATFORM_CPPFLAGS += -mbig-endian -march=armv5te -mtune=strongarm1100
|
||||
# =========================================================================
|
||||
#
|
||||
# Supply options according to compiler version
|
||||
|
@ -34,10 +34,47 @@
|
||||
#include <command.h>
|
||||
#include <asm/arch/ixp425.h>
|
||||
|
||||
ulong loops_per_jiffy;
|
||||
|
||||
#ifdef CONFIG_USE_IRQ
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_DISPLAY_CPUINFO)
|
||||
int print_cpuinfo (void)
|
||||
{
|
||||
unsigned long id;
|
||||
int speed = 0;
|
||||
|
||||
asm ("mrc p15, 0, %0, c0, c0, 0":"=r" (id));
|
||||
|
||||
puts("CPU: Intel IXP425 at ");
|
||||
switch ((id & 0x000003f0) >> 4) {
|
||||
case 0x1c:
|
||||
loops_per_jiffy = 887467;
|
||||
speed = 533;
|
||||
break;
|
||||
|
||||
case 0x1d:
|
||||
loops_per_jiffy = 666016;
|
||||
speed = 400;
|
||||
break;
|
||||
|
||||
case 0x1f:
|
||||
loops_per_jiffy = 442901;
|
||||
speed = 266;
|
||||
break;
|
||||
}
|
||||
|
||||
if (speed)
|
||||
printf("%d MHz\n", speed);
|
||||
else
|
||||
puts("unknown revision\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_DISPLAY_CPUINFO */
|
||||
|
||||
int cpu_init (void)
|
||||
{
|
||||
/*
|
||||
@ -48,7 +85,9 @@ int cpu_init (void)
|
||||
FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ;
|
||||
#endif
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_PCI) || defined (CONFIG_PCI)
|
||||
pci_init();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -154,3 +193,25 @@ void pci_init(void)
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_BOOTCOUNT_LIMIT
|
||||
|
||||
void bootcount_store (ulong a)
|
||||
{
|
||||
volatile ulong *save_addr = (volatile ulong *)(CFG_BOOTCOUNT_ADDR);
|
||||
|
||||
save_addr[0] = a;
|
||||
save_addr[1] = BOOTCOUNT_MAGIC;
|
||||
}
|
||||
|
||||
ulong bootcount_load (void)
|
||||
{
|
||||
volatile ulong *save_addr = (volatile ulong *)(CFG_BOOTCOUNT_ADDR);
|
||||
|
||||
if (save_addr[1] != BOOTCOUNT_MAGIC)
|
||||
return 0;
|
||||
else
|
||||
return save_addr[0];
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BOOTCOUNT_LIMIT */
|
||||
|
@ -1,5 +1,7 @@
|
||||
/* vi: set ts=8 sw=8 noet: */
|
||||
/*
|
||||
* (C) Copyright 2006
|
||||
* Stefan Roese, DENX Software Engineering, sr@denx.de.
|
||||
*
|
||||
* (C) Copyright 2002
|
||||
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
|
||||
* Marius Groeger <mgroeger@sysgo.de>
|
||||
@ -31,22 +33,85 @@
|
||||
#include <asm/arch/ixp425.h>
|
||||
|
||||
#ifdef CONFIG_USE_IRQ
|
||||
/* enable IRQ/FIQ interrupts */
|
||||
void enable_interrupts (void)
|
||||
{
|
||||
#error: interrupts not implemented yet
|
||||
}
|
||||
/*
|
||||
* When interrupts are enabled, use timer 2 for time/delay generation...
|
||||
*/
|
||||
|
||||
#define FREQ 66666666
|
||||
#define CLOCK_TICK_RATE (((FREQ / CFG_HZ & ~IXP425_OST_RELOAD_MASK) + 1) * CFG_HZ)
|
||||
#define LATCH ((CLOCK_TICK_RATE + CFG_HZ/2) / CFG_HZ) /* For divider */
|
||||
|
||||
struct _irq_handler {
|
||||
void *m_data;
|
||||
void (*m_func)( void *data);
|
||||
};
|
||||
|
||||
static struct _irq_handler IRQ_HANDLER[N_IRQS];
|
||||
|
||||
static volatile ulong timestamp;
|
||||
|
||||
/* enable IRQ/FIQ interrupts */
|
||||
void enable_interrupts(void)
|
||||
{
|
||||
unsigned long temp;
|
||||
__asm__ __volatile__("mrs %0, cpsr\n"
|
||||
"bic %0, %0, #0x80\n"
|
||||
"msr cpsr_c, %0"
|
||||
: "=r" (temp)
|
||||
:
|
||||
: "memory");
|
||||
}
|
||||
|
||||
/*
|
||||
* disable IRQ/FIQ interrupts
|
||||
* returns true if interrupts had been enabled before we disabled them
|
||||
*/
|
||||
int disable_interrupts (void)
|
||||
int disable_interrupts(void)
|
||||
{
|
||||
#error: interrupts not implemented yet
|
||||
unsigned long old,temp;
|
||||
__asm__ __volatile__("mrs %0, cpsr\n"
|
||||
"orr %1, %0, #0x80\n"
|
||||
"msr cpsr_c, %1"
|
||||
: "=r" (old), "=r" (temp)
|
||||
:
|
||||
: "memory");
|
||||
return (old & 0x80) == 0;
|
||||
}
|
||||
#else
|
||||
|
||||
static void default_isr(void *data)
|
||||
{
|
||||
printf("default_isr(): called for IRQ %d, Interrupt Status=%x PR=%x\n",
|
||||
(int)data, *IXP425_ICIP, *IXP425_ICIH);
|
||||
}
|
||||
|
||||
static int next_irq(void)
|
||||
{
|
||||
return (((*IXP425_ICIH & 0x000000fc) >> 2) - 1);
|
||||
}
|
||||
|
||||
static void timer_isr(void *data)
|
||||
{
|
||||
unsigned int *pTime = (unsigned int *)data;
|
||||
|
||||
(*pTime)++;
|
||||
|
||||
/*
|
||||
* Reset IRQ source
|
||||
*/
|
||||
*IXP425_OSST = IXP425_OSST_TIMER_2_PEND;
|
||||
}
|
||||
|
||||
ulong get_timer (ulong base)
|
||||
{
|
||||
return timestamp - base;
|
||||
}
|
||||
|
||||
void reset_timer (void)
|
||||
{
|
||||
timestamp = 0;
|
||||
}
|
||||
|
||||
#else /* #ifdef CONFIG_USE_IRQ */
|
||||
void enable_interrupts (void)
|
||||
{
|
||||
return;
|
||||
@ -55,8 +120,7 @@ int disable_interrupts (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #ifdef CONFIG_USE_IRQ */
|
||||
|
||||
void bad_mode (void)
|
||||
{
|
||||
@ -140,19 +204,46 @@ void do_fiq (struct pt_regs *pt_regs)
|
||||
{
|
||||
printf ("fast interrupt request\n");
|
||||
show_regs (pt_regs);
|
||||
bad_mode ();
|
||||
printf("IRQ=%08lx FIQ=%08lx\n", *IXP425_ICIH, *IXP425_ICFH);
|
||||
}
|
||||
|
||||
void do_irq (struct pt_regs *pt_regs)
|
||||
{
|
||||
#ifdef CONFIG_USE_IRQ
|
||||
int irq = next_irq();
|
||||
|
||||
IRQ_HANDLER[irq].m_func(IRQ_HANDLER[irq].m_data);
|
||||
#else
|
||||
printf ("interrupt request\n");
|
||||
show_regs (pt_regs);
|
||||
bad_mode ();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int interrupt_init (void)
|
||||
{
|
||||
/* nothing happens here - we don't setup any IRQs */
|
||||
#ifdef CONFIG_USE_IRQ
|
||||
int i;
|
||||
|
||||
/* install default interrupt handlers */
|
||||
for (i = 0; i < N_IRQS; i++) {
|
||||
IRQ_HANDLER[i].m_data = (void *)i;
|
||||
IRQ_HANDLER[i].m_func = default_isr;
|
||||
}
|
||||
|
||||
/* install interrupt handler for timer */
|
||||
IRQ_HANDLER[IXP425_TIMER_2_IRQ].m_data = (void *)×tamp;
|
||||
IRQ_HANDLER[IXP425_TIMER_2_IRQ].m_func = timer_isr;
|
||||
|
||||
/* setup the Timer counter value */
|
||||
*IXP425_OSRT2 = (LATCH & ~IXP425_OST_RELOAD_MASK) | IXP425_OST_ENABLE;
|
||||
|
||||
/* configure interrupts for IRQ mode */
|
||||
*IXP425_ICLR = 0x00000000;
|
||||
|
||||
/* enable timer irq */
|
||||
*IXP425_ICMR = (1 << IXP425_TIMER_2_IRQ);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
261
cpu/ixp/npe/IxEthAcc.c
Normal file
261
cpu/ixp/npe/IxEthAcc.c
Normal file
@ -0,0 +1,261 @@
|
||||
/**
|
||||
* @file IxEthAcc.c
|
||||
*
|
||||
* @author Intel Corporation
|
||||
* @date 20-Feb-2001
|
||||
*
|
||||
* @brief This file contains the implementation of the IXP425 Ethernet Access Component
|
||||
*
|
||||
* Design Notes:
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "IxEthAcc.h"
|
||||
#ifdef CONFIG_IXP425_COMPONENT_ETHDB
|
||||
#include "IxEthDB.h"
|
||||
#endif
|
||||
#include "IxFeatureCtrl.h"
|
||||
|
||||
#include "IxEthAcc_p.h"
|
||||
#include "IxEthAccMac_p.h"
|
||||
#include "IxEthAccMii_p.h"
|
||||
|
||||
/**
|
||||
* @addtogroup IxEthAcc
|
||||
*@{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief System-wide information data strucure.
|
||||
*
|
||||
* @ingroup IxEthAccPri
|
||||
*
|
||||
*/
|
||||
|
||||
IxEthAccInfo ixEthAccDataInfo;
|
||||
extern PUBLIC IxEthAccMacState ixEthAccMacState[];
|
||||
extern PUBLIC IxOsalMutex ixEthAccControlInterfaceMutex;
|
||||
|
||||
/**
|
||||
* @brief System-wide information
|
||||
*
|
||||
* @ingroup IxEthAccPri
|
||||
*
|
||||
*/
|
||||
BOOL ixEthAccServiceInit = FALSE;
|
||||
|
||||
/* global filtering bit mask */
|
||||
PUBLIC UINT32 ixEthAccNewSrcMask;
|
||||
|
||||
/**
|
||||
* @brief Per port information data strucure.
|
||||
*
|
||||
* @ingroup IxEthAccPri
|
||||
*
|
||||
*/
|
||||
|
||||
IxEthAccPortDataInfo ixEthAccPortData[IX_ETH_ACC_NUMBER_OF_PORTS];
|
||||
|
||||
PUBLIC IxEthAccStatus ixEthAccInit()
|
||||
{
|
||||
#ifdef CONFIG_IXP425_COMPONENT_ETHDB
|
||||
/*
|
||||
* Initialize Control plane
|
||||
*/
|
||||
if (ixEthDBInit() != IX_ETH_ACC_SUCCESS)
|
||||
{
|
||||
IX_ETH_ACC_WARNING_LOG("ixEthAccInit: EthDB init failed\n", 0, 0, 0, 0, 0, 0);
|
||||
|
||||
return IX_ETH_ACC_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (IX_FEATURE_CTRL_SWCONFIG_ENABLED == ixFeatureCtrlSwConfigurationCheck (IX_FEATURECTRL_ETH_LEARNING))
|
||||
{
|
||||
ixEthAccNewSrcMask = (~0); /* want all the bits */
|
||||
}
|
||||
else
|
||||
{
|
||||
ixEthAccNewSrcMask = (~IX_ETHACC_NE_NEWSRCMASK); /* want all but the NewSrc bit */
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize Data plane
|
||||
*/
|
||||
if ( ixEthAccInitDataPlane() != IX_ETH_ACC_SUCCESS )
|
||||
{
|
||||
IX_ETH_ACC_WARNING_LOG("ixEthAccInit: data plane init failed\n", 0, 0, 0, 0, 0, 0);
|
||||
|
||||
return IX_ETH_ACC_FAIL;
|
||||
}
|
||||
|
||||
|
||||
if ( ixEthAccQMgrQueuesConfig() != IX_ETH_ACC_SUCCESS )
|
||||
{
|
||||
IX_ETH_ACC_WARNING_LOG("ixEthAccInit: queue config failed\n", 0, 0, 0, 0, 0, 0);
|
||||
|
||||
return IX_ETH_ACC_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize MII
|
||||
*/
|
||||
if ( ixEthAccMiiInit() != IX_ETH_ACC_SUCCESS )
|
||||
{
|
||||
IX_ETH_ACC_WARNING_LOG("ixEthAccInit: Mii init failed\n", 0, 0, 0, 0, 0, 0);
|
||||
|
||||
return IX_ETH_ACC_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize MAC I/O memory
|
||||
*/
|
||||
if (ixEthAccMacMemInit() != IX_ETH_ACC_SUCCESS)
|
||||
{
|
||||
IX_ETH_ACC_WARNING_LOG("ixEthAccInit: Mac init failed\n", 0, 0, 0, 0, 0, 0);
|
||||
|
||||
return IX_ETH_ACC_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize control plane interface lock
|
||||
*/
|
||||
if (ixOsalMutexInit(&ixEthAccControlInterfaceMutex) != IX_SUCCESS)
|
||||
{
|
||||
IX_ETH_ACC_WARNING_LOG("ixEthAccInit: Control plane interface lock initialization failed\n", 0, 0, 0, 0, 0, 0);
|
||||
|
||||
return IX_ETH_ACC_FAIL;
|
||||
}
|
||||
|
||||
/* initialiasation is complete */
|
||||
ixEthAccServiceInit = TRUE;
|
||||
|
||||
return IX_ETH_ACC_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
PUBLIC void ixEthAccUnload(void)
|
||||
{
|
||||
IxEthAccPortId portId;
|
||||
|
||||
if ( IX_ETH_ACC_IS_SERVICE_INITIALIZED() )
|
||||
{
|
||||
/* check none of the port is still active */
|
||||
for (portId = 0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++)
|
||||
{
|
||||
if ( IX_ETH_IS_PORT_INITIALIZED(portId) )
|
||||
{
|
||||
if (ixEthAccMacState[portId].portDisableState == ACTIVE)
|
||||
{
|
||||
IX_ETH_ACC_WARNING_LOG("ixEthAccUnload: port %u still active, bail out\n", portId, 0, 0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* unmap the memory areas */
|
||||
ixEthAccMiiUnload();
|
||||
ixEthAccMacUnload();
|
||||
|
||||
/* set all ports as uninitialized */
|
||||
for (portId = 0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++)
|
||||
{
|
||||
ixEthAccPortData[portId].portInitialized = FALSE;
|
||||
}
|
||||
|
||||
/* uninitialize the service */
|
||||
ixEthAccServiceInit = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
PUBLIC IxEthAccStatus ixEthAccPortInit( IxEthAccPortId portId)
|
||||
{
|
||||
|
||||
IxEthAccStatus ret=IX_ETH_ACC_SUCCESS;
|
||||
|
||||
if ( ! IX_ETH_ACC_IS_SERVICE_INITIALIZED() )
|
||||
{
|
||||
return(IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for valid port
|
||||
*/
|
||||
|
||||
if ( ! IX_ETH_ACC_IS_PORT_VALID(portId) )
|
||||
{
|
||||
return (IX_ETH_ACC_INVALID_PORT);
|
||||
}
|
||||
|
||||
if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
|
||||
{
|
||||
IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot initialize Eth port.\n",(INT32) portId,0,0,0,0,0);
|
||||
return IX_ETH_ACC_SUCCESS ;
|
||||
}
|
||||
|
||||
if ( IX_ETH_IS_PORT_INITIALIZED(portId) )
|
||||
{
|
||||
/* Already initialized */
|
||||
return(IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
if(ixEthAccMacInit(portId)!=IX_ETH_ACC_SUCCESS)
|
||||
{
|
||||
return IX_ETH_ACC_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the port init flag.
|
||||
*/
|
||||
|
||||
ixEthAccPortData[portId].portInitialized = TRUE;
|
||||
|
||||
#ifdef CONFIG_IXP425_COMPONENT_ETHDB
|
||||
/* init learning/filtering database structures for this port */
|
||||
ixEthDBPortInit(portId);
|
||||
#endif
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
1049
cpu/ixp/npe/IxEthAccCommon.c
Normal file
1049
cpu/ixp/npe/IxEthAccCommon.c
Normal file
File diff suppressed because it is too large
Load Diff
533
cpu/ixp/npe/IxEthAccControlInterface.c
Normal file
533
cpu/ixp/npe/IxEthAccControlInterface.c
Normal file
@ -0,0 +1,533 @@
|
||||
/**
|
||||
* @file IxEthAccControlInterface.c
|
||||
*
|
||||
* @author Intel Corporation
|
||||
* @date
|
||||
*
|
||||
* @brief IX_ETH_ACC_PUBLIC wrappers for control plane functions
|
||||
*
|
||||
* Design Notes:
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
#include "IxOsal.h"
|
||||
#include "IxEthAcc.h"
|
||||
#include "IxEthAcc_p.h"
|
||||
|
||||
PUBLIC IxOsalMutex ixEthAccControlInterfaceMutex;
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortEnable(IxEthAccPortId portId)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
printf("EthAcc: (Mac) cannot enable port %d, service not initialized\n", portId);
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortEnablePriv(portId);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortDisable(IxEthAccPortId portId)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
/* check the context is iinitialized */
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortDisablePriv(portId);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortEnabledQuery(IxEthAccPortId portId, BOOL *enabled)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortEnabledQueryPriv(portId, enabled);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortPromiscuousModeClear(IxEthAccPortId portId)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortPromiscuousModeClearPriv(portId);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortPromiscuousModeSet(IxEthAccPortId portId)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortPromiscuousModeSetPriv(portId);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortUnicastMacAddressSet(IxEthAccPortId portId, IxEthAccMacAddr *macAddr)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortUnicastMacAddressSetPriv(portId, macAddr);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortUnicastMacAddressGet(IxEthAccPortId portId, IxEthAccMacAddr *macAddr)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortUnicastMacAddressGetPriv(portId, macAddr);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortMulticastAddressJoin(IxEthAccPortId portId, IxEthAccMacAddr *macAddr)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortMulticastAddressJoinPriv(portId, macAddr);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortMulticastAddressJoinAll(IxEthAccPortId portId)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortMulticastAddressJoinAllPriv(portId);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortMulticastAddressLeave(IxEthAccPortId portId, IxEthAccMacAddr *macAddr)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortMulticastAddressLeavePriv(portId, macAddr);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortMulticastAddressLeaveAll(IxEthAccPortId portId)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortMulticastAddressLeaveAllPriv(portId);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortUnicastAddressShow(IxEthAccPortId portId)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortUnicastAddressShowPriv(portId);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC void
|
||||
ixEthAccPortMulticastAddressShow(IxEthAccPortId portId)
|
||||
{
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
ixEthAccPortMulticastAddressShowPriv(portId);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortDuplexModeSet(IxEthAccPortId portId, IxEthAccDuplexMode mode)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortDuplexModeSetPriv(portId, mode);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortDuplexModeGet(IxEthAccPortId portId, IxEthAccDuplexMode *mode)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortDuplexModeGetPriv(portId, mode);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortTxFrameAppendPaddingEnable(IxEthAccPortId portId)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortTxFrameAppendPaddingEnablePriv(portId);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortTxFrameAppendPaddingDisable(IxEthAccPortId portId)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortTxFrameAppendPaddingDisablePriv(portId);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortTxFrameAppendFCSEnable(IxEthAccPortId portId)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortTxFrameAppendFCSEnablePriv(portId);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortTxFrameAppendFCSDisable(IxEthAccPortId portId)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortTxFrameAppendFCSDisablePriv(portId);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortRxFrameAppendFCSEnable(IxEthAccPortId portId)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortRxFrameAppendFCSEnablePriv(portId);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortRxFrameAppendFCSDisable(IxEthAccPortId portId)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortRxFrameAppendFCSDisablePriv(portId);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccTxSchedulingDisciplineSet(IxEthAccPortId portId, IxEthAccSchedulerDiscipline sched)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccTxSchedulingDisciplineSetPriv(portId, sched);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccRxSchedulingDisciplineSet(IxEthAccSchedulerDiscipline sched)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccRxSchedulingDisciplineSetPriv(sched);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortNpeLoopbackEnable(IxEthAccPortId portId)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccNpeLoopbackEnablePriv(portId);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortTxEnable(IxEthAccPortId portId)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortTxEnablePriv(portId);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortRxEnable(IxEthAccPortId portId)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortRxEnablePriv(portId);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortNpeLoopbackDisable(IxEthAccPortId portId)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccNpeLoopbackDisablePriv(portId);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortTxDisable(IxEthAccPortId portId)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortTxDisablePriv(portId);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortRxDisable(IxEthAccPortId portId)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortRxDisablePriv(portId);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus
|
||||
ixEthAccPortMacReset(IxEthAccPortId portId)
|
||||
{
|
||||
IxEthAccStatus result;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixEthAccControlInterfaceMutex, IX_OSAL_WAIT_FOREVER);
|
||||
result = ixEthAccPortMacResetPriv(portId);
|
||||
ixOsalMutexUnlock(&ixEthAccControlInterfaceMutex);
|
||||
return result;
|
||||
}
|
2483
cpu/ixp/npe/IxEthAccDataPlane.c
Normal file
2483
cpu/ixp/npe/IxEthAccDataPlane.c
Normal file
File diff suppressed because it is too large
Load Diff
2641
cpu/ixp/npe/IxEthAccMac.c
Normal file
2641
cpu/ixp/npe/IxEthAccMac.c
Normal file
File diff suppressed because it is too large
Load Diff
410
cpu/ixp/npe/IxEthAccMii.c
Normal file
410
cpu/ixp/npe/IxEthAccMii.c
Normal file
@ -0,0 +1,410 @@
|
||||
/**
|
||||
* @file IxEthAccMii.c
|
||||
*
|
||||
* @author Intel Corporation
|
||||
* @date
|
||||
*
|
||||
* @brief MII control functions
|
||||
*
|
||||
* Design Notes:
|
||||
*
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
#include "IxOsal.h"
|
||||
#include "IxEthAcc.h"
|
||||
#include "IxEthAcc_p.h"
|
||||
#include "IxEthAccMac_p.h"
|
||||
#include "IxEthAccMii_p.h"
|
||||
|
||||
|
||||
PRIVATE UINT32 miiBaseAddressVirt;
|
||||
PRIVATE IxOsalMutex miiAccessLock;
|
||||
|
||||
PUBLIC UINT32 ixEthAccMiiRetryCount = IX_ETH_ACC_MII_TIMEOUT_10TH_SECS;
|
||||
PUBLIC UINT32 ixEthAccMiiAccessTimeout = IX_ETH_ACC_MII_10TH_SEC_IN_MILLIS;
|
||||
|
||||
/* -----------------------------------
|
||||
* private function prototypes
|
||||
*/
|
||||
PRIVATE void
|
||||
ixEthAccMdioCmdWrite(UINT32 mdioCommand);
|
||||
|
||||
PRIVATE void
|
||||
ixEthAccMdioCmdRead(UINT32 *data);
|
||||
|
||||
PRIVATE void
|
||||
ixEthAccMdioStatusRead(UINT32 *data);
|
||||
|
||||
|
||||
PRIVATE void
|
||||
ixEthAccMdioCmdWrite(UINT32 mdioCommand)
|
||||
{
|
||||
REG_WRITE(miiBaseAddressVirt,
|
||||
IX_ETH_ACC_MAC_MDIO_CMD_1,
|
||||
mdioCommand & 0xff);
|
||||
|
||||
REG_WRITE(miiBaseAddressVirt,
|
||||
IX_ETH_ACC_MAC_MDIO_CMD_2,
|
||||
(mdioCommand >> 8) & 0xff);
|
||||
|
||||
REG_WRITE(miiBaseAddressVirt,
|
||||
IX_ETH_ACC_MAC_MDIO_CMD_3,
|
||||
(mdioCommand >> 16) & 0xff);
|
||||
|
||||
REG_WRITE(miiBaseAddressVirt,
|
||||
IX_ETH_ACC_MAC_MDIO_CMD_4,
|
||||
(mdioCommand >> 24) & 0xff);
|
||||
}
|
||||
|
||||
PRIVATE void
|
||||
ixEthAccMdioCmdRead(UINT32 *data)
|
||||
{
|
||||
UINT32 regval;
|
||||
|
||||
REG_READ(miiBaseAddressVirt,
|
||||
IX_ETH_ACC_MAC_MDIO_CMD_1,
|
||||
regval);
|
||||
|
||||
*data = regval & 0xff;
|
||||
|
||||
REG_READ(miiBaseAddressVirt,
|
||||
IX_ETH_ACC_MAC_MDIO_CMD_2,
|
||||
regval);
|
||||
|
||||
*data |= (regval & 0xff) << 8;
|
||||
|
||||
REG_READ(miiBaseAddressVirt,
|
||||
IX_ETH_ACC_MAC_MDIO_CMD_3,
|
||||
regval);
|
||||
|
||||
*data |= (regval & 0xff) << 16;
|
||||
|
||||
REG_READ(miiBaseAddressVirt,
|
||||
IX_ETH_ACC_MAC_MDIO_CMD_4,
|
||||
regval);
|
||||
|
||||
*data |= (regval & 0xff) << 24;
|
||||
|
||||
}
|
||||
|
||||
PRIVATE void
|
||||
ixEthAccMdioStatusRead(UINT32 *data)
|
||||
{
|
||||
UINT32 regval;
|
||||
|
||||
REG_READ(miiBaseAddressVirt,
|
||||
IX_ETH_ACC_MAC_MDIO_STS_1,
|
||||
regval);
|
||||
|
||||
*data = regval & 0xff;
|
||||
|
||||
REG_READ(miiBaseAddressVirt,
|
||||
IX_ETH_ACC_MAC_MDIO_STS_2,
|
||||
regval);
|
||||
|
||||
*data |= (regval & 0xff) << 8;
|
||||
|
||||
REG_READ(miiBaseAddressVirt,
|
||||
IX_ETH_ACC_MAC_MDIO_STS_3,
|
||||
regval);
|
||||
|
||||
*data |= (regval & 0xff) << 16;
|
||||
|
||||
REG_READ(miiBaseAddressVirt,
|
||||
IX_ETH_ACC_MAC_MDIO_STS_4,
|
||||
regval);
|
||||
|
||||
*data |= (regval & 0xff) << 24;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* ixEthAccMiiInit
|
||||
*/
|
||||
IxEthAccStatus
|
||||
ixEthAccMiiInit()
|
||||
{
|
||||
if(ixOsalMutexInit(&miiAccessLock)!= IX_SUCCESS)
|
||||
{
|
||||
return IX_ETH_ACC_FAIL;
|
||||
}
|
||||
|
||||
miiBaseAddressVirt = (UINT32) IX_OSAL_MEM_MAP(IX_ETH_ACC_MAC_0_BASE, IX_OSAL_IXP400_ETHA_MAP_SIZE);
|
||||
|
||||
if (miiBaseAddressVirt == 0)
|
||||
{
|
||||
ixOsalLog(IX_OSAL_LOG_LVL_FATAL,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"EthAcc: Could not map MII I/O mapped memory\n",
|
||||
0, 0, 0, 0, 0, 0);
|
||||
|
||||
return IX_ETH_ACC_FAIL;
|
||||
}
|
||||
|
||||
return IX_ETH_ACC_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
ixEthAccMiiUnload(void)
|
||||
{
|
||||
IX_OSAL_MEM_UNMAP(miiBaseAddressVirt);
|
||||
|
||||
miiBaseAddressVirt = 0;
|
||||
}
|
||||
|
||||
PUBLIC IxEthAccStatus
|
||||
ixEthAccMiiAccessTimeoutSet(UINT32 timeout, UINT32 retryCount)
|
||||
{
|
||||
if (retryCount < 1) return IX_ETH_ACC_FAIL;
|
||||
|
||||
ixEthAccMiiRetryCount = retryCount;
|
||||
ixEthAccMiiAccessTimeout = timeout;
|
||||
|
||||
return IX_ETH_ACC_SUCCESS;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* ixEthAccMiiReadRtn - read a 16 bit value from a PHY
|
||||
*/
|
||||
IxEthAccStatus
|
||||
ixEthAccMiiReadRtn (UINT8 phyAddr,
|
||||
UINT8 phyReg,
|
||||
UINT16 *value)
|
||||
{
|
||||
UINT32 mdioCommand;
|
||||
UINT32 regval;
|
||||
UINT32 miiTimeout;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
if ((phyAddr >= IXP425_ETH_ACC_MII_MAX_ADDR)
|
||||
|| (phyReg >= IXP425_ETH_ACC_MII_MAX_REG))
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
if (value == NULL)
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&miiAccessLock, IX_OSAL_WAIT_FOREVER);
|
||||
mdioCommand = phyReg << IX_ETH_ACC_MII_REG_SHL
|
||||
| phyAddr << IX_ETH_ACC_MII_ADDR_SHL;
|
||||
mdioCommand |= IX_ETH_ACC_MII_GO;
|
||||
|
||||
ixEthAccMdioCmdWrite(mdioCommand);
|
||||
|
||||
miiTimeout = ixEthAccMiiRetryCount;
|
||||
|
||||
while(miiTimeout)
|
||||
{
|
||||
|
||||
ixEthAccMdioCmdRead(®val);
|
||||
|
||||
if((regval & IX_ETH_ACC_MII_GO) == 0x0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
/* Sleep for a while */
|
||||
ixOsalSleep(ixEthAccMiiAccessTimeout);
|
||||
miiTimeout--;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(miiTimeout == 0)
|
||||
{
|
||||
ixOsalMutexUnlock(&miiAccessLock);
|
||||
*value = 0xffff;
|
||||
return IX_ETH_ACC_FAIL;
|
||||
}
|
||||
|
||||
|
||||
ixEthAccMdioStatusRead(®val);
|
||||
if(regval & IX_ETH_ACC_MII_READ_FAIL)
|
||||
{
|
||||
ixOsalMutexUnlock(&miiAccessLock);
|
||||
*value = 0xffff;
|
||||
return IX_ETH_ACC_FAIL;
|
||||
}
|
||||
|
||||
*value = regval & 0xffff;
|
||||
ixOsalMutexUnlock(&miiAccessLock);
|
||||
return IX_ETH_ACC_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* ixEthAccMiiWriteRtn - write a 16 bit value to a PHY
|
||||
*/
|
||||
IxEthAccStatus
|
||||
ixEthAccMiiWriteRtn (UINT8 phyAddr,
|
||||
UINT8 phyReg,
|
||||
UINT16 value)
|
||||
{
|
||||
UINT32 mdioCommand;
|
||||
UINT32 regval;
|
||||
UINT16 readVal;
|
||||
UINT32 miiTimeout;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
if ((phyAddr >= IXP425_ETH_ACC_MII_MAX_ADDR)
|
||||
|| (phyReg >= IXP425_ETH_ACC_MII_MAX_REG))
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
/* ensure that a PHY is present at this address */
|
||||
if(ixEthAccMiiReadRtn(phyAddr,
|
||||
IX_ETH_ACC_MII_CTRL_REG,
|
||||
&readVal) != IX_ETH_ACC_SUCCESS)
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&miiAccessLock, IX_OSAL_WAIT_FOREVER);
|
||||
mdioCommand = phyReg << IX_ETH_ACC_MII_REG_SHL
|
||||
| phyAddr << IX_ETH_ACC_MII_ADDR_SHL ;
|
||||
mdioCommand |= IX_ETH_ACC_MII_GO | IX_ETH_ACC_MII_WRITE | value;
|
||||
|
||||
ixEthAccMdioCmdWrite(mdioCommand);
|
||||
|
||||
miiTimeout = ixEthAccMiiRetryCount;
|
||||
|
||||
while(miiTimeout)
|
||||
{
|
||||
|
||||
ixEthAccMdioCmdRead(®val);
|
||||
|
||||
/*The "GO" bit is reset to 0 when the write completes*/
|
||||
if((regval & IX_ETH_ACC_MII_GO) == 0x0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
/* Sleep for a while */
|
||||
ixOsalSleep(ixEthAccMiiAccessTimeout);
|
||||
miiTimeout--;
|
||||
}
|
||||
|
||||
ixOsalMutexUnlock(&miiAccessLock);
|
||||
if(miiTimeout == 0)
|
||||
{
|
||||
return IX_ETH_ACC_FAIL;
|
||||
}
|
||||
return IX_ETH_ACC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
*
|
||||
* Phy query functions
|
||||
*
|
||||
*/
|
||||
IxEthAccStatus
|
||||
ixEthAccMiiStatsShow (UINT32 phyAddr)
|
||||
{
|
||||
UINT16 regval;
|
||||
printf("Regisers on PHY at address 0x%x\n", phyAddr);
|
||||
ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_CTRL_REG, ®val);
|
||||
printf(" Control Register : 0x%4.4x\n", regval);
|
||||
ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_STAT_REG, ®val);
|
||||
printf(" Status Register : 0x%4.4x\n", regval);
|
||||
ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_PHY_ID1_REG, ®val);
|
||||
printf(" PHY ID1 Register : 0x%4.4x\n", regval);
|
||||
ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_PHY_ID2_REG, ®val);
|
||||
printf(" PHY ID2 Register : 0x%4.4x\n", regval);
|
||||
ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_AN_ADS_REG, ®val);
|
||||
printf(" Auto Neg ADS Register : 0x%4.4x\n", regval);
|
||||
ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_AN_PRTN_REG, ®val);
|
||||
printf(" Auto Neg Partner Ability Register : 0x%4.4x\n", regval);
|
||||
ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_AN_EXP_REG, ®val);
|
||||
printf(" Auto Neg Expansion Register : 0x%4.4x\n", regval);
|
||||
ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_AN_NEXT_REG, ®val);
|
||||
printf(" Auto Neg Next Register : 0x%4.4x\n", regval);
|
||||
|
||||
return IX_ETH_ACC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
*
|
||||
* Interface query functions
|
||||
*
|
||||
*/
|
||||
IxEthAccStatus
|
||||
ixEthAccMdioShow (void)
|
||||
{
|
||||
UINT32 regval;
|
||||
|
||||
if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
|
||||
{
|
||||
return (IX_ETH_ACC_FAIL);
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&miiAccessLock, IX_OSAL_WAIT_FOREVER);
|
||||
ixEthAccMdioCmdRead(®val);
|
||||
ixOsalMutexUnlock(&miiAccessLock);
|
||||
|
||||
printf("MDIO command register\n");
|
||||
printf(" Go bit : 0x%x\n", (regval & BIT(31)) >> 31);
|
||||
printf(" MDIO Write : 0x%x\n", (regval & BIT(26)) >> 26);
|
||||
printf(" PHY address : 0x%x\n", (regval >> 21) & 0x1f);
|
||||
printf(" Reg address : 0x%x\n", (regval >> 16) & 0x1f);
|
||||
|
||||
ixOsalMutexLock(&miiAccessLock, IX_OSAL_WAIT_FOREVER);
|
||||
ixEthAccMdioStatusRead(®val);
|
||||
ixOsalMutexUnlock(&miiAccessLock);
|
||||
|
||||
printf("MDIO status register\n");
|
||||
printf(" Read OK : 0x%x\n", (regval & BIT(31)) >> 31);
|
||||
printf(" Read Data : 0x%x\n", (regval >> 16) & 0xff);
|
||||
|
||||
return IX_ETH_ACC_SUCCESS;
|
||||
}
|
||||
|
448
cpu/ixp/npe/IxEthDBAPI.c
Normal file
448
cpu/ixp/npe/IxEthDBAPI.c
Normal file
@ -0,0 +1,448 @@
|
||||
/**
|
||||
* @file IxEthDBAPI.c
|
||||
*
|
||||
* @brief Implementation of the public API
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
#include "IxEthDB_p.h"
|
||||
#include "IxFeatureCtrl.h"
|
||||
|
||||
extern HashTable dbHashtable;
|
||||
extern IxEthDBPortMap overflowUpdatePortList;
|
||||
extern BOOL ixEthDBPortUpdateRequired[IX_ETH_DB_MAX_RECORD_TYPE_INDEX + 1];
|
||||
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBFilteringStaticEntryProvision(IxEthDBPortId portID, IxEthDBMacAddr *macAddr)
|
||||
{
|
||||
IX_ETH_DB_CHECK_PORT(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_REFERENCE(macAddr);
|
||||
|
||||
IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_LEARNING);
|
||||
|
||||
return ixEthDBTriggerAddPortUpdate(macAddr, portID, TRUE);
|
||||
}
|
||||
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBFilteringDynamicEntryProvision(IxEthDBPortId portID, IxEthDBMacAddr *macAddr)
|
||||
{
|
||||
IX_ETH_DB_CHECK_PORT(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_REFERENCE(macAddr);
|
||||
|
||||
IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_LEARNING);
|
||||
|
||||
return ixEthDBTriggerAddPortUpdate(macAddr, portID, FALSE);
|
||||
}
|
||||
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBFilteringEntryDelete(IxEthDBMacAddr *macAddr)
|
||||
{
|
||||
HashNode *searchResult;
|
||||
|
||||
IX_ETH_DB_CHECK_REFERENCE(macAddr);
|
||||
|
||||
searchResult = ixEthDBSearch(macAddr, IX_ETH_DB_ALL_FILTERING_RECORDS);
|
||||
|
||||
if (searchResult == NULL)
|
||||
{
|
||||
return IX_ETH_DB_NO_SUCH_ADDR; /* not found */
|
||||
}
|
||||
|
||||
ixEthDBReleaseHashNode(searchResult);
|
||||
|
||||
/* build a remove event and place it on the event queue */
|
||||
return ixEthDBTriggerRemovePortUpdate(macAddr, ((MacDescriptor *) searchResult->data)->portID);
|
||||
}
|
||||
|
||||
IX_ETH_DB_PUBLIC
|
||||
void ixEthDBDatabaseMaintenance()
|
||||
{
|
||||
HashIterator iterator;
|
||||
UINT32 portIndex;
|
||||
BOOL agingRequired = FALSE;
|
||||
|
||||
/* ports who will have deleted records and therefore will need updating */
|
||||
IxEthDBPortMap triggerPorts;
|
||||
|
||||
if (IX_FEATURE_CTRL_SWCONFIG_ENABLED !=
|
||||
ixFeatureCtrlSwConfigurationCheck (IX_FEATURECTRL_ETH_LEARNING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SET_EMPTY_DEPENDENCY_MAP(triggerPorts);
|
||||
|
||||
/* check if there's at least a port that needs aging */
|
||||
for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
|
||||
{
|
||||
if (ixEthDBPortInfo[portIndex].agingEnabled && ixEthDBPortInfo[portIndex].enabled)
|
||||
{
|
||||
agingRequired = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (agingRequired)
|
||||
{
|
||||
/* ask each NPE port to write back the database for aging inspection */
|
||||
for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
|
||||
{
|
||||
if (ixEthDBPortDefinitions[portIndex].type == IX_ETH_NPE
|
||||
&& ixEthDBPortInfo[portIndex].agingEnabled
|
||||
&& ixEthDBPortInfo[portIndex].enabled)
|
||||
{
|
||||
IxNpeMhMessage message;
|
||||
IX_STATUS result;
|
||||
|
||||
/* send EDB_GetMACAddressDatabase message */
|
||||
FILL_GETMACADDRESSDATABASE(message,
|
||||
0 /* unused */,
|
||||
IX_OSAL_MMU_VIRT_TO_PHYS(ixEthDBPortInfo[portIndex].updateMethod.npeUpdateZone));
|
||||
|
||||
IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portIndex), message, result);
|
||||
|
||||
if (result == IX_SUCCESS)
|
||||
{
|
||||
/* analyze NPE copy */
|
||||
ixEthDBNPESyncScan(portIndex, ixEthDBPortInfo[portIndex].updateMethod.npeUpdateZone, FULL_ELT_BYTE_SIZE);
|
||||
|
||||
IX_ETH_DB_SUPPORT_TRACE("DB: (API) Finished scanning NPE tree on port %d\n", portIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
ixEthDBPortInfo[portIndex].agingEnabled = FALSE;
|
||||
ixEthDBPortInfo[portIndex].updateMethod.updateEnabled = FALSE;
|
||||
ixEthDBPortInfo[portIndex].updateMethod.userControlled = TRUE;
|
||||
|
||||
ixOsalLog(IX_OSAL_LOG_LVL_FATAL,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"EthDB: (Maintenance) warning, disabling aging and updates for port %d (assumed dead)\n",
|
||||
portIndex, 0, 0, 0, 0, 0);
|
||||
|
||||
ixEthDBDatabaseClear(portIndex, IX_ETH_DB_ALL_RECORD_TYPES);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* browse database and age entries */
|
||||
BUSY_RETRY(ixEthDBInitHashIterator(&dbHashtable, &iterator));
|
||||
|
||||
while (IS_ITERATOR_VALID(&iterator))
|
||||
{
|
||||
MacDescriptor *descriptor = (MacDescriptor *) iterator.node->data;
|
||||
UINT32 *age = NULL;
|
||||
BOOL staticEntry = TRUE;
|
||||
|
||||
if (descriptor->type == IX_ETH_DB_FILTERING_RECORD)
|
||||
{
|
||||
age = &descriptor->recordData.filteringData.age;
|
||||
staticEntry = descriptor->recordData.filteringData.staticEntry;
|
||||
}
|
||||
else if (descriptor->type == IX_ETH_DB_FILTERING_VLAN_RECORD)
|
||||
{
|
||||
age = &descriptor->recordData.filteringVlanData.age;
|
||||
staticEntry = descriptor->recordData.filteringVlanData.staticEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
staticEntry = TRUE;
|
||||
}
|
||||
|
||||
if (ixEthDBPortInfo[descriptor->portID].agingEnabled && (staticEntry == FALSE))
|
||||
{
|
||||
/* manually increment the age if the port has no such capability */
|
||||
if ((ixEthDBPortDefinitions[descriptor->portID].capabilities & IX_ETH_ENTRY_AGING) == 0)
|
||||
{
|
||||
*age += (IX_ETH_DB_MAINTENANCE_TIME / 60);
|
||||
}
|
||||
|
||||
/* age entry if it exceeded the maximum time to live */
|
||||
if (*age >= (IX_ETH_DB_LEARNING_ENTRY_AGE_TIME / 60))
|
||||
{
|
||||
/* add port to the set of update trigger ports */
|
||||
JOIN_PORT_TO_MAP(triggerPorts, descriptor->portID);
|
||||
|
||||
/* delete entry */
|
||||
BUSY_RETRY(ixEthDBRemoveEntryAtHashIterator(&dbHashtable, &iterator));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* move to the next record */
|
||||
BUSY_RETRY(ixEthDBIncrementHashIterator(&dbHashtable, &iterator));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* move to the next record */
|
||||
BUSY_RETRY(ixEthDBIncrementHashIterator(&dbHashtable, &iterator));
|
||||
}
|
||||
}
|
||||
|
||||
/* update ports which lost records */
|
||||
ixEthDBUpdatePortLearningTrees(triggerPorts);
|
||||
}
|
||||
}
|
||||
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBDatabaseClear(IxEthDBPortId portID, IxEthDBRecordType recordType)
|
||||
{
|
||||
IxEthDBPortMap triggerPorts;
|
||||
HashIterator iterator;
|
||||
|
||||
if (portID >= IX_ETH_DB_NUMBER_OF_PORTS && portID != IX_ETH_DB_ALL_PORTS)
|
||||
{
|
||||
return IX_ETH_DB_INVALID_PORT;
|
||||
}
|
||||
|
||||
/* check if the user passes some extra bits */
|
||||
if ((recordType | IX_ETH_DB_ALL_RECORD_TYPES) != IX_ETH_DB_ALL_RECORD_TYPES)
|
||||
{
|
||||
return IX_ETH_DB_INVALID_ARG;
|
||||
}
|
||||
|
||||
SET_EMPTY_DEPENDENCY_MAP(triggerPorts);
|
||||
|
||||
/* browse database and age entries */
|
||||
BUSY_RETRY(ixEthDBInitHashIterator(&dbHashtable, &iterator));
|
||||
|
||||
while (IS_ITERATOR_VALID(&iterator))
|
||||
{
|
||||
MacDescriptor *descriptor = (MacDescriptor *) iterator.node->data;
|
||||
|
||||
if (((descriptor->portID == portID) || (portID == IX_ETH_DB_ALL_PORTS))
|
||||
&& ((descriptor->type & recordType) != 0))
|
||||
{
|
||||
/* add to trigger if automatic updates are required */
|
||||
if (ixEthDBPortUpdateRequired[descriptor->type])
|
||||
{
|
||||
/* add port to the set of update trigger ports */
|
||||
JOIN_PORT_TO_MAP(triggerPorts, descriptor->portID);
|
||||
}
|
||||
|
||||
/* delete entry */
|
||||
BUSY_RETRY(ixEthDBRemoveEntryAtHashIterator(&dbHashtable, &iterator));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* move to the next record */
|
||||
BUSY_RETRY(ixEthDBIncrementHashIterator(&dbHashtable, &iterator));
|
||||
}
|
||||
}
|
||||
|
||||
/* update ports which lost records */
|
||||
ixEthDBUpdatePortLearningTrees(triggerPorts);
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBFilteringPortSearch(IxEthDBPortId portID, IxEthDBMacAddr *macAddr)
|
||||
{
|
||||
HashNode *searchResult;
|
||||
IxEthDBStatus result = IX_ETH_DB_NO_SUCH_ADDR;
|
||||
|
||||
IX_ETH_DB_CHECK_PORT(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_REFERENCE(macAddr);
|
||||
|
||||
IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_LEARNING);
|
||||
|
||||
searchResult = ixEthDBSearch(macAddr, IX_ETH_DB_ALL_FILTERING_RECORDS);
|
||||
|
||||
if (searchResult == NULL)
|
||||
{
|
||||
return IX_ETH_DB_NO_SUCH_ADDR; /* not found */
|
||||
}
|
||||
|
||||
if (((MacDescriptor *) (searchResult->data))->portID == portID)
|
||||
{
|
||||
result = IX_ETH_DB_SUCCESS; /* address and port match */
|
||||
}
|
||||
|
||||
ixEthDBReleaseHashNode(searchResult);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBFilteringDatabaseSearch(IxEthDBPortId *portID, IxEthDBMacAddr *macAddr)
|
||||
{
|
||||
HashNode *searchResult;
|
||||
|
||||
IX_ETH_DB_CHECK_REFERENCE(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_REFERENCE(macAddr);
|
||||
|
||||
searchResult = ixEthDBSearch(macAddr, IX_ETH_DB_ALL_FILTERING_RECORDS);
|
||||
|
||||
if (searchResult == NULL)
|
||||
{
|
||||
return IX_ETH_DB_NO_SUCH_ADDR; /* not found */
|
||||
}
|
||||
|
||||
/* return the port ID */
|
||||
*portID = ((MacDescriptor *) searchResult->data)->portID;
|
||||
|
||||
ixEthDBReleaseHashNode(searchResult);
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBPortAgingDisable(IxEthDBPortId portID)
|
||||
{
|
||||
IX_ETH_DB_CHECK_PORT(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_LEARNING);
|
||||
|
||||
ixEthDBPortInfo[portID].agingEnabled = FALSE;
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBPortAgingEnable(IxEthDBPortId portID)
|
||||
{
|
||||
IX_ETH_DB_CHECK_PORT(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_LEARNING);
|
||||
|
||||
ixEthDBPortInfo[portID].agingEnabled = TRUE;
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBFilteringPortUpdatingSearch(IxEthDBPortId *portID, IxEthDBMacAddr *macAddr)
|
||||
{
|
||||
HashNode *searchResult;
|
||||
MacDescriptor *descriptor;
|
||||
|
||||
IX_ETH_DB_CHECK_REFERENCE(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_REFERENCE(macAddr);
|
||||
|
||||
searchResult = ixEthDBSearch(macAddr, IX_ETH_DB_ALL_FILTERING_RECORDS);
|
||||
|
||||
if (searchResult == NULL)
|
||||
{
|
||||
return IX_ETH_DB_NO_SUCH_ADDR; /* not found */
|
||||
}
|
||||
|
||||
descriptor = (MacDescriptor *) searchResult->data;
|
||||
|
||||
/* return the port ID */
|
||||
*portID = descriptor->portID;
|
||||
|
||||
/* reset entry age */
|
||||
if (descriptor->type == IX_ETH_DB_FILTERING_RECORD)
|
||||
{
|
||||
descriptor->recordData.filteringData.age = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
descriptor->recordData.filteringVlanData.age = 0;
|
||||
}
|
||||
|
||||
ixEthDBReleaseHashNode(searchResult);
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBPortDependencyMapSet(IxEthDBPortId portID, IxEthDBPortMap dependencyPortMap)
|
||||
{
|
||||
IX_ETH_DB_CHECK_PORT(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_REFERENCE(dependencyPortMap);
|
||||
|
||||
IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_FILTERING);
|
||||
|
||||
/* force bit at offset 255 to 0 (reserved) */
|
||||
dependencyPortMap[31] &= 0xFE;
|
||||
|
||||
COPY_DEPENDENCY_MAP(ixEthDBPortInfo[portID].dependencyPortMap, dependencyPortMap);
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBPortDependencyMapGet(IxEthDBPortId portID, IxEthDBPortMap dependencyPortMap)
|
||||
{
|
||||
IX_ETH_DB_CHECK_PORT(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_REFERENCE(dependencyPortMap);
|
||||
|
||||
IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_FILTERING);
|
||||
|
||||
COPY_DEPENDENCY_MAP(dependencyPortMap, ixEthDBPortInfo[portID].dependencyPortMap);
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBPortUpdateEnableSet(IxEthDBPortId portID, BOOL enableUpdate)
|
||||
{
|
||||
IX_ETH_DB_CHECK_PORT(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_FILTERING);
|
||||
|
||||
ixEthDBPortInfo[portID].updateMethod.updateEnabled = enableUpdate;
|
||||
ixEthDBPortInfo[portID].updateMethod.userControlled = TRUE;
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
678
cpu/ixp/npe/IxEthDBAPISupport.c
Normal file
678
cpu/ixp/npe/IxEthDBAPISupport.c
Normal file
@ -0,0 +1,678 @@
|
||||
/**
|
||||
* @file IxEthDBAPISupport.c
|
||||
*
|
||||
* @brief Public API support functions
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
#include <IxEthDB.h>
|
||||
#include <IxNpeMh.h>
|
||||
#include <IxFeatureCtrl.h>
|
||||
|
||||
#include "IxEthDB_p.h"
|
||||
#include "IxEthDBMessages_p.h"
|
||||
#include "IxEthDB_p.h"
|
||||
#include "IxEthDBLog_p.h"
|
||||
|
||||
#ifdef IX_UNIT_TEST
|
||||
|
||||
int dbAccessCounter = 0;
|
||||
int overflowEvent = 0;
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* External declaration
|
||||
*/
|
||||
extern HashTable dbHashtable;
|
||||
|
||||
/*
|
||||
* Internal declaration
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
PortInfo ixEthDBPortInfo[IX_ETH_DB_NUMBER_OF_PORTS];
|
||||
|
||||
IX_ETH_DB_PRIVATE
|
||||
struct
|
||||
{
|
||||
BOOL saved;
|
||||
IxEthDBPriorityTable priorityTable;
|
||||
IxEthDBVlanSet vlanMembership;
|
||||
IxEthDBVlanSet transmitTaggingInfo;
|
||||
IxEthDBFrameFilter frameFilter;
|
||||
IxEthDBTaggingAction taggingAction;
|
||||
IxEthDBFirewallMode firewallMode;
|
||||
BOOL stpBlocked;
|
||||
BOOL srcAddressFilterEnabled;
|
||||
UINT32 maxRxFrameSize;
|
||||
UINT32 maxTxFrameSize;
|
||||
} ixEthDBPortState[IX_ETH_DB_NUMBER_OF_PORTS];
|
||||
|
||||
#define IX_ETH_DB_DEFAULT_FRAME_SIZE (1518)
|
||||
|
||||
/**
|
||||
* @brief initializes a port
|
||||
*
|
||||
* @param portID ID of the port to be initialized
|
||||
*
|
||||
* Note that redundant initializations are silently
|
||||
* dealt with and do not constitute an error
|
||||
*
|
||||
* This function is fully documented in the main
|
||||
* header file, IxEthDB.h
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
void ixEthDBPortInit(IxEthDBPortId portID)
|
||||
{
|
||||
PortInfo *portInfo;
|
||||
|
||||
if (portID >= IX_ETH_DB_NUMBER_OF_PORTS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
portInfo = &ixEthDBPortInfo[portID];
|
||||
|
||||
if (ixEthDBSingleEthNpeCheck(portID) != IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
WARNING_LOG("EthDB: Unavailable Eth %d: Cannot initialize EthDB Port.\n", (UINT32) portID);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (portInfo->initialized)
|
||||
{
|
||||
/* redundant */
|
||||
return;
|
||||
}
|
||||
|
||||
/* initialize core fields */
|
||||
portInfo->portID = portID;
|
||||
SET_DEPENDENCY_MAP(portInfo->dependencyPortMap, portID);
|
||||
|
||||
/* default values */
|
||||
portInfo->agingEnabled = FALSE;
|
||||
portInfo->enabled = FALSE;
|
||||
portInfo->macAddressUploaded = FALSE;
|
||||
portInfo->maxRxFrameSize = IX_ETHDB_DEFAULT_FRAME_SIZE;
|
||||
portInfo->maxTxFrameSize = IX_ETHDB_DEFAULT_FRAME_SIZE;
|
||||
|
||||
/* default update control values */
|
||||
portInfo->updateMethod.searchTree = NULL;
|
||||
portInfo->updateMethod.searchTreePendingWrite = FALSE;
|
||||
portInfo->updateMethod.treeInitialized = FALSE;
|
||||
portInfo->updateMethod.updateEnabled = FALSE;
|
||||
portInfo->updateMethod.userControlled = FALSE;
|
||||
|
||||
/* default WiFi parameters */
|
||||
memset(portInfo->bbsid, 0, sizeof (portInfo->bbsid));
|
||||
portInfo->frameControlDurationID = 0;
|
||||
|
||||
/* Ethernet NPE-specific initializations */
|
||||
if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
|
||||
{
|
||||
/* update handler */
|
||||
portInfo->updateMethod.updateHandler = ixEthDBNPEUpdateHandler;
|
||||
}
|
||||
|
||||
/* initialize state save */
|
||||
ixEthDBPortState[portID].saved = FALSE;
|
||||
|
||||
portInfo->initialized = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief enables a port
|
||||
*
|
||||
* @param portID ID of the port to enable
|
||||
*
|
||||
* This function is fully documented in the main
|
||||
* header file, IxEthDB.h
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if enabling was
|
||||
* accomplished, or a meaningful error message otherwise
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBPortEnable(IxEthDBPortId portID)
|
||||
{
|
||||
IxEthDBPortMap triggerPorts;
|
||||
PortInfo *portInfo;
|
||||
|
||||
IX_ETH_DB_CHECK_PORT_EXISTS(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
portInfo = &ixEthDBPortInfo[portID];
|
||||
|
||||
if (portInfo->enabled)
|
||||
{
|
||||
/* redundant */
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
SET_DEPENDENCY_MAP(triggerPorts, portID);
|
||||
|
||||
/* mark as enabled */
|
||||
portInfo->enabled = TRUE;
|
||||
|
||||
/* Operation stops here when Ethernet Learning is not enabled */
|
||||
if(IX_FEATURE_CTRL_SWCONFIG_DISABLED ==
|
||||
ixFeatureCtrlSwConfigurationCheck(IX_FEATURECTRL_ETH_LEARNING))
|
||||
{
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE && !portInfo->macAddressUploaded)
|
||||
{
|
||||
IX_ETH_DB_SUPPORT_TRACE("DB: (Support) MAC address not set on port %d, enable failed\n", portID);
|
||||
|
||||
/* must use UnicastAddressSet() before enabling an NPE port */
|
||||
return IX_ETH_DB_MAC_UNINITIALIZED;
|
||||
}
|
||||
|
||||
if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
|
||||
{
|
||||
IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Attempting to enable the NPE callback for port %d...\n", portID);
|
||||
|
||||
if (!portInfo->updateMethod.userControlled
|
||||
&& ((portInfo->featureCapability & IX_ETH_DB_FILTERING) != 0))
|
||||
{
|
||||
portInfo->updateMethod.updateEnabled = TRUE;
|
||||
}
|
||||
|
||||
/* if this is first time initialization then we already have
|
||||
write access to the tree and can AccessRelease directly */
|
||||
if (!portInfo->updateMethod.treeInitialized)
|
||||
{
|
||||
IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Initializing tree for port %d\n", portID);
|
||||
|
||||
/* create an initial tree and release access into it */
|
||||
ixEthDBUpdatePortLearningTrees(triggerPorts);
|
||||
|
||||
/* mark tree as being initialized */
|
||||
portInfo->updateMethod.treeInitialized = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (ixEthDBPortState[portID].saved)
|
||||
{
|
||||
/* previous configuration data stored, restore state */
|
||||
if ((portInfo->featureCapability & IX_ETH_DB_FIREWALL) != 0)
|
||||
{
|
||||
ixEthDBFirewallModeSet(portID, ixEthDBPortState[portID].firewallMode);
|
||||
ixEthDBFirewallInvalidAddressFilterEnable(portID, ixEthDBPortState[portID].srcAddressFilterEnabled);
|
||||
}
|
||||
|
||||
#if 0 /* test-only */
|
||||
if ((portInfo->featureCapability & IX_ETH_DB_VLAN_QOS) != 0)
|
||||
{
|
||||
ixEthDBAcceptableFrameTypeSet(portID, ixEthDBPortState[portID].frameFilter);
|
||||
ixEthDBIngressVlanTaggingEnabledSet(portID, ixEthDBPortState[portID].taggingAction);
|
||||
|
||||
ixEthDBEgressVlanTaggingEnabledSet(portID, ixEthDBPortState[portID].transmitTaggingInfo);
|
||||
ixEthDBPortVlanMembershipSet(portID, ixEthDBPortState[portID].vlanMembership);
|
||||
|
||||
ixEthDBPriorityMappingTableSet(portID, ixEthDBPortState[portID].priorityTable);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((portInfo->featureCapability & IX_ETH_DB_SPANNING_TREE_PROTOCOL) != 0)
|
||||
{
|
||||
ixEthDBSpanningTreeBlockingStateSet(portID, ixEthDBPortState[portID].stpBlocked);
|
||||
}
|
||||
|
||||
ixEthDBFilteringPortMaximumRxFrameSizeSet(portID, ixEthDBPortState[portID].maxRxFrameSize);
|
||||
ixEthDBFilteringPortMaximumTxFrameSizeSet(portID, ixEthDBPortState[portID].maxTxFrameSize);
|
||||
|
||||
/* discard previous save */
|
||||
ixEthDBPortState[portID].saved = FALSE;
|
||||
}
|
||||
|
||||
IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Enabling succeeded for port %d\n", portID);
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief disables a port
|
||||
*
|
||||
* @param portID ID of the port to disable
|
||||
*
|
||||
* This function is fully documented in the
|
||||
* main header file, IxEthDB.h
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if disabling was
|
||||
* successful or an appropriate error message
|
||||
* otherwise
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBPortDisable(IxEthDBPortId portID)
|
||||
{
|
||||
HashIterator iterator;
|
||||
IxEthDBPortMap triggerPorts; /* ports who will have deleted records and therefore will need updating */
|
||||
BOOL result;
|
||||
PortInfo *portInfo;
|
||||
IxEthDBFeature learningEnabled;
|
||||
#if 0 /* test-only */
|
||||
IxEthDBPriorityTable classZeroTable;
|
||||
#endif
|
||||
|
||||
IX_ETH_DB_CHECK_PORT_EXISTS(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
portInfo = &ixEthDBPortInfo[portID];
|
||||
|
||||
if (!portInfo->enabled)
|
||||
{
|
||||
/* redundant */
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
|
||||
{
|
||||
/* save filtering state */
|
||||
ixEthDBPortState[portID].firewallMode = portInfo->firewallMode;
|
||||
ixEthDBPortState[portID].frameFilter = portInfo->frameFilter;
|
||||
ixEthDBPortState[portID].taggingAction = portInfo->taggingAction;
|
||||
ixEthDBPortState[portID].stpBlocked = portInfo->stpBlocked;
|
||||
ixEthDBPortState[portID].srcAddressFilterEnabled = portInfo->srcAddressFilterEnabled;
|
||||
ixEthDBPortState[portID].maxRxFrameSize = portInfo->maxRxFrameSize;
|
||||
ixEthDBPortState[portID].maxTxFrameSize = portInfo->maxTxFrameSize;
|
||||
|
||||
memcpy(ixEthDBPortState[portID].vlanMembership, portInfo->vlanMembership, sizeof (IxEthDBVlanSet));
|
||||
memcpy(ixEthDBPortState[portID].transmitTaggingInfo, portInfo->transmitTaggingInfo, sizeof (IxEthDBVlanSet));
|
||||
memcpy(ixEthDBPortState[portID].priorityTable, portInfo->priorityTable, sizeof (IxEthDBPriorityTable));
|
||||
|
||||
ixEthDBPortState[portID].saved = TRUE;
|
||||
|
||||
/* now turn off all EthDB filtering features on the port */
|
||||
|
||||
#if 0 /* test-only */
|
||||
/* VLAN & QoS */
|
||||
if ((portInfo->featureCapability & IX_ETH_DB_VLAN_QOS) != 0)
|
||||
{
|
||||
ixEthDBPortVlanMembershipRangeAdd((IxEthDBPortId) portID, 0, IX_ETH_DB_802_1Q_MAX_VLAN_ID);
|
||||
ixEthDBEgressVlanRangeTaggingEnabledSet((IxEthDBPortId) portID, 0, IX_ETH_DB_802_1Q_MAX_VLAN_ID, FALSE);
|
||||
ixEthDBAcceptableFrameTypeSet((IxEthDBPortId) portID, IX_ETH_DB_ACCEPT_ALL_FRAMES);
|
||||
ixEthDBIngressVlanTaggingEnabledSet((IxEthDBPortId) portID, IX_ETH_DB_PASS_THROUGH);
|
||||
|
||||
memset(classZeroTable, 0, sizeof (classZeroTable));
|
||||
ixEthDBPriorityMappingTableSet((IxEthDBPortId) portID, classZeroTable);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* STP */
|
||||
if ((portInfo->featureCapability & IX_ETH_DB_SPANNING_TREE_PROTOCOL) != 0)
|
||||
{
|
||||
ixEthDBSpanningTreeBlockingStateSet((IxEthDBPortId) portID, FALSE);
|
||||
}
|
||||
|
||||
/* Firewall */
|
||||
if ((portInfo->featureCapability & IX_ETH_DB_FIREWALL) != 0)
|
||||
{
|
||||
ixEthDBFirewallModeSet((IxEthDBPortId) portID, IX_ETH_DB_FIREWALL_BLACK_LIST);
|
||||
ixEthDBFirewallTableDownload((IxEthDBPortId) portID);
|
||||
ixEthDBFirewallInvalidAddressFilterEnable((IxEthDBPortId) portID, FALSE);
|
||||
}
|
||||
|
||||
/* Frame size filter */
|
||||
ixEthDBFilteringPortMaximumFrameSizeSet((IxEthDBPortId) portID, IX_ETH_DB_DEFAULT_FRAME_SIZE);
|
||||
|
||||
/* WiFi */
|
||||
if ((portInfo->featureCapability & IX_ETH_DB_WIFI_HEADER_CONVERSION) != 0)
|
||||
{
|
||||
ixEthDBWiFiConversionTableDownload((IxEthDBPortId) portID);
|
||||
}
|
||||
|
||||
/* save and disable the learning feature bit */
|
||||
learningEnabled = portInfo->featureStatus & IX_ETH_DB_LEARNING;
|
||||
portInfo->featureStatus &= ~IX_ETH_DB_LEARNING;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* save the learning feature bit */
|
||||
learningEnabled = portInfo->featureStatus & IX_ETH_DB_LEARNING;
|
||||
}
|
||||
|
||||
SET_EMPTY_DEPENDENCY_MAP(triggerPorts);
|
||||
|
||||
ixEthDBUpdateLock();
|
||||
|
||||
/* wipe out current entries for this port */
|
||||
BUSY_RETRY(ixEthDBInitHashIterator(&dbHashtable, &iterator));
|
||||
|
||||
while (IS_ITERATOR_VALID(&iterator))
|
||||
{
|
||||
MacDescriptor *descriptor = (MacDescriptor *) iterator.node->data;
|
||||
|
||||
/* check if the port match. If so, remove the entry */
|
||||
if (descriptor->portID == portID
|
||||
&& (descriptor->type == IX_ETH_DB_FILTERING_RECORD || descriptor->type == IX_ETH_DB_FILTERING_VLAN_RECORD)
|
||||
&& !descriptor->recordData.filteringData.staticEntry)
|
||||
{
|
||||
/* delete entry */
|
||||
BUSY_RETRY(ixEthDBRemoveEntryAtHashIterator(&dbHashtable, &iterator));
|
||||
|
||||
/* add port to the set of update trigger ports */
|
||||
JOIN_PORT_TO_MAP(triggerPorts, portID);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* move to the next record */
|
||||
BUSY_RETRY(ixEthDBIncrementHashIterator(&dbHashtable, &iterator));
|
||||
}
|
||||
}
|
||||
|
||||
if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
|
||||
{
|
||||
if (portInfo->updateMethod.searchTree != NULL)
|
||||
{
|
||||
ixEthDBFreeMacTreeNode(portInfo->updateMethod.searchTree);
|
||||
portInfo->updateMethod.searchTree = NULL;
|
||||
}
|
||||
|
||||
ixEthDBNPEUpdateHandler(portID, IX_ETH_DB_FILTERING_RECORD);
|
||||
}
|
||||
|
||||
/* mark as disabled */
|
||||
portInfo->enabled = FALSE;
|
||||
|
||||
/* disable updates unless the user has specifically altered the default behavior */
|
||||
if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
|
||||
{
|
||||
if (!portInfo->updateMethod.userControlled)
|
||||
{
|
||||
portInfo->updateMethod.updateEnabled = FALSE;
|
||||
}
|
||||
|
||||
/* make sure we re-initialize the NPE learning tree when the port is re-enabled */
|
||||
portInfo->updateMethod.treeInitialized = FALSE;
|
||||
}
|
||||
|
||||
ixEthDBUpdateUnlock();
|
||||
|
||||
/* restore learning feature bit */
|
||||
portInfo->featureStatus |= learningEnabled;
|
||||
|
||||
/* if we've removed any records or lost any events make sure to force an update */
|
||||
IS_EMPTY_DEPENDENCY_MAP(result, triggerPorts);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
ixEthDBUpdatePortLearningTrees(triggerPorts);
|
||||
}
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sends the updated maximum Tx/Rx frame lengths to the NPE
|
||||
*
|
||||
* @param portID ID of the port to update
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the update completed
|
||||
* successfully or an appropriate error message otherwise
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PRIVATE
|
||||
IxEthDBStatus ixEthDBPortFrameLengthsUpdate(IxEthDBPortId portID)
|
||||
{
|
||||
IxNpeMhMessage message;
|
||||
PortInfo *portInfo = &ixEthDBPortInfo[portID];
|
||||
IX_STATUS result;
|
||||
|
||||
FILL_SETMAXFRAMELENGTHS_MSG(message, portID, portInfo->maxRxFrameSize, portInfo->maxTxFrameSize);
|
||||
|
||||
IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sets the port maximum Rx frame size
|
||||
*
|
||||
* @param portID ID of the port to set the frame size on
|
||||
* @param maximumRxFrameSize maximum Rx frame size
|
||||
*
|
||||
* This function updates the internal data structures and
|
||||
* calls ixEthDBPortFrameLengthsUpdate() for NPE update.
|
||||
*
|
||||
* This function is fully documented in the main header
|
||||
* file, IxEthDB.h.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation was
|
||||
* successfull or an appropriate error message otherwise
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBFilteringPortMaximumRxFrameSizeSet(IxEthDBPortId portID, UINT32 maximumRxFrameSize)
|
||||
{
|
||||
IX_ETH_DB_CHECK_PORT_EXISTS(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
if (!ixEthDBPortInfo[portID].initialized)
|
||||
{
|
||||
return IX_ETH_DB_PORT_UNINITIALIZED;
|
||||
}
|
||||
|
||||
if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
|
||||
{
|
||||
if ((maximumRxFrameSize < IX_ETHDB_MIN_NPE_FRAME_SIZE) ||
|
||||
(maximumRxFrameSize > IX_ETHDB_MAX_NPE_FRAME_SIZE))
|
||||
{
|
||||
return IX_ETH_DB_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return IX_ETH_DB_NO_PERMISSION;
|
||||
}
|
||||
|
||||
/* update internal structure */
|
||||
ixEthDBPortInfo[portID].maxRxFrameSize = maximumRxFrameSize;
|
||||
|
||||
/* update the maximum frame size in the NPE */
|
||||
return ixEthDBPortFrameLengthsUpdate(portID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sets the port maximum Tx frame size
|
||||
*
|
||||
* @param portID ID of the port to set the frame size on
|
||||
* @param maximumTxFrameSize maximum Tx frame size
|
||||
*
|
||||
* This function updates the internal data structures and
|
||||
* calls ixEthDBPortFrameLengthsUpdate() for NPE update.
|
||||
*
|
||||
* This function is fully documented in the main header
|
||||
* file, IxEthDB.h.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation was
|
||||
* successfull or an appropriate error message otherwise
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBFilteringPortMaximumTxFrameSizeSet(IxEthDBPortId portID, UINT32 maximumTxFrameSize)
|
||||
{
|
||||
IX_ETH_DB_CHECK_PORT_EXISTS(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
if (!ixEthDBPortInfo[portID].initialized)
|
||||
{
|
||||
return IX_ETH_DB_PORT_UNINITIALIZED;
|
||||
}
|
||||
|
||||
if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
|
||||
{
|
||||
if ((maximumTxFrameSize < IX_ETHDB_MIN_NPE_FRAME_SIZE) ||
|
||||
(maximumTxFrameSize > IX_ETHDB_MAX_NPE_FRAME_SIZE))
|
||||
{
|
||||
return IX_ETH_DB_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return IX_ETH_DB_NO_PERMISSION;
|
||||
}
|
||||
|
||||
/* update internal structure */
|
||||
ixEthDBPortInfo[portID].maxTxFrameSize = maximumTxFrameSize;
|
||||
|
||||
/* update the maximum frame size in the NPE */
|
||||
return ixEthDBPortFrameLengthsUpdate(portID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sets the port maximum Tx and Rx frame sizes
|
||||
*
|
||||
* @param portID ID of the port to set the frame size on
|
||||
* @param maximumFrameSize maximum Tx and Rx frame sizes
|
||||
*
|
||||
* This function updates the internal data structures and
|
||||
* calls ixEthDBPortFrameLengthsUpdate() for NPE update.
|
||||
*
|
||||
* Note that both the maximum Tx and Rx frame size are set
|
||||
* to the same value. This function is kept for compatibility
|
||||
* reasons.
|
||||
*
|
||||
* This function is fully documented in the main header
|
||||
* file, IxEthDB.h.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation was
|
||||
* successfull or an appropriate error message otherwise
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBFilteringPortMaximumFrameSizeSet(IxEthDBPortId portID, UINT32 maximumFrameSize)
|
||||
{
|
||||
IX_ETH_DB_CHECK_PORT_EXISTS(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
if (!ixEthDBPortInfo[portID].initialized)
|
||||
{
|
||||
return IX_ETH_DB_PORT_UNINITIALIZED;
|
||||
}
|
||||
|
||||
if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
|
||||
{
|
||||
if ((maximumFrameSize < IX_ETHDB_MIN_NPE_FRAME_SIZE) ||
|
||||
(maximumFrameSize > IX_ETHDB_MAX_NPE_FRAME_SIZE))
|
||||
{
|
||||
return IX_ETH_DB_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return IX_ETH_DB_NO_PERMISSION;
|
||||
}
|
||||
|
||||
/* update internal structure */
|
||||
ixEthDBPortInfo[portID].maxRxFrameSize = maximumFrameSize;
|
||||
ixEthDBPortInfo[portID].maxTxFrameSize = maximumFrameSize;
|
||||
|
||||
/* update the maximum frame size in the NPE */
|
||||
return ixEthDBPortFrameLengthsUpdate(portID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sets the MAC address of an NPE port
|
||||
*
|
||||
* @param portID port ID to set the MAC address on
|
||||
* @param macAddr pointer to the 6-byte MAC address
|
||||
*
|
||||
* This function is called by the EthAcc
|
||||
* ixEthAccUnicastMacAddressSet() and should not be
|
||||
* manually invoked unless required by special circumstances.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation succeeded
|
||||
* or an appropriate error message otherwise
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBPortAddressSet(IxEthDBPortId portID, IxEthDBMacAddr *macAddr)
|
||||
{
|
||||
IxNpeMhMessage message;
|
||||
IxOsalMutex *ackPortAddressLock;
|
||||
IX_STATUS result;
|
||||
|
||||
/* use this macro instead CHECK_PORT
|
||||
as the port doesn't need to be enabled */
|
||||
IX_ETH_DB_CHECK_PORT_EXISTS(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_REFERENCE(macAddr);
|
||||
|
||||
if (!ixEthDBPortInfo[portID].initialized)
|
||||
{
|
||||
return IX_ETH_DB_PORT_UNINITIALIZED;
|
||||
}
|
||||
|
||||
ackPortAddressLock = &ixEthDBPortInfo[portID].npeAckLock;
|
||||
|
||||
/* Operation stops here when Ethernet Learning is not enabled */
|
||||
if(IX_FEATURE_CTRL_SWCONFIG_DISABLED ==
|
||||
ixFeatureCtrlSwConfigurationCheck(IX_FEATURECTRL_ETH_LEARNING))
|
||||
{
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
/* exit if the port is not an Ethernet NPE */
|
||||
if (ixEthDBPortDefinitions[portID].type != IX_ETH_NPE)
|
||||
{
|
||||
return IX_ETH_DB_INVALID_PORT;
|
||||
}
|
||||
|
||||
/* populate message */
|
||||
FILL_SETPORTADDRESS_MSG(message, portID, macAddr->macAddress);
|
||||
|
||||
IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Sending SetPortAddress on port %d...\n", portID);
|
||||
|
||||
/* send a SetPortAddress message */
|
||||
IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result);
|
||||
|
||||
if (result == IX_SUCCESS)
|
||||
{
|
||||
ixEthDBPortInfo[portID].macAddressUploaded = TRUE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
463
cpu/ixp/npe/IxEthDBCore.c
Normal file
463
cpu/ixp/npe/IxEthDBCore.c
Normal file
@ -0,0 +1,463 @@
|
||||
/**
|
||||
* @file IxEthDBDBCore.c
|
||||
*
|
||||
* @brief Database support functions
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
#include "IxEthDB_p.h"
|
||||
|
||||
/* list of database hashtables */
|
||||
IX_ETH_DB_PUBLIC HashTable dbHashtable;
|
||||
IX_ETH_DB_PUBLIC MatchFunction matchFunctions[IX_ETH_DB_MAX_KEY_INDEX + 1];
|
||||
IX_ETH_DB_PUBLIC BOOL ixEthDBPortUpdateRequired[IX_ETH_DB_MAX_RECORD_TYPE_INDEX + 1];
|
||||
IX_ETH_DB_PUBLIC UINT32 ixEthDBKeyType[IX_ETH_DB_MAX_RECORD_TYPE_INDEX + 1];
|
||||
|
||||
/* private initialization flag */
|
||||
IX_ETH_DB_PRIVATE BOOL ethDBInitializationComplete = FALSE;
|
||||
|
||||
/**
|
||||
* @brief initializes EthDB
|
||||
*
|
||||
* This function must be called to initialize the component.
|
||||
*
|
||||
* It does the following things:
|
||||
* - checks the port definition structure
|
||||
* - scans the capabilities of the NPE images and sets the
|
||||
* capabilities of the ports accordingly
|
||||
* - initializes the memory pools internally used in EthDB
|
||||
* for storing database records and handling data
|
||||
* - registers automatic update handlers for add and remove
|
||||
* operations
|
||||
* - registers hashing match functions, depending on key sets
|
||||
* - initializes the main database hashtable
|
||||
* - allocates contiguous memory zones to be used for NPE
|
||||
* updates
|
||||
* - registers the serialize methods used to convert data
|
||||
* into NPE-readable format
|
||||
* - starts the event processor
|
||||
*
|
||||
* Note that this function is documented in the public
|
||||
* component header file, IxEthDB.h.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS or an appropriate error if the
|
||||
* component failed to initialize correctly
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBInit(void)
|
||||
{
|
||||
IxEthDBStatus result;
|
||||
|
||||
if (ethDBInitializationComplete)
|
||||
{
|
||||
/* redundant */
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
/* trap an invalid port definition structure */
|
||||
IX_ETH_DB_PORTS_ASSERTION;
|
||||
|
||||
/* memory management */
|
||||
ixEthDBInitMemoryPools();
|
||||
|
||||
/* register hashing search methods */
|
||||
ixEthDBMatchMethodsRegister(matchFunctions);
|
||||
|
||||
/* register type-based automatic port updates */
|
||||
ixEthDBUpdateTypeRegister(ixEthDBPortUpdateRequired);
|
||||
|
||||
/* register record to key type mappings */
|
||||
ixEthDBKeyTypeRegister(ixEthDBKeyType);
|
||||
|
||||
/* hash table */
|
||||
ixEthDBInitHash(&dbHashtable, NUM_BUCKETS, ixEthDBEntryXORHash, matchFunctions, (FreeFunction) ixEthDBFreeMacDescriptor);
|
||||
|
||||
/* NPE update zones */
|
||||
ixEthDBNPEUpdateAreasInit();
|
||||
|
||||
/* register record serialization methods */
|
||||
ixEthDBRecordSerializeMethodsRegister();
|
||||
|
||||
/* start the event processor */
|
||||
result = ixEthDBEventProcessorInit();
|
||||
|
||||
/* scan NPE features */
|
||||
if (result == IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
ixEthDBFeatureCapabilityScan();
|
||||
}
|
||||
|
||||
ethDBInitializationComplete = TRUE;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief prepares EthDB for unloading
|
||||
*
|
||||
* This function must be called before removing the
|
||||
* EthDB component from memory (e.g. doing rmmod in
|
||||
* Linux) if the component is to be re-initialized again
|
||||
* without rebooting the platform.
|
||||
*
|
||||
* All the EthDB ports must be disabled before this
|
||||
* function is to be called. Failure to disable all
|
||||
* the ports will return the IX_ETH_DB_BUSY error.
|
||||
*
|
||||
* This function will destroy mutexes, deallocate
|
||||
* memory and stop the event processor.
|
||||
*
|
||||
* Note that this function is fully documented in the
|
||||
* main component header file, IxEthDB.h.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if de-initialization
|
||||
* completed successfully or an appropriate error
|
||||
* message otherwise
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBUnload(void)
|
||||
{
|
||||
IxEthDBPortId portIndex;
|
||||
|
||||
if (!ethDBInitializationComplete)
|
||||
{
|
||||
/* redundant */
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
/* check if any ports are enabled */
|
||||
for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
|
||||
{
|
||||
if (ixEthDBPortInfo[portIndex].enabled)
|
||||
{
|
||||
return IX_ETH_DB_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/* free port resources */
|
||||
for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
|
||||
{
|
||||
if (ixEthDBPortDefinitions[portIndex].type == IX_ETH_NPE)
|
||||
{
|
||||
ixOsalMutexDestroy(&ixEthDBPortInfo[portIndex].npeAckLock);
|
||||
}
|
||||
|
||||
ixEthDBPortInfo[portIndex].initialized = FALSE;
|
||||
}
|
||||
|
||||
/* shutdown event processor */
|
||||
ixEthDBStopLearningFunction();
|
||||
|
||||
/* deallocate NPE update zones */
|
||||
ixEthDBNPEUpdateAreasUnload();
|
||||
|
||||
ethDBInitializationComplete = FALSE;
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief adds a new entry to the Ethernet database
|
||||
*
|
||||
* @param newRecordTemplate address of the record template to use
|
||||
* @param updateTrigger port map containing the update triggers
|
||||
* resulting from this update operation
|
||||
*
|
||||
* Creates a new database entry, populates it with the data
|
||||
* copied from the given template and adds the record to the
|
||||
* database hash table.
|
||||
* It also checks whether the new record type is registered to trigger
|
||||
* automatic updates; if it is, the update trigger will contain the
|
||||
* port on which the record insertion was performed, as well as the
|
||||
* old port in case the addition was a record migration (from one port
|
||||
* to the other). The caller can use the updateTrigger to trigger
|
||||
* automatic updates on the ports changed as a result of this addition.
|
||||
*
|
||||
* @retval IX_ETH_DB_SUCCESS addition successful
|
||||
* @retval IX_ETH_DB_NOMEM insertion failed, no memory left in the mac descriptor memory pool
|
||||
* @retval IX_ETH_DB_BUSY database busy, cannot insert due to locking
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBAdd(MacDescriptor *newRecordTemplate, IxEthDBPortMap updateTrigger)
|
||||
{
|
||||
IxEthDBStatus result;
|
||||
MacDescriptor *newDescriptor;
|
||||
IxEthDBPortId originalPortID;
|
||||
HashNode *node = NULL;
|
||||
|
||||
BUSY_RETRY(ixEthDBSearchHashEntry(&dbHashtable, ixEthDBKeyType[newRecordTemplate->type], newRecordTemplate, &node));
|
||||
|
||||
TEST_FIXTURE_INCREMENT_DB_CORE_ACCESS_COUNTER;
|
||||
|
||||
if (node == NULL)
|
||||
{
|
||||
/* not found, create a new one */
|
||||
newDescriptor = ixEthDBAllocMacDescriptor();
|
||||
|
||||
if (newDescriptor == NULL)
|
||||
{
|
||||
return IX_ETH_DB_NOMEM; /* no memory */
|
||||
}
|
||||
|
||||
/* old port does not exist, avoid unnecessary updates */
|
||||
originalPortID = newRecordTemplate->portID;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* a node with the same key exists, will update node */
|
||||
newDescriptor = (MacDescriptor *) node->data;
|
||||
|
||||
/* save original port id */
|
||||
originalPortID = newDescriptor->portID;
|
||||
}
|
||||
|
||||
/* copy/update fields into new record */
|
||||
memcpy(newDescriptor->macAddress, newRecordTemplate->macAddress, sizeof (IxEthDBMacAddr));
|
||||
memcpy(&newDescriptor->recordData, &newRecordTemplate->recordData, sizeof (IxEthDBRecordData));
|
||||
|
||||
newDescriptor->type = newRecordTemplate->type;
|
||||
newDescriptor->portID = newRecordTemplate->portID;
|
||||
newDescriptor->user = newRecordTemplate->user;
|
||||
|
||||
if (node == NULL)
|
||||
{
|
||||
/* new record, insert into hashtable */
|
||||
BUSY_RETRY_WITH_RESULT(ixEthDBAddHashEntry(&dbHashtable, newDescriptor), result);
|
||||
|
||||
if (result != IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
ixEthDBFreeMacDescriptor(newDescriptor);
|
||||
|
||||
return result; /* insertion failed */
|
||||
}
|
||||
}
|
||||
|
||||
if (node != NULL)
|
||||
{
|
||||
/* release access */
|
||||
ixEthDBReleaseHashNode(node);
|
||||
}
|
||||
|
||||
/* trigger add/remove update if required by type */
|
||||
if (updateTrigger != NULL &&
|
||||
ixEthDBPortUpdateRequired[newRecordTemplate->type])
|
||||
{
|
||||
/* add new port to update list */
|
||||
JOIN_PORT_TO_MAP(updateTrigger, newRecordTemplate->portID);
|
||||
|
||||
/* check if record has moved, we'll need to update the old port as well */
|
||||
if (originalPortID != newDescriptor->portID)
|
||||
{
|
||||
JOIN_PORT_TO_MAP(updateTrigger, originalPortID);
|
||||
}
|
||||
}
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief remove a record from the Ethernet database
|
||||
*
|
||||
* @param templateRecord template record used to determine
|
||||
* what record is to be removed
|
||||
* @param updateTrigger port map containing the update triggers
|
||||
* resulting from this update operation
|
||||
*
|
||||
* This function will examine the template record it receives
|
||||
* and attempts to delete a record of the same type and containing
|
||||
* the same keys as the template record. If deletion is successful
|
||||
* and the record type is registered for automatic port updates the
|
||||
* port will also be set in the updateTrigger port map, so that the
|
||||
* client can perform an update of the port.
|
||||
*
|
||||
* @retval IX_ETH_DB_SUCCESS removal was successful
|
||||
* @retval IX_ETH_DB_NO_SUCH_ADDR the record with the given MAC address was not found
|
||||
* @retval IX_ETH_DB_BUSY database busy, cannot remove due to locking
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBRemove(MacDescriptor *templateRecord, IxEthDBPortMap updateTrigger)
|
||||
{
|
||||
IxEthDBStatus result;
|
||||
|
||||
TEST_FIXTURE_INCREMENT_DB_CORE_ACCESS_COUNTER;
|
||||
|
||||
BUSY_RETRY_WITH_RESULT(ixEthDBRemoveHashEntry(&dbHashtable, ixEthDBKeyType[templateRecord->type], templateRecord), result);
|
||||
|
||||
if (result != IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
return IX_ETH_DB_NO_SUCH_ADDR; /* not found */
|
||||
}
|
||||
|
||||
/* trigger add/remove update if required by type */
|
||||
if (updateTrigger != NULL
|
||||
&&ixEthDBPortUpdateRequired[templateRecord->type])
|
||||
{
|
||||
/* add new port to update list */
|
||||
JOIN_PORT_TO_MAP(updateTrigger, templateRecord->portID);
|
||||
}
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief register record key types
|
||||
*
|
||||
* This function registers the appropriate key types,
|
||||
* depending on record types.
|
||||
*
|
||||
* All filtering records use the MAC address as the key.
|
||||
* WiFi and Firewall records use a compound key consisting
|
||||
* in both the MAC address and the port ID.
|
||||
*
|
||||
* @return the number of registered record types
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
UINT32 ixEthDBKeyTypeRegister(UINT32 *keyType)
|
||||
{
|
||||
/* safety */
|
||||
memset(keyType, 0, sizeof (keyType));
|
||||
|
||||
/* register all known record types */
|
||||
keyType[IX_ETH_DB_FILTERING_RECORD] = IX_ETH_DB_MAC_KEY;
|
||||
keyType[IX_ETH_DB_FILTERING_VLAN_RECORD] = IX_ETH_DB_MAC_KEY;
|
||||
keyType[IX_ETH_DB_ALL_FILTERING_RECORDS] = IX_ETH_DB_MAC_KEY;
|
||||
keyType[IX_ETH_DB_WIFI_RECORD] = IX_ETH_DB_MAC_PORT_KEY;
|
||||
keyType[IX_ETH_DB_FIREWALL_RECORD] = IX_ETH_DB_MAC_PORT_KEY;
|
||||
|
||||
return 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets a user-defined field into a database record
|
||||
*
|
||||
* Note that this function is fully documented in the main component
|
||||
* header file.
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBUserFieldSet(IxEthDBRecordType recordType, IxEthDBMacAddr *macAddr, IxEthDBPortId portID, IxEthDBVlanId vlanID, void *field)
|
||||
{
|
||||
HashNode *result = NULL;
|
||||
|
||||
if (macAddr == NULL)
|
||||
{
|
||||
return IX_ETH_DB_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (recordType == IX_ETH_DB_FILTERING_RECORD)
|
||||
{
|
||||
result = ixEthDBSearch(macAddr, recordType);
|
||||
}
|
||||
else if (recordType == IX_ETH_DB_FILTERING_VLAN_RECORD)
|
||||
{
|
||||
result = ixEthDBVlanSearch(macAddr, vlanID, recordType);
|
||||
}
|
||||
else if (recordType == IX_ETH_DB_WIFI_RECORD || recordType == IX_ETH_DB_FIREWALL_RECORD)
|
||||
{
|
||||
IX_ETH_DB_CHECK_PORT_EXISTS(portID);
|
||||
|
||||
result = ixEthDBPortSearch(macAddr, portID, recordType);
|
||||
}
|
||||
else
|
||||
{
|
||||
return IX_ETH_DB_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (result == NULL)
|
||||
{
|
||||
return IX_ETH_DB_NO_SUCH_ADDR;
|
||||
}
|
||||
|
||||
((MacDescriptor *) result->data)->user = field;
|
||||
|
||||
ixEthDBReleaseHashNode(result);
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves a user-defined field from a database record
|
||||
*
|
||||
* Note that this function is fully documented in the main component
|
||||
* header file.
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBUserFieldGet(IxEthDBRecordType recordType, IxEthDBMacAddr *macAddr, IxEthDBPortId portID, IxEthDBVlanId vlanID, void **field)
|
||||
{
|
||||
HashNode *result = NULL;
|
||||
|
||||
if (macAddr == NULL || field == NULL)
|
||||
{
|
||||
return IX_ETH_DB_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (recordType == IX_ETH_DB_FILTERING_RECORD)
|
||||
{
|
||||
result = ixEthDBSearch(macAddr, recordType);
|
||||
}
|
||||
else if (recordType == IX_ETH_DB_FILTERING_VLAN_RECORD)
|
||||
{
|
||||
result = ixEthDBVlanSearch(macAddr, vlanID, recordType);
|
||||
}
|
||||
else if (recordType == IX_ETH_DB_WIFI_RECORD || recordType == IX_ETH_DB_FIREWALL_RECORD)
|
||||
{
|
||||
IX_ETH_DB_CHECK_PORT_EXISTS(portID);
|
||||
|
||||
result = ixEthDBPortSearch(macAddr, portID, recordType);
|
||||
}
|
||||
else
|
||||
{
|
||||
return IX_ETH_DB_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (result == NULL)
|
||||
{
|
||||
return IX_ETH_DB_NO_SUCH_ADDR;
|
||||
}
|
||||
|
||||
*field = ((MacDescriptor *) result->data)->user;
|
||||
|
||||
ixEthDBReleaseHashNode(result);
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
520
cpu/ixp/npe/IxEthDBEvents.c
Normal file
520
cpu/ixp/npe/IxEthDBEvents.c
Normal file
@ -0,0 +1,520 @@
|
||||
/**
|
||||
* @file IxEthDBEvents.c
|
||||
*
|
||||
* @brief Implementation of the event processor component
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
#include <IxNpeMh.h>
|
||||
#include <IxFeatureCtrl.h>
|
||||
|
||||
#include "IxEthDB_p.h"
|
||||
|
||||
/* forward prototype declarations */
|
||||
IX_ETH_DB_PUBLIC void ixEthDBEventProcessorLoop(void *);
|
||||
IX_ETH_DB_PUBLIC void ixEthDBNPEEventCallback(IxNpeMhNpeId npeID, IxNpeMhMessage msg);
|
||||
IX_ETH_DB_PRIVATE void ixEthDBProcessEvent(PortEvent *local_event, IxEthDBPortMap triggerPorts);
|
||||
IX_ETH_DB_PRIVATE IxEthDBStatus ixEthDBTriggerPortUpdate(UINT32 eventType, IxEthDBMacAddr *macAddr, IxEthDBPortId portID, BOOL staticEntry);
|
||||
IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBStartLearningFunction(void);
|
||||
IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBStopLearningFunction(void);
|
||||
|
||||
/* data */
|
||||
IX_ETH_DB_PRIVATE IxOsalSemaphore eventQueueSemaphore;
|
||||
IX_ETH_DB_PRIVATE PortEventQueue eventQueue;
|
||||
IX_ETH_DB_PRIVATE IxOsalMutex eventQueueLock;
|
||||
IX_ETH_DB_PRIVATE IxOsalMutex portUpdateLock;
|
||||
|
||||
IX_ETH_DB_PRIVATE BOOL ixEthDBLearningShutdown = FALSE;
|
||||
IX_ETH_DB_PRIVATE BOOL ixEthDBEventProcessorRunning = FALSE;
|
||||
|
||||
/* imported data */
|
||||
extern HashTable dbHashtable;
|
||||
|
||||
/**
|
||||
* @brief initializes the event processor
|
||||
*
|
||||
* Initializes the event processor queue and processing thread.
|
||||
* Called from ixEthDBInit() DB-subcomponent master init function.
|
||||
*
|
||||
* @warning do not call directly
|
||||
*
|
||||
* @retval IX_ETH_DB_SUCCESS initialization was successful
|
||||
* @retval IX_ETH_DB_FAIL initialization failed (OSAL or mutex init failure)
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBEventProcessorInit(void)
|
||||
{
|
||||
if (ixOsalMutexInit(&portUpdateLock) != IX_SUCCESS)
|
||||
{
|
||||
return IX_ETH_DB_FAIL;
|
||||
}
|
||||
|
||||
if (ixOsalMutexInit(&eventQueueLock) != IX_SUCCESS)
|
||||
{
|
||||
return IX_ETH_DB_FAIL;
|
||||
}
|
||||
|
||||
if (IX_FEATURE_CTRL_SWCONFIG_ENABLED ==
|
||||
ixFeatureCtrlSwConfigurationCheck (IX_FEATURECTRL_ETH_LEARNING))
|
||||
{
|
||||
|
||||
/* start processor loop thread */
|
||||
if (ixEthDBStartLearningFunction() != IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
return IX_ETH_DB_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief initializes the event queue and the event processor
|
||||
*
|
||||
* This function is called by the component initialization
|
||||
* function, ixEthDBInit().
|
||||
*
|
||||
* @warning do not call directly
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed
|
||||
* successfully or IX_ETH_DB_FAIL otherwise
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBStartLearningFunction(void)
|
||||
{
|
||||
IxOsalThread eventProcessorThread;
|
||||
IxOsalThreadAttr threadAttr;
|
||||
|
||||
threadAttr.name = "EthDB event thread";
|
||||
threadAttr.stackSize = 32 * 1024; /* 32kbytes */
|
||||
threadAttr.priority = 128;
|
||||
|
||||
/* reset event queue */
|
||||
ixOsalMutexLock(&eventQueueLock, IX_OSAL_WAIT_FOREVER);
|
||||
|
||||
RESET_QUEUE(&eventQueue);
|
||||
|
||||
ixOsalMutexUnlock(&eventQueueLock);
|
||||
|
||||
/* init event queue semaphore */
|
||||
if (ixOsalSemaphoreInit(&eventQueueSemaphore, 0) != IX_SUCCESS)
|
||||
{
|
||||
return IX_ETH_DB_FAIL;
|
||||
}
|
||||
|
||||
ixEthDBLearningShutdown = FALSE;
|
||||
|
||||
/* create processor loop thread */
|
||||
if (ixOsalThreadCreate(&eventProcessorThread, &threadAttr, ixEthDBEventProcessorLoop, NULL) != IX_SUCCESS)
|
||||
{
|
||||
return IX_ETH_DB_FAIL;
|
||||
}
|
||||
|
||||
/* start event processor */
|
||||
ixOsalThreadStart(&eventProcessorThread);
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief stops the event processor
|
||||
*
|
||||
* Stops the event processor and frees the event queue semaphore
|
||||
* Called by the component de-initialization function, ixEthDBUnload()
|
||||
*
|
||||
* @warning do not call directly
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed
|
||||
* successfully or IX_ETH_DB_FAIL otherwise;
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBStopLearningFunction(void)
|
||||
{
|
||||
ixEthDBLearningShutdown = TRUE;
|
||||
|
||||
/* wake up event processing loop to actually process the shutdown event */
|
||||
ixOsalSemaphorePost(&eventQueueSemaphore);
|
||||
|
||||
if (ixOsalSemaphoreDestroy(&eventQueueSemaphore) != IX_SUCCESS)
|
||||
{
|
||||
return IX_ETH_DB_FAIL;
|
||||
}
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief default NPE event processing callback
|
||||
*
|
||||
* @param npeID ID of the NPE that generated the event
|
||||
* @param msg NPE message (encapsulated event)
|
||||
*
|
||||
* Creates an event object on the Ethernet event processor queue
|
||||
* and signals the new event by incrementing the event queue semaphore.
|
||||
* Events are processed by @ref ixEthDBEventProcessorLoop() which runs
|
||||
* at user level.
|
||||
*
|
||||
* @see ixEthDBEventProcessorLoop()
|
||||
*
|
||||
* @warning do not call directly
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
void ixEthDBNPEEventCallback(IxNpeMhNpeId npeID, IxNpeMhMessage msg)
|
||||
{
|
||||
PortEvent *local_event;
|
||||
|
||||
IX_ETH_DB_IRQ_EVENTS_TRACE("DB: (Events) new event received by processor callback from port %d, id 0x%X\n", IX_ETH_DB_NPE_TO_PORT_ID(npeID), NPE_MSG_ID(msg), 0, 0, 0, 0);
|
||||
|
||||
if (CAN_ENQUEUE(&eventQueue))
|
||||
{
|
||||
TEST_FIXTURE_LOCK_EVENT_QUEUE;
|
||||
|
||||
local_event = QUEUE_HEAD(&eventQueue);
|
||||
|
||||
/* create event structure on queue */
|
||||
local_event->eventType = NPE_MSG_ID(msg);
|
||||
local_event->portID = IX_ETH_DB_NPE_TO_PORT_ID(npeID);
|
||||
|
||||
/* update queue */
|
||||
PUSH_UPDATE_QUEUE(&eventQueue);
|
||||
|
||||
TEST_FIXTURE_UNLOCK_EVENT_QUEUE;
|
||||
|
||||
IX_ETH_DB_IRQ_EVENTS_TRACE("DB: (Events) Waking up main processor loop...\n", 0, 0, 0, 0, 0, 0);
|
||||
|
||||
/* increment event queue semaphore */
|
||||
ixOsalSemaphorePost(&eventQueueSemaphore);
|
||||
}
|
||||
else
|
||||
{
|
||||
IX_ETH_DB_IRQ_EVENTS_TRACE("DB: (Events) Warning: could not enqueue event (overflow)\n", 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Ethernet event processor loop
|
||||
*
|
||||
* Extracts at most EVENT_PROCESSING_LIMIT batches of events and
|
||||
* sends them for processing to @ref ixEthDBProcessEvent().
|
||||
* Triggers port updates which normally follow learning events.
|
||||
*
|
||||
* @warning do not call directly, executes in separate thread
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
void ixEthDBEventProcessorLoop(void *unused1)
|
||||
{
|
||||
IxEthDBPortMap triggerPorts;
|
||||
IxEthDBPortId portIndex;
|
||||
|
||||
ixEthDBEventProcessorRunning = TRUE;
|
||||
|
||||
IX_ETH_DB_EVENTS_TRACE("DB: (Events) Event processor loop was started\n");
|
||||
|
||||
while (!ixEthDBLearningShutdown)
|
||||
{
|
||||
BOOL keepProcessing = TRUE;
|
||||
UINT32 processedEvents = 0;
|
||||
|
||||
IX_ETH_DB_EVENTS_VERBOSE_TRACE("DB: (Events) Waiting for new learning event...\n");
|
||||
|
||||
ixOsalSemaphoreWait(&eventQueueSemaphore, IX_OSAL_WAIT_FOREVER);
|
||||
|
||||
IX_ETH_DB_EVENTS_VERBOSE_TRACE("DB: (Events) Received new event\n");
|
||||
|
||||
if (!ixEthDBLearningShutdown)
|
||||
{
|
||||
/* port update handling */
|
||||
SET_EMPTY_DEPENDENCY_MAP(triggerPorts);
|
||||
|
||||
while (keepProcessing)
|
||||
{
|
||||
PortEvent local_event;
|
||||
UINT32 intLockKey;
|
||||
|
||||
/* lock queue */
|
||||
ixOsalMutexLock(&eventQueueLock, IX_OSAL_WAIT_FOREVER);
|
||||
|
||||
/* lock NPE interrupts */
|
||||
intLockKey = ixOsalIrqLock();
|
||||
|
||||
/* extract event */
|
||||
local_event = *(QUEUE_TAIL(&eventQueue));
|
||||
|
||||
SHIFT_UPDATE_QUEUE(&eventQueue);
|
||||
|
||||
ixOsalIrqUnlock(intLockKey);
|
||||
|
||||
ixOsalMutexUnlock(&eventQueueLock);
|
||||
|
||||
IX_ETH_DB_EVENTS_TRACE("DB: (Events) Processing event with ID 0x%X\n", local_event.eventType);
|
||||
|
||||
ixEthDBProcessEvent(&local_event, triggerPorts);
|
||||
|
||||
processedEvents++;
|
||||
|
||||
if (processedEvents > EVENT_PROCESSING_LIMIT /* maximum burst reached? */
|
||||
|| ixOsalSemaphoreTryWait(&eventQueueSemaphore) != IX_SUCCESS) /* or empty queue? */
|
||||
{
|
||||
keepProcessing = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
ixEthDBUpdatePortLearningTrees(triggerPorts);
|
||||
}
|
||||
}
|
||||
|
||||
/* turn off automatic updates */
|
||||
for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
|
||||
{
|
||||
ixEthDBPortInfo[portIndex].updateMethod.updateEnabled = FALSE;
|
||||
}
|
||||
|
||||
ixEthDBEventProcessorRunning = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief event processor routine
|
||||
*
|
||||
* @param event event to be processed
|
||||
* @param triggerPorts port map accumulating ports to be updated
|
||||
*
|
||||
* Processes learning events by synchronizing the database with
|
||||
* newly learnt data. Called only by @ref ixEthDBEventProcessorLoop().
|
||||
*
|
||||
* @warning do not call directly
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PRIVATE
|
||||
void ixEthDBProcessEvent(PortEvent *local_event, IxEthDBPortMap triggerPorts)
|
||||
{
|
||||
MacDescriptor recordTemplate;
|
||||
|
||||
switch (local_event->eventType)
|
||||
{
|
||||
case IX_ETH_DB_ADD_FILTERING_RECORD:
|
||||
/* add record */
|
||||
memset(&recordTemplate, 0, sizeof (recordTemplate));
|
||||
memcpy(recordTemplate.macAddress, local_event->macAddr.macAddress, sizeof (IxEthDBMacAddr));
|
||||
|
||||
recordTemplate.type = IX_ETH_DB_FILTERING_RECORD;
|
||||
recordTemplate.portID = local_event->portID;
|
||||
recordTemplate.recordData.filteringData.staticEntry = local_event->staticEntry;
|
||||
|
||||
ixEthDBAdd(&recordTemplate, triggerPorts);
|
||||
|
||||
IX_ETH_DB_EVENTS_TRACE("DB: (Events) Added record on port %d\n", local_event->portID);
|
||||
|
||||
break;
|
||||
|
||||
case IX_ETH_DB_REMOVE_FILTERING_RECORD:
|
||||
/* remove record */
|
||||
memset(&recordTemplate, 0, sizeof (recordTemplate));
|
||||
memcpy(recordTemplate.macAddress, local_event->macAddr.macAddress, sizeof (IxEthDBMacAddr));
|
||||
|
||||
recordTemplate.type = IX_ETH_DB_FILTERING_RECORD | IX_ETH_DB_FILTERING_VLAN_RECORD;
|
||||
|
||||
ixEthDBRemove(&recordTemplate, triggerPorts);
|
||||
|
||||
IX_ETH_DB_EVENTS_TRACE("DB: (Events) Removed record on port %d\n", local_event->portID);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
/* can't handle/not interested in this event type */
|
||||
ERROR_LOG("DB: (Events) Event processor received an unknown event type (0x%X)\n", local_event->eventType);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief asynchronously adds a filtering record
|
||||
* by posting an ADD_FILTERING_RECORD event to the event queue
|
||||
*
|
||||
* @param macAddr MAC address of the new record
|
||||
* @param portID port ID of the new record
|
||||
* @param staticEntry TRUE if record is static, FALSE if dynamic
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the event creation was
|
||||
* successfull or IX_ETH_DB_BUSY if the event queue is full
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBTriggerAddPortUpdate(IxEthDBMacAddr *macAddr, IxEthDBPortId portID, BOOL staticEntry)
|
||||
{
|
||||
MacDescriptor reference;
|
||||
|
||||
TEST_FIXTURE_INCREMENT_DB_CORE_ACCESS_COUNTER;
|
||||
|
||||
/* fill search fields */
|
||||
memcpy(reference.macAddress, macAddr, sizeof (IxEthDBMacAddr));
|
||||
reference.portID = portID;
|
||||
|
||||
/* set acceptable record types */
|
||||
reference.type = IX_ETH_DB_ALL_FILTERING_RECORDS;
|
||||
|
||||
if (ixEthDBPeekHashEntry(&dbHashtable, IX_ETH_DB_MAC_PORT_KEY, &reference) == IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
/* already have an identical record */
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ixEthDBTriggerPortUpdate(IX_ETH_DB_ADD_FILTERING_RECORD, macAddr, portID, staticEntry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief asynchronously removes a filtering record
|
||||
* by posting a REMOVE_FILTERING_RECORD event to the event queue
|
||||
*
|
||||
* @param macAddr MAC address of the record to remove
|
||||
* @param portID port ID of the record to remove
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the event creation was
|
||||
* successfull or IX_ETH_DB_BUSY if the event queue is full
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBTriggerRemovePortUpdate(IxEthDBMacAddr *macAddr, IxEthDBPortId portID)
|
||||
{
|
||||
if (ixEthDBPeek(macAddr, IX_ETH_DB_ALL_FILTERING_RECORDS) != IX_ETH_DB_NO_SUCH_ADDR)
|
||||
{
|
||||
return ixEthDBTriggerPortUpdate(IX_ETH_DB_REMOVE_FILTERING_RECORD, macAddr, portID, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
return IX_ETH_DB_NO_SUCH_ADDR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief adds an ADD or REMOVE event to the main event queue
|
||||
*
|
||||
* @param eventType event type - IX_ETH_DB_ADD_FILTERING_RECORD
|
||||
* to add and IX_ETH_DB_REMOVE_FILTERING_RECORD to remove a
|
||||
* record.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the event was successfully
|
||||
* sent or IX_ETH_DB_BUSY if the event queue is full
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PRIVATE
|
||||
IxEthDBStatus ixEthDBTriggerPortUpdate(UINT32 eventType, IxEthDBMacAddr *macAddr, IxEthDBPortId portID, BOOL staticEntry)
|
||||
{
|
||||
UINT32 intLockKey;
|
||||
|
||||
/* lock interrupts to protect queue */
|
||||
intLockKey = ixOsalIrqLock();
|
||||
|
||||
if (CAN_ENQUEUE(&eventQueue))
|
||||
{
|
||||
PortEvent *queueEvent = QUEUE_HEAD(&eventQueue);
|
||||
|
||||
/* update fields on the queue */
|
||||
memcpy(queueEvent->macAddr.macAddress, macAddr->macAddress, sizeof (IxEthDBMacAddr));
|
||||
|
||||
queueEvent->eventType = eventType;
|
||||
queueEvent->portID = portID;
|
||||
queueEvent->staticEntry = staticEntry;
|
||||
|
||||
PUSH_UPDATE_QUEUE(&eventQueue);
|
||||
|
||||
/* imcrement event queue semaphore */
|
||||
ixOsalSemaphorePost(&eventQueueSemaphore);
|
||||
|
||||
/* unlock interrupts */
|
||||
ixOsalIrqUnlock(intLockKey);
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
else /* event queue full */
|
||||
{
|
||||
/* unlock interrupts */
|
||||
ixOsalIrqUnlock(intLockKey);
|
||||
|
||||
return IX_ETH_DB_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Locks learning tree updates and port disable
|
||||
*
|
||||
*
|
||||
* This function locks portUpdateLock single mutex. It is primarily used
|
||||
* to avoid executing 'port disable' during ELT maintenance.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
void ixEthDBUpdateLock(void)
|
||||
{
|
||||
ixOsalMutexLock(&portUpdateLock, IX_OSAL_WAIT_FOREVER);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unlocks learning tree updates and port disable
|
||||
*
|
||||
*
|
||||
* This function unlocks a portUpdateLock mutex. It is primarily used
|
||||
* to avoid executing 'port disable' during ELT maintenance.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
void ixEthDBUpdateUnlock(void)
|
||||
{
|
||||
ixOsalMutexUnlock(&portUpdateLock);
|
||||
}
|
||||
|
662
cpu/ixp/npe/IxEthDBFeatures.c
Normal file
662
cpu/ixp/npe/IxEthDBFeatures.c
Normal file
@ -0,0 +1,662 @@
|
||||
/**
|
||||
* @file IxEthDBFeatures.c
|
||||
*
|
||||
* @brief Implementation of the EthDB feature control API
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
#include "IxNpeDl.h"
|
||||
#include "IxEthDBQoS.h"
|
||||
#include "IxEthDB_p.h"
|
||||
|
||||
/**
|
||||
* @brief scans the capabilities of the loaded NPE images
|
||||
*
|
||||
* This function MUST be called by the ixEthDBInit() function.
|
||||
* No EthDB features (including learning and filtering) are enabled
|
||||
* before this function is called.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
void ixEthDBFeatureCapabilityScan(void)
|
||||
{
|
||||
IxNpeDlImageId imageId, npeAImageId;
|
||||
IxEthDBPortId portIndex;
|
||||
PortInfo *portInfo;
|
||||
IxEthDBPriorityTable defaultPriorityTable;
|
||||
IX_STATUS result;
|
||||
UINT32 queueIndex;
|
||||
UINT32 queueStructureIndex;
|
||||
UINT32 trafficClassDefinitionIndex;
|
||||
|
||||
/* read version of NPE A - required to set the AQM queues for B and C */
|
||||
npeAImageId.functionalityId = 0;
|
||||
ixNpeDlLoadedImageGet(IX_NPEDL_NPEID_NPEA, &npeAImageId);
|
||||
|
||||
for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
|
||||
{
|
||||
IxNpeMhMessage msg;
|
||||
|
||||
portInfo = &ixEthDBPortInfo[portIndex];
|
||||
|
||||
/* check and bypass if NPE B or C is fused out */
|
||||
if (ixEthDBSingleEthNpeCheck(portIndex) != IX_ETH_DB_SUCCESS) continue;
|
||||
|
||||
/* all ports are capable of LEARNING by default */
|
||||
portInfo->featureCapability |= IX_ETH_DB_LEARNING;
|
||||
portInfo->featureStatus |= IX_ETH_DB_LEARNING;
|
||||
|
||||
if (ixEthDBPortDefinitions[portIndex].type == IX_ETH_NPE)
|
||||
{
|
||||
|
||||
if (ixNpeDlLoadedImageGet(IX_ETH_DB_PORT_ID_TO_NPE(portIndex), &imageId) != IX_SUCCESS)
|
||||
{
|
||||
WARNING_LOG("DB: (FeatureScan) NpeDl did not provide the image ID for NPE port %d\n", portIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* initialize and empty NPE response mutex */
|
||||
ixOsalMutexInit(&portInfo->npeAckLock);
|
||||
ixOsalMutexLock(&portInfo->npeAckLock, IX_OSAL_WAIT_FOREVER);
|
||||
|
||||
/* check NPE response to GetStatus */
|
||||
msg.data[0] = IX_ETHNPE_NPE_GETSTATUS << 24;
|
||||
msg.data[1] = 0;
|
||||
IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portIndex), msg, result);
|
||||
if (result != IX_SUCCESS)
|
||||
{
|
||||
WARNING_LOG("DB: (FeatureScan) warning, could not send message to the NPE\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (imageId.functionalityId == 0x00
|
||||
|| imageId.functionalityId == 0x03
|
||||
|| imageId.functionalityId == 0x04
|
||||
|| imageId.functionalityId == 0x80)
|
||||
{
|
||||
portInfo->featureCapability |= IX_ETH_DB_FILTERING;
|
||||
portInfo->featureCapability |= IX_ETH_DB_FIREWALL;
|
||||
portInfo->featureCapability |= IX_ETH_DB_SPANNING_TREE_PROTOCOL;
|
||||
}
|
||||
else if (imageId.functionalityId == 0x01
|
||||
|| imageId.functionalityId == 0x81)
|
||||
{
|
||||
portInfo->featureCapability |= IX_ETH_DB_FILTERING;
|
||||
portInfo->featureCapability |= IX_ETH_DB_FIREWALL;
|
||||
portInfo->featureCapability |= IX_ETH_DB_SPANNING_TREE_PROTOCOL;
|
||||
portInfo->featureCapability |= IX_ETH_DB_VLAN_QOS;
|
||||
}
|
||||
else if (imageId.functionalityId == 0x02
|
||||
|| imageId.functionalityId == 0x82)
|
||||
{
|
||||
portInfo->featureCapability |= IX_ETH_DB_WIFI_HEADER_CONVERSION;
|
||||
portInfo->featureCapability |= IX_ETH_DB_FIREWALL;
|
||||
portInfo->featureCapability |= IX_ETH_DB_SPANNING_TREE_PROTOCOL;
|
||||
portInfo->featureCapability |= IX_ETH_DB_VLAN_QOS;
|
||||
}
|
||||
|
||||
/* reset AQM queues */
|
||||
memset(portInfo->ixEthDBTrafficClassAQMAssignments, 0, sizeof (portInfo->ixEthDBTrafficClassAQMAssignments));
|
||||
|
||||
/* ensure there's at least one traffic class record in the definition table, otherwise we have no default case, hence no queues */
|
||||
IX_ENSURE(sizeof (ixEthDBTrafficClassDefinitions) != 0, "DB: no traffic class definitions found, check IxEthDBQoS.h");
|
||||
|
||||
/* find the traffic class definition index compatible with the current NPE A functionality ID */
|
||||
for (trafficClassDefinitionIndex = 0 ;
|
||||
trafficClassDefinitionIndex < sizeof (ixEthDBTrafficClassDefinitions) / sizeof (ixEthDBTrafficClassDefinitions[0]);
|
||||
trafficClassDefinitionIndex++)
|
||||
{
|
||||
if (ixEthDBTrafficClassDefinitions[trafficClassDefinitionIndex][IX_ETH_DB_NPE_A_FUNCTIONALITY_ID_INDEX] == npeAImageId.functionalityId)
|
||||
{
|
||||
/* found it */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* select the default case if we went over the array boundary */
|
||||
if (trafficClassDefinitionIndex == sizeof (ixEthDBTrafficClassDefinitions) / sizeof (ixEthDBTrafficClassDefinitions[0]))
|
||||
{
|
||||
trafficClassDefinitionIndex = 0; /* the first record is the default case */
|
||||
}
|
||||
|
||||
/* select queue assignment structure based on the traffic class configuration index */
|
||||
queueStructureIndex = ixEthDBTrafficClassDefinitions[trafficClassDefinitionIndex][IX_ETH_DB_QUEUE_ASSIGNMENT_INDEX];
|
||||
|
||||
/* only traffic class 0 is active at initialization time */
|
||||
portInfo->ixEthDBTrafficClassCount = 1;
|
||||
|
||||
/* enable port, VLAN and Firewall feature bits to initialize QoS/VLAN/Firewall configuration */
|
||||
portInfo->featureStatus |= IX_ETH_DB_VLAN_QOS;
|
||||
portInfo->featureStatus |= IX_ETH_DB_FIREWALL;
|
||||
portInfo->enabled = TRUE;
|
||||
|
||||
#define CONFIG_WITH_VLAN /* test-only: VLAN support not included to save space!!! */
|
||||
#ifdef CONFIG_WITH_VLAN /* test-only: VLAN support not included to save space!!! */
|
||||
/* set VLAN initial configuration (permissive) */
|
||||
if ((portInfo->featureCapability & IX_ETH_DB_VLAN_QOS) != 0) /* QoS-enabled image */
|
||||
{
|
||||
/* QoS capable */
|
||||
portInfo->ixEthDBTrafficClassAvailable = ixEthDBTrafficClassDefinitions[trafficClassDefinitionIndex][IX_ETH_DB_TRAFFIC_CLASS_COUNT_INDEX];
|
||||
|
||||
/* set AQM queues */
|
||||
for (queueIndex = 0 ; queueIndex < IX_IEEE802_1Q_QOS_PRIORITY_COUNT ; queueIndex++)
|
||||
{
|
||||
portInfo->ixEthDBTrafficClassAQMAssignments[queueIndex] = ixEthDBQueueAssignments[queueStructureIndex][queueIndex];
|
||||
}
|
||||
|
||||
/* set default PVID (0) and default traffic class 0 */
|
||||
ixEthDBPortVlanTagSet(portIndex, 0);
|
||||
|
||||
/* enable reception of all frames */
|
||||
ixEthDBAcceptableFrameTypeSet(portIndex, IX_ETH_DB_ACCEPT_ALL_FRAMES);
|
||||
|
||||
/* clear full VLAN membership */
|
||||
ixEthDBPortVlanMembershipRangeRemove(portIndex, 0, IX_ETH_DB_802_1Q_MAX_VLAN_ID);
|
||||
|
||||
/* clear TTI table - no VLAN tagged frames will be transmitted */
|
||||
ixEthDBEgressVlanRangeTaggingEnabledSet(portIndex, 0, 4094, FALSE);
|
||||
|
||||
/* set membership on 0, otherwise no Tx or Rx is working */
|
||||
ixEthDBPortVlanMembershipAdd(portIndex, 0);
|
||||
}
|
||||
else /* QoS not available in this image */
|
||||
#endif /* test-only */
|
||||
{
|
||||
/* initialize traffic class availability (only class 0 is available) */
|
||||
portInfo->ixEthDBTrafficClassAvailable = 1;
|
||||
|
||||
/* point all AQM queues to traffic class 0 */
|
||||
for (queueIndex = 0 ; queueIndex < IX_IEEE802_1Q_QOS_PRIORITY_COUNT ; queueIndex++)
|
||||
{
|
||||
portInfo->ixEthDBTrafficClassAQMAssignments[queueIndex] =
|
||||
ixEthDBQueueAssignments[queueStructureIndex][0];
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_WITH_VLAN /* test-only: VLAN support not included to save space!!! */
|
||||
/* download priority mapping table and Rx queue configuration */
|
||||
memset (defaultPriorityTable, 0, sizeof (defaultPriorityTable));
|
||||
ixEthDBPriorityMappingTableSet(portIndex, defaultPriorityTable);
|
||||
#endif
|
||||
|
||||
/* by default we turn off invalid source MAC address filtering */
|
||||
ixEthDBFirewallInvalidAddressFilterEnable(portIndex, FALSE);
|
||||
|
||||
/* disable port, VLAN, Firewall feature bits */
|
||||
portInfo->featureStatus &= ~IX_ETH_DB_VLAN_QOS;
|
||||
portInfo->featureStatus &= ~IX_ETH_DB_FIREWALL;
|
||||
portInfo->enabled = FALSE;
|
||||
|
||||
/* enable filtering by default if present */
|
||||
if ((portInfo->featureCapability & IX_ETH_DB_FILTERING) != 0)
|
||||
{
|
||||
portInfo->featureStatus |= IX_ETH_DB_FILTERING;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief returns the capability of a port
|
||||
*
|
||||
* @param portID ID of the port
|
||||
* @param featureSet location to store the port capability in
|
||||
*
|
||||
* This function will save the capability set of the given port
|
||||
* into the given location. Capabilities are bit-ORed, each representing
|
||||
* a bit of the feature set.
|
||||
*
|
||||
* Note that this function is documented in the main component
|
||||
* public header file, IxEthDB.h.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed successfully
|
||||
* or IX_ETH_DB_INVALID_PORT if the given port is invalid
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBFeatureCapabilityGet(IxEthDBPortId portID, IxEthDBFeature *featureSet)
|
||||
{
|
||||
IX_ETH_DB_CHECK_PORT_INITIALIZED(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_REFERENCE(featureSet);
|
||||
|
||||
*featureSet = ixEthDBPortInfo[portID].featureCapability;
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief enables or disables a port capability
|
||||
*
|
||||
* @param portID ID of the port
|
||||
* @param feature feature to enable or disable
|
||||
* @param enabled TRUE to enable the selected feature or FALSE to disable it
|
||||
*
|
||||
* Note that this function is documented in the main component
|
||||
* header file, IxEthDB.h.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed
|
||||
* successfully or an appropriate error message otherwise
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBFeatureEnable(IxEthDBPortId portID, IxEthDBFeature feature, BOOL enable)
|
||||
{
|
||||
PortInfo *portInfo;
|
||||
IxEthDBPriorityTable defaultPriorityTable;
|
||||
IxEthDBVlanSet vlanSet;
|
||||
IxEthDBStatus status = IX_ETH_DB_SUCCESS;
|
||||
BOOL portEnabled;
|
||||
|
||||
IX_ETH_DB_CHECK_PORT_INITIALIZED(portID);
|
||||
|
||||
portInfo = &ixEthDBPortInfo[portID];
|
||||
portEnabled = portInfo->enabled;
|
||||
|
||||
/* check that only one feature is selected */
|
||||
if (!ixEthDBCheckSingleBitValue(feature))
|
||||
{
|
||||
return IX_ETH_DB_FEATURE_UNAVAILABLE;
|
||||
}
|
||||
|
||||
/* port capable of this feature? */
|
||||
if ((portInfo->featureCapability & feature) == 0)
|
||||
{
|
||||
return IX_ETH_DB_FEATURE_UNAVAILABLE;
|
||||
}
|
||||
|
||||
/* mutual exclusion between learning and WiFi header conversion */
|
||||
if (enable && ((feature | portInfo->featureStatus) & (IX_ETH_DB_FILTERING | IX_ETH_DB_WIFI_HEADER_CONVERSION))
|
||||
== (IX_ETH_DB_FILTERING | IX_ETH_DB_WIFI_HEADER_CONVERSION))
|
||||
{
|
||||
return IX_ETH_DB_NO_PERMISSION;
|
||||
}
|
||||
|
||||
/* learning must be enabled before filtering */
|
||||
if (enable && (feature == IX_ETH_DB_FILTERING) && ((portInfo->featureStatus & IX_ETH_DB_LEARNING) == 0))
|
||||
{
|
||||
return IX_ETH_DB_NO_PERMISSION;
|
||||
}
|
||||
|
||||
/* filtering must be disabled before learning */
|
||||
if (!enable && (feature == IX_ETH_DB_LEARNING) && ((portInfo->featureStatus & IX_ETH_DB_FILTERING) != 0))
|
||||
{
|
||||
return IX_ETH_DB_NO_PERMISSION;
|
||||
}
|
||||
|
||||
/* redundant enabling or disabling */
|
||||
if ((!enable && ((portInfo->featureStatus & feature) == 0))
|
||||
|| (enable && ((portInfo->featureStatus & feature) != 0)))
|
||||
{
|
||||
/* do nothing */
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
/* force port enabled */
|
||||
portInfo->enabled = TRUE;
|
||||
|
||||
if (enable)
|
||||
{
|
||||
/* turn on enable bit */
|
||||
portInfo->featureStatus |= feature;
|
||||
|
||||
#ifdef CONFIG_WITH_VLAN /* test-only: VLAN support not included to save space!!! */
|
||||
/* if this is VLAN/QoS set the default priority table */
|
||||
if (feature == IX_ETH_DB_VLAN_QOS)
|
||||
{
|
||||
/* turn on VLAN/QoS (most permissive mode):
|
||||
- set default 802.1Q priority mapping table, in accordance to the
|
||||
availability of traffic classes
|
||||
- set the acceptable frame filter to accept all
|
||||
- set the Ingress tagging mode to pass-through
|
||||
- set full VLAN membership list
|
||||
- set full TTI table
|
||||
- set the default 802.1Q tag to 0 (VLAN ID 0, Pri 0, CFI 0)
|
||||
- enable TPID port extraction
|
||||
*/
|
||||
|
||||
portInfo->ixEthDBTrafficClassCount = portInfo->ixEthDBTrafficClassAvailable;
|
||||
|
||||
/* set default 802.1Q priority mapping table - note that C indexing starts from 0, so we substract 1 here */
|
||||
memcpy (defaultPriorityTable,
|
||||
(const void *) ixEthIEEE802_1QUserPriorityToTrafficClassMapping[portInfo->ixEthDBTrafficClassCount - 1],
|
||||
sizeof (defaultPriorityTable));
|
||||
|
||||
/* update priority mapping and AQM queue assignments */
|
||||
status = ixEthDBPriorityMappingTableSet(portID, defaultPriorityTable);
|
||||
|
||||
if (status == IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
status = ixEthDBAcceptableFrameTypeSet(portID, IX_ETH_DB_ACCEPT_ALL_FRAMES);
|
||||
}
|
||||
|
||||
if (status == IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
status = ixEthDBIngressVlanTaggingEnabledSet(portID, IX_ETH_DB_PASS_THROUGH);
|
||||
}
|
||||
|
||||
/* set membership and TTI tables */
|
||||
memset (vlanSet, 0xFF, sizeof (vlanSet));
|
||||
|
||||
if (status == IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
/* use the internal function to bypass PVID check */
|
||||
status = ixEthDBPortVlanTableSet(portID, portInfo->vlanMembership, vlanSet);
|
||||
}
|
||||
|
||||
if (status == IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
/* use the internal function to bypass PVID check */
|
||||
status = ixEthDBPortVlanTableSet(portID, portInfo->transmitTaggingInfo, vlanSet);
|
||||
}
|
||||
|
||||
/* reset the PVID */
|
||||
if (status == IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
status = ixEthDBPortVlanTagSet(portID, 0);
|
||||
}
|
||||
|
||||
/* enable TPID port extraction */
|
||||
if (status == IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
status = ixEthDBVlanPortExtractionEnable(portID, TRUE);
|
||||
}
|
||||
}
|
||||
else if (feature == IX_ETH_DB_FIREWALL)
|
||||
#endif
|
||||
{
|
||||
/* firewall starts in black-list mode unless otherwise configured before *
|
||||
* note that invalid source MAC address filtering is disabled by default */
|
||||
if (portInfo->firewallMode != IX_ETH_DB_FIREWALL_BLACK_LIST
|
||||
&& portInfo->firewallMode != IX_ETH_DB_FIREWALL_WHITE_LIST)
|
||||
{
|
||||
status = ixEthDBFirewallModeSet(portID, IX_ETH_DB_FIREWALL_BLACK_LIST);
|
||||
|
||||
if (status == IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
status = ixEthDBFirewallInvalidAddressFilterEnable(portID, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (status != IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
/* checks failed, disable */
|
||||
portInfo->featureStatus &= ~feature;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* turn off features */
|
||||
if (feature == IX_ETH_DB_FIREWALL)
|
||||
{
|
||||
/* turning off the firewall is equivalent to:
|
||||
- set to black-list mode
|
||||
- clear all the entries and download the new table
|
||||
- turn off the invalid source address checking
|
||||
*/
|
||||
|
||||
status = ixEthDBDatabaseClear(portID, IX_ETH_DB_FIREWALL_RECORD);
|
||||
|
||||
if (status == IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
status = ixEthDBFirewallModeSet(portID, IX_ETH_DB_FIREWALL_BLACK_LIST);
|
||||
}
|
||||
|
||||
if (status == IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
status = ixEthDBFirewallInvalidAddressFilterEnable(portID, FALSE);
|
||||
}
|
||||
|
||||
if (status == IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
status = ixEthDBFirewallTableDownload(portID);
|
||||
}
|
||||
}
|
||||
else if (feature == IX_ETH_DB_WIFI_HEADER_CONVERSION)
|
||||
{
|
||||
/* turn off header conversion */
|
||||
status = ixEthDBDatabaseClear(portID, IX_ETH_DB_WIFI_RECORD);
|
||||
|
||||
if (status == IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
status = ixEthDBWiFiConversionTableDownload(portID);
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_WITH_VLAN /* test-only: VLAN support not included to save space!!! */
|
||||
else if (feature == IX_ETH_DB_VLAN_QOS)
|
||||
{
|
||||
/* turn off VLAN/QoS:
|
||||
- set a priority mapping table with one traffic class
|
||||
- set the acceptable frame filter to accept all
|
||||
- set the Ingress tagging mode to pass-through
|
||||
- clear the VLAN membership list
|
||||
- clear the TTI table
|
||||
- set the default 802.1Q tag to 0 (VLAN ID 0, Pri 0, CFI 0)
|
||||
- disable TPID port extraction
|
||||
*/
|
||||
|
||||
/* initialize all => traffic class 0 priority mapping table */
|
||||
memset (defaultPriorityTable, 0, sizeof (defaultPriorityTable));
|
||||
portInfo->ixEthDBTrafficClassCount = 1;
|
||||
status = ixEthDBPriorityMappingTableSet(portID, defaultPriorityTable);
|
||||
|
||||
if (status == IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
status = ixEthDBAcceptableFrameTypeSet(portID, IX_ETH_DB_ACCEPT_ALL_FRAMES);
|
||||
}
|
||||
|
||||
if (status == IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
status = ixEthDBIngressVlanTaggingEnabledSet(portID, IX_ETH_DB_PASS_THROUGH);
|
||||
}
|
||||
|
||||
/* clear membership and TTI tables */
|
||||
memset (vlanSet, 0, sizeof (vlanSet));
|
||||
|
||||
if (status == IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
/* use the internal function to bypass PVID check */
|
||||
status = ixEthDBPortVlanTableSet(portID, portInfo->vlanMembership, vlanSet);
|
||||
}
|
||||
|
||||
if (status == IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
/* use the internal function to bypass PVID check */
|
||||
status = ixEthDBPortVlanTableSet(portID, portInfo->transmitTaggingInfo, vlanSet);
|
||||
}
|
||||
|
||||
/* reset the PVID */
|
||||
if (status == IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
status = ixEthDBPortVlanTagSet(portID, 0);
|
||||
}
|
||||
|
||||
/* disable TPID port extraction */
|
||||
if (status == IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
status = ixEthDBVlanPortExtractionEnable(portID, FALSE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (status == IX_ETH_DB_SUCCESS)
|
||||
{
|
||||
/* checks passed, disable */
|
||||
portInfo->featureStatus &= ~feature;
|
||||
}
|
||||
}
|
||||
|
||||
/* restore port enabled state */
|
||||
portInfo->enabled = portEnabled;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief returns the status of a feature
|
||||
*
|
||||
* @param portID port ID
|
||||
* @param present location to store a boolean value indicating
|
||||
* if the feature is present (TRUE) or not (FALSE)
|
||||
* @param enabled location to store a booleam value indicating
|
||||
* if the feature is present (TRUE) or not (FALSE)
|
||||
*
|
||||
* Note that this function is documented in the main component
|
||||
* header file, IxEthDB.h.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed
|
||||
* successfully or an appropriate error message otherwise
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBFeatureStatusGet(IxEthDBPortId portID, IxEthDBFeature feature, BOOL *present, BOOL *enabled)
|
||||
{
|
||||
PortInfo *portInfo;
|
||||
|
||||
IX_ETH_DB_CHECK_PORT(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_REFERENCE(present);
|
||||
|
||||
IX_ETH_DB_CHECK_REFERENCE(enabled);
|
||||
|
||||
portInfo = &ixEthDBPortInfo[portID];
|
||||
|
||||
*present = (portInfo->featureCapability & feature) != 0;
|
||||
*enabled = (portInfo->featureStatus & feature) != 0;
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief returns the value of an EthDB property
|
||||
*
|
||||
* @param portID ID of the port
|
||||
* @param feature feature owning the property
|
||||
* @param property ID of the property
|
||||
* @param type location to store the property type into
|
||||
* @param value location to store the property value into
|
||||
*
|
||||
* Note that this function is documented in the main component
|
||||
* header file, IxEthDB.h.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed
|
||||
* successfully or an appropriate error message otherwise
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBFeaturePropertyGet(IxEthDBPortId portID, IxEthDBFeature feature, IxEthDBProperty property, IxEthDBPropertyType *type, void *value)
|
||||
{
|
||||
IX_ETH_DB_CHECK_PORT_EXISTS(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_REFERENCE(type);
|
||||
|
||||
IX_ETH_DB_CHECK_REFERENCE(value);
|
||||
|
||||
if (feature == IX_ETH_DB_VLAN_QOS)
|
||||
{
|
||||
if (property == IX_ETH_DB_QOS_TRAFFIC_CLASS_COUNT_PROPERTY)
|
||||
{
|
||||
* (UINT32 *) value = ixEthDBPortInfo[portID].ixEthDBTrafficClassCount;
|
||||
*type = IX_ETH_DB_INTEGER_PROPERTY;
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
else if (property >= IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY
|
||||
&& property <= IX_ETH_DB_QOS_TRAFFIC_CLASS_7_RX_QUEUE_PROPERTY)
|
||||
{
|
||||
UINT32 classDelta = property - IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY;
|
||||
|
||||
if (classDelta >= ixEthDBPortInfo[portID].ixEthDBTrafficClassCount)
|
||||
{
|
||||
return IX_ETH_DB_FAIL;
|
||||
}
|
||||
|
||||
* (UINT32 *) value = ixEthDBPortInfo[portID].ixEthDBTrafficClassAQMAssignments[classDelta];
|
||||
*type = IX_ETH_DB_INTEGER_PROPERTY;
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return IX_ETH_DB_INVALID_ARG;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sets the value of an EthDB property
|
||||
*
|
||||
* @param portID ID of the port
|
||||
* @param feature feature owning the property
|
||||
* @param property ID of the property
|
||||
* @param value location containing the property value
|
||||
*
|
||||
* This function implements a private property intended
|
||||
* only for EthAcc usage. Upon setting the IX_ETH_DB_QOS_QUEUE_CONFIGURATION_COMPLETE
|
||||
* property (the value is ignored), the availability of traffic classes is
|
||||
* frozen to whatever traffic class structure is currently in use.
|
||||
* This means that if VLAN_QOS has been enabled before EthAcc
|
||||
* initialization then all the defined traffic classes will be available;
|
||||
* otherwise only one traffic class (0) will be available.
|
||||
*
|
||||
* Note that this function is documented in the main component
|
||||
* header file, IxEthDB.h as not accepting any parameters. The
|
||||
* current implementation is only intended for the private use of EthAcc.
|
||||
*
|
||||
* Also note that once this function is called the effect is irreversible,
|
||||
* unless EthDB is complete unloaded and re-initialized.
|
||||
*
|
||||
* @return IX_ETH_DB_INVALID_ARG (no read-write properties are
|
||||
* supported in this release)
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBFeaturePropertySet(IxEthDBPortId portID, IxEthDBFeature feature, IxEthDBProperty property, void *value)
|
||||
{
|
||||
IX_ETH_DB_CHECK_PORT_EXISTS(portID);
|
||||
|
||||
if ((feature == IX_ETH_DB_VLAN_QOS) && (property == IX_ETH_DB_QOS_QUEUE_CONFIGURATION_COMPLETE))
|
||||
{
|
||||
ixEthDBPortInfo[portID].ixEthDBTrafficClassAvailable = ixEthDBPortInfo[portID].ixEthDBTrafficClassCount;
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
return IX_ETH_DB_INVALID_ARG;
|
||||
}
|
266
cpu/ixp/npe/IxEthDBFirewall.c
Normal file
266
cpu/ixp/npe/IxEthDBFirewall.c
Normal file
@ -0,0 +1,266 @@
|
||||
/**
|
||||
* @file IxEthDBFirewall.c
|
||||
*
|
||||
* @brief Implementation of the firewall API
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
|
||||
#include "IxEthDB_p.h"
|
||||
|
||||
/**
|
||||
* @brief updates the NPE firewall operating mode and
|
||||
* firewall address table
|
||||
*
|
||||
* @param portID ID of the port
|
||||
* @param epDelta initial entry point for binary searches (NPE optimization)
|
||||
* @param address address of the firewall MAC address table
|
||||
*
|
||||
* This function will send a message to the NPE configuring the
|
||||
* firewall mode (white list or black list), invalid source
|
||||
* address filtering and downloading a new MAC address database
|
||||
* to be used for firewall matching.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed
|
||||
* successfully or IX_ETH_DB_FAIL otherwise
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBFirewallUpdate(IxEthDBPortId portID, void *address, UINT32 epDelta)
|
||||
{
|
||||
IxNpeMhMessage message;
|
||||
IX_STATUS result;
|
||||
|
||||
UINT32 mode = 0;
|
||||
PortInfo *portInfo = &ixEthDBPortInfo[portID];
|
||||
|
||||
mode = (portInfo->srcAddressFilterEnabled != FALSE) << 1 | (portInfo->firewallMode == IX_ETH_DB_FIREWALL_WHITE_LIST);
|
||||
|
||||
FILL_SETFIREWALLMODE_MSG(message,
|
||||
IX_ETH_DB_PORT_ID_TO_NPE_LOGICAL_ID(portID),
|
||||
epDelta,
|
||||
mode,
|
||||
IX_OSAL_MMU_VIRT_TO_PHYS(address));
|
||||
|
||||
IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief configures the firewall white list/black list
|
||||
* access mode
|
||||
*
|
||||
* @param portID ID of the port
|
||||
* @param mode firewall filtering mode (IX_ETH_DB_FIREWALL_WHITE_LIST
|
||||
* or IX_ETH_DB_FIREWALL_BLACK_LIST)
|
||||
*
|
||||
* Note that this function is documented in the main component
|
||||
* header file, IxEthDB.h.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed
|
||||
* successfully or an appropriate error message otherwise
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBFirewallModeSet(IxEthDBPortId portID, IxEthDBFirewallMode mode)
|
||||
{
|
||||
IX_ETH_DB_CHECK_PORT(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_FIREWALL);
|
||||
|
||||
if (mode != IX_ETH_DB_FIREWALL_WHITE_LIST
|
||||
&& mode != IX_ETH_DB_FIREWALL_BLACK_LIST)
|
||||
{
|
||||
return IX_ETH_DB_INVALID_ARG;
|
||||
}
|
||||
|
||||
ixEthDBPortInfo[portID].firewallMode = mode;
|
||||
|
||||
return ixEthDBFirewallTableDownload(portID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief enables or disables the invalid source MAC address filter
|
||||
*
|
||||
* @param portID ID of the port
|
||||
* @param enable TRUE to enable invalid source MAC address filtering
|
||||
* or FALSE to disable it
|
||||
*
|
||||
* The invalid source MAC address filter will discard, when enabled,
|
||||
* frames whose source MAC address is a multicast or the broadcast MAC
|
||||
* address.
|
||||
*
|
||||
* Note that this function is documented in the main component
|
||||
* header file, IxEthDB.h.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed
|
||||
* successfully or an appropriate error message otherwise
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBFirewallInvalidAddressFilterEnable(IxEthDBPortId portID, BOOL enable)
|
||||
{
|
||||
IX_ETH_DB_CHECK_PORT(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_FIREWALL);
|
||||
|
||||
ixEthDBPortInfo[portID].srcAddressFilterEnabled = enable;
|
||||
|
||||
return ixEthDBFirewallTableDownload(portID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief adds a firewall record
|
||||
*
|
||||
* @param portID ID of the port
|
||||
* @param macAddr MAC address of the new record
|
||||
*
|
||||
* This function will add a new firewall record
|
||||
* on the specified port, using the specified
|
||||
* MAC address. If the record already exists this
|
||||
* function will silently return IX_ETH_DB_SUCCESS,
|
||||
* although no duplicate records are added.
|
||||
*
|
||||
* Note that this function is documented in the main
|
||||
* component header file, IxEthDB.h.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed
|
||||
* successfully or an appropriate error message otherwise
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBFirewallEntryAdd(IxEthDBPortId portID, IxEthDBMacAddr *macAddr)
|
||||
{
|
||||
MacDescriptor recordTemplate;
|
||||
|
||||
IX_ETH_DB_CHECK_PORT(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_REFERENCE(macAddr);
|
||||
|
||||
IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_FIREWALL);
|
||||
|
||||
memcpy(recordTemplate.macAddress, macAddr, sizeof (IxEthDBMacAddr));
|
||||
|
||||
recordTemplate.type = IX_ETH_DB_FIREWALL_RECORD;
|
||||
recordTemplate.portID = portID;
|
||||
|
||||
return ixEthDBAdd(&recordTemplate, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief removes a firewall record
|
||||
*
|
||||
* @param portID ID of the port
|
||||
* @param macAddr MAC address of the record to remove
|
||||
*
|
||||
* This function will attempt to remove a firewall
|
||||
* record from the given port, using the specified
|
||||
* MAC address.
|
||||
*
|
||||
* Note that this function is documented in the main
|
||||
* component header file, IxEthDB.h.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed
|
||||
* successfully of an appropriate error message otherwise
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBFirewallEntryRemove(IxEthDBPortId portID, IxEthDBMacAddr *macAddr)
|
||||
{
|
||||
MacDescriptor recordTemplate;
|
||||
|
||||
IX_ETH_DB_CHECK_PORT(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_REFERENCE(macAddr);
|
||||
|
||||
IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_FIREWALL);
|
||||
|
||||
memcpy(recordTemplate.macAddress, macAddr, sizeof (IxEthDBMacAddr));
|
||||
|
||||
recordTemplate.type = IX_ETH_DB_FIREWALL_RECORD;
|
||||
recordTemplate.portID = portID;
|
||||
|
||||
return ixEthDBRemove(&recordTemplate, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief downloads the firewall address table to an NPE
|
||||
*
|
||||
* @param portID ID of the port
|
||||
*
|
||||
* This function will download the firewall address table to
|
||||
* an NPE port.
|
||||
*
|
||||
* Note that this function is documented in the main
|
||||
* component header file, IxEthDB.h.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed
|
||||
* successfully or IX_ETH_DB_FAIL otherwise
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBFirewallTableDownload(IxEthDBPortId portID)
|
||||
{
|
||||
IxEthDBPortMap query;
|
||||
IxEthDBStatus result;
|
||||
|
||||
IX_ETH_DB_CHECK_PORT(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_FIREWALL);
|
||||
|
||||
SET_DEPENDENCY_MAP(query, portID);
|
||||
|
||||
ixEthDBUpdateLock();
|
||||
|
||||
ixEthDBPortInfo[portID].updateMethod.searchTree = ixEthDBQuery(NULL, query, IX_ETH_DB_FIREWALL_RECORD, MAX_FW_SIZE);
|
||||
|
||||
result = ixEthDBNPEUpdateHandler(portID, IX_ETH_DB_FIREWALL_RECORD);
|
||||
|
||||
ixEthDBUpdateUnlock();
|
||||
|
||||
return result;
|
||||
}
|
642
cpu/ixp/npe/IxEthDBHashtable.c
Normal file
642
cpu/ixp/npe/IxEthDBHashtable.c
Normal file
@ -0,0 +1,642 @@
|
||||
/**
|
||||
* @file ethHash.c
|
||||
*
|
||||
* @brief Hashtable implementation
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
|
||||
#include "IxEthDB_p.h"
|
||||
#include "IxEthDBLocks_p.h"
|
||||
|
||||
/**
|
||||
* @addtogroup EthDB
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief initializes a hash table object
|
||||
*
|
||||
* @param hashTable uninitialized hash table structure
|
||||
* @param numBuckets number of buckets to use
|
||||
* @param entryHashFunction hash function used
|
||||
* to hash entire hash node data block (for adding)
|
||||
* @param matchFunctions array of match functions, indexed on type,
|
||||
* used to differentiate records with the same hash value
|
||||
* @param freeFunction function used to free node data blocks
|
||||
*
|
||||
* Initializes the given hash table object.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
void ixEthDBInitHash(HashTable *hashTable,
|
||||
UINT32 numBuckets,
|
||||
HashFunction entryHashFunction,
|
||||
MatchFunction *matchFunctions,
|
||||
FreeFunction freeFunction)
|
||||
{
|
||||
UINT32 bucketIndex;
|
||||
UINT32 hashSize = numBuckets * sizeof(HashNode *);
|
||||
|
||||
/* entry hashing, matching and freeing methods */
|
||||
hashTable->entryHashFunction = entryHashFunction;
|
||||
hashTable->matchFunctions = matchFunctions;
|
||||
hashTable->freeFunction = freeFunction;
|
||||
|
||||
/* buckets */
|
||||
hashTable->numBuckets = numBuckets;
|
||||
|
||||
/* set to 0 all buckets */
|
||||
memset(hashTable->hashBuckets, 0, hashSize);
|
||||
|
||||
/* init bucket locks - note that initially all mutexes are unlocked after MutexInit()*/
|
||||
for (bucketIndex = 0 ; bucketIndex < numBuckets ; bucketIndex++)
|
||||
{
|
||||
ixOsalFastMutexInit(&hashTable->bucketLocks[bucketIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief adds an entry to the hash table
|
||||
*
|
||||
* @param hashTable hash table to add the entry to
|
||||
* @param entry entry to add
|
||||
*
|
||||
* The entry will be hashed using the entry hashing function and added to the
|
||||
* hash table, unless a locking blockage occurs, in which case the caller
|
||||
* should retry.
|
||||
*
|
||||
* @retval IX_ETH_DB_SUCCESS if adding <i>entry</i> has succeeded
|
||||
* @retval IX_ETH_DB_NOMEM if there's no memory left in the hash node pool
|
||||
* @retval IX_ETH_DB_BUSY if there's a locking failure on the insertion path
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBAddHashEntry(HashTable *hashTable, void *entry)
|
||||
{
|
||||
UINT32 hashValue = hashTable->entryHashFunction(entry);
|
||||
UINT32 bucketIndex = hashValue % hashTable->numBuckets;
|
||||
HashNode *bucket = hashTable->hashBuckets[bucketIndex];
|
||||
HashNode *newNode;
|
||||
|
||||
LockStack locks;
|
||||
|
||||
INIT_STACK(&locks);
|
||||
|
||||
/* lock bucket */
|
||||
PUSH_LOCK(&locks, &hashTable->bucketLocks[bucketIndex]);
|
||||
|
||||
/* lock insertion element (first in chain), if any */
|
||||
if (bucket != NULL)
|
||||
{
|
||||
PUSH_LOCK(&locks, &bucket->lock);
|
||||
}
|
||||
|
||||
/* get new node */
|
||||
newNode = ixEthDBAllocHashNode();
|
||||
|
||||
if (newNode == NULL)
|
||||
{
|
||||
/* unlock everything */
|
||||
UNROLL_STACK(&locks);
|
||||
|
||||
return IX_ETH_DB_NOMEM;
|
||||
}
|
||||
|
||||
/* init lock - note that mutexes are unlocked after MutexInit */
|
||||
ixOsalFastMutexInit(&newNode->lock);
|
||||
|
||||
/* populate new link */
|
||||
newNode->data = entry;
|
||||
|
||||
/* add to bucket */
|
||||
newNode->next = bucket;
|
||||
hashTable->hashBuckets[bucketIndex] = newNode;
|
||||
|
||||
/* unlock bucket and insertion point */
|
||||
UNROLL_STACK(&locks);
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief removes an entry from the hashtable
|
||||
*
|
||||
* @param hashTable hash table to remove entry from
|
||||
* @param keyType type of record key used for matching
|
||||
* @param reference reference key used to identify the entry
|
||||
*
|
||||
* The reference key will be hashed using the key hashing function,
|
||||
* the entry is searched using the hashed value and then examined
|
||||
* against the reference entry using the match function. A positive
|
||||
* match will trigger the deletion of the entry.
|
||||
* Locking failures are reported and the caller should retry.
|
||||
*
|
||||
* @retval IX_ETH_DB_SUCCESS if the removal was successful
|
||||
* @retval IX_ETH_DB_NO_SUCH_ADDR if the entry was not found
|
||||
* @retval IX_ETH_DB_BUSY if a locking failure occured during the process
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IxEthDBStatus ixEthDBRemoveHashEntry(HashTable *hashTable, int keyType, void *reference)
|
||||
{
|
||||
UINT32 hashValue = hashTable->entryHashFunction(reference);
|
||||
UINT32 bucketIndex = hashValue % hashTable->numBuckets;
|
||||
HashNode *node = hashTable->hashBuckets[bucketIndex];
|
||||
HashNode *previousNode = NULL;
|
||||
|
||||
LockStack locks;
|
||||
|
||||
INIT_STACK(&locks);
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
/* try to lock node */
|
||||
PUSH_LOCK(&locks, &node->lock);
|
||||
|
||||
if (hashTable->matchFunctions[keyType](reference, node->data))
|
||||
{
|
||||
/* found entry */
|
||||
if (node->next != NULL)
|
||||
{
|
||||
PUSH_LOCK(&locks, &node->next->lock);
|
||||
}
|
||||
|
||||
if (previousNode == NULL)
|
||||
{
|
||||
/* node is head of chain */
|
||||
PUSH_LOCK(&locks, &hashTable->bucketLocks[bucketIndex]);
|
||||
|
||||
hashTable->hashBuckets[bucketIndex] = node->next;
|
||||
|
||||
POP_LOCK(&locks);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* relink */
|
||||
previousNode->next = node->next;
|
||||
}
|
||||
|
||||
UNROLL_STACK(&locks);
|
||||
|
||||
/* free node */
|
||||
hashTable->freeFunction(node->data);
|
||||
ixEthDBFreeHashNode(node);
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (previousNode != NULL)
|
||||
{
|
||||
/* unlock previous node */
|
||||
SHIFT_STACK(&locks);
|
||||
}
|
||||
|
||||
/* advance to next element in chain */
|
||||
previousNode = node;
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
|
||||
UNROLL_STACK(&locks);
|
||||
|
||||
/* not found */
|
||||
return IX_ETH_DB_NO_SUCH_ADDR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief retrieves an entry from the hash table
|
||||
*
|
||||
* @param hashTable hash table to perform the search into
|
||||
* @param reference search key (a MAC address)
|
||||
* @param keyType type of record key used for matching
|
||||
* @param searchResult pointer where a reference to the located hash node
|
||||
* is placed
|
||||
*
|
||||
* Searches the entry with the same key as <i>reference</i> and places the
|
||||
* pointer to the resulting node in <i>searchResult</i>.
|
||||
* An implicit write access lock is granted after a search, which gives the
|
||||
* caller the opportunity to modify the entry.
|
||||
* Access should be released as soon as possible using @ref ixEthDBReleaseHashNode().
|
||||
*
|
||||
* @see ixEthDBReleaseHashNode()
|
||||
*
|
||||
* @retval IX_ETH_DB_SUCCESS if the search was completed successfully
|
||||
* @retval IX_ETH_DB_NO_SUCH_ADDRESS if no entry with the given key was found
|
||||
* @retval IX_ETH_DB_BUSY if a locking failure has occured, in which case
|
||||
* the caller should retry
|
||||
*
|
||||
* @warning unless the return value is <b>IX_ETH_DB_SUCCESS</b> the searchResult
|
||||
* location is NOT modified and therefore using a NULL comparison test when the
|
||||
* value was not properly initialized would be an error
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IxEthDBStatus ixEthDBSearchHashEntry(HashTable *hashTable, int keyType, void *reference, HashNode **searchResult)
|
||||
{
|
||||
UINT32 hashValue;
|
||||
HashNode *node;
|
||||
|
||||
hashValue = hashTable->entryHashFunction(reference);
|
||||
node = hashTable->hashBuckets[hashValue % hashTable->numBuckets];
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
TRY_LOCK(&node->lock);
|
||||
|
||||
if (hashTable->matchFunctions[keyType](reference, node->data))
|
||||
{
|
||||
*searchResult = node;
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
UNLOCK(&node->lock);
|
||||
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* not found */
|
||||
return IX_ETH_DB_NO_SUCH_ADDR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief reports the existence of an entry in the hash table
|
||||
*
|
||||
* @param hashTable hash table to perform the search into
|
||||
* @param reference search key (a MAC address)
|
||||
* @param keyType type of record key used for matching
|
||||
*
|
||||
* Searches the entry with the same key as <i>reference</i>.
|
||||
* No implicit write access lock is granted after a search, hence the
|
||||
* caller cannot access or modify the entry. The result is only temporary.
|
||||
*
|
||||
* @see ixEthDBReleaseHashNode()
|
||||
*
|
||||
* @retval IX_ETH_DB_SUCCESS if the search was completed successfully
|
||||
* @retval IX_ETH_DB_NO_SUCH_ADDRESS if no entry with the given key was found
|
||||
* @retval IX_ETH_DB_BUSY if a locking failure has occured, in which case
|
||||
* the caller should retry
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IxEthDBStatus ixEthDBPeekHashEntry(HashTable *hashTable, int keyType, void *reference)
|
||||
{
|
||||
UINT32 hashValue;
|
||||
HashNode *node;
|
||||
|
||||
hashValue = hashTable->entryHashFunction(reference);
|
||||
node = hashTable->hashBuckets[hashValue % hashTable->numBuckets];
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
TRY_LOCK(&node->lock);
|
||||
|
||||
if (hashTable->matchFunctions[keyType](reference, node->data))
|
||||
{
|
||||
UNLOCK(&node->lock);
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
UNLOCK(&node->lock);
|
||||
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* not found */
|
||||
return IX_ETH_DB_NO_SUCH_ADDR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief releases the write access lock
|
||||
*
|
||||
* @pre the node should have been obtained via @ref ixEthDBSearchHashEntry()
|
||||
*
|
||||
* @see ixEthDBSearchHashEntry()
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
void ixEthDBReleaseHashNode(HashNode *node)
|
||||
{
|
||||
UNLOCK(&node->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief initializes a hash iterator
|
||||
*
|
||||
* @param hashTable hash table to be iterated
|
||||
* @param iterator iterator object
|
||||
*
|
||||
* If the initialization is successful the iterator will point to the
|
||||
* first hash table record (if any).
|
||||
* Testing if the iterator has not passed the end of the table should be
|
||||
* done using the IS_ITERATOR_VALID(iteratorPtr) macro.
|
||||
* An implicit write access lock is granted on the entry pointed by the iterator.
|
||||
* The access is automatically revoked when the iterator is incremented.
|
||||
* If the caller decides to terminate the iteration before the end of the table is
|
||||
* passed then the manual access release method, @ref ixEthDBReleaseHashIterator,
|
||||
* must be called.
|
||||
*
|
||||
* @see ixEthDBReleaseHashIterator()
|
||||
*
|
||||
* @retval IX_ETH_DB_SUCCESS if initialization was successful and the iterator points
|
||||
* to the first valid table node
|
||||
* @retval IX_ETH_DB_FAIL if the table is empty
|
||||
* @retval IX_ETH_DB_BUSY if a locking failure has occured, in which case the caller
|
||||
* should retry
|
||||
*
|
||||
* @warning do not use ixEthDBReleaseHashNode() on entries pointed by the iterator, as this
|
||||
* might place the database in a permanent invalid lock state
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IxEthDBStatus ixEthDBInitHashIterator(HashTable *hashTable, HashIterator *iterator)
|
||||
{
|
||||
iterator->bucketIndex = 0;
|
||||
iterator->node = NULL;
|
||||
iterator->previousNode = NULL;
|
||||
|
||||
return ixEthDBIncrementHashIterator(hashTable, iterator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief releases the write access locks of the iterator nodes
|
||||
*
|
||||
* @warning use of this function is required only when the caller terminates an iteration
|
||||
* before reaching the end of the table
|
||||
*
|
||||
* @see ixEthDBInitHashIterator()
|
||||
* @see ixEthDBIncrementHashIterator()
|
||||
*
|
||||
* @param iterator iterator whose node(s) should be unlocked
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
void ixEthDBReleaseHashIterator(HashIterator *iterator)
|
||||
{
|
||||
if (iterator->previousNode != NULL)
|
||||
{
|
||||
UNLOCK(&iterator->previousNode->lock);
|
||||
}
|
||||
|
||||
if (iterator->node != NULL)
|
||||
{
|
||||
UNLOCK(&iterator->node->lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief incremenents an iterator so that it points to the next valid entry of the table
|
||||
* (if any)
|
||||
*
|
||||
* @param hashTable hash table to iterate
|
||||
* @param iterator iterator object
|
||||
*
|
||||
* @pre the iterator object must be initialized using @ref ixEthDBInitHashIterator()
|
||||
*
|
||||
* If the increment operation is successful the iterator will point to the
|
||||
* next hash table record (if any).
|
||||
* Testing if the iterator has not passed the end of the table should be
|
||||
* done using the IS_ITERATOR_VALID(iteratorPtr) macro.
|
||||
* An implicit write access lock is granted on the entry pointed by the iterator.
|
||||
* The access is automatically revoked when the iterator is re-incremented.
|
||||
* If the caller decides to terminate the iteration before the end of the table is
|
||||
* passed then the manual access release method, @ref ixEthDBReleaseHashIterator,
|
||||
* must be called.
|
||||
* Is is guaranteed that no other thread can remove or change the iterated entry until
|
||||
* the iterator is incremented successfully.
|
||||
*
|
||||
* @see ixEthDBReleaseHashIterator()
|
||||
*
|
||||
* @retval IX_ETH_DB_SUCCESS if the operation was successful and the iterator points
|
||||
* to the next valid table node
|
||||
* @retval IX_ETH_DB_FAIL if the iterator has passed the end of the table
|
||||
* @retval IX_ETH_DB_BUSY if a locking failure has occured, in which case the caller
|
||||
* should retry
|
||||
*
|
||||
* @warning do not use ixEthDBReleaseHashNode() on entries pointed by the iterator, as this
|
||||
* might place the database in a permanent invalid lock state
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IxEthDBStatus ixEthDBIncrementHashIterator(HashTable *hashTable, HashIterator *iterator)
|
||||
{
|
||||
/* unless iterator is just initialized... */
|
||||
if (iterator->node != NULL)
|
||||
{
|
||||
/* try next in chain */
|
||||
if (iterator->node->next != NULL)
|
||||
{
|
||||
TRY_LOCK(&iterator->node->next->lock);
|
||||
|
||||
if (iterator->previousNode != NULL)
|
||||
{
|
||||
UNLOCK(&iterator->previousNode->lock);
|
||||
}
|
||||
|
||||
iterator->previousNode = iterator->node;
|
||||
iterator->node = iterator->node->next;
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* last in chain, prepare for next bucket */
|
||||
iterator->bucketIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
/* try next used bucket */
|
||||
for (; iterator->bucketIndex < hashTable->numBuckets ; iterator->bucketIndex++)
|
||||
{
|
||||
HashNode **nodePtr = &(hashTable->hashBuckets[iterator->bucketIndex]);
|
||||
HashNode *node = *nodePtr;
|
||||
#if (CPU!=SIMSPARCSOLARIS) && !defined (__wince)
|
||||
if (((iterator->bucketIndex & IX_ETHDB_BUCKET_INDEX_MASK) == 0) &&
|
||||
(iterator->bucketIndex < (hashTable->numBuckets - IX_ETHDB_BUCKETPTR_AHEAD)))
|
||||
{
|
||||
/* preload next cache line (2 cache line ahead) */
|
||||
nodePtr += IX_ETHDB_BUCKETPTR_AHEAD;
|
||||
__asm__ ("pld [%0];\n": : "r" (nodePtr));
|
||||
}
|
||||
#endif
|
||||
if (node != NULL)
|
||||
{
|
||||
TRY_LOCK(&node->lock);
|
||||
|
||||
/* unlock last one or two nodes in the previous chain */
|
||||
if (iterator->node != NULL)
|
||||
{
|
||||
UNLOCK(&iterator->node->lock);
|
||||
|
||||
if (iterator->previousNode != NULL)
|
||||
{
|
||||
UNLOCK(&iterator->previousNode->lock);
|
||||
}
|
||||
}
|
||||
|
||||
/* redirect iterator */
|
||||
iterator->previousNode = NULL;
|
||||
iterator->node = node;
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* could not advance iterator */
|
||||
if (iterator->node != NULL)
|
||||
{
|
||||
UNLOCK(&iterator->node->lock);
|
||||
|
||||
if (iterator->previousNode != NULL)
|
||||
{
|
||||
UNLOCK(&iterator->previousNode->lock);
|
||||
}
|
||||
|
||||
iterator->node = NULL;
|
||||
}
|
||||
|
||||
return IX_ETH_DB_END;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief removes an entry pointed by an iterator
|
||||
*
|
||||
* @param hashTable iterated hash table
|
||||
* @param iterator iterator object
|
||||
*
|
||||
* Removes the entry currently pointed by the iterator and repositions the iterator
|
||||
* on the next valid entry (if any). Handles locking issues automatically and
|
||||
* implicitely grants write access lock to the new pointed entry.
|
||||
* Failures due to concurrent threads having write access locks in the same region
|
||||
* preserve the state of the database and the iterator object, leaving the caller
|
||||
* free to retry without loss of access. It is guaranteed that only the thread owning
|
||||
* the iterator can remove the object pointed by the iterator.
|
||||
*
|
||||
* @retval IX_ETH_DB_SUCCESS if removal has succeeded
|
||||
* @retval IX_ETH_DB_BUSY if a locking failure has occured, in which case the caller
|
||||
* should retry
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IxEthDBStatus ixEthDBRemoveEntryAtHashIterator(HashTable *hashTable, HashIterator *iterator)
|
||||
{
|
||||
HashIterator nextIteratorPos;
|
||||
LockStack locks;
|
||||
|
||||
INIT_STACK(&locks);
|
||||
|
||||
/* set initial bucket index for next position */
|
||||
nextIteratorPos.bucketIndex = iterator->bucketIndex;
|
||||
|
||||
/* compute iterator position before removing anything and lock ahead */
|
||||
if (iterator->node->next != NULL)
|
||||
{
|
||||
PUSH_LOCK(&locks, &iterator->node->next->lock);
|
||||
|
||||
/* reposition on the next node in the chain */
|
||||
nextIteratorPos.node = iterator->node->next;
|
||||
nextIteratorPos.previousNode = iterator->previousNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* try next chain - don't know yet if we'll find anything */
|
||||
nextIteratorPos.node = NULL;
|
||||
|
||||
/* if we find something it's a chain head */
|
||||
nextIteratorPos.previousNode = NULL;
|
||||
|
||||
/* browse up in the buckets to find a non-null chain */
|
||||
while (++nextIteratorPos.bucketIndex < hashTable->numBuckets)
|
||||
{
|
||||
nextIteratorPos.node = hashTable->hashBuckets[nextIteratorPos.bucketIndex];
|
||||
|
||||
if (nextIteratorPos.node != NULL)
|
||||
{
|
||||
/* found a non-empty chain, try to lock head */
|
||||
PUSH_LOCK(&locks, &nextIteratorPos.node->lock);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* restore links over the to-be-deleted item */
|
||||
if (iterator->previousNode == NULL)
|
||||
{
|
||||
/* first in chain, lock bucket */
|
||||
PUSH_LOCK(&locks, &hashTable->bucketLocks[iterator->bucketIndex]);
|
||||
|
||||
hashTable->hashBuckets[iterator->bucketIndex] = iterator->node->next;
|
||||
|
||||
POP_LOCK(&locks);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* relink */
|
||||
iterator->previousNode->next = iterator->node->next;
|
||||
|
||||
/* unlock last remaining node in current chain when moving between chains */
|
||||
if (iterator->node->next == NULL)
|
||||
{
|
||||
UNLOCK(&iterator->previousNode->lock);
|
||||
}
|
||||
}
|
||||
|
||||
/* delete entry */
|
||||
hashTable->freeFunction(iterator->node->data);
|
||||
ixEthDBFreeHashNode(iterator->node);
|
||||
|
||||
/* reposition iterator */
|
||||
*iterator = nextIteratorPos;
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
149
cpu/ixp/npe/IxEthDBLearning.c
Normal file
149
cpu/ixp/npe/IxEthDBLearning.c
Normal file
@ -0,0 +1,149 @@
|
||||
/**
|
||||
* @file IxEthDBLearning.c
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
#include "IxEthDB_p.h"
|
||||
|
||||
/**
|
||||
* @brief hashes the mac address in a mac descriptor with a XOR function
|
||||
*
|
||||
* @param entry pointer to a mac descriptor to be hashed
|
||||
*
|
||||
* This function only extracts the mac address and employs ixEthDBKeyXORHash()
|
||||
* to do the actual hashing.
|
||||
* Used only to add a whole entry to a hash table, as opposed to searching which
|
||||
* takes only a key and uses the key hashing directly.
|
||||
*
|
||||
* @see ixEthDBKeyXORHash()
|
||||
*
|
||||
* @return the hash value
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
UINT32 ixEthDBEntryXORHash(void *entry)
|
||||
{
|
||||
MacDescriptor *descriptor = (MacDescriptor *) entry;
|
||||
|
||||
return ixEthDBKeyXORHash(descriptor->macAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief hashes a mac address
|
||||
*
|
||||
* @param key pointer to a 6 byte structure (typically an IxEthDBMacAddr pointer)
|
||||
* to be hashed
|
||||
*
|
||||
* Given a 6 bytes MAC address, the hash used is:
|
||||
*
|
||||
* hash(MAC[0:5]) = MAC[0:1] ^ MAC[2:3] ^ MAC[4:5]
|
||||
*
|
||||
* Used by the hash table to search and remove entries based
|
||||
* solely on their keys (mac addresses).
|
||||
*
|
||||
* @return the hash value
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
UINT32 ixEthDBKeyXORHash(void *key)
|
||||
{
|
||||
UINT32 hashValue;
|
||||
UINT8 *value = (UINT8 *) key;
|
||||
|
||||
hashValue = (value[5] << 8) | value[4];
|
||||
hashValue ^= (value[3] << 8) | value[2];
|
||||
hashValue ^= (value[1] << 8) | value[0];
|
||||
|
||||
return hashValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mac descriptor match function
|
||||
*
|
||||
* @param reference mac address (typically an IxEthDBMacAddr pointer) structure
|
||||
* @param entry pointer to a mac descriptor whose key (mac address) is to be
|
||||
* matched against the reference key
|
||||
*
|
||||
* Used by the hash table to retrieve entries. Hashing entries can produce
|
||||
* collisions, i.e. descriptors with different mac addresses and the same
|
||||
* hash value, where this function is used to differentiate entries.
|
||||
*
|
||||
* @retval TRUE if the entry matches the reference key (equal addresses)
|
||||
* @retval FALSE if the entry does not match the reference key
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
BOOL ixEthDBAddressMatch(void *reference, void *entry)
|
||||
{
|
||||
return (ixEthDBAddressCompare(reference, ((MacDescriptor *) entry)->macAddress) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief compares two mac addresses
|
||||
*
|
||||
* @param mac1 first mac address to compare
|
||||
* @param mac2 second mac address to compare
|
||||
*
|
||||
* This comparison works in a similar way to strcmp, producing similar results.
|
||||
* Used to insert values keyed on mac addresses into binary search trees.
|
||||
*
|
||||
* @retval -1 if mac1 < mac2
|
||||
* @retval 0 if ma1 == mac2
|
||||
* @retval 1 if mac1 > mac2
|
||||
*/
|
||||
UINT32 ixEthDBAddressCompare(UINT8 *mac1, UINT8 *mac2)
|
||||
{
|
||||
UINT32 local_index;
|
||||
|
||||
for (local_index = 0 ; local_index < IX_IEEE803_MAC_ADDRESS_SIZE ; local_index++)
|
||||
{
|
||||
if (mac1[local_index] > mac2[local_index])
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (mac1[local_index] < mac2[local_index])
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
649
cpu/ixp/npe/IxEthDBMem.c
Normal file
649
cpu/ixp/npe/IxEthDBMem.c
Normal file
@ -0,0 +1,649 @@
|
||||
/**
|
||||
* @file IxEthDBDBMem.c
|
||||
*
|
||||
* @brief Memory handling routines for the MAC address database
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
|
||||
#include "IxEthDB_p.h"
|
||||
|
||||
IX_ETH_DB_PRIVATE HashNode *nodePool = NULL;
|
||||
IX_ETH_DB_PRIVATE MacDescriptor *macPool = NULL;
|
||||
IX_ETH_DB_PRIVATE MacTreeNode *treePool = NULL;
|
||||
|
||||
IX_ETH_DB_PRIVATE HashNode nodePoolArea[NODE_POOL_SIZE];
|
||||
IX_ETH_DB_PRIVATE MacDescriptor macPoolArea[MAC_POOL_SIZE];
|
||||
IX_ETH_DB_PRIVATE MacTreeNode treePoolArea[TREE_POOL_SIZE];
|
||||
|
||||
IX_ETH_DB_PRIVATE IxOsalMutex nodePoolLock;
|
||||
IX_ETH_DB_PRIVATE IxOsalMutex macPoolLock;
|
||||
IX_ETH_DB_PRIVATE IxOsalMutex treePoolLock;
|
||||
|
||||
#define LOCK_NODE_POOL { ixOsalMutexLock(&nodePoolLock, IX_OSAL_WAIT_FOREVER); }
|
||||
#define UNLOCK_NODE_POOL { ixOsalMutexUnlock(&nodePoolLock); }
|
||||
|
||||
#define LOCK_MAC_POOL { ixOsalMutexLock(&macPoolLock, IX_OSAL_WAIT_FOREVER); }
|
||||
#define UNLOCK_MAC_POOL { ixOsalMutexUnlock(&macPoolLock); }
|
||||
|
||||
#define LOCK_TREE_POOL { ixOsalMutexLock(&treePoolLock, IX_OSAL_WAIT_FOREVER); }
|
||||
#define UNLOCK_TREE_POOL { ixOsalMutexUnlock(&treePoolLock); }
|
||||
|
||||
/* private function prototypes */
|
||||
IX_ETH_DB_PRIVATE MacDescriptor* ixEthDBPoolAllocMacDescriptor(void);
|
||||
IX_ETH_DB_PRIVATE void ixEthDBPoolFreeMacDescriptor(MacDescriptor *macDescriptor);
|
||||
|
||||
/**
|
||||
* @addtogroup EthMemoryManagement
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief initializes the memory pools used by the ethernet database component
|
||||
*
|
||||
* Initializes the hash table node, mac descriptor and mac tree node pools.
|
||||
* Called at initialization time by @ref ixEthDBInit().
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
void ixEthDBInitMemoryPools(void)
|
||||
{
|
||||
int local_index;
|
||||
|
||||
/* HashNode pool */
|
||||
ixOsalMutexInit(&nodePoolLock);
|
||||
|
||||
for (local_index = 0 ; local_index < NODE_POOL_SIZE ; local_index++)
|
||||
{
|
||||
HashNode *freeNode = &nodePoolArea[local_index];
|
||||
|
||||
freeNode->nextFree = nodePool;
|
||||
nodePool = freeNode;
|
||||
}
|
||||
|
||||
/* MacDescriptor pool */
|
||||
ixOsalMutexInit(&macPoolLock);
|
||||
|
||||
for (local_index = 0 ; local_index < MAC_POOL_SIZE ; local_index++)
|
||||
{
|
||||
MacDescriptor *freeDescriptor = &macPoolArea[local_index];
|
||||
|
||||
freeDescriptor->nextFree = macPool;
|
||||
macPool = freeDescriptor;
|
||||
}
|
||||
|
||||
/* MacTreeNode pool */
|
||||
ixOsalMutexInit(&treePoolLock);
|
||||
|
||||
for (local_index = 0 ; local_index < TREE_POOL_SIZE ; local_index++)
|
||||
{
|
||||
MacTreeNode *freeNode = &treePoolArea[local_index];
|
||||
|
||||
freeNode->nextFree = treePool;
|
||||
treePool = freeNode;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief allocates a hash node from the pool
|
||||
*
|
||||
* Allocates a hash node and resets its value.
|
||||
*
|
||||
* @return the allocated hash node or NULL if the pool is empty
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
HashNode* ixEthDBAllocHashNode(void)
|
||||
{
|
||||
HashNode *allocatedNode = NULL;
|
||||
|
||||
if (nodePool != NULL)
|
||||
{
|
||||
LOCK_NODE_POOL;
|
||||
|
||||
allocatedNode = nodePool;
|
||||
nodePool = nodePool->nextFree;
|
||||
|
||||
UNLOCK_NODE_POOL;
|
||||
|
||||
memset(allocatedNode, 0, sizeof(HashNode));
|
||||
}
|
||||
|
||||
return allocatedNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief frees a hash node into the pool
|
||||
*
|
||||
* @param hashNode node to be freed
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
void ixEthDBFreeHashNode(HashNode *hashNode)
|
||||
{
|
||||
if (hashNode != NULL)
|
||||
{
|
||||
LOCK_NODE_POOL;
|
||||
|
||||
hashNode->nextFree = nodePool;
|
||||
nodePool = hashNode;
|
||||
|
||||
UNLOCK_NODE_POOL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief allocates a mac descriptor from the pool
|
||||
*
|
||||
* Allocates a mac descriptor and resets its value.
|
||||
* This function is not used directly, instead @ref ixEthDBAllocMacDescriptor()
|
||||
* is used, which keeps track of the pointer reference count.
|
||||
*
|
||||
* @see ixEthDBAllocMacDescriptor()
|
||||
*
|
||||
* @warning this function is not used directly by any other function
|
||||
* apart from ixEthDBAllocMacDescriptor()
|
||||
*
|
||||
* @return the allocated mac descriptor or NULL if the pool is empty
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PRIVATE
|
||||
MacDescriptor* ixEthDBPoolAllocMacDescriptor(void)
|
||||
{
|
||||
MacDescriptor *allocatedDescriptor = NULL;
|
||||
|
||||
if (macPool != NULL)
|
||||
{
|
||||
LOCK_MAC_POOL;
|
||||
|
||||
allocatedDescriptor = macPool;
|
||||
macPool = macPool->nextFree;
|
||||
|
||||
UNLOCK_MAC_POOL;
|
||||
|
||||
memset(allocatedDescriptor, 0, sizeof(MacDescriptor));
|
||||
}
|
||||
|
||||
return allocatedDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief allocates and initializes a mac descriptor smart pointer
|
||||
*
|
||||
* Uses @ref ixEthDBPoolAllocMacDescriptor() to allocate a mac descriptor
|
||||
* from the pool and initializes its reference count.
|
||||
*
|
||||
* @see ixEthDBPoolAllocMacDescriptor()
|
||||
*
|
||||
* @return the allocated mac descriptor or NULL if the pool is empty
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
MacDescriptor* ixEthDBAllocMacDescriptor(void)
|
||||
{
|
||||
MacDescriptor *allocatedDescriptor = ixEthDBPoolAllocMacDescriptor();
|
||||
|
||||
if (allocatedDescriptor != NULL)
|
||||
{
|
||||
LOCK_MAC_POOL;
|
||||
|
||||
allocatedDescriptor->refCount++;
|
||||
|
||||
UNLOCK_MAC_POOL;
|
||||
}
|
||||
|
||||
return allocatedDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief frees a mac descriptor back into the pool
|
||||
*
|
||||
* @param macDescriptor mac descriptor to be freed
|
||||
*
|
||||
* @warning this function is not to be called by anyone but
|
||||
* ixEthDBFreeMacDescriptor()
|
||||
*
|
||||
* @see ixEthDBFreeMacDescriptor()
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PRIVATE
|
||||
void ixEthDBPoolFreeMacDescriptor(MacDescriptor *macDescriptor)
|
||||
{
|
||||
LOCK_MAC_POOL;
|
||||
|
||||
macDescriptor->nextFree = macPool;
|
||||
macPool = macDescriptor;
|
||||
|
||||
UNLOCK_MAC_POOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief frees or reduces the usage count of a mac descriptor smart pointer
|
||||
*
|
||||
* If the reference count reaches 0 (structure is no longer used anywhere)
|
||||
* then the descriptor is freed back into the pool using ixEthDBPoolFreeMacDescriptor().
|
||||
*
|
||||
* @see ixEthDBPoolFreeMacDescriptor()
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
void ixEthDBFreeMacDescriptor(MacDescriptor *macDescriptor)
|
||||
{
|
||||
if (macDescriptor != NULL)
|
||||
{
|
||||
LOCK_MAC_POOL;
|
||||
|
||||
if (macDescriptor->refCount > 0)
|
||||
{
|
||||
macDescriptor->refCount--;
|
||||
|
||||
if (macDescriptor->refCount == 0)
|
||||
{
|
||||
UNLOCK_MAC_POOL;
|
||||
|
||||
ixEthDBPoolFreeMacDescriptor(macDescriptor);
|
||||
}
|
||||
else
|
||||
{
|
||||
UNLOCK_MAC_POOL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UNLOCK_MAC_POOL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief clones a mac descriptor smart pointer
|
||||
*
|
||||
* @param macDescriptor mac descriptor to clone
|
||||
*
|
||||
* Increments the usage count of the smart pointer
|
||||
*
|
||||
* @returns the cloned smart pointer
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
MacDescriptor* ixEthDBCloneMacDescriptor(MacDescriptor *macDescriptor)
|
||||
{
|
||||
LOCK_MAC_POOL;
|
||||
|
||||
if (macDescriptor->refCount == 0)
|
||||
{
|
||||
UNLOCK_MAC_POOL;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
macDescriptor->refCount++;
|
||||
|
||||
UNLOCK_MAC_POOL;
|
||||
|
||||
return macDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief allocates a mac tree node from the pool
|
||||
*
|
||||
* Allocates and initializes a mac tree node from the pool.
|
||||
*
|
||||
* @return the allocated mac tree node or NULL if the pool is empty
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
MacTreeNode* ixEthDBAllocMacTreeNode(void)
|
||||
{
|
||||
MacTreeNode *allocatedNode = NULL;
|
||||
|
||||
if (treePool != NULL)
|
||||
{
|
||||
LOCK_TREE_POOL;
|
||||
|
||||
allocatedNode = treePool;
|
||||
treePool = treePool->nextFree;
|
||||
|
||||
UNLOCK_TREE_POOL;
|
||||
|
||||
memset(allocatedNode, 0, sizeof(MacTreeNode));
|
||||
}
|
||||
|
||||
return allocatedNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief frees a mac tree node back into the pool
|
||||
*
|
||||
* @param macNode mac tree node to be freed
|
||||
*
|
||||
* @warning not to be used except from ixEthDBFreeMacTreeNode().
|
||||
*
|
||||
* @see ixEthDBFreeMacTreeNode()
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
void ixEthDBPoolFreeMacTreeNode(MacTreeNode *macNode)
|
||||
{
|
||||
if (macNode != NULL)
|
||||
{
|
||||
LOCK_TREE_POOL;
|
||||
|
||||
macNode->nextFree = treePool;
|
||||
treePool = macNode;
|
||||
|
||||
UNLOCK_TREE_POOL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief frees or reduces the usage count of a mac tree node smart pointer
|
||||
*
|
||||
* @param macNode mac tree node to free
|
||||
*
|
||||
* Reduces the usage count of the given mac node. If the usage count
|
||||
* reaches 0 the node is freed back into the pool using ixEthDBPoolFreeMacTreeNode()
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
void ixEthDBFreeMacTreeNode(MacTreeNode *macNode)
|
||||
{
|
||||
if (macNode->descriptor != NULL)
|
||||
{
|
||||
ixEthDBFreeMacDescriptor(macNode->descriptor);
|
||||
}
|
||||
|
||||
if (macNode->left != NULL)
|
||||
{
|
||||
ixEthDBFreeMacTreeNode(macNode->left);
|
||||
}
|
||||
|
||||
if (macNode->right != NULL)
|
||||
{
|
||||
ixEthDBFreeMacTreeNode(macNode->right);
|
||||
}
|
||||
|
||||
ixEthDBPoolFreeMacTreeNode(macNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief clones a mac tree node
|
||||
*
|
||||
* @param macNode mac tree node to be cloned
|
||||
*
|
||||
* Increments the usage count of the node, <i>its associated descriptor
|
||||
* and <b>recursively</b> of all its child nodes</i>.
|
||||
*
|
||||
* @warning this function is recursive and clones whole trees/subtrees, use only for
|
||||
* root nodes
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
MacTreeNode* ixEthDBCloneMacTreeNode(MacTreeNode *macNode)
|
||||
{
|
||||
if (macNode != NULL)
|
||||
{
|
||||
MacTreeNode *clonedMacNode = ixEthDBAllocMacTreeNode();
|
||||
|
||||
if (clonedMacNode != NULL)
|
||||
{
|
||||
if (macNode->right != NULL)
|
||||
{
|
||||
clonedMacNode->right = ixEthDBCloneMacTreeNode(macNode->right);
|
||||
}
|
||||
|
||||
if (macNode->left != NULL)
|
||||
{
|
||||
clonedMacNode->left = ixEthDBCloneMacTreeNode(macNode->left);
|
||||
}
|
||||
|
||||
if (macNode->descriptor != NULL)
|
||||
{
|
||||
clonedMacNode->descriptor = ixEthDBCloneMacDescriptor(macNode->descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
return clonedMacNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* Debug statistical functions for memory usage */
|
||||
|
||||
extern HashTable dbHashtable;
|
||||
int ixEthDBNumHashElements(void);
|
||||
|
||||
int ixEthDBNumHashElements(void)
|
||||
{
|
||||
UINT32 bucketIndex;
|
||||
int numElements = 0;
|
||||
HashTable *hashTable = &dbHashtable;
|
||||
|
||||
for (bucketIndex = 0 ; bucketIndex < hashTable->numBuckets ; bucketIndex++)
|
||||
{
|
||||
if (hashTable->hashBuckets[bucketIndex] != NULL)
|
||||
{
|
||||
HashNode *node = hashTable->hashBuckets[bucketIndex];
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
numElements++;
|
||||
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return numElements;
|
||||
}
|
||||
|
||||
UINT32 ixEthDBSearchTreeUsageGet(MacTreeNode *tree)
|
||||
{
|
||||
if (tree == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1 /* this node */ + ixEthDBSearchTreeUsageGet(tree->left) + ixEthDBSearchTreeUsageGet(tree->right);
|
||||
}
|
||||
}
|
||||
|
||||
int ixEthDBShowMemoryStatus(void)
|
||||
{
|
||||
MacDescriptor *mac;
|
||||
MacTreeNode *tree;
|
||||
HashNode *node;
|
||||
|
||||
int macCounter = 0;
|
||||
int treeCounter = 0;
|
||||
int nodeCounter = 0;
|
||||
|
||||
int totalTreeUsage = 0;
|
||||
int totalDescriptorUsage = 0;
|
||||
int totalCloneDescriptorUsage = 0;
|
||||
int totalNodeUsage = 0;
|
||||
|
||||
UINT32 portIndex;
|
||||
|
||||
LOCK_NODE_POOL;
|
||||
LOCK_MAC_POOL;
|
||||
LOCK_TREE_POOL;
|
||||
|
||||
mac = macPool;
|
||||
tree = treePool;
|
||||
node = nodePool;
|
||||
|
||||
while (mac != NULL)
|
||||
{
|
||||
macCounter++;
|
||||
|
||||
mac = mac->nextFree;
|
||||
|
||||
if (macCounter > MAC_POOL_SIZE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (tree != NULL)
|
||||
{
|
||||
treeCounter++;
|
||||
|
||||
tree = tree->nextFree;
|
||||
|
||||
if (treeCounter > TREE_POOL_SIZE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
nodeCounter++;
|
||||
|
||||
node = node->nextFree;
|
||||
|
||||
if (nodeCounter > NODE_POOL_SIZE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
|
||||
{
|
||||
int treeUsage = ixEthDBSearchTreeUsageGet(ixEthDBPortInfo[portIndex].updateMethod.searchTree);
|
||||
|
||||
totalTreeUsage += treeUsage;
|
||||
totalCloneDescriptorUsage += treeUsage; /* each tree node contains a descriptor */
|
||||
}
|
||||
|
||||
totalNodeUsage = ixEthDBNumHashElements();
|
||||
totalDescriptorUsage += totalNodeUsage; /* each hash table entry contains a descriptor */
|
||||
|
||||
UNLOCK_NODE_POOL;
|
||||
UNLOCK_MAC_POOL;
|
||||
UNLOCK_TREE_POOL;
|
||||
|
||||
printf("Ethernet database memory usage stats:\n\n");
|
||||
|
||||
if (macCounter <= MAC_POOL_SIZE)
|
||||
{
|
||||
printf("\tMAC descriptor pool : %d free out of %d entries (%d%%)\n", macCounter, MAC_POOL_SIZE, macCounter * 100 / MAC_POOL_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("\tMAC descriptor pool : invalid state (ring within the pool), normally %d entries\n", MAC_POOL_SIZE);
|
||||
}
|
||||
|
||||
if (treeCounter <= TREE_POOL_SIZE)
|
||||
{
|
||||
printf("\tTree node pool : %d free out of %d entries (%d%%)\n", treeCounter, TREE_POOL_SIZE, treeCounter * 100 / TREE_POOL_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("\tTREE descriptor pool : invalid state (ring within the pool), normally %d entries\n", TREE_POOL_SIZE);
|
||||
}
|
||||
|
||||
if (nodeCounter <= NODE_POOL_SIZE)
|
||||
{
|
||||
printf("\tHash node pool : %d free out of %d entries (%d%%)\n", nodeCounter, NODE_POOL_SIZE, nodeCounter * 100 / NODE_POOL_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("\tNODE descriptor pool : invalid state (ring within the pool), normally %d entries\n", NODE_POOL_SIZE);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
printf("\tMAC descriptor usage : %d entries, %d cloned\n", totalDescriptorUsage, totalCloneDescriptorUsage);
|
||||
printf("\tTree node usage : %d entries\n", totalTreeUsage);
|
||||
printf("\tHash node usage : %d entries\n", totalNodeUsage);
|
||||
printf("\n");
|
||||
|
||||
/* search for duplicate nodes in the mac pool */
|
||||
{
|
||||
MacDescriptor *reference = macPool;
|
||||
|
||||
while (reference != NULL)
|
||||
{
|
||||
MacDescriptor *comparison = reference->nextFree;
|
||||
|
||||
while (comparison != NULL)
|
||||
{
|
||||
if (reference == comparison)
|
||||
{
|
||||
printf("Warning: reached a duplicate (%p), invalid MAC pool state\n", reference);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
comparison = comparison->nextFree;
|
||||
}
|
||||
|
||||
reference = reference->nextFree;
|
||||
}
|
||||
}
|
||||
|
||||
printf("No duplicates found in the MAC pool (sanity check ok)\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* NDEBUG */
|
||||
|
||||
/**
|
||||
* @} EthMemoryManagement
|
||||
*/
|
719
cpu/ixp/npe/IxEthDBNPEAdaptor.c
Normal file
719
cpu/ixp/npe/IxEthDBNPEAdaptor.c
Normal file
@ -0,0 +1,719 @@
|
||||
/**
|
||||
* @file IxEthDBDBNPEAdaptor.c
|
||||
*
|
||||
* @brief Routines that read and write learning/search trees in NPE-specific format
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
#include "IxEthDB_p.h"
|
||||
#include "IxEthDBLog_p.h"
|
||||
|
||||
/* forward prototype declarations */
|
||||
IX_ETH_DB_PUBLIC void ixEthDBELTShow(IxEthDBPortId portID);
|
||||
IX_ETH_DB_PUBLIC void ixEthDBShowNpeMsgHistory(void);
|
||||
|
||||
/* data */
|
||||
UINT8* ixEthDBNPEUpdateArea[IX_ETH_DB_NUMBER_OF_PORTS];
|
||||
UINT32 dumpEltSize;
|
||||
|
||||
/* private data */
|
||||
IX_ETH_DB_PRIVATE IxEthDBNoteWriteFn ixEthDBNPENodeWrite[IX_ETH_DB_MAX_RECORD_TYPE_INDEX + 1];
|
||||
|
||||
#define IX_ETH_DB_MAX_DELTA_ZONES (6) /* at most 6 EP Delta zones, according to NPE FS */
|
||||
IX_ETH_DB_PRIVATE UINT32 ixEthDBEPDeltaOffset[IX_ETH_DB_MAX_RECORD_TYPE_INDEX + 1][IX_ETH_DB_MAX_DELTA_ZONES];
|
||||
IX_ETH_DB_PRIVATE UINT32 ixEthDBEPDelta[IX_ETH_DB_MAX_RECORD_TYPE_INDEX + 1][IX_ETH_DB_MAX_DELTA_ZONES];
|
||||
|
||||
/**
|
||||
* @brief allocates non-cached or contiguous NPE tree update areas for all the ports
|
||||
*
|
||||
* This function is called only once at initialization time from
|
||||
* @ref ixEthDBInit().
|
||||
*
|
||||
* @warning do not call manually
|
||||
*
|
||||
* @see ixEthDBInit()
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
void ixEthDBNPEUpdateAreasInit(void)
|
||||
{
|
||||
UINT32 portIndex;
|
||||
PortUpdateMethod *update;
|
||||
|
||||
for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
|
||||
{
|
||||
update = &ixEthDBPortInfo[portIndex].updateMethod;
|
||||
|
||||
if (ixEthDBPortDefinitions[portIndex].type == IX_ETH_NPE)
|
||||
{
|
||||
update->npeUpdateZone = IX_OSAL_CACHE_DMA_MALLOC(FULL_ELT_BYTE_SIZE);
|
||||
update->npeGwUpdateZone = IX_OSAL_CACHE_DMA_MALLOC(FULL_GW_BYTE_SIZE);
|
||||
update->vlanUpdateZone = IX_OSAL_CACHE_DMA_MALLOC(FULL_VLAN_BYTE_SIZE);
|
||||
|
||||
if (update->npeUpdateZone == NULL
|
||||
|| update->npeGwUpdateZone == NULL
|
||||
|| update->vlanUpdateZone == NULL)
|
||||
{
|
||||
ERROR_LOG("Fatal error: IX_ACC_DRV_DMA_MALLOC() returned NULL, no NPE update zones available\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(update->npeUpdateZone, 0, FULL_ELT_BYTE_SIZE);
|
||||
memset(update->npeGwUpdateZone, 0, FULL_GW_BYTE_SIZE);
|
||||
memset(update->vlanUpdateZone, 0, FULL_VLAN_BYTE_SIZE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* unused */
|
||||
update->npeUpdateZone = NULL;
|
||||
update->npeGwUpdateZone = NULL;
|
||||
update->vlanUpdateZone = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief deallocates the NPE update areas for all the ports
|
||||
*
|
||||
* This function is called at component de-initialization time
|
||||
* by @ref ixEthDBUnload().
|
||||
*
|
||||
* @warning do not call manually
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
void ixEthDBNPEUpdateAreasUnload(void)
|
||||
{
|
||||
UINT32 portIndex;
|
||||
|
||||
for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
|
||||
{
|
||||
if (ixEthDBPortDefinitions[portIndex].type == IX_ETH_NPE)
|
||||
{
|
||||
IX_OSAL_CACHE_DMA_FREE(ixEthDBPortInfo[portIndex].updateMethod.npeUpdateZone);
|
||||
IX_OSAL_CACHE_DMA_FREE(ixEthDBPortInfo[portIndex].updateMethod.npeGwUpdateZone);
|
||||
IX_OSAL_CACHE_DMA_FREE(ixEthDBPortInfo[portIndex].updateMethod.vlanUpdateZone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief general-purpose NPE callback function
|
||||
*
|
||||
* @param npeID NPE ID
|
||||
* @param msg NPE message
|
||||
*
|
||||
* This function will unblock the caller by unlocking
|
||||
* the npeAckLock mutex defined for each NPE port
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
void ixEthDBNpeMsgAck(IxNpeMhNpeId npeID, IxNpeMhMessage msg)
|
||||
{
|
||||
IxEthDBPortId portID = IX_ETH_DB_NPE_TO_PORT_ID(npeID);
|
||||
PortInfo *portInfo;
|
||||
|
||||
if (portID >= IX_ETH_DB_NUMBER_OF_PORTS)
|
||||
{
|
||||
/* invalid port */
|
||||
return;
|
||||
}
|
||||
|
||||
if (ixEthDBPortDefinitions[portID].type != IX_ETH_NPE)
|
||||
{
|
||||
/* not an NPE */
|
||||
return;
|
||||
}
|
||||
|
||||
portInfo = &ixEthDBPortInfo[portID];
|
||||
|
||||
ixOsalMutexUnlock(&portInfo->npeAckLock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief synchronizes the database with tree
|
||||
*
|
||||
* @param portID port ID of the NPE whose tree is to be scanned
|
||||
* @param eltBaseAddress memory base address of the NPE serialized tree
|
||||
* @param eltSize size in bytes of the NPE serialized tree
|
||||
*
|
||||
* Scans the NPE learning tree and resets the age of active database records.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
void ixEthDBNPESyncScan(IxEthDBPortId portID, void *eltBaseAddress, UINT32 eltSize)
|
||||
{
|
||||
UINT32 eltEntryOffset;
|
||||
UINT32 entryPortID;
|
||||
|
||||
/* invalidate cache */
|
||||
IX_OSAL_CACHE_INVALIDATE(eltBaseAddress, eltSize);
|
||||
|
||||
for (eltEntryOffset = ELT_ROOT_OFFSET ; eltEntryOffset < eltSize ; eltEntryOffset += ELT_ENTRY_SIZE)
|
||||
{
|
||||
/* (eltBaseAddress + eltEntryOffset) points to a valid NPE tree node
|
||||
*
|
||||
* the format of the node is MAC[6 bytes]:PortID[1 byte]:Reserved[6 bits]:Active[1 bit]:Valid[1 bit]
|
||||
* therefore we can just use the pointer for database searches as only the first 6 bytes are checked
|
||||
*/
|
||||
void *eltNodeAddress = (void *) ((UINT32) eltBaseAddress + eltEntryOffset);
|
||||
|
||||
/* debug */
|
||||
IX_ETH_DB_NPE_VERBOSE_TRACE("DB: (NPEAdaptor) checking node at offset %d...\n", eltEntryOffset / ELT_ENTRY_SIZE);
|
||||
|
||||
if (IX_EDB_NPE_NODE_VALID(eltNodeAddress) != TRUE)
|
||||
{
|
||||
IX_ETH_DB_NPE_VERBOSE_TRACE("\t... node is empty\n");
|
||||
}
|
||||
else if (eltEntryOffset == ELT_ROOT_OFFSET)
|
||||
{
|
||||
IX_ETH_DB_NPE_VERBOSE_TRACE("\t... node is root\n");
|
||||
}
|
||||
|
||||
if (IX_EDB_NPE_NODE_VALID(eltNodeAddress))
|
||||
{
|
||||
entryPortID = IX_ETH_DB_NPE_LOGICAL_ID_TO_PORT_ID(IX_EDB_NPE_NODE_PORT_ID(eltNodeAddress));
|
||||
|
||||
/* check only active entries belonging to this port */
|
||||
if (ixEthDBPortInfo[portID].agingEnabled && IX_EDB_NPE_NODE_ACTIVE(eltNodeAddress) && (portID == entryPortID)
|
||||
&& ((ixEthDBPortDefinitions[portID].capabilities & IX_ETH_ENTRY_AGING) == 0))
|
||||
{
|
||||
/* search record */
|
||||
HashNode *node = ixEthDBSearch((IxEthDBMacAddr *) eltNodeAddress, IX_ETH_DB_ALL_FILTERING_RECORDS);
|
||||
|
||||
/* safety check, maybe user deleted record right before sync? */
|
||||
if (node != NULL)
|
||||
{
|
||||
/* found record */
|
||||
MacDescriptor *descriptor = (MacDescriptor *) node->data;
|
||||
|
||||
IX_ETH_DB_NPE_VERBOSE_TRACE("DB: (NPEAdaptor) synced entry [%s] already in the database, updating fields\n", mac2string(eltNodeAddress));
|
||||
|
||||
/* reset age - set to -1 so that maintenance will restore it to 0 (or more) when incrementing */
|
||||
if (!descriptor->recordData.filteringData.staticEntry)
|
||||
{
|
||||
if (descriptor->type == IX_ETH_DB_FILTERING_RECORD)
|
||||
{
|
||||
descriptor->recordData.filteringData.age = AGE_RESET;
|
||||
}
|
||||
else if (descriptor->type == IX_ETH_DB_FILTERING_VLAN_RECORD)
|
||||
{
|
||||
descriptor->recordData.filteringVlanData.age = AGE_RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/* end transaction */
|
||||
ixEthDBReleaseHashNode(node);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IX_ETH_DB_NPE_VERBOSE_TRACE("\t... found portID %d, we check only port %d\n", entryPortID, portID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writes a search tree in NPE format
|
||||
*
|
||||
* @param type type of records to be written into the NPE update zone
|
||||
* @param totalSize maximum size of the linearized tree
|
||||
* @param baseAddress memory base address where to write the NPE tree into
|
||||
* @param tree search tree to write in NPE format
|
||||
* @param blocks number of written 64-byte blocks
|
||||
* @param startIndex optimal binary search start index
|
||||
*
|
||||
* Serializes the given tree in NPE linear format
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
void ixEthDBNPETreeWrite(IxEthDBRecordType type, UINT32 totalSize, void *baseAddress, MacTreeNode *tree, UINT32 *epDelta, UINT32 *blocks)
|
||||
{
|
||||
MacTreeNodeStack *stack;
|
||||
UINT32 maxOffset = 0;
|
||||
UINT32 emptyOffset;
|
||||
|
||||
stack = ixOsalCacheDmaMalloc(sizeof (MacTreeNodeStack));
|
||||
|
||||
if (stack == NULL)
|
||||
{
|
||||
ERROR_LOG("DB: (NPEAdaptor) failed to allocate the node stack for learning tree linearization, out of memory?\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* zero out empty root */
|
||||
memset(baseAddress, 0, ELT_ENTRY_SIZE);
|
||||
|
||||
NODE_STACK_INIT(stack);
|
||||
|
||||
if (tree != NULL)
|
||||
{
|
||||
/* push tree root at offset 1 */
|
||||
NODE_STACK_PUSH(stack, tree, 1);
|
||||
|
||||
maxOffset = 1;
|
||||
}
|
||||
|
||||
while (NODE_STACK_NONEMPTY(stack))
|
||||
{
|
||||
MacTreeNode *node;
|
||||
UINT32 offset;
|
||||
|
||||
NODE_STACK_POP(stack, node, offset);
|
||||
|
||||
/* update maximum offset */
|
||||
if (offset > maxOffset)
|
||||
{
|
||||
maxOffset = offset;
|
||||
}
|
||||
|
||||
IX_ETH_DB_NPE_VERBOSE_TRACE("DB: (NPEAdaptor) writing MAC [%s] at offset %d\n", mac2string(node->descriptor->macAddress), offset);
|
||||
|
||||
/* add node to NPE ELT at position indicated by offset */
|
||||
if (offset < MAX_ELT_SIZE)
|
||||
{
|
||||
ixEthDBNPENodeWrite[type]((void *) (((UINT32) baseAddress) + offset * ELT_ENTRY_SIZE), node);
|
||||
}
|
||||
|
||||
if (node->left != NULL)
|
||||
{
|
||||
NODE_STACK_PUSH(stack, node->left, LEFT_CHILD_OFFSET(offset));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ensure this entry is zeroed */
|
||||
memset((void *) ((UINT32) baseAddress + LEFT_CHILD_OFFSET(offset) * ELT_ENTRY_SIZE), 0, ELT_ENTRY_SIZE);
|
||||
}
|
||||
|
||||
if (node->right != NULL)
|
||||
{
|
||||
NODE_STACK_PUSH(stack, node->right, RIGHT_CHILD_OFFSET(offset));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ensure this entry is zeroed */
|
||||
memset((void *) ((UINT32) baseAddress + RIGHT_CHILD_OFFSET(offset) * ELT_ENTRY_SIZE), 0, ELT_ENTRY_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
emptyOffset = maxOffset + 1;
|
||||
|
||||
/* zero out rest of the tree */
|
||||
IX_ETH_DB_NPE_TRACE("DB: (NPEAdaptor) Emptying tree from offset %d, address 0x%08X, %d bytes\n",
|
||||
emptyOffset, ((UINT32) baseAddress) + emptyOffset * ELT_ENTRY_SIZE, totalSize - (emptyOffset * ELT_ENTRY_SIZE));
|
||||
|
||||
if (emptyOffset < MAX_ELT_SIZE - 1)
|
||||
{
|
||||
memset((void *) (((UINT32) baseAddress) + (emptyOffset * ELT_ENTRY_SIZE)), 0, totalSize - (emptyOffset * ELT_ENTRY_SIZE));
|
||||
}
|
||||
|
||||
/* flush cache */
|
||||
IX_OSAL_CACHE_FLUSH(baseAddress, totalSize);
|
||||
|
||||
/* debug */
|
||||
IX_ETH_DB_NPE_TRACE("DB: (NPEAdaptor) Ethernet learning/filtering tree XScale wrote at address 0x%08X (max %d bytes):\n\n",
|
||||
(UINT32) baseAddress, FULL_ELT_BYTE_SIZE);
|
||||
|
||||
IX_ETH_DB_NPE_DUMP_ELT(baseAddress, FULL_ELT_BYTE_SIZE);
|
||||
|
||||
/* compute number of 64-byte blocks */
|
||||
if (blocks != NULL)
|
||||
{
|
||||
*blocks = maxOffset != 0 ? 1 + maxOffset / 8 : 0;
|
||||
|
||||
IX_ETH_DB_NPE_TRACE("DB: (NPEAdaptor) Wrote %d 64-byte blocks\n", *blocks);
|
||||
}
|
||||
|
||||
/* compute epDelta - start index for binary search */
|
||||
if (epDelta != NULL)
|
||||
{
|
||||
UINT32 deltaIndex = 0;
|
||||
|
||||
*epDelta = 0;
|
||||
|
||||
for (; deltaIndex < IX_ETH_DB_MAX_DELTA_ZONES ; deltaIndex ++)
|
||||
{
|
||||
if (ixEthDBEPDeltaOffset[type][deltaIndex] >= maxOffset)
|
||||
{
|
||||
*epDelta = ixEthDBEPDelta[type][deltaIndex];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
IX_ETH_DB_NPE_TRACE("DB: (NPEAdaptor) Computed epDelta %d (based on maxOffset %d)\n", *epDelta, maxOffset);
|
||||
}
|
||||
|
||||
ixOsalCacheDmaFree(stack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief implements a dummy node serialization function
|
||||
*
|
||||
* @param address address of where the node is to be serialized (unused)
|
||||
* @param node tree node to be serialized (unused)
|
||||
*
|
||||
* This function is registered for safety reasons and should
|
||||
* never be called. It will display an error message if this
|
||||
* function is called.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PRIVATE
|
||||
void ixEthDBNullSerialize(void *address, MacTreeNode *node)
|
||||
{
|
||||
IX_ETH_DB_NPE_TRACE("DB: (NPEAdaptor) Warning, the NullSerialize function was called, wrong record type?\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writes a filtering entry in NPE linear format
|
||||
*
|
||||
* @param address memory address to write node to
|
||||
* @param node node to be written
|
||||
*
|
||||
* Used by @ref ixEthDBNPETreeWrite to liniarize a search tree
|
||||
* in NPE-readable format.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PRIVATE
|
||||
void ixEthDBNPELearningNodeWrite(void *address, MacTreeNode *node)
|
||||
{
|
||||
/* copy mac address */
|
||||
memcpy(address, node->descriptor->macAddress, IX_IEEE803_MAC_ADDRESS_SIZE);
|
||||
|
||||
/* copy port ID */
|
||||
NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_ELT_PORT_ID_OFFSET) = IX_ETH_DB_PORT_ID_TO_NPE_LOGICAL_ID(node->descriptor->portID);
|
||||
|
||||
/* copy flags (valid and not active, as the NPE sets it to active) and clear reserved section (bits 2-7) */
|
||||
NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_ELT_FLAGS_OFFSET) = (UINT8) IX_EDB_FLAGS_INACTIVE_VALID;
|
||||
|
||||
IX_ETH_DB_NPE_VERBOSE_TRACE("DB: (NPEAdaptor) writing ELT node 0x%08x:0x%08x\n", * (UINT32 *) address, * (((UINT32 *) (address)) + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writes a WiFi header conversion record in
|
||||
* NPE linear format
|
||||
*
|
||||
* @param address memory address to write node to
|
||||
* @param node node to be written
|
||||
*
|
||||
* Used by @ref ixEthDBNPETreeWrite to liniarize a search tree
|
||||
* in NPE-readable format.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PRIVATE
|
||||
void ixEthDBNPEWiFiNodeWrite(void *address, MacTreeNode *node)
|
||||
{
|
||||
/* copy mac address */
|
||||
memcpy(address, node->descriptor->macAddress, IX_IEEE803_MAC_ADDRESS_SIZE);
|
||||
|
||||
/* copy index */
|
||||
NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_WIFI_INDEX_OFFSET) = node->descriptor->recordData.wifiData.gwAddressIndex;
|
||||
|
||||
/* copy flags (type and valid) */
|
||||
NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_WIFI_FLAGS_OFFSET) = node->descriptor->recordData.wifiData.type << 1 | IX_EDB_FLAGS_VALID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writes a WiFi gateway header conversion record in
|
||||
* NPE linear format
|
||||
*
|
||||
* @param address memory address to write node to
|
||||
* @param node node to be written
|
||||
*
|
||||
* Used by @ref ixEthDBNPETreeWrite to liniarize a search tree
|
||||
* in NPE-readable format.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
void ixEthDBNPEGatewayNodeWrite(void *address, MacTreeNode *node)
|
||||
{
|
||||
/* copy mac address */
|
||||
memcpy(address, node->descriptor->recordData.wifiData.gwMacAddress, IX_IEEE803_MAC_ADDRESS_SIZE);
|
||||
|
||||
/* set reserved field, two bytes */
|
||||
NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_FW_RESERVED_OFFSET) = 0;
|
||||
NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_FW_RESERVED_OFFSET + 1) = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writes a firewall record in
|
||||
* NPE linear format
|
||||
*
|
||||
* @param address memory address to write node to
|
||||
* @param node node to be written
|
||||
*
|
||||
* Used by @ref ixEthDBNPETreeWrite to liniarize a search tree
|
||||
* in NPE-readable format.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PRIVATE
|
||||
void ixEthDBNPEFirewallNodeWrite(void *address, MacTreeNode *node)
|
||||
{
|
||||
/* set reserved field */
|
||||
NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_FW_RESERVED_OFFSET) = 0;
|
||||
|
||||
/* set flags */
|
||||
NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_FW_FLAGS_OFFSET) = IX_EDB_FLAGS_VALID;
|
||||
|
||||
/* copy mac address */
|
||||
memcpy((void *) ((UINT32) address + IX_EDB_NPE_NODE_FW_ADDR_OFFSET), node->descriptor->macAddress, IX_IEEE803_MAC_ADDRESS_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief registers the NPE serialization methods
|
||||
*
|
||||
* This functions registers NPE serialization methods
|
||||
* for writing the following types of records in NPE
|
||||
* readable linear format:
|
||||
* - filtering records
|
||||
* - WiFi header conversion records
|
||||
* - WiFi gateway header conversion records
|
||||
* - firewall records
|
||||
*
|
||||
* Note that this function should be called by the
|
||||
* component initialization function.
|
||||
*
|
||||
* @return number of registered record types
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
UINT32 ixEthDBRecordSerializeMethodsRegister()
|
||||
{
|
||||
int i;
|
||||
|
||||
/* safety - register a blank method for everybody first */
|
||||
for ( i = 0 ; i < IX_ETH_DB_MAX_RECORD_TYPE_INDEX + 1 ; i++)
|
||||
{
|
||||
ixEthDBNPENodeWrite[i] = ixEthDBNullSerialize;
|
||||
}
|
||||
|
||||
/* register real methods */
|
||||
ixEthDBNPENodeWrite[IX_ETH_DB_FILTERING_RECORD] = ixEthDBNPELearningNodeWrite;
|
||||
ixEthDBNPENodeWrite[IX_ETH_DB_FILTERING_VLAN_RECORD] = ixEthDBNPELearningNodeWrite;
|
||||
ixEthDBNPENodeWrite[IX_ETH_DB_WIFI_RECORD] = ixEthDBNPEWiFiNodeWrite;
|
||||
ixEthDBNPENodeWrite[IX_ETH_DB_FIREWALL_RECORD] = ixEthDBNPEFirewallNodeWrite;
|
||||
ixEthDBNPENodeWrite[IX_ETH_DB_GATEWAY_RECORD] = ixEthDBNPEGatewayNodeWrite;
|
||||
|
||||
/* EP Delta arrays */
|
||||
memset(ixEthDBEPDeltaOffset, 0, sizeof (ixEthDBEPDeltaOffset));
|
||||
memset(ixEthDBEPDelta, 0, sizeof (ixEthDBEPDelta));
|
||||
|
||||
/* filtering records */
|
||||
ixEthDBEPDeltaOffset[IX_ETH_DB_FILTERING_RECORD][0] = 1;
|
||||
ixEthDBEPDelta[IX_ETH_DB_FILTERING_RECORD][0] = 0;
|
||||
|
||||
ixEthDBEPDeltaOffset[IX_ETH_DB_FILTERING_RECORD][1] = 3;
|
||||
ixEthDBEPDelta[IX_ETH_DB_FILTERING_RECORD][1] = 7;
|
||||
|
||||
ixEthDBEPDeltaOffset[IX_ETH_DB_FILTERING_RECORD][2] = 511;
|
||||
ixEthDBEPDelta[IX_ETH_DB_FILTERING_RECORD][2] = 14;
|
||||
|
||||
/* wifi records */
|
||||
ixEthDBEPDeltaOffset[IX_ETH_DB_WIFI_RECORD][0] = 1;
|
||||
ixEthDBEPDelta[IX_ETH_DB_WIFI_RECORD][0] = 0;
|
||||
|
||||
ixEthDBEPDeltaOffset[IX_ETH_DB_WIFI_RECORD][1] = 3;
|
||||
ixEthDBEPDelta[IX_ETH_DB_WIFI_RECORD][1] = 7;
|
||||
|
||||
ixEthDBEPDeltaOffset[IX_ETH_DB_WIFI_RECORD][2] = 511;
|
||||
ixEthDBEPDelta[IX_ETH_DB_WIFI_RECORD][2] = 14;
|
||||
|
||||
/* firewall records */
|
||||
ixEthDBEPDeltaOffset[IX_ETH_DB_FIREWALL_RECORD][0] = 0;
|
||||
ixEthDBEPDelta[IX_ETH_DB_FIREWALL_RECORD][0] = 0;
|
||||
|
||||
ixEthDBEPDeltaOffset[IX_ETH_DB_FIREWALL_RECORD][1] = 1;
|
||||
ixEthDBEPDelta[IX_ETH_DB_FIREWALL_RECORD][1] = 5;
|
||||
|
||||
ixEthDBEPDeltaOffset[IX_ETH_DB_FIREWALL_RECORD][2] = 3;
|
||||
ixEthDBEPDelta[IX_ETH_DB_FIREWALL_RECORD][2] = 13;
|
||||
|
||||
ixEthDBEPDeltaOffset[IX_ETH_DB_FIREWALL_RECORD][3] = 7;
|
||||
ixEthDBEPDelta[IX_ETH_DB_FIREWALL_RECORD][3] = 21;
|
||||
|
||||
ixEthDBEPDeltaOffset[IX_ETH_DB_FIREWALL_RECORD][4] = 15;
|
||||
ixEthDBEPDelta[IX_ETH_DB_FIREWALL_RECORD][4] = 29;
|
||||
|
||||
ixEthDBEPDeltaOffset[IX_ETH_DB_FIREWALL_RECORD][5] = 31;
|
||||
ixEthDBEPDelta[IX_ETH_DB_FIREWALL_RECORD][5] = 37;
|
||||
|
||||
return 5; /* 5 methods registered */
|
||||
}
|
||||
|
||||
#ifndef IX_NDEBUG
|
||||
|
||||
IX_ETH_DB_PUBLIC UINT32 npeMsgHistory[IX_ETH_DB_NPE_MSG_HISTORY_DEPTH][2];
|
||||
IX_ETH_DB_PUBLIC UINT32 npeMsgHistoryLen = 0;
|
||||
|
||||
/**
|
||||
* When compiled in DEBUG mode, this function can be used to display
|
||||
* the history of messages sent to the NPEs (up to 100).
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
void ixEthDBShowNpeMsgHistory()
|
||||
{
|
||||
UINT32 i = 0;
|
||||
UINT32 base, len;
|
||||
|
||||
if (npeMsgHistoryLen <= IX_ETH_DB_NPE_MSG_HISTORY_DEPTH)
|
||||
{
|
||||
base = 0;
|
||||
len = npeMsgHistoryLen;
|
||||
}
|
||||
else
|
||||
{
|
||||
base = npeMsgHistoryLen % IX_ETH_DB_NPE_MSG_HISTORY_DEPTH;
|
||||
len = IX_ETH_DB_NPE_MSG_HISTORY_DEPTH;
|
||||
}
|
||||
|
||||
printf("NPE message history [last %d messages, from least to most recent]:\n", len);
|
||||
|
||||
for (; i < len ; i++)
|
||||
{
|
||||
UINT32 pos = (base + i) % IX_ETH_DB_NPE_MSG_HISTORY_DEPTH;
|
||||
printf("msg[%d]: 0x%08x:0x%08x\n", i, npeMsgHistory[pos][0], npeMsgHistory[pos][1]);
|
||||
}
|
||||
}
|
||||
|
||||
IX_ETH_DB_PUBLIC
|
||||
void ixEthDBELTShow(IxEthDBPortId portID)
|
||||
{
|
||||
IxNpeMhMessage message;
|
||||
IX_STATUS result;
|
||||
|
||||
/* send EDB_GetMACAddressDatabase message */
|
||||
FILL_GETMACADDRESSDATABASE(message,
|
||||
0 /* reserved */,
|
||||
IX_OSAL_MMU_VIRT_TO_PHYS(ixEthDBPortInfo[portID].updateMethod.npeUpdateZone));
|
||||
|
||||
IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result);
|
||||
|
||||
if (result == IX_SUCCESS)
|
||||
{
|
||||
/* analyze NPE copy */
|
||||
UINT32 eltEntryOffset;
|
||||
UINT32 entryPortID;
|
||||
|
||||
UINT32 eltBaseAddress = (UINT32) ixEthDBPortInfo[portID].updateMethod.npeUpdateZone;
|
||||
UINT32 eltSize = FULL_ELT_BYTE_SIZE;
|
||||
|
||||
/* invalidate cache */
|
||||
IX_OSAL_CACHE_INVALIDATE((void *) eltBaseAddress, eltSize);
|
||||
|
||||
printf("Listing records in main learning tree for port %d\n", portID);
|
||||
|
||||
for (eltEntryOffset = ELT_ROOT_OFFSET ; eltEntryOffset < eltSize ; eltEntryOffset += ELT_ENTRY_SIZE)
|
||||
{
|
||||
/* (eltBaseAddress + eltEntryOffset) points to a valid NPE tree node
|
||||
*
|
||||
* the format of the node is MAC[6 bytes]:PortID[1 byte]:Reserved[6 bits]:Active[1 bit]:Valid[1 bit]
|
||||
* therefore we can just use the pointer for database searches as only the first 6 bytes are checked
|
||||
*/
|
||||
void *eltNodeAddress = (void *) ((UINT32) eltBaseAddress + eltEntryOffset);
|
||||
|
||||
if (IX_EDB_NPE_NODE_VALID(eltNodeAddress))
|
||||
{
|
||||
HashNode *node;
|
||||
|
||||
entryPortID = IX_ETH_DB_NPE_LOGICAL_ID_TO_PORT_ID(IX_EDB_NPE_NODE_PORT_ID(eltNodeAddress));
|
||||
|
||||
/* search record */
|
||||
node = ixEthDBSearch((IxEthDBMacAddr *) eltNodeAddress, IX_ETH_DB_ALL_RECORD_TYPES);
|
||||
|
||||
printf("%s - port %d - %s ", mac2string((unsigned char *) eltNodeAddress), entryPortID,
|
||||
IX_EDB_NPE_NODE_ACTIVE(eltNodeAddress) ? "active" : "inactive");
|
||||
|
||||
/* safety check, maybe user deleted record right before sync? */
|
||||
if (node != NULL)
|
||||
{
|
||||
/* found record */
|
||||
MacDescriptor *descriptor = (MacDescriptor *) node->data;
|
||||
|
||||
printf("- %s ",
|
||||
descriptor->type == IX_ETH_DB_FILTERING_RECORD ? "filtering" :
|
||||
descriptor->type == IX_ETH_DB_FILTERING_VLAN_RECORD ? "vlan" :
|
||||
descriptor->type == IX_ETH_DB_WIFI_RECORD ? "wifi" : "other (check main DB)");
|
||||
|
||||
if (descriptor->type == IX_ETH_DB_FILTERING_RECORD) printf("- age %d - %s ",
|
||||
descriptor->recordData.filteringData.age,
|
||||
descriptor->recordData.filteringData.staticEntry ? "static" : "dynamic");
|
||||
|
||||
if (descriptor->type == IX_ETH_DB_FILTERING_VLAN_RECORD) printf("- age %d - %s - tci %d ",
|
||||
descriptor->recordData.filteringVlanData.age,
|
||||
descriptor->recordData.filteringVlanData.staticEntry ? "static" : "dynamic",
|
||||
descriptor->recordData.filteringVlanData.ieee802_1qTag);
|
||||
|
||||
/* end transaction */
|
||||
ixEthDBReleaseHashNode(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("- not synced");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ixOsalLog(IX_OSAL_LOG_LVL_FATAL, IX_OSAL_LOG_DEV_STDOUT,
|
||||
"EthDB: (ShowELT) Could not complete action (communication failure)\n",
|
||||
portID, 0, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
740
cpu/ixp/npe/IxEthDBPortUpdate.c
Normal file
740
cpu/ixp/npe/IxEthDBPortUpdate.c
Normal file
@ -0,0 +1,740 @@
|
||||
/**
|
||||
* @file IxEthDBDBPortUpdate.c
|
||||
*
|
||||
* @brief Implementation of dependency and port update handling
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
#include "IxEthDB_p.h"
|
||||
|
||||
/* forward prototype declarations */
|
||||
IX_ETH_DB_PRIVATE MacTreeNode* ixEthDBTreeInsert(MacTreeNode *searchTree, MacDescriptor *descriptor);
|
||||
IX_ETH_DB_PRIVATE void ixEthDBCreateTrees(IxEthDBPortMap updatePorts);
|
||||
IX_ETH_DB_PRIVATE MacTreeNode* ixEthDBTreeRebalance(MacTreeNode *searchTree);
|
||||
IX_ETH_DB_PRIVATE void ixEthDBRebalanceTreeToVine(MacTreeNode *root, UINT32 *size);
|
||||
IX_ETH_DB_PRIVATE void ixEthDBRebalanceVineToTree(MacTreeNode *root, UINT32 size);
|
||||
IX_ETH_DB_PRIVATE void ixEthDBRebalanceCompression(MacTreeNode *root, UINT32 count);
|
||||
IX_ETH_DB_PRIVATE UINT32 ixEthDBRebalanceLog2Floor(UINT32 x);
|
||||
|
||||
extern HashTable dbHashtable;
|
||||
|
||||
/**
|
||||
* @brief register types requiring automatic updates
|
||||
*
|
||||
* @param typeArray array indexed on record types, each
|
||||
* element indicating whether the record type requires an
|
||||
* automatic update (TRUE) or not (FALSE)
|
||||
*
|
||||
* Automatic updates are done for registered record types
|
||||
* upon adding, updating (that is, updating the record portID)
|
||||
* and removing records. Whenever an automatic update is triggered
|
||||
* the appropriate ports will be provided with new database
|
||||
* information.
|
||||
*
|
||||
* It is assumed that the typeArray parameter is allocated large
|
||||
* enough to hold all the user defined types. Also, the type
|
||||
* array should be initialized to FALSE as this function only
|
||||
* caters for types which do require automatic updates.
|
||||
*
|
||||
* Note that this function should be called by the component
|
||||
* initialization function.
|
||||
*
|
||||
* @return number of record types registered for automatic
|
||||
* updates
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
UINT32 ixEthDBUpdateTypeRegister(BOOL *typeArray)
|
||||
{
|
||||
typeArray[IX_ETH_DB_FILTERING_RECORD] = TRUE;
|
||||
typeArray[IX_ETH_DB_FILTERING_VLAN_RECORD] = TRUE;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief computes dependencies and triggers port learning tree updates
|
||||
*
|
||||
* @param triggerPorts port map consisting in the ports which triggered the update
|
||||
*
|
||||
* This function browses through all the ports and determines how to waterfall the update
|
||||
* event from the trigger ports to all other ports depending on them.
|
||||
*
|
||||
* Once the list of ports to be updated is determined this function
|
||||
* calls @ref ixEthDBCreateTrees.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
void ixEthDBUpdatePortLearningTrees(IxEthDBPortMap triggerPorts)
|
||||
{
|
||||
IxEthDBPortMap updatePorts;
|
||||
UINT32 portIndex;
|
||||
|
||||
ixEthDBUpdateLock();
|
||||
|
||||
SET_EMPTY_DEPENDENCY_MAP(updatePorts);
|
||||
|
||||
for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
|
||||
{
|
||||
PortInfo *port = &ixEthDBPortInfo[portIndex];
|
||||
BOOL mapsCollide;
|
||||
|
||||
MAPS_COLLIDE(mapsCollide, triggerPorts, port->dependencyPortMap);
|
||||
|
||||
if (mapsCollide /* do triggers influence this port? */
|
||||
&& !IS_PORT_INCLUDED(portIndex, updatePorts) /* and it's not already in the update list */
|
||||
&& port->updateMethod.updateEnabled) /* and we're allowed to update it */
|
||||
{
|
||||
IX_ETH_DB_UPDATE_TRACE("DB: (Update) Adding port %d to update set\n", portIndex);
|
||||
|
||||
JOIN_PORT_TO_MAP(updatePorts, portIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
IX_ETH_DB_UPDATE_TRACE("DB: (Update) Didn't add port %d to update set, reasons follow:\n", portIndex);
|
||||
|
||||
if (!mapsCollide)
|
||||
{
|
||||
IX_ETH_DB_UPDATE_TRACE("\tMaps don't collide on port %d\n", portIndex);
|
||||
}
|
||||
|
||||
if (IS_PORT_INCLUDED(portIndex, updatePorts))
|
||||
{
|
||||
IX_ETH_DB_UPDATE_TRACE("\tPort %d is already in the update set\n", portIndex);
|
||||
}
|
||||
|
||||
if (!port->updateMethod.updateEnabled)
|
||||
{
|
||||
IX_ETH_DB_UPDATE_TRACE("\tPort %d doesn't have updateEnabled set\n", portIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IX_ETH_DB_UPDATE_TRACE("DB: (Update) Updating port set\n");
|
||||
|
||||
ixEthDBCreateTrees(updatePorts);
|
||||
|
||||
ixEthDBUpdateUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief creates learning trees and calls the port update handlers
|
||||
*
|
||||
* @param updatePorts set of ports in need of learning trees
|
||||
*
|
||||
* This function determines the optimal method of creating learning
|
||||
* trees using a minimal number of database queries, keeping in mind
|
||||
* that different ports can either use the same learning trees or they
|
||||
* can partially share them. The actual tree building routine is
|
||||
* @ref ixEthDBQuery.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PRIVATE
|
||||
void ixEthDBCreateTrees(IxEthDBPortMap updatePorts)
|
||||
{
|
||||
UINT32 portIndex;
|
||||
BOOL result;
|
||||
BOOL portsLeft = TRUE;
|
||||
|
||||
while (portsLeft)
|
||||
{
|
||||
/* get port with minimal dependency map and NULL search tree */
|
||||
UINT32 minPortIndex = MAX_PORT_SIZE;
|
||||
UINT32 minimalSize = MAX_PORT_SIZE;
|
||||
|
||||
for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
|
||||
{
|
||||
UINT32 size;
|
||||
PortInfo *port = &ixEthDBPortInfo[portIndex];
|
||||
|
||||
/* generate trees only for ports that need them */
|
||||
if (!port->updateMethod.searchTreePendingWrite && IS_PORT_INCLUDED(portIndex, updatePorts))
|
||||
{
|
||||
GET_MAP_SIZE(port->dependencyPortMap, size);
|
||||
|
||||
IX_ETH_DB_UPDATE_TRACE("DB: (Update) Dependency map for port %d: size %d\n",
|
||||
portIndex, size);
|
||||
|
||||
if (size < minimalSize)
|
||||
{
|
||||
minPortIndex = portIndex;
|
||||
minimalSize = size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IX_ETH_DB_UPDATE_TRACE("DB: (Update) Skipped port %d from tree diff (%s)\n", portIndex,
|
||||
port->updateMethod.searchTreePendingWrite ? "pending write access" : "ignored by query");
|
||||
}
|
||||
}
|
||||
|
||||
/* if a port was found than minimalSize is not MAX_PORT_SIZE */
|
||||
if (minimalSize != MAX_PORT_SIZE)
|
||||
{
|
||||
/* minPortIndex is the port we seek */
|
||||
PortInfo *port = &ixEthDBPortInfo[minPortIndex];
|
||||
|
||||
IxEthDBPortMap query;
|
||||
MacTreeNode *baseTree;
|
||||
|
||||
/* now try to find a port with minimal map difference */
|
||||
PortInfo *minimalDiffPort = NULL;
|
||||
UINT32 minimalDiff = MAX_PORT_SIZE;
|
||||
|
||||
IX_ETH_DB_UPDATE_TRACE("DB: (Update) Minimal size port is %d\n", minPortIndex);
|
||||
|
||||
for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
|
||||
{
|
||||
PortInfo *diffPort = &ixEthDBPortInfo[portIndex];
|
||||
BOOL mapIsSubset;
|
||||
|
||||
IS_MAP_SUBSET(mapIsSubset, diffPort->dependencyPortMap, port->dependencyPortMap);
|
||||
|
||||
|
||||
if (portIndex != minPortIndex
|
||||
&& diffPort->updateMethod.searchTree != NULL
|
||||
&& mapIsSubset)
|
||||
{
|
||||
/* compute size and pick only minimal size difference */
|
||||
UINT32 diffPortSize;
|
||||
UINT32 sizeDifference;
|
||||
|
||||
GET_MAP_SIZE(diffPort->dependencyPortMap, diffPortSize);
|
||||
|
||||
IX_ETH_DB_UPDATE_TRACE("DB: (Update) Checking port %d for differences...\n", portIndex);
|
||||
|
||||
sizeDifference = minimalSize - diffPortSize;
|
||||
|
||||
if (sizeDifference < minimalDiff)
|
||||
{
|
||||
minimalDiffPort = diffPort;
|
||||
minimalDiff = sizeDifference;
|
||||
|
||||
IX_ETH_DB_UPDATE_TRACE("DB: (Update) Minimal difference 0x%x was found on port %d\n",
|
||||
minimalDiff, portIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check if filtering is enabled on this port */
|
||||
if ((port->featureStatus & IX_ETH_DB_FILTERING) != 0)
|
||||
{
|
||||
/* if minimalDiff is not MAX_PORT_SIZE minimalDiffPort points to the most similar port */
|
||||
if (minimalDiff != MAX_PORT_SIZE)
|
||||
{
|
||||
baseTree = ixEthDBCloneMacTreeNode(minimalDiffPort->updateMethod.searchTree);
|
||||
DIFF_MAPS(query, port->dependencyPortMap , minimalDiffPort->dependencyPortMap);
|
||||
|
||||
IX_ETH_DB_UPDATE_TRACE("DB: (Update) Found minimal diff, extending tree %d on query\n",
|
||||
minimalDiffPort->portID);
|
||||
}
|
||||
else /* .. otherwise no similar port was found, build tree from scratch */
|
||||
{
|
||||
baseTree = NULL;
|
||||
|
||||
COPY_DEPENDENCY_MAP(query, port->dependencyPortMap);
|
||||
|
||||
IX_ETH_DB_UPDATE_TRACE("DB: (Update) No similar diff, creating tree from query\n");
|
||||
}
|
||||
|
||||
IS_EMPTY_DEPENDENCY_MAP(result, query);
|
||||
|
||||
if (!result) /* otherwise we don't need anything more on top of the cloned tree */
|
||||
{
|
||||
IX_ETH_DB_UPDATE_TRACE("DB: (Update) Adding query tree to port %d\n", minPortIndex);
|
||||
|
||||
/* build learning tree */
|
||||
port->updateMethod.searchTree = ixEthDBQuery(baseTree, query, IX_ETH_DB_ALL_FILTERING_RECORDS, MAX_ELT_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
IX_ETH_DB_UPDATE_TRACE("DB: (Update) Query is empty, assuming identical nearest tree\n");
|
||||
|
||||
port->updateMethod.searchTree = baseTree;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* filtering is not enabled, will download an empty tree */
|
||||
if (port->updateMethod.searchTree != NULL)
|
||||
{
|
||||
ixEthDBFreeMacTreeNode(port->updateMethod.searchTree);
|
||||
}
|
||||
|
||||
port->updateMethod.searchTree = NULL;
|
||||
}
|
||||
|
||||
/* mark tree as valid */
|
||||
port->updateMethod.searchTreePendingWrite = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
portsLeft = FALSE;
|
||||
|
||||
IX_ETH_DB_UPDATE_TRACE("DB: (Update) No trees to create this round\n");
|
||||
}
|
||||
}
|
||||
|
||||
for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
|
||||
{
|
||||
PortInfo *updatePort = &ixEthDBPortInfo[portIndex];
|
||||
|
||||
if (updatePort->updateMethod.searchTreePendingWrite)
|
||||
{
|
||||
IX_ETH_DB_UPDATE_TRACE("DB: (PortUpdate) Starting procedure to upload new search tree (%snull) into NPE %d\n",
|
||||
updatePort->updateMethod.searchTree != NULL ? "not " : "",
|
||||
portIndex);
|
||||
|
||||
updatePort->updateMethod.updateHandler(portIndex, IX_ETH_DB_FILTERING_RECORD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief standard NPE update handler
|
||||
*
|
||||
* @param portID id of the port to be updated
|
||||
* @param type record type to be pushed during this update
|
||||
*
|
||||
* The NPE update handler manages updating the NPE databases
|
||||
* given a certain record type.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBNPEUpdateHandler(IxEthDBPortId portID, IxEthDBRecordType type)
|
||||
{
|
||||
UINT32 epDelta, blockCount;
|
||||
IxNpeMhMessage message;
|
||||
UINT32 treeSize = 0;
|
||||
PortInfo *port = &ixEthDBPortInfo[portID];
|
||||
|
||||
/* size selection and type check */
|
||||
if (type == IX_ETH_DB_FILTERING_RECORD || type == IX_ETH_DB_WIFI_RECORD)
|
||||
{
|
||||
treeSize = FULL_ELT_BYTE_SIZE;
|
||||
}
|
||||
else if (type == IX_ETH_DB_FIREWALL_RECORD)
|
||||
{
|
||||
treeSize = FULL_FW_BYTE_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return IX_ETH_DB_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* serialize tree into memory */
|
||||
ixEthDBNPETreeWrite(type, treeSize, port->updateMethod.npeUpdateZone, port->updateMethod.searchTree, &epDelta, &blockCount);
|
||||
|
||||
/* free internal copy */
|
||||
if (port->updateMethod.searchTree != NULL)
|
||||
{
|
||||
ixEthDBFreeMacTreeNode(port->updateMethod.searchTree);
|
||||
}
|
||||
|
||||
/* forget last used search tree */
|
||||
port->updateMethod.searchTree = NULL;
|
||||
port->updateMethod.searchTreePendingWrite = FALSE;
|
||||
|
||||
/* dependending on the update type we do different things */
|
||||
if (type == IX_ETH_DB_FILTERING_RECORD || type == IX_ETH_DB_WIFI_RECORD)
|
||||
{
|
||||
IX_STATUS result;
|
||||
|
||||
FILL_SETMACADDRESSDATABASE_MSG(message, IX_ETH_DB_PORT_ID_TO_NPE_LOGICAL_ID(portID),
|
||||
epDelta, blockCount,
|
||||
IX_OSAL_MMU_VIRT_TO_PHYS(port->updateMethod.npeUpdateZone));
|
||||
|
||||
IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result);
|
||||
|
||||
if (result == IX_SUCCESS)
|
||||
{
|
||||
IX_ETH_DB_UPDATE_TRACE("DB: (PortUpdate) Finished downloading NPE tree on port %d\n", portID);
|
||||
}
|
||||
else
|
||||
{
|
||||
ixEthDBPortInfo[portID].agingEnabled = FALSE;
|
||||
ixEthDBPortInfo[portID].updateMethod.updateEnabled = FALSE;
|
||||
ixEthDBPortInfo[portID].updateMethod.userControlled = TRUE;
|
||||
|
||||
ERROR_LOG("EthDB: (PortUpdate) disabling aging and updates on port %d (assumed dead)\n", portID);
|
||||
|
||||
ixEthDBDatabaseClear(portID, IX_ETH_DB_ALL_RECORD_TYPES);
|
||||
|
||||
return IX_ETH_DB_FAIL;
|
||||
}
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
else if (type == IX_ETH_DB_FIREWALL_RECORD)
|
||||
{
|
||||
return ixEthDBFirewallUpdate(portID, port->updateMethod.npeUpdateZone, epDelta);
|
||||
}
|
||||
|
||||
return IX_ETH_DB_INVALID_ARG;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief queries the database for a set of records to be inserted into a given tree
|
||||
*
|
||||
* @param searchTree pointer to a tree where insertions will be performed; can be NULL
|
||||
* @param query set of ports that a database record must match to be inserted into the tree
|
||||
*
|
||||
* The query method browses through the database, extracts all the descriptors matching
|
||||
* the given query parameter and inserts them into the given learning tree.
|
||||
* Note that this is an append procedure, the given tree needs not to be empty.
|
||||
* A "descriptor matching the query" is a descriptor whose port id is in the query map.
|
||||
* If the given tree is empty (NULL) a new tree is created and returned.
|
||||
*
|
||||
* @return the tree root
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
MacTreeNode* ixEthDBQuery(MacTreeNode *searchTree, IxEthDBPortMap query, IxEthDBRecordType recordFilter, UINT32 maxEntries)
|
||||
{
|
||||
HashIterator iterator;
|
||||
UINT32 entryCount = 0;
|
||||
|
||||
/* browse database */
|
||||
BUSY_RETRY(ixEthDBInitHashIterator(&dbHashtable, &iterator));
|
||||
|
||||
while (IS_ITERATOR_VALID(&iterator))
|
||||
{
|
||||
MacDescriptor *descriptor = (MacDescriptor *) iterator.node->data;
|
||||
|
||||
IX_ETH_DB_UPDATE_TRACE("DB: (PortUpdate) querying [%s]:%d on port map ... ",
|
||||
mac2string(descriptor->macAddress),
|
||||
descriptor->portID);
|
||||
|
||||
if ((descriptor->type & recordFilter) != 0
|
||||
&& IS_PORT_INCLUDED(descriptor->portID, query))
|
||||
{
|
||||
MacDescriptor *descriptorClone = ixEthDBCloneMacDescriptor(descriptor);
|
||||
|
||||
IX_ETH_DB_UPDATE_TRACE("match\n");
|
||||
|
||||
if (descriptorClone != NULL)
|
||||
{
|
||||
/* add descriptor to tree */
|
||||
searchTree = ixEthDBTreeInsert(searchTree, descriptorClone);
|
||||
|
||||
entryCount++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IX_ETH_DB_UPDATE_TRACE("no match\n");
|
||||
}
|
||||
|
||||
if (entryCount < maxEntries)
|
||||
{
|
||||
/* advance to the next record */
|
||||
BUSY_RETRY(ixEthDBIncrementHashIterator(&dbHashtable, &iterator));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* the NPE won't accept more entries so we can stop now */
|
||||
ixEthDBReleaseHashIterator(&iterator);
|
||||
|
||||
IX_ETH_DB_UPDATE_TRACE("DB: (PortUpdate) number of elements reached maximum supported by port\n");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
IX_ETH_DB_UPDATE_TRACE("DB: (PortUpdate) query inserted %d records in the search tree\n", entryCount);
|
||||
|
||||
return ixEthDBTreeRebalance(searchTree);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief inserts a mac descriptor into an tree
|
||||
*
|
||||
* @param searchTree tree where the insertion is to be performed (may be NULL)
|
||||
* @param descriptor descriptor to insert into tree
|
||||
*
|
||||
* @return the tree root
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PRIVATE
|
||||
MacTreeNode* ixEthDBTreeInsert(MacTreeNode *searchTree, MacDescriptor *descriptor)
|
||||
{
|
||||
MacTreeNode *currentNode = searchTree;
|
||||
MacTreeNode *insertLocation = NULL;
|
||||
MacTreeNode *newNode;
|
||||
INT32 insertPosition = RIGHT;
|
||||
|
||||
if (descriptor == NULL)
|
||||
{
|
||||
return searchTree;
|
||||
}
|
||||
|
||||
/* create a new node */
|
||||
newNode = ixEthDBAllocMacTreeNode();
|
||||
|
||||
if (newNode == NULL)
|
||||
{
|
||||
/* out of memory */
|
||||
ERROR_LOG("Warning: ixEthDBAllocMacTreeNode returned NULL in file %s:%d (out of memory?)\n", __FILE__, __LINE__);
|
||||
|
||||
ixEthDBFreeMacDescriptor(descriptor);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* populate node */
|
||||
newNode->descriptor = descriptor;
|
||||
|
||||
/* an empty initial tree is a special case */
|
||||
if (searchTree == NULL)
|
||||
{
|
||||
return newNode;
|
||||
}
|
||||
|
||||
/* get insertion location */
|
||||
while (insertLocation == NULL)
|
||||
{
|
||||
MacTreeNode *nextNode;
|
||||
|
||||
/* compare given key with current node key */
|
||||
insertPosition = ixEthDBAddressCompare(descriptor->macAddress, currentNode->descriptor->macAddress);
|
||||
|
||||
/* navigate down */
|
||||
if (insertPosition == RIGHT)
|
||||
{
|
||||
nextNode = currentNode->right;
|
||||
}
|
||||
else if (insertPosition == LEFT)
|
||||
{
|
||||
nextNode = currentNode->left;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* error, duplicate key */
|
||||
ERROR_LOG("Warning: trapped insertion of a duplicate MAC address in an NPE search tree\n");
|
||||
|
||||
/* this will free the MAC descriptor as well */
|
||||
ixEthDBFreeMacTreeNode(newNode);
|
||||
|
||||
return searchTree;
|
||||
}
|
||||
|
||||
/* when we can no longer dive through the tree we found the insertion place */
|
||||
if (nextNode != NULL)
|
||||
{
|
||||
currentNode = nextNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
insertLocation = currentNode;
|
||||
}
|
||||
}
|
||||
|
||||
/* insert node */
|
||||
if (insertPosition == RIGHT)
|
||||
{
|
||||
insertLocation->right = newNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
insertLocation->left = newNode;
|
||||
}
|
||||
|
||||
return searchTree;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief balance a tree
|
||||
*
|
||||
* @param searchTree tree to balance
|
||||
*
|
||||
* Converts a tree into a balanced tree and returns the root of
|
||||
* the balanced tree. The resulting tree is <i>route balanced</i>
|
||||
* not <i>perfectly balanced</i>. This makes no difference to the
|
||||
* average tree search time which is the same in both cases, O(log2(n)).
|
||||
*
|
||||
* @return root of the balanced tree or NULL if there's no memory left
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PRIVATE
|
||||
MacTreeNode* ixEthDBTreeRebalance(MacTreeNode *searchTree)
|
||||
{
|
||||
MacTreeNode *pseudoRoot = ixEthDBAllocMacTreeNode();
|
||||
UINT32 size;
|
||||
|
||||
if (pseudoRoot == NULL)
|
||||
{
|
||||
/* out of memory */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pseudoRoot->right = searchTree;
|
||||
|
||||
ixEthDBRebalanceTreeToVine(pseudoRoot, &size);
|
||||
ixEthDBRebalanceVineToTree(pseudoRoot, size);
|
||||
|
||||
searchTree = pseudoRoot->right;
|
||||
|
||||
/* remove pseudoRoot right branch, otherwise it will free the entire tree */
|
||||
pseudoRoot->right = NULL;
|
||||
|
||||
ixEthDBFreeMacTreeNode(pseudoRoot);
|
||||
|
||||
return searchTree;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief converts a tree into a vine
|
||||
*
|
||||
* @param root root of tree to convert
|
||||
* @param size depth of vine (equal to the number of nodes in the tree)
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PRIVATE
|
||||
void ixEthDBRebalanceTreeToVine(MacTreeNode *root, UINT32 *size)
|
||||
{
|
||||
MacTreeNode *vineTail = root;
|
||||
MacTreeNode *remainder = vineTail->right;
|
||||
MacTreeNode *tempPtr;
|
||||
|
||||
*size = 0;
|
||||
|
||||
while (remainder != NULL)
|
||||
{
|
||||
if (remainder->left == NULL)
|
||||
{
|
||||
/* move tail down one */
|
||||
vineTail = remainder;
|
||||
remainder = remainder->right;
|
||||
(*size)++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* rotate around remainder */
|
||||
tempPtr = remainder->left;
|
||||
remainder->left = tempPtr->right;
|
||||
tempPtr->right = remainder;
|
||||
remainder = tempPtr;
|
||||
vineTail->right = tempPtr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief converts a vine into a balanced tree
|
||||
*
|
||||
* @param root vine to convert
|
||||
* @param size depth of vine
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PRIVATE
|
||||
void ixEthDBRebalanceVineToTree(MacTreeNode *root, UINT32 size)
|
||||
{
|
||||
UINT32 leafCount = size + 1 - (1 << ixEthDBRebalanceLog2Floor(size + 1));
|
||||
|
||||
ixEthDBRebalanceCompression(root, leafCount);
|
||||
|
||||
size = size - leafCount;
|
||||
|
||||
while (size > 1)
|
||||
{
|
||||
ixEthDBRebalanceCompression(root, size / 2);
|
||||
|
||||
size /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief compresses a vine/tree stage into a more balanced vine/tree
|
||||
*
|
||||
* @param root root of the tree to compress
|
||||
* @param count number of "spine" nodes
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PRIVATE
|
||||
void ixEthDBRebalanceCompression(MacTreeNode *root, UINT32 count)
|
||||
{
|
||||
MacTreeNode *scanner = root;
|
||||
MacTreeNode *child;
|
||||
UINT32 local_index;
|
||||
|
||||
for (local_index = 0 ; local_index < count ; local_index++)
|
||||
{
|
||||
child = scanner->right;
|
||||
scanner->right = child->right;
|
||||
scanner = scanner->right;
|
||||
child->right = scanner->left;
|
||||
scanner->left = child;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief computes |_log2(x)_| (a.k.a. floor(log2(x)))
|
||||
*
|
||||
* @param x number to compute |_log2(x)_| for
|
||||
*
|
||||
* @return |_log2(x)_|
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PRIVATE
|
||||
UINT32 ixEthDBRebalanceLog2Floor(UINT32 x)
|
||||
{
|
||||
UINT32 log = 0;
|
||||
UINT32 val = 1;
|
||||
|
||||
while (val < x)
|
||||
{
|
||||
log++;
|
||||
val <<= 1;
|
||||
}
|
||||
|
||||
return val == x ? log : log - 1;
|
||||
}
|
||||
|
652
cpu/ixp/npe/IxEthDBReports.c
Normal file
652
cpu/ixp/npe/IxEthDBReports.c
Normal file
@ -0,0 +1,652 @@
|
||||
/**
|
||||
* @file IxEthDBAPI.c
|
||||
*
|
||||
* @brief Implementation of the public API
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
#include "IxEthDB_p.h"
|
||||
|
||||
extern HashTable dbHashtable;
|
||||
IX_ETH_DB_PRIVATE void ixEthDBPortInfoShow(IxEthDBPortId portID, IxEthDBRecordType recordFilter);
|
||||
IX_ETH_DB_PRIVATE IxEthDBStatus ixEthDBHeaderShow(IxEthDBRecordType recordFilter);
|
||||
IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBDependencyPortMapShow(IxEthDBPortId portID, IxEthDBPortMap map);
|
||||
|
||||
/**
|
||||
* @brief displays a port dependency map
|
||||
*
|
||||
* @param portID ID of the port
|
||||
* @param map port map to display
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed
|
||||
* successfully
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBDependencyPortMapShow(IxEthDBPortId portID, IxEthDBPortMap map)
|
||||
{
|
||||
UINT32 portIndex;
|
||||
BOOL mapSelf = TRUE, mapNone = TRUE, firstPort = TRUE;
|
||||
|
||||
/* dependency port maps */
|
||||
printf("Dependency port map: ");
|
||||
|
||||
/* browse the port map */
|
||||
for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
|
||||
{
|
||||
if (IS_PORT_INCLUDED(portIndex, map))
|
||||
{
|
||||
mapNone = FALSE;
|
||||
|
||||
if (portIndex != portID)
|
||||
{
|
||||
mapSelf = FALSE;
|
||||
}
|
||||
|
||||
printf("%s%d", firstPort ? "{" : ", ", portIndex);
|
||||
|
||||
firstPort = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (mapNone)
|
||||
{
|
||||
mapSelf = FALSE;
|
||||
}
|
||||
|
||||
printf("%s (%s)\n", firstPort ? "" : "}", mapSelf ? "self" : mapNone ? "none" : "group");
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief displays all the filtering records belonging to a port
|
||||
*
|
||||
* @param portID ID of the port to display
|
||||
*
|
||||
* Note that this function is documented in the main component
|
||||
* header file, IxEthDB.h.
|
||||
*
|
||||
* @warning deprecated, use @ref ixEthDBFilteringDatabaseShowRecords()
|
||||
* instead. Calling this function is equivalent to calling
|
||||
* ixEthDBFilteringDatabaseShowRecords(portID, IX_ETH_DB_FILTERING_RECORD)
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBFilteringDatabaseShow(IxEthDBPortId portID)
|
||||
{
|
||||
IxEthDBStatus local_result;
|
||||
HashIterator iterator;
|
||||
PortInfo *portInfo;
|
||||
UINT32 recordCount = 0;
|
||||
|
||||
IX_ETH_DB_CHECK_PORT(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
portInfo = &ixEthDBPortInfo[portID];
|
||||
|
||||
/* display table header */
|
||||
printf("Ethernet database records for port ID [%d]\n", portID);
|
||||
|
||||
ixEthDBDependencyPortMapShow(portID, portInfo->dependencyPortMap);
|
||||
|
||||
if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
|
||||
{
|
||||
printf("NPE updates are %s\n\n", portInfo->updateMethod.updateEnabled ? "enabled" : "disabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("updates disabled (not an NPE)\n\n");
|
||||
}
|
||||
|
||||
printf(" MAC address | Age | Type \n");
|
||||
printf("___________________________________\n");
|
||||
|
||||
/* browse database */
|
||||
BUSY_RETRY(ixEthDBInitHashIterator(&dbHashtable, &iterator));
|
||||
|
||||
while (IS_ITERATOR_VALID(&iterator))
|
||||
{
|
||||
MacDescriptor *descriptor = (MacDescriptor *) iterator.node->data;
|
||||
|
||||
if (descriptor->portID == portID && descriptor->type == IX_ETH_DB_FILTERING_RECORD)
|
||||
{
|
||||
recordCount++;
|
||||
|
||||
/* display entry */
|
||||
printf(" %02X:%02X:%02X:%02X:%02X:%02X | %5d | %s\n",
|
||||
descriptor->macAddress[0],
|
||||
descriptor->macAddress[1],
|
||||
descriptor->macAddress[2],
|
||||
descriptor->macAddress[3],
|
||||
descriptor->macAddress[4],
|
||||
descriptor->macAddress[5],
|
||||
descriptor->recordData.filteringData.age,
|
||||
descriptor->recordData.filteringData.staticEntry ? "static" : "dynamic");
|
||||
}
|
||||
|
||||
/* move to the next record */
|
||||
BUSY_RETRY_WITH_RESULT(ixEthDBIncrementHashIterator(&dbHashtable, &iterator), local_result);
|
||||
|
||||
/* debug */
|
||||
if (local_result == IX_ETH_DB_BUSY)
|
||||
{
|
||||
return IX_ETH_DB_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/* display number of records */
|
||||
printf("\nFound %d records\n", recordCount);
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief displays all the filtering records belonging to all the ports
|
||||
*
|
||||
* Note that this function is documented in the main component
|
||||
* header file, IxEthDB.h.
|
||||
*
|
||||
* @warning deprecated, use @ref ixEthDBFilteringDatabaseShowRecords()
|
||||
* instead. Calling this function is equivalent to calling
|
||||
* ixEthDBFilteringDatabaseShowRecords(IX_ETH_DB_ALL_PORTS, IX_ETH_DB_FILTERING_RECORD)
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
void ixEthDBFilteringDatabaseShowAll()
|
||||
{
|
||||
IxEthDBPortId portIndex;
|
||||
|
||||
printf("\nEthernet learning/filtering database: listing %d ports\n\n", (UINT32) IX_ETH_DB_NUMBER_OF_PORTS);
|
||||
|
||||
for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
|
||||
{
|
||||
ixEthDBFilteringDatabaseShow(portIndex);
|
||||
|
||||
if (portIndex < IX_ETH_DB_NUMBER_OF_PORTS - 1)
|
||||
{
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief displays one record in a format depending on the record filter
|
||||
*
|
||||
* @param descriptor pointer to the record
|
||||
* @param recordFilter format filter
|
||||
*
|
||||
* This function will display the fields in a record depending on the
|
||||
* selected record filter.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PRIVATE
|
||||
void ixEthDBRecordShow(MacDescriptor *descriptor, IxEthDBRecordType recordFilter)
|
||||
{
|
||||
if (recordFilter == IX_ETH_DB_FILTERING_VLAN_RECORD
|
||||
|| recordFilter == (IX_ETH_DB_FILTERING_RECORD | IX_ETH_DB_FILTERING_VLAN_RECORD))
|
||||
{
|
||||
/* display VLAN record header - leave this commented code in place, its purpose is to align the print format with the header
|
||||
printf(" MAC address | Age | Type | VLAN ID | CFI | QoS class \n");
|
||||
printf("___________________________________________________________________\n"); */
|
||||
|
||||
if (descriptor->type == IX_ETH_DB_FILTERING_VLAN_RECORD)
|
||||
{
|
||||
printf("%02X:%02X:%02X:%02X:%02X:%02X | %3d | %s | %d | %d | %d\n",
|
||||
descriptor->macAddress[0],
|
||||
descriptor->macAddress[1],
|
||||
descriptor->macAddress[2],
|
||||
descriptor->macAddress[3],
|
||||
descriptor->macAddress[4],
|
||||
descriptor->macAddress[5],
|
||||
descriptor->recordData.filteringVlanData.age,
|
||||
descriptor->recordData.filteringVlanData.staticEntry ? "static" : "dynamic",
|
||||
IX_ETH_DB_GET_VLAN_ID(descriptor->recordData.filteringVlanData.ieee802_1qTag),
|
||||
(descriptor->recordData.filteringVlanData.ieee802_1qTag & 0x1000) >> 12,
|
||||
IX_ETH_DB_GET_QOS_PRIORITY(descriptor->recordData.filteringVlanData.ieee802_1qTag));
|
||||
}
|
||||
else if (descriptor->type == IX_ETH_DB_FILTERING_RECORD)
|
||||
{
|
||||
printf("%02X:%02X:%02X:%02X:%02X:%02X | %3d | %s | - | - | -\n",
|
||||
descriptor->macAddress[0],
|
||||
descriptor->macAddress[1],
|
||||
descriptor->macAddress[2],
|
||||
descriptor->macAddress[3],
|
||||
descriptor->macAddress[4],
|
||||
descriptor->macAddress[5],
|
||||
descriptor->recordData.filteringData.age,
|
||||
descriptor->recordData.filteringData.staticEntry ? "static" : "dynamic");
|
||||
}
|
||||
}
|
||||
else if (recordFilter == IX_ETH_DB_FILTERING_RECORD)
|
||||
{
|
||||
/* display filtering record header - leave this commented code in place, its purpose is to align the print format with the header
|
||||
printf(" MAC address | Age | Type \n");
|
||||
printf("_______________________________________\n"); */
|
||||
|
||||
if (descriptor->type == IX_ETH_DB_FILTERING_RECORD)
|
||||
{
|
||||
printf("%02X:%02X:%02X:%02X:%02X:%02X | %3d | %s \n",
|
||||
descriptor->macAddress[0],
|
||||
descriptor->macAddress[1],
|
||||
descriptor->macAddress[2],
|
||||
descriptor->macAddress[3],
|
||||
descriptor->macAddress[4],
|
||||
descriptor->macAddress[5],
|
||||
descriptor->recordData.filteringData.age,
|
||||
descriptor->recordData.filteringData.staticEntry ? "static" : "dynamic");
|
||||
}
|
||||
}
|
||||
else if (recordFilter == IX_ETH_DB_WIFI_RECORD)
|
||||
{
|
||||
/* display WiFi record header - leave this commented code in place, its purpose is to align the print format with the header
|
||||
printf(" MAC address | GW MAC address \n");
|
||||
printf("_______________________________________\n"); */
|
||||
|
||||
if (descriptor->type == IX_ETH_DB_WIFI_RECORD)
|
||||
{
|
||||
if (descriptor->recordData.wifiData.type == IX_ETH_DB_WIFI_AP_TO_AP)
|
||||
{
|
||||
/* gateway address present */
|
||||
printf("%02X:%02X:%02X:%02X:%02X:%02X | %02X:%02X:%02X:%02X:%02X:%02X \n",
|
||||
descriptor->macAddress[0],
|
||||
descriptor->macAddress[1],
|
||||
descriptor->macAddress[2],
|
||||
descriptor->macAddress[3],
|
||||
descriptor->macAddress[4],
|
||||
descriptor->macAddress[5],
|
||||
descriptor->recordData.wifiData.gwMacAddress[0],
|
||||
descriptor->recordData.wifiData.gwMacAddress[1],
|
||||
descriptor->recordData.wifiData.gwMacAddress[2],
|
||||
descriptor->recordData.wifiData.gwMacAddress[3],
|
||||
descriptor->recordData.wifiData.gwMacAddress[4],
|
||||
descriptor->recordData.wifiData.gwMacAddress[5]);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no gateway */
|
||||
printf("%02X:%02X:%02X:%02X:%02X:%02X | ----no gateway----- \n",
|
||||
descriptor->macAddress[0],
|
||||
descriptor->macAddress[1],
|
||||
descriptor->macAddress[2],
|
||||
descriptor->macAddress[3],
|
||||
descriptor->macAddress[4],
|
||||
descriptor->macAddress[5]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (recordFilter == IX_ETH_DB_FIREWALL_RECORD)
|
||||
{
|
||||
/* display Firewall record header - leave this commented code in place, its purpose is to align the print format with the header
|
||||
printf(" MAC address \n");
|
||||
printf("__________________\n"); */
|
||||
|
||||
if (descriptor->type == IX_ETH_DB_FIREWALL_RECORD)
|
||||
{
|
||||
printf("%02X:%02X:%02X:%02X:%02X:%02X \n",
|
||||
descriptor->macAddress[0],
|
||||
descriptor->macAddress[1],
|
||||
descriptor->macAddress[2],
|
||||
descriptor->macAddress[3],
|
||||
descriptor->macAddress[4],
|
||||
descriptor->macAddress[5]);
|
||||
}
|
||||
}
|
||||
else if (recordFilter == IX_ETH_DB_ALL_RECORD_TYPES)
|
||||
{
|
||||
/* display composite record header - leave this commented code in place, its purpose is to align the print format with the header
|
||||
printf(" MAC address | Record | Age| Type | VLAN |CFI| QoS | GW MAC address \n");
|
||||
printf("_______________________________________________________________________________\n"); */
|
||||
|
||||
if (descriptor->type == IX_ETH_DB_FILTERING_VLAN_RECORD)
|
||||
{
|
||||
printf("%02X:%02X:%02X:%02X:%02X:%02X | VLAN | %2d | %s | %4d | %1d | %1d | -----------------\n",
|
||||
descriptor->macAddress[0],
|
||||
descriptor->macAddress[1],
|
||||
descriptor->macAddress[2],
|
||||
descriptor->macAddress[3],
|
||||
descriptor->macAddress[4],
|
||||
descriptor->macAddress[5],
|
||||
descriptor->recordData.filteringVlanData.age,
|
||||
descriptor->recordData.filteringVlanData.staticEntry ? "static " : "dynamic",
|
||||
IX_ETH_DB_GET_VLAN_ID(descriptor->recordData.filteringVlanData.ieee802_1qTag),
|
||||
(descriptor->recordData.filteringVlanData.ieee802_1qTag & 0x1000) >> 12,
|
||||
IX_ETH_DB_GET_QOS_PRIORITY(descriptor->recordData.filteringVlanData.ieee802_1qTag));
|
||||
}
|
||||
else if (descriptor->type == IX_ETH_DB_FILTERING_RECORD)
|
||||
{
|
||||
printf("%02X:%02X:%02X:%02X:%02X:%02X | Filter | %2d | %s | ---- | - | --- | -----------------\n",
|
||||
descriptor->macAddress[0],
|
||||
descriptor->macAddress[1],
|
||||
descriptor->macAddress[2],
|
||||
descriptor->macAddress[3],
|
||||
descriptor->macAddress[4],
|
||||
descriptor->macAddress[5],
|
||||
descriptor->recordData.filteringData.age,
|
||||
descriptor->recordData.filteringData.staticEntry ? "static " : "dynamic");
|
||||
}
|
||||
else if (descriptor->type == IX_ETH_DB_WIFI_RECORD)
|
||||
{
|
||||
if (descriptor->recordData.wifiData.type == IX_ETH_DB_WIFI_AP_TO_AP)
|
||||
{
|
||||
/* gateway address present */
|
||||
printf("%02X:%02X:%02X:%02X:%02X:%02X | WiFi | -- | AP=>AP | ---- | - | --- | %02X:%02X:%02X:%02X:%02X:%02X\n",
|
||||
descriptor->macAddress[0],
|
||||
descriptor->macAddress[1],
|
||||
descriptor->macAddress[2],
|
||||
descriptor->macAddress[3],
|
||||
descriptor->macAddress[4],
|
||||
descriptor->macAddress[5],
|
||||
descriptor->recordData.wifiData.gwMacAddress[0],
|
||||
descriptor->recordData.wifiData.gwMacAddress[1],
|
||||
descriptor->recordData.wifiData.gwMacAddress[2],
|
||||
descriptor->recordData.wifiData.gwMacAddress[3],
|
||||
descriptor->recordData.wifiData.gwMacAddress[4],
|
||||
descriptor->recordData.wifiData.gwMacAddress[5]);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no gateway */
|
||||
printf("%02X:%02X:%02X:%02X:%02X:%02X | WiFi | -- | AP=>ST | ---- | - | --- | -- no gateway -- \n",
|
||||
descriptor->macAddress[0],
|
||||
descriptor->macAddress[1],
|
||||
descriptor->macAddress[2],
|
||||
descriptor->macAddress[3],
|
||||
descriptor->macAddress[4],
|
||||
descriptor->macAddress[5]);
|
||||
}
|
||||
}
|
||||
else if (descriptor->type == IX_ETH_DB_FIREWALL_RECORD)
|
||||
{
|
||||
printf("%02X:%02X:%02X:%02X:%02X:%02X | FW | -- | ------- | ---- | - | --- | -----------------\n",
|
||||
descriptor->macAddress[0],
|
||||
descriptor->macAddress[1],
|
||||
descriptor->macAddress[2],
|
||||
descriptor->macAddress[3],
|
||||
descriptor->macAddress[4],
|
||||
descriptor->macAddress[5]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("invalid record filter\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief displays the status, records and configuration information of a port
|
||||
*
|
||||
* @param portID ID of the port
|
||||
* @param recordFilter record filter to display
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PRIVATE
|
||||
void ixEthDBPortInfoShow(IxEthDBPortId portID, IxEthDBRecordType recordFilter)
|
||||
{
|
||||
PortInfo *portInfo = &ixEthDBPortInfo[portID];
|
||||
UINT32 recordCount = 0;
|
||||
HashIterator iterator;
|
||||
IxEthDBStatus local_result;
|
||||
|
||||
/* display port status */
|
||||
printf("== Port ID %d ==\n", portID);
|
||||
|
||||
/* display capabilities */
|
||||
printf("- Capabilities: ");
|
||||
|
||||
if ((portInfo->featureCapability & IX_ETH_DB_LEARNING) != 0)
|
||||
{
|
||||
printf("Learning (%s) ", ((portInfo->featureStatus & IX_ETH_DB_LEARNING) != 0) ? "on" : "off");
|
||||
}
|
||||
|
||||
if ((portInfo->featureCapability & IX_ETH_DB_VLAN_QOS) != 0)
|
||||
{
|
||||
printf("VLAN/QoS (%s) ", ((portInfo->featureStatus & IX_ETH_DB_VLAN_QOS) != 0) ? "on" : "off");
|
||||
}
|
||||
|
||||
if ((portInfo->featureCapability & IX_ETH_DB_FIREWALL) != 0)
|
||||
{
|
||||
printf("Firewall (%s) ", ((portInfo->featureStatus & IX_ETH_DB_FIREWALL) != 0) ? "on" : "off");
|
||||
}
|
||||
|
||||
if ((portInfo->featureCapability & IX_ETH_DB_WIFI_HEADER_CONVERSION) != 0)
|
||||
{
|
||||
printf("WiFi (%s) ", ((portInfo->featureStatus & IX_ETH_DB_WIFI_HEADER_CONVERSION) != 0) ? "on" : "off");
|
||||
}
|
||||
|
||||
if ((portInfo->featureCapability & IX_ETH_DB_SPANNING_TREE_PROTOCOL) != 0)
|
||||
{
|
||||
printf("STP (%s) ", ((portInfo->featureStatus & IX_ETH_DB_SPANNING_TREE_PROTOCOL) != 0) ? "on" : "off");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
/* dependency map */
|
||||
ixEthDBDependencyPortMapShow(portID, portInfo->dependencyPortMap);
|
||||
|
||||
/* NPE dynamic updates */
|
||||
if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
|
||||
{
|
||||
printf(" - NPE dynamic update is %s\n", portInfo->updateMethod.updateEnabled ? "enabled" : "disabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" - dynamic update disabled (not an NPE)\n");
|
||||
}
|
||||
|
||||
if ((portInfo->featureCapability & IX_ETH_DB_WIFI_HEADER_CONVERSION) != 0)
|
||||
{
|
||||
if ((portInfo->featureStatus & IX_ETH_DB_WIFI_HEADER_CONVERSION) != 0)
|
||||
{
|
||||
/* WiFi header conversion */
|
||||
if ((portInfo->frameControlDurationID
|
||||
+ portInfo->bbsid[0]
|
||||
+ portInfo->bbsid[1]
|
||||
+ portInfo->bbsid[2]
|
||||
+ portInfo->bbsid[3]
|
||||
+ portInfo->bbsid[4]
|
||||
+ portInfo->bbsid[5]) == 0)
|
||||
{
|
||||
printf(" - WiFi header conversion not configured\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" - WiFi header conversion: BBSID [%02X:%02X:%02X:%02X:%02X:%02X], Frame Control 0x%X, Duration/ID 0x%X\n",
|
||||
portInfo->bbsid[0],
|
||||
portInfo->bbsid[1],
|
||||
portInfo->bbsid[2],
|
||||
portInfo->bbsid[3],
|
||||
portInfo->bbsid[4],
|
||||
portInfo->bbsid[5],
|
||||
portInfo->frameControlDurationID >> 16,
|
||||
portInfo->frameControlDurationID & 0xFFFF);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" - WiFi header conversion not enabled\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Firewall */
|
||||
if ((portInfo->featureCapability & IX_ETH_DB_FIREWALL) != 0)
|
||||
{
|
||||
if ((portInfo->featureStatus & IX_ETH_DB_FIREWALL) != 0)
|
||||
{
|
||||
printf(" - Firewall is in %s-list mode\n", portInfo->firewallMode == IX_ETH_DB_FIREWALL_BLACK_LIST ? "black" : "white");
|
||||
printf(" - Invalid source MAC address filtering is %s\n", portInfo->srcAddressFilterEnabled ? "enabled" : "disabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" - Firewall not enabled\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* browse database if asked to display records */
|
||||
if (recordFilter != IX_ETH_DB_NO_RECORD_TYPE)
|
||||
{
|
||||
printf("\n");
|
||||
ixEthDBHeaderShow(recordFilter);
|
||||
|
||||
BUSY_RETRY(ixEthDBInitHashIterator(&dbHashtable, &iterator));
|
||||
|
||||
while (IS_ITERATOR_VALID(&iterator))
|
||||
{
|
||||
MacDescriptor *descriptor = (MacDescriptor *) iterator.node->data;
|
||||
|
||||
if (descriptor->portID == portID && (descriptor->type & recordFilter) != 0)
|
||||
{
|
||||
recordCount++;
|
||||
|
||||
/* display entry */
|
||||
ixEthDBRecordShow(descriptor, recordFilter);
|
||||
}
|
||||
|
||||
/* move to the next record */
|
||||
BUSY_RETRY_WITH_RESULT(ixEthDBIncrementHashIterator(&dbHashtable, &iterator), local_result);
|
||||
|
||||
/* debug */
|
||||
if (local_result == IX_ETH_DB_BUSY)
|
||||
{
|
||||
printf("EthDB (API): Error, database browser failed (no access), giving up\n");
|
||||
}
|
||||
}
|
||||
|
||||
printf("\nFound %d records\n\n", recordCount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief displays a record header
|
||||
*
|
||||
* @param recordFilter record type filter
|
||||
*
|
||||
* This function displays a record header, depending on
|
||||
* the given record type filter. It is useful when used
|
||||
* in conjunction with ixEthDBRecordShow which will display
|
||||
* record fields formatted for the header, provided the same
|
||||
* record filter is used.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed
|
||||
* successfully or IX_ETH_DB_INVALID_ARG if the recordFilter
|
||||
* parameter is invalid or not supported
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PRIVATE
|
||||
IxEthDBStatus ixEthDBHeaderShow(IxEthDBRecordType recordFilter)
|
||||
{
|
||||
if (recordFilter == IX_ETH_DB_FILTERING_VLAN_RECORD
|
||||
|| recordFilter == (IX_ETH_DB_FILTERING_RECORD | IX_ETH_DB_FILTERING_VLAN_RECORD))
|
||||
{
|
||||
/* display VLAN record header */
|
||||
printf(" MAC address | Age | Type | VLAN ID | CFI | QoS class \n");
|
||||
printf("___________________________________________________________________\n");
|
||||
}
|
||||
else if (recordFilter == IX_ETH_DB_FILTERING_RECORD)
|
||||
{
|
||||
/* display filtering record header */
|
||||
printf(" MAC address | Age | Type \n");
|
||||
printf("_______________________________________\n");
|
||||
}
|
||||
else if (recordFilter == IX_ETH_DB_WIFI_RECORD)
|
||||
{
|
||||
/* display WiFi record header */
|
||||
printf(" MAC address | GW MAC address \n");
|
||||
printf("_______________________________________\n");
|
||||
}
|
||||
else if (recordFilter == IX_ETH_DB_FIREWALL_RECORD)
|
||||
{
|
||||
/* display Firewall record header */
|
||||
printf(" MAC address \n");
|
||||
printf("__________________\n");
|
||||
}
|
||||
else if (recordFilter == IX_ETH_DB_ALL_RECORD_TYPES)
|
||||
{
|
||||
/* display composite record header */
|
||||
printf(" MAC address | Record | Age| Type | VLAN |CFI| QoS | GW MAC address \n");
|
||||
printf("_______________________________________________________________________________\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
return IX_ETH_DB_INVALID_ARG;
|
||||
}
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief displays database information (records and port information)
|
||||
*
|
||||
* @param portID ID of the port to display (or IX_ETH_DB_ALL_PORTS for all the ports)
|
||||
* @param recordFilter record filter (use IX_ETH_DB_NO_RECORD_TYPE to display only
|
||||
* port information)
|
||||
*
|
||||
* Note that this function is documented in the main component header
|
||||
* file, IxEthDB.h.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed successfully or
|
||||
* an appropriate error code otherwise
|
||||
*
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBFilteringDatabaseShowRecords(IxEthDBPortId portID, IxEthDBRecordType recordFilter)
|
||||
{
|
||||
IxEthDBPortId currentPort;
|
||||
BOOL showAllPorts = (portID == IX_ETH_DB_ALL_PORTS);
|
||||
|
||||
IX_ETH_DB_CHECK_PORT_ALL(portID);
|
||||
|
||||
printf("\nEthernet learning/filtering database: listing %d port(s)\n\n", showAllPorts ? (UINT32) IX_ETH_DB_NUMBER_OF_PORTS : 1);
|
||||
|
||||
currentPort = showAllPorts ? 0 : portID;
|
||||
|
||||
while (currentPort != IX_ETH_DB_NUMBER_OF_PORTS)
|
||||
{
|
||||
/* display port info */
|
||||
ixEthDBPortInfoShow(currentPort, recordFilter);
|
||||
|
||||
/* next port */
|
||||
currentPort = showAllPorts ? currentPort + 1 : IX_ETH_DB_NUMBER_OF_PORTS;
|
||||
}
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
327
cpu/ixp/npe/IxEthDBSearch.c
Normal file
327
cpu/ixp/npe/IxEthDBSearch.c
Normal file
@ -0,0 +1,327 @@
|
||||
/**
|
||||
* @file IxEthDBSearch.c
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
#include "IxEthDB_p.h"
|
||||
|
||||
extern HashTable dbHashtable;
|
||||
|
||||
/**
|
||||
* @brief matches two database records based on their MAC addresses
|
||||
*
|
||||
* @param untypedReference record to match against
|
||||
* @param untypedEntry record to match
|
||||
*
|
||||
* @return TRUE if the match is successful or FALSE otherwise
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
BOOL ixEthDBAddressRecordMatch(void *untypedReference, void *untypedEntry)
|
||||
{
|
||||
MacDescriptor *entry = (MacDescriptor *) untypedEntry;
|
||||
MacDescriptor *reference = (MacDescriptor *) untypedReference;
|
||||
|
||||
/* check accepted record types */
|
||||
if ((entry->type & reference->type) == 0) return FALSE;
|
||||
|
||||
return (ixEthDBAddressCompare((UINT8 *) entry->macAddress, (UINT8 *) reference->macAddress) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief matches two database records based on their MAC addresses
|
||||
* and VLAN IDs
|
||||
*
|
||||
* @param untypedReference record to match against
|
||||
* @param untypedEntry record to match
|
||||
*
|
||||
* @return TRUE if the match is successful or FALSE otherwise
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
BOOL ixEthDBVlanRecordMatch(void *untypedReference, void *untypedEntry)
|
||||
{
|
||||
MacDescriptor *entry = (MacDescriptor *) untypedEntry;
|
||||
MacDescriptor *reference = (MacDescriptor *) untypedReference;
|
||||
|
||||
/* check accepted record types */
|
||||
if ((entry->type & reference->type) == 0) return FALSE;
|
||||
|
||||
return (IX_ETH_DB_GET_VLAN_ID(entry->recordData.filteringVlanData.ieee802_1qTag) ==
|
||||
IX_ETH_DB_GET_VLAN_ID(reference->recordData.filteringVlanData.ieee802_1qTag)) &&
|
||||
(ixEthDBAddressCompare(entry->macAddress, reference->macAddress) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief matches two database records based on their MAC addresses
|
||||
* and port IDs
|
||||
*
|
||||
* @param untypedReference record to match against
|
||||
* @param untypedEntry record to match
|
||||
*
|
||||
* @return TRUE if the match is successful or FALSE otherwise
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
BOOL ixEthDBPortRecordMatch(void *untypedReference, void *untypedEntry)
|
||||
{
|
||||
MacDescriptor *entry = (MacDescriptor *) untypedEntry;
|
||||
MacDescriptor *reference = (MacDescriptor *) untypedReference;
|
||||
|
||||
/* check accepted record types */
|
||||
if ((entry->type & reference->type) == 0) return FALSE;
|
||||
|
||||
return (entry->portID == reference->portID) &&
|
||||
(ixEthDBAddressCompare(entry->macAddress, reference->macAddress) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief dummy matching function, registered for safety
|
||||
*
|
||||
* @param reference record to match against (unused)
|
||||
* @param entry record to match (unused)
|
||||
*
|
||||
* This function is registered in the matching functions
|
||||
* array on invalid types. Calling it will display an
|
||||
* error message, indicating an error in the component logic.
|
||||
*
|
||||
* @return FALSE
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
BOOL ixEthDBNullMatch(void *reference, void *entry)
|
||||
{
|
||||
/* display an error message */
|
||||
|
||||
ixOsalLog(IX_OSAL_LOG_LVL_WARNING, IX_OSAL_LOG_DEV_STDOUT, "DB: (Search) The NullMatch function was called, wrong key type?\n", 0, 0, 0, 0, 0, 0);
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief registers hash matching methods
|
||||
*
|
||||
* @param matchFunctions table of match functions to be populated
|
||||
*
|
||||
* This function registers the available record matching functions
|
||||
* by indexing them on record types into the given function array.
|
||||
*
|
||||
* Note that it is compulsory to call this in ixEthDBInit(),
|
||||
* otherwise hashtable searching and removal will not work
|
||||
*
|
||||
* @return number of registered functions
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
UINT32 ixEthDBMatchMethodsRegister(MatchFunction *matchFunctions)
|
||||
{
|
||||
UINT32 i;
|
||||
|
||||
/* safety first */
|
||||
for ( i = 0 ; i < IX_ETH_DB_MAX_KEY_INDEX + 1 ; i++)
|
||||
{
|
||||
matchFunctions[i] = ixEthDBNullMatch;
|
||||
}
|
||||
|
||||
/* register MAC search method */
|
||||
matchFunctions[IX_ETH_DB_MAC_KEY] = ixEthDBAddressRecordMatch;
|
||||
|
||||
/* register MAC/PortID search method */
|
||||
matchFunctions[IX_ETH_DB_MAC_PORT_KEY] = ixEthDBPortRecordMatch;
|
||||
|
||||
/* register MAC/VLAN ID search method */
|
||||
matchFunctions[IX_ETH_DB_MAC_VLAN_KEY] = ixEthDBVlanRecordMatch;
|
||||
|
||||
return 3; /* three methods */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief search a record in the Ethernet datbase
|
||||
*
|
||||
* @param macAddress MAC address to perform the search on
|
||||
* @param typeFilter type of records to consider for matching
|
||||
*
|
||||
* @warning if searching is successful an implicit write lock
|
||||
* to the search result is granted, therefore unlock the
|
||||
* entry using @ref ixEthDBReleaseHashNode() as soon as possible.
|
||||
*
|
||||
* @see ixEthDBReleaseHashNode()
|
||||
*
|
||||
* @return the search result, or NULL if a record with the given
|
||||
* MAC address was not found
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
HashNode* ixEthDBSearch(IxEthDBMacAddr *macAddress, IxEthDBRecordType typeFilter)
|
||||
{
|
||||
HashNode *searchResult = NULL;
|
||||
MacDescriptor reference;
|
||||
|
||||
TEST_FIXTURE_INCREMENT_DB_CORE_ACCESS_COUNTER;
|
||||
|
||||
if (macAddress == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* fill search fields */
|
||||
memcpy(reference.macAddress, macAddress, sizeof (IxEthDBMacAddr));
|
||||
|
||||
/* set acceptable record types */
|
||||
reference.type = typeFilter;
|
||||
|
||||
BUSY_RETRY(ixEthDBSearchHashEntry(&dbHashtable, IX_ETH_DB_MAC_KEY, &reference, &searchResult));
|
||||
|
||||
return searchResult;
|
||||
}
|
||||
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBPeek(IxEthDBMacAddr *macAddress, IxEthDBRecordType typeFilter)
|
||||
{
|
||||
MacDescriptor reference;
|
||||
IxEthDBStatus result;
|
||||
|
||||
TEST_FIXTURE_INCREMENT_DB_CORE_ACCESS_COUNTER;
|
||||
|
||||
if (macAddress == NULL)
|
||||
{
|
||||
return IX_ETH_DB_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* fill search fields */
|
||||
memcpy(reference.macAddress, macAddress, sizeof (IxEthDBMacAddr));
|
||||
|
||||
/* set acceptable record types */
|
||||
reference.type = typeFilter;
|
||||
|
||||
result = ixEthDBPeekHashEntry(&dbHashtable, IX_ETH_DB_MAC_KEY, &reference);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief search a record in the Ethernet datbase
|
||||
*
|
||||
* @param macAddress MAC address to perform the search on
|
||||
* @param portID port ID to perform the search on
|
||||
* @param typeFilter type of records to consider for matching
|
||||
*
|
||||
* @warning if searching is successful an implicit write lock
|
||||
* to the search result is granted, therefore unlock the
|
||||
* entry using @ref ixEthDBReleaseHashNode() as soon as possible.
|
||||
*
|
||||
* @see ixEthDBReleaseHashNode()
|
||||
*
|
||||
* @return the search result, or NULL if a record with the given
|
||||
* MAC address/port ID combination was not found
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
HashNode* ixEthDBPortSearch(IxEthDBMacAddr *macAddress, IxEthDBPortId portID, IxEthDBRecordType typeFilter)
|
||||
{
|
||||
HashNode *searchResult = NULL;
|
||||
MacDescriptor reference;
|
||||
|
||||
if (macAddress == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* fill search fields */
|
||||
memcpy(reference.macAddress, macAddress, sizeof (IxEthDBMacAddr));
|
||||
reference.portID = portID;
|
||||
|
||||
/* set acceptable record types */
|
||||
reference.type = typeFilter;
|
||||
|
||||
BUSY_RETRY(ixEthDBSearchHashEntry(&dbHashtable, IX_ETH_DB_MAC_PORT_KEY, &reference, &searchResult));
|
||||
|
||||
return searchResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief search a record in the Ethernet datbase
|
||||
*
|
||||
* @param macAddress MAC address to perform the search on
|
||||
* @param vlanID VLAN ID to perform the search on
|
||||
* @param typeFilter type of records to consider for matching
|
||||
*
|
||||
* @warning if searching is successful an implicit write lock
|
||||
* to the search result is granted, therefore unlock the
|
||||
* entry using @ref ixEthDBReleaseHashNode() as soon as possible.
|
||||
*
|
||||
* @see ixEthDBReleaseHashNode()
|
||||
*
|
||||
* @return the search result, or NULL if a record with the given
|
||||
* MAC address/VLAN ID combination was not found
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
HashNode* ixEthDBVlanSearch(IxEthDBMacAddr *macAddress, IxEthDBVlanId vlanID, IxEthDBRecordType typeFilter)
|
||||
{
|
||||
HashNode *searchResult = NULL;
|
||||
MacDescriptor reference;
|
||||
|
||||
if (macAddress == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* fill search fields */
|
||||
memcpy(reference.macAddress, macAddress, sizeof (IxEthDBMacAddr));
|
||||
reference.recordData.filteringVlanData.ieee802_1qTag =
|
||||
IX_ETH_DB_SET_VLAN_ID(reference.recordData.filteringVlanData.ieee802_1qTag, vlanID);
|
||||
|
||||
/* set acceptable record types */
|
||||
reference.type = typeFilter;
|
||||
|
||||
BUSY_RETRY(ixEthDBSearchHashEntry(&dbHashtable, IX_ETH_DB_MAC_VLAN_KEY, &reference, &searchResult));
|
||||
|
||||
return searchResult;
|
||||
}
|
107
cpu/ixp/npe/IxEthDBSpanningTree.c
Normal file
107
cpu/ixp/npe/IxEthDBSpanningTree.c
Normal file
@ -0,0 +1,107 @@
|
||||
/**
|
||||
* @file IxEthDBSpanningTree.c
|
||||
*
|
||||
* @brief Implementation of the STP API
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
|
||||
#include "IxEthDB_p.h"
|
||||
|
||||
/**
|
||||
* @brief sets the STP blocking state of a port
|
||||
*
|
||||
* @param portID ID of the port
|
||||
* @param blocked TRUE to block the port or FALSE to unblock it
|
||||
*
|
||||
* Note that this function is documented in the main component
|
||||
* header file, IxEthDB.h.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed successfully
|
||||
* or an appropriate error message otherwise
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBSpanningTreeBlockingStateSet(IxEthDBPortId portID, BOOL blocked)
|
||||
{
|
||||
IxNpeMhMessage message;
|
||||
IX_STATUS result;
|
||||
|
||||
IX_ETH_DB_CHECK_PORT(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_SPANNING_TREE_PROTOCOL);
|
||||
|
||||
ixEthDBPortInfo[portID].stpBlocked = blocked;
|
||||
|
||||
FILL_SETBLOCKINGSTATE_MSG(message, portID, blocked);
|
||||
|
||||
IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief retrieves the STP blocking state of a port
|
||||
*
|
||||
* @param portID ID of the port
|
||||
* @param blocked address to write the blocked status into
|
||||
*
|
||||
* Note that this function is documented in the main component
|
||||
* header file, IxEthDB.h.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed successfully
|
||||
* or an appropriate error message otherwise
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBSpanningTreeBlockingStateGet(IxEthDBPortId portID, BOOL *blocked)
|
||||
{
|
||||
IX_ETH_DB_CHECK_PORT(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_SPANNING_TREE_PROTOCOL);
|
||||
|
||||
IX_ETH_DB_CHECK_REFERENCE(blocked);
|
||||
|
||||
*blocked = ixEthDBPortInfo[portID].stpBlocked;
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
120
cpu/ixp/npe/IxEthDBUtil.c
Normal file
120
cpu/ixp/npe/IxEthDBUtil.c
Normal file
@ -0,0 +1,120 @@
|
||||
/**
|
||||
* @file ethUtil.c
|
||||
*
|
||||
* @brief Utility functions
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
|
||||
#include "IxFeatureCtrl.h"
|
||||
#include "IxEthDB_p.h"
|
||||
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBSingleEthNpeCheck(IxEthDBPortId portID)
|
||||
{
|
||||
/* If not IXP42X A0 stepping, proceed to check for existence of coprocessors */
|
||||
if ((IX_FEATURE_CTRL_SILICON_TYPE_A0 !=
|
||||
(ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK))
|
||||
|| (IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X != ixFeatureCtrlDeviceRead ()))
|
||||
{
|
||||
if ((portID == 0) &&
|
||||
(ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH0) ==
|
||||
IX_FEATURE_CTRL_COMPONENT_DISABLED))
|
||||
{
|
||||
return IX_ETH_DB_FAIL;
|
||||
}
|
||||
|
||||
if ((portID == 1) &&
|
||||
(ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH1) ==
|
||||
IX_FEATURE_CTRL_COMPONENT_DISABLED))
|
||||
{
|
||||
return IX_ETH_DB_FAIL;
|
||||
}
|
||||
|
||||
if ((portID == 2) &&
|
||||
(ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEA_ETH) ==
|
||||
IX_FEATURE_CTRL_COMPONENT_DISABLED))
|
||||
{
|
||||
return IX_ETH_DB_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return IX_ETH_DB_SUCCESS;
|
||||
}
|
||||
|
||||
IX_ETH_DB_PUBLIC
|
||||
BOOL ixEthDBCheckSingleBitValue(UINT32 value)
|
||||
{
|
||||
#if (CPU != SIMSPARCSOLARIS) && !defined (__wince)
|
||||
UINT32 shift;
|
||||
|
||||
/* use the count-leading-zeros XScale instruction */
|
||||
__asm__ ("clz %0, %1\n" : "=r" (shift) : "r" (value));
|
||||
|
||||
return ((value << shift) == 0x80000000UL);
|
||||
|
||||
#else
|
||||
|
||||
while (value != 0)
|
||||
{
|
||||
if (value == 1) return TRUE;
|
||||
else if ((value & 1) == 1) return FALSE;
|
||||
|
||||
value >>= 1;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *mac2string(const unsigned char *mac)
|
||||
{
|
||||
static char str[19];
|
||||
|
||||
if (mac == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
|
||||
return str;
|
||||
}
|
1179
cpu/ixp/npe/IxEthDBVlan.c
Normal file
1179
cpu/ixp/npe/IxEthDBVlan.c
Normal file
File diff suppressed because it is too large
Load Diff
480
cpu/ixp/npe/IxEthDBWiFi.c
Normal file
480
cpu/ixp/npe/IxEthDBWiFi.c
Normal file
@ -0,0 +1,480 @@
|
||||
/**
|
||||
* @file IxEthDBAPI.c
|
||||
*
|
||||
* @brief Implementation of the public API
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
#include "IxEthDB_p.h"
|
||||
|
||||
/* forward prototypes */
|
||||
IX_ETH_DB_PUBLIC
|
||||
MacTreeNode *ixEthDBGatewaySelect(MacTreeNode *stations);
|
||||
|
||||
/**
|
||||
* @brief sets the BBSID value for the WiFi header conversion feature
|
||||
*
|
||||
* @param portID ID of the port
|
||||
* @param bbsid pointer to the 6-byte BBSID value
|
||||
*
|
||||
* Note that this function is documented in the main component
|
||||
* header file, IxEthDB.h.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed successfully
|
||||
* or an appropriate error message otherwise
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBWiFiBBSIDSet(IxEthDBPortId portID, IxEthDBMacAddr *bbsid)
|
||||
{
|
||||
IxNpeMhMessage message;
|
||||
IX_STATUS result;
|
||||
|
||||
IX_ETH_DB_CHECK_PORT(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_WIFI_HEADER_CONVERSION);
|
||||
|
||||
IX_ETH_DB_CHECK_REFERENCE(bbsid);
|
||||
|
||||
memcpy(ixEthDBPortInfo[portID].bbsid, bbsid, sizeof (IxEthDBMacAddr));
|
||||
|
||||
FILL_SETBBSID_MSG(message, portID, bbsid);
|
||||
|
||||
IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief updates the Frame Control and Duration/ID WiFi header
|
||||
* conversion parameters in an NPE
|
||||
*
|
||||
* @param portID ID of the port
|
||||
*
|
||||
* This function will send a message to the NPE updating the
|
||||
* frame conversion parameters for 802.3 => 802.11 header conversion.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed successfully
|
||||
* or IX_ETH_DB_FAIL otherwise
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PRIVATE
|
||||
IxEthDBStatus ixEthDBWiFiFrameControlDurationIDUpdate(IxEthDBPortId portID)
|
||||
{
|
||||
IxNpeMhMessage message;
|
||||
IX_STATUS result;
|
||||
|
||||
FILL_SETFRAMECONTROLDURATIONID(message, portID, ixEthDBPortInfo[portID].frameControlDurationID);
|
||||
|
||||
IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sets the Duration/ID WiFi frame header conversion parameter
|
||||
*
|
||||
* @param portID ID of the port
|
||||
* @param durationID 16-bit value containing the new Duration/ID parameter
|
||||
*
|
||||
* Note that this function is documented in the main component
|
||||
* header file, IxEthDB.h.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed successfully
|
||||
* or an appropriate error message otherwise
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBWiFiDurationIDSet(IxEthDBPortId portID, UINT16 durationID)
|
||||
{
|
||||
IX_ETH_DB_CHECK_PORT(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_WIFI_HEADER_CONVERSION);
|
||||
|
||||
ixEthDBPortInfo[portID].frameControlDurationID = (ixEthDBPortInfo[portID].frameControlDurationID & 0xFFFF0000) | durationID;
|
||||
|
||||
return ixEthDBWiFiFrameControlDurationIDUpdate(portID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sets the Frame Control WiFi frame header conversion parameter
|
||||
*
|
||||
* @param portID ID of the port
|
||||
* @param durationID 16-bit value containing the new Frame Control parameter
|
||||
*
|
||||
* Note that this function is documented in the main component
|
||||
* header file, IxEthDB.h.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed successfully
|
||||
* or an appropriate error message otherwise
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBWiFiFrameControlSet(IxEthDBPortId portID, UINT16 frameControl)
|
||||
{
|
||||
IX_ETH_DB_CHECK_PORT(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_WIFI_HEADER_CONVERSION);
|
||||
|
||||
ixEthDBPortInfo[portID].frameControlDurationID = (ixEthDBPortInfo[portID].frameControlDurationID & 0xFFFF) | (frameControl << 16);
|
||||
|
||||
return ixEthDBWiFiFrameControlDurationIDUpdate(portID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief removes a WiFi header conversion record
|
||||
*
|
||||
* @param portID ID of the port
|
||||
* @param macAddr MAC address of the record to remove
|
||||
*
|
||||
* Note that this function is documented in the main
|
||||
* component header file, IxEthDB.h.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed
|
||||
* successfully or an appropriate error message otherwise
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBWiFiEntryRemove(IxEthDBPortId portID, IxEthDBMacAddr *macAddr)
|
||||
{
|
||||
MacDescriptor recordTemplate;
|
||||
|
||||
IX_ETH_DB_CHECK_PORT(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_REFERENCE(macAddr);
|
||||
|
||||
IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_WIFI_HEADER_CONVERSION);
|
||||
|
||||
memcpy(recordTemplate.macAddress, macAddr, sizeof (IxEthDBMacAddr));
|
||||
|
||||
recordTemplate.type = IX_ETH_DB_WIFI_RECORD;
|
||||
recordTemplate.portID = portID;
|
||||
|
||||
return ixEthDBRemove(&recordTemplate, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief adds a WiFi header conversion record
|
||||
*
|
||||
* @param portID ID of the port
|
||||
* @param macAddr MAC address of the record to add
|
||||
* @param gatewayMacAddr address of the gateway (or
|
||||
* NULL if this is a station record)
|
||||
*
|
||||
* This function adds a record of type AP_TO_AP (gateway is not NULL)
|
||||
* or AP_TO_STA (gateway is NULL) in the main database as a
|
||||
* WiFi header conversion record.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed
|
||||
* successfully or an appropriate error message otherwise
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PRIVATE
|
||||
IxEthDBStatus ixEthDBWiFiEntryAdd(IxEthDBPortId portID, IxEthDBMacAddr *macAddr, IxEthDBMacAddr *gatewayMacAddr)
|
||||
{
|
||||
MacDescriptor recordTemplate;
|
||||
|
||||
IX_ETH_DB_CHECK_PORT(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_REFERENCE(macAddr);
|
||||
|
||||
IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_WIFI_HEADER_CONVERSION);
|
||||
|
||||
memcpy(recordTemplate.macAddress, macAddr, sizeof (IxEthDBMacAddr));
|
||||
|
||||
recordTemplate.type = IX_ETH_DB_WIFI_RECORD;
|
||||
recordTemplate.portID = portID;
|
||||
|
||||
if (gatewayMacAddr != NULL)
|
||||
{
|
||||
memcpy(recordTemplate.recordData.wifiData.gwMacAddress, gatewayMacAddr, sizeof (IxEthDBMacAddr));
|
||||
|
||||
recordTemplate.recordData.wifiData.type = IX_ETH_DB_WIFI_AP_TO_AP;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(recordTemplate.recordData.wifiData.gwMacAddress, 0, sizeof (IxEthDBMacAddr));
|
||||
|
||||
recordTemplate.recordData.wifiData.type = IX_ETH_DB_WIFI_AP_TO_STA;
|
||||
}
|
||||
|
||||
return ixEthDBAdd(&recordTemplate, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief adds a WiFi header conversion record
|
||||
*
|
||||
* @param portID ID of the port
|
||||
* @param macAddr MAC address of the record to add
|
||||
* @param gatewayMacAddr address of the gateway
|
||||
*
|
||||
* This function adds a record of type AP_TO_AP
|
||||
* in the main database as a WiFi header conversion record.
|
||||
*
|
||||
* This is simply a wrapper over @ref ixEthDBWiFiEntryAdd().
|
||||
*
|
||||
* Note that this function is documented in the main
|
||||
* component header file, IxEthDB.h.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed
|
||||
* successfully or an appropriate error message otherwise
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBWiFiAccessPointEntryAdd(IxEthDBPortId portID, IxEthDBMacAddr *macAddr, IxEthDBMacAddr *gatewayMacAddr)
|
||||
{
|
||||
IX_ETH_DB_CHECK_REFERENCE(gatewayMacAddr);
|
||||
|
||||
return ixEthDBWiFiEntryAdd(portID, macAddr, gatewayMacAddr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief adds a WiFi header conversion record
|
||||
*
|
||||
* @param portID ID of the port
|
||||
* @param macAddr MAC address of the record to add
|
||||
*
|
||||
* This function adds a record of type AP_TO_STA
|
||||
* in the main database as a WiFi header conversion record.
|
||||
*
|
||||
* This is simply a wrapper over @ref ixEthDBWiFiEntryAdd().
|
||||
*
|
||||
* Note that this function is documented in the main
|
||||
* component header file, IxEthDB.h.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed
|
||||
* successfully or an appropriate error message otherwise
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBWiFiStationEntryAdd(IxEthDBPortId portID, IxEthDBMacAddr *macAddr)
|
||||
{
|
||||
return ixEthDBWiFiEntryAdd(portID, macAddr, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief selects a set of gateways from a tree of
|
||||
* WiFi header conversion records
|
||||
*
|
||||
* @param stations binary tree containing pointers to WiFi header
|
||||
* conversion records
|
||||
*
|
||||
* This function browses through the input binary tree, identifies
|
||||
* records of type AP_TO_AP, clones these records and appends them
|
||||
* to a vine (a single right-branch binary tree) which is returned
|
||||
* as result. A maximum of MAX_GW_SIZE entries containing gateways
|
||||
* will be cloned from the original tree.
|
||||
*
|
||||
* @return vine (linear binary tree) containing record
|
||||
* clones of AP_TO_AP type, which have a gateway field
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
MacTreeNode *ixEthDBGatewaySelect(MacTreeNode *stations)
|
||||
{
|
||||
MacTreeNodeStack *stack;
|
||||
MacTreeNode *gateways, *insertionPlace;
|
||||
UINT32 gwIndex = 1; /* skip the empty root */
|
||||
|
||||
if (stations == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stack = ixOsalCacheDmaMalloc(sizeof (MacTreeNodeStack));
|
||||
|
||||
if (stack == NULL)
|
||||
{
|
||||
ERROR_LOG("DB: (WiFi) failed to allocate the node stack for gateway tree linearization, out of memory?\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* initialize root node */
|
||||
gateways = insertionPlace = NULL;
|
||||
|
||||
/* start browsing the station tree */
|
||||
NODE_STACK_INIT(stack);
|
||||
|
||||
/* initialize stack by pushing the tree root at offset 0 */
|
||||
NODE_STACK_PUSH(stack, stations, 0);
|
||||
|
||||
while (NODE_STACK_NONEMPTY(stack))
|
||||
{
|
||||
MacTreeNode *node;
|
||||
UINT32 offset;
|
||||
|
||||
NODE_STACK_POP(stack, node, offset);
|
||||
|
||||
/* we can store maximum 31 (32 total, 1 empty root) entries in the gateway tree */
|
||||
if (offset > (MAX_GW_SIZE - 1)) break;
|
||||
|
||||
/* check if this record has a gateway address */
|
||||
if (node->descriptor != NULL && node->descriptor->recordData.wifiData.type == IX_ETH_DB_WIFI_AP_TO_AP)
|
||||
{
|
||||
/* found a record, create an insertion place */
|
||||
if (insertionPlace != NULL)
|
||||
{
|
||||
insertionPlace->right = ixEthDBAllocMacTreeNode();
|
||||
insertionPlace = insertionPlace->right;
|
||||
}
|
||||
else
|
||||
{
|
||||
gateways = ixEthDBAllocMacTreeNode();
|
||||
insertionPlace = gateways;
|
||||
}
|
||||
|
||||
if (insertionPlace == NULL)
|
||||
{
|
||||
/* no nodes left, bail out with what we have */
|
||||
ixOsalCacheDmaFree(stack);
|
||||
return gateways;
|
||||
}
|
||||
|
||||
/* clone the original record for the gateway tree */
|
||||
insertionPlace->descriptor = ixEthDBCloneMacDescriptor(node->descriptor);
|
||||
|
||||
/* insert and update the offset in the original record */
|
||||
node->descriptor->recordData.wifiData.gwAddressIndex = gwIndex++;
|
||||
}
|
||||
|
||||
/* browse the tree */
|
||||
if (node->left != NULL)
|
||||
{
|
||||
NODE_STACK_PUSH(stack, node->left, LEFT_CHILD_OFFSET(offset));
|
||||
}
|
||||
|
||||
if (node->right != NULL)
|
||||
{
|
||||
NODE_STACK_PUSH(stack, node->right, RIGHT_CHILD_OFFSET(offset));
|
||||
}
|
||||
}
|
||||
|
||||
ixOsalCacheDmaFree(stack);
|
||||
return gateways;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief downloads the WiFi header conversion table to an NPE
|
||||
*
|
||||
* @param portID ID of the port
|
||||
*
|
||||
* This function prepares the WiFi header conversion tables and
|
||||
* downloads them to the specified NPE port.
|
||||
*
|
||||
* The header conversion tables consist in the main table of
|
||||
* addresses and the secondary table of gateways. AP_TO_AP records
|
||||
* from the first table contain index fields into the second table
|
||||
* for gateway selection.
|
||||
*
|
||||
* Note that this function is documented in the main component
|
||||
* header file, IxEthDB.h.
|
||||
*
|
||||
* @return IX_ETH_DB_SUCCESS if the operation completed successfully
|
||||
* or an appropriate error message otherwise
|
||||
*/
|
||||
IX_ETH_DB_PUBLIC
|
||||
IxEthDBStatus ixEthDBWiFiConversionTableDownload(IxEthDBPortId portID)
|
||||
{
|
||||
IxEthDBPortMap query;
|
||||
MacTreeNode *stations = NULL, *gateways = NULL, *gateway = NULL;
|
||||
IxNpeMhMessage message;
|
||||
PortInfo *portInfo;
|
||||
IX_STATUS result;
|
||||
|
||||
IX_ETH_DB_CHECK_PORT(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_SINGLE_NPE(portID);
|
||||
|
||||
IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_WIFI_HEADER_CONVERSION);
|
||||
|
||||
portInfo = &ixEthDBPortInfo[portID];
|
||||
|
||||
SET_DEPENDENCY_MAP(query, portID);
|
||||
|
||||
ixEthDBUpdateLock();
|
||||
|
||||
stations = ixEthDBQuery(NULL, query, IX_ETH_DB_WIFI_RECORD, MAX_ELT_SIZE);
|
||||
gateways = ixEthDBGatewaySelect(stations);
|
||||
|
||||
/* clean up gw area */
|
||||
memset((void *) portInfo->updateMethod.npeGwUpdateZone, FULL_GW_BYTE_SIZE, 0);
|
||||
|
||||
/* write all gateways */
|
||||
gateway = gateways;
|
||||
|
||||
while (gateway != NULL)
|
||||
{
|
||||
ixEthDBNPEGatewayNodeWrite((void *) (((UINT32) portInfo->updateMethod.npeGwUpdateZone)
|
||||
+ gateway->descriptor->recordData.wifiData.gwAddressIndex * ELT_ENTRY_SIZE),
|
||||
gateway);
|
||||
|
||||
gateway = gateway->right;
|
||||
}
|
||||
|
||||
/* free the gateway tree */
|
||||
if (gateways != NULL)
|
||||
{
|
||||
ixEthDBFreeMacTreeNode(gateways);
|
||||
}
|
||||
|
||||
FILL_SETAPMACTABLE_MSG(message,
|
||||
IX_OSAL_MMU_VIRT_TO_PHYS(portInfo->updateMethod.npeGwUpdateZone));
|
||||
|
||||
IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result);
|
||||
|
||||
if (result == IX_SUCCESS)
|
||||
{
|
||||
/* update the main tree (the stations tree) */
|
||||
portInfo->updateMethod.searchTree = stations;
|
||||
|
||||
result = ixEthDBNPEUpdateHandler(portID, IX_ETH_DB_WIFI_RECORD);
|
||||
}
|
||||
|
||||
ixEthDBUpdateUnlock();
|
||||
|
||||
return result;
|
||||
}
|
497
cpu/ixp/npe/IxEthMii.c
Normal file
497
cpu/ixp/npe/IxEthMii.c
Normal file
@ -0,0 +1,497 @@
|
||||
/**
|
||||
* @file IxEthMii.c
|
||||
*
|
||||
* @author Intel Corporation
|
||||
* @date
|
||||
*
|
||||
* @brief MII control functions
|
||||
*
|
||||
* Design Notes:
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
#include "IxOsal.h"
|
||||
|
||||
#include "IxEthAcc.h"
|
||||
#include "IxEthMii_p.h"
|
||||
|
||||
#ifdef __wince
|
||||
#include "IxOsPrintf.h"
|
||||
#endif
|
||||
|
||||
/* Array to store the phy IDs of the discovered phys */
|
||||
PRIVATE UINT32 ixEthMiiPhyId[IXP425_ETH_ACC_MII_MAX_ADDR];
|
||||
|
||||
/*********************************************************
|
||||
*
|
||||
* Scan for PHYs on the MII bus. This function returns
|
||||
* an array of booleans, one for each PHY address.
|
||||
* If a PHY is found at a particular address, the
|
||||
* corresponding entry in the array is set to TRUE.
|
||||
*
|
||||
*/
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixEthMiiPhyScan(BOOL phyPresent[], UINT32 maxPhyCount)
|
||||
{
|
||||
UINT32 i;
|
||||
UINT16 regval, regvalId1, regvalId2;
|
||||
|
||||
/*Search for PHYs on the MII*/
|
||||
/*Search for existant phys on the MDIO bus*/
|
||||
|
||||
if ((phyPresent == NULL) ||
|
||||
(maxPhyCount > IXP425_ETH_ACC_MII_MAX_ADDR))
|
||||
{
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* fill the array */
|
||||
for(i=0;
|
||||
i<IXP425_ETH_ACC_MII_MAX_ADDR;
|
||||
i++)
|
||||
{
|
||||
phyPresent[i] = FALSE;
|
||||
}
|
||||
|
||||
/* iterate through the PHY addresses */
|
||||
for(i=0;
|
||||
maxPhyCount > 0 && i<IXP425_ETH_ACC_MII_MAX_ADDR;
|
||||
i++)
|
||||
{
|
||||
ixEthMiiPhyId[i] = IX_ETH_MII_INVALID_PHY_ID;
|
||||
if(ixEthAccMiiReadRtn(i,
|
||||
IX_ETH_MII_CTRL_REG,
|
||||
®val) == IX_ETH_ACC_SUCCESS)
|
||||
{
|
||||
if((regval & 0xffff) != 0xffff)
|
||||
{
|
||||
maxPhyCount--;
|
||||
/*Need to read the register twice here to flush PHY*/
|
||||
ixEthAccMiiReadRtn(i, IX_ETH_MII_PHY_ID1_REG, ®valId1);
|
||||
ixEthAccMiiReadRtn(i, IX_ETH_MII_PHY_ID1_REG, ®valId1);
|
||||
ixEthAccMiiReadRtn(i, IX_ETH_MII_PHY_ID2_REG, ®valId2);
|
||||
ixEthMiiPhyId[i] = (regvalId1 << IX_ETH_MII_REG_SHL) | regvalId2;
|
||||
if ((ixEthMiiPhyId[i] == IX_ETH_MII_KS8995_PHY_ID)
|
||||
|| (ixEthMiiPhyId[i] == IX_ETH_MII_LXT971_PHY_ID)
|
||||
|| (ixEthMiiPhyId[i] == IX_ETH_MII_LXT972_PHY_ID)
|
||||
|| (ixEthMiiPhyId[i] == IX_ETH_MII_LXT973_PHY_ID)
|
||||
|| (ixEthMiiPhyId[i] == IX_ETH_MII_LXT973A3_PHY_ID)
|
||||
|| (ixEthMiiPhyId[i] == IX_ETH_MII_LXT9785_PHY_ID)
|
||||
)
|
||||
{
|
||||
/* supported phy */
|
||||
phyPresent[i] = TRUE;
|
||||
} /* end of if(ixEthMiiPhyId) */
|
||||
else
|
||||
{
|
||||
if (ixEthMiiPhyId[i] != IX_ETH_MII_INVALID_PHY_ID)
|
||||
{
|
||||
/* unsupported phy */
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"ixEthMiiPhyScan : unexpected Mii PHY ID %8.8x\n",
|
||||
ixEthMiiPhyId[i], 2, 3, 4, 5, 6);
|
||||
ixEthMiiPhyId[i] = IX_ETH_MII_UNKNOWN_PHY_ID;
|
||||
phyPresent[i] = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
*
|
||||
* Configure the PHY at the specified address
|
||||
*
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixEthMiiPhyConfig(UINT32 phyAddr,
|
||||
BOOL speed100,
|
||||
BOOL fullDuplex,
|
||||
BOOL autonegotiate)
|
||||
{
|
||||
UINT16 regval=0;
|
||||
|
||||
/* parameter check */
|
||||
if ((phyAddr < IXP425_ETH_ACC_MII_MAX_ADDR) &&
|
||||
(ixEthMiiPhyId[phyAddr] != IX_ETH_MII_INVALID_PHY_ID))
|
||||
{
|
||||
/*
|
||||
* set the control register
|
||||
*/
|
||||
if(autonegotiate)
|
||||
{
|
||||
regval |= IX_ETH_MII_CR_AUTO_EN | IX_ETH_MII_CR_RESTART;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(speed100)
|
||||
{
|
||||
regval |= IX_ETH_MII_CR_100;
|
||||
}
|
||||
if(fullDuplex)
|
||||
{
|
||||
regval |= IX_ETH_MII_CR_FDX;
|
||||
}
|
||||
} /* end of if-else() */
|
||||
if (ixEthAccMiiWriteRtn(phyAddr,
|
||||
IX_ETH_MII_CTRL_REG,
|
||||
regval) == IX_ETH_ACC_SUCCESS)
|
||||
{
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
} /* end of if(phyAddr) */
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
*
|
||||
* Enable the PHY Loopback at the specified address
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixEthMiiPhyLoopbackEnable (UINT32 phyAddr)
|
||||
{
|
||||
UINT16 regval ;
|
||||
|
||||
if ((phyAddr < IXP425_ETH_ACC_MII_MAX_ADDR) &&
|
||||
(IX_ETH_MII_INVALID_PHY_ID != ixEthMiiPhyId[phyAddr]))
|
||||
{
|
||||
/* read/write the control register */
|
||||
if(ixEthAccMiiReadRtn (phyAddr,
|
||||
IX_ETH_MII_CTRL_REG,
|
||||
®val)
|
||||
== IX_ETH_ACC_SUCCESS)
|
||||
{
|
||||
if(ixEthAccMiiWriteRtn (phyAddr,
|
||||
IX_ETH_MII_CTRL_REG,
|
||||
regval | IX_ETH_MII_CR_LOOPBACK)
|
||||
== IX_ETH_ACC_SUCCESS)
|
||||
{
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
*
|
||||
* Disable the PHY Loopback at the specified address
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixEthMiiPhyLoopbackDisable (UINT32 phyAddr)
|
||||
{
|
||||
UINT16 regval ;
|
||||
|
||||
if ((phyAddr < IXP425_ETH_ACC_MII_MAX_ADDR) &&
|
||||
(IX_ETH_MII_INVALID_PHY_ID != ixEthMiiPhyId[phyAddr]))
|
||||
{
|
||||
/* read/write the control register */
|
||||
if(ixEthAccMiiReadRtn (phyAddr,
|
||||
IX_ETH_MII_CTRL_REG,
|
||||
®val)
|
||||
== IX_ETH_ACC_SUCCESS)
|
||||
{
|
||||
if(ixEthAccMiiWriteRtn (phyAddr,
|
||||
IX_ETH_MII_CTRL_REG,
|
||||
regval & (~IX_ETH_MII_CR_LOOPBACK))
|
||||
== IX_ETH_ACC_SUCCESS)
|
||||
{
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
*
|
||||
* Reset the PHY at the specified address
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixEthMiiPhyReset(UINT32 phyAddr)
|
||||
{
|
||||
UINT32 timeout;
|
||||
UINT16 regval;
|
||||
|
||||
if ((phyAddr < IXP425_ETH_ACC_MII_MAX_ADDR) &&
|
||||
(ixEthMiiPhyId[phyAddr] != IX_ETH_MII_INVALID_PHY_ID))
|
||||
{
|
||||
if ((ixEthMiiPhyId[phyAddr] == IX_ETH_MII_LXT971_PHY_ID) ||
|
||||
(ixEthMiiPhyId[phyAddr] == IX_ETH_MII_LXT972_PHY_ID) ||
|
||||
(ixEthMiiPhyId[phyAddr] == IX_ETH_MII_LXT973_PHY_ID) ||
|
||||
(ixEthMiiPhyId[phyAddr] == IX_ETH_MII_LXT973A3_PHY_ID) ||
|
||||
(ixEthMiiPhyId[phyAddr] == IX_ETH_MII_LXT9785_PHY_ID)
|
||||
)
|
||||
{
|
||||
/* use the control register to reset the phy */
|
||||
ixEthAccMiiWriteRtn(phyAddr,
|
||||
IX_ETH_MII_CTRL_REG,
|
||||
IX_ETH_MII_CR_RESET);
|
||||
|
||||
/* poll until the reset bit is cleared */
|
||||
timeout = 0;
|
||||
do
|
||||
{
|
||||
ixOsalSleep (IX_ETH_MII_RESET_POLL_MS);
|
||||
|
||||
/* read the control register and check for timeout */
|
||||
ixEthAccMiiReadRtn(phyAddr,
|
||||
IX_ETH_MII_CTRL_REG,
|
||||
®val);
|
||||
if ((regval & IX_ETH_MII_CR_RESET) == 0)
|
||||
{
|
||||
/* timeout bit is self-cleared */
|
||||
break;
|
||||
}
|
||||
timeout += IX_ETH_MII_RESET_POLL_MS;
|
||||
}
|
||||
while (timeout < IX_ETH_MII_RESET_DELAY_MS);
|
||||
|
||||
/* check for timeout */
|
||||
if (timeout >= IX_ETH_MII_RESET_DELAY_MS)
|
||||
{
|
||||
ixEthAccMiiWriteRtn(phyAddr, IX_ETH_MII_CTRL_REG,
|
||||
IX_ETH_MII_CR_NORM_EN);
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
return IX_SUCCESS;
|
||||
} /* end of if(ixEthMiiPhyId) */
|
||||
else if (ixEthMiiPhyId[phyAddr] == IX_ETH_MII_KS8995_PHY_ID)
|
||||
{
|
||||
/* reset bit is reserved, just reset the control register */
|
||||
ixEthAccMiiWriteRtn(phyAddr, IX_ETH_MII_CTRL_REG,
|
||||
IX_ETH_MII_CR_NORM_EN);
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* unknown PHY, set the control register reset bit,
|
||||
* wait 2 s. and clear the control register.
|
||||
*/
|
||||
ixEthAccMiiWriteRtn(phyAddr, IX_ETH_MII_CTRL_REG,
|
||||
IX_ETH_MII_CR_RESET);
|
||||
|
||||
ixOsalSleep (IX_ETH_MII_RESET_DELAY_MS);
|
||||
|
||||
ixEthAccMiiWriteRtn(phyAddr, IX_ETH_MII_CTRL_REG,
|
||||
IX_ETH_MII_CR_NORM_EN);
|
||||
return IX_SUCCESS;
|
||||
} /* end of if-else(ixEthMiiPhyId) */
|
||||
} /* end of if(phyAddr) */
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
*
|
||||
* Link state query functions
|
||||
*/
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixEthMiiLinkStatus(UINT32 phyAddr,
|
||||
BOOL *linkUp,
|
||||
BOOL *speed100,
|
||||
BOOL *fullDuplex,
|
||||
BOOL *autoneg)
|
||||
{
|
||||
UINT16 ctrlRegval, statRegval, regval, regval4, regval5;
|
||||
|
||||
/* check the parameters */
|
||||
if ((linkUp == NULL) ||
|
||||
(speed100 == NULL) ||
|
||||
(fullDuplex == NULL) ||
|
||||
(autoneg == NULL))
|
||||
{
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
*linkUp = FALSE;
|
||||
*speed100 = FALSE;
|
||||
*fullDuplex = FALSE;
|
||||
*autoneg = FALSE;
|
||||
|
||||
if ((phyAddr < IXP425_ETH_ACC_MII_MAX_ADDR) &&
|
||||
(ixEthMiiPhyId[phyAddr] != IX_ETH_MII_INVALID_PHY_ID))
|
||||
{
|
||||
if ((ixEthMiiPhyId[phyAddr] == IX_ETH_MII_LXT971_PHY_ID) ||
|
||||
(ixEthMiiPhyId[phyAddr] == IX_ETH_MII_LXT972_PHY_ID) ||
|
||||
(ixEthMiiPhyId[phyAddr] == IX_ETH_MII_LXT9785_PHY_ID)
|
||||
)
|
||||
{
|
||||
/* --------------------------------------------------*/
|
||||
/* Retrieve information from PHY specific register */
|
||||
/* --------------------------------------------------*/
|
||||
if (ixEthAccMiiReadRtn(phyAddr,
|
||||
IX_ETH_MII_STAT2_REG,
|
||||
®val) != IX_ETH_ACC_SUCCESS)
|
||||
{
|
||||
return IX_FAIL;
|
||||
}
|
||||
*linkUp = ((regval & IX_ETH_MII_SR2_LINK) != 0);
|
||||
*speed100 = ((regval & IX_ETH_MII_SR2_100) != 0);
|
||||
*fullDuplex = ((regval & IX_ETH_MII_SR2_FD) != 0);
|
||||
*autoneg = ((regval & IX_ETH_MII_SR2_AUTO) != 0);
|
||||
return IX_SUCCESS;
|
||||
} /* end of if(ixEthMiiPhyId) */
|
||||
else
|
||||
{
|
||||
/* ----------------------------------------------------*/
|
||||
/* Retrieve information from status and ctrl registers */
|
||||
/* ----------------------------------------------------*/
|
||||
if (ixEthAccMiiReadRtn(phyAddr,
|
||||
IX_ETH_MII_CTRL_REG,
|
||||
&ctrlRegval) != IX_ETH_ACC_SUCCESS)
|
||||
{
|
||||
return IX_FAIL;
|
||||
}
|
||||
ixEthAccMiiReadRtn(phyAddr, IX_ETH_MII_STAT_REG, &statRegval);
|
||||
|
||||
*linkUp = ((statRegval & IX_ETH_MII_SR_LINK_STATUS) != 0);
|
||||
if (*linkUp)
|
||||
{
|
||||
*autoneg = ((ctrlRegval & IX_ETH_MII_CR_AUTO_EN) != 0) &&
|
||||
((statRegval & IX_ETH_MII_SR_AUTO_SEL) != 0) &&
|
||||
((statRegval & IX_ETH_MII_SR_AUTO_NEG) != 0);
|
||||
|
||||
if (*autoneg)
|
||||
{
|
||||
/* mask the current stat values with the capabilities */
|
||||
ixEthAccMiiReadRtn(phyAddr, IX_ETH_MII_AN_ADS_REG, ®val4);
|
||||
ixEthAccMiiReadRtn(phyAddr, IX_ETH_MII_AN_PRTN_REG, ®val5);
|
||||
/* merge the flags from the 3 registers */
|
||||
regval = (statRegval & ((regval4 & regval5) << 6));
|
||||
/* initialise from status register values */
|
||||
if ((regval & IX_ETH_MII_SR_TX_FULL_DPX) != 0)
|
||||
{
|
||||
/* 100 Base X full dplx */
|
||||
*speed100 = TRUE;
|
||||
*fullDuplex = TRUE;
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
if ((regval & IX_ETH_MII_SR_TX_HALF_DPX) != 0)
|
||||
{
|
||||
/* 100 Base X half dplx */
|
||||
*speed100 = TRUE;
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
if ((regval & IX_ETH_MII_SR_10T_FULL_DPX) != 0)
|
||||
{
|
||||
/* 10 mb full dplx */
|
||||
*fullDuplex = TRUE;
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
if ((regval & IX_ETH_MII_SR_10T_HALF_DPX) != 0)
|
||||
{
|
||||
/* 10 mb half dplx */
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
} /* end of if(autoneg) */
|
||||
else
|
||||
{
|
||||
/* autonegotiate not complete, return setup parameters */
|
||||
*speed100 = ((ctrlRegval & IX_ETH_MII_CR_100) != 0);
|
||||
*fullDuplex = ((ctrlRegval & IX_ETH_MII_CR_FDX) != 0);
|
||||
}
|
||||
} /* end of if(linkUp) */
|
||||
} /* end of if-else(ixEthMiiPhyId) */
|
||||
} /* end of if(phyAddr) */
|
||||
else
|
||||
{
|
||||
return IX_FAIL;
|
||||
} /* end of if-else(phyAddr) */
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
*
|
||||
* Link state display functions
|
||||
*/
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixEthMiiPhyShow (UINT32 phyAddr)
|
||||
{
|
||||
BOOL linkUp, speed100, fullDuplex, autoneg;
|
||||
UINT16 cregval;
|
||||
UINT16 sregval;
|
||||
|
||||
|
||||
ixEthAccMiiReadRtn(phyAddr, IX_ETH_MII_STAT_REG, &sregval);
|
||||
ixEthAccMiiReadRtn(phyAddr, IX_ETH_MII_CTRL_REG, &cregval);
|
||||
|
||||
/* get link information */
|
||||
if (ixEthMiiLinkStatus(phyAddr,
|
||||
&linkUp,
|
||||
&speed100,
|
||||
&fullDuplex,
|
||||
&autoneg) != IX_ETH_ACC_SUCCESS)
|
||||
{
|
||||
printf("PHY Status unknown\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
printf("PHY ID [phyAddr]: %8.8x\n",ixEthMiiPhyId[phyAddr]);
|
||||
printf( " Status reg: %4.4x\n",sregval);
|
||||
printf( " control reg: %4.4x\n",cregval);
|
||||
/* display link information */
|
||||
printf("PHY Status:\n");
|
||||
printf(" Link is %s\n",
|
||||
(linkUp ? "Up" : "Down"));
|
||||
if((sregval & IX_ETH_MII_SR_REMOTE_FAULT) != 0)
|
||||
{
|
||||
printf(" Remote fault detected\n");
|
||||
}
|
||||
printf(" Auto Negotiation %s\n",
|
||||
(autoneg ? "Completed" : "Not Completed"));
|
||||
|
||||
printf("PHY Configuration:\n");
|
||||
printf(" Speed %sMb/s\n",
|
||||
(speed100 ? "100" : "10"));
|
||||
printf(" %s Duplex\n",
|
||||
(fullDuplex ? "Full" : "Half"));
|
||||
printf(" Auto Negotiation %s\n",
|
||||
(autoneg ? "Enabled" : "Disabled"));
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
422
cpu/ixp/npe/IxFeatureCtrl.c
Normal file
422
cpu/ixp/npe/IxFeatureCtrl.c
Normal file
@ -0,0 +1,422 @@
|
||||
/**
|
||||
* @file IxFeatureCtrl.c
|
||||
*
|
||||
* @author Intel Corporation
|
||||
* @date 29-Jan-2003
|
||||
*
|
||||
* @brief Feature Control Public API Implementation
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
#include "IxOsal.h"
|
||||
#include "IxVersionId.h"
|
||||
#include "IxFeatureCtrl.h"
|
||||
|
||||
/* Macro to read from the Feature Control Register */
|
||||
#define IX_FEATURE_CTRL_READ(result) \
|
||||
do { \
|
||||
ixFeatureCtrlExpMap(); \
|
||||
(result) = IX_OSAL_READ_LONG(ixFeatureCtrlRegister); \
|
||||
} while (0)
|
||||
|
||||
/* Macro to write to the Feature Control Register */
|
||||
#define IX_FEATURE_CTRL_WRITE(value) \
|
||||
do { \
|
||||
ixFeatureCtrlExpMap(); \
|
||||
IX_OSAL_WRITE_LONG(ixFeatureCtrlRegister, (value)); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* This is the offset of the feature register relative to the base of the
|
||||
* Expansion Bus Controller MMR.
|
||||
*/
|
||||
#define IX_FEATURE_CTRL_REG_OFFSET (0x00000028)
|
||||
|
||||
|
||||
/* Boolean to mark the fact that the EXP_CONFIG address space was mapped */
|
||||
PRIVATE BOOL ixFeatureCtrlExpCfgRegionMapped = FALSE;
|
||||
|
||||
/* Pointer holding the virtual address of the Feature Control Register */
|
||||
PRIVATE VUINT32 *ixFeatureCtrlRegister = NULL;
|
||||
|
||||
/* Place holder to store the software configuration */
|
||||
PRIVATE BOOL swConfiguration[IX_FEATURECTRL_SWCONFIG_MAX];
|
||||
|
||||
/* Flag to control swConfiguration[] is initialized once */
|
||||
PRIVATE BOOL swConfigurationFlag = FALSE ;
|
||||
|
||||
/* Array containing component mask values */
|
||||
#ifdef __ixp42X
|
||||
UINT32 componentMask[IX_FEATURECTRL_MAX_COMPONENTS] = {
|
||||
(0x1<<IX_FEATURECTRL_RCOMP),
|
||||
(0x1<<IX_FEATURECTRL_USB),
|
||||
(0x1<<IX_FEATURECTRL_HASH),
|
||||
(0x1<<IX_FEATURECTRL_AES),
|
||||
(0x1<<IX_FEATURECTRL_DES),
|
||||
(0x1<<IX_FEATURECTRL_HDLC),
|
||||
(0x1<<IX_FEATURECTRL_AAL),
|
||||
(0x1<<IX_FEATURECTRL_HSS),
|
||||
(0x1<<IX_FEATURECTRL_UTOPIA),
|
||||
(0x1<<IX_FEATURECTRL_ETH0),
|
||||
(0x1<<IX_FEATURECTRL_ETH1),
|
||||
(0x1<<IX_FEATURECTRL_NPEA),
|
||||
(0x1<<IX_FEATURECTRL_NPEB),
|
||||
(0x1<<IX_FEATURECTRL_NPEC),
|
||||
(0x1<<IX_FEATURECTRL_PCI),
|
||||
IX_FEATURECTRL_COMPONENT_NOT_AVAILABLE,
|
||||
(0x3<<IX_FEATURECTRL_UTOPIA_PHY_LIMIT),
|
||||
(0x1<<IX_FEATURECTRL_UTOPIA_PHY_LIMIT_BIT2),
|
||||
IX_FEATURECTRL_COMPONENT_NOT_AVAILABLE,
|
||||
IX_FEATURECTRL_COMPONENT_NOT_AVAILABLE,
|
||||
IX_FEATURECTRL_COMPONENT_NOT_AVAILABLE,
|
||||
IX_FEATURECTRL_COMPONENT_NOT_AVAILABLE,
|
||||
IX_FEATURECTRL_COMPONENT_NOT_AVAILABLE
|
||||
};
|
||||
#elif defined (__ixp46X)
|
||||
UINT32 componentMask[IX_FEATURECTRL_MAX_COMPONENTS] = {
|
||||
(0x1<<IX_FEATURECTRL_RCOMP),
|
||||
(0x1<<IX_FEATURECTRL_USB),
|
||||
(0x1<<IX_FEATURECTRL_HASH),
|
||||
(0x1<<IX_FEATURECTRL_AES),
|
||||
(0x1<<IX_FEATURECTRL_DES),
|
||||
(0x1<<IX_FEATURECTRL_HDLC),
|
||||
IX_FEATURECTRL_COMPONENT_ALWAYS_AVAILABLE, /* AAL component is always on */
|
||||
(0x1<<IX_FEATURECTRL_HSS),
|
||||
(0x1<<IX_FEATURECTRL_UTOPIA),
|
||||
(0x1<<IX_FEATURECTRL_ETH0),
|
||||
(0x1<<IX_FEATURECTRL_ETH1),
|
||||
(0x1<<IX_FEATURECTRL_NPEA),
|
||||
(0x1<<IX_FEATURECTRL_NPEB),
|
||||
(0x1<<IX_FEATURECTRL_NPEC),
|
||||
(0x1<<IX_FEATURECTRL_PCI),
|
||||
(0x1<<IX_FEATURECTRL_ECC_TIMESYNC),
|
||||
(0x3<<IX_FEATURECTRL_UTOPIA_PHY_LIMIT),
|
||||
(0x1<<IX_FEATURECTRL_UTOPIA_PHY_LIMIT_BIT2), /* NOT TO BE USED */
|
||||
(0x1<<IX_FEATURECTRL_USB_HOST_CONTROLLER),
|
||||
(0x1<<IX_FEATURECTRL_NPEA_ETH),
|
||||
(0x1<<IX_FEATURECTRL_NPEB_ETH),
|
||||
(0x1<<IX_FEATURECTRL_RSA),
|
||||
(0x3<<IX_FEATURECTRL_XSCALE_MAX_FREQ),
|
||||
(0x1<<IX_FEATURECTRL_XSCALE_MAX_FREQ_BIT2)
|
||||
};
|
||||
#endif /* __ixp42X */
|
||||
|
||||
/**
|
||||
* Forward declaration
|
||||
*/
|
||||
PRIVATE
|
||||
void ixFeatureCtrlExpMap(void);
|
||||
|
||||
PRIVATE
|
||||
void ixFeatureCtrlSwConfigurationInit(void);
|
||||
|
||||
/**
|
||||
* Function to map EXP_CONFIG space
|
||||
*/
|
||||
PRIVATE
|
||||
void ixFeatureCtrlExpMap(void)
|
||||
{
|
||||
UINT32 expCfgBaseAddress = 0;
|
||||
|
||||
/* If the EXP Configuration space has already been mapped then
|
||||
* return */
|
||||
if (ixFeatureCtrlExpCfgRegionMapped == TRUE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Map (get virtual address) for the EXP_CONFIG space */
|
||||
expCfgBaseAddress = (UINT32)
|
||||
(IX_OSAL_MEM_MAP(IX_OSAL_IXP400_EXP_BUS_REGS_PHYS_BASE,
|
||||
IX_OSAL_IXP400_EXP_REG_MAP_SIZE));
|
||||
|
||||
/* Assert that the mapping operation succeeded */
|
||||
IX_OSAL_ASSERT(expCfgBaseAddress);
|
||||
|
||||
/* Set the address of the Feature register */
|
||||
ixFeatureCtrlRegister =
|
||||
(VUINT32 *) (expCfgBaseAddress + IX_FEATURE_CTRL_REG_OFFSET);
|
||||
|
||||
/* Mark the fact that the EXP_CONFIG space has already been mapped */
|
||||
ixFeatureCtrlExpCfgRegionMapped = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function definition: ixFeatureCtrlSwConfigurationInit
|
||||
* This function will only initialize software configuration once.
|
||||
*/
|
||||
PRIVATE void ixFeatureCtrlSwConfigurationInit(void)
|
||||
{
|
||||
UINT32 i;
|
||||
if (FALSE == swConfigurationFlag)
|
||||
{
|
||||
for (i=0; i<IX_FEATURECTRL_SWCONFIG_MAX ; i++)
|
||||
{
|
||||
/* By default, all software configuration are enabled */
|
||||
swConfiguration[i]= TRUE ;
|
||||
}
|
||||
/*Make sure this function only initializes swConfiguration[] once*/
|
||||
swConfigurationFlag = TRUE ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function definition: ixFeatureCtrlRead
|
||||
*/
|
||||
IxFeatureCtrlReg
|
||||
ixFeatureCtrlRead (void)
|
||||
{
|
||||
IxFeatureCtrlReg result;
|
||||
|
||||
#if CPU!=SIMSPARCSOLARIS
|
||||
/* Read the feature control register */
|
||||
IX_FEATURE_CTRL_READ(result);
|
||||
return result;
|
||||
#else
|
||||
/* Return an invalid value for VxWorks simulation */
|
||||
result = 0xFFFFFFFF;
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Function definition: ixFeatureCtrlWrite
|
||||
*/
|
||||
void
|
||||
ixFeatureCtrlWrite (IxFeatureCtrlReg expUnitReg)
|
||||
{
|
||||
#if CPU!=SIMSPARCSOLARIS
|
||||
/* Write value to feature control register */
|
||||
IX_FEATURE_CTRL_WRITE(expUnitReg);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function definition: ixFeatureCtrlHwCapabilityRead
|
||||
*/
|
||||
IxFeatureCtrlReg
|
||||
ixFeatureCtrlHwCapabilityRead (void)
|
||||
{
|
||||
IxFeatureCtrlReg currentReg, hwCapability;
|
||||
|
||||
/* Capture a copy of feature control register */
|
||||
currentReg = ixFeatureCtrlRead();
|
||||
|
||||
/* Try to enable all hardware components.
|
||||
* Only software disable hardware can be enabled again */
|
||||
ixFeatureCtrlWrite(0);
|
||||
|
||||
/* Read feature control register to know the hardware capability. */
|
||||
hwCapability = ixFeatureCtrlRead();
|
||||
|
||||
/* Restore initial feature control value */
|
||||
ixFeatureCtrlWrite(currentReg);
|
||||
|
||||
/* return Hardware Capability */
|
||||
return hwCapability;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function definition: ixFeatureCtrlComponentCheck
|
||||
*/
|
||||
IX_STATUS
|
||||
ixFeatureCtrlComponentCheck (IxFeatureCtrlComponentType componentType)
|
||||
{
|
||||
IxFeatureCtrlReg expUnitReg;
|
||||
UINT32 mask = 0;
|
||||
|
||||
/* Lookup mask of component */
|
||||
mask=componentMask[componentType];
|
||||
|
||||
/* Check if mask is available or not */
|
||||
if(IX_FEATURECTRL_COMPONENT_NOT_AVAILABLE == mask)
|
||||
{
|
||||
return IX_FEATURE_CTRL_COMPONENT_DISABLED;
|
||||
}
|
||||
|
||||
if(IX_FEATURECTRL_COMPONENT_ALWAYS_AVAILABLE == mask)
|
||||
{
|
||||
return IX_FEATURE_CTRL_COMPONENT_ENABLED;
|
||||
}
|
||||
|
||||
/* Read feature control register to know current hardware capability. */
|
||||
expUnitReg = ixFeatureCtrlRead();
|
||||
|
||||
/* For example: To check for Hashing Coprocessor (bit-2)
|
||||
* expUniteg = 0x0010
|
||||
* ~expUnitReg = 0x1101
|
||||
* componentType = 0x0100
|
||||
* ~expUnitReg & componentType = 0x0100 (Not zero)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Inverse the bit value because available component is 0 in value
|
||||
*/
|
||||
expUnitReg = ~expUnitReg ;
|
||||
|
||||
if (expUnitReg & mask)
|
||||
{
|
||||
return (IX_FEATURE_CTRL_COMPONENT_ENABLED);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (IX_FEATURE_CTRL_COMPONENT_DISABLED);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function definition: ixFeatureCtrlProductIdRead
|
||||
*/
|
||||
IxFeatureCtrlProductId
|
||||
ixFeatureCtrlProductIdRead ()
|
||||
{
|
||||
#if CPU!=SIMSPARCSOLARIS
|
||||
IxFeatureCtrlProductId pdId = 0 ;
|
||||
|
||||
/* Use ARM instruction to move register0 from coprocessor to ARM register */
|
||||
|
||||
#ifndef __wince
|
||||
__asm("mrc p15, 0, %0, cr0, cr0, 0;" : "=r"(pdId) :);
|
||||
#else
|
||||
|
||||
#ifndef IN_KERNEL
|
||||
BOOL mode;
|
||||
#endif
|
||||
extern IxFeatureCtrlProductId AsmixFeatureCtrlProductIdRead();
|
||||
|
||||
#ifndef IN_KERNEL
|
||||
mode = SetKMode(TRUE);
|
||||
#endif
|
||||
pdId = AsmixFeatureCtrlProductIdRead();
|
||||
#ifndef IN_KERNEL
|
||||
SetKMode(mode);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
return (pdId);
|
||||
#else
|
||||
/* Return an invalid value for VxWorks simulation */
|
||||
return 0xffffffff;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Function definition: ixFeatureCtrlDeviceRead
|
||||
*/
|
||||
IxFeatureCtrlDeviceId
|
||||
ixFeatureCtrlDeviceRead ()
|
||||
{
|
||||
return ((ixFeatureCtrlProductIdRead() >> IX_FEATURE_CTRL_DEVICE_TYPE_OFFSET)
|
||||
& IX_FEATURE_CTRL_DEVICE_TYPE_MASK);
|
||||
} /* End function ixFeatureCtrlDeviceRead */
|
||||
|
||||
|
||||
/**
|
||||
* Function definition: ixFeatureCtrlSwConfigurationCheck
|
||||
*/
|
||||
IX_STATUS
|
||||
ixFeatureCtrlSwConfigurationCheck (IxFeatureCtrlSwConfig swConfigType)
|
||||
{
|
||||
if (swConfigType >= IX_FEATURECTRL_SWCONFIG_MAX)
|
||||
{
|
||||
ixOsalLog(IX_OSAL_LOG_LVL_WARNING,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"FeatureCtrl: Invalid software configuraiton input.\n",
|
||||
0, 0, 0, 0, 0, 0);
|
||||
|
||||
return IX_FEATURE_CTRL_SWCONFIG_DISABLED;
|
||||
}
|
||||
|
||||
/* The function will only initialize once. */
|
||||
ixFeatureCtrlSwConfigurationInit();
|
||||
|
||||
/* Check and return software configuration */
|
||||
return ((swConfiguration[(UINT32)swConfigType] == TRUE) ? IX_FEATURE_CTRL_SWCONFIG_ENABLED: IX_FEATURE_CTRL_SWCONFIG_DISABLED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function definition: ixFeatureCtrlSwConfigurationWrite
|
||||
*/
|
||||
void
|
||||
ixFeatureCtrlSwConfigurationWrite (IxFeatureCtrlSwConfig swConfigType, BOOL enabled)
|
||||
{
|
||||
if (swConfigType >= IX_FEATURECTRL_SWCONFIG_MAX)
|
||||
{
|
||||
ixOsalLog(IX_OSAL_LOG_LVL_WARNING,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"FeatureCtrl: Invalid software configuraiton input.\n",
|
||||
0, 0, 0, 0, 0, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* The function will only initialize once. */
|
||||
ixFeatureCtrlSwConfigurationInit();
|
||||
|
||||
/* Write software configuration */
|
||||
swConfiguration[(UINT32)swConfigType]=enabled ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function definition: ixFeatureCtrlIxp400SwVersionShow
|
||||
*/
|
||||
void
|
||||
ixFeatureCtrlIxp400SwVersionShow (void)
|
||||
{
|
||||
printf ("\nIXP400 Software Release %s %s\n\n", IX_VERSION_ID, IX_VERSION_INTERNAL_ID);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Function definition: ixFeatureCtrlSoftwareBuildGet
|
||||
*/
|
||||
IxFeatureCtrlBuildDevice
|
||||
ixFeatureCtrlSoftwareBuildGet (void)
|
||||
{
|
||||
#ifdef __ixp42X
|
||||
return IX_FEATURE_CTRL_SW_BUILD_IXP42X;
|
||||
#else
|
||||
return IX_FEATURE_CTRL_SW_BUILD_IXP46X;
|
||||
#endif
|
||||
}
|
972
cpu/ixp/npe/IxNpeDl.c
Normal file
972
cpu/ixp/npe/IxNpeDl.c
Normal file
@ -0,0 +1,972 @@
|
||||
/**
|
||||
* @file IxNpeDl.c
|
||||
*
|
||||
* @author Intel Corporation
|
||||
* @date 08 January 2002
|
||||
*
|
||||
* @brief This file contains the implementation of the public API for the
|
||||
* IXP425 NPE Downloader component
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
/*
|
||||
* Put the system defined include files required
|
||||
*/
|
||||
|
||||
/*
|
||||
* Put the user defined include files required
|
||||
*/
|
||||
#include "IxNpeDl.h"
|
||||
#include "IxNpeDlImageMgr_p.h"
|
||||
#include "IxNpeDlNpeMgr_p.h"
|
||||
#include "IxNpeDlMacros_p.h"
|
||||
#include "IxFeatureCtrl.h"
|
||||
#include "IxOsal.h"
|
||||
/*
|
||||
* #defines used in this file
|
||||
*/
|
||||
#define IMAGEID_MAJOR_NUMBER_DEFAULT 0
|
||||
#define IMAGEID_MINOR_NUMBER_DEFAULT 0
|
||||
|
||||
/*
|
||||
* Typedefs whose scope is limited to this file.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
BOOL validImage;
|
||||
IxNpeDlImageId imageId;
|
||||
} IxNpeDlNpeState;
|
||||
|
||||
/* module statistics counters */
|
||||
typedef struct
|
||||
{
|
||||
UINT32 attemptedDownloads;
|
||||
UINT32 successfulDownloads;
|
||||
UINT32 criticalFailDownloads;
|
||||
} IxNpeDlStats;
|
||||
|
||||
/*
|
||||
* Variable declarations global to this file only. Externs are followed
|
||||
* by static variables.
|
||||
*/
|
||||
static IxNpeDlNpeState ixNpeDlNpeState[IX_NPEDL_NPEID_MAX] =
|
||||
{
|
||||
{FALSE, {IX_NPEDL_NPEID_MAX, 0, 0, 0}},
|
||||
{FALSE, {IX_NPEDL_NPEID_MAX, 0, 0, 0}},
|
||||
{FALSE, {IX_NPEDL_NPEID_MAX, 0, 0, 0}}
|
||||
};
|
||||
|
||||
static IxNpeDlStats ixNpeDlStats;
|
||||
|
||||
/*
|
||||
* Software guard to prevent NPE from being started multiple times.
|
||||
*/
|
||||
static BOOL ixNpeDlNpeStarted[IX_NPEDL_NPEID_MAX] ={FALSE, FALSE, FALSE} ;
|
||||
|
||||
|
||||
/*
|
||||
* static function prototypes.
|
||||
*/
|
||||
PRIVATE IX_STATUS
|
||||
ixNpeDlNpeInitAndStartInternal (UINT32 *imageLibrary, UINT32 imageId);
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlMicrocodeImageLibraryOverride
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixNpeDlMicrocodeImageLibraryOverride (UINT32 *clientImageLibrary)
|
||||
{
|
||||
IX_STATUS status = IX_SUCCESS;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlMicrocodeImageLibraryOverride\n");
|
||||
|
||||
if (clientImageLibrary == NULL)
|
||||
{
|
||||
status = IX_NPEDL_PARAM_ERR;
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlMicrocodeImageLibraryOverride - "
|
||||
"invalid parameter\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ixNpeDlImageMgrMicrocodeImageLibraryOverride (clientImageLibrary);
|
||||
if (status != IX_SUCCESS)
|
||||
{
|
||||
status = IX_FAIL;
|
||||
}
|
||||
} /* end of if-else(clientImageLibrary) */
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlMicrocodeImageLibraryOverride : "
|
||||
"status = %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlImageDownload
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixNpeDlImageDownload (IxNpeDlImageId *imageIdPtr,
|
||||
BOOL verify)
|
||||
{
|
||||
UINT32 imageSize;
|
||||
UINT32 *imageCodePtr = NULL;
|
||||
IX_STATUS status;
|
||||
IxNpeDlNpeId npeId = imageIdPtr->npeId;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlImageDownload\n");
|
||||
|
||||
ixNpeDlStats.attemptedDownloads++;
|
||||
|
||||
/* Check input parameters */
|
||||
if ((npeId >= IX_NPEDL_NPEID_MAX) || (npeId < 0))
|
||||
{
|
||||
status = IX_NPEDL_PARAM_ERR;
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlImageDownload - invalid parameter\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Ensure initialisation has been completed */
|
||||
ixNpeDlNpeMgrInit();
|
||||
|
||||
/* If not IXP42X A0 stepping, proceed to check for existence of npe's */
|
||||
if ((IX_FEATURE_CTRL_SILICON_TYPE_A0 !=
|
||||
(ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK))
|
||||
|| (IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X != ixFeatureCtrlDeviceRead ()))
|
||||
{
|
||||
if (npeId == IX_NPEDL_NPEID_NPEA)
|
||||
{
|
||||
if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEA) ==
|
||||
IX_FEATURE_CTRL_COMPONENT_DISABLED)
|
||||
{
|
||||
IX_NPEDL_WARNING_REPORT("Warning: the NPE A component you specified does"
|
||||
" not exist\n");
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
} /* end of if(npeId) */
|
||||
else if (npeId == IX_NPEDL_NPEID_NPEB)
|
||||
{
|
||||
if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEB)==
|
||||
IX_FEATURE_CTRL_COMPONENT_DISABLED)
|
||||
{
|
||||
IX_NPEDL_WARNING_REPORT("Warning: the NPE B component you specified"
|
||||
" does not exist\n");
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
} /* end of elseif(npeId) */
|
||||
else if (npeId == IX_NPEDL_NPEID_NPEC)
|
||||
{
|
||||
if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEC)==
|
||||
IX_FEATURE_CTRL_COMPONENT_DISABLED)
|
||||
{
|
||||
IX_NPEDL_WARNING_REPORT("Warning: the NPE C component you specified"
|
||||
" does not exist\n");
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
} /* end of elseif(npeId) */
|
||||
} /* end of if(IX_FEATURE_CTRL_SILICON_TYPE_B0) */ /*End of Silicon Type Check*/
|
||||
|
||||
/* stop and reset the NPE */
|
||||
if (IX_SUCCESS != ixNpeDlNpeStopAndReset (npeId))
|
||||
{
|
||||
IX_NPEDL_ERROR_REPORT ("Failed to stop and reset NPE\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* Locate image */
|
||||
status = ixNpeDlImageMgrImageLocate (imageIdPtr, &imageCodePtr,
|
||||
&imageSize);
|
||||
if (IX_SUCCESS == status)
|
||||
{
|
||||
/*
|
||||
* If download was successful, store image Id in list of
|
||||
* currently loaded images. If a critical error occured
|
||||
* during download, record that the NPE has an invalid image
|
||||
*/
|
||||
status = ixNpeDlNpeMgrImageLoad (npeId, imageCodePtr,
|
||||
verify);
|
||||
if (IX_SUCCESS == status)
|
||||
{
|
||||
ixNpeDlNpeState[npeId].imageId = *imageIdPtr;
|
||||
ixNpeDlNpeState[npeId].validImage = TRUE;
|
||||
ixNpeDlStats.successfulDownloads++;
|
||||
|
||||
status = ixNpeDlNpeExecutionStart (npeId);
|
||||
}
|
||||
else if ((status == IX_NPEDL_CRITICAL_NPE_ERR) ||
|
||||
(status == IX_NPEDL_CRITICAL_MICROCODE_ERR))
|
||||
{
|
||||
ixNpeDlNpeState[npeId].imageId = *imageIdPtr;
|
||||
ixNpeDlNpeState[npeId].validImage = FALSE;
|
||||
ixNpeDlStats.criticalFailDownloads++;
|
||||
}
|
||||
} /* end of if(IX_SUCCESS) */ /* condition: image located successfully in microcode image */
|
||||
} /* end of if-else(npeId) */ /* condition: parameter checks ok */
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlImageDownload : status = %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlAvailableImagesCountGet
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixNpeDlAvailableImagesCountGet (UINT32 *numImagesPtr)
|
||||
{
|
||||
IX_STATUS status;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlAvailableImagesCountGet\n");
|
||||
|
||||
/* Check input parameters */
|
||||
if (numImagesPtr == NULL)
|
||||
{
|
||||
status = IX_NPEDL_PARAM_ERR;
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlAvailableImagesCountGet - "
|
||||
"invalid parameter\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Use ImageMgr module to get no. of images listed in Image Library Header.
|
||||
* If NULL is passed as imageListPtr parameter to following function,
|
||||
* it will only fill number of images into numImagesPtr
|
||||
*/
|
||||
status = ixNpeDlImageMgrImageListExtract (NULL, numImagesPtr);
|
||||
} /* end of if-else(numImagesPtr) */
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlAvailableImagesCountGet : "
|
||||
"status = %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlAvailableImagesListGet
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixNpeDlAvailableImagesListGet (IxNpeDlImageId *imageIdListPtr,
|
||||
UINT32 *listSizePtr)
|
||||
{
|
||||
IX_STATUS status;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlAvailableImagesListGet\n");
|
||||
|
||||
/* Check input parameters */
|
||||
if ((imageIdListPtr == NULL) || (listSizePtr == NULL))
|
||||
{
|
||||
status = IX_NPEDL_PARAM_ERR;
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlAvailableImagesListGet - "
|
||||
"invalid parameter\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call ImageMgr to get list of images listed in Image Library Header */
|
||||
status = ixNpeDlImageMgrImageListExtract (imageIdListPtr,
|
||||
listSizePtr);
|
||||
} /* end of if-else(imageIdListPtr) */
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlAvailableImagesListGet : status = %d\n",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlLoadedImageGet
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixNpeDlLoadedImageGet (IxNpeDlNpeId npeId,
|
||||
IxNpeDlImageId *imageIdPtr)
|
||||
{
|
||||
IX_STATUS status = IX_SUCCESS;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlLoadedImageGet\n");
|
||||
|
||||
/* Check input parameters */
|
||||
if ((npeId >= IX_NPEDL_NPEID_MAX) || (npeId < 0) || (imageIdPtr == NULL))
|
||||
{
|
||||
status = IX_NPEDL_PARAM_ERR;
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlLoadedImageGet - invalid parameter\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* If not IXP42X A0 stepping, proceed to check for existence of npe's */
|
||||
if ((IX_FEATURE_CTRL_SILICON_TYPE_A0 !=
|
||||
(ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK))
|
||||
|| (IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X != ixFeatureCtrlDeviceRead ()))
|
||||
{
|
||||
if (npeId == IX_NPEDL_NPEID_NPEA &&
|
||||
(ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEA) ==
|
||||
IX_FEATURE_CTRL_COMPONENT_DISABLED))
|
||||
{
|
||||
IX_NPEDL_WARNING_REPORT("Warning: the NPE A component you specified does"
|
||||
" not exist\n");
|
||||
return IX_SUCCESS;
|
||||
} /* end of if(npeId) */
|
||||
|
||||
if (npeId == IX_NPEDL_NPEID_NPEB &&
|
||||
(ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEB) ==
|
||||
IX_FEATURE_CTRL_COMPONENT_DISABLED))
|
||||
{
|
||||
IX_NPEDL_WARNING_REPORT("Warning: the NPE B component you specified does"
|
||||
" not exist\n");
|
||||
return IX_SUCCESS;
|
||||
} /* end of if(npeId) */
|
||||
|
||||
if (npeId == IX_NPEDL_NPEID_NPEC &&
|
||||
(ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEC) ==
|
||||
IX_FEATURE_CTRL_COMPONENT_DISABLED))
|
||||
{
|
||||
IX_NPEDL_WARNING_REPORT("Warning: the NPE C component you specified does"
|
||||
" not exist\n");
|
||||
return IX_SUCCESS;
|
||||
} /* end of if(npeId) */
|
||||
} /* end of if not IXP42x-A0 silicon */
|
||||
|
||||
if (ixNpeDlNpeState[npeId].validImage)
|
||||
{
|
||||
/* use npeId to get imageId from list of currently loaded
|
||||
images */
|
||||
*imageIdPtr = ixNpeDlNpeState[npeId].imageId;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = IX_FAIL;
|
||||
} /* end of if-else(ixNpeDlNpeState) */
|
||||
} /* end of if-else(npeId) */
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlLoadedImageGet : status = %d\n",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlLatestImageGet
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixNpeDlLatestImageGet (
|
||||
IxNpeDlNpeId npeId,
|
||||
IxNpeDlFunctionalityId functionalityId,
|
||||
IxNpeDlImageId *imageIdPtr)
|
||||
{
|
||||
IX_STATUS status;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlLatestImageGet\n");
|
||||
|
||||
/* Check input parameters */
|
||||
if ((npeId >= IX_NPEDL_NPEID_MAX) ||
|
||||
(npeId < 0) ||
|
||||
(imageIdPtr == NULL))
|
||||
{
|
||||
status = IX_NPEDL_PARAM_ERR;
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlLatestImageGet - "
|
||||
"invalid parameter\n");
|
||||
} /* end of if(npeId) */
|
||||
else
|
||||
{
|
||||
|
||||
/* If not IXP42X A0 stepping, proceed to check for existence of npe's */
|
||||
if ((IX_FEATURE_CTRL_SILICON_TYPE_A0 !=
|
||||
(ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK))
|
||||
|| (IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X != ixFeatureCtrlDeviceRead ()))
|
||||
{
|
||||
if (npeId == IX_NPEDL_NPEID_NPEA &&
|
||||
(ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEA) ==
|
||||
IX_FEATURE_CTRL_COMPONENT_DISABLED))
|
||||
{
|
||||
IX_NPEDL_WARNING_REPORT("Warning: the NPE A component you specified does"
|
||||
" not exist\n");
|
||||
return IX_SUCCESS;
|
||||
} /* end of if(npeId) */
|
||||
|
||||
if (npeId == IX_NPEDL_NPEID_NPEB &&
|
||||
(ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEB) ==
|
||||
IX_FEATURE_CTRL_COMPONENT_DISABLED))
|
||||
{
|
||||
IX_NPEDL_WARNING_REPORT("Warning: the NPE B component you specified does"
|
||||
" not exist\n");
|
||||
return IX_SUCCESS;
|
||||
} /* end of if(npeId) */
|
||||
|
||||
if (npeId == IX_NPEDL_NPEID_NPEC &&
|
||||
(ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEC) ==
|
||||
IX_FEATURE_CTRL_COMPONENT_DISABLED))
|
||||
{
|
||||
IX_NPEDL_WARNING_REPORT("Warning: the NPE C component you specified does"
|
||||
" not exist\n");
|
||||
return IX_SUCCESS;
|
||||
} /* end of if(npeId) */
|
||||
} /* end of if not IXP42x-A0 silicon */
|
||||
|
||||
imageIdPtr->npeId = npeId;
|
||||
imageIdPtr->functionalityId = functionalityId;
|
||||
imageIdPtr->major = IMAGEID_MAJOR_NUMBER_DEFAULT;
|
||||
imageIdPtr->minor = IMAGEID_MINOR_NUMBER_DEFAULT;
|
||||
/* Call ImageMgr to get list of images listed in Image Library Header */
|
||||
status = ixNpeDlImageMgrLatestImageExtract(imageIdPtr);
|
||||
} /* end of if-else(npeId) */
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlLatestImageGet : status = %d\n",
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeStopAndReset
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixNpeDlNpeStopAndReset (IxNpeDlNpeId npeId)
|
||||
{
|
||||
IX_STATUS status = IX_SUCCESS;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlNpeStopAndReset\n");
|
||||
|
||||
/* Ensure initialisation has been completed */
|
||||
ixNpeDlNpeMgrInit();
|
||||
|
||||
/* If not IXP42X A0 stepping, proceed to check for existence of npe's */
|
||||
if ((IX_FEATURE_CTRL_SILICON_TYPE_A0 !=
|
||||
(ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK))
|
||||
|| (IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X != ixFeatureCtrlDeviceRead ()))
|
||||
{
|
||||
/*
|
||||
* Check whether NPE is present
|
||||
*/
|
||||
if (IX_NPEDL_NPEID_NPEA == npeId)
|
||||
{
|
||||
/* Check whether NPE A is present */
|
||||
if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEA)==
|
||||
IX_FEATURE_CTRL_COMPONENT_DISABLED)
|
||||
{
|
||||
/* NPE A does not present */
|
||||
IX_NPEDL_WARNING_REPORT ("ixNpeDlNpeStopAndReset - Warning:NPEA does not present.\n");
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
} /* end of if(IX_NPEDL_NPEID_NPEA) */
|
||||
else if (IX_NPEDL_NPEID_NPEB == npeId)
|
||||
{
|
||||
/* Check whether NPE B is present */
|
||||
if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEB)==
|
||||
IX_FEATURE_CTRL_COMPONENT_DISABLED)
|
||||
{
|
||||
/* NPE B does not present */
|
||||
IX_NPEDL_WARNING_REPORT ("ixNpeDlNpeStopAndReset - Warning:NPEB does not present.\n");
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
} /* end of elseif(IX_NPEDL_NPEID_NPEB) */
|
||||
else if (IX_NPEDL_NPEID_NPEC == npeId)
|
||||
{
|
||||
/* Check whether NPE C is present */
|
||||
if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEC)==
|
||||
IX_FEATURE_CTRL_COMPONENT_DISABLED)
|
||||
{
|
||||
/* NPE C does not present */
|
||||
IX_NPEDL_WARNING_REPORT ("ixNpeDlNpeStopAndReset - Warning:NPEC does not present.\n");
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
} /* end of elseif(IX_NPEDL_NPEID_NPEC) */
|
||||
else
|
||||
{
|
||||
/* Invalid NPE ID */
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeStopAndReset - invalid Npe ID\n");
|
||||
status = IX_NPEDL_PARAM_ERR;
|
||||
} /* end of if-else(IX_NPEDL_NPEID_NPEC) */
|
||||
} /* end of if not IXP42x-A0 Silicon */
|
||||
|
||||
if (status == IX_SUCCESS)
|
||||
{
|
||||
/* call NpeMgr function to stop the NPE */
|
||||
status = ixNpeDlNpeMgrNpeStop (npeId);
|
||||
if (status == IX_SUCCESS)
|
||||
{
|
||||
/* call NpeMgr function to reset the NPE */
|
||||
status = ixNpeDlNpeMgrNpeReset (npeId);
|
||||
}
|
||||
} /* end of if(status) */
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlNpeStopAndReset : status = %d\n", status);
|
||||
|
||||
if (IX_SUCCESS == status)
|
||||
{
|
||||
/* Indicate NPE has been stopped */
|
||||
ixNpeDlNpeStarted[npeId] = FALSE ;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeExecutionStart
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixNpeDlNpeExecutionStart (IxNpeDlNpeId npeId)
|
||||
{
|
||||
IX_STATUS status = IX_SUCCESS;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlNpeExecutionStart\n");
|
||||
|
||||
/* If not IXP42X A0 stepping, proceed to check for existence of npe's */
|
||||
if ((IX_FEATURE_CTRL_SILICON_TYPE_A0 !=
|
||||
(ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK))
|
||||
|| (IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X != ixFeatureCtrlDeviceRead ()))
|
||||
{
|
||||
/*
|
||||
* Check whether NPE is present
|
||||
*/
|
||||
if (IX_NPEDL_NPEID_NPEA == npeId)
|
||||
{
|
||||
/* Check whether NPE A is present */
|
||||
if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEA)==
|
||||
IX_FEATURE_CTRL_COMPONENT_DISABLED)
|
||||
{
|
||||
/* NPE A does not present */
|
||||
IX_NPEDL_WARNING_REPORT ("ixNpeDlNpeExecutionStart - Warning:NPEA does not present.\n");
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
} /* end of if(IX_NPEDL_NPEID_NPEA) */
|
||||
else if (IX_NPEDL_NPEID_NPEB == npeId)
|
||||
{
|
||||
/* Check whether NPE B is present */
|
||||
if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEB)==
|
||||
IX_FEATURE_CTRL_COMPONENT_DISABLED)
|
||||
{
|
||||
/* NPE B does not present */
|
||||
IX_NPEDL_WARNING_REPORT ("ixNpeDlNpeExecutionStart - Warning:NPEB does not present.\n");
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
} /* end of elseif(IX_NPEDL_NPEID_NPEB) */
|
||||
else if (IX_NPEDL_NPEID_NPEC == npeId)
|
||||
{
|
||||
/* Check whether NPE C is present */
|
||||
if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEC)==
|
||||
IX_FEATURE_CTRL_COMPONENT_DISABLED)
|
||||
{
|
||||
/* NPE C does not present */
|
||||
IX_NPEDL_WARNING_REPORT ("ixNpeDlNpeExecutionStart - Warning:NPEC does not present.\n");
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
} /* end of elseif(IX_NPEDL_NPEID_NPEC) */
|
||||
else
|
||||
{
|
||||
/* Invalid NPE ID */
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeExecutionStart - invalid Npe ID\n");
|
||||
return IX_NPEDL_PARAM_ERR;
|
||||
} /* end of if-else(IX_NPEDL_NPEID_NPEC) */
|
||||
} /* end of if not IXP42x-A0 Silicon */
|
||||
|
||||
if (TRUE == ixNpeDlNpeStarted[npeId])
|
||||
{
|
||||
/* NPE has been started. */
|
||||
return IX_SUCCESS ;
|
||||
}
|
||||
|
||||
/* Ensure initialisation has been completed */
|
||||
ixNpeDlNpeMgrInit();
|
||||
|
||||
/* call NpeMgr function to start the NPE */
|
||||
status = ixNpeDlNpeMgrNpeStart (npeId);
|
||||
|
||||
if (IX_SUCCESS == status)
|
||||
{
|
||||
/* Indicate NPE has started */
|
||||
ixNpeDlNpeStarted[npeId] = TRUE ;
|
||||
}
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlNpeExecutionStart : status = %d\n",
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeExecutionStop
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixNpeDlNpeExecutionStop (IxNpeDlNpeId npeId)
|
||||
{
|
||||
IX_STATUS status = IX_SUCCESS;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlNpeExecutionStop\n");
|
||||
|
||||
/* Ensure initialisation has been completed */
|
||||
ixNpeDlNpeMgrInit();
|
||||
|
||||
/* If not IXP42X A0 stepping, proceed to check for existence of npe's */
|
||||
if ((IX_FEATURE_CTRL_SILICON_TYPE_A0 !=
|
||||
(ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK))
|
||||
|| (IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X != ixFeatureCtrlDeviceRead ()))
|
||||
{
|
||||
/*
|
||||
* Check whether NPE is present
|
||||
*/
|
||||
if (IX_NPEDL_NPEID_NPEA == npeId)
|
||||
{
|
||||
/* Check whether NPE A is present */
|
||||
if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEA)==
|
||||
IX_FEATURE_CTRL_COMPONENT_DISABLED)
|
||||
{
|
||||
/* NPE A does not present */
|
||||
IX_NPEDL_WARNING_REPORT ("ixNpeDlNpeExecutionStop - Warning:NPEA does not present.\n");
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
} /* end of if(IX_NPEDL_NPEID_NPEA) */
|
||||
else if (IX_NPEDL_NPEID_NPEB == npeId)
|
||||
{
|
||||
/* Check whether NPE B is present */
|
||||
if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEB)==
|
||||
IX_FEATURE_CTRL_COMPONENT_DISABLED)
|
||||
{
|
||||
/* NPE B does not present */
|
||||
IX_NPEDL_WARNING_REPORT ("ixNpeDlNpeExecutionStop - Warning:NPEB does not present.\n");
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
} /* end of elseif(IX_NPEDL_NPEID_NPEB) */
|
||||
else if (IX_NPEDL_NPEID_NPEC == npeId)
|
||||
{
|
||||
/* Check whether NPE C is present */
|
||||
if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEC)==
|
||||
IX_FEATURE_CTRL_COMPONENT_DISABLED)
|
||||
{
|
||||
/* NPE C does not present */
|
||||
IX_NPEDL_WARNING_REPORT ("ixNpeDlNpeExecutionStop - Warning:NPEC does not present.\n");
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
} /* end of elseif(IX_NPEDL_NPEID_NPEC) */
|
||||
else
|
||||
{
|
||||
/* Invalid NPE ID */
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeExecutionStop - invalid Npe ID\n");
|
||||
status = IX_NPEDL_PARAM_ERR;
|
||||
} /* end of if-else(IX_NPEDL_NPEID_NPEC) */
|
||||
} /* end of if not IXP42X-AO Silicon */
|
||||
|
||||
if (status == IX_SUCCESS)
|
||||
{
|
||||
/* call NpeMgr function to stop the NPE */
|
||||
status = ixNpeDlNpeMgrNpeStop (npeId);
|
||||
}
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlNpeExecutionStop : status = %d\n",
|
||||
status);
|
||||
|
||||
if (IX_SUCCESS == status)
|
||||
{
|
||||
/* Indicate NPE has been stopped */
|
||||
ixNpeDlNpeStarted[npeId] = FALSE ;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlUnload
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixNpeDlUnload (void)
|
||||
{
|
||||
IX_STATUS status;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlUnload\n");
|
||||
|
||||
status = ixNpeDlNpeMgrUninit();
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlUnload : status = %d\n",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlStatsShow
|
||||
*/
|
||||
PUBLIC void
|
||||
ixNpeDlStatsShow (void)
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_USER,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"\nixNpeDlStatsShow:\n"
|
||||
"\tDownloads Attempted by user: %u\n"
|
||||
"\tSuccessful Downloads: %u\n"
|
||||
"\tFailed Downloads (due to Critical Error): %u\n\n",
|
||||
ixNpeDlStats.attemptedDownloads,
|
||||
ixNpeDlStats.successfulDownloads,
|
||||
ixNpeDlStats.criticalFailDownloads,
|
||||
0,0,0);
|
||||
|
||||
ixNpeDlImageMgrStatsShow ();
|
||||
ixNpeDlNpeMgrStatsShow ();
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlStatsReset
|
||||
*/
|
||||
PUBLIC void
|
||||
ixNpeDlStatsReset (void)
|
||||
{
|
||||
ixNpeDlStats.attemptedDownloads = 0;
|
||||
ixNpeDlStats.successfulDownloads = 0;
|
||||
ixNpeDlStats.criticalFailDownloads = 0;
|
||||
|
||||
ixNpeDlImageMgrStatsReset ();
|
||||
ixNpeDlNpeMgrStatsReset ();
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeInitAndStartInternal
|
||||
*/
|
||||
PRIVATE IX_STATUS
|
||||
ixNpeDlNpeInitAndStartInternal (UINT32 *imageLibrary,
|
||||
UINT32 imageId)
|
||||
{
|
||||
UINT32 imageSize;
|
||||
UINT32 *imageCodePtr = NULL;
|
||||
IX_STATUS status;
|
||||
IxNpeDlNpeId npeId = IX_NPEDL_NPEID_FROM_IMAGEID_GET(imageId);
|
||||
IxFeatureCtrlDeviceId deviceId = IX_NPEDL_DEVICEID_FROM_IMAGEID_GET(imageId);
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlNpeInitAndStartInternal\n");
|
||||
|
||||
ixNpeDlStats.attemptedDownloads++;
|
||||
|
||||
/* Check input parameter device correctness */
|
||||
if ((deviceId >= IX_FEATURE_CTRL_DEVICE_TYPE_MAX) ||
|
||||
(deviceId < IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X))
|
||||
{
|
||||
status = IX_NPEDL_PARAM_ERR;
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeInitAndStartInternal - "
|
||||
"invalid parameter\n");
|
||||
} /* End valid device id checking */
|
||||
|
||||
/* Check input parameters */
|
||||
else if ((npeId >= IX_NPEDL_NPEID_MAX) || (npeId < 0))
|
||||
{
|
||||
status = IX_NPEDL_PARAM_ERR;
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeInitAndStartInternal - "
|
||||
"invalid parameter\n");
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
/* Ensure initialisation has been completed */
|
||||
ixNpeDlNpeMgrInit();
|
||||
|
||||
/* Checking if image being loaded is meant for device that is running.
|
||||
* Image is forward compatible. i.e Image built for IXP42X should run
|
||||
* on IXP46X but not vice versa.*/
|
||||
if (deviceId > (ixFeatureCtrlDeviceRead() & IX_FEATURE_CTRL_DEVICE_TYPE_MASK))
|
||||
{
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeInitAndStartInternal - "
|
||||
"Device type mismatch. NPE Image not "
|
||||
"meant for device in use \n");
|
||||
return IX_NPEDL_DEVICE_ERR;
|
||||
}/* if statement - matching image device and current device */
|
||||
|
||||
/* If not IXP42X A0 stepping, proceed to check for existence of npe's */
|
||||
if ((IX_FEATURE_CTRL_SILICON_TYPE_A0 !=
|
||||
(ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK))
|
||||
|| (IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X != ixFeatureCtrlDeviceRead ()))
|
||||
{
|
||||
if (npeId == IX_NPEDL_NPEID_NPEA)
|
||||
{
|
||||
if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEA) ==
|
||||
IX_FEATURE_CTRL_COMPONENT_DISABLED)
|
||||
{
|
||||
IX_NPEDL_WARNING_REPORT("Warning: the NPE A component you specified does"
|
||||
" not exist\n");
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
} /* end of if(npeId) */
|
||||
else if (npeId == IX_NPEDL_NPEID_NPEB)
|
||||
{
|
||||
if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEB)==
|
||||
IX_FEATURE_CTRL_COMPONENT_DISABLED)
|
||||
{
|
||||
IX_NPEDL_WARNING_REPORT("Warning: the NPE B component you specified"
|
||||
" does not exist\n");
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
} /* end of elseif(npeId) */
|
||||
else if (npeId == IX_NPEDL_NPEID_NPEC)
|
||||
{
|
||||
if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEC)==
|
||||
IX_FEATURE_CTRL_COMPONENT_DISABLED)
|
||||
{
|
||||
IX_NPEDL_WARNING_REPORT("Warning: the NPE C component you specified"
|
||||
" does not exist\n");
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
} /* end of elseif(npeId) */
|
||||
} /* end of if not IXP42X-A0 Silicon */
|
||||
|
||||
/* stop and reset the NPE */
|
||||
status = ixNpeDlNpeStopAndReset (npeId);
|
||||
if (IX_SUCCESS != status)
|
||||
{
|
||||
IX_NPEDL_ERROR_REPORT ("Failed to stop and reset NPE\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Locate image */
|
||||
status = ixNpeDlImageMgrImageFind (imageLibrary, imageId,
|
||||
&imageCodePtr, &imageSize);
|
||||
if (IX_SUCCESS == status)
|
||||
{
|
||||
/*
|
||||
* If download was successful, store image Id in list of
|
||||
* currently loaded images. If a critical error occured
|
||||
* during download, record that the NPE has an invalid image
|
||||
*/
|
||||
status = ixNpeDlNpeMgrImageLoad (npeId, imageCodePtr, TRUE);
|
||||
if (IX_SUCCESS == status)
|
||||
{
|
||||
ixNpeDlNpeState[npeId].validImage = TRUE;
|
||||
ixNpeDlStats.successfulDownloads++;
|
||||
|
||||
status = ixNpeDlNpeExecutionStart (npeId);
|
||||
}
|
||||
else if ((status == IX_NPEDL_CRITICAL_NPE_ERR) ||
|
||||
(status == IX_NPEDL_CRITICAL_MICROCODE_ERR))
|
||||
{
|
||||
ixNpeDlNpeState[npeId].validImage = FALSE;
|
||||
ixNpeDlStats.criticalFailDownloads++;
|
||||
}
|
||||
|
||||
/* NOTE - The following section of code is here to support
|
||||
* a deprecated function ixNpeDlLoadedImageGet(). When that
|
||||
* function is removed from the API, this code should be revised.
|
||||
*/
|
||||
ixNpeDlNpeState[npeId].imageId.npeId = npeId;
|
||||
ixNpeDlNpeState[npeId].imageId.functionalityId =
|
||||
IX_NPEDL_FUNCTIONID_FROM_IMAGEID_GET(imageId);
|
||||
ixNpeDlNpeState[npeId].imageId.major =
|
||||
IX_NPEDL_MAJOR_FROM_IMAGEID_GET(imageId);
|
||||
ixNpeDlNpeState[npeId].imageId.minor =
|
||||
IX_NPEDL_MINOR_FROM_IMAGEID_GET(imageId);
|
||||
} /* end of if(IX_SUCCESS) */ /* condition: image located successfully in microcode image */
|
||||
} /* end of if-else(npeId-deviceId) */ /* condition: parameter checks ok */
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlNpeInitAndStartInternal : "
|
||||
"status = %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlCustomImageNpeInitAndStart
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixNpeDlCustomImageNpeInitAndStart (UINT32 *imageLibrary,
|
||||
UINT32 imageId)
|
||||
{
|
||||
IX_STATUS status;
|
||||
|
||||
if (imageLibrary == NULL)
|
||||
{
|
||||
status = IX_NPEDL_PARAM_ERR;
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlCustomImageNpeInitAndStart "
|
||||
"- invalid parameter\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ixNpeDlNpeInitAndStartInternal (imageLibrary, imageId);
|
||||
} /* end of if-else(imageLibrary) */
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeInitAndStart
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixNpeDlNpeInitAndStart (UINT32 imageId)
|
||||
{
|
||||
return ixNpeDlNpeInitAndStartInternal (NULL, imageId);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlLoadedImageFunctionalityGet
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixNpeDlLoadedImageFunctionalityGet (IxNpeDlNpeId npeId,
|
||||
UINT8 *functionalityId)
|
||||
{
|
||||
/* Check input parameters */
|
||||
if ((npeId >= IX_NPEDL_NPEID_MAX) || (npeId < 0))
|
||||
{
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlLoadedImageFunctionalityGet "
|
||||
"- invalid parameter\n");
|
||||
return IX_NPEDL_PARAM_ERR;
|
||||
}
|
||||
if (functionalityId == NULL)
|
||||
{
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlLoadedImageFunctionalityGet "
|
||||
"- invalid parameter\n");
|
||||
return IX_NPEDL_PARAM_ERR;
|
||||
}
|
||||
|
||||
if (ixNpeDlNpeState[npeId].validImage)
|
||||
{
|
||||
*functionalityId = ixNpeDlNpeState[npeId].imageId.functionalityId;
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return IX_FAIL;
|
||||
}
|
||||
}
|
675
cpu/ixp/npe/IxNpeDlImageMgr.c
Normal file
675
cpu/ixp/npe/IxNpeDlImageMgr.c
Normal file
@ -0,0 +1,675 @@
|
||||
/**
|
||||
* @file IxNpeDlImageMgr.c
|
||||
*
|
||||
* @author Intel Corporation
|
||||
* @date 09 January 2002
|
||||
*
|
||||
* @brief This file contains the implementation of the private API for the
|
||||
* IXP425 NPE Downloader ImageMgr module
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Put the system defined include files required.
|
||||
*/
|
||||
#include "IxOsal.h"
|
||||
|
||||
/*
|
||||
* Put the user defined include files required.
|
||||
*/
|
||||
#include "IxNpeDlImageMgr_p.h"
|
||||
#include "IxNpeDlMacros_p.h"
|
||||
|
||||
/*
|
||||
* define the flag which toggles the firmare inclusion
|
||||
*/
|
||||
#define IX_NPE_MICROCODE_FIRMWARE_INCLUDED 1
|
||||
#include "IxNpeMicrocode.h"
|
||||
|
||||
/*
|
||||
* Indicates the start of an NPE Image, in new NPE Image Library format.
|
||||
* 2 consecutive occurances indicates the end of the NPE Image Library
|
||||
*/
|
||||
#define NPE_IMAGE_MARKER 0xfeedf00d
|
||||
|
||||
/*
|
||||
* Typedefs whose scope is limited to this file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* FOR BACKWARD-COMPATIBILITY WITH OLD NPE IMAGE LIBRARY FORMAT
|
||||
* TO BE DEPRECATED IN A FUTURE RELEASE
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UINT32 size;
|
||||
UINT32 offset;
|
||||
UINT32 id;
|
||||
} IxNpeDlImageMgrImageEntry;
|
||||
|
||||
/*
|
||||
* FOR BACKWARD-COMPATIBILITY WITH OLD NPE IMAGE LIBRARY FORMAT
|
||||
* TO BE DEPRECATED IN A FUTURE RELEASE
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
IxNpeDlImageMgrImageEntry image;
|
||||
UINT32 eohMarker;
|
||||
} IxNpeDlImageMgrHeaderEntry;
|
||||
|
||||
/*
|
||||
* FOR BACKWARD-COMPATIBILITY WITH OLD NPE IMAGE LIBRARY FORMAT
|
||||
* TO BE DEPRECATED IN A FUTURE RELEASE
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UINT32 signature;
|
||||
/* 1st entry in the header (there may be more than one) */
|
||||
IxNpeDlImageMgrHeaderEntry entry[1];
|
||||
} IxNpeDlImageMgrImageLibraryHeader;
|
||||
|
||||
|
||||
/*
|
||||
* NPE Image Header definition, used in new NPE Image Library format
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UINT32 marker;
|
||||
UINT32 id;
|
||||
UINT32 size;
|
||||
} IxNpeDlImageMgrImageHeader;
|
||||
|
||||
/* module statistics counters */
|
||||
typedef struct
|
||||
{
|
||||
UINT32 invalidSignature;
|
||||
UINT32 imageIdListOverflow;
|
||||
UINT32 imageIdNotFound;
|
||||
} IxNpeDlImageMgrStats;
|
||||
|
||||
|
||||
/*
|
||||
* Variable declarations global to this file only. Externs are followed by
|
||||
* static variables.
|
||||
*/
|
||||
static IxNpeDlImageMgrStats ixNpeDlImageMgrStats;
|
||||
|
||||
/* default image */
|
||||
#ifdef IX_NPEDL_READ_MICROCODE_FROM_FILE
|
||||
static UINT32 *IxNpeMicroCodeImageLibrary = NULL; /* Gets set to proper value at runtime */
|
||||
#else
|
||||
static UINT32 *IxNpeMicroCodeImageLibrary = (UINT32 *)IxNpeMicrocode_array;
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* static function prototypes.
|
||||
*/
|
||||
PRIVATE BOOL
|
||||
ixNpeDlImageMgrSignatureCheck (UINT32 *microCodeImageLibrary);
|
||||
|
||||
PRIVATE void
|
||||
ixNpeDlImageMgrImageIdFormat (UINT32 rawImageId, IxNpeDlImageId *imageId);
|
||||
|
||||
PRIVATE BOOL
|
||||
ixNpeDlImageMgrImageIdCompare (IxNpeDlImageId *imageIdA,
|
||||
IxNpeDlImageId *imageIdB);
|
||||
|
||||
PRIVATE BOOL
|
||||
ixNpeDlImageMgrNpeFunctionIdCompare (IxNpeDlImageId *imageIdA,
|
||||
IxNpeDlImageId *imageIdB);
|
||||
|
||||
PRIVATE IX_STATUS
|
||||
ixNpeDlImageMgrImageFind_legacy (UINT32 *imageLibrary,
|
||||
UINT32 imageId,
|
||||
UINT32 **imagePtr,
|
||||
UINT32 *imageSize);
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlImageMgrMicrocodeImageLibraryOverride
|
||||
*
|
||||
* FOR BACKWARD-COMPATIBILITY WITH OLD NPE IMAGE LIBRARY FORMAT
|
||||
* AND/OR LEGACY API FUNCTIONS. TO BE DEPRECATED IN A FUTURE RELEASE
|
||||
*/
|
||||
IX_STATUS
|
||||
ixNpeDlImageMgrMicrocodeImageLibraryOverride (
|
||||
UINT32 *clientImageLibrary)
|
||||
{
|
||||
IX_STATUS status = IX_SUCCESS;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlImageMgrMicrocodeImageLibraryOverride\n");
|
||||
|
||||
if (ixNpeDlImageMgrSignatureCheck (clientImageLibrary))
|
||||
{
|
||||
IxNpeMicroCodeImageLibrary = clientImageLibrary;
|
||||
}
|
||||
else
|
||||
{
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlImageMgrMicrocodeImageLibraryOverride: "
|
||||
"Client-supplied image has invalid signature\n");
|
||||
status = IX_FAIL;
|
||||
}
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlImageMgrMicrocodeImageLibraryOverride: status = %d\n",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlImageMgrImageListExtract
|
||||
*
|
||||
* FOR BACKWARD-COMPATIBILITY WITH OLD NPE IMAGE LIBRARY FORMAT
|
||||
* AND/OR LEGACY API FUNCTIONS. TO BE DEPRECATED IN A FUTURE RELEASE
|
||||
*/
|
||||
IX_STATUS
|
||||
ixNpeDlImageMgrImageListExtract (
|
||||
IxNpeDlImageId *imageListPtr,
|
||||
UINT32 *numImages)
|
||||
{
|
||||
UINT32 rawImageId;
|
||||
IxNpeDlImageId formattedImageId;
|
||||
IX_STATUS status = IX_SUCCESS;
|
||||
UINT32 imageCount = 0;
|
||||
IxNpeDlImageMgrImageLibraryHeader *header;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlImageMgrImageListExtract\n");
|
||||
|
||||
header = (IxNpeDlImageMgrImageLibraryHeader *) IxNpeMicroCodeImageLibrary;
|
||||
|
||||
if (ixNpeDlImageMgrSignatureCheck (IxNpeMicroCodeImageLibrary))
|
||||
{
|
||||
/* for each image entry in the image header ... */
|
||||
while (header->entry[imageCount].eohMarker !=
|
||||
IX_NPEDL_IMAGEMGR_END_OF_HEADER)
|
||||
{
|
||||
/*
|
||||
* if the image list container from calling function has capacity,
|
||||
* add the image id to the list
|
||||
*/
|
||||
if ((imageListPtr != NULL) && (imageCount < *numImages))
|
||||
{
|
||||
rawImageId = header->entry[imageCount].image.id;
|
||||
ixNpeDlImageMgrImageIdFormat (rawImageId, &formattedImageId);
|
||||
imageListPtr[imageCount] = formattedImageId;
|
||||
}
|
||||
/* imageCount reflects no. of image entries in image library header */
|
||||
imageCount++;
|
||||
}
|
||||
|
||||
/*
|
||||
* if image list container from calling function was too small to
|
||||
* contain all image ids in the header, set return status to FAIL
|
||||
*/
|
||||
if ((imageListPtr != NULL) && (imageCount > *numImages))
|
||||
{
|
||||
status = IX_FAIL;
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlImageMgrImageListExtract: "
|
||||
"number of Ids found exceeds list capacity\n");
|
||||
ixNpeDlImageMgrStats.imageIdListOverflow++;
|
||||
}
|
||||
/* return number of image ids found in image library header */
|
||||
*numImages = imageCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = IX_FAIL;
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlImageMgrImageListExtract: "
|
||||
"invalid signature in image\n");
|
||||
}
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlImageMgrImageListExtract: status = %d\n",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlImageMgrImageLocate
|
||||
*
|
||||
* FOR BACKWARD-COMPATIBILITY WITH OLD NPE IMAGE LIBRARY FORMAT
|
||||
* AND/OR LEGACY API FUNCTIONS. TO BE DEPRECATED IN A FUTURE RELEASE
|
||||
*/
|
||||
IX_STATUS
|
||||
ixNpeDlImageMgrImageLocate (
|
||||
IxNpeDlImageId *imageId,
|
||||
UINT32 **imagePtr,
|
||||
UINT32 *imageSize)
|
||||
{
|
||||
UINT32 imageOffset;
|
||||
UINT32 rawImageId;
|
||||
IxNpeDlImageId formattedImageId;
|
||||
/* used to index image entries in image library header */
|
||||
UINT32 imageCount = 0;
|
||||
IX_STATUS status = IX_FAIL;
|
||||
IxNpeDlImageMgrImageLibraryHeader *header;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlImageMgrImageLocate\n");
|
||||
|
||||
header = (IxNpeDlImageMgrImageLibraryHeader *) IxNpeMicroCodeImageLibrary;
|
||||
|
||||
if (ixNpeDlImageMgrSignatureCheck (IxNpeMicroCodeImageLibrary))
|
||||
{
|
||||
/* for each image entry in the image library header ... */
|
||||
while (header->entry[imageCount].eohMarker !=
|
||||
IX_NPEDL_IMAGEMGR_END_OF_HEADER)
|
||||
{
|
||||
rawImageId = header->entry[imageCount].image.id;
|
||||
ixNpeDlImageMgrImageIdFormat (rawImageId, &formattedImageId);
|
||||
/* if a match for imageId is found in the image library header... */
|
||||
if (ixNpeDlImageMgrImageIdCompare (imageId, &formattedImageId))
|
||||
{
|
||||
/*
|
||||
* get pointer to the image in the image library using offset from
|
||||
* 1st word in image library
|
||||
*/
|
||||
imageOffset = header->entry[imageCount].image.offset;
|
||||
*imagePtr = &IxNpeMicroCodeImageLibrary[imageOffset];
|
||||
/* get the image size */
|
||||
*imageSize = header->entry[imageCount].image.size;
|
||||
status = IX_SUCCESS;
|
||||
break;
|
||||
}
|
||||
imageCount++;
|
||||
}
|
||||
if (status != IX_SUCCESS)
|
||||
{
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlImageMgrImageLocate: "
|
||||
"imageId not found in image library header\n");
|
||||
ixNpeDlImageMgrStats.imageIdNotFound++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlImageMgrImageLocate: "
|
||||
"invalid signature in image library\n");
|
||||
}
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlImageMgrImageLocate: status = %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlImageMgrLatestImageExtract
|
||||
*
|
||||
* FOR BACKWARD-COMPATIBILITY WITH OLD NPE IMAGE LIBRARY FORMAT
|
||||
* AND/OR LEGACY API FUNCTIONS. TO BE DEPRECATED IN A FUTURE RELEASE
|
||||
*/
|
||||
IX_STATUS
|
||||
ixNpeDlImageMgrLatestImageExtract (IxNpeDlImageId *imageId)
|
||||
{
|
||||
UINT32 imageCount = 0;
|
||||
UINT32 rawImageId;
|
||||
IxNpeDlImageId formattedImageId;
|
||||
IX_STATUS status = IX_FAIL;
|
||||
IxNpeDlImageMgrImageLibraryHeader *header;
|
||||
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlImageMgrLatestImageExtract\n");
|
||||
|
||||
header = (IxNpeDlImageMgrImageLibraryHeader *) IxNpeMicroCodeImageLibrary;
|
||||
|
||||
if (ixNpeDlImageMgrSignatureCheck (IxNpeMicroCodeImageLibrary))
|
||||
{
|
||||
/* for each image entry in the image library header ... */
|
||||
while (header->entry[imageCount].eohMarker !=
|
||||
IX_NPEDL_IMAGEMGR_END_OF_HEADER)
|
||||
{
|
||||
rawImageId = header->entry[imageCount].image.id;
|
||||
ixNpeDlImageMgrImageIdFormat (rawImageId, &formattedImageId);
|
||||
/*
|
||||
* if a match for the npe Id and functionality Id of the imageId is
|
||||
* found in the image library header...
|
||||
*/
|
||||
if(ixNpeDlImageMgrNpeFunctionIdCompare(imageId, &formattedImageId))
|
||||
{
|
||||
if(imageId->major <= formattedImageId.major)
|
||||
{
|
||||
if(imageId->minor < formattedImageId.minor)
|
||||
{
|
||||
imageId->minor = formattedImageId.minor;
|
||||
}
|
||||
imageId->major = formattedImageId.major;
|
||||
}
|
||||
status = IX_SUCCESS;
|
||||
}
|
||||
imageCount++;
|
||||
}
|
||||
if (status != IX_SUCCESS)
|
||||
{
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlImageMgrLatestImageExtract: "
|
||||
"imageId not found in image library header\n");
|
||||
ixNpeDlImageMgrStats.imageIdNotFound++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlImageMgrLatestImageGet: "
|
||||
"invalid signature in image library\n");
|
||||
}
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlImageMgrLatestImageGet: status = %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlImageMgrSignatureCheck
|
||||
*
|
||||
* FOR BACKWARD-COMPATIBILITY WITH OLD NPE IMAGE LIBRARY FORMAT
|
||||
* AND/OR LEGACY API FUNCTIONS. TO BE DEPRECATED IN A FUTURE RELEASE
|
||||
*/
|
||||
PRIVATE BOOL
|
||||
ixNpeDlImageMgrSignatureCheck (UINT32 *microCodeImageLibrary)
|
||||
{
|
||||
IxNpeDlImageMgrImageLibraryHeader *header =
|
||||
(IxNpeDlImageMgrImageLibraryHeader *) microCodeImageLibrary;
|
||||
BOOL result = TRUE;
|
||||
|
||||
if (header->signature != IX_NPEDL_IMAGEMGR_SIGNATURE)
|
||||
{
|
||||
result = FALSE;
|
||||
ixNpeDlImageMgrStats.invalidSignature++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlImageMgrImageIdFormat
|
||||
*
|
||||
* FOR BACKWARD-COMPATIBILITY WITH OLD NPE IMAGE LIBRARY FORMAT
|
||||
* AND/OR LEGACY API FUNCTIONS. TO BE DEPRECATED IN A FUTURE RELEASE
|
||||
*/
|
||||
PRIVATE void
|
||||
ixNpeDlImageMgrImageIdFormat (
|
||||
UINT32 rawImageId,
|
||||
IxNpeDlImageId *imageId)
|
||||
{
|
||||
imageId->npeId = (rawImageId >>
|
||||
IX_NPEDL_IMAGEID_NPEID_OFFSET) &
|
||||
IX_NPEDL_NPEIMAGE_FIELD_MASK;
|
||||
imageId->functionalityId = (rawImageId >>
|
||||
IX_NPEDL_IMAGEID_FUNCTIONID_OFFSET) &
|
||||
IX_NPEDL_NPEIMAGE_FIELD_MASK;
|
||||
imageId->major = (rawImageId >>
|
||||
IX_NPEDL_IMAGEID_MAJOR_OFFSET) &
|
||||
IX_NPEDL_NPEIMAGE_FIELD_MASK;
|
||||
imageId->minor = (rawImageId >>
|
||||
IX_NPEDL_IMAGEID_MINOR_OFFSET) &
|
||||
IX_NPEDL_NPEIMAGE_FIELD_MASK;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlImageMgrImageIdCompare
|
||||
*
|
||||
* FOR BACKWARD-COMPATIBILITY WITH OLD NPE IMAGE LIBRARY FORMAT
|
||||
* AND/OR LEGACY API FUNCTIONS. TO BE DEPRECATED IN A FUTURE RELEASE
|
||||
*/
|
||||
PRIVATE BOOL
|
||||
ixNpeDlImageMgrImageIdCompare (
|
||||
IxNpeDlImageId *imageIdA,
|
||||
IxNpeDlImageId *imageIdB)
|
||||
{
|
||||
if ((imageIdA->npeId == imageIdB->npeId) &&
|
||||
(imageIdA->functionalityId == imageIdB->functionalityId) &&
|
||||
(imageIdA->major == imageIdB->major) &&
|
||||
(imageIdA->minor == imageIdB->minor))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlImageMgrNpeFunctionIdCompare
|
||||
*
|
||||
* FOR BACKWARD-COMPATIBILITY WITH OLD NPE IMAGE LIBRARY FORMAT
|
||||
* AND/OR LEGACY API FUNCTIONS. TO BE DEPRECATED IN A FUTURE RELEASE
|
||||
*/
|
||||
PRIVATE BOOL
|
||||
ixNpeDlImageMgrNpeFunctionIdCompare (
|
||||
IxNpeDlImageId *imageIdA,
|
||||
IxNpeDlImageId *imageIdB)
|
||||
{
|
||||
if ((imageIdA->npeId == imageIdB->npeId) &&
|
||||
(imageIdA->functionalityId == imageIdB->functionalityId))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlImageMgrStatsShow
|
||||
*/
|
||||
void
|
||||
ixNpeDlImageMgrStatsShow (void)
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_USER,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"\nixNpeDlImageMgrStatsShow:\n"
|
||||
"\tInvalid Image Signatures: %u\n"
|
||||
"\tImage Id List capacity too small: %u\n"
|
||||
"\tImage Id not found: %u\n\n",
|
||||
ixNpeDlImageMgrStats.invalidSignature,
|
||||
ixNpeDlImageMgrStats.imageIdListOverflow,
|
||||
ixNpeDlImageMgrStats.imageIdNotFound,
|
||||
0,0,0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlImageMgrStatsReset
|
||||
*/
|
||||
void
|
||||
ixNpeDlImageMgrStatsReset (void)
|
||||
{
|
||||
ixNpeDlImageMgrStats.invalidSignature = 0;
|
||||
ixNpeDlImageMgrStats.imageIdListOverflow = 0;
|
||||
ixNpeDlImageMgrStats.imageIdNotFound = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlImageMgrImageFind_legacy
|
||||
*
|
||||
* FOR BACKWARD-COMPATIBILITY WITH OLD NPE IMAGE LIBRARY FORMAT
|
||||
* AND/OR LEGACY API FUNCTIONS. TO BE DEPRECATED IN A FUTURE RELEASE
|
||||
*/
|
||||
PRIVATE IX_STATUS
|
||||
ixNpeDlImageMgrImageFind_legacy (
|
||||
UINT32 *imageLibrary,
|
||||
UINT32 imageId,
|
||||
UINT32 **imagePtr,
|
||||
UINT32 *imageSize)
|
||||
{
|
||||
UINT32 imageOffset;
|
||||
/* used to index image entries in image library header */
|
||||
UINT32 imageCount = 0;
|
||||
IX_STATUS status = IX_FAIL;
|
||||
IxNpeDlImageMgrImageLibraryHeader *header;
|
||||
BOOL imageFound = FALSE;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlImageMgrImageFind\n");
|
||||
|
||||
|
||||
/* If user didn't specify a library to use, use the default
|
||||
* one from IxNpeMicrocode.h
|
||||
*/
|
||||
if (imageLibrary == NULL)
|
||||
{
|
||||
imageLibrary = IxNpeMicroCodeImageLibrary;
|
||||
}
|
||||
|
||||
if (ixNpeDlImageMgrSignatureCheck (imageLibrary))
|
||||
{
|
||||
header = (IxNpeDlImageMgrImageLibraryHeader *) imageLibrary;
|
||||
|
||||
/* for each image entry in the image library header ... */
|
||||
while ((header->entry[imageCount].eohMarker !=
|
||||
IX_NPEDL_IMAGEMGR_END_OF_HEADER) && !(imageFound))
|
||||
{
|
||||
/* if a match for imageId is found in the image library header... */
|
||||
if (imageId == header->entry[imageCount].image.id)
|
||||
{
|
||||
/*
|
||||
* get pointer to the image in the image library using offset from
|
||||
* 1st word in image library
|
||||
*/
|
||||
imageOffset = header->entry[imageCount].image.offset;
|
||||
*imagePtr = &imageLibrary[imageOffset];
|
||||
/* get the image size */
|
||||
*imageSize = header->entry[imageCount].image.size;
|
||||
status = IX_SUCCESS;
|
||||
imageFound = TRUE;
|
||||
}
|
||||
imageCount++;
|
||||
}
|
||||
if (status != IX_SUCCESS)
|
||||
{
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlImageMgrImageFind: "
|
||||
"imageId not found in image library header\n");
|
||||
ixNpeDlImageMgrStats.imageIdNotFound++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlImageMgrImageFind: "
|
||||
"invalid signature in image library\n");
|
||||
}
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlImageMgrImageFind: status = %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlImageMgrImageFind
|
||||
*/
|
||||
IX_STATUS
|
||||
ixNpeDlImageMgrImageFind (
|
||||
UINT32 *imageLibrary,
|
||||
UINT32 imageId,
|
||||
UINT32 **imagePtr,
|
||||
UINT32 *imageSize)
|
||||
{
|
||||
IxNpeDlImageMgrImageHeader *image;
|
||||
UINT32 offset = 0;
|
||||
|
||||
/* If user didn't specify a library to use, use the default
|
||||
* one from IxNpeMicrocode.h
|
||||
*/
|
||||
if (imageLibrary == NULL)
|
||||
{
|
||||
#ifdef IX_NPEDL_READ_MICROCODE_FROM_FILE
|
||||
if (ixNpeMicrocode_binaryArray == NULL)
|
||||
{
|
||||
printk (KERN_ERR "ixp400.o: ERROR, no Microcode found in memory\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
imageLibrary = ixNpeMicrocode_binaryArray;
|
||||
}
|
||||
#else
|
||||
imageLibrary = IxNpeMicroCodeImageLibrary;
|
||||
#endif /* IX_NPEDL_READ_MICROCODE_FROM_FILE */
|
||||
}
|
||||
|
||||
/* For backward's compatibility with previous image format */
|
||||
if (ixNpeDlImageMgrSignatureCheck(imageLibrary))
|
||||
{
|
||||
return ixNpeDlImageMgrImageFind_legacy(imageLibrary,
|
||||
imageId,
|
||||
imagePtr,
|
||||
imageSize);
|
||||
}
|
||||
|
||||
while (*(imageLibrary+offset) == NPE_IMAGE_MARKER)
|
||||
{
|
||||
image = (IxNpeDlImageMgrImageHeader *)(imageLibrary+offset);
|
||||
offset += sizeof(IxNpeDlImageMgrImageHeader)/sizeof(UINT32);
|
||||
|
||||
if (image->id == imageId)
|
||||
{
|
||||
*imagePtr = imageLibrary + offset;
|
||||
*imageSize = image->size;
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
/* 2 consecutive NPE_IMAGE_MARKER's indicates end of library */
|
||||
else if (image->id == NPE_IMAGE_MARKER)
|
||||
{
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlImageMgrImageFind: "
|
||||
"imageId not found in image library header\n");
|
||||
ixNpeDlImageMgrStats.imageIdNotFound++;
|
||||
/* reached end of library, image not found */
|
||||
return IX_FAIL;
|
||||
}
|
||||
offset += image->size;
|
||||
}
|
||||
|
||||
/* If we get here, our image library may be corrupted */
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlImageMgrImageFind: "
|
||||
"image library format may be invalid or corrupted\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
936
cpu/ixp/npe/IxNpeDlNpeMgr.c
Normal file
936
cpu/ixp/npe/IxNpeDlNpeMgr.c
Normal file
@ -0,0 +1,936 @@
|
||||
/**
|
||||
* @file IxNpeDlNpeMgr.c
|
||||
*
|
||||
* @author Intel Corporation
|
||||
* @date 09 January 2002
|
||||
*
|
||||
* @brief This file contains the implementation of the private API for the
|
||||
* IXP425 NPE Downloader NpeMgr module
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Put the user defined include files required.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Put the user defined include files required.
|
||||
*/
|
||||
#include "IxOsal.h"
|
||||
#include "IxNpeDl.h"
|
||||
#include "IxNpeDlNpeMgr_p.h"
|
||||
#include "IxNpeDlNpeMgrUtils_p.h"
|
||||
#include "IxNpeDlNpeMgrEcRegisters_p.h"
|
||||
#include "IxNpeDlMacros_p.h"
|
||||
#include "IxFeatureCtrl.h"
|
||||
|
||||
/*
|
||||
* #defines and macros used in this file.
|
||||
*/
|
||||
#define IX_NPEDL_BYTES_PER_WORD 4
|
||||
|
||||
/* used to read download map from version in microcode image */
|
||||
#define IX_NPEDL_BLOCK_TYPE_INSTRUCTION 0x00000000
|
||||
#define IX_NPEDL_BLOCK_TYPE_DATA 0x00000001
|
||||
#define IX_NPEDL_BLOCK_TYPE_STATE 0x00000002
|
||||
#define IX_NPEDL_END_OF_DOWNLOAD_MAP 0x0000000F
|
||||
|
||||
/*
|
||||
* masks used to extract address info from State information context
|
||||
* register addresses as read from microcode image
|
||||
*/
|
||||
#define IX_NPEDL_MASK_STATE_ADDR_CTXT_REG 0x0000000F
|
||||
#define IX_NPEDL_MASK_STATE_ADDR_CTXT_NUM 0x000000F0
|
||||
|
||||
/* LSB offset of Context Number field in State-Info Context Address */
|
||||
#define IX_NPEDL_OFFSET_STATE_ADDR_CTXT_NUM 4
|
||||
|
||||
/* size (in words) of single State Information entry (ctxt reg address|data) */
|
||||
#define IX_NPEDL_STATE_INFO_ENTRY_SIZE 2
|
||||
|
||||
|
||||
#define IX_NPEDL_RESET_NPE_PARITY 0x0800
|
||||
#define IX_NPEDL_PARITY_BIT_MASK 0x3F00FFFF
|
||||
#define IX_NPEDL_CONFIG_CTRL_REG_MASK 0x3F3FFFFF
|
||||
|
||||
|
||||
/*
|
||||
* Typedefs whose scope is limited to this file.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 type;
|
||||
UINT32 offset;
|
||||
} IxNpeDlNpeMgrDownloadMapBlockEntry;
|
||||
|
||||
typedef union
|
||||
{
|
||||
IxNpeDlNpeMgrDownloadMapBlockEntry block;
|
||||
UINT32 eodmMarker;
|
||||
} IxNpeDlNpeMgrDownloadMapEntry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* 1st entry in the download map (there may be more than one) */
|
||||
IxNpeDlNpeMgrDownloadMapEntry entry[1];
|
||||
} IxNpeDlNpeMgrDownloadMap;
|
||||
|
||||
|
||||
/* used to access an instruction or data block in a microcode image */
|
||||
typedef struct
|
||||
{
|
||||
UINT32 npeMemAddress;
|
||||
UINT32 size;
|
||||
UINT32 data[1];
|
||||
} IxNpeDlNpeMgrCodeBlock;
|
||||
|
||||
/* used to access each Context Reg entry state-information block */
|
||||
typedef struct
|
||||
{
|
||||
UINT32 addressInfo;
|
||||
UINT32 value;
|
||||
} IxNpeDlNpeMgrStateInfoCtxtRegEntry;
|
||||
|
||||
/* used to access a state-information block in a microcode image */
|
||||
typedef struct
|
||||
{
|
||||
UINT32 size;
|
||||
IxNpeDlNpeMgrStateInfoCtxtRegEntry ctxtRegEntry[1];
|
||||
} IxNpeDlNpeMgrStateInfoBlock;
|
||||
|
||||
/* used to store some useful NPE information for easy access */
|
||||
typedef struct
|
||||
{
|
||||
UINT32 baseAddress;
|
||||
UINT32 insMemSize;
|
||||
UINT32 dataMemSize;
|
||||
} IxNpeDlNpeInfo;
|
||||
|
||||
/* used to distinguish instruction and data memory operations */
|
||||
typedef enum
|
||||
{
|
||||
IX_NPEDL_MEM_TYPE_INSTRUCTION = 0,
|
||||
IX_NPEDL_MEM_TYPE_DATA
|
||||
} IxNpeDlNpeMemType;
|
||||
|
||||
/* used to hold a reset value for a particular ECS register */
|
||||
typedef struct
|
||||
{
|
||||
UINT32 regAddr;
|
||||
UINT32 regResetVal;
|
||||
} IxNpeDlEcsRegResetValue;
|
||||
|
||||
/* prototype of function to write either Instruction or Data memory */
|
||||
typedef IX_STATUS (*IxNpeDlNpeMgrMemWrite) (UINT32 npeBaseAddress,
|
||||
UINT32 npeMemAddress,
|
||||
UINT32 npeMemData,
|
||||
BOOL verify);
|
||||
|
||||
/* module statistics counters */
|
||||
typedef struct
|
||||
{
|
||||
UINT32 instructionBlocksLoaded;
|
||||
UINT32 dataBlocksLoaded;
|
||||
UINT32 stateInfoBlocksLoaded;
|
||||
UINT32 criticalNpeErrors;
|
||||
UINT32 criticalMicrocodeErrors;
|
||||
UINT32 npeStarts;
|
||||
UINT32 npeStops;
|
||||
UINT32 npeResets;
|
||||
} IxNpeDlNpeMgrStats;
|
||||
|
||||
|
||||
/*
|
||||
* Variable declarations global to this file only. Externs are followed by
|
||||
* static variables.
|
||||
*/
|
||||
static IxNpeDlNpeInfo ixNpeDlNpeInfo[] =
|
||||
{
|
||||
{
|
||||
0,
|
||||
IX_NPEDL_INS_MEMSIZE_WORDS_NPEA,
|
||||
IX_NPEDL_DATA_MEMSIZE_WORDS_NPEA
|
||||
},
|
||||
{
|
||||
0,
|
||||
IX_NPEDL_INS_MEMSIZE_WORDS_NPEB,
|
||||
IX_NPEDL_DATA_MEMSIZE_WORDS_NPEB
|
||||
},
|
||||
{
|
||||
0,
|
||||
IX_NPEDL_INS_MEMSIZE_WORDS_NPEC,
|
||||
IX_NPEDL_DATA_MEMSIZE_WORDS_NPEC
|
||||
}
|
||||
};
|
||||
|
||||
/* contains Reset values for Context Store Registers */
|
||||
static UINT32 ixNpeDlCtxtRegResetValues[] =
|
||||
{
|
||||
IX_NPEDL_CTXT_REG_RESET_STEVT,
|
||||
IX_NPEDL_CTXT_REG_RESET_STARTPC,
|
||||
IX_NPEDL_CTXT_REG_RESET_REGMAP,
|
||||
IX_NPEDL_CTXT_REG_RESET_CINDEX,
|
||||
};
|
||||
|
||||
/* contains Reset values for Context Store Registers */
|
||||
static IxNpeDlEcsRegResetValue ixNpeDlEcsRegResetValues[] =
|
||||
{
|
||||
{IX_NPEDL_ECS_BG_CTXT_REG_0, IX_NPEDL_ECS_BG_CTXT_REG_0_RESET},
|
||||
{IX_NPEDL_ECS_BG_CTXT_REG_1, IX_NPEDL_ECS_BG_CTXT_REG_1_RESET},
|
||||
{IX_NPEDL_ECS_BG_CTXT_REG_2, IX_NPEDL_ECS_BG_CTXT_REG_2_RESET},
|
||||
{IX_NPEDL_ECS_PRI_1_CTXT_REG_0, IX_NPEDL_ECS_PRI_1_CTXT_REG_0_RESET},
|
||||
{IX_NPEDL_ECS_PRI_1_CTXT_REG_1, IX_NPEDL_ECS_PRI_1_CTXT_REG_1_RESET},
|
||||
{IX_NPEDL_ECS_PRI_1_CTXT_REG_2, IX_NPEDL_ECS_PRI_1_CTXT_REG_2_RESET},
|
||||
{IX_NPEDL_ECS_PRI_2_CTXT_REG_0, IX_NPEDL_ECS_PRI_2_CTXT_REG_0_RESET},
|
||||
{IX_NPEDL_ECS_PRI_2_CTXT_REG_1, IX_NPEDL_ECS_PRI_2_CTXT_REG_1_RESET},
|
||||
{IX_NPEDL_ECS_PRI_2_CTXT_REG_2, IX_NPEDL_ECS_PRI_2_CTXT_REG_2_RESET},
|
||||
{IX_NPEDL_ECS_DBG_CTXT_REG_0, IX_NPEDL_ECS_DBG_CTXT_REG_0_RESET},
|
||||
{IX_NPEDL_ECS_DBG_CTXT_REG_1, IX_NPEDL_ECS_DBG_CTXT_REG_1_RESET},
|
||||
{IX_NPEDL_ECS_DBG_CTXT_REG_2, IX_NPEDL_ECS_DBG_CTXT_REG_2_RESET},
|
||||
{IX_NPEDL_ECS_INSTRUCT_REG, IX_NPEDL_ECS_INSTRUCT_REG_RESET}
|
||||
};
|
||||
|
||||
static IxNpeDlNpeMgrStats ixNpeDlNpeMgrStats;
|
||||
|
||||
/* Set when NPE register memory has been mapped */
|
||||
static BOOL ixNpeDlMemInitialised = FALSE;
|
||||
|
||||
|
||||
/*
|
||||
* static function prototypes.
|
||||
*/
|
||||
PRIVATE IX_STATUS
|
||||
ixNpeDlNpeMgrMemLoad (IxNpeDlNpeId npeId, UINT32 npeBaseAddress,
|
||||
IxNpeDlNpeMgrCodeBlock *codeBlockPtr,
|
||||
BOOL verify, IxNpeDlNpeMemType npeMemType);
|
||||
PRIVATE IX_STATUS
|
||||
ixNpeDlNpeMgrStateInfoLoad (UINT32 npeBaseAddress,
|
||||
IxNpeDlNpeMgrStateInfoBlock *codeBlockPtr,
|
||||
BOOL verify);
|
||||
PRIVATE BOOL
|
||||
ixNpeDlNpeMgrBitsSetCheck (UINT32 npeBaseAddress, UINT32 regOffset,
|
||||
UINT32 expectedBitsSet);
|
||||
|
||||
PRIVATE UINT32
|
||||
ixNpeDlNpeMgrBaseAddressGet (IxNpeDlNpeId npeId);
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrBaseAddressGet
|
||||
*/
|
||||
PRIVATE UINT32
|
||||
ixNpeDlNpeMgrBaseAddressGet (IxNpeDlNpeId npeId)
|
||||
{
|
||||
IX_OSAL_ASSERT (ixNpeDlMemInitialised);
|
||||
return ixNpeDlNpeInfo[npeId].baseAddress;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrInit
|
||||
*/
|
||||
void
|
||||
ixNpeDlNpeMgrInit (void)
|
||||
{
|
||||
/* Only map the memory once */
|
||||
if (!ixNpeDlMemInitialised)
|
||||
{
|
||||
UINT32 virtAddr;
|
||||
|
||||
/* map the register memory for NPE-A */
|
||||
virtAddr = (UINT32) IX_OSAL_MEM_MAP (IX_NPEDL_NPEBASEADDRESS_NPEA,
|
||||
IX_OSAL_IXP400_NPEA_MAP_SIZE);
|
||||
IX_OSAL_ASSERT(virtAddr);
|
||||
ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEA].baseAddress = virtAddr;
|
||||
|
||||
/* map the register memory for NPE-B */
|
||||
virtAddr = (UINT32) IX_OSAL_MEM_MAP (IX_NPEDL_NPEBASEADDRESS_NPEB,
|
||||
IX_OSAL_IXP400_NPEB_MAP_SIZE);
|
||||
IX_OSAL_ASSERT(virtAddr);
|
||||
ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEB].baseAddress = virtAddr;
|
||||
|
||||
/* map the register memory for NPE-C */
|
||||
virtAddr = (UINT32) IX_OSAL_MEM_MAP (IX_NPEDL_NPEBASEADDRESS_NPEC,
|
||||
IX_OSAL_IXP400_NPEC_MAP_SIZE);
|
||||
IX_OSAL_ASSERT(virtAddr);
|
||||
ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEC].baseAddress = virtAddr;
|
||||
|
||||
ixNpeDlMemInitialised = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrUninit
|
||||
*/
|
||||
IX_STATUS
|
||||
ixNpeDlNpeMgrUninit (void)
|
||||
{
|
||||
if (!ixNpeDlMemInitialised)
|
||||
{
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
IX_OSAL_MEM_UNMAP (ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEA].baseAddress);
|
||||
IX_OSAL_MEM_UNMAP (ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEB].baseAddress);
|
||||
IX_OSAL_MEM_UNMAP (ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEC].baseAddress);
|
||||
|
||||
ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEA].baseAddress = 0;
|
||||
ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEB].baseAddress = 0;
|
||||
ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEC].baseAddress = 0;
|
||||
|
||||
ixNpeDlMemInitialised = FALSE;
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrImageLoad
|
||||
*/
|
||||
IX_STATUS
|
||||
ixNpeDlNpeMgrImageLoad (
|
||||
IxNpeDlNpeId npeId,
|
||||
UINT32 *imageCodePtr,
|
||||
BOOL verify)
|
||||
{
|
||||
UINT32 npeBaseAddress;
|
||||
IxNpeDlNpeMgrDownloadMap *downloadMap;
|
||||
UINT32 *blockPtr;
|
||||
UINT32 mapIndex = 0;
|
||||
IX_STATUS status = IX_SUCCESS;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlNpeMgrImageLoad\n");
|
||||
|
||||
/* get base memory address of NPE from npeId */
|
||||
npeBaseAddress = ixNpeDlNpeMgrBaseAddressGet (npeId);
|
||||
|
||||
/* check execution status of NPE to verify NPE Stop was successful */
|
||||
if (!ixNpeDlNpeMgrBitsSetCheck (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXCTL,
|
||||
IX_NPEDL_EXCTL_STATUS_STOP))
|
||||
{
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrImageDownload - "
|
||||
"NPE was not stopped before download\n");
|
||||
status = IX_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Read Download Map, checking each block type and calling
|
||||
* appropriate function to perform download
|
||||
*/
|
||||
downloadMap = (IxNpeDlNpeMgrDownloadMap *) imageCodePtr;
|
||||
while ((downloadMap->entry[mapIndex].eodmMarker !=
|
||||
IX_NPEDL_END_OF_DOWNLOAD_MAP)
|
||||
&& (status == IX_SUCCESS))
|
||||
{
|
||||
/* calculate pointer to block to be downloaded */
|
||||
blockPtr = imageCodePtr +
|
||||
downloadMap->entry[mapIndex].block.offset;
|
||||
|
||||
switch (downloadMap->entry[mapIndex].block.type)
|
||||
{
|
||||
case IX_NPEDL_BLOCK_TYPE_INSTRUCTION:
|
||||
status = ixNpeDlNpeMgrMemLoad (npeId, npeBaseAddress,
|
||||
(IxNpeDlNpeMgrCodeBlock *)blockPtr,
|
||||
verify,
|
||||
IX_NPEDL_MEM_TYPE_INSTRUCTION);
|
||||
break;
|
||||
case IX_NPEDL_BLOCK_TYPE_DATA:
|
||||
status = ixNpeDlNpeMgrMemLoad (npeId, npeBaseAddress,
|
||||
(IxNpeDlNpeMgrCodeBlock *)blockPtr,
|
||||
verify, IX_NPEDL_MEM_TYPE_DATA);
|
||||
break;
|
||||
case IX_NPEDL_BLOCK_TYPE_STATE:
|
||||
status = ixNpeDlNpeMgrStateInfoLoad (npeBaseAddress,
|
||||
(IxNpeDlNpeMgrStateInfoBlock *) blockPtr,
|
||||
verify);
|
||||
break;
|
||||
default:
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrImageLoad: "
|
||||
"unknown block type in download map\n");
|
||||
status = IX_NPEDL_CRITICAL_MICROCODE_ERR;
|
||||
ixNpeDlNpeMgrStats.criticalMicrocodeErrors++;
|
||||
break;
|
||||
}
|
||||
mapIndex++;
|
||||
}/* loop: for each entry in download map, while status == SUCCESS */
|
||||
}/* condition: NPE stopped before attempting download */
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlNpeMgrImageLoad : status = %d\n",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrMemLoad
|
||||
*/
|
||||
PRIVATE IX_STATUS
|
||||
ixNpeDlNpeMgrMemLoad (
|
||||
IxNpeDlNpeId npeId,
|
||||
UINT32 npeBaseAddress,
|
||||
IxNpeDlNpeMgrCodeBlock *blockPtr,
|
||||
BOOL verify,
|
||||
IxNpeDlNpeMemType npeMemType)
|
||||
{
|
||||
UINT32 npeMemAddress;
|
||||
UINT32 blockSize;
|
||||
UINT32 memSize = 0;
|
||||
IxNpeDlNpeMgrMemWrite memWriteFunc = NULL;
|
||||
UINT32 localIndex = 0;
|
||||
IX_STATUS status = IX_SUCCESS;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlNpeMgrMemLoad\n");
|
||||
|
||||
/*
|
||||
* select NPE EXCTL reg read/write commands depending on memory
|
||||
* type (instruction/data) to be accessed
|
||||
*/
|
||||
if (npeMemType == IX_NPEDL_MEM_TYPE_INSTRUCTION)
|
||||
{
|
||||
memSize = ixNpeDlNpeInfo[npeId].insMemSize;
|
||||
memWriteFunc = (IxNpeDlNpeMgrMemWrite) ixNpeDlNpeMgrInsMemWrite;
|
||||
}
|
||||
else if (npeMemType == IX_NPEDL_MEM_TYPE_DATA)
|
||||
{
|
||||
memSize = ixNpeDlNpeInfo[npeId].dataMemSize;
|
||||
memWriteFunc = (IxNpeDlNpeMgrMemWrite) ixNpeDlNpeMgrDataMemWrite;
|
||||
}
|
||||
|
||||
/*
|
||||
* NPE memory is loaded contiguously from each block, so only address
|
||||
* of 1st word in block is needed
|
||||
*/
|
||||
npeMemAddress = blockPtr->npeMemAddress;
|
||||
/* number of words of instruction/data microcode in block to download */
|
||||
blockSize = blockPtr->size;
|
||||
if ((npeMemAddress + blockSize) > memSize)
|
||||
{
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrMemLoad: "
|
||||
"Block size too big for NPE memory\n");
|
||||
status = IX_NPEDL_CRITICAL_MICROCODE_ERR;
|
||||
ixNpeDlNpeMgrStats.criticalMicrocodeErrors++;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (localIndex = 0; localIndex < blockSize; localIndex++)
|
||||
{
|
||||
status = memWriteFunc (npeBaseAddress, npeMemAddress,
|
||||
blockPtr->data[localIndex], verify);
|
||||
|
||||
if (status != IX_SUCCESS)
|
||||
{
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrMemLoad: "
|
||||
"write to NPE memory failed\n");
|
||||
status = IX_NPEDL_CRITICAL_NPE_ERR;
|
||||
ixNpeDlNpeMgrStats.criticalNpeErrors++;
|
||||
break; /* abort download */
|
||||
}
|
||||
/* increment target (word)address in NPE memory */
|
||||
npeMemAddress++;
|
||||
}
|
||||
}/* condition: block size will fit in NPE memory */
|
||||
|
||||
if (status == IX_SUCCESS)
|
||||
{
|
||||
if (npeMemType == IX_NPEDL_MEM_TYPE_INSTRUCTION)
|
||||
{
|
||||
ixNpeDlNpeMgrStats.instructionBlocksLoaded++;
|
||||
}
|
||||
else if (npeMemType == IX_NPEDL_MEM_TYPE_DATA)
|
||||
{
|
||||
ixNpeDlNpeMgrStats.dataBlocksLoaded++;
|
||||
}
|
||||
}
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlNpeMgrMemLoad : status = %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrStateInfoLoad
|
||||
*/
|
||||
PRIVATE IX_STATUS
|
||||
ixNpeDlNpeMgrStateInfoLoad (
|
||||
UINT32 npeBaseAddress,
|
||||
IxNpeDlNpeMgrStateInfoBlock *blockPtr,
|
||||
BOOL verify)
|
||||
{
|
||||
UINT32 blockSize;
|
||||
UINT32 ctxtRegAddrInfo;
|
||||
UINT32 ctxtRegVal;
|
||||
IxNpeDlCtxtRegNum ctxtReg; /* identifies Context Store reg (0-3) */
|
||||
UINT32 ctxtNum; /* identifies Context number (0-16) */
|
||||
UINT32 i;
|
||||
IX_STATUS status = IX_SUCCESS;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlNpeMgrStateInfoLoad\n");
|
||||
|
||||
/* block size contains number of words of state-info in block */
|
||||
blockSize = blockPtr->size;
|
||||
|
||||
ixNpeDlNpeMgrDebugInstructionPreExec (npeBaseAddress);
|
||||
|
||||
/* for each state-info context register entry in block */
|
||||
for (i = 0; i < (blockSize/IX_NPEDL_STATE_INFO_ENTRY_SIZE); i++)
|
||||
{
|
||||
/* each state-info entry is 2 words (address, value) in length */
|
||||
ctxtRegAddrInfo = (blockPtr->ctxtRegEntry[i]).addressInfo;
|
||||
ctxtRegVal = (blockPtr->ctxtRegEntry[i]).value;
|
||||
|
||||
ctxtReg = (ctxtRegAddrInfo & IX_NPEDL_MASK_STATE_ADDR_CTXT_REG);
|
||||
ctxtNum = (ctxtRegAddrInfo & IX_NPEDL_MASK_STATE_ADDR_CTXT_NUM) >>
|
||||
IX_NPEDL_OFFSET_STATE_ADDR_CTXT_NUM;
|
||||
|
||||
/* error-check Context Register No. and Context Number values */
|
||||
/* NOTE that there is no STEVT register for Context 0 */
|
||||
if ((ctxtReg < 0) ||
|
||||
(ctxtReg >= IX_NPEDL_CTXT_REG_MAX) ||
|
||||
(ctxtNum > IX_NPEDL_CTXT_NUM_MAX) ||
|
||||
((ctxtNum == 0) && (ctxtReg == IX_NPEDL_CTXT_REG_STEVT)))
|
||||
{
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrStateInfoLoad: "
|
||||
"invalid Context Register Address\n");
|
||||
status = IX_NPEDL_CRITICAL_MICROCODE_ERR;
|
||||
ixNpeDlNpeMgrStats.criticalMicrocodeErrors++;
|
||||
break; /* abort download */
|
||||
}
|
||||
|
||||
status = ixNpeDlNpeMgrCtxtRegWrite (npeBaseAddress, ctxtNum, ctxtReg,
|
||||
ctxtRegVal, verify);
|
||||
if (status != IX_SUCCESS)
|
||||
{
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrStateInfoLoad: "
|
||||
"write of state-info to NPE failed\n");
|
||||
status = IX_NPEDL_CRITICAL_NPE_ERR;
|
||||
ixNpeDlNpeMgrStats.criticalNpeErrors++;
|
||||
break; /* abort download */
|
||||
}
|
||||
}/* loop: for each context reg entry in State Info block */
|
||||
|
||||
ixNpeDlNpeMgrDebugInstructionPostExec (npeBaseAddress);
|
||||
|
||||
if (status == IX_SUCCESS)
|
||||
{
|
||||
ixNpeDlNpeMgrStats.stateInfoBlocksLoaded++;
|
||||
}
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlNpeMgrStateInfoLoad : status = %d\n",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrNpeReset
|
||||
*/
|
||||
IX_STATUS
|
||||
ixNpeDlNpeMgrNpeReset (
|
||||
IxNpeDlNpeId npeId)
|
||||
{
|
||||
UINT32 npeBaseAddress;
|
||||
IxNpeDlCtxtRegNum ctxtReg; /* identifies Context Store reg (0-3) */
|
||||
UINT32 ctxtNum; /* identifies Context number (0-16) */
|
||||
UINT32 regAddr;
|
||||
UINT32 regVal;
|
||||
UINT32 localIndex;
|
||||
UINT32 indexMax;
|
||||
IX_STATUS status = IX_SUCCESS;
|
||||
IxFeatureCtrlReg unitFuseReg;
|
||||
UINT32 ixNpeConfigCtrlRegVal;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlNpeMgrNpeReset\n");
|
||||
|
||||
/* get base memory address of NPE from npeId */
|
||||
npeBaseAddress = ixNpeDlNpeMgrBaseAddressGet (npeId);
|
||||
|
||||
/* pre-store the NPE Config Control Register Value */
|
||||
IX_NPEDL_REG_READ (npeBaseAddress, IX_NPEDL_REG_OFFSET_CTL, &ixNpeConfigCtrlRegVal);
|
||||
|
||||
ixNpeConfigCtrlRegVal |= 0x3F000000;
|
||||
|
||||
/* disable the parity interrupt */
|
||||
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_CTL, (ixNpeConfigCtrlRegVal & IX_NPEDL_PARITY_BIT_MASK));
|
||||
|
||||
ixNpeDlNpeMgrDebugInstructionPreExec (npeBaseAddress);
|
||||
|
||||
/*
|
||||
* clear the FIFOs
|
||||
*/
|
||||
while (ixNpeDlNpeMgrBitsSetCheck (npeBaseAddress,
|
||||
IX_NPEDL_REG_OFFSET_WFIFO,
|
||||
IX_NPEDL_MASK_WFIFO_VALID))
|
||||
{
|
||||
/* read from the Watch-point FIFO until empty */
|
||||
IX_NPEDL_REG_READ (npeBaseAddress, IX_NPEDL_REG_OFFSET_WFIFO,
|
||||
®Val);
|
||||
}
|
||||
|
||||
while (ixNpeDlNpeMgrBitsSetCheck (npeBaseAddress,
|
||||
IX_NPEDL_REG_OFFSET_STAT,
|
||||
IX_NPEDL_MASK_STAT_OFNE))
|
||||
{
|
||||
/* read from the outFIFO until empty */
|
||||
IX_NPEDL_REG_READ (npeBaseAddress, IX_NPEDL_REG_OFFSET_FIFO,
|
||||
®Val);
|
||||
}
|
||||
|
||||
while (ixNpeDlNpeMgrBitsSetCheck (npeBaseAddress,
|
||||
IX_NPEDL_REG_OFFSET_STAT,
|
||||
IX_NPEDL_MASK_STAT_IFNE))
|
||||
{
|
||||
/*
|
||||
* step execution of the NPE intruction to read inFIFO using
|
||||
* the Debug Executing Context stack
|
||||
*/
|
||||
status = ixNpeDlNpeMgrDebugInstructionExec (npeBaseAddress,
|
||||
IX_NPEDL_INSTR_RD_FIFO, 0, 0);
|
||||
|
||||
if (IX_SUCCESS != status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset the mailbox reg
|
||||
*/
|
||||
/* ...from XScale side */
|
||||
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_MBST,
|
||||
IX_NPEDL_REG_RESET_MBST);
|
||||
/* ...from NPE side */
|
||||
status = ixNpeDlNpeMgrDebugInstructionExec (npeBaseAddress,
|
||||
IX_NPEDL_INSTR_RESET_MBOX, 0, 0);
|
||||
|
||||
if (IX_SUCCESS != status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset the physical registers in the NPE register file:
|
||||
* Note: no need to save/restore REGMAP for Context 0 here
|
||||
* since all Context Store regs are reset in subsequent code
|
||||
*/
|
||||
for (regAddr = 0;
|
||||
(regAddr < IX_NPEDL_TOTAL_NUM_PHYS_REG) && (status != IX_FAIL);
|
||||
regAddr++)
|
||||
{
|
||||
/* for each physical register in the NPE reg file, write 0 : */
|
||||
status = ixNpeDlNpeMgrPhysicalRegWrite (npeBaseAddress, regAddr,
|
||||
0, TRUE);
|
||||
if (status != IX_SUCCESS)
|
||||
{
|
||||
return status; /* abort reset */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reset the context store:
|
||||
*/
|
||||
for (ctxtNum = IX_NPEDL_CTXT_NUM_MIN;
|
||||
ctxtNum <= IX_NPEDL_CTXT_NUM_MAX; ctxtNum++)
|
||||
{
|
||||
/* set each context's Context Store registers to reset values: */
|
||||
for (ctxtReg = 0; ctxtReg < IX_NPEDL_CTXT_REG_MAX; ctxtReg++)
|
||||
{
|
||||
/* NOTE that there is no STEVT register for Context 0 */
|
||||
if (!((ctxtNum == 0) && (ctxtReg == IX_NPEDL_CTXT_REG_STEVT)))
|
||||
{
|
||||
regVal = ixNpeDlCtxtRegResetValues[ctxtReg];
|
||||
status = ixNpeDlNpeMgrCtxtRegWrite (npeBaseAddress, ctxtNum,
|
||||
ctxtReg, regVal, TRUE);
|
||||
if (status != IX_SUCCESS)
|
||||
{
|
||||
return status; /* abort reset */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ixNpeDlNpeMgrDebugInstructionPostExec (npeBaseAddress);
|
||||
|
||||
/* write Reset values to Execution Context Stack registers */
|
||||
indexMax = sizeof (ixNpeDlEcsRegResetValues) /
|
||||
sizeof (IxNpeDlEcsRegResetValue);
|
||||
for (localIndex = 0; localIndex < indexMax; localIndex++)
|
||||
{
|
||||
regAddr = ixNpeDlEcsRegResetValues[localIndex].regAddr;
|
||||
regVal = ixNpeDlEcsRegResetValues[localIndex].regResetVal;
|
||||
ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, regAddr, regVal);
|
||||
}
|
||||
|
||||
/* clear the profile counter */
|
||||
ixNpeDlNpeMgrCommandIssue (npeBaseAddress,
|
||||
IX_NPEDL_EXCTL_CMD_CLR_PROFILE_CNT);
|
||||
|
||||
/* clear registers EXCT, AP0, AP1, AP2 and AP3 */
|
||||
for (regAddr = IX_NPEDL_REG_OFFSET_EXCT;
|
||||
regAddr <= IX_NPEDL_REG_OFFSET_AP3;
|
||||
regAddr += IX_NPEDL_BYTES_PER_WORD)
|
||||
{
|
||||
IX_NPEDL_REG_WRITE (npeBaseAddress, regAddr, 0);
|
||||
}
|
||||
|
||||
/* Reset the Watch-count register */
|
||||
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_WC, 0);
|
||||
|
||||
/*
|
||||
* WR IXA00055043 - Remove IMEM Parity Introduced by NPE Reset Operation
|
||||
*/
|
||||
|
||||
/*
|
||||
* Call the feature control API to fused out and reset the NPE and its
|
||||
* coprocessor - to reset internal states and remove parity error
|
||||
*/
|
||||
unitFuseReg = ixFeatureCtrlRead ();
|
||||
unitFuseReg |= (IX_NPEDL_RESET_NPE_PARITY << npeId);
|
||||
ixFeatureCtrlWrite (unitFuseReg);
|
||||
|
||||
/* call the feature control API to un-fused and un-reset the NPE & COP */
|
||||
unitFuseReg &= (~(IX_NPEDL_RESET_NPE_PARITY << npeId));
|
||||
ixFeatureCtrlWrite (unitFuseReg);
|
||||
|
||||
/*
|
||||
* Call NpeMgr function to stop the NPE again after the Feature Control
|
||||
* has unfused and Un-Reset the NPE and its associated Coprocessors
|
||||
*/
|
||||
status = ixNpeDlNpeMgrNpeStop (npeId);
|
||||
|
||||
/* restore NPE configuration bus Control Register - Parity Settings */
|
||||
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_CTL,
|
||||
(ixNpeConfigCtrlRegVal & IX_NPEDL_CONFIG_CTRL_REG_MASK));
|
||||
|
||||
ixNpeDlNpeMgrStats.npeResets++;
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlNpeMgrNpeReset : status = %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrNpeStart
|
||||
*/
|
||||
IX_STATUS
|
||||
ixNpeDlNpeMgrNpeStart (
|
||||
IxNpeDlNpeId npeId)
|
||||
{
|
||||
UINT32 npeBaseAddress;
|
||||
UINT32 ecsRegVal;
|
||||
BOOL npeRunning;
|
||||
IX_STATUS status = IX_SUCCESS;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlNpeMgrNpeStart\n");
|
||||
|
||||
/* get base memory address of NPE from npeId */
|
||||
npeBaseAddress = ixNpeDlNpeMgrBaseAddressGet (npeId);
|
||||
|
||||
/*
|
||||
* ensure only Background Context Stack Level is Active by turning off
|
||||
* the Active bit in each of the other Executing Context Stack levels
|
||||
*/
|
||||
ecsRegVal = ixNpeDlNpeMgrExecAccRegRead (npeBaseAddress,
|
||||
IX_NPEDL_ECS_PRI_1_CTXT_REG_0);
|
||||
ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE;
|
||||
ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, IX_NPEDL_ECS_PRI_1_CTXT_REG_0,
|
||||
ecsRegVal);
|
||||
|
||||
ecsRegVal = ixNpeDlNpeMgrExecAccRegRead (npeBaseAddress,
|
||||
IX_NPEDL_ECS_PRI_2_CTXT_REG_0);
|
||||
ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE;
|
||||
ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, IX_NPEDL_ECS_PRI_2_CTXT_REG_0,
|
||||
ecsRegVal);
|
||||
|
||||
ecsRegVal = ixNpeDlNpeMgrExecAccRegRead (npeBaseAddress,
|
||||
IX_NPEDL_ECS_DBG_CTXT_REG_0);
|
||||
ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE;
|
||||
ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, IX_NPEDL_ECS_DBG_CTXT_REG_0,
|
||||
ecsRegVal);
|
||||
|
||||
/* clear the pipeline */
|
||||
ixNpeDlNpeMgrCommandIssue (npeBaseAddress, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE);
|
||||
|
||||
/* start NPE execution by issuing command through EXCTL register on NPE */
|
||||
ixNpeDlNpeMgrCommandIssue (npeBaseAddress, IX_NPEDL_EXCTL_CMD_NPE_START);
|
||||
|
||||
/*
|
||||
* check execution status of NPE to verify NPE Start operation was
|
||||
* successful
|
||||
*/
|
||||
npeRunning = ixNpeDlNpeMgrBitsSetCheck (npeBaseAddress,
|
||||
IX_NPEDL_REG_OFFSET_EXCTL,
|
||||
IX_NPEDL_EXCTL_STATUS_RUN);
|
||||
if (npeRunning)
|
||||
{
|
||||
ixNpeDlNpeMgrStats.npeStarts++;
|
||||
}
|
||||
else
|
||||
{
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrNpeStart: "
|
||||
"failed to start NPE execution\n");
|
||||
status = IX_FAIL;
|
||||
}
|
||||
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlNpeMgrNpeStart : status = %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrNpeStop
|
||||
*/
|
||||
IX_STATUS
|
||||
ixNpeDlNpeMgrNpeStop (
|
||||
IxNpeDlNpeId npeId)
|
||||
{
|
||||
UINT32 npeBaseAddress;
|
||||
IX_STATUS status = IX_SUCCESS;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlNpeMgrNpeStop\n");
|
||||
|
||||
/* get base memory address of NPE from npeId */
|
||||
npeBaseAddress = ixNpeDlNpeMgrBaseAddressGet (npeId);
|
||||
|
||||
/* stop NPE execution by issuing command through EXCTL register on NPE */
|
||||
ixNpeDlNpeMgrCommandIssue (npeBaseAddress, IX_NPEDL_EXCTL_CMD_NPE_STOP);
|
||||
|
||||
/* verify that NPE Stop was successful */
|
||||
if (! ixNpeDlNpeMgrBitsSetCheck (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXCTL,
|
||||
IX_NPEDL_EXCTL_STATUS_STOP))
|
||||
{
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrNpeStop: "
|
||||
"failed to stop NPE execution\n");
|
||||
status = IX_FAIL;
|
||||
}
|
||||
|
||||
ixNpeDlNpeMgrStats.npeStops++;
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlNpeMgrNpeStop : status = %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrBitsSetCheck
|
||||
*/
|
||||
PRIVATE BOOL
|
||||
ixNpeDlNpeMgrBitsSetCheck (
|
||||
UINT32 npeBaseAddress,
|
||||
UINT32 regOffset,
|
||||
UINT32 expectedBitsSet)
|
||||
{
|
||||
UINT32 regVal;
|
||||
IX_NPEDL_REG_READ (npeBaseAddress, regOffset, ®Val);
|
||||
|
||||
return expectedBitsSet == (expectedBitsSet & regVal);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrStatsShow
|
||||
*/
|
||||
void
|
||||
ixNpeDlNpeMgrStatsShow (void)
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_USER,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"\nixNpeDlNpeMgrStatsShow:\n"
|
||||
"\tInstruction Blocks loaded: %u\n"
|
||||
"\tData Blocks loaded: %u\n"
|
||||
"\tState Information Blocks loaded: %u\n"
|
||||
"\tCritical NPE errors: %u\n"
|
||||
"\tCritical Microcode errors: %u\n",
|
||||
ixNpeDlNpeMgrStats.instructionBlocksLoaded,
|
||||
ixNpeDlNpeMgrStats.dataBlocksLoaded,
|
||||
ixNpeDlNpeMgrStats.stateInfoBlocksLoaded,
|
||||
ixNpeDlNpeMgrStats.criticalNpeErrors,
|
||||
ixNpeDlNpeMgrStats.criticalMicrocodeErrors,
|
||||
0);
|
||||
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_USER,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"\tSuccessful NPE Starts: %u\n"
|
||||
"\tSuccessful NPE Stops: %u\n"
|
||||
"\tSuccessful NPE Resets: %u\n\n",
|
||||
ixNpeDlNpeMgrStats.npeStarts,
|
||||
ixNpeDlNpeMgrStats.npeStops,
|
||||
ixNpeDlNpeMgrStats.npeResets,
|
||||
0,0,0);
|
||||
|
||||
ixNpeDlNpeMgrUtilsStatsShow ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrStatsReset
|
||||
*/
|
||||
void
|
||||
ixNpeDlNpeMgrStatsReset (void)
|
||||
{
|
||||
ixNpeDlNpeMgrStats.instructionBlocksLoaded = 0;
|
||||
ixNpeDlNpeMgrStats.dataBlocksLoaded = 0;
|
||||
ixNpeDlNpeMgrStats.stateInfoBlocksLoaded = 0;
|
||||
ixNpeDlNpeMgrStats.criticalNpeErrors = 0;
|
||||
ixNpeDlNpeMgrStats.criticalMicrocodeErrors = 0;
|
||||
ixNpeDlNpeMgrStats.npeStarts = 0;
|
||||
ixNpeDlNpeMgrStats.npeStops = 0;
|
||||
ixNpeDlNpeMgrStats.npeResets = 0;
|
||||
|
||||
ixNpeDlNpeMgrUtilsStatsReset ();
|
||||
}
|
806
cpu/ixp/npe/IxNpeDlNpeMgrUtils.c
Normal file
806
cpu/ixp/npe/IxNpeDlNpeMgrUtils.c
Normal file
@ -0,0 +1,806 @@
|
||||
/**
|
||||
* @file IxNpeDlNpeMgrUtils.c
|
||||
*
|
||||
* @author Intel Corporation
|
||||
* @date 18 February 2002
|
||||
*
|
||||
* @brief This file contains the implementation of the private API for the
|
||||
* IXP425 NPE Downloader NpeMgr Utils module
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Put the system defined include files required.
|
||||
*/
|
||||
#define IX_NPE_DL_MAX_NUM_OF_RETRIES 1000000 /**< Maximum number of
|
||||
* retries before
|
||||
* timeout
|
||||
*/
|
||||
|
||||
/*
|
||||
* Put the user defined include files required.
|
||||
*/
|
||||
#include "IxOsal.h"
|
||||
#include "IxNpeDl.h"
|
||||
#include "IxNpeDlNpeMgrUtils_p.h"
|
||||
#include "IxNpeDlNpeMgrEcRegisters_p.h"
|
||||
#include "IxNpeDlMacros_p.h"
|
||||
|
||||
/*
|
||||
* #defines and macros used in this file.
|
||||
*/
|
||||
|
||||
/* used to bit-mask a number of bytes */
|
||||
#define IX_NPEDL_MASK_LOWER_BYTE_OF_WORD 0x000000FF
|
||||
#define IX_NPEDL_MASK_LOWER_SHORT_OF_WORD 0x0000FFFF
|
||||
#define IX_NPEDL_MASK_FULL_WORD 0xFFFFFFFF
|
||||
|
||||
#define IX_NPEDL_BYTES_PER_WORD 4
|
||||
#define IX_NPEDL_BYTES_PER_SHORT 2
|
||||
|
||||
#define IX_NPEDL_REG_SIZE_BYTE 8
|
||||
#define IX_NPEDL_REG_SIZE_SHORT 16
|
||||
#define IX_NPEDL_REG_SIZE_WORD 32
|
||||
|
||||
/*
|
||||
* Introduce extra read cycles after issuing read command to NPE
|
||||
* so that we read the register after the NPE has updated it
|
||||
* This is to overcome race condition between XScale and NPE
|
||||
*/
|
||||
#define IX_NPEDL_DELAY_READ_CYCLES 2
|
||||
/*
|
||||
* To mask top three MSBs of 32bit word to download into NPE IMEM
|
||||
*/
|
||||
#define IX_NPEDL_MASK_UNUSED_IMEM_BITS 0x1FFFFFFF;
|
||||
|
||||
|
||||
/*
|
||||
* typedefs
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UINT32 regAddress;
|
||||
UINT32 regSize;
|
||||
} IxNpeDlCtxtRegAccessInfo;
|
||||
|
||||
/* module statistics counters */
|
||||
typedef struct
|
||||
{
|
||||
UINT32 insMemWrites;
|
||||
UINT32 insMemWriteFails;
|
||||
UINT32 dataMemWrites;
|
||||
UINT32 dataMemWriteFails;
|
||||
UINT32 ecsRegWrites;
|
||||
UINT32 ecsRegReads;
|
||||
UINT32 dbgInstructionExecs;
|
||||
UINT32 contextRegWrites;
|
||||
UINT32 physicalRegWrites;
|
||||
UINT32 nextPcWrites;
|
||||
} IxNpeDlNpeMgrUtilsStats;
|
||||
|
||||
|
||||
/*
|
||||
* Variable declarations global to this file only. Externs are followed by
|
||||
* static variables.
|
||||
*/
|
||||
|
||||
/*
|
||||
* contains useful address and function pointers to read/write Context Regs,
|
||||
* eliminating some switch or if-else statements in places
|
||||
*/
|
||||
static IxNpeDlCtxtRegAccessInfo ixNpeDlCtxtRegAccInfo[IX_NPEDL_CTXT_REG_MAX] =
|
||||
{
|
||||
{
|
||||
IX_NPEDL_CTXT_REG_ADDR_STEVT,
|
||||
IX_NPEDL_REG_SIZE_BYTE
|
||||
},
|
||||
{
|
||||
IX_NPEDL_CTXT_REG_ADDR_STARTPC,
|
||||
IX_NPEDL_REG_SIZE_SHORT
|
||||
},
|
||||
{
|
||||
IX_NPEDL_CTXT_REG_ADDR_REGMAP,
|
||||
IX_NPEDL_REG_SIZE_SHORT
|
||||
},
|
||||
{
|
||||
IX_NPEDL_CTXT_REG_ADDR_CINDEX,
|
||||
IX_NPEDL_REG_SIZE_BYTE
|
||||
}
|
||||
};
|
||||
|
||||
static UINT32 ixNpeDlSavedExecCount = 0;
|
||||
static UINT32 ixNpeDlSavedEcsDbgCtxtReg2 = 0;
|
||||
|
||||
static IxNpeDlNpeMgrUtilsStats ixNpeDlNpeMgrUtilsStats;
|
||||
|
||||
|
||||
/*
|
||||
* static function prototypes.
|
||||
*/
|
||||
PRIVATE __inline__ void
|
||||
ixNpeDlNpeMgrWriteCommandIssue (UINT32 npeBaseAddress, UINT32 cmd,
|
||||
UINT32 addr, UINT32 data);
|
||||
|
||||
PRIVATE __inline__ UINT32
|
||||
ixNpeDlNpeMgrReadCommandIssue (UINT32 npeBaseAddress, UINT32 cmd, UINT32 addr);
|
||||
|
||||
PRIVATE IX_STATUS
|
||||
ixNpeDlNpeMgrLogicalRegRead (UINT32 npeBaseAddress, UINT32 regAddr,
|
||||
UINT32 regSize, UINT32 ctxtNum, UINT32 *regVal);
|
||||
|
||||
PRIVATE IX_STATUS
|
||||
ixNpeDlNpeMgrLogicalRegWrite (UINT32 npeBaseAddress, UINT32 regAddr,
|
||||
UINT32 regVal, UINT32 regSize,
|
||||
UINT32 ctxtNum, BOOL verify);
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrWriteCommandIssue
|
||||
*/
|
||||
PRIVATE __inline__ void
|
||||
ixNpeDlNpeMgrWriteCommandIssue (
|
||||
UINT32 npeBaseAddress,
|
||||
UINT32 cmd,
|
||||
UINT32 addr,
|
||||
UINT32 data)
|
||||
{
|
||||
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXDATA, data);
|
||||
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXAD, addr);
|
||||
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXCTL, cmd);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrReadCommandIssue
|
||||
*/
|
||||
PRIVATE __inline__ UINT32
|
||||
ixNpeDlNpeMgrReadCommandIssue (
|
||||
UINT32 npeBaseAddress,
|
||||
UINT32 cmd,
|
||||
UINT32 addr)
|
||||
{
|
||||
UINT32 data = 0;
|
||||
int i;
|
||||
|
||||
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXAD, addr);
|
||||
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXCTL, cmd);
|
||||
for (i = 0; i <= IX_NPEDL_DELAY_READ_CYCLES; i++)
|
||||
{
|
||||
IX_NPEDL_REG_READ (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXDATA, &data);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrInsMemWrite
|
||||
*/
|
||||
IX_STATUS
|
||||
ixNpeDlNpeMgrInsMemWrite (
|
||||
UINT32 npeBaseAddress,
|
||||
UINT32 insMemAddress,
|
||||
UINT32 insMemData,
|
||||
BOOL verify)
|
||||
{
|
||||
UINT32 insMemDataRtn;
|
||||
|
||||
ixNpeDlNpeMgrWriteCommandIssue (npeBaseAddress,
|
||||
IX_NPEDL_EXCTL_CMD_WR_INS_MEM,
|
||||
insMemAddress, insMemData);
|
||||
if (verify)
|
||||
{
|
||||
/* write invalid data to this reg, so we can see if we're reading
|
||||
the EXDATA register too early */
|
||||
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXDATA,
|
||||
~insMemData);
|
||||
|
||||
/*Disabled since top 3 MSB are not used for Azusa hardware Refer WR:IXA00053900*/
|
||||
insMemData&=IX_NPEDL_MASK_UNUSED_IMEM_BITS;
|
||||
|
||||
insMemDataRtn=ixNpeDlNpeMgrReadCommandIssue (npeBaseAddress,
|
||||
IX_NPEDL_EXCTL_CMD_RD_INS_MEM,
|
||||
insMemAddress);
|
||||
|
||||
insMemDataRtn&=IX_NPEDL_MASK_UNUSED_IMEM_BITS;
|
||||
|
||||
if (insMemData != insMemDataRtn)
|
||||
{
|
||||
ixNpeDlNpeMgrUtilsStats.insMemWriteFails++;
|
||||
return IX_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
ixNpeDlNpeMgrUtilsStats.insMemWrites++;
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrDataMemWrite
|
||||
*/
|
||||
IX_STATUS
|
||||
ixNpeDlNpeMgrDataMemWrite (
|
||||
UINT32 npeBaseAddress,
|
||||
UINT32 dataMemAddress,
|
||||
UINT32 dataMemData,
|
||||
BOOL verify)
|
||||
{
|
||||
ixNpeDlNpeMgrWriteCommandIssue (npeBaseAddress,
|
||||
IX_NPEDL_EXCTL_CMD_WR_DATA_MEM,
|
||||
dataMemAddress, dataMemData);
|
||||
if (verify)
|
||||
{
|
||||
/* write invalid data to this reg, so we can see if we're reading
|
||||
the EXDATA register too early */
|
||||
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXDATA, ~dataMemData);
|
||||
|
||||
if (dataMemData !=
|
||||
ixNpeDlNpeMgrReadCommandIssue (npeBaseAddress,
|
||||
IX_NPEDL_EXCTL_CMD_RD_DATA_MEM,
|
||||
dataMemAddress))
|
||||
{
|
||||
ixNpeDlNpeMgrUtilsStats.dataMemWriteFails++;
|
||||
return IX_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
ixNpeDlNpeMgrUtilsStats.dataMemWrites++;
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrExecAccRegWrite
|
||||
*/
|
||||
void
|
||||
ixNpeDlNpeMgrExecAccRegWrite (
|
||||
UINT32 npeBaseAddress,
|
||||
UINT32 regAddress,
|
||||
UINT32 regData)
|
||||
{
|
||||
ixNpeDlNpeMgrWriteCommandIssue (npeBaseAddress,
|
||||
IX_NPEDL_EXCTL_CMD_WR_ECS_REG,
|
||||
regAddress, regData);
|
||||
ixNpeDlNpeMgrUtilsStats.ecsRegWrites++;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrExecAccRegRead
|
||||
*/
|
||||
UINT32
|
||||
ixNpeDlNpeMgrExecAccRegRead (
|
||||
UINT32 npeBaseAddress,
|
||||
UINT32 regAddress)
|
||||
{
|
||||
ixNpeDlNpeMgrUtilsStats.ecsRegReads++;
|
||||
return ixNpeDlNpeMgrReadCommandIssue (npeBaseAddress,
|
||||
IX_NPEDL_EXCTL_CMD_RD_ECS_REG,
|
||||
regAddress);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrCommandIssue
|
||||
*/
|
||||
void
|
||||
ixNpeDlNpeMgrCommandIssue (
|
||||
UINT32 npeBaseAddress,
|
||||
UINT32 command)
|
||||
{
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlNpeMgrCommandIssue\n");
|
||||
|
||||
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXCTL, command);
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlNpeMgrCommandIssue\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrDebugInstructionPreExec
|
||||
*/
|
||||
void
|
||||
ixNpeDlNpeMgrDebugInstructionPreExec(
|
||||
UINT32 npeBaseAddress)
|
||||
{
|
||||
/* turn off the halt bit by clearing Execution Count register. */
|
||||
/* save reg contents 1st and restore later */
|
||||
IX_NPEDL_REG_READ (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXCT,
|
||||
&ixNpeDlSavedExecCount);
|
||||
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXCT, 0);
|
||||
|
||||
/* ensure that IF and IE are on (temporarily), so that we don't end up
|
||||
* stepping forever */
|
||||
ixNpeDlSavedEcsDbgCtxtReg2 = ixNpeDlNpeMgrExecAccRegRead (npeBaseAddress,
|
||||
IX_NPEDL_ECS_DBG_CTXT_REG_2);
|
||||
|
||||
ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, IX_NPEDL_ECS_DBG_CTXT_REG_2,
|
||||
(ixNpeDlSavedEcsDbgCtxtReg2 |
|
||||
IX_NPEDL_MASK_ECS_DBG_REG_2_IF |
|
||||
IX_NPEDL_MASK_ECS_DBG_REG_2_IE));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrDebugInstructionExec
|
||||
*/
|
||||
IX_STATUS
|
||||
ixNpeDlNpeMgrDebugInstructionExec(
|
||||
UINT32 npeBaseAddress,
|
||||
UINT32 npeInstruction,
|
||||
UINT32 ctxtNum,
|
||||
UINT32 ldur)
|
||||
{
|
||||
UINT32 ecsDbgRegVal;
|
||||
UINT32 oldWatchcount, newWatchcount;
|
||||
UINT32 retriesCount = 0;
|
||||
IX_STATUS status = IX_SUCCESS;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlNpeMgrDebugInstructionExec\n");
|
||||
|
||||
/* set the Active bit, and the LDUR, in the debug level */
|
||||
ecsDbgRegVal = IX_NPEDL_MASK_ECS_REG_0_ACTIVE |
|
||||
(ldur << IX_NPEDL_OFFSET_ECS_REG_0_LDUR);
|
||||
|
||||
ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, IX_NPEDL_ECS_DBG_CTXT_REG_0,
|
||||
ecsDbgRegVal);
|
||||
|
||||
/*
|
||||
* set CCTXT at ECS DEBUG L3 to specify in which context to execute the
|
||||
* instruction, and set SELCTXT at ECS DEBUG Level to specify which context
|
||||
* store to access.
|
||||
* Debug ECS Level Reg 1 has form 0x000n000n, where n = context number
|
||||
*/
|
||||
ecsDbgRegVal = (ctxtNum << IX_NPEDL_OFFSET_ECS_REG_1_CCTXT) |
|
||||
(ctxtNum << IX_NPEDL_OFFSET_ECS_REG_1_SELCTXT);
|
||||
|
||||
ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, IX_NPEDL_ECS_DBG_CTXT_REG_1,
|
||||
ecsDbgRegVal);
|
||||
|
||||
/* clear the pipeline */
|
||||
ixNpeDlNpeMgrCommandIssue (npeBaseAddress, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE);
|
||||
|
||||
/* load NPE instruction into the instruction register */
|
||||
ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, IX_NPEDL_ECS_INSTRUCT_REG,
|
||||
npeInstruction);
|
||||
|
||||
/* we need this value later to wait for completion of NPE execution step */
|
||||
IX_NPEDL_REG_READ (npeBaseAddress, IX_NPEDL_REG_OFFSET_WC, &oldWatchcount);
|
||||
|
||||
/* issue a Step One command via the Execution Control register */
|
||||
ixNpeDlNpeMgrCommandIssue (npeBaseAddress, IX_NPEDL_EXCTL_CMD_NPE_STEP);
|
||||
|
||||
/* Watch Count register increments when NPE completes an instruction */
|
||||
IX_NPEDL_REG_READ (npeBaseAddress, IX_NPEDL_REG_OFFSET_WC,
|
||||
&newWatchcount);
|
||||
|
||||
/*
|
||||
* force the XScale to wait until the NPE has finished execution step
|
||||
* NOTE that this delay will be very small, just long enough to allow a
|
||||
* single NPE instruction to complete execution; if instruction execution
|
||||
* is not completed before timeout retries, exit the while loop
|
||||
*/
|
||||
while ((IX_NPE_DL_MAX_NUM_OF_RETRIES > retriesCount)
|
||||
&& (newWatchcount == oldWatchcount))
|
||||
{
|
||||
/* Watch Count register increments when NPE completes an instruction */
|
||||
IX_NPEDL_REG_READ (npeBaseAddress, IX_NPEDL_REG_OFFSET_WC,
|
||||
&newWatchcount);
|
||||
|
||||
retriesCount++;
|
||||
}
|
||||
|
||||
if (IX_NPE_DL_MAX_NUM_OF_RETRIES > retriesCount)
|
||||
{
|
||||
ixNpeDlNpeMgrUtilsStats.dbgInstructionExecs++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Return timeout status as the instruction has not been executed
|
||||
* after maximum retries */
|
||||
status = IX_NPEDL_CRITICAL_NPE_ERR;
|
||||
}
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlNpeMgrDebugInstructionExec\n");
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrDebugInstructionPostExec
|
||||
*/
|
||||
void
|
||||
ixNpeDlNpeMgrDebugInstructionPostExec(
|
||||
UINT32 npeBaseAddress)
|
||||
{
|
||||
/* clear active bit in debug level */
|
||||
ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, IX_NPEDL_ECS_DBG_CTXT_REG_0,
|
||||
0);
|
||||
|
||||
/* clear the pipeline */
|
||||
ixNpeDlNpeMgrCommandIssue (npeBaseAddress, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE);
|
||||
|
||||
/* restore Execution Count register contents. */
|
||||
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXCT,
|
||||
ixNpeDlSavedExecCount);
|
||||
|
||||
/* restore IF and IE bits to original values */
|
||||
ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, IX_NPEDL_ECS_DBG_CTXT_REG_2,
|
||||
ixNpeDlSavedEcsDbgCtxtReg2);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrLogicalRegRead
|
||||
*/
|
||||
PRIVATE IX_STATUS
|
||||
ixNpeDlNpeMgrLogicalRegRead (
|
||||
UINT32 npeBaseAddress,
|
||||
UINT32 regAddr,
|
||||
UINT32 regSize,
|
||||
UINT32 ctxtNum,
|
||||
UINT32 *regVal)
|
||||
{
|
||||
IX_STATUS status = IX_SUCCESS;
|
||||
UINT32 npeInstruction = 0;
|
||||
UINT32 mask = 0;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlNpeMgrLogicalRegRead\n");
|
||||
|
||||
switch (regSize)
|
||||
{
|
||||
case IX_NPEDL_REG_SIZE_BYTE:
|
||||
npeInstruction = IX_NPEDL_INSTR_RD_REG_BYTE;
|
||||
mask = IX_NPEDL_MASK_LOWER_BYTE_OF_WORD; break;
|
||||
case IX_NPEDL_REG_SIZE_SHORT:
|
||||
npeInstruction = IX_NPEDL_INSTR_RD_REG_SHORT;
|
||||
mask = IX_NPEDL_MASK_LOWER_SHORT_OF_WORD; break;
|
||||
case IX_NPEDL_REG_SIZE_WORD:
|
||||
npeInstruction = IX_NPEDL_INSTR_RD_REG_WORD;
|
||||
mask = IX_NPEDL_MASK_FULL_WORD; break;
|
||||
}
|
||||
|
||||
/* make regAddr be the SRC and DEST operands (e.g. movX d0, d0) */
|
||||
npeInstruction |= (regAddr << IX_NPEDL_OFFSET_INSTR_SRC) |
|
||||
(regAddr << IX_NPEDL_OFFSET_INSTR_DEST);
|
||||
|
||||
/* step execution of NPE intruction using Debug Executing Context stack */
|
||||
status = ixNpeDlNpeMgrDebugInstructionExec (npeBaseAddress, npeInstruction,
|
||||
ctxtNum, IX_NPEDL_RD_INSTR_LDUR);
|
||||
|
||||
if (IX_SUCCESS != status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
/* read value of register from Execution Data register */
|
||||
IX_NPEDL_REG_READ (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXDATA, regVal);
|
||||
|
||||
/* align value from left to right */
|
||||
*regVal = (*regVal >> (IX_NPEDL_REG_SIZE_WORD - regSize)) & mask;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlNpeMgrLogicalRegRead\n");
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrLogicalRegWrite
|
||||
*/
|
||||
PRIVATE IX_STATUS
|
||||
ixNpeDlNpeMgrLogicalRegWrite (
|
||||
UINT32 npeBaseAddress,
|
||||
UINT32 regAddr,
|
||||
UINT32 regVal,
|
||||
UINT32 regSize,
|
||||
UINT32 ctxtNum,
|
||||
BOOL verify)
|
||||
{
|
||||
UINT32 npeInstruction = 0;
|
||||
UINT32 mask = 0;
|
||||
IX_STATUS status = IX_SUCCESS;
|
||||
UINT32 retRegVal;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlNpeMgrLogicalRegWrite\n");
|
||||
|
||||
if (regSize == IX_NPEDL_REG_SIZE_WORD)
|
||||
{
|
||||
/* NPE register addressing is left-to-right: e.g. |d0|d1|d2|d3| */
|
||||
/* Write upper half-word (short) to |d0|d1| */
|
||||
status = ixNpeDlNpeMgrLogicalRegWrite (npeBaseAddress, regAddr,
|
||||
regVal >> IX_NPEDL_REG_SIZE_SHORT,
|
||||
IX_NPEDL_REG_SIZE_SHORT,
|
||||
ctxtNum, verify);
|
||||
|
||||
if (IX_SUCCESS != status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Write lower half-word (short) to |d2|d3| */
|
||||
status = ixNpeDlNpeMgrLogicalRegWrite (npeBaseAddress,
|
||||
regAddr + IX_NPEDL_BYTES_PER_SHORT,
|
||||
regVal & IX_NPEDL_MASK_LOWER_SHORT_OF_WORD,
|
||||
IX_NPEDL_REG_SIZE_SHORT,
|
||||
ctxtNum, verify);
|
||||
|
||||
if (IX_SUCCESS != status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (regSize)
|
||||
{
|
||||
case IX_NPEDL_REG_SIZE_BYTE:
|
||||
npeInstruction = IX_NPEDL_INSTR_WR_REG_BYTE;
|
||||
mask = IX_NPEDL_MASK_LOWER_BYTE_OF_WORD; break;
|
||||
case IX_NPEDL_REG_SIZE_SHORT:
|
||||
npeInstruction = IX_NPEDL_INSTR_WR_REG_SHORT;
|
||||
mask = IX_NPEDL_MASK_LOWER_SHORT_OF_WORD; break;
|
||||
}
|
||||
/* mask out any redundant bits, so verify will work later */
|
||||
regVal &= mask;
|
||||
|
||||
/* fill dest operand field of instruction with destination reg addr */
|
||||
npeInstruction |= (regAddr << IX_NPEDL_OFFSET_INSTR_DEST);
|
||||
|
||||
/* fill src operand field of instruction with least-sig 5 bits of val*/
|
||||
npeInstruction |= ((regVal & IX_NPEDL_MASK_IMMED_INSTR_SRC_DATA) <<
|
||||
IX_NPEDL_OFFSET_INSTR_SRC);
|
||||
|
||||
/* fill coprocessor field of instruction with most-sig 11 bits of val*/
|
||||
npeInstruction |= ((regVal & IX_NPEDL_MASK_IMMED_INSTR_COPROC_DATA) <<
|
||||
IX_NPEDL_DISPLACE_IMMED_INSTR_COPROC_DATA);
|
||||
|
||||
/* step execution of NPE intruction using Debug ECS */
|
||||
status = ixNpeDlNpeMgrDebugInstructionExec(npeBaseAddress, npeInstruction,
|
||||
ctxtNum, IX_NPEDL_WR_INSTR_LDUR);
|
||||
|
||||
if (IX_SUCCESS != status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}/* condition: if reg to be written is 8-bit or 16-bit (not 32-bit) */
|
||||
|
||||
if (verify)
|
||||
{
|
||||
status = ixNpeDlNpeMgrLogicalRegRead (npeBaseAddress, regAddr,
|
||||
regSize, ctxtNum, &retRegVal);
|
||||
|
||||
if (IX_SUCCESS == status)
|
||||
{
|
||||
if (regVal != retRegVal)
|
||||
{
|
||||
status = IX_FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlNpeMgrLogicalRegWrite : status = %d\n",
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrPhysicalRegWrite
|
||||
*/
|
||||
IX_STATUS
|
||||
ixNpeDlNpeMgrPhysicalRegWrite (
|
||||
UINT32 npeBaseAddress,
|
||||
UINT32 regAddr,
|
||||
UINT32 regValue,
|
||||
BOOL verify)
|
||||
{
|
||||
IX_STATUS status;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlNpeMgrPhysicalRegWrite\n");
|
||||
|
||||
/*
|
||||
* There are 32 physical registers used in an NPE. These are
|
||||
* treated as 16 pairs of 32-bit registers. To write one of the pair,
|
||||
* write the pair number (0-16) to the REGMAP for Context 0. Then write
|
||||
* the value to register 0 or 4 in the regfile, depending on which
|
||||
* register of the pair is to be written
|
||||
*/
|
||||
|
||||
/*
|
||||
* set REGMAP for context 0 to (regAddr >> 1) to choose which pair (0-16)
|
||||
* of physical registers to write
|
||||
*/
|
||||
status = ixNpeDlNpeMgrLogicalRegWrite (npeBaseAddress,
|
||||
IX_NPEDL_CTXT_REG_ADDR_REGMAP,
|
||||
(regAddr >>
|
||||
IX_NPEDL_OFFSET_PHYS_REG_ADDR_REGMAP),
|
||||
IX_NPEDL_REG_SIZE_SHORT, 0, verify);
|
||||
if (status == IX_SUCCESS)
|
||||
{
|
||||
/* regAddr = 0 or 4 */
|
||||
regAddr = (regAddr & IX_NPEDL_MASK_PHYS_REG_ADDR_LOGICAL_ADDR) *
|
||||
IX_NPEDL_BYTES_PER_WORD;
|
||||
|
||||
status = ixNpeDlNpeMgrLogicalRegWrite (npeBaseAddress, regAddr, regValue,
|
||||
IX_NPEDL_REG_SIZE_WORD, 0, verify);
|
||||
}
|
||||
|
||||
if (status != IX_SUCCESS)
|
||||
{
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrPhysicalRegWrite: "
|
||||
"error writing to physical register\n");
|
||||
}
|
||||
|
||||
ixNpeDlNpeMgrUtilsStats.physicalRegWrites++;
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlNpeMgrPhysicalRegWrite : status = %d\n",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrCtxtRegWrite
|
||||
*/
|
||||
IX_STATUS
|
||||
ixNpeDlNpeMgrCtxtRegWrite (
|
||||
UINT32 npeBaseAddress,
|
||||
UINT32 ctxtNum,
|
||||
IxNpeDlCtxtRegNum ctxtReg,
|
||||
UINT32 ctxtRegVal,
|
||||
BOOL verify)
|
||||
{
|
||||
UINT32 tempRegVal;
|
||||
UINT32 ctxtRegAddr;
|
||||
UINT32 ctxtRegSize;
|
||||
IX_STATUS status = IX_SUCCESS;
|
||||
|
||||
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Entering ixNpeDlNpeMgrCtxtRegWrite\n");
|
||||
|
||||
/*
|
||||
* Context 0 has no STARTPC. Instead, this value is used to set
|
||||
* NextPC for Background ECS, to set where NPE starts executing code
|
||||
*/
|
||||
if ((ctxtNum == 0) && (ctxtReg == IX_NPEDL_CTXT_REG_STARTPC))
|
||||
{
|
||||
/* read BG_CTXT_REG_0, update NEXTPC bits, and write back to reg */
|
||||
tempRegVal = ixNpeDlNpeMgrExecAccRegRead (npeBaseAddress,
|
||||
IX_NPEDL_ECS_BG_CTXT_REG_0);
|
||||
tempRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_NEXTPC;
|
||||
tempRegVal |= (ctxtRegVal << IX_NPEDL_OFFSET_ECS_REG_0_NEXTPC) &
|
||||
IX_NPEDL_MASK_ECS_REG_0_NEXTPC;
|
||||
|
||||
ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress,
|
||||
IX_NPEDL_ECS_BG_CTXT_REG_0, tempRegVal);
|
||||
|
||||
ixNpeDlNpeMgrUtilsStats.nextPcWrites++;
|
||||
}
|
||||
else
|
||||
{
|
||||
ctxtRegAddr = ixNpeDlCtxtRegAccInfo[ctxtReg].regAddress;
|
||||
ctxtRegSize = ixNpeDlCtxtRegAccInfo[ctxtReg].regSize;
|
||||
status = ixNpeDlNpeMgrLogicalRegWrite (npeBaseAddress, ctxtRegAddr,
|
||||
ctxtRegVal, ctxtRegSize,
|
||||
ctxtNum, verify);
|
||||
if (status != IX_SUCCESS)
|
||||
{
|
||||
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrCtxtRegWrite: "
|
||||
"error writing to context store register\n");
|
||||
}
|
||||
|
||||
ixNpeDlNpeMgrUtilsStats.contextRegWrites++;
|
||||
}
|
||||
|
||||
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
||||
"Exiting ixNpeDlNpeMgrCtxtRegWrite : status = %d\n",
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrUtilsStatsShow
|
||||
*/
|
||||
void
|
||||
ixNpeDlNpeMgrUtilsStatsShow (void)
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_USER,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"\nixNpeDlNpeMgrUtilsStatsShow:\n"
|
||||
"\tInstruction Memory writes: %u\n"
|
||||
"\tInstruction Memory writes failed: %u\n"
|
||||
"\tData Memory writes: %u\n"
|
||||
"\tData Memory writes failed: %u\n",
|
||||
ixNpeDlNpeMgrUtilsStats.insMemWrites,
|
||||
ixNpeDlNpeMgrUtilsStats.insMemWriteFails,
|
||||
ixNpeDlNpeMgrUtilsStats.dataMemWrites,
|
||||
ixNpeDlNpeMgrUtilsStats.dataMemWriteFails,
|
||||
0,0);
|
||||
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_USER,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"\tExecuting Context Stack Register writes: %u\n"
|
||||
"\tExecuting Context Stack Register reads: %u\n"
|
||||
"\tPhysical Register writes: %u\n"
|
||||
"\tContext Store Register writes: %u\n"
|
||||
"\tExecution Backgound Context NextPC writes: %u\n"
|
||||
"\tDebug Instructions Executed: %u\n\n",
|
||||
ixNpeDlNpeMgrUtilsStats.ecsRegWrites,
|
||||
ixNpeDlNpeMgrUtilsStats.ecsRegReads,
|
||||
ixNpeDlNpeMgrUtilsStats.physicalRegWrites,
|
||||
ixNpeDlNpeMgrUtilsStats.contextRegWrites,
|
||||
ixNpeDlNpeMgrUtilsStats.nextPcWrites,
|
||||
ixNpeDlNpeMgrUtilsStats.dbgInstructionExecs);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeDlNpeMgrUtilsStatsReset
|
||||
*/
|
||||
void
|
||||
ixNpeDlNpeMgrUtilsStatsReset (void)
|
||||
{
|
||||
ixNpeDlNpeMgrUtilsStats.insMemWrites = 0;
|
||||
ixNpeDlNpeMgrUtilsStats.insMemWriteFails = 0;
|
||||
ixNpeDlNpeMgrUtilsStats.dataMemWrites = 0;
|
||||
ixNpeDlNpeMgrUtilsStats.dataMemWriteFails = 0;
|
||||
ixNpeDlNpeMgrUtilsStats.ecsRegWrites = 0;
|
||||
ixNpeDlNpeMgrUtilsStats.ecsRegReads = 0;
|
||||
ixNpeDlNpeMgrUtilsStats.physicalRegWrites = 0;
|
||||
ixNpeDlNpeMgrUtilsStats.contextRegWrites = 0;
|
||||
ixNpeDlNpeMgrUtilsStats.nextPcWrites = 0;
|
||||
ixNpeDlNpeMgrUtilsStats.dbgInstructionExecs = 0;
|
||||
}
|
582
cpu/ixp/npe/IxNpeMh.c
Normal file
582
cpu/ixp/npe/IxNpeMh.c
Normal file
@ -0,0 +1,582 @@
|
||||
/**
|
||||
* @file IxNpeMh.c
|
||||
*
|
||||
* @author Intel Corporation
|
||||
* @date 18 Jan 2002
|
||||
*
|
||||
* @brief This file contains the implementation of the public API for the
|
||||
* IXP425 NPE Message Handler component.
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
/*
|
||||
* Put the system defined include files required.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Put the user defined include files required.
|
||||
*/
|
||||
|
||||
#include "IxOsal.h"
|
||||
#include "IxNpeMhMacros_p.h"
|
||||
|
||||
#include "IxNpeMh.h"
|
||||
|
||||
#include "IxNpeMhConfig_p.h"
|
||||
#include "IxNpeMhReceive_p.h"
|
||||
#include "IxNpeMhSend_p.h"
|
||||
#include "IxNpeMhSolicitedCbMgr_p.h"
|
||||
#include "IxNpeMhUnsolicitedCbMgr_p.h"
|
||||
|
||||
/*
|
||||
* #defines and macros used in this file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Typedefs whose scope is limited to this file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Variable declarations global to this file only. Externs are followed by
|
||||
* static variables.
|
||||
*/
|
||||
|
||||
PRIVATE BOOL ixNpeMhInitialized = FALSE;
|
||||
|
||||
/*
|
||||
* Extern function prototypes.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Static function prototypes.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhInitialize
|
||||
*/
|
||||
|
||||
PUBLIC IX_STATUS ixNpeMhInitialize (
|
||||
IxNpeMhNpeInterrupts npeInterrupts)
|
||||
{
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
|
||||
"ixNpeMhInitialize\n");
|
||||
|
||||
/* check the npeInterrupts parameter */
|
||||
if ((npeInterrupts != IX_NPEMH_NPEINTERRUPTS_NO) &&
|
||||
(npeInterrupts != IX_NPEMH_NPEINTERRUPTS_YES))
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("Illegal npeInterrupts parameter value\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* parameters are ok ... */
|
||||
|
||||
/* initialize the Receive module */
|
||||
ixNpeMhReceiveInitialize ();
|
||||
|
||||
/* initialize the Solicited Callback Manager module */
|
||||
ixNpeMhSolicitedCbMgrInitialize ();
|
||||
|
||||
/* initialize the Unsolicited Callback Manager module */
|
||||
ixNpeMhUnsolicitedCbMgrInitialize ();
|
||||
|
||||
/* initialize the Configuration module
|
||||
*
|
||||
* NOTE: This module was originally configured before the
|
||||
* others, but the sequence was changed so that interrupts
|
||||
* would only be enabled after the handler functions were
|
||||
* set up. The above modules need to be initialised to
|
||||
* handle the NPE interrupts. See SCR #2231.
|
||||
*/
|
||||
ixNpeMhConfigInitialize (npeInterrupts);
|
||||
|
||||
ixNpeMhInitialized = TRUE;
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
|
||||
"ixNpeMhInitialize\n");
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhUnload
|
||||
*/
|
||||
|
||||
PUBLIC IX_STATUS ixNpeMhUnload (void)
|
||||
{
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
|
||||
"ixNpeMhUnload\n");
|
||||
|
||||
if (!ixNpeMhInitialized)
|
||||
{
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* Uninitialize the Configuration module */
|
||||
ixNpeMhConfigUninit ();
|
||||
|
||||
ixNpeMhInitialized = FALSE;
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
|
||||
"ixNpeMhUnload\n");
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhUnsolicitedCallbackRegister
|
||||
*/
|
||||
|
||||
PUBLIC IX_STATUS ixNpeMhUnsolicitedCallbackRegister (
|
||||
IxNpeMhNpeId npeId,
|
||||
IxNpeMhMessageId messageId,
|
||||
IxNpeMhCallback unsolicitedCallback)
|
||||
{
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
|
||||
"ixNpeMhUnsolicitedCallbackRegister\n");
|
||||
|
||||
/* check that we are initialized */
|
||||
if (!ixNpeMhInitialized)
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("IxNpeMh component is not initialized\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* check the npeId parameter */
|
||||
if (!ixNpeMhConfigNpeIdIsValid (npeId))
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("NPE ID invalid\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* check the messageId parameter */
|
||||
if ((messageId < IX_NPEMH_MIN_MESSAGE_ID)
|
||||
|| (messageId > IX_NPEMH_MAX_MESSAGE_ID))
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("Message ID is out of range\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* the unsolicitedCallback parameter is allowed to be NULL */
|
||||
|
||||
/* parameters are ok ... */
|
||||
|
||||
/* get the lock to prevent other clients from entering */
|
||||
ixNpeMhConfigLockGet (npeId);
|
||||
|
||||
/* save the unsolicited callback for the message ID */
|
||||
ixNpeMhUnsolicitedCbMgrCallbackSave (
|
||||
npeId, messageId, unsolicitedCallback);
|
||||
|
||||
/* release the lock to allow other clients back in */
|
||||
ixNpeMhConfigLockRelease (npeId);
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
|
||||
"ixNpeMhUnsolicitedCallbackRegister\n");
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhUnsolicitedCallbackForRangeRegister
|
||||
*/
|
||||
|
||||
PUBLIC IX_STATUS ixNpeMhUnsolicitedCallbackForRangeRegister (
|
||||
IxNpeMhNpeId npeId,
|
||||
IxNpeMhMessageId minMessageId,
|
||||
IxNpeMhMessageId maxMessageId,
|
||||
IxNpeMhCallback unsolicitedCallback)
|
||||
{
|
||||
IxNpeMhMessageId messageId;
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
|
||||
"ixNpeMhUnsolicitedCallbackForRangeRegister\n");
|
||||
|
||||
/* check that we are initialized */
|
||||
if (!ixNpeMhInitialized)
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("IxNpeMh component is not initialized\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* check the npeId parameter */
|
||||
if (!ixNpeMhConfigNpeIdIsValid (npeId))
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("NPE ID invalid\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* check the minMessageId parameter */
|
||||
if ((minMessageId < IX_NPEMH_MIN_MESSAGE_ID)
|
||||
|| (minMessageId > IX_NPEMH_MAX_MESSAGE_ID))
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("Min message ID is out of range\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* check the maxMessageId parameter */
|
||||
if ((maxMessageId < IX_NPEMH_MIN_MESSAGE_ID)
|
||||
|| (maxMessageId > IX_NPEMH_MAX_MESSAGE_ID))
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("Max message ID is out of range\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* check the semantics of the message range parameters */
|
||||
if (minMessageId > maxMessageId)
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("Min message ID greater than max message "
|
||||
"ID\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* the unsolicitedCallback parameter is allowed to be NULL */
|
||||
|
||||
/* parameters are ok ... */
|
||||
|
||||
/* get the lock to prevent other clients from entering */
|
||||
ixNpeMhConfigLockGet (npeId);
|
||||
|
||||
/* for each message ID in the range ... */
|
||||
for (messageId = minMessageId; messageId <= maxMessageId; messageId++)
|
||||
{
|
||||
/* save the unsolicited callback for the message ID */
|
||||
ixNpeMhUnsolicitedCbMgrCallbackSave (
|
||||
npeId, messageId, unsolicitedCallback);
|
||||
}
|
||||
|
||||
/* release the lock to allow other clients back in */
|
||||
ixNpeMhConfigLockRelease (npeId);
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
|
||||
"ixNpeMhUnsolicitedCallbackForRangeRegister\n");
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhMessageSend
|
||||
*/
|
||||
|
||||
PUBLIC IX_STATUS ixNpeMhMessageSend (
|
||||
IxNpeMhNpeId npeId,
|
||||
IxNpeMhMessage message,
|
||||
UINT32 maxSendRetries)
|
||||
{
|
||||
IX_STATUS status = IX_SUCCESS;
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
|
||||
"ixNpeMhMessageSend\n");
|
||||
|
||||
/* check that we are initialized */
|
||||
if (!ixNpeMhInitialized)
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("IxNpeMh component is not initialized\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* check the npeId parameter */
|
||||
if (!ixNpeMhConfigNpeIdIsValid (npeId))
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("NPE ID invalid\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* parameters are ok ... */
|
||||
|
||||
/* get the lock to prevent other clients from entering */
|
||||
ixNpeMhConfigLockGet (npeId);
|
||||
|
||||
/* send the message */
|
||||
status = ixNpeMhSendMessageSend (npeId, message, maxSendRetries);
|
||||
if (status != IX_SUCCESS)
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("Failed to send message\n");
|
||||
}
|
||||
|
||||
/* release the lock to allow other clients back in */
|
||||
ixNpeMhConfigLockRelease (npeId);
|
||||
|
||||
IX_NPEMH_TRACE1 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
|
||||
"ixNpeMhMessageSend"
|
||||
" : status = %d\n", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhMessageWithResponseSend
|
||||
*/
|
||||
|
||||
PUBLIC IX_STATUS ixNpeMhMessageWithResponseSend (
|
||||
IxNpeMhNpeId npeId,
|
||||
IxNpeMhMessage message,
|
||||
IxNpeMhMessageId solicitedMessageId,
|
||||
IxNpeMhCallback solicitedCallback,
|
||||
UINT32 maxSendRetries)
|
||||
{
|
||||
IX_STATUS status = IX_SUCCESS;
|
||||
IxNpeMhCallback unsolicitedCallback = NULL;
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
|
||||
"ixNpeMhMessageWithResponseSend\n");
|
||||
|
||||
/* check that we are initialized */
|
||||
if (!ixNpeMhInitialized)
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("IxNpeMh component is not initialized\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* the solicitecCallback parameter is allowed to be NULL. this */
|
||||
/* signifies the client is not interested in the response message */
|
||||
|
||||
/* check the npeId parameter */
|
||||
if (!ixNpeMhConfigNpeIdIsValid (npeId))
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("NPE ID invalid\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* check the solicitedMessageId parameter */
|
||||
if ((solicitedMessageId < IX_NPEMH_MIN_MESSAGE_ID)
|
||||
|| (solicitedMessageId > IX_NPEMH_MAX_MESSAGE_ID))
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("Solicited message ID is out of range\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* check the solicitedMessageId parameter. if an unsolicited */
|
||||
/* callback has been registered for the specified message ID then */
|
||||
/* report an error and return failure */
|
||||
ixNpeMhUnsolicitedCbMgrCallbackRetrieve (
|
||||
npeId, solicitedMessageId, &unsolicitedCallback);
|
||||
if (unsolicitedCallback != NULL)
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("Solicited message ID conflicts with "
|
||||
"unsolicited message ID\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* parameters are ok ... */
|
||||
|
||||
/* get the lock to prevent other clients from entering */
|
||||
ixNpeMhConfigLockGet (npeId);
|
||||
|
||||
/* send the message */
|
||||
status = ixNpeMhSendMessageWithResponseSend (
|
||||
npeId, message, solicitedMessageId, solicitedCallback,
|
||||
maxSendRetries);
|
||||
if (status != IX_SUCCESS)
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("Failed to send message\n");
|
||||
}
|
||||
|
||||
/* release the lock to allow other clients back in */
|
||||
ixNpeMhConfigLockRelease (npeId);
|
||||
|
||||
IX_NPEMH_TRACE1 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
|
||||
"ixNpeMhMessageWithResponseSend"
|
||||
" : status = %d\n", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhMessagesReceive
|
||||
*/
|
||||
|
||||
PUBLIC IX_STATUS ixNpeMhMessagesReceive (
|
||||
IxNpeMhNpeId npeId)
|
||||
{
|
||||
IX_STATUS status = IX_SUCCESS;
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
|
||||
"ixNpeMhMessagesReceive\n");
|
||||
|
||||
/* check that we are initialized */
|
||||
if (!ixNpeMhInitialized)
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("IxNpeMh component is not initialized\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* check the npeId parameter */
|
||||
if (!ixNpeMhConfigNpeIdIsValid (npeId))
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("NPE ID invalid\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* parameters are ok ... */
|
||||
|
||||
/* get the lock to prevent other clients from entering */
|
||||
ixNpeMhConfigLockGet (npeId);
|
||||
|
||||
/* receive messages from the NPE */
|
||||
status = ixNpeMhReceiveMessagesReceive (npeId);
|
||||
|
||||
if (status != IX_SUCCESS)
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("Failed to receive message\n");
|
||||
}
|
||||
|
||||
/* release the lock to allow other clients back in */
|
||||
ixNpeMhConfigLockRelease (npeId);
|
||||
|
||||
IX_NPEMH_TRACE1 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
|
||||
"ixNpeMhMessagesReceive"
|
||||
" : status = %d\n", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhShow
|
||||
*/
|
||||
|
||||
PUBLIC IX_STATUS ixNpeMhShow (
|
||||
IxNpeMhNpeId npeId)
|
||||
{
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
|
||||
"ixNpeMhShow\n");
|
||||
|
||||
/* check that we are initialized */
|
||||
if (!ixNpeMhInitialized)
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("IxNpeMh component is not initialized\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* check the npeId parameter */
|
||||
if (!ixNpeMhConfigNpeIdIsValid (npeId))
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("NPE ID invalid\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* parameters are ok ... */
|
||||
|
||||
/* note we don't get the lock here as printing the statistics */
|
||||
/* to a console may take some time and we don't want to impact */
|
||||
/* system performance. this means that the statistics displayed */
|
||||
/* may be in a state of flux and make not represent a consistent */
|
||||
/* snapshot. */
|
||||
|
||||
/* display a header */
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT,
|
||||
"Current state of NPE ID %d:\n\n", npeId, 0, 0, 0, 0, 0);
|
||||
|
||||
/* show the current state of each module */
|
||||
|
||||
/* show the current state of the Configuration module */
|
||||
ixNpeMhConfigShow (npeId);
|
||||
|
||||
/* show the current state of the Receive module */
|
||||
ixNpeMhReceiveShow (npeId);
|
||||
|
||||
/* show the current state of the Send module */
|
||||
ixNpeMhSendShow (npeId);
|
||||
|
||||
/* show the current state of the Solicited Callback Manager module */
|
||||
ixNpeMhSolicitedCbMgrShow (npeId);
|
||||
|
||||
/* show the current state of the Unsolicited Callback Manager module */
|
||||
ixNpeMhUnsolicitedCbMgrShow (npeId);
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
|
||||
"ixNpeMhShow\n");
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhShowReset
|
||||
*/
|
||||
|
||||
PUBLIC IX_STATUS ixNpeMhShowReset (
|
||||
IxNpeMhNpeId npeId)
|
||||
{
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
|
||||
"ixNpeMhShowReset\n");
|
||||
|
||||
/* check that we are initialized */
|
||||
if (!ixNpeMhInitialized)
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("IxNpeMh component is not initialized\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* check the npeId parameter */
|
||||
if (!ixNpeMhConfigNpeIdIsValid (npeId))
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("NPE ID invalid\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* parameters are ok ... */
|
||||
|
||||
/* note we don't get the lock here as resetting the statistics */
|
||||
/* shouldn't impact system performance. */
|
||||
|
||||
/* reset the current state of each module */
|
||||
|
||||
/* reset the current state of the Configuration module */
|
||||
ixNpeMhConfigShowReset (npeId);
|
||||
|
||||
/* reset the current state of the Receive module */
|
||||
ixNpeMhReceiveShowReset (npeId);
|
||||
|
||||
/* reset the current state of the Send module */
|
||||
ixNpeMhSendShowReset (npeId);
|
||||
|
||||
/* reset the current state of the Solicited Callback Manager module */
|
||||
ixNpeMhSolicitedCbMgrShowReset (npeId);
|
||||
|
||||
/* reset the current state of the Unsolicited Callback Manager module */
|
||||
ixNpeMhUnsolicitedCbMgrShowReset (npeId);
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
|
||||
"ixNpeMhShowReset\n");
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
608
cpu/ixp/npe/IxNpeMhConfig.c
Normal file
608
cpu/ixp/npe/IxNpeMhConfig.c
Normal file
@ -0,0 +1,608 @@
|
||||
/**
|
||||
* @file IxNpeMhConfig.c
|
||||
*
|
||||
* @author Intel Corporation
|
||||
* @date 18 Jan 2002
|
||||
*
|
||||
* @brief This file contains the implementation of the private API for the
|
||||
* Configuration module.
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
/*
|
||||
* Put the system defined include files required.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Put the user defined include files required.
|
||||
*/
|
||||
|
||||
#include "IxOsal.h"
|
||||
|
||||
#include "IxNpeMhMacros_p.h"
|
||||
|
||||
#include "IxNpeMhConfig_p.h"
|
||||
|
||||
/*
|
||||
* #defines and macros used in this file.
|
||||
*/
|
||||
#define IX_NPE_MH_MAX_NUM_OF_RETRIES 1000000 /**< Maximum number of
|
||||
* retries before
|
||||
* timeout
|
||||
*/
|
||||
|
||||
/*
|
||||
* Typedefs whose scope is limited to this file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @struct IxNpeMhConfigStats
|
||||
*
|
||||
* @brief This structure is used to maintain statistics for the
|
||||
* Configuration module.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 outFifoReads; /**< outFifo reads */
|
||||
UINT32 inFifoWrites; /**< inFifo writes */
|
||||
UINT32 maxInFifoFullRetries; /**< max retries if inFIFO full */
|
||||
UINT32 maxOutFifoEmptyRetries; /**< max retries if outFIFO empty */
|
||||
} IxNpeMhConfigStats;
|
||||
|
||||
/*
|
||||
* Variable declarations global to this file only. Externs are followed by
|
||||
* static variables.
|
||||
*/
|
||||
|
||||
IxNpeMhConfigNpeInfo ixNpeMhConfigNpeInfo[IX_NPEMH_NUM_NPES] =
|
||||
{
|
||||
{
|
||||
0,
|
||||
IX_NPEMH_NPEA_INT,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
FALSE
|
||||
},
|
||||
{
|
||||
0,
|
||||
IX_NPEMH_NPEB_INT,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
FALSE
|
||||
},
|
||||
{
|
||||
0,
|
||||
IX_NPEMH_NPEC_INT,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
FALSE
|
||||
}
|
||||
};
|
||||
|
||||
PRIVATE IxNpeMhConfigStats ixNpeMhConfigStats[IX_NPEMH_NUM_NPES];
|
||||
|
||||
/*
|
||||
* Extern function prototypes.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Static function prototypes.
|
||||
*/
|
||||
PRIVATE
|
||||
void ixNpeMhConfigIsr (void *parameter);
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhConfigIsr
|
||||
*/
|
||||
|
||||
PRIVATE
|
||||
void ixNpeMhConfigIsr (void *parameter)
|
||||
{
|
||||
IxNpeMhNpeId npeId = (IxNpeMhNpeId)parameter;
|
||||
UINT32 ofint;
|
||||
volatile UINT32 *statusReg =
|
||||
(UINT32 *)ixNpeMhConfigNpeInfo[npeId].statusRegister;
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
|
||||
"ixNpeMhConfigIsr\n");
|
||||
|
||||
/* get the OFINT (OutFifo interrupt) bit of the status register */
|
||||
IX_NPEMH_REGISTER_READ_BITS (statusReg, &ofint, IX_NPEMH_NPE_STAT_OFINT);
|
||||
|
||||
/* if the OFINT status bit is set */
|
||||
if (ofint)
|
||||
{
|
||||
/* if there is an ISR registered for this NPE */
|
||||
if (ixNpeMhConfigNpeInfo[npeId].isr != NULL)
|
||||
{
|
||||
/* invoke the ISR routine */
|
||||
ixNpeMhConfigNpeInfo[npeId].isr (npeId);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if we don't service the interrupt the NPE will continue */
|
||||
/* to trigger the interrupt indefinitely */
|
||||
IX_NPEMH_ERROR_REPORT ("No ISR registered to service "
|
||||
"interrupt\n");
|
||||
}
|
||||
}
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
|
||||
"ixNpeMhConfigIsr\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhConfigInitialize
|
||||
*/
|
||||
|
||||
void ixNpeMhConfigInitialize (
|
||||
IxNpeMhNpeInterrupts npeInterrupts)
|
||||
{
|
||||
IxNpeMhNpeId npeId;
|
||||
UINT32 virtualAddr[IX_NPEMH_NUM_NPES];
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
|
||||
"ixNpeMhConfigInitialize\n");
|
||||
|
||||
/* Request a mapping for the NPE-A config register address space */
|
||||
virtualAddr[IX_NPEMH_NPEID_NPEA] =
|
||||
(UINT32) IX_OSAL_MEM_MAP (IX_NPEMH_NPEA_BASE,
|
||||
IX_OSAL_IXP400_NPEA_MAP_SIZE);
|
||||
IX_OSAL_ASSERT (virtualAddr[IX_NPEMH_NPEID_NPEA]);
|
||||
|
||||
/* Request a mapping for the NPE-B config register address space */
|
||||
virtualAddr[IX_NPEMH_NPEID_NPEB] =
|
||||
(UINT32) IX_OSAL_MEM_MAP (IX_NPEMH_NPEB_BASE,
|
||||
IX_OSAL_IXP400_NPEB_MAP_SIZE);
|
||||
IX_OSAL_ASSERT (virtualAddr[IX_NPEMH_NPEID_NPEB]);
|
||||
|
||||
/* Request a mapping for the NPE-C config register address space */
|
||||
virtualAddr[IX_NPEMH_NPEID_NPEC] =
|
||||
(UINT32) IX_OSAL_MEM_MAP (IX_NPEMH_NPEC_BASE,
|
||||
IX_OSAL_IXP400_NPEC_MAP_SIZE);
|
||||
IX_OSAL_ASSERT (virtualAddr[IX_NPEMH_NPEID_NPEC]);
|
||||
|
||||
/* for each NPE ... */
|
||||
for (npeId = 0; npeId < IX_NPEMH_NUM_NPES; npeId++)
|
||||
{
|
||||
/* declare a convenience pointer */
|
||||
IxNpeMhConfigNpeInfo *npeInfo = &ixNpeMhConfigNpeInfo[npeId];
|
||||
|
||||
/* store the virtual addresses of the NPE registers for later use */
|
||||
npeInfo->virtualRegisterBase = virtualAddr[npeId];
|
||||
npeInfo->statusRegister = virtualAddr[npeId] + IX_NPEMH_NPESTAT_OFFSET;
|
||||
npeInfo->controlRegister = virtualAddr[npeId] + IX_NPEMH_NPECTL_OFFSET;
|
||||
npeInfo->inFifoRegister = virtualAddr[npeId] + IX_NPEMH_NPEFIFO_OFFSET;
|
||||
npeInfo->outFifoRegister = virtualAddr[npeId] + IX_NPEMH_NPEFIFO_OFFSET;
|
||||
|
||||
/* for test purposes - to verify the register addresses */
|
||||
IX_NPEMH_TRACE2 (IX_NPEMH_DEBUG, "NPE %d status register = "
|
||||
"0x%08X\n", npeId, npeInfo->statusRegister);
|
||||
IX_NPEMH_TRACE2 (IX_NPEMH_DEBUG, "NPE %d control register = "
|
||||
"0x%08X\n", npeId, npeInfo->controlRegister);
|
||||
IX_NPEMH_TRACE2 (IX_NPEMH_DEBUG, "NPE %d inFifo register = "
|
||||
"0x%08X\n", npeId, npeInfo->inFifoRegister);
|
||||
IX_NPEMH_TRACE2 (IX_NPEMH_DEBUG, "NPE %d outFifo register = "
|
||||
"0x%08X\n", npeId, npeInfo->outFifoRegister);
|
||||
|
||||
/* connect our ISR to the NPE interrupt */
|
||||
(void) ixOsalIrqBind (
|
||||
npeInfo->interruptId, ixNpeMhConfigIsr, (void *)npeId);
|
||||
|
||||
/* initialise a mutex for this NPE */
|
||||
(void) ixOsalMutexInit (&npeInfo->mutex);
|
||||
|
||||
/* if we should service the NPE's "outFIFO not empty" interrupt */
|
||||
if (npeInterrupts == IX_NPEMH_NPEINTERRUPTS_YES)
|
||||
{
|
||||
/* enable the NPE's "outFIFO not empty" interrupt */
|
||||
ixNpeMhConfigNpeInterruptEnable (npeId);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* disable the NPE's "outFIFO not empty" interrupt */
|
||||
ixNpeMhConfigNpeInterruptDisable (npeId);
|
||||
}
|
||||
}
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
|
||||
"ixNpeMhConfigInitialize\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhConfigUninit
|
||||
*/
|
||||
|
||||
void ixNpeMhConfigUninit (void)
|
||||
{
|
||||
IxNpeMhNpeId npeId;
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
|
||||
"ixNpeMhConfigUninit\n");
|
||||
|
||||
/* for each NPE ... */
|
||||
for (npeId = 0; npeId < IX_NPEMH_NUM_NPES; npeId++)
|
||||
{
|
||||
/* declare a convenience pointer */
|
||||
IxNpeMhConfigNpeInfo *npeInfo = &ixNpeMhConfigNpeInfo[npeId];
|
||||
|
||||
/* disconnect ISR */
|
||||
ixOsalIrqUnbind(npeInfo->interruptId);
|
||||
|
||||
/* destroy mutex associated with this NPE */
|
||||
ixOsalMutexDestroy(&npeInfo->mutex);
|
||||
|
||||
IX_OSAL_MEM_UNMAP (npeInfo->virtualRegisterBase);
|
||||
|
||||
npeInfo->virtualRegisterBase = 0;
|
||||
npeInfo->statusRegister = 0;
|
||||
npeInfo->controlRegister = 0;
|
||||
npeInfo->inFifoRegister = 0;
|
||||
npeInfo->outFifoRegister = 0;
|
||||
}
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
|
||||
"ixNpeMhConfigUninit\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhConfigIsrRegister
|
||||
*/
|
||||
|
||||
void ixNpeMhConfigIsrRegister (
|
||||
IxNpeMhNpeId npeId,
|
||||
IxNpeMhConfigIsr isr)
|
||||
{
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
|
||||
"ixNpeMhConfigIsrRegister\n");
|
||||
|
||||
/* check if there is already an ISR registered for this NPE */
|
||||
if (ixNpeMhConfigNpeInfo[npeId].isr != NULL)
|
||||
{
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_DEBUG, "Over-writing registered NPE ISR\n");
|
||||
}
|
||||
|
||||
/* save the ISR routine with the NPE info */
|
||||
ixNpeMhConfigNpeInfo[npeId].isr = isr;
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
|
||||
"ixNpeMhConfigIsrRegister\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhConfigNpeInterruptEnable
|
||||
*/
|
||||
|
||||
BOOL ixNpeMhConfigNpeInterruptEnable (
|
||||
IxNpeMhNpeId npeId)
|
||||
{
|
||||
UINT32 ofe;
|
||||
volatile UINT32 *controlReg =
|
||||
(UINT32 *)ixNpeMhConfigNpeInfo[npeId].controlRegister;
|
||||
|
||||
/* get the OFE (OutFifoEnable) bit of the control register */
|
||||
IX_NPEMH_REGISTER_READ_BITS (controlReg, &ofe, IX_NPEMH_NPE_CTL_OFE);
|
||||
|
||||
/* if the interrupt is disabled then we must enable it */
|
||||
if (!ofe)
|
||||
{
|
||||
/* set the OFE (OutFifoEnable) bit of the control register */
|
||||
/* we must set the OFEWE (OutFifoEnableWriteEnable) at the same */
|
||||
/* time for the write to have effect */
|
||||
IX_NPEMH_REGISTER_WRITE_BITS (controlReg,
|
||||
(IX_NPEMH_NPE_CTL_OFE |
|
||||
IX_NPEMH_NPE_CTL_OFEWE),
|
||||
(IX_NPEMH_NPE_CTL_OFE |
|
||||
IX_NPEMH_NPE_CTL_OFEWE));
|
||||
}
|
||||
|
||||
/* return the previous state of the interrupt */
|
||||
return (ofe != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhConfigNpeInterruptDisable
|
||||
*/
|
||||
|
||||
BOOL ixNpeMhConfigNpeInterruptDisable (
|
||||
IxNpeMhNpeId npeId)
|
||||
{
|
||||
UINT32 ofe;
|
||||
volatile UINT32 *controlReg =
|
||||
(UINT32 *)ixNpeMhConfigNpeInfo[npeId].controlRegister;
|
||||
|
||||
/* get the OFE (OutFifoEnable) bit of the control register */
|
||||
IX_NPEMH_REGISTER_READ_BITS (controlReg, &ofe, IX_NPEMH_NPE_CTL_OFE);
|
||||
|
||||
/* if the interrupt is enabled then we must disable it */
|
||||
if (ofe)
|
||||
{
|
||||
/* unset the OFE (OutFifoEnable) bit of the control register */
|
||||
/* we must set the OFEWE (OutFifoEnableWriteEnable) at the same */
|
||||
/* time for the write to have effect */
|
||||
IX_NPEMH_REGISTER_WRITE_BITS (controlReg,
|
||||
(0 |
|
||||
IX_NPEMH_NPE_CTL_OFEWE),
|
||||
(IX_NPEMH_NPE_CTL_OFE |
|
||||
IX_NPEMH_NPE_CTL_OFEWE));
|
||||
}
|
||||
|
||||
/* return the previous state of the interrupt */
|
||||
return (ofe != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhConfigMessageIdGet
|
||||
*/
|
||||
|
||||
IxNpeMhMessageId ixNpeMhConfigMessageIdGet (
|
||||
IxNpeMhMessage message)
|
||||
{
|
||||
/* return the most-significant byte of the first word of the */
|
||||
/* message */
|
||||
return ((IxNpeMhMessageId) ((message.data[0] >> 24) & 0xFF));
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhConfigNpeIdIsValid
|
||||
*/
|
||||
|
||||
BOOL ixNpeMhConfigNpeIdIsValid (
|
||||
IxNpeMhNpeId npeId)
|
||||
{
|
||||
/* check that the npeId parameter is within the range of valid IDs */
|
||||
return (npeId >= 0 && npeId < IX_NPEMH_NUM_NPES);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhConfigLockGet
|
||||
*/
|
||||
|
||||
void ixNpeMhConfigLockGet (
|
||||
IxNpeMhNpeId npeId)
|
||||
{
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
|
||||
"ixNpeMhConfigLockGet\n");
|
||||
|
||||
/* lock the mutex for this NPE */
|
||||
(void) ixOsalMutexLock (&ixNpeMhConfigNpeInfo[npeId].mutex,
|
||||
IX_OSAL_WAIT_FOREVER);
|
||||
|
||||
/* disable the NPE's "outFIFO not empty" interrupt */
|
||||
ixNpeMhConfigNpeInfo[npeId].oldInterruptState =
|
||||
ixNpeMhConfigNpeInterruptDisable (npeId);
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
|
||||
"ixNpeMhConfigLockGet\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhConfigLockRelease
|
||||
*/
|
||||
|
||||
void ixNpeMhConfigLockRelease (
|
||||
IxNpeMhNpeId npeId)
|
||||
{
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
|
||||
"ixNpeMhConfigLockRelease\n");
|
||||
|
||||
/* if the interrupt was previously enabled */
|
||||
if (ixNpeMhConfigNpeInfo[npeId].oldInterruptState)
|
||||
{
|
||||
/* enable the NPE's "outFIFO not empty" interrupt */
|
||||
ixNpeMhConfigNpeInfo[npeId].oldInterruptState =
|
||||
ixNpeMhConfigNpeInterruptEnable (npeId);
|
||||
}
|
||||
|
||||
/* unlock the mutex for this NPE */
|
||||
(void) ixOsalMutexUnlock (&ixNpeMhConfigNpeInfo[npeId].mutex);
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
|
||||
"ixNpeMhConfigLockRelease\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhConfigInFifoWrite
|
||||
*/
|
||||
|
||||
IX_STATUS ixNpeMhConfigInFifoWrite (
|
||||
IxNpeMhNpeId npeId,
|
||||
IxNpeMhMessage message)
|
||||
{
|
||||
volatile UINT32 *npeInFifo =
|
||||
(UINT32 *)ixNpeMhConfigNpeInfo[npeId].inFifoRegister;
|
||||
UINT32 retriesCount = 0;
|
||||
|
||||
/* write the first word of the message to the NPE's inFIFO */
|
||||
IX_NPEMH_REGISTER_WRITE (npeInFifo, message.data[0]);
|
||||
|
||||
/* need to wait for room to write second word - see SCR #493,
|
||||
poll for maximum number of retries, if exceed maximum
|
||||
retries, exit from while loop */
|
||||
while ((IX_NPE_MH_MAX_NUM_OF_RETRIES > retriesCount)
|
||||
&& ixNpeMhConfigInFifoIsFull (npeId))
|
||||
{
|
||||
retriesCount++;
|
||||
}
|
||||
|
||||
/* Return TIMEOUT status to caller, indicate that NPE Hang / Halt */
|
||||
if (IX_NPE_MH_MAX_NUM_OF_RETRIES == retriesCount)
|
||||
{
|
||||
return IX_NPEMH_CRITICAL_NPE_ERR;
|
||||
}
|
||||
|
||||
/* write the second word of the message to the NPE's inFIFO */
|
||||
IX_NPEMH_REGISTER_WRITE (npeInFifo, message.data[1]);
|
||||
|
||||
/* record in the stats the maximum number of retries needed */
|
||||
if (ixNpeMhConfigStats[npeId].maxInFifoFullRetries < retriesCount)
|
||||
{
|
||||
ixNpeMhConfigStats[npeId].maxInFifoFullRetries = retriesCount;
|
||||
}
|
||||
|
||||
/* update statistical info */
|
||||
ixNpeMhConfigStats[npeId].inFifoWrites++;
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhConfigOutFifoRead
|
||||
*/
|
||||
|
||||
IX_STATUS ixNpeMhConfigOutFifoRead (
|
||||
IxNpeMhNpeId npeId,
|
||||
IxNpeMhMessage *message)
|
||||
{
|
||||
volatile UINT32 *npeOutFifo =
|
||||
(UINT32 *)ixNpeMhConfigNpeInfo[npeId].outFifoRegister;
|
||||
UINT32 retriesCount = 0;
|
||||
|
||||
/* read the first word of the message from the NPE's outFIFO */
|
||||
IX_NPEMH_REGISTER_READ (npeOutFifo, &message->data[0]);
|
||||
|
||||
/* need to wait for NPE to write second word - see SCR #493
|
||||
poll for maximum number of retries, if exceed maximum
|
||||
retries, exit from while loop */
|
||||
while ((IX_NPE_MH_MAX_NUM_OF_RETRIES > retriesCount)
|
||||
&& ixNpeMhConfigOutFifoIsEmpty (npeId))
|
||||
{
|
||||
retriesCount++;
|
||||
}
|
||||
|
||||
/* Return TIMEOUT status to caller, indicate that NPE Hang / Halt */
|
||||
if (IX_NPE_MH_MAX_NUM_OF_RETRIES == retriesCount)
|
||||
{
|
||||
return IX_NPEMH_CRITICAL_NPE_ERR;
|
||||
}
|
||||
|
||||
/* read the second word of the message from the NPE's outFIFO */
|
||||
IX_NPEMH_REGISTER_READ (npeOutFifo, &message->data[1]);
|
||||
|
||||
/* record in the stats the maximum number of retries needed */
|
||||
if (ixNpeMhConfigStats[npeId].maxOutFifoEmptyRetries < retriesCount)
|
||||
{
|
||||
ixNpeMhConfigStats[npeId].maxOutFifoEmptyRetries = retriesCount;
|
||||
}
|
||||
|
||||
/* update statistical info */
|
||||
ixNpeMhConfigStats[npeId].outFifoReads++;
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhConfigShow
|
||||
*/
|
||||
|
||||
void ixNpeMhConfigShow (
|
||||
IxNpeMhNpeId npeId)
|
||||
{
|
||||
/* show the message fifo read counter */
|
||||
IX_NPEMH_SHOW ("Message FIFO reads",
|
||||
ixNpeMhConfigStats[npeId].outFifoReads);
|
||||
|
||||
/* show the message fifo write counter */
|
||||
IX_NPEMH_SHOW ("Message FIFO writes",
|
||||
ixNpeMhConfigStats[npeId].inFifoWrites);
|
||||
|
||||
/* show the max retries performed when inFIFO full */
|
||||
IX_NPEMH_SHOW ("Max inFIFO Full retries",
|
||||
ixNpeMhConfigStats[npeId].maxInFifoFullRetries);
|
||||
|
||||
/* show the max retries performed when outFIFO empty */
|
||||
IX_NPEMH_SHOW ("Max outFIFO Empty retries",
|
||||
ixNpeMhConfigStats[npeId].maxOutFifoEmptyRetries);
|
||||
|
||||
/* show the current status of the inFifo */
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT,
|
||||
"InFifo is %s and %s\n",
|
||||
(ixNpeMhConfigInFifoIsEmpty (npeId) ?
|
||||
(int) "EMPTY" : (int) "NOT EMPTY"),
|
||||
(ixNpeMhConfigInFifoIsFull (npeId) ?
|
||||
(int) "FULL" : (int) "NOT FULL"),
|
||||
0, 0, 0, 0);
|
||||
|
||||
/* show the current status of the outFifo */
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT,
|
||||
"OutFifo is %s and %s\n",
|
||||
(ixNpeMhConfigOutFifoIsEmpty (npeId) ?
|
||||
(int) "EMPTY" : (int) "NOT EMPTY"),
|
||||
(ixNpeMhConfigOutFifoIsFull (npeId) ?
|
||||
(int) "FULL" : (int) "NOT FULL"),
|
||||
0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhConfigShowReset
|
||||
*/
|
||||
|
||||
void ixNpeMhConfigShowReset (
|
||||
IxNpeMhNpeId npeId)
|
||||
{
|
||||
/* reset the message fifo read counter */
|
||||
ixNpeMhConfigStats[npeId].outFifoReads = 0;
|
||||
|
||||
/* reset the message fifo write counter */
|
||||
ixNpeMhConfigStats[npeId].inFifoWrites = 0;
|
||||
|
||||
/* reset the max inFIFO Full retries counter */
|
||||
ixNpeMhConfigStats[npeId].maxInFifoFullRetries = 0;
|
||||
|
||||
/* reset the max outFIFO empty retries counter */
|
||||
ixNpeMhConfigStats[npeId].maxOutFifoEmptyRetries = 0;
|
||||
}
|
||||
|
||||
|
320
cpu/ixp/npe/IxNpeMhReceive.c
Normal file
320
cpu/ixp/npe/IxNpeMhReceive.c
Normal file
@ -0,0 +1,320 @@
|
||||
/**
|
||||
* @file IxNpeMhReceive.c
|
||||
*
|
||||
* @author Intel Corporation
|
||||
* @date 18 Jan 2002
|
||||
*
|
||||
* @brief This file contains the implementation of the private API for the
|
||||
* Receive module.
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
/*
|
||||
* Put the system defined include files required.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Put the user defined include files required.
|
||||
*/
|
||||
#include "IxOsal.h"
|
||||
#include "IxNpeMhMacros_p.h"
|
||||
#include "IxNpeMhConfig_p.h"
|
||||
#include "IxNpeMhReceive_p.h"
|
||||
#include "IxNpeMhSolicitedCbMgr_p.h"
|
||||
#include "IxNpeMhUnsolicitedCbMgr_p.h"
|
||||
|
||||
/*
|
||||
* #defines and macros used in this file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Typedefs whose scope is limited to this file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @struct IxNpeMhReceiveStats
|
||||
*
|
||||
* @brief This structure is used to maintain statistics for the Receive
|
||||
* module.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 isrs; /**< receive ISR invocations */
|
||||
UINT32 receives; /**< receive messages invocations */
|
||||
UINT32 messages; /**< messages received */
|
||||
UINT32 solicited; /**< solicited messages received */
|
||||
UINT32 unsolicited; /**< unsolicited messages received */
|
||||
UINT32 callbacks; /**< callbacks invoked */
|
||||
} IxNpeMhReceiveStats;
|
||||
|
||||
/*
|
||||
* Variable declarations global to this file only. Externs are followed by
|
||||
* static variables.
|
||||
*/
|
||||
|
||||
PRIVATE IxNpeMhReceiveStats ixNpeMhReceiveStats[IX_NPEMH_NUM_NPES];
|
||||
|
||||
/*
|
||||
* Extern function prototypes.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Static function prototypes.
|
||||
*/
|
||||
PRIVATE
|
||||
void ixNpeMhReceiveIsr (int npeId);
|
||||
|
||||
PRIVATE
|
||||
void ixNpeMhReceiveIsr (int npeId)
|
||||
{
|
||||
int lockKey;
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
|
||||
"ixNpeMhReceiveIsr\n");
|
||||
|
||||
lockKey = ixOsalIrqLock ();
|
||||
|
||||
/* invoke the message receive routine to get messages from the NPE */
|
||||
ixNpeMhReceiveMessagesReceive (npeId);
|
||||
|
||||
/* update statistical info */
|
||||
ixNpeMhReceiveStats[npeId].isrs++;
|
||||
|
||||
ixOsalIrqUnlock (lockKey);
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
|
||||
"ixNpeMhReceiveIsr\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhReceiveInitialize
|
||||
*/
|
||||
|
||||
void ixNpeMhReceiveInitialize (void)
|
||||
{
|
||||
IxNpeMhNpeId npeId = 0;
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
|
||||
"ixNpeMhReceiveInitialize\n");
|
||||
|
||||
/* for each NPE ... */
|
||||
for (npeId = 0; npeId < IX_NPEMH_NUM_NPES; npeId++)
|
||||
{
|
||||
/* register our internal ISR for the NPE to handle "outFIFO not */
|
||||
/* empty" interrupts */
|
||||
ixNpeMhConfigIsrRegister (npeId, ixNpeMhReceiveIsr);
|
||||
}
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
|
||||
"ixNpeMhReceiveInitialize\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhReceiveMessagesReceive
|
||||
*/
|
||||
|
||||
IX_STATUS ixNpeMhReceiveMessagesReceive (
|
||||
IxNpeMhNpeId npeId)
|
||||
{
|
||||
IxNpeMhMessage message = { { 0, 0 } };
|
||||
IxNpeMhMessageId messageId = 0;
|
||||
IxNpeMhCallback callback = NULL;
|
||||
IX_STATUS status;
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
|
||||
"ixNpeMhReceiveMessagesReceive\n");
|
||||
|
||||
/* update statistical info */
|
||||
ixNpeMhReceiveStats[npeId].receives++;
|
||||
|
||||
/* while the NPE has messages in its outFIFO */
|
||||
while (!ixNpeMhConfigOutFifoIsEmpty (npeId))
|
||||
{
|
||||
/* read a message from the NPE's outFIFO */
|
||||
status = ixNpeMhConfigOutFifoRead (npeId, &message);
|
||||
|
||||
if (IX_SUCCESS != status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
/* get the ID of the message */
|
||||
messageId = ixNpeMhConfigMessageIdGet (message);
|
||||
|
||||
IX_NPEMH_TRACE2 (IX_NPEMH_DEBUG,
|
||||
"Received message from NPE %d with ID 0x%02X\n",
|
||||
npeId, messageId);
|
||||
|
||||
/* update statistical info */
|
||||
ixNpeMhReceiveStats[npeId].messages++;
|
||||
|
||||
/* try to find a matching unsolicited callback for this message. */
|
||||
|
||||
/* we assume the message is unsolicited. only if there is no */
|
||||
/* unsolicited callback for this message type do we assume the */
|
||||
/* message is solicited. it is much faster to check for an */
|
||||
/* unsolicited callback, so doing this check first should result */
|
||||
/* in better performance. */
|
||||
|
||||
ixNpeMhUnsolicitedCbMgrCallbackRetrieve (
|
||||
npeId, messageId, &callback);
|
||||
|
||||
if (callback != NULL)
|
||||
{
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_DEBUG,
|
||||
"Found matching unsolicited callback\n");
|
||||
|
||||
/* update statistical info */
|
||||
ixNpeMhReceiveStats[npeId].unsolicited++;
|
||||
}
|
||||
|
||||
/* if no unsolicited callback was found try to find a matching */
|
||||
/* solicited callback for this message */
|
||||
if (callback == NULL)
|
||||
{
|
||||
ixNpeMhSolicitedCbMgrCallbackRetrieve (
|
||||
npeId, messageId, &callback);
|
||||
|
||||
if (callback != NULL)
|
||||
{
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_DEBUG,
|
||||
"Found matching solicited callback\n");
|
||||
|
||||
/* update statistical info */
|
||||
ixNpeMhReceiveStats[npeId].solicited++;
|
||||
}
|
||||
}
|
||||
|
||||
/* if a callback (either unsolicited or solicited) was found */
|
||||
if (callback != NULL)
|
||||
{
|
||||
/* invoke the callback to pass the message back to the client */
|
||||
callback (npeId, message);
|
||||
|
||||
/* update statistical info */
|
||||
ixNpeMhReceiveStats[npeId].callbacks++;
|
||||
}
|
||||
else /* no callback (neither unsolicited nor solicited) was found */
|
||||
{
|
||||
IX_NPEMH_TRACE2 (IX_NPEMH_WARNING,
|
||||
"No matching callback for NPE %d"
|
||||
" and ID 0x%02X, discarding message\n",
|
||||
npeId, messageId);
|
||||
|
||||
/* the message will be discarded. this is normal behaviour */
|
||||
/* if the client passes a NULL solicited callback when */
|
||||
/* sending a message. this indicates that the client is not */
|
||||
/* interested in receiving the response. alternatively a */
|
||||
/* NULL callback here may signify an unsolicited message */
|
||||
/* with no appropriate registered callback. */
|
||||
}
|
||||
}
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
|
||||
"ixNpeMhReceiveMessagesReceive\n");
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhReceiveShow
|
||||
*/
|
||||
|
||||
void ixNpeMhReceiveShow (
|
||||
IxNpeMhNpeId npeId)
|
||||
{
|
||||
/* show the ISR invocation counter */
|
||||
IX_NPEMH_SHOW ("Receive ISR invocations",
|
||||
ixNpeMhReceiveStats[npeId].isrs);
|
||||
|
||||
/* show the receive message invocation counter */
|
||||
IX_NPEMH_SHOW ("Receive messages invocations",
|
||||
ixNpeMhReceiveStats[npeId].receives);
|
||||
|
||||
/* show the message received counter */
|
||||
IX_NPEMH_SHOW ("Messages received",
|
||||
ixNpeMhReceiveStats[npeId].messages);
|
||||
|
||||
/* show the solicited message counter */
|
||||
IX_NPEMH_SHOW ("Solicited messages received",
|
||||
ixNpeMhReceiveStats[npeId].solicited);
|
||||
|
||||
/* show the unsolicited message counter */
|
||||
IX_NPEMH_SHOW ("Unsolicited messages received",
|
||||
ixNpeMhReceiveStats[npeId].unsolicited);
|
||||
|
||||
/* show the callback invoked counter */
|
||||
IX_NPEMH_SHOW ("Callbacks invoked",
|
||||
ixNpeMhReceiveStats[npeId].callbacks);
|
||||
|
||||
/* show the message discarded counter */
|
||||
IX_NPEMH_SHOW ("Received messages discarded",
|
||||
(ixNpeMhReceiveStats[npeId].messages -
|
||||
ixNpeMhReceiveStats[npeId].callbacks));
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhReceiveShowReset
|
||||
*/
|
||||
|
||||
void ixNpeMhReceiveShowReset (
|
||||
IxNpeMhNpeId npeId)
|
||||
{
|
||||
/* reset the ISR invocation counter */
|
||||
ixNpeMhReceiveStats[npeId].isrs = 0;
|
||||
|
||||
/* reset the receive message invocation counter */
|
||||
ixNpeMhReceiveStats[npeId].receives = 0;
|
||||
|
||||
/* reset the message received counter */
|
||||
ixNpeMhReceiveStats[npeId].messages = 0;
|
||||
|
||||
/* reset the solicited message counter */
|
||||
ixNpeMhReceiveStats[npeId].solicited = 0;
|
||||
|
||||
/* reset the unsolicited message counter */
|
||||
ixNpeMhReceiveStats[npeId].unsolicited = 0;
|
||||
|
||||
/* reset the callback invoked counter */
|
||||
ixNpeMhReceiveStats[npeId].callbacks = 0;
|
||||
}
|
307
cpu/ixp/npe/IxNpeMhSend.c
Normal file
307
cpu/ixp/npe/IxNpeMhSend.c
Normal file
@ -0,0 +1,307 @@
|
||||
/**
|
||||
* @file IxNpeMhSend.c
|
||||
*
|
||||
* @author Intel Corporation
|
||||
* @date 18 Jan 2002
|
||||
*
|
||||
* @brief This file contains the implementation of the private API for the
|
||||
* Send module.
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
/*
|
||||
* Put the system defined include files required.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Put the user defined include files required.
|
||||
*/
|
||||
|
||||
#include "IxNpeMhMacros_p.h"
|
||||
|
||||
#include "IxNpeMhConfig_p.h"
|
||||
#include "IxNpeMhSend_p.h"
|
||||
#include "IxNpeMhSolicitedCbMgr_p.h"
|
||||
|
||||
/*
|
||||
* #defines and macros used in this file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def IX_NPEMH_INFIFO_RETRY_DELAY_US
|
||||
*
|
||||
* @brief Amount of time (uSecs) to delay between retries
|
||||
* while inFIFO is Full when attempting to send a message
|
||||
*/
|
||||
#define IX_NPEMH_INFIFO_RETRY_DELAY_US (1)
|
||||
|
||||
|
||||
/*
|
||||
* Typedefs whose scope is limited to this file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @struct IxNpeMhSendStats
|
||||
*
|
||||
* @brief This structure is used to maintain statistics for the Send
|
||||
* module.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 sends; /**< send invocations */
|
||||
UINT32 sendWithResponses; /**< send with response invocations */
|
||||
UINT32 queueFulls; /**< fifo queue full occurrences */
|
||||
UINT32 queueFullRetries; /**< fifo queue full retry occurrences */
|
||||
UINT32 maxQueueFullRetries; /**< max fifo queue full retries */
|
||||
UINT32 callbackFulls; /**< callback list full occurrences */
|
||||
} IxNpeMhSendStats;
|
||||
|
||||
/*
|
||||
* Variable declarations global to this file only. Externs are followed by
|
||||
* static variables.
|
||||
*/
|
||||
|
||||
PRIVATE IxNpeMhSendStats ixNpeMhSendStats[IX_NPEMH_NUM_NPES];
|
||||
|
||||
/*
|
||||
* Extern function prototypes.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Static function prototypes.
|
||||
*/
|
||||
PRIVATE
|
||||
BOOL ixNpeMhSendInFifoIsFull(
|
||||
IxNpeMhNpeId npeId,
|
||||
UINT32 maxSendRetries);
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhSendInFifoIsFull
|
||||
*/
|
||||
|
||||
PRIVATE
|
||||
BOOL ixNpeMhSendInFifoIsFull(
|
||||
IxNpeMhNpeId npeId,
|
||||
UINT32 maxSendRetries)
|
||||
{
|
||||
BOOL isFull = FALSE;
|
||||
UINT32 numRetries = 0;
|
||||
|
||||
/* check the NPE's inFIFO */
|
||||
isFull = ixNpeMhConfigInFifoIsFull (npeId);
|
||||
|
||||
/* we retry a few times, just to give the NPE a chance to read from */
|
||||
/* the FIFO if the FIFO is currently full */
|
||||
while (isFull && (numRetries++ < maxSendRetries))
|
||||
{
|
||||
if (numRetries >= IX_NPEMH_SEND_RETRIES_DEFAULT)
|
||||
{
|
||||
/* Delay here for as short a time as possible (1 us). */
|
||||
/* Adding a delay here should ensure we are not hogging */
|
||||
/* the AHB bus while we are retrying */
|
||||
ixOsalBusySleep (IX_NPEMH_INFIFO_RETRY_DELAY_US);
|
||||
}
|
||||
|
||||
/* re-check the NPE's inFIFO */
|
||||
isFull = ixNpeMhConfigInFifoIsFull (npeId);
|
||||
|
||||
/* update statistical info */
|
||||
ixNpeMhSendStats[npeId].queueFullRetries++;
|
||||
}
|
||||
|
||||
/* record the highest number of retries that occurred */
|
||||
if (ixNpeMhSendStats[npeId].maxQueueFullRetries < numRetries)
|
||||
{
|
||||
ixNpeMhSendStats[npeId].maxQueueFullRetries = numRetries;
|
||||
}
|
||||
|
||||
if (isFull)
|
||||
{
|
||||
/* update statistical info */
|
||||
ixNpeMhSendStats[npeId].queueFulls++;
|
||||
}
|
||||
|
||||
return isFull;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhSendMessageSend
|
||||
*/
|
||||
|
||||
IX_STATUS ixNpeMhSendMessageSend (
|
||||
IxNpeMhNpeId npeId,
|
||||
IxNpeMhMessage message,
|
||||
UINT32 maxSendRetries)
|
||||
{
|
||||
IX_STATUS status;
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
|
||||
"ixNpeMhSendMessageSend\n");
|
||||
|
||||
/* update statistical info */
|
||||
ixNpeMhSendStats[npeId].sends++;
|
||||
|
||||
/* check if the NPE's inFIFO is full - if so return an error */
|
||||
if (ixNpeMhSendInFifoIsFull (npeId, maxSendRetries))
|
||||
{
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_WARNING, "NPE's inFIFO is full\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* write the message to the NPE's inFIFO */
|
||||
status = ixNpeMhConfigInFifoWrite (npeId, message);
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
|
||||
"ixNpeMhSendMessageSend\n");
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhSendMessageWithResponseSend
|
||||
*/
|
||||
|
||||
IX_STATUS ixNpeMhSendMessageWithResponseSend (
|
||||
IxNpeMhNpeId npeId,
|
||||
IxNpeMhMessage message,
|
||||
IxNpeMhMessageId solicitedMessageId,
|
||||
IxNpeMhCallback solicitedCallback,
|
||||
UINT32 maxSendRetries)
|
||||
{
|
||||
IX_STATUS status = IX_SUCCESS;
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
|
||||
"ixNpeMhSendMessageWithResponseSend\n");
|
||||
|
||||
/* update statistical info */
|
||||
ixNpeMhSendStats[npeId].sendWithResponses++;
|
||||
|
||||
/* sr: this sleep will call the receive routine (no interrupts used!!!) */
|
||||
ixOsalSleep (IX_NPEMH_INFIFO_RETRY_DELAY_US);
|
||||
|
||||
/* check if the NPE's inFIFO is full - if so return an error */
|
||||
if (ixNpeMhSendInFifoIsFull (npeId, maxSendRetries))
|
||||
{
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_WARNING, "NPE's inFIFO is full\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* save the solicited callback */
|
||||
status = ixNpeMhSolicitedCbMgrCallbackSave (
|
||||
npeId, solicitedMessageId, solicitedCallback);
|
||||
if (status != IX_SUCCESS)
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("Failed to save solicited callback\n");
|
||||
|
||||
/* update statistical info */
|
||||
ixNpeMhSendStats[npeId].callbackFulls++;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* write the message to the NPE's inFIFO */
|
||||
status = ixNpeMhConfigInFifoWrite (npeId, message);
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
|
||||
"ixNpeMhSendMessageWithResponseSend\n");
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhSendShow
|
||||
*/
|
||||
|
||||
void ixNpeMhSendShow (
|
||||
IxNpeMhNpeId npeId)
|
||||
{
|
||||
/* show the message send invocation counter */
|
||||
IX_NPEMH_SHOW ("Send invocations",
|
||||
ixNpeMhSendStats[npeId].sends);
|
||||
|
||||
/* show the message send with response invocation counter */
|
||||
IX_NPEMH_SHOW ("Send with response invocations",
|
||||
ixNpeMhSendStats[npeId].sendWithResponses);
|
||||
|
||||
/* show the fifo queue full occurrence counter */
|
||||
IX_NPEMH_SHOW ("Fifo queue full occurrences",
|
||||
ixNpeMhSendStats[npeId].queueFulls);
|
||||
|
||||
/* show the fifo queue full retry occurrence counter */
|
||||
IX_NPEMH_SHOW ("Fifo queue full retry occurrences",
|
||||
ixNpeMhSendStats[npeId].queueFullRetries);
|
||||
|
||||
/* show the fifo queue full maximum retries counter */
|
||||
IX_NPEMH_SHOW ("Maximum fifo queue full retries",
|
||||
ixNpeMhSendStats[npeId].maxQueueFullRetries);
|
||||
|
||||
/* show the callback list full occurrence counter */
|
||||
IX_NPEMH_SHOW ("Solicited callback list full occurrences",
|
||||
ixNpeMhSendStats[npeId].callbackFulls);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhSendShowReset
|
||||
*/
|
||||
|
||||
void ixNpeMhSendShowReset (
|
||||
IxNpeMhNpeId npeId)
|
||||
{
|
||||
/* reset the message send invocation counter */
|
||||
ixNpeMhSendStats[npeId].sends = 0;
|
||||
|
||||
/* reset the message send with response invocation counter */
|
||||
ixNpeMhSendStats[npeId].sendWithResponses = 0;
|
||||
|
||||
/* reset the fifo queue full occurrence counter */
|
||||
ixNpeMhSendStats[npeId].queueFulls = 0;
|
||||
|
||||
/* reset the fifo queue full retry occurrence counter */
|
||||
ixNpeMhSendStats[npeId].queueFullRetries = 0;
|
||||
|
||||
/* reset the max fifo queue full retries counter */
|
||||
ixNpeMhSendStats[npeId].maxQueueFullRetries = 0;
|
||||
|
||||
/* reset the callback list full occurrence counter */
|
||||
ixNpeMhSendStats[npeId].callbackFulls = 0;
|
||||
}
|
358
cpu/ixp/npe/IxNpeMhSolicitedCbMgr.c
Normal file
358
cpu/ixp/npe/IxNpeMhSolicitedCbMgr.c
Normal file
@ -0,0 +1,358 @@
|
||||
/**
|
||||
* @file IxNpeMhSolicitedCbMgr.c
|
||||
*
|
||||
* @author Intel Corporation
|
||||
* @date 18 Jan 2002
|
||||
*
|
||||
* @brief This file contains the implementation of the private API for the
|
||||
* Solicited Callback Manager module.
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
#ifndef IXNPEMHCONFIG_P_H
|
||||
# define IXNPEMHSOLICITEDCBMGR_C
|
||||
#else
|
||||
# error "Error, IxNpeMhConfig_p.h should not be included before this definition."
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Put the system defined include files required.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Put the user defined include files required.
|
||||
*/
|
||||
|
||||
#include "IxOsal.h"
|
||||
|
||||
#include "IxNpeMhMacros_p.h"
|
||||
#include "IxNpeMhSolicitedCbMgr_p.h"
|
||||
#include "IxNpeMhConfig_p.h"
|
||||
/*
|
||||
* #defines and macros used in this file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Typedefs whose scope is limited to this file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @struct IxNpeMhSolicitedCallbackListEntry
|
||||
*
|
||||
* @brief This structure is used to store the information associated with
|
||||
* an entry in the callback list. This consists of the ID of the send
|
||||
* message (which indicates the ID of the corresponding response message)
|
||||
* and the callback function pointer itself.
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct IxNpeMhSolicitedCallbackListEntry
|
||||
{
|
||||
/** message ID */
|
||||
IxNpeMhMessageId messageId;
|
||||
|
||||
/** callback function pointer */
|
||||
IxNpeMhCallback callback;
|
||||
|
||||
/** pointer to next entry in the list */
|
||||
struct IxNpeMhSolicitedCallbackListEntry *next;
|
||||
} IxNpeMhSolicitedCallbackListEntry;
|
||||
|
||||
/**
|
||||
* @struct IxNpeMhSolicitedCallbackList
|
||||
*
|
||||
* @brief This structure is used to maintain the list of response
|
||||
* callbacks. The number of entries in this list will be variable, and
|
||||
* they will be stored in a linked list fashion for ease of addition and
|
||||
* removal. The entries themselves are statically allocated, and are
|
||||
* organised into a "free" list and a "callback" list. Adding an entry
|
||||
* means taking an entry from the "free" list and adding it to the
|
||||
* "callback" list. Removing an entry means removing it from the
|
||||
* "callback" list and returning it to the "free" list.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/** pointer to the head of the free list */
|
||||
IxNpeMhSolicitedCallbackListEntry *freeHead;
|
||||
|
||||
/** pointer to the head of the callback list */
|
||||
IxNpeMhSolicitedCallbackListEntry *callbackHead;
|
||||
|
||||
/** pointer to the tail of the callback list */
|
||||
IxNpeMhSolicitedCallbackListEntry *callbackTail;
|
||||
|
||||
/** array of entries - the first entry is used as a dummy entry to */
|
||||
/* avoid the scenario of having an empty list, hence '+ 1' */
|
||||
IxNpeMhSolicitedCallbackListEntry entries[IX_NPEMH_MAX_CALLBACKS + 1];
|
||||
} IxNpeMhSolicitedCallbackList;
|
||||
|
||||
/**
|
||||
* @struct IxNpeMhSolicitedCbMgrStats
|
||||
*
|
||||
* @brief This structure is used to maintain statistics for the Solicited
|
||||
* Callback Manager module.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 saves; /**< callback list saves */
|
||||
UINT32 retrieves; /**< callback list retrieves */
|
||||
} IxNpeMhSolicitedCbMgrStats;
|
||||
|
||||
/*
|
||||
* Variable declarations global to this file only. Externs are followed by
|
||||
* static variables.
|
||||
*/
|
||||
|
||||
PRIVATE IxNpeMhSolicitedCallbackList
|
||||
ixNpeMhSolicitedCbMgrCallbackLists[IX_NPEMH_NUM_NPES];
|
||||
|
||||
PRIVATE IxNpeMhSolicitedCbMgrStats
|
||||
ixNpeMhSolicitedCbMgrStats[IX_NPEMH_NUM_NPES];
|
||||
|
||||
/*
|
||||
* Extern function prototypes.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Static function prototypes.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhSolicitedCbMgrInitialize
|
||||
*/
|
||||
|
||||
void ixNpeMhSolicitedCbMgrInitialize (void)
|
||||
{
|
||||
IxNpeMhNpeId npeId;
|
||||
UINT32 localIndex;
|
||||
IxNpeMhSolicitedCallbackList *list = NULL;
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
|
||||
"ixNpeMhSolicitedCbMgrInitialize\n");
|
||||
|
||||
/* for each NPE ... */
|
||||
for (npeId = 0; npeId < IX_NPEMH_NUM_NPES; npeId++)
|
||||
{
|
||||
/* initialise a pointer to the list for convenience */
|
||||
list = &ixNpeMhSolicitedCbMgrCallbackLists[npeId];
|
||||
|
||||
/* for each entry in the list, after the dummy entry ... */
|
||||
for (localIndex = 1; localIndex <= IX_NPEMH_MAX_CALLBACKS; localIndex++)
|
||||
{
|
||||
/* initialise the entry */
|
||||
list->entries[localIndex].messageId = 0x00;
|
||||
list->entries[localIndex].callback = NULL;
|
||||
|
||||
/* if this entry is before the last entry */
|
||||
if (localIndex < IX_NPEMH_MAX_CALLBACKS)
|
||||
{
|
||||
/* chain this entry to the following entry */
|
||||
list->entries[localIndex].next = &(list->entries[localIndex + 1]);
|
||||
}
|
||||
else /* this entry is the last entry */
|
||||
{
|
||||
/* the last entry isn't chained to anything */
|
||||
list->entries[localIndex].next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* set the free list pointer to point to the first real entry */
|
||||
/* (all real entries begin chained together on the free list) */
|
||||
list->freeHead = &(list->entries[1]);
|
||||
|
||||
/* set the callback list pointers to point to the dummy entry */
|
||||
/* (the callback list is initially empty) */
|
||||
list->callbackHead = &(list->entries[0]);
|
||||
list->callbackTail = &(list->entries[0]);
|
||||
}
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
|
||||
"ixNpeMhSolicitedCbMgrInitialize\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhSolicitedCbMgrCallbackSave
|
||||
*/
|
||||
|
||||
IX_STATUS ixNpeMhSolicitedCbMgrCallbackSave (
|
||||
IxNpeMhNpeId npeId,
|
||||
IxNpeMhMessageId solicitedMessageId,
|
||||
IxNpeMhCallback solicitedCallback)
|
||||
{
|
||||
IxNpeMhSolicitedCallbackList *list = NULL;
|
||||
IxNpeMhSolicitedCallbackListEntry *callbackEntry = NULL;
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
|
||||
"ixNpeMhSolicitedCbMgrCallbackSave\n");
|
||||
|
||||
/* initialise a pointer to the list for convenience */
|
||||
list = &ixNpeMhSolicitedCbMgrCallbackLists[npeId];
|
||||
|
||||
/* check to see if there are any entries in the free list */
|
||||
if (list->freeHead == NULL)
|
||||
{
|
||||
IX_NPEMH_ERROR_REPORT ("Solicited callback list is full\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* there is an entry in the free list we can use */
|
||||
|
||||
/* update statistical info */
|
||||
ixNpeMhSolicitedCbMgrStats[npeId].saves++;
|
||||
|
||||
/* remove a callback entry from the start of the free list */
|
||||
callbackEntry = list->freeHead;
|
||||
list->freeHead = callbackEntry->next;
|
||||
|
||||
/* fill in the callback entry with the new data */
|
||||
callbackEntry->messageId = solicitedMessageId;
|
||||
callbackEntry->callback = solicitedCallback;
|
||||
|
||||
/* the new callback entry will be added to the tail of the callback */
|
||||
/* list, so it isn't chained to anything */
|
||||
callbackEntry->next = NULL;
|
||||
|
||||
/* chain new callback entry to the last entry of the callback list */
|
||||
list->callbackTail->next = callbackEntry;
|
||||
list->callbackTail = callbackEntry;
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
|
||||
"ixNpeMhSolicitedCbMgrCallbackSave\n");
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhSolicitedCbMgrCallbackRetrieve
|
||||
*/
|
||||
|
||||
void ixNpeMhSolicitedCbMgrCallbackRetrieve (
|
||||
IxNpeMhNpeId npeId,
|
||||
IxNpeMhMessageId solicitedMessageId,
|
||||
IxNpeMhCallback *solicitedCallback)
|
||||
{
|
||||
IxNpeMhSolicitedCallbackList *list = NULL;
|
||||
IxNpeMhSolicitedCallbackListEntry *callbackEntry = NULL;
|
||||
IxNpeMhSolicitedCallbackListEntry *previousEntry = NULL;
|
||||
|
||||
/* initialise a pointer to the list for convenience */
|
||||
list = &ixNpeMhSolicitedCbMgrCallbackLists[npeId];
|
||||
|
||||
/* initialise the callback entry to the first entry of the callback */
|
||||
/* list - we must skip over the dummy entry, which is the previous */
|
||||
callbackEntry = list->callbackHead->next;
|
||||
previousEntry = list->callbackHead;
|
||||
|
||||
/* traverse the callback list looking for an entry with a matching */
|
||||
/* message ID. note we also save the previous entry's pointer to */
|
||||
/* allow us to unchain the matching entry from the callback list */
|
||||
while ((callbackEntry != NULL) &&
|
||||
(callbackEntry->messageId != solicitedMessageId))
|
||||
{
|
||||
previousEntry = callbackEntry;
|
||||
callbackEntry = callbackEntry->next;
|
||||
}
|
||||
|
||||
/* if we didn't find a matching callback entry */
|
||||
if (callbackEntry == NULL)
|
||||
{
|
||||
/* return a NULL callback in the outgoing parameter */
|
||||
*solicitedCallback = NULL;
|
||||
}
|
||||
else /* we found a matching callback entry */
|
||||
{
|
||||
/* update statistical info */
|
||||
ixNpeMhSolicitedCbMgrStats[npeId].retrieves++;
|
||||
|
||||
/* return the callback in the outgoing parameter */
|
||||
*solicitedCallback = callbackEntry->callback;
|
||||
|
||||
/* unchain callback entry by chaining previous entry to next */
|
||||
previousEntry->next = callbackEntry->next;
|
||||
|
||||
/* if the callback entry is at the tail of the list */
|
||||
if (list->callbackTail == callbackEntry)
|
||||
{
|
||||
/* update the tail of the callback list */
|
||||
list->callbackTail = previousEntry;
|
||||
}
|
||||
|
||||
/* re-initialise the callback entry */
|
||||
callbackEntry->messageId = 0x00;
|
||||
callbackEntry->callback = NULL;
|
||||
|
||||
/* add the callback entry to the start of the free list */
|
||||
callbackEntry->next = list->freeHead;
|
||||
list->freeHead = callbackEntry;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhSolicitedCbMgrShow
|
||||
*/
|
||||
|
||||
void ixNpeMhSolicitedCbMgrShow (
|
||||
IxNpeMhNpeId npeId)
|
||||
{
|
||||
/* show the solicited callback list save counter */
|
||||
IX_NPEMH_SHOW ("Solicited callback list saves",
|
||||
ixNpeMhSolicitedCbMgrStats[npeId].saves);
|
||||
|
||||
/* show the solicited callback list retrieve counter */
|
||||
IX_NPEMH_SHOW ("Solicited callback list retrieves",
|
||||
ixNpeMhSolicitedCbMgrStats[npeId].retrieves);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhSolicitedCbMgrShowReset
|
||||
*/
|
||||
|
||||
void ixNpeMhSolicitedCbMgrShowReset (
|
||||
IxNpeMhNpeId npeId)
|
||||
{
|
||||
/* reset the solicited callback list save counter */
|
||||
ixNpeMhSolicitedCbMgrStats[npeId].saves = 0;
|
||||
|
||||
/* reset the solicited callback list retrieve counter */
|
||||
ixNpeMhSolicitedCbMgrStats[npeId].retrieves = 0;
|
||||
}
|
246
cpu/ixp/npe/IxNpeMhUnsolicitedCbMgr.c
Normal file
246
cpu/ixp/npe/IxNpeMhUnsolicitedCbMgr.c
Normal file
@ -0,0 +1,246 @@
|
||||
/**
|
||||
* @file IxNpeMhUnsolicitedCbMgr.c
|
||||
*
|
||||
* @author Intel Corporation
|
||||
* @date 18 Jan 2002
|
||||
*
|
||||
* @brief This file contains the implementation of the private API for
|
||||
* the Unsolicited Callback Manager module.
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
/*
|
||||
* Put the system defined include files required.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Put the user defined include files required.
|
||||
*/
|
||||
#include "IxOsal.h"
|
||||
|
||||
#include "IxNpeMhMacros_p.h"
|
||||
|
||||
#include "IxNpeMhUnsolicitedCbMgr_p.h"
|
||||
|
||||
|
||||
/*
|
||||
* #defines and macros used in this file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Typedefs whose scope is limited to this file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @struct IxNpeMhUnsolicitedCallbackTable
|
||||
*
|
||||
* @brief This structure is used to maintain the list of registered
|
||||
* callbacks. One entry exists for each message ID, and a NULL entry will
|
||||
* signify that no callback has been registered for that ID.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/** array of entries */
|
||||
IxNpeMhCallback entries[IX_NPEMH_MAX_MESSAGE_ID + 1];
|
||||
} IxNpeMhUnsolicitedCallbackTable;
|
||||
|
||||
/**
|
||||
* @struct IxNpeMhUnsolicitedCbMgrStats
|
||||
*
|
||||
* @brief This structure is used to maintain statistics for the Unsolicited
|
||||
* Callback Manager module.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 saves; /**< callback table saves */
|
||||
UINT32 overwrites; /**< callback table overwrites */
|
||||
} IxNpeMhUnsolicitedCbMgrStats;
|
||||
|
||||
/*
|
||||
* Variable declarations global to this file only. Externs are followed by
|
||||
* static variables.
|
||||
*/
|
||||
|
||||
PRIVATE IxNpeMhUnsolicitedCallbackTable
|
||||
ixNpeMhUnsolicitedCallbackTables[IX_NPEMH_NUM_NPES];
|
||||
|
||||
PRIVATE IxNpeMhUnsolicitedCbMgrStats
|
||||
ixNpeMhUnsolicitedCbMgrStats[IX_NPEMH_NUM_NPES];
|
||||
|
||||
/*
|
||||
* Extern function prototypes.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Static function prototypes.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhUnsolicitedCbMgrInitialize
|
||||
*/
|
||||
|
||||
void ixNpeMhUnsolicitedCbMgrInitialize (void)
|
||||
{
|
||||
IxNpeMhNpeId npeId = 0;
|
||||
IxNpeMhUnsolicitedCallbackTable *table = NULL;
|
||||
IxNpeMhMessageId messageId = 0;
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
|
||||
"ixNpeMhUnsolicitedCbMgrInitialize\n");
|
||||
|
||||
/* for each NPE ... */
|
||||
for (npeId = 0; npeId < IX_NPEMH_NUM_NPES; npeId++)
|
||||
{
|
||||
/* initialise a pointer to the table for convenience */
|
||||
table = &ixNpeMhUnsolicitedCallbackTables[npeId];
|
||||
|
||||
/* for each message ID ... */
|
||||
for (messageId = IX_NPEMH_MIN_MESSAGE_ID;
|
||||
messageId <= IX_NPEMH_MAX_MESSAGE_ID; messageId++)
|
||||
{
|
||||
/* initialise the callback for this message ID to NULL */
|
||||
table->entries[messageId] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
|
||||
"ixNpeMhUnsolicitedCbMgrInitialize\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhUnsolicitedCbMgrCallbackSave
|
||||
*/
|
||||
|
||||
void ixNpeMhUnsolicitedCbMgrCallbackSave (
|
||||
IxNpeMhNpeId npeId,
|
||||
IxNpeMhMessageId unsolicitedMessageId,
|
||||
IxNpeMhCallback unsolicitedCallback)
|
||||
{
|
||||
IxNpeMhUnsolicitedCallbackTable *table = NULL;
|
||||
|
||||
/* initialise a pointer to the table for convenience */
|
||||
table = &ixNpeMhUnsolicitedCallbackTables[npeId];
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
|
||||
"ixNpeMhUnsolicitedCbMgrCallbackSave\n");
|
||||
|
||||
/* update statistical info */
|
||||
ixNpeMhUnsolicitedCbMgrStats[npeId].saves++;
|
||||
|
||||
/* check if there is a callback already registered for this NPE and */
|
||||
/* message ID */
|
||||
if (table->entries[unsolicitedMessageId] != NULL)
|
||||
{
|
||||
/* if we are overwriting an existing callback */
|
||||
if (unsolicitedCallback != NULL)
|
||||
{
|
||||
IX_NPEMH_TRACE2 (IX_NPEMH_DEBUG, "Unsolicited callback "
|
||||
"overwriting existing callback for NPE ID %d "
|
||||
"message ID 0x%02X\n", npeId, unsolicitedMessageId);
|
||||
}
|
||||
else /* if we are clearing an existing callback */
|
||||
{
|
||||
IX_NPEMH_TRACE2 (IX_NPEMH_DEBUG, "NULL unsolicited callback "
|
||||
"clearing existing callback for NPE ID %d "
|
||||
"message ID 0x%02X\n", npeId, unsolicitedMessageId);
|
||||
}
|
||||
|
||||
/* update statistical info */
|
||||
ixNpeMhUnsolicitedCbMgrStats[npeId].overwrites++;
|
||||
}
|
||||
|
||||
/* save the callback into the table */
|
||||
table->entries[unsolicitedMessageId] = unsolicitedCallback;
|
||||
|
||||
IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
|
||||
"ixNpeMhUnsolicitedCbMgrCallbackSave\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhUnsolicitedCbMgrCallbackRetrieve
|
||||
*/
|
||||
|
||||
void ixNpeMhUnsolicitedCbMgrCallbackRetrieve (
|
||||
IxNpeMhNpeId npeId,
|
||||
IxNpeMhMessageId unsolicitedMessageId,
|
||||
IxNpeMhCallback *unsolicitedCallback)
|
||||
{
|
||||
IxNpeMhUnsolicitedCallbackTable *table = NULL;
|
||||
|
||||
/* initialise a pointer to the table for convenience */
|
||||
table = &ixNpeMhUnsolicitedCallbackTables[npeId];
|
||||
|
||||
/* retrieve the callback from the table */
|
||||
*unsolicitedCallback = table->entries[unsolicitedMessageId];
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhUnsolicitedCbMgrShow
|
||||
*/
|
||||
|
||||
void ixNpeMhUnsolicitedCbMgrShow (
|
||||
IxNpeMhNpeId npeId)
|
||||
{
|
||||
/* show the unsolicited callback table save counter */
|
||||
IX_NPEMH_SHOW ("Unsolicited callback table saves",
|
||||
ixNpeMhUnsolicitedCbMgrStats[npeId].saves);
|
||||
|
||||
/* show the unsolicited callback table overwrite counter */
|
||||
IX_NPEMH_SHOW ("Unsolicited callback table overwrites",
|
||||
ixNpeMhUnsolicitedCbMgrStats[npeId].overwrites);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixNpeMhUnsolicitedCbMgrShowReset
|
||||
*/
|
||||
|
||||
void ixNpeMhUnsolicitedCbMgrShowReset (
|
||||
IxNpeMhNpeId npeId)
|
||||
{
|
||||
/* reset the unsolicited callback table save counter */
|
||||
ixNpeMhUnsolicitedCbMgrStats[npeId].saves = 0;
|
||||
|
||||
/* reset the unsolicited callback table overwrite counter */
|
||||
ixNpeMhUnsolicitedCbMgrStats[npeId].overwrites = 0;
|
||||
}
|
800
cpu/ixp/npe/IxOsalBufferMgt.c
Normal file
800
cpu/ixp/npe/IxOsalBufferMgt.c
Normal file
@ -0,0 +1,800 @@
|
||||
/**
|
||||
* @file IxOsalBufferMgt.c
|
||||
*
|
||||
* @brief Default buffer pool management and buffer management
|
||||
* Implementation.
|
||||
*
|
||||
* Design Notes:
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
/*
|
||||
* OS may choose to use default bufferMgt by defining
|
||||
* IX_OSAL_USE_DEFAULT_BUFFER_MGT in IxOsalOsBufferMgt.h
|
||||
*/
|
||||
|
||||
#include "IxOsal.h"
|
||||
|
||||
#define IX_OSAL_BUFFER_FREE_PROTECTION /* Define this to enable Illegal MBuf Freed Protection*/
|
||||
|
||||
/*
|
||||
* The implementation is only used when the following
|
||||
* is defined.
|
||||
*/
|
||||
#ifdef IX_OSAL_USE_DEFAULT_BUFFER_MGT
|
||||
|
||||
|
||||
#define IX_OSAL_MBUF_SYS_SIGNATURE (0x8BADF00D)
|
||||
#define IX_OSAL_MBUF_SYS_SIGNATURE_MASK (0xEFFFFFFF)
|
||||
#define IX_OSAL_MBUF_USED_FLAG (0x10000000)
|
||||
#define IX_OSAL_MBUF_SYS_SIGNATURE_INIT(bufPtr) IX_OSAL_MBUF_SIGNATURE (bufPtr) = (UINT32)IX_OSAL_MBUF_SYS_SIGNATURE
|
||||
|
||||
/*
|
||||
* This implementation is protect, the buffer pool management's ixOsalMBufFree
|
||||
* against an invalid MBUF pointer argument that already has been freed earlier
|
||||
* or in other words resides in the free pool of MBUFs. This added feature,
|
||||
* checks the MBUF "USED" FLAG. The Flag tells if the MBUF is still not freed
|
||||
* back to the Buffer Pool.
|
||||
* Disable this feature for performance reasons by undef
|
||||
* IX_OSAL_BUFFER_FREE_PROTECTION macro.
|
||||
*/
|
||||
#ifdef IX_OSAL_BUFFER_FREE_PROTECTION /*IX_OSAL_BUFFER_FREE_PROTECTION With Buffer Free protection*/
|
||||
|
||||
#define IX_OSAL_MBUF_GET_SYS_SIGNATURE(bufPtr) (IX_OSAL_MBUF_SIGNATURE (bufPtr)&(IX_OSAL_MBUF_SYS_SIGNATURE_MASK) )
|
||||
#define IX_OSAL_MBUF_SET_SYS_SIGNATURE(bufPtr) do { \
|
||||
IX_OSAL_MBUF_SIGNATURE (bufPtr)&(~IX_OSAL_MBUF_SYS_SIGNATURE_MASK);\
|
||||
IX_OSAL_MBUF_SIGNATURE (bufPtr)|=IX_OSAL_MBUF_SYS_SIGNATURE; \
|
||||
}while(0)
|
||||
|
||||
#define IX_OSAL_MBUF_SET_USED_FLAG(bufPtr) IX_OSAL_MBUF_SIGNATURE (bufPtr)|=IX_OSAL_MBUF_USED_FLAG
|
||||
#define IX_OSAL_MBUF_CLEAR_USED_FLAG(bufPtr) IX_OSAL_MBUF_SIGNATURE (bufPtr)&=~IX_OSAL_MBUF_USED_FLAG
|
||||
#define IX_OSAL_MBUF_ISSET_USED_FLAG(bufPtr) (IX_OSAL_MBUF_SIGNATURE (bufPtr)&IX_OSAL_MBUF_USED_FLAG)
|
||||
|
||||
#else
|
||||
|
||||
#define IX_OSAL_MBUF_GET_SYS_SIGNATURE(bufPtr) IX_OSAL_MBUF_SIGNATURE (bufPtr)
|
||||
#define IX_OSAL_MBUF_SET_SYS_SIGNATURE(bufPtr) IX_OSAL_MBUF_SIGNATURE (bufPtr) = IX_OSAL_MBUF_SYS_SIGNATURE
|
||||
|
||||
#endif /*IX_OSAL_BUFFER_FREE_PROTECTION With Buffer Free protection*/
|
||||
/*
|
||||
* Variable declarations global to this file only. Externs are followed by
|
||||
* static variables.
|
||||
*/
|
||||
|
||||
/*
|
||||
* A unit of 32, used to provide bit-shift for pool
|
||||
* management. Needs some work if users want more than 32 pools.
|
||||
*/
|
||||
#define IX_OSAL_BUFF_FREE_BITS 32
|
||||
|
||||
PRIVATE UINT32 ixOsalBuffFreePools[IX_OSAL_MBUF_MAX_POOLS /
|
||||
IX_OSAL_BUFF_FREE_BITS];
|
||||
|
||||
PUBLIC IX_OSAL_MBUF_POOL ixOsalBuffPools[IX_OSAL_MBUF_MAX_POOLS];
|
||||
|
||||
static int ixOsalBuffPoolsInUse = 0;
|
||||
|
||||
#ifdef IX_OSAL_BUFFER_ALLOC_SEPARATELY
|
||||
PRIVATE IX_OSAL_MBUF *
|
||||
ixOsalBuffPoolMbufInit (UINT32 mbufSizeAligned,
|
||||
UINT32 dataSizeAligned,
|
||||
IX_OSAL_MBUF_POOL *poolPtr);
|
||||
#endif
|
||||
|
||||
PRIVATE IX_OSAL_MBUF_POOL * ixOsalPoolAlloc (void);
|
||||
|
||||
/*
|
||||
* Function definition: ixOsalPoolAlloc
|
||||
*/
|
||||
|
||||
/****************************/
|
||||
|
||||
PRIVATE IX_OSAL_MBUF_POOL *
|
||||
ixOsalPoolAlloc (void)
|
||||
{
|
||||
register unsigned int i = 0;
|
||||
|
||||
/*
|
||||
* Scan for the first free buffer. Free buffers are indicated by 0
|
||||
* on the corrsponding bit in ixOsalBuffFreePools.
|
||||
*/
|
||||
if (ixOsalBuffPoolsInUse >= IX_OSAL_MBUF_MAX_POOLS)
|
||||
{
|
||||
/*
|
||||
* Fail to grab a ptr this time
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (ixOsalBuffFreePools[i / IX_OSAL_BUFF_FREE_BITS] &
|
||||
(1 << (i % IX_OSAL_BUFF_FREE_BITS)))
|
||||
i++;
|
||||
/*
|
||||
* Free buffer found. Mark it as busy and initialize.
|
||||
*/
|
||||
ixOsalBuffFreePools[i / IX_OSAL_BUFF_FREE_BITS] |=
|
||||
(1 << (i % IX_OSAL_BUFF_FREE_BITS));
|
||||
|
||||
memset (&ixOsalBuffPools[i], 0, sizeof (IX_OSAL_MBUF_POOL));
|
||||
|
||||
ixOsalBuffPools[i].poolIdx = i;
|
||||
ixOsalBuffPoolsInUse++;
|
||||
|
||||
return &ixOsalBuffPools[i];
|
||||
}
|
||||
|
||||
|
||||
#ifdef IX_OSAL_BUFFER_ALLOC_SEPARATELY
|
||||
PRIVATE IX_OSAL_MBUF *
|
||||
ixOsalBuffPoolMbufInit (UINT32 mbufSizeAligned,
|
||||
UINT32 dataSizeAligned,
|
||||
IX_OSAL_MBUF_POOL *poolPtr)
|
||||
{
|
||||
UINT8 *dataPtr;
|
||||
IX_OSAL_MBUF *realMbufPtr;
|
||||
/* Allocate cache-aligned memory for mbuf header */
|
||||
realMbufPtr = (IX_OSAL_MBUF *) IX_OSAL_CACHE_DMA_MALLOC (mbufSizeAligned);
|
||||
IX_OSAL_ASSERT (realMbufPtr != NULL);
|
||||
memset (realMbufPtr, 0, mbufSizeAligned);
|
||||
|
||||
/* Allocate cache-aligned memory for mbuf data */
|
||||
dataPtr = (UINT8 *) IX_OSAL_CACHE_DMA_MALLOC (dataSizeAligned);
|
||||
IX_OSAL_ASSERT (dataPtr != NULL);
|
||||
memset (dataPtr, 0, dataSizeAligned);
|
||||
|
||||
/* Fill in mbuf header fields */
|
||||
IX_OSAL_MBUF_MDATA (realMbufPtr) = dataPtr;
|
||||
IX_OSAL_MBUF_ALLOCATED_BUFF_DATA (realMbufPtr) = (UINT32)dataPtr;
|
||||
|
||||
IX_OSAL_MBUF_MLEN (realMbufPtr) = dataSizeAligned;
|
||||
IX_OSAL_MBUF_ALLOCATED_BUFF_LEN (realMbufPtr) = dataSizeAligned;
|
||||
|
||||
IX_OSAL_MBUF_NET_POOL (realMbufPtr) = (IX_OSAL_MBUF_POOL *) poolPtr;
|
||||
|
||||
IX_OSAL_MBUF_SYS_SIGNATURE_INIT(realMbufPtr);
|
||||
|
||||
/* update some statistical information */
|
||||
poolPtr->mbufMemSize += mbufSizeAligned;
|
||||
poolPtr->dataMemSize += dataSizeAligned;
|
||||
|
||||
return realMbufPtr;
|
||||
}
|
||||
#endif /* #ifdef IX_OSAL_BUFFER_ALLOC_SEPARATELY */
|
||||
|
||||
/*
|
||||
* Function definition: ixOsalBuffPoolInit
|
||||
*/
|
||||
|
||||
PUBLIC IX_OSAL_MBUF_POOL *
|
||||
ixOsalPoolInit (UINT32 count, UINT32 size, const char *name)
|
||||
{
|
||||
|
||||
/* These variables are only used if UX_OSAL_BUFFER_ALLOC_SEPERATELY
|
||||
* is defined .
|
||||
*/
|
||||
#ifdef IX_OSAL_BUFFER_ALLOC_SEPARATELY
|
||||
UINT32 i, mbufSizeAligned, dataSizeAligned;
|
||||
IX_OSAL_MBUF *currentMbufPtr = NULL;
|
||||
#else
|
||||
void *poolBufPtr;
|
||||
void *poolDataPtr;
|
||||
int mbufMemSize;
|
||||
int dataMemSize;
|
||||
#endif
|
||||
|
||||
IX_OSAL_MBUF_POOL *poolPtr = NULL;
|
||||
|
||||
if (count <= 0)
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"ixOsalPoolInit(): " "count = 0 \n", 0, 0, 0, 0, 0, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (name == NULL)
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"ixOsalPoolInit(): " "NULL name \n", 0, 0, 0, 0, 0, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strlen (name) > IX_OSAL_MBUF_POOL_NAME_LEN)
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"ixOsalPoolInit(): "
|
||||
"ERROR - name length should be no greater than %d \n",
|
||||
IX_OSAL_MBUF_POOL_NAME_LEN, 0, 0, 0, 0, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* OS can choose whether to allocate all buffers all together (if it
|
||||
* can handle a huge single alloc request), or to allocate buffers
|
||||
* separately by the defining IX_OSAL_BUFFER_ALLOC_SEPARATELY.
|
||||
*/
|
||||
#ifdef IX_OSAL_BUFFER_ALLOC_SEPARATELY
|
||||
/* Get a pool Ptr */
|
||||
poolPtr = ixOsalPoolAlloc ();
|
||||
|
||||
if (poolPtr == NULL)
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"ixOsalPoolInit(): " "Fail to Get PoolPtr \n", 0, 0, 0, 0, 0, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mbufSizeAligned = IX_OSAL_MBUF_POOL_SIZE_ALIGN (sizeof (IX_OSAL_MBUF));
|
||||
dataSizeAligned = IX_OSAL_MBUF_POOL_SIZE_ALIGN(size);
|
||||
|
||||
poolPtr->nextFreeBuf = NULL;
|
||||
poolPtr->mbufMemPtr = NULL;
|
||||
poolPtr->dataMemPtr = NULL;
|
||||
poolPtr->bufDataSize = dataSizeAligned;
|
||||
poolPtr->totalBufsInPool = count;
|
||||
poolPtr->poolAllocType = IX_OSAL_MBUF_POOL_TYPE_SYS_ALLOC;
|
||||
strcpy (poolPtr->name, name);
|
||||
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
/* create an mbuf */
|
||||
currentMbufPtr = ixOsalBuffPoolMbufInit (mbufSizeAligned,
|
||||
dataSizeAligned,
|
||||
poolPtr);
|
||||
|
||||
#ifdef IX_OSAL_BUFFER_FREE_PROTECTION
|
||||
/* Set the Buffer USED Flag. If not, ixOsalMBufFree will fail.
|
||||
ixOsalMbufFree used here is in a special case whereby, it's
|
||||
used to add MBUF to the Pool. By specification, ixOsalMbufFree
|
||||
deallocates an allocated MBUF from Pool.
|
||||
*/
|
||||
IX_OSAL_MBUF_SET_USED_FLAG(currentMbufPtr);
|
||||
#endif
|
||||
/* Add it to the pool */
|
||||
ixOsalMbufFree (currentMbufPtr);
|
||||
|
||||
/* flush the pool information to RAM */
|
||||
IX_OSAL_CACHE_FLUSH (currentMbufPtr, mbufSizeAligned);
|
||||
}
|
||||
|
||||
/*
|
||||
* update the number of free buffers in the pool
|
||||
*/
|
||||
poolPtr->freeBufsInPool = count;
|
||||
|
||||
#else
|
||||
/* Otherwise allocate buffers in a continuous block fashion */
|
||||
poolBufPtr = IX_OSAL_MBUF_POOL_MBUF_AREA_ALLOC (count, mbufMemSize);
|
||||
IX_OSAL_ASSERT (poolBufPtr != NULL);
|
||||
poolDataPtr =
|
||||
IX_OSAL_MBUF_POOL_DATA_AREA_ALLOC (count, size, dataMemSize);
|
||||
IX_OSAL_ASSERT (poolDataPtr != NULL);
|
||||
|
||||
poolPtr = ixOsalNoAllocPoolInit (poolBufPtr, poolDataPtr,
|
||||
count, size, name);
|
||||
if (poolPtr == NULL)
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"ixOsalPoolInit(): " "Fail to get pool ptr \n", 0, 0, 0, 0, 0, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
poolPtr->poolAllocType = IX_OSAL_MBUF_POOL_TYPE_SYS_ALLOC;
|
||||
|
||||
#endif /* IX_OSAL_BUFFER_ALLOC_SEPARATELY */
|
||||
return poolPtr;
|
||||
}
|
||||
|
||||
PUBLIC IX_OSAL_MBUF_POOL *
|
||||
ixOsalNoAllocPoolInit (void *poolBufPtr,
|
||||
void *poolDataPtr, UINT32 count, UINT32 size, const char *name)
|
||||
{
|
||||
UINT32 i, mbufSizeAligned, sizeAligned;
|
||||
IX_OSAL_MBUF *currentMbufPtr = NULL;
|
||||
IX_OSAL_MBUF *nextMbufPtr = NULL;
|
||||
IX_OSAL_MBUF_POOL *poolPtr = NULL;
|
||||
|
||||
/*
|
||||
* check parameters
|
||||
*/
|
||||
if (poolBufPtr == NULL)
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"ixOsalNoAllocPoolInit(): "
|
||||
"ERROR - NULL poolBufPtr \n", 0, 0, 0, 0, 0, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (count <= 0)
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"ixOsalNoAllocPoolInit(): "
|
||||
"ERROR - count must > 0 \n", 0, 0, 0, 0, 0, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (name == NULL)
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"ixOsalNoAllocPoolInit(): "
|
||||
"ERROR - NULL name ptr \n", 0, 0, 0, 0, 0, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strlen (name) > IX_OSAL_MBUF_POOL_NAME_LEN)
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"ixOsalNoAllocPoolInit(): "
|
||||
"ERROR - name length should be no greater than %d \n",
|
||||
IX_OSAL_MBUF_POOL_NAME_LEN, 0, 0, 0, 0, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
poolPtr = ixOsalPoolAlloc ();
|
||||
|
||||
if (poolPtr == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust sizes to ensure alignment on cache line boundaries
|
||||
*/
|
||||
mbufSizeAligned =
|
||||
IX_OSAL_MBUF_POOL_SIZE_ALIGN (sizeof (IX_OSAL_MBUF));
|
||||
/*
|
||||
* clear the mbuf memory area
|
||||
*/
|
||||
memset (poolBufPtr, 0, mbufSizeAligned * count);
|
||||
|
||||
if (poolDataPtr != NULL)
|
||||
{
|
||||
/*
|
||||
* Adjust sizes to ensure alignment on cache line boundaries
|
||||
*/
|
||||
sizeAligned = IX_OSAL_MBUF_POOL_SIZE_ALIGN (size);
|
||||
/*
|
||||
* clear the data memory area
|
||||
*/
|
||||
memset (poolDataPtr, 0, sizeAligned * count);
|
||||
}
|
||||
else
|
||||
{
|
||||
sizeAligned = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* initialise pool fields
|
||||
*/
|
||||
strcpy ((poolPtr)->name, name);
|
||||
|
||||
poolPtr->dataMemPtr = poolDataPtr;
|
||||
poolPtr->mbufMemPtr = poolBufPtr;
|
||||
poolPtr->bufDataSize = sizeAligned;
|
||||
poolPtr->totalBufsInPool = count;
|
||||
poolPtr->mbufMemSize = mbufSizeAligned * count;
|
||||
poolPtr->dataMemSize = sizeAligned * count;
|
||||
|
||||
currentMbufPtr = (IX_OSAL_MBUF *) poolBufPtr;
|
||||
|
||||
poolPtr->nextFreeBuf = currentMbufPtr;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (i < (count - 1))
|
||||
{
|
||||
nextMbufPtr =
|
||||
(IX_OSAL_MBUF *) ((unsigned) currentMbufPtr +
|
||||
mbufSizeAligned);
|
||||
}
|
||||
else
|
||||
{ /* last mbuf in chain */
|
||||
nextMbufPtr = NULL;
|
||||
}
|
||||
IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR (currentMbufPtr) = nextMbufPtr;
|
||||
IX_OSAL_MBUF_NET_POOL (currentMbufPtr) = poolPtr;
|
||||
|
||||
IX_OSAL_MBUF_SYS_SIGNATURE_INIT(currentMbufPtr);
|
||||
|
||||
if (poolDataPtr != NULL)
|
||||
{
|
||||
IX_OSAL_MBUF_MDATA (currentMbufPtr) = poolDataPtr;
|
||||
IX_OSAL_MBUF_ALLOCATED_BUFF_DATA(currentMbufPtr) = (UINT32) poolDataPtr;
|
||||
|
||||
IX_OSAL_MBUF_MLEN (currentMbufPtr) = sizeAligned;
|
||||
IX_OSAL_MBUF_ALLOCATED_BUFF_LEN(currentMbufPtr) = sizeAligned;
|
||||
|
||||
poolDataPtr = (void *) ((unsigned) poolDataPtr + sizeAligned);
|
||||
}
|
||||
|
||||
currentMbufPtr = nextMbufPtr;
|
||||
}
|
||||
|
||||
/*
|
||||
* update the number of free buffers in the pool
|
||||
*/
|
||||
poolPtr->freeBufsInPool = count;
|
||||
|
||||
poolPtr->poolAllocType = IX_OSAL_MBUF_POOL_TYPE_USER_ALLOC;
|
||||
|
||||
return poolPtr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a mbuf ptr from the pool
|
||||
*/
|
||||
PUBLIC IX_OSAL_MBUF *
|
||||
ixOsalMbufAlloc (IX_OSAL_MBUF_POOL * poolPtr)
|
||||
{
|
||||
int lock;
|
||||
IX_OSAL_MBUF *newBufPtr = NULL;
|
||||
|
||||
/*
|
||||
* check parameters
|
||||
*/
|
||||
if (poolPtr == NULL)
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"ixOsalMbufAlloc(): "
|
||||
"ERROR - Invalid Parameter\n", 0, 0, 0, 0, 0, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lock = ixOsalIrqLock ();
|
||||
|
||||
newBufPtr = poolPtr->nextFreeBuf;
|
||||
if (newBufPtr)
|
||||
{
|
||||
poolPtr->nextFreeBuf =
|
||||
IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR (newBufPtr);
|
||||
IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR (newBufPtr) = NULL;
|
||||
|
||||
/*
|
||||
* update the number of free buffers in the pool
|
||||
*/
|
||||
poolPtr->freeBufsInPool--;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Return NULL to indicate to caller that request is denied. */
|
||||
ixOsalIrqUnlock (lock);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef IX_OSAL_BUFFER_FREE_PROTECTION
|
||||
/* Set Buffer Used Flag to indicate state.*/
|
||||
IX_OSAL_MBUF_SET_USED_FLAG(newBufPtr);
|
||||
#endif
|
||||
|
||||
ixOsalIrqUnlock (lock);
|
||||
|
||||
return newBufPtr;
|
||||
}
|
||||
|
||||
PUBLIC IX_OSAL_MBUF *
|
||||
ixOsalMbufFree (IX_OSAL_MBUF * bufPtr)
|
||||
{
|
||||
int lock;
|
||||
IX_OSAL_MBUF_POOL *poolPtr;
|
||||
|
||||
IX_OSAL_MBUF *nextBufPtr = NULL;
|
||||
|
||||
/*
|
||||
* check parameters
|
||||
*/
|
||||
if (bufPtr == NULL)
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"ixOsalMbufFree(): "
|
||||
"ERROR - Invalid Parameter\n", 0, 0, 0, 0, 0, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
lock = ixOsalIrqLock ();
|
||||
|
||||
#ifdef IX_OSAL_BUFFER_FREE_PROTECTION
|
||||
|
||||
/* Prevention for Buffer freed more than once*/
|
||||
if(!IX_OSAL_MBUF_ISSET_USED_FLAG(bufPtr))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
IX_OSAL_MBUF_CLEAR_USED_FLAG(bufPtr);
|
||||
#endif
|
||||
|
||||
poolPtr = IX_OSAL_MBUF_NET_POOL (bufPtr);
|
||||
|
||||
/*
|
||||
* check the mbuf wrapper signature (if mbuf wrapper was used)
|
||||
*/
|
||||
if (poolPtr->poolAllocType == IX_OSAL_MBUF_POOL_TYPE_SYS_ALLOC)
|
||||
{
|
||||
IX_OSAL_ENSURE ( (IX_OSAL_MBUF_GET_SYS_SIGNATURE(bufPtr) == IX_OSAL_MBUF_SYS_SIGNATURE),
|
||||
"ixOsalBuffPoolBufFree: ERROR - Invalid mbuf signature.");
|
||||
}
|
||||
|
||||
nextBufPtr = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR (bufPtr);
|
||||
|
||||
IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR (bufPtr) = poolPtr->nextFreeBuf;
|
||||
poolPtr->nextFreeBuf = bufPtr;
|
||||
|
||||
/*
|
||||
* update the number of free buffers in the pool
|
||||
*/
|
||||
poolPtr->freeBufsInPool++;
|
||||
|
||||
ixOsalIrqUnlock (lock);
|
||||
|
||||
return nextBufPtr;
|
||||
}
|
||||
|
||||
PUBLIC void
|
||||
ixOsalMbufChainFree (IX_OSAL_MBUF * bufPtr)
|
||||
{
|
||||
while ((bufPtr = ixOsalMbufFree (bufPtr)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixOsalBuffPoolShow
|
||||
*/
|
||||
PUBLIC void
|
||||
ixOsalMbufPoolShow (IX_OSAL_MBUF_POOL * poolPtr)
|
||||
{
|
||||
IX_OSAL_MBUF *nextBufPtr;
|
||||
int count = 0;
|
||||
int lock;
|
||||
|
||||
/*
|
||||
* check parameters
|
||||
*/
|
||||
if (poolPtr == NULL)
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"ixOsalBuffPoolShow(): "
|
||||
"ERROR - Invalid Parameter", 0, 0, 0, 0, 0, 0);
|
||||
/*
|
||||
* return IX_FAIL;
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
lock = ixOsalIrqLock ();
|
||||
count = poolPtr->freeBufsInPool;
|
||||
nextBufPtr = poolPtr->nextFreeBuf;
|
||||
ixOsalIrqUnlock (lock);
|
||||
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_MESSAGE,
|
||||
IX_OSAL_LOG_DEV_STDOUT, "=== POOL INFORMATION ===\n", 0, 0, 0,
|
||||
0, 0, 0);
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT,
|
||||
"Pool Name: %s\n",
|
||||
(unsigned int) poolPtr->name, 0, 0, 0, 0, 0);
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT,
|
||||
"Pool Allocation Type: %d\n",
|
||||
(unsigned int) poolPtr->poolAllocType, 0, 0, 0, 0, 0);
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT,
|
||||
"Pool Mbuf Mem Usage (bytes): %d\n",
|
||||
(unsigned int) poolPtr->mbufMemSize, 0, 0, 0, 0, 0);
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT,
|
||||
"Pool Data Mem Usage (bytes): %d\n",
|
||||
(unsigned int) poolPtr->dataMemSize, 0, 0, 0, 0, 0);
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT,
|
||||
"Mbuf Data Capacity (bytes): %d\n",
|
||||
(unsigned int) poolPtr->bufDataSize, 0, 0, 0, 0, 0);
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT,
|
||||
"Total Mbufs in Pool: %d\n",
|
||||
(unsigned int) poolPtr->totalBufsInPool, 0, 0, 0, 0, 0);
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT,
|
||||
"Available Mbufs: %d\n", (unsigned int) count, 0,
|
||||
0, 0, 0, 0);
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT,
|
||||
"Next Available Mbuf: %p\n", (unsigned int) nextBufPtr,
|
||||
0, 0, 0, 0, 0);
|
||||
|
||||
if (poolPtr->poolAllocType == IX_OSAL_MBUF_POOL_TYPE_USER_ALLOC)
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_MESSAGE,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"Mbuf Mem Area Start address: %p\n",
|
||||
(unsigned int) poolPtr->mbufMemPtr, 0, 0, 0, 0, 0);
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT,
|
||||
"Data Mem Area Start address: %p\n",
|
||||
(unsigned int) poolPtr->dataMemPtr, 0, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
PUBLIC void
|
||||
ixOsalMbufDataPtrReset (IX_OSAL_MBUF * bufPtr)
|
||||
{
|
||||
IX_OSAL_MBUF_POOL *poolPtr;
|
||||
UINT8 *poolDataPtr;
|
||||
|
||||
if (bufPtr == NULL)
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT,
|
||||
"ixOsalBuffPoolBufDataPtrReset"
|
||||
": ERROR - Invalid Parameter\n", 0, 0, 0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
poolPtr = (IX_OSAL_MBUF_POOL *) IX_OSAL_MBUF_NET_POOL (bufPtr);
|
||||
poolDataPtr = poolPtr->dataMemPtr;
|
||||
|
||||
if (poolPtr->poolAllocType == IX_OSAL_MBUF_POOL_TYPE_SYS_ALLOC)
|
||||
{
|
||||
if (IX_OSAL_MBUF_GET_SYS_SIGNATURE(bufPtr) != IX_OSAL_MBUF_SYS_SIGNATURE)
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT,
|
||||
"ixOsalBuffPoolBufDataPtrReset"
|
||||
": invalid mbuf, cannot reset mData pointer\n", 0, 0,
|
||||
0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
IX_OSAL_MBUF_MDATA (bufPtr) = (UINT8*)IX_OSAL_MBUF_ALLOCATED_BUFF_DATA (bufPtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (poolDataPtr)
|
||||
{
|
||||
unsigned int bufSize = poolPtr->bufDataSize;
|
||||
unsigned int bufDataAddr =
|
||||
(unsigned int) IX_OSAL_MBUF_MDATA (bufPtr);
|
||||
unsigned int poolDataAddr = (unsigned int) poolDataPtr;
|
||||
|
||||
/*
|
||||
* the pointer is still pointing somewhere in the mbuf payload.
|
||||
* This operation moves the pointer to the beginning of the
|
||||
* mbuf payload
|
||||
*/
|
||||
bufDataAddr = ((bufDataAddr - poolDataAddr) / bufSize) * bufSize;
|
||||
IX_OSAL_MBUF_MDATA (bufPtr) = &poolDataPtr[bufDataAddr];
|
||||
}
|
||||
else
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_WARNING, IX_OSAL_LOG_DEV_STDOUT,
|
||||
"ixOsalBuffPoolBufDataPtrReset"
|
||||
": cannot be used if user supplied NULL pointer for pool data area "
|
||||
"when pool was created\n", 0, 0, 0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixOsalBuffPoolUninit
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalBuffPoolUninit (IX_OSAL_MBUF_POOL * pool)
|
||||
{
|
||||
if (!pool)
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT,
|
||||
"ixOsalBuffPoolUninit: NULL ptr \n", 0, 0, 0, 0, 0, 0);
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
if (pool->freeBufsInPool != pool->totalBufsInPool)
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT,
|
||||
"ixOsalBuffPoolUninit: need to return all ptrs to the pool first! \n",
|
||||
0, 0, 0, 0, 0, 0);
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
if (pool->poolAllocType == IX_OSAL_MBUF_POOL_TYPE_SYS_ALLOC)
|
||||
{
|
||||
#ifdef IX_OSAL_BUFFER_ALLOC_SEPARATELY
|
||||
UINT32 i;
|
||||
IX_OSAL_MBUF* pBuf;
|
||||
|
||||
pBuf = pool->nextFreeBuf;
|
||||
/* Freed the Buffer one by one till all the Memory is freed*/
|
||||
for (i= pool->freeBufsInPool; i >0 && pBuf!=NULL ;i--){
|
||||
IX_OSAL_MBUF* pBufTemp;
|
||||
pBufTemp = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(pBuf);
|
||||
/* Freed MBUF Data Memory area*/
|
||||
IX_OSAL_CACHE_DMA_FREE( (void *) (IX_OSAL_MBUF_ALLOCATED_BUFF_DATA(pBuf)) );
|
||||
/* Freed MBUF Struct Memory area*/
|
||||
IX_OSAL_CACHE_DMA_FREE(pBuf);
|
||||
pBuf = pBufTemp;
|
||||
}
|
||||
|
||||
#else
|
||||
IX_OSAL_CACHE_DMA_FREE (pool->mbufMemPtr);
|
||||
IX_OSAL_CACHE_DMA_FREE (pool->dataMemPtr);
|
||||
#endif
|
||||
}
|
||||
|
||||
ixOsalBuffFreePools[pool->poolIdx / IX_OSAL_BUFF_FREE_BITS] &=
|
||||
~(1 << (pool->poolIdx % IX_OSAL_BUFF_FREE_BITS));
|
||||
ixOsalBuffPoolsInUse--;
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixOsalBuffPoolDataAreaSizeGet
|
||||
*/
|
||||
PUBLIC UINT32
|
||||
ixOsalBuffPoolDataAreaSizeGet (int count, int size)
|
||||
{
|
||||
UINT32 memorySize;
|
||||
memorySize = count * IX_OSAL_MBUF_POOL_SIZE_ALIGN (size);
|
||||
return memorySize;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixOsalBuffPoolMbufAreaSizeGet
|
||||
*/
|
||||
PUBLIC UINT32
|
||||
ixOsalBuffPoolMbufAreaSizeGet (int count)
|
||||
{
|
||||
UINT32 memorySize;
|
||||
memorySize =
|
||||
count * IX_OSAL_MBUF_POOL_SIZE_ALIGN (sizeof (IX_OSAL_MBUF));
|
||||
return memorySize;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function definition: ixOsalBuffPoolFreeCountGet
|
||||
*/
|
||||
PUBLIC UINT32 ixOsalBuffPoolFreeCountGet(IX_OSAL_MBUF_POOL * poolPtr)
|
||||
|
||||
{
|
||||
|
||||
return poolPtr->freeBufsInPool;
|
||||
|
||||
}
|
||||
|
||||
#endif /* IX_OSAL_USE_DEFAULT_BUFFER_MGT */
|
332
cpu/ixp/npe/IxOsalIoMem.c
Normal file
332
cpu/ixp/npe/IxOsalIoMem.c
Normal file
@ -0,0 +1,332 @@
|
||||
/**
|
||||
* @file IxOsalIoMem.c
|
||||
*
|
||||
* @brief OS-independent IO/Mem implementation
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
/* Access to the global mem map is only allowed in this file */
|
||||
#define IxOsalIoMem_C
|
||||
|
||||
#include "IxOsal.h"
|
||||
|
||||
#define SEARCH_PHYSICAL_ADDRESS (1)
|
||||
#define SEARCH_VIRTUAL_ADDRESS (2)
|
||||
|
||||
/*
|
||||
* Searches for map using one of the following criteria:
|
||||
*
|
||||
* - enough room to include a zone starting with the physical "requestedAddress" of size "size" (for mapping)
|
||||
* - includes the virtual "requestedAddress" in its virtual address space (already mapped, for unmapping)
|
||||
* - correct coherency
|
||||
*
|
||||
* Returns a pointer to the map or NULL if a suitable map is not found.
|
||||
*/
|
||||
PRIVATE IxOsalMemoryMap *
|
||||
ixOsalMemMapFind (UINT32 requestedAddress,
|
||||
UINT32 size, UINT32 searchCriteria, UINT32 requestedEndianType)
|
||||
{
|
||||
UINT32 mapIndex;
|
||||
|
||||
UINT32 numMapElements =
|
||||
sizeof (ixOsalGlobalMemoryMap) / sizeof (IxOsalMemoryMap);
|
||||
|
||||
for (mapIndex = 0; mapIndex < numMapElements; mapIndex++)
|
||||
{
|
||||
IxOsalMemoryMap *map = &ixOsalGlobalMemoryMap[mapIndex];
|
||||
|
||||
if (searchCriteria == SEARCH_PHYSICAL_ADDRESS
|
||||
&& requestedAddress >= map->physicalAddress
|
||||
&& (requestedAddress + size) <= (map->physicalAddress + map->size)
|
||||
&& (map->mapEndianType & requestedEndianType) != 0)
|
||||
{
|
||||
return map;
|
||||
}
|
||||
else if (searchCriteria == SEARCH_VIRTUAL_ADDRESS
|
||||
&& requestedAddress >= map->virtualAddress
|
||||
&& requestedAddress <= (map->virtualAddress + map->size)
|
||||
&& (map->mapEndianType & requestedEndianType) != 0)
|
||||
{
|
||||
return map;
|
||||
}
|
||||
else if (searchCriteria == SEARCH_PHYSICAL_ADDRESS)
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"Osal: Checking [phys addr 0x%x:size 0x%x:endianType %d]\n",
|
||||
map->physicalAddress, map->size, map->mapEndianType, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* not found
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function maps an I/O mapped physical memory zone of the given size
|
||||
* into a virtual memory zone accessible by the caller and returns a cookie -
|
||||
* the start address of the virtual memory zone.
|
||||
* IX_OSAL_MMAP_PHYS_TO_VIRT should NOT therefore be used on the returned
|
||||
* virtual address.
|
||||
* The memory zone is to be unmapped using ixOsalMemUnmap once the caller has
|
||||
* finished using this zone (e.g. on driver unload) using the cookie as
|
||||
* parameter.
|
||||
* The IX_OSAL_READ/WRITE_LONG/SHORT macros should be used to read and write
|
||||
* the mapped memory, adding the necessary offsets to the address cookie.
|
||||
*
|
||||
* Note: this function is not to be used directly. Use IX_OSAL_MEM_MAP
|
||||
* instead.
|
||||
*/
|
||||
PUBLIC void *
|
||||
ixOsalIoMemMap (UINT32 requestedAddress,
|
||||
UINT32 size, IxOsalMapEndianessType requestedEndianType)
|
||||
{
|
||||
IxOsalMemoryMap *map;
|
||||
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"OSAL: Mapping [addr 0x%x:size 0x%x:endianType %d]\n",
|
||||
requestedAddress, size, requestedEndianType, 0, 0, 0);
|
||||
|
||||
if (requestedEndianType == IX_OSAL_LE)
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"ixOsalIoMemMap: Please specify component coherency mode to use MEM functions \n",
|
||||
0, 0, 0, 0, 0, 0);
|
||||
return (NULL);
|
||||
}
|
||||
map = ixOsalMemMapFind (requestedAddress,
|
||||
size, SEARCH_PHYSICAL_ADDRESS, requestedEndianType);
|
||||
if (map != NULL)
|
||||
{
|
||||
UINT32 offset = requestedAddress - map->physicalAddress;
|
||||
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
|
||||
IX_OSAL_LOG_DEV_STDOUT, "OSAL: Found map [", 0, 0, 0, 0, 0, 0);
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
|
||||
IX_OSAL_LOG_DEV_STDOUT, map->name, 0, 0, 0, 0, 0, 0);
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
":addr 0x%x: virt 0x%x:size 0x%x:ref %d:endianType %d]\n",
|
||||
map->physicalAddress, map->virtualAddress,
|
||||
map->size, map->refCount, map->mapEndianType, 0);
|
||||
|
||||
if (map->type == IX_OSAL_DYNAMIC_MAP && map->virtualAddress == 0)
|
||||
{
|
||||
if (map->mapFunction != NULL)
|
||||
{
|
||||
map->mapFunction (map);
|
||||
|
||||
if (map->virtualAddress == 0)
|
||||
{
|
||||
/*
|
||||
* failed
|
||||
*/
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_FATAL,
|
||||
IX_OSAL_LOG_DEV_STDERR,
|
||||
"OSAL: Remap failed - [addr 0x%x:size 0x%x:endianType %d]\n",
|
||||
requestedAddress, size, requestedEndianType, 0, 0, 0);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* error, no map function for a dynamic map
|
||||
*/
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_FATAL,
|
||||
IX_OSAL_LOG_DEV_STDERR,
|
||||
"OSAL: No map function for a dynamic map - "
|
||||
"[addr 0x%x:size 0x%x:endianType %d]\n",
|
||||
requestedAddress, size, requestedEndianType, 0, 0, 0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* increment reference count
|
||||
*/
|
||||
map->refCount++;
|
||||
|
||||
return (void *) (map->virtualAddress + offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* requested address is not described in the global memory map
|
||||
*/
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_FATAL,
|
||||
IX_OSAL_LOG_DEV_STDERR,
|
||||
"OSAL: No mapping found - [addr 0x%x:size 0x%x:endianType %d]\n",
|
||||
requestedAddress, size, requestedEndianType, 0, 0, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function unmaps a previously mapped I/O memory zone using
|
||||
* the cookie obtained in the mapping operation. The memory zone in question
|
||||
* becomes unavailable to the caller once unmapped and the cookie should be
|
||||
* discarded.
|
||||
*
|
||||
* This function cannot fail if the given parameter is correct and does not
|
||||
* return a value.
|
||||
*
|
||||
* Note: this function is not to be used directly. Use IX_OSAL_MEM_UNMAP
|
||||
* instead.
|
||||
*/
|
||||
PUBLIC void
|
||||
ixOsalIoMemUnmap (UINT32 requestedAddress, UINT32 endianType)
|
||||
{
|
||||
IxOsalMemoryMap *map;
|
||||
|
||||
if (endianType == IX_OSAL_LE)
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"ixOsalIoMemUnmap: Please specify component coherency mode to use MEM functions \n",
|
||||
0, 0, 0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (requestedAddress == 0)
|
||||
{
|
||||
/*
|
||||
* invalid virtual address
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
map =
|
||||
ixOsalMemMapFind (requestedAddress, 0, SEARCH_VIRTUAL_ADDRESS,
|
||||
endianType);
|
||||
|
||||
if (map != NULL)
|
||||
{
|
||||
if (map->refCount > 0)
|
||||
{
|
||||
/*
|
||||
* decrement reference count
|
||||
*/
|
||||
map->refCount--;
|
||||
|
||||
if (map->refCount == 0)
|
||||
{
|
||||
/*
|
||||
* no longer used, deallocate
|
||||
*/
|
||||
if (map->type == IX_OSAL_DYNAMIC_MAP
|
||||
&& map->unmapFunction != NULL)
|
||||
{
|
||||
map->unmapFunction (map);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_WARNING,
|
||||
IX_OSAL_LOG_DEV_STDERR,
|
||||
"OSAL: ixOsServMemUnmap didn't find the requested map "
|
||||
"[virt addr 0x%x: endianType %d], ignoring call\n",
|
||||
requestedAddress, endianType, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function Converts a virtual address into a physical
|
||||
* address, including the dynamically mapped memory.
|
||||
*
|
||||
* Parameters virtAddr - virtual address to convert
|
||||
* Return value: corresponding physical address, or NULL
|
||||
* if there is no physical address addressable
|
||||
* by the given virtual address
|
||||
* OS: VxWorks, Linux, WinCE, QNX, eCos
|
||||
* Reentrant: Yes
|
||||
* IRQ safe: Yes
|
||||
*/
|
||||
PUBLIC UINT32
|
||||
ixOsalIoMemVirtToPhys (UINT32 virtualAddress, UINT32 requestedCoherency)
|
||||
{
|
||||
IxOsalMemoryMap *map =
|
||||
ixOsalMemMapFind (virtualAddress, 0, SEARCH_VIRTUAL_ADDRESS,
|
||||
requestedCoherency);
|
||||
|
||||
if (map != NULL)
|
||||
{
|
||||
return map->physicalAddress + virtualAddress - map->virtualAddress;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (UINT32) IX_OSAL_MMU_VIRT_TO_PHYS (virtualAddress);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function Converts a virtual address into a physical
|
||||
* address, including the dynamically mapped memory.
|
||||
*
|
||||
* Parameters virtAddr - virtual address to convert
|
||||
* Return value: corresponding physical address, or NULL
|
||||
* if there is no physical address addressable
|
||||
* by the given virtual address
|
||||
* OS: VxWorks, Linux, WinCE, QNX, eCos
|
||||
* Reentrant: Yes
|
||||
* IRQ safe: Yes
|
||||
*/
|
||||
PUBLIC UINT32
|
||||
ixOsalIoMemPhysToVirt (UINT32 physicalAddress, UINT32 requestedCoherency)
|
||||
{
|
||||
IxOsalMemoryMap *map =
|
||||
ixOsalMemMapFind (physicalAddress, 0, SEARCH_PHYSICAL_ADDRESS,
|
||||
requestedCoherency);
|
||||
|
||||
if (map != NULL)
|
||||
{
|
||||
return map->virtualAddress + physicalAddress - map->physicalAddress;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (UINT32) IX_OSAL_MMU_PHYS_TO_VIRT (physicalAddress);
|
||||
}
|
||||
}
|
67
cpu/ixp/npe/IxOsalOsCacheMMU.c
Normal file
67
cpu/ixp/npe/IxOsalOsCacheMMU.c
Normal file
@ -0,0 +1,67 @@
|
||||
/**
|
||||
* @file IxOsalOsCacheMMU.c (linux)
|
||||
*
|
||||
* @brief Cache MemAlloc and MemFree.
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 1.5
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
#include "IxOsal.h"
|
||||
|
||||
#include <malloc.h>
|
||||
|
||||
/*
|
||||
* Allocate on a cache line boundary (null pointers are
|
||||
* not affected by this operation). This operation is NOT cache safe.
|
||||
*/
|
||||
void *
|
||||
ixOsalCacheDmaMalloc (UINT32 n)
|
||||
{
|
||||
return malloc(n);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
void
|
||||
ixOsalCacheDmaFree (void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
79
cpu/ixp/npe/IxOsalOsMsgQ.c
Normal file
79
cpu/ixp/npe/IxOsalOsMsgQ.c
Normal file
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* @file IxOsalOsMsgQ.c (eCos)
|
||||
*
|
||||
* @brief OS-specific Message Queue implementation.
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 1.5
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
#include "IxOsal.h"
|
||||
|
||||
/*******************************
|
||||
* Public functions
|
||||
*******************************/
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalMessageQueueCreate (IxOsalMessageQueue * queue,
|
||||
UINT32 msgCount, UINT32 msgLen)
|
||||
{
|
||||
diag_printf("%s called\n", __FUNCTION__);
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalMessageQueueDelete (IxOsalMessageQueue * queue)
|
||||
{
|
||||
diag_printf("%s called\n", __FUNCTION__);
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalMessageQueueSend (IxOsalMessageQueue * queue, UINT8 * message)
|
||||
{
|
||||
diag_printf("%s called\n", __FUNCTION__);
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalMessageQueueReceive (IxOsalMessageQueue * queue, UINT8 * message)
|
||||
{
|
||||
diag_printf("%s called\n", __FUNCTION__);
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
233
cpu/ixp/npe/IxOsalOsSemaphore.c
Normal file
233
cpu/ixp/npe/IxOsalOsSemaphore.c
Normal file
@ -0,0 +1,233 @@
|
||||
/**
|
||||
* @file IxOsalOsSemaphore.c (eCos)
|
||||
*
|
||||
* @brief Implementation for semaphore and mutex.
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 1.5
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
#include "IxOsal.h"
|
||||
#include "IxNpeMhReceive_p.h"
|
||||
|
||||
/* Define a large number */
|
||||
#define IX_OSAL_MAX_LONG (0x7FFFFFFF)
|
||||
|
||||
/* Max timeout in MS, used to guard against possible overflow */
|
||||
#define IX_OSAL_MAX_TIMEOUT_MS (IX_OSAL_MAX_LONG/HZ)
|
||||
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalSemaphoreInit (IxOsalSemaphore * sid, UINT32 start_value)
|
||||
{
|
||||
diag_printf("%s called\n", __FUNCTION__);
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* DESCRIPTION: If the semaphore is 'empty', the calling thread is blocked.
|
||||
* If the semaphore is 'full', it is taken and control is returned
|
||||
* to the caller. If the time indicated in 'timeout' is reached,
|
||||
* the thread will unblock and return an error indication. If the
|
||||
* timeout is set to 'IX_OSAL_WAIT_NONE', the thread will never block;
|
||||
* if it is set to 'IX_OSAL_WAIT_FOREVER', the thread will block until
|
||||
* the semaphore is available.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalSemaphoreWait (IxOsalOsSemaphore * sid, INT32 timeout)
|
||||
{
|
||||
diag_printf("%s called\n", __FUNCTION__);
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to get semaphore, return immediately,
|
||||
* no error info because users expect some failures
|
||||
* when using this API.
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalSemaphoreTryWait (IxOsalSemaphore * sid)
|
||||
{
|
||||
diag_printf("%s called\n", __FUNCTION__);
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* DESCRIPTION: This function causes the next available thread in the pend queue
|
||||
* to be unblocked. If no thread is pending on this semaphore, the
|
||||
* semaphore becomes 'full'.
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalSemaphorePost (IxOsalSemaphore * sid)
|
||||
{
|
||||
diag_printf("%s called\n", __FUNCTION__);
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalSemaphoreGetValue (IxOsalSemaphore * sid, UINT32 * value)
|
||||
{
|
||||
diag_printf("%s called\n", __FUNCTION__);
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalSemaphoreDestroy (IxOsalSemaphore * sid)
|
||||
{
|
||||
diag_printf("%s called\n", __FUNCTION__);
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/****************************
|
||||
* Mutex
|
||||
****************************/
|
||||
|
||||
static void drv_mutex_init(IxOsalMutex *mutex)
|
||||
{
|
||||
*mutex = 0;
|
||||
}
|
||||
|
||||
static void drv_mutex_destroy(IxOsalMutex *mutex)
|
||||
{
|
||||
*mutex = -1;
|
||||
}
|
||||
|
||||
static int drv_mutex_trylock(IxOsalMutex *mutex)
|
||||
{
|
||||
int result = TRUE;
|
||||
|
||||
if (*mutex == 1)
|
||||
result = FALSE;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void drv_mutex_unlock(IxOsalMutex *mutex)
|
||||
{
|
||||
if (*mutex == 1)
|
||||
printf("Trying to unlock unlocked mutex!");
|
||||
|
||||
*mutex = 0;
|
||||
}
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalMutexInit (IxOsalMutex * mutex)
|
||||
{
|
||||
drv_mutex_init(mutex);
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalMutexLock (IxOsalMutex * mutex, INT32 timeout)
|
||||
{
|
||||
int tries;
|
||||
|
||||
if (timeout == IX_OSAL_WAIT_NONE) {
|
||||
if (drv_mutex_trylock(mutex))
|
||||
return IX_SUCCESS;
|
||||
else
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
tries = (timeout * 1000) / 50;
|
||||
while (1) {
|
||||
if (drv_mutex_trylock(mutex))
|
||||
return IX_SUCCESS;
|
||||
if (timeout != IX_OSAL_WAIT_FOREVER && tries-- <= 0)
|
||||
break;
|
||||
udelay(50);
|
||||
}
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalMutexUnlock (IxOsalMutex * mutex)
|
||||
{
|
||||
drv_mutex_unlock(mutex);
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to get mutex, return immediately,
|
||||
* no error info because users expect some failures
|
||||
* when using this API.
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalMutexTryLock (IxOsalMutex * mutex)
|
||||
{
|
||||
if (drv_mutex_trylock(mutex))
|
||||
return IX_SUCCESS;
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalMutexDestroy (IxOsalMutex * mutex)
|
||||
{
|
||||
drv_mutex_destroy(mutex);
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalFastMutexInit (IxOsalFastMutex * mutex)
|
||||
{
|
||||
return ixOsalMutexInit(mutex);
|
||||
}
|
||||
|
||||
PUBLIC IX_STATUS ixOsalFastMutexTryLock(IxOsalFastMutex *mutex)
|
||||
{
|
||||
return ixOsalMutexTryLock(mutex);
|
||||
}
|
||||
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalFastMutexUnlock (IxOsalFastMutex * mutex)
|
||||
{
|
||||
return ixOsalMutexUnlock(mutex);
|
||||
}
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalFastMutexDestroy (IxOsalFastMutex * mutex)
|
||||
{
|
||||
return ixOsalMutexDestroy(mutex);
|
||||
}
|
251
cpu/ixp/npe/IxOsalOsServices.c
Normal file
251
cpu/ixp/npe/IxOsalOsServices.c
Normal file
@ -0,0 +1,251 @@
|
||||
/**
|
||||
* @file IxOsalOsServices.c (linux)
|
||||
*
|
||||
* @brief Implementation for Irq, Mem, sleep.
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 1.5
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include "IxOsal.h"
|
||||
#include <IxEthAcc.h>
|
||||
#include <IxEthDB.h>
|
||||
#include <IxNpeDl.h>
|
||||
#include <IxQMgr.h>
|
||||
#include <IxNpeMh.h>
|
||||
|
||||
static char *traceHeaders[] = {
|
||||
"",
|
||||
"[fatal] ",
|
||||
"[error] ",
|
||||
"[warning] ",
|
||||
"[message] ",
|
||||
"[debug1] ",
|
||||
"[debug2] ",
|
||||
"[debug3] ",
|
||||
"[all]"
|
||||
};
|
||||
|
||||
/* by default trace all but debug message */
|
||||
PRIVATE int ixOsalCurrLogLevel = IX_OSAL_LOG_LVL_MESSAGE;
|
||||
|
||||
/**************************************
|
||||
* Irq services
|
||||
*************************************/
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalIrqBind (UINT32 vector, IxOsalVoidFnVoidPtr routine, void *parameter)
|
||||
{
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalIrqUnbind (UINT32 vector)
|
||||
{
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
PUBLIC UINT32
|
||||
ixOsalIrqLock ()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Enable interrupts and task scheduling,
|
||||
* input parameter: irqEnable status returned
|
||||
* by ixOsalIrqLock().
|
||||
*/
|
||||
PUBLIC void
|
||||
ixOsalIrqUnlock (UINT32 lockKey)
|
||||
{
|
||||
}
|
||||
|
||||
PUBLIC UINT32
|
||||
ixOsalIrqLevelSet (UINT32 level)
|
||||
{
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
PUBLIC void
|
||||
ixOsalIrqEnable (UINT32 irqLevel)
|
||||
{
|
||||
}
|
||||
|
||||
PUBLIC void
|
||||
ixOsalIrqDisable (UINT32 irqLevel)
|
||||
{
|
||||
}
|
||||
|
||||
/*********************
|
||||
* Log function
|
||||
*********************/
|
||||
|
||||
INT32
|
||||
ixOsalLog (IxOsalLogLevel level,
|
||||
IxOsalLogDevice device,
|
||||
char *format, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6)
|
||||
{
|
||||
/*
|
||||
* Return -1 for custom display devices
|
||||
*/
|
||||
if ((device != IX_OSAL_LOG_DEV_STDOUT)
|
||||
&& (device != IX_OSAL_LOG_DEV_STDERR))
|
||||
{
|
||||
debug("ixOsalLog: only IX_OSAL_LOG_DEV_STDOUT and IX_OSAL_LOG_DEV_STDERR are supported \n");
|
||||
return (IX_OSAL_LOG_ERROR);
|
||||
}
|
||||
|
||||
if (level <= ixOsalCurrLogLevel && level != IX_OSAL_LOG_LVL_NONE)
|
||||
{
|
||||
#if 0 /* sr: U-Boots printf or debug doesn't return a length */
|
||||
int headerByteCount = (level == IX_OSAL_LOG_LVL_USER) ? 0 : diag_printf(traceHeaders[level - 1]);
|
||||
|
||||
return headerByteCount + diag_printf (format, arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
#else
|
||||
int headerByteCount = (level == IX_OSAL_LOG_LVL_USER) ? 0 : strlen(traceHeaders[level - 1]);
|
||||
|
||||
return headerByteCount + strlen(format);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Return error
|
||||
*/
|
||||
return (IX_OSAL_LOG_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
PUBLIC UINT32
|
||||
ixOsalLogLevelSet (UINT32 level)
|
||||
{
|
||||
UINT32 oldLevel;
|
||||
|
||||
/*
|
||||
* Check value first
|
||||
*/
|
||||
if ((level < IX_OSAL_LOG_LVL_NONE) || (level > IX_OSAL_LOG_LVL_ALL))
|
||||
{
|
||||
ixOsalLog (IX_OSAL_LOG_LVL_MESSAGE,
|
||||
IX_OSAL_LOG_DEV_STDOUT,
|
||||
"ixOsalLogLevelSet: Log Level is between %d and%d \n",
|
||||
IX_OSAL_LOG_LVL_NONE, IX_OSAL_LOG_LVL_ALL, 0, 0, 0, 0);
|
||||
return IX_OSAL_LOG_LVL_NONE;
|
||||
}
|
||||
oldLevel = ixOsalCurrLogLevel;
|
||||
|
||||
ixOsalCurrLogLevel = level;
|
||||
|
||||
return oldLevel;
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* Task services
|
||||
*************************************/
|
||||
|
||||
PUBLIC void
|
||||
ixOsalBusySleep (UINT32 microseconds)
|
||||
{
|
||||
udelay(microseconds);
|
||||
}
|
||||
|
||||
PUBLIC void
|
||||
ixOsalSleep (UINT32 milliseconds)
|
||||
{
|
||||
if (milliseconds != 0) {
|
||||
#if 1
|
||||
/*
|
||||
* sr: We poll while we wait because interrupts are off in U-Boot
|
||||
* and CSR expects messages, etc to be dispatched while sleeping.
|
||||
*/
|
||||
int i;
|
||||
IxQMgrDispatcherFuncPtr qDispatcherFunc;
|
||||
|
||||
ixQMgrDispatcherLoopGet(&qDispatcherFunc);
|
||||
|
||||
while (milliseconds--) {
|
||||
for (i = 1; i <= 2; i++)
|
||||
ixNpeMhMessagesReceive(i);
|
||||
(*qDispatcherFunc)(IX_QMGR_QUELOW_GROUP);
|
||||
|
||||
udelay(1000);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* Memory functions
|
||||
*************************************/
|
||||
|
||||
void *
|
||||
ixOsalMemAlloc (UINT32 size)
|
||||
{
|
||||
return (void *)0;
|
||||
}
|
||||
|
||||
void
|
||||
ixOsalMemFree (void *ptr)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy count bytes from src to dest ,
|
||||
* returns pointer to the dest mem zone.
|
||||
*/
|
||||
void *
|
||||
ixOsalMemCopy (void *dest, void *src, UINT32 count)
|
||||
{
|
||||
IX_OSAL_ASSERT (dest != NULL);
|
||||
IX_OSAL_ASSERT (src != NULL);
|
||||
return (memcpy (dest, src, count));
|
||||
}
|
||||
|
||||
/*
|
||||
* Fills a memory zone with a given constant byte,
|
||||
* returns pointer to the memory zone.
|
||||
*/
|
||||
void *
|
||||
ixOsalMemSet (void *ptr, UINT8 filler, UINT32 count)
|
||||
{
|
||||
IX_OSAL_ASSERT (ptr != NULL);
|
||||
return (memset (ptr, filler, count));
|
||||
}
|
98
cpu/ixp/npe/IxOsalOsThread.c
Normal file
98
cpu/ixp/npe/IxOsalOsThread.c
Normal file
@ -0,0 +1,98 @@
|
||||
/**
|
||||
* @file IxOsalOsThread.c (eCos)
|
||||
*
|
||||
* @brief OS-specific thread implementation.
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 1.5
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
#include "IxOsal.h"
|
||||
|
||||
/* Thread attribute is ignored */
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalThreadCreate (IxOsalThread * ptrTid,
|
||||
IxOsalThreadAttr * threadAttr, IxOsalVoidFnVoidPtr entryPoint, void *arg)
|
||||
{
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start thread after given its thread handle
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalThreadStart (IxOsalThread * tId)
|
||||
{
|
||||
/* Thread already started upon creation */
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* In Linux threadKill does not actually destroy the thread,
|
||||
* it will stop the signal handling.
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalThreadKill (IxOsalThread * tid)
|
||||
{
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
PUBLIC void
|
||||
ixOsalThreadExit (void)
|
||||
{
|
||||
}
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalThreadPrioritySet (IxOsalOsThread * tid, UINT32 priority)
|
||||
{
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalThreadSuspend (IxOsalThread * tId)
|
||||
{
|
||||
return IX_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixOsalThreadResume (IxOsalThread * tId)
|
||||
{
|
||||
return IX_SUCCESS;
|
||||
}
|
963
cpu/ixp/npe/IxQMgrAqmIf.c
Normal file
963
cpu/ixp/npe/IxQMgrAqmIf.c
Normal file
@ -0,0 +1,963 @@
|
||||
/*
|
||||
* @file: IxQMgrAqmIf.c
|
||||
*
|
||||
* @author Intel Corporation
|
||||
* @date 30-Oct-2001
|
||||
*
|
||||
* @brief This component provides a set of functions for
|
||||
* perfoming I/O on the AQM hardware.
|
||||
*
|
||||
* Design Notes:
|
||||
* These functions are intended to be as fast as possible
|
||||
* and as a result perform NO PARAMETER CHECKING.
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
/*
|
||||
* Inlines are compiled as function when this is defined.
|
||||
* N.B. Must be placed before #include of "IxQMgrAqmIf_p.h
|
||||
*/
|
||||
#ifndef IXQMGRAQMIF_P_H
|
||||
# define IXQMGRAQMIF_C
|
||||
#else
|
||||
# error
|
||||
#endif
|
||||
|
||||
/*
|
||||
* User defined include files.
|
||||
*/
|
||||
#include "IxOsal.h"
|
||||
#include "IxQMgr.h"
|
||||
#include "IxQMgrAqmIf_p.h"
|
||||
#include "IxQMgrLog_p.h"
|
||||
|
||||
|
||||
/*
|
||||
* #defines and macros used in this file.
|
||||
*/
|
||||
|
||||
/* These defines are the bit offsets of the various fields of
|
||||
* the queue configuration register
|
||||
*/
|
||||
#define IX_QMGR_Q_CONFIG_WRPTR_OFFSET 0x00
|
||||
#define IX_QMGR_Q_CONFIG_RDPTR_OFFSET 0x07
|
||||
#define IX_QMGR_Q_CONFIG_BADDR_OFFSET 0x0E
|
||||
#define IX_QMGR_Q_CONFIG_ESIZE_OFFSET 0x16
|
||||
#define IX_QMGR_Q_CONFIG_BSIZE_OFFSET 0x18
|
||||
#define IX_QMGR_Q_CONFIG_NE_OFFSET 0x1A
|
||||
#define IX_QMGR_Q_CONFIG_NF_OFFSET 0x1D
|
||||
|
||||
#define IX_QMGR_BASE_ADDR_16_WORD_ALIGN 0x40
|
||||
#define IX_QMGR_BASE_ADDR_16_WORD_SHIFT 0x6
|
||||
|
||||
#define IX_QMGR_NE_NF_CLEAR_MASK 0x03FFFFFF
|
||||
#define IX_QMGR_NE_MASK 0x7
|
||||
#define IX_QMGR_NF_MASK 0x7
|
||||
#define IX_QMGR_SIZE_MASK 0x3
|
||||
#define IX_QMGR_ENTRY_SIZE_MASK 0x3
|
||||
#define IX_QMGR_BADDR_MASK 0x003FC000
|
||||
#define IX_QMGR_RDPTR_MASK 0x7F
|
||||
#define IX_QMGR_WRPTR_MASK 0x7F
|
||||
#define IX_QMGR_RDWRPTR_MASK 0x00003FFF
|
||||
|
||||
#define IX_QMGR_AQM_ADDRESS_SPACE_SIZE_IN_WORDS 0x1000
|
||||
|
||||
/* Base address of AQM SRAM */
|
||||
#define IX_QMGR_AQM_SRAM_BASE_ADDRESS_OFFSET \
|
||||
((IX_QMGR_QUECONFIG_BASE_OFFSET) + (IX_QMGR_QUECONFIG_SIZE))
|
||||
|
||||
/* Min buffer size used for generating buffer size in QUECONFIG */
|
||||
#define IX_QMGR_MIN_BUFFER_SIZE 16
|
||||
|
||||
/* Reset values of QMgr hardware registers */
|
||||
#define IX_QMGR_QUELOWSTAT_RESET_VALUE 0x33333333
|
||||
#define IX_QMGR_QUEUOSTAT_RESET_VALUE 0x00000000
|
||||
#define IX_QMGR_QUEUPPSTAT0_RESET_VALUE 0xFFFFFFFF
|
||||
#define IX_QMGR_QUEUPPSTAT1_RESET_VALUE 0x00000000
|
||||
#define IX_QMGR_INT0SRCSELREG_RESET_VALUE 0x00000000
|
||||
#define IX_QMGR_QUEIEREG_RESET_VALUE 0x00000000
|
||||
#define IX_QMGR_QINTREG_RESET_VALUE 0xFFFFFFFF
|
||||
#define IX_QMGR_QUECONFIG_RESET_VALUE 0x00000000
|
||||
|
||||
#define IX_QMGR_PHYSICAL_AQM_BASE_ADDRESS IX_OSAL_IXP400_QMGR_PHYS_BASE
|
||||
|
||||
#define IX_QMGR_QUELOWSTAT_BITS_PER_Q (BITS_PER_WORD/IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD)
|
||||
|
||||
#define IX_QMGR_QUELOWSTAT_QID_MASK 0x7
|
||||
#define IX_QMGR_Q_CONFIG_ADDR_GET(qId)\
|
||||
(((qId) * IX_QMGR_NUM_BYTES_PER_WORD) +\
|
||||
IX_QMGR_QUECONFIG_BASE_OFFSET)
|
||||
|
||||
#define IX_QMGR_ENTRY1_OFFSET 0
|
||||
#define IX_QMGR_ENTRY2_OFFSET 1
|
||||
#define IX_QMGR_ENTRY4_OFFSET 3
|
||||
|
||||
/*
|
||||
* Variable declarations global to this file. Externs are followed by
|
||||
* statics.
|
||||
*/
|
||||
UINT32 aqmBaseAddress = 0;
|
||||
/* Store addresses and bit-masks for certain queue access and status registers.
|
||||
* This is to facilitate inlining of QRead, QWrite and QStatusGet functions
|
||||
* in IxQMgr,h
|
||||
*/
|
||||
extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
|
||||
UINT32 * ixQMgrAqmIfQueAccRegAddr[IX_QMGR_MAX_NUM_QUEUES];
|
||||
UINT32 ixQMgrAqmIfQueLowStatRegAddr[IX_QMGR_MIN_QUEUPP_QID];
|
||||
UINT32 ixQMgrAqmIfQueLowStatBitsOffset[IX_QMGR_MIN_QUEUPP_QID];
|
||||
UINT32 ixQMgrAqmIfQueLowStatBitsMask;
|
||||
UINT32 ixQMgrAqmIfQueUppStat0RegAddr;
|
||||
UINT32 ixQMgrAqmIfQueUppStat1RegAddr;
|
||||
UINT32 ixQMgrAqmIfQueUppStat0BitMask[IX_QMGR_MIN_QUEUPP_QID];
|
||||
UINT32 ixQMgrAqmIfQueUppStat1BitMask[IX_QMGR_MIN_QUEUPP_QID];
|
||||
|
||||
/*
|
||||
* Fast mutexes, one for each queue, used to protect peek & poke functions
|
||||
*/
|
||||
IxOsalFastMutex ixQMgrAqmIfPeekPokeFastMutex[IX_QMGR_MAX_NUM_QUEUES];
|
||||
|
||||
/*
|
||||
* Function prototypes
|
||||
*/
|
||||
PRIVATE unsigned
|
||||
watermarkToAqmWatermark (IxQMgrWMLevel watermark );
|
||||
|
||||
PRIVATE unsigned
|
||||
entrySizeToAqmEntrySize (IxQMgrQEntrySizeInWords entrySize);
|
||||
|
||||
PRIVATE unsigned
|
||||
bufferSizeToAqmBufferSize (unsigned bufferSizeInWords);
|
||||
|
||||
PRIVATE void
|
||||
ixQMgrAqmIfRegistersReset (void);
|
||||
|
||||
PRIVATE void
|
||||
ixQMgrAqmIfEntryAddressGet (unsigned int entryIndex,
|
||||
UINT32 configRegWord,
|
||||
unsigned int qEntrySizeInwords,
|
||||
unsigned int qSizeInWords,
|
||||
UINT32 **address);
|
||||
/*
|
||||
* Function definitions
|
||||
*/
|
||||
void
|
||||
ixQMgrAqmIfInit (void)
|
||||
{
|
||||
UINT32 aqmVirtualAddr;
|
||||
int i;
|
||||
|
||||
/* The value of aqmBaseAddress depends on the logical address
|
||||
* assigned by the MMU.
|
||||
*/
|
||||
aqmVirtualAddr =
|
||||
(UINT32) IX_OSAL_MEM_MAP(IX_QMGR_PHYSICAL_AQM_BASE_ADDRESS,
|
||||
IX_OSAL_IXP400_QMGR_MAP_SIZE);
|
||||
IX_OSAL_ASSERT (aqmVirtualAddr);
|
||||
|
||||
ixQMgrAqmIfBaseAddressSet (aqmVirtualAddr);
|
||||
|
||||
ixQMgrAqmIfRegistersReset ();
|
||||
|
||||
for (i = 0; i< IX_QMGR_MAX_NUM_QUEUES; i++)
|
||||
{
|
||||
ixOsalFastMutexInit(&ixQMgrAqmIfPeekPokeFastMutex[i]);
|
||||
|
||||
/********************************************************************
|
||||
* Register addresses and bit masks are calculated and stored here to
|
||||
* facilitate inlining of QRead, QWrite and QStatusGet functions in
|
||||
* IxQMgr.h.
|
||||
* These calculations are normally performed dynamically in inlined
|
||||
* functions in IxQMgrAqmIf_p.h, and their semantics are reused here.
|
||||
*/
|
||||
|
||||
/* AQM Queue access reg addresses, per queue */
|
||||
ixQMgrAqmIfQueAccRegAddr[i] =
|
||||
(UINT32 *)(aqmBaseAddress + IX_QMGR_Q_ACCESS_ADDR_GET(i));
|
||||
ixQMgrQInlinedReadWriteInfo[i].qAccRegAddr =
|
||||
(volatile UINT32 *)(aqmBaseAddress + IX_QMGR_Q_ACCESS_ADDR_GET(i));
|
||||
|
||||
|
||||
ixQMgrQInlinedReadWriteInfo[i].qConfigRegAddr =
|
||||
(volatile UINT32 *)(aqmBaseAddress + IX_QMGR_Q_CONFIG_ADDR_GET(i));
|
||||
|
||||
/* AQM Queue lower-group (0-31), only */
|
||||
if (i < IX_QMGR_MIN_QUEUPP_QID)
|
||||
{
|
||||
/* AQM Q underflow/overflow status register addresses, per queue */
|
||||
ixQMgrQInlinedReadWriteInfo[i].qUOStatRegAddr =
|
||||
(volatile UINT32 *)(aqmBaseAddress +
|
||||
IX_QMGR_QUEUOSTAT0_OFFSET +
|
||||
((i / IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD) *
|
||||
IX_QMGR_NUM_BYTES_PER_WORD));
|
||||
|
||||
/* AQM Q underflow status bit masks for status register per queue */
|
||||
ixQMgrQInlinedReadWriteInfo[i].qUflowStatBitMask =
|
||||
(IX_QMGR_UNDERFLOW_BIT_OFFSET + 1) <<
|
||||
((i & (IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD - 1)) *
|
||||
(BITS_PER_WORD / IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD));
|
||||
|
||||
/* AQM Q overflow status bit masks for status register, per queue */
|
||||
ixQMgrQInlinedReadWriteInfo[i].qOflowStatBitMask =
|
||||
(IX_QMGR_OVERFLOW_BIT_OFFSET + 1) <<
|
||||
((i & (IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD - 1)) *
|
||||
(BITS_PER_WORD / IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD));
|
||||
|
||||
/* AQM Q lower-group (0-31) status register addresses, per queue */
|
||||
ixQMgrAqmIfQueLowStatRegAddr[i] = aqmBaseAddress +
|
||||
IX_QMGR_QUELOWSTAT0_OFFSET +
|
||||
((i / IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD) *
|
||||
IX_QMGR_NUM_BYTES_PER_WORD);
|
||||
|
||||
/* AQM Q lower-group (0-31) status register bit offset */
|
||||
ixQMgrAqmIfQueLowStatBitsOffset[i] =
|
||||
(i & (IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD - 1)) *
|
||||
(BITS_PER_WORD / IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD);
|
||||
}
|
||||
else /* AQM Q upper-group (32-63), only */
|
||||
{
|
||||
/* AQM Q upper-group (32-63) Nearly Empty status reg bit masks */
|
||||
ixQMgrAqmIfQueUppStat0BitMask[i - IX_QMGR_MIN_QUEUPP_QID] =
|
||||
(1 << (i - IX_QMGR_MIN_QUEUPP_QID));
|
||||
|
||||
/* AQM Q upper-group (32-63) Full status register bit masks */
|
||||
ixQMgrAqmIfQueUppStat1BitMask[i - IX_QMGR_MIN_QUEUPP_QID] =
|
||||
(1 << (i - IX_QMGR_MIN_QUEUPP_QID));
|
||||
}
|
||||
}
|
||||
|
||||
/* AQM Q lower-group (0-31) status register bit mask */
|
||||
ixQMgrAqmIfQueLowStatBitsMask = (1 <<
|
||||
(BITS_PER_WORD /
|
||||
IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD)) - 1;
|
||||
|
||||
/* AQM Q upper-group (32-63) Nearly Empty status register address */
|
||||
ixQMgrAqmIfQueUppStat0RegAddr = aqmBaseAddress + IX_QMGR_QUEUPPSTAT0_OFFSET;
|
||||
|
||||
/* AQM Q upper-group (32-63) Full status register address */
|
||||
ixQMgrAqmIfQueUppStat1RegAddr = aqmBaseAddress + IX_QMGR_QUEUPPSTAT1_OFFSET;
|
||||
}
|
||||
|
||||
/*
|
||||
* Uninitialise the AqmIf module by unmapping memory, etc
|
||||
*/
|
||||
void
|
||||
ixQMgrAqmIfUninit (void)
|
||||
{
|
||||
UINT32 virtAddr;
|
||||
|
||||
ixQMgrAqmIfBaseAddressGet (&virtAddr);
|
||||
IX_OSAL_MEM_UNMAP (virtAddr);
|
||||
ixQMgrAqmIfBaseAddressSet (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the the logical base address of AQM
|
||||
*/
|
||||
void
|
||||
ixQMgrAqmIfBaseAddressSet (UINT32 address)
|
||||
{
|
||||
aqmBaseAddress = address;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the logical base address of AQM
|
||||
*/
|
||||
void
|
||||
ixQMgrAqmIfBaseAddressGet (UINT32 *address)
|
||||
{
|
||||
*address = aqmBaseAddress;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the logical base address of AQM SRAM
|
||||
*/
|
||||
void
|
||||
ixQMgrAqmIfSramBaseAddressGet (UINT32 *address)
|
||||
{
|
||||
*address = aqmBaseAddress +
|
||||
IX_QMGR_AQM_SRAM_BASE_ADDRESS_OFFSET;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function will write the status bits of a queue
|
||||
* specified by qId.
|
||||
*/
|
||||
void
|
||||
ixQMgrAqmIfQRegisterBitsWrite (IxQMgrQId qId,
|
||||
UINT32 registerBaseAddrOffset,
|
||||
unsigned queuesPerRegWord,
|
||||
UINT32 value)
|
||||
{
|
||||
volatile UINT32 *registerAddress;
|
||||
UINT32 registerWord;
|
||||
UINT32 statusBitsMask;
|
||||
UINT32 bitsPerQueue;
|
||||
|
||||
bitsPerQueue = BITS_PER_WORD / queuesPerRegWord;
|
||||
|
||||
/*
|
||||
* Calculate the registerAddress
|
||||
* multiple queues split accross registers
|
||||
*/
|
||||
registerAddress = (UINT32*)(aqmBaseAddress +
|
||||
registerBaseAddrOffset +
|
||||
((qId / queuesPerRegWord) *
|
||||
IX_QMGR_NUM_BYTES_PER_WORD));
|
||||
|
||||
/* Read the current data */
|
||||
ixQMgrAqmIfWordRead (registerAddress, ®isterWord);
|
||||
|
||||
|
||||
if( (registerBaseAddrOffset == IX_QMGR_INT0SRCSELREG0_OFFSET) &&
|
||||
(qId == IX_QMGR_QUEUE_0) )
|
||||
{
|
||||
statusBitsMask = 0x7 ;
|
||||
|
||||
/* Queue 0 at INT0SRCSELREG should not corrupt the value bit-3 */
|
||||
value &= 0x7 ;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Calculate the mask for the status bits for this queue. */
|
||||
statusBitsMask = ((1 << bitsPerQueue) - 1);
|
||||
statusBitsMask <<= ((qId & (queuesPerRegWord - 1)) * bitsPerQueue);
|
||||
|
||||
/* Mask out bits in value that would overwrite other q data */
|
||||
value <<= ((qId & (queuesPerRegWord - 1)) * bitsPerQueue);
|
||||
value &= statusBitsMask;
|
||||
}
|
||||
|
||||
/* Mask out bits to write to */
|
||||
registerWord &= ~statusBitsMask;
|
||||
|
||||
|
||||
/* Set the write bits */
|
||||
registerWord |= value;
|
||||
|
||||
/*
|
||||
* Write the data
|
||||
*/
|
||||
ixQMgrAqmIfWordWrite (registerAddress, registerWord);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function generates the parameters that can be used to
|
||||
* check if a Qs status matches the specified source select.
|
||||
* It calculates which status word to check (statusWordOffset),
|
||||
* the value to check the status against (checkValue) and the
|
||||
* mask (mask) to mask out all but the bits to check in the status word.
|
||||
*/
|
||||
void
|
||||
ixQMgrAqmIfQStatusCheckValsCalc (IxQMgrQId qId,
|
||||
IxQMgrSourceId srcSel,
|
||||
unsigned int *statusWordOffset,
|
||||
UINT32 *checkValue,
|
||||
UINT32 *mask)
|
||||
{
|
||||
UINT32 shiftVal;
|
||||
|
||||
if (qId < IX_QMGR_MIN_QUEUPP_QID)
|
||||
{
|
||||
switch (srcSel)
|
||||
{
|
||||
case IX_QMGR_Q_SOURCE_ID_E:
|
||||
*checkValue = IX_QMGR_Q_STATUS_E_BIT_MASK;
|
||||
*mask = IX_QMGR_Q_STATUS_E_BIT_MASK;
|
||||
break;
|
||||
case IX_QMGR_Q_SOURCE_ID_NE:
|
||||
*checkValue = IX_QMGR_Q_STATUS_NE_BIT_MASK;
|
||||
*mask = IX_QMGR_Q_STATUS_NE_BIT_MASK;
|
||||
break;
|
||||
case IX_QMGR_Q_SOURCE_ID_NF:
|
||||
*checkValue = IX_QMGR_Q_STATUS_NF_BIT_MASK;
|
||||
*mask = IX_QMGR_Q_STATUS_NF_BIT_MASK;
|
||||
break;
|
||||
case IX_QMGR_Q_SOURCE_ID_F:
|
||||
*checkValue = IX_QMGR_Q_STATUS_F_BIT_MASK;
|
||||
*mask = IX_QMGR_Q_STATUS_F_BIT_MASK;
|
||||
break;
|
||||
case IX_QMGR_Q_SOURCE_ID_NOT_E:
|
||||
*checkValue = 0;
|
||||
*mask = IX_QMGR_Q_STATUS_E_BIT_MASK;
|
||||
break;
|
||||
case IX_QMGR_Q_SOURCE_ID_NOT_NE:
|
||||
*checkValue = 0;
|
||||
*mask = IX_QMGR_Q_STATUS_NE_BIT_MASK;
|
||||
break;
|
||||
case IX_QMGR_Q_SOURCE_ID_NOT_NF:
|
||||
*checkValue = 0;
|
||||
*mask = IX_QMGR_Q_STATUS_NF_BIT_MASK;
|
||||
break;
|
||||
case IX_QMGR_Q_SOURCE_ID_NOT_F:
|
||||
*checkValue = 0;
|
||||
*mask = IX_QMGR_Q_STATUS_F_BIT_MASK;
|
||||
break;
|
||||
default:
|
||||
/* Should never hit */
|
||||
IX_OSAL_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
/* One nibble of status per queue so need to shift the
|
||||
* check value and mask out to the correct position.
|
||||
*/
|
||||
shiftVal = (qId % IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD) *
|
||||
IX_QMGR_QUELOWSTAT_BITS_PER_Q;
|
||||
|
||||
/* Calculate the which status word to check from the qId,
|
||||
* 8 Qs status per word
|
||||
*/
|
||||
*statusWordOffset = qId / IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD;
|
||||
|
||||
*checkValue <<= shiftVal;
|
||||
*mask <<= shiftVal;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* One status word */
|
||||
*statusWordOffset = 0;
|
||||
/* Single bits per queue and int source bit hardwired NE,
|
||||
* Qs start at 32.
|
||||
*/
|
||||
*mask = 1 << (qId - IX_QMGR_MIN_QUEUPP_QID);
|
||||
*checkValue = *mask;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ixQMgrAqmIfQInterruptEnable (IxQMgrQId qId)
|
||||
{
|
||||
volatile UINT32 *registerAddress;
|
||||
UINT32 registerWord;
|
||||
UINT32 actualBitOffset;
|
||||
|
||||
if (qId < IX_QMGR_MIN_QUEUPP_QID)
|
||||
{
|
||||
registerAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_QUEIEREG0_OFFSET);
|
||||
}
|
||||
else
|
||||
{
|
||||
registerAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_QUEIEREG1_OFFSET);
|
||||
}
|
||||
|
||||
actualBitOffset = 1 << (qId % IX_QMGR_MIN_QUEUPP_QID);
|
||||
|
||||
ixQMgrAqmIfWordRead (registerAddress, ®isterWord);
|
||||
ixQMgrAqmIfWordWrite (registerAddress, (registerWord | actualBitOffset));
|
||||
}
|
||||
|
||||
void
|
||||
ixQMgrAqmIfQInterruptDisable (IxQMgrQId qId)
|
||||
{
|
||||
volatile UINT32 *registerAddress;
|
||||
UINT32 registerWord;
|
||||
UINT32 actualBitOffset;
|
||||
|
||||
if (qId < IX_QMGR_MIN_QUEUPP_QID)
|
||||
{
|
||||
registerAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_QUEIEREG0_OFFSET);
|
||||
}
|
||||
else
|
||||
{
|
||||
registerAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_QUEIEREG1_OFFSET);
|
||||
}
|
||||
|
||||
actualBitOffset = 1 << (qId % IX_QMGR_MIN_QUEUPP_QID);
|
||||
|
||||
ixQMgrAqmIfWordRead (registerAddress, ®isterWord);
|
||||
ixQMgrAqmIfWordWrite (registerAddress, registerWord & (~actualBitOffset));
|
||||
}
|
||||
|
||||
void
|
||||
ixQMgrAqmIfQueCfgWrite (IxQMgrQId qId,
|
||||
IxQMgrQSizeInWords qSizeInWords,
|
||||
IxQMgrQEntrySizeInWords entrySizeInWords,
|
||||
UINT32 freeSRAMAddress)
|
||||
{
|
||||
volatile UINT32 *cfgAddress = NULL;
|
||||
UINT32 qCfg = 0;
|
||||
UINT32 baseAddress = 0;
|
||||
unsigned aqmEntrySize = 0;
|
||||
unsigned aqmBufferSize = 0;
|
||||
|
||||
/* Build config register */
|
||||
aqmEntrySize = entrySizeToAqmEntrySize (entrySizeInWords);
|
||||
qCfg |= (aqmEntrySize&IX_QMGR_ENTRY_SIZE_MASK) <<
|
||||
IX_QMGR_Q_CONFIG_ESIZE_OFFSET;
|
||||
|
||||
aqmBufferSize = bufferSizeToAqmBufferSize (qSizeInWords);
|
||||
qCfg |= (aqmBufferSize&IX_QMGR_SIZE_MASK) << IX_QMGR_Q_CONFIG_BSIZE_OFFSET;
|
||||
|
||||
/* baseAddress, calculated relative to aqmBaseAddress and start address */
|
||||
baseAddress = freeSRAMAddress -
|
||||
(aqmBaseAddress + IX_QMGR_QUECONFIG_BASE_OFFSET);
|
||||
|
||||
/* Verify base address aligned to a 16 word boundary */
|
||||
if ((baseAddress % IX_QMGR_BASE_ADDR_16_WORD_ALIGN) != 0)
|
||||
{
|
||||
IX_QMGR_LOG_ERROR0("ixQMgrAqmIfQueCfgWrite () address is not on 16 word boundary\n");
|
||||
}
|
||||
/* Now convert it to a 16 word pointer as required by QUECONFIG register */
|
||||
baseAddress >>= IX_QMGR_BASE_ADDR_16_WORD_SHIFT;
|
||||
|
||||
|
||||
qCfg |= (baseAddress << IX_QMGR_Q_CONFIG_BADDR_OFFSET);
|
||||
|
||||
|
||||
cfgAddress = (UINT32*)(aqmBaseAddress +
|
||||
IX_QMGR_Q_CONFIG_ADDR_GET(qId));
|
||||
|
||||
|
||||
/* NOTE: High and Low watermarks are set to zero */
|
||||
ixQMgrAqmIfWordWrite (cfgAddress, qCfg);
|
||||
}
|
||||
|
||||
void
|
||||
ixQMgrAqmIfQueCfgRead (IxQMgrQId qId,
|
||||
unsigned int numEntries,
|
||||
UINT32 *baseAddress,
|
||||
unsigned int *ne,
|
||||
unsigned int *nf,
|
||||
UINT32 *readPtr,
|
||||
UINT32 *writePtr)
|
||||
{
|
||||
UINT32 qcfg;
|
||||
UINT32 *cfgAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_Q_CONFIG_ADDR_GET(qId));
|
||||
unsigned int qEntrySizeInwords;
|
||||
unsigned int qSizeInWords;
|
||||
UINT32 *readPtr_ = NULL;
|
||||
|
||||
/* Read the queue configuration register */
|
||||
ixQMgrAqmIfWordRead (cfgAddress, &qcfg);
|
||||
|
||||
/* Extract the base address */
|
||||
*baseAddress = (UINT32)((qcfg & IX_QMGR_BADDR_MASK) >>
|
||||
(IX_QMGR_Q_CONFIG_BADDR_OFFSET));
|
||||
|
||||
/* Base address is a 16 word pointer from the start of AQM SRAM.
|
||||
* Convert to absolute word address.
|
||||
*/
|
||||
*baseAddress <<= IX_QMGR_BASE_ADDR_16_WORD_SHIFT;
|
||||
*baseAddress += (UINT32)IX_QMGR_QUECONFIG_BASE_OFFSET;
|
||||
|
||||
/*
|
||||
* Extract the watermarks. 0->0 entries, 1->1 entries, 2->2 entries, 3->4 entries......
|
||||
* If ne > 0 ==> neInEntries = 2^(ne - 1)
|
||||
* If ne == 0 ==> neInEntries = 0
|
||||
* The same applies.
|
||||
*/
|
||||
*ne = ((qcfg) >> (IX_QMGR_Q_CONFIG_NE_OFFSET)) & IX_QMGR_NE_MASK;
|
||||
*nf = ((qcfg) >> (IX_QMGR_Q_CONFIG_NF_OFFSET)) & IX_QMGR_NF_MASK;
|
||||
|
||||
if (0 != *ne)
|
||||
{
|
||||
*ne = 1 << (*ne - 1);
|
||||
}
|
||||
if (0 != *nf)
|
||||
{
|
||||
*nf = 1 << (*nf - 1);
|
||||
}
|
||||
|
||||
/* Get the queue entry size in words */
|
||||
qEntrySizeInwords = ixQMgrQEntrySizeInWordsGet (qId);
|
||||
|
||||
/* Get the queue size in words */
|
||||
qSizeInWords = ixQMgrQSizeInWordsGet (qId);
|
||||
|
||||
ixQMgrAqmIfEntryAddressGet (0/* Entry 0. i.e the readPtr*/,
|
||||
qcfg,
|
||||
qEntrySizeInwords,
|
||||
qSizeInWords,
|
||||
&readPtr_);
|
||||
*readPtr = (UINT32)readPtr_;
|
||||
*readPtr -= (UINT32)aqmBaseAddress;/* Offset, not absolute address */
|
||||
|
||||
*writePtr = (qcfg >> IX_QMGR_Q_CONFIG_WRPTR_OFFSET) & IX_QMGR_WRPTR_MASK;
|
||||
*writePtr = *baseAddress + (*writePtr * (IX_QMGR_NUM_BYTES_PER_WORD));
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned
|
||||
ixQMgrAqmIfLog2 (unsigned number)
|
||||
{
|
||||
unsigned count = 0;
|
||||
|
||||
/*
|
||||
* N.B. this function will return 0
|
||||
* for ixQMgrAqmIfLog2 (0)
|
||||
*/
|
||||
while (number/2)
|
||||
{
|
||||
number /=2;
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void ixQMgrAqmIfIntSrcSelReg0Bit3Set (void)
|
||||
{
|
||||
|
||||
volatile UINT32 *registerAddress;
|
||||
UINT32 registerWord;
|
||||
|
||||
/*
|
||||
* Calculate the registerAddress
|
||||
* multiple queues split accross registers
|
||||
*/
|
||||
registerAddress = (UINT32*)(aqmBaseAddress +
|
||||
IX_QMGR_INT0SRCSELREG0_OFFSET);
|
||||
|
||||
/* Read the current data */
|
||||
ixQMgrAqmIfWordRead (registerAddress, ®isterWord);
|
||||
|
||||
/* Set the write bits */
|
||||
registerWord |= (1<<IX_QMGR_INT0SRCSELREG0_BIT3) ;
|
||||
|
||||
/*
|
||||
* Write the data
|
||||
*/
|
||||
ixQMgrAqmIfWordWrite (registerAddress, registerWord);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ixQMgrAqmIfIntSrcSelWrite (IxQMgrQId qId,
|
||||
IxQMgrSourceId sourceId)
|
||||
{
|
||||
ixQMgrAqmIfQRegisterBitsWrite (qId,
|
||||
IX_QMGR_INT0SRCSELREG0_OFFSET,
|
||||
IX_QMGR_INTSRC_NUM_QUE_PER_WORD,
|
||||
sourceId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ixQMgrAqmIfWatermarkSet (IxQMgrQId qId,
|
||||
unsigned ne,
|
||||
unsigned nf)
|
||||
{
|
||||
volatile UINT32 *address = 0;
|
||||
UINT32 value = 0;
|
||||
unsigned aqmNeWatermark = 0;
|
||||
unsigned aqmNfWatermark = 0;
|
||||
|
||||
address = (UINT32*)(aqmBaseAddress +
|
||||
IX_QMGR_Q_CONFIG_ADDR_GET(qId));
|
||||
|
||||
aqmNeWatermark = watermarkToAqmWatermark (ne);
|
||||
aqmNfWatermark = watermarkToAqmWatermark (nf);
|
||||
|
||||
/* Read the current watermarks */
|
||||
ixQMgrAqmIfWordRead (address, &value);
|
||||
|
||||
/* Clear out the old watermarks */
|
||||
value &= IX_QMGR_NE_NF_CLEAR_MASK;
|
||||
|
||||
/* Generate the value to write */
|
||||
value |= (aqmNeWatermark << IX_QMGR_Q_CONFIG_NE_OFFSET) |
|
||||
(aqmNfWatermark << IX_QMGR_Q_CONFIG_NF_OFFSET);
|
||||
|
||||
ixQMgrAqmIfWordWrite (address, value);
|
||||
|
||||
}
|
||||
|
||||
PRIVATE void
|
||||
ixQMgrAqmIfEntryAddressGet (unsigned int entryIndex,
|
||||
UINT32 configRegWord,
|
||||
unsigned int qEntrySizeInwords,
|
||||
unsigned int qSizeInWords,
|
||||
UINT32 **address)
|
||||
{
|
||||
UINT32 readPtr;
|
||||
UINT32 baseAddress;
|
||||
UINT32 *topOfAqmSram;
|
||||
|
||||
topOfAqmSram = ((UINT32 *)aqmBaseAddress + IX_QMGR_AQM_ADDRESS_SPACE_SIZE_IN_WORDS);
|
||||
|
||||
/* Extract the base address */
|
||||
baseAddress = (UINT32)((configRegWord & IX_QMGR_BADDR_MASK) >>
|
||||
(IX_QMGR_Q_CONFIG_BADDR_OFFSET));
|
||||
|
||||
/* Base address is a 16 word pointer from the start of AQM SRAM.
|
||||
* Convert to absolute word address.
|
||||
*/
|
||||
baseAddress <<= IX_QMGR_BASE_ADDR_16_WORD_SHIFT;
|
||||
baseAddress += ((UINT32)aqmBaseAddress + (UINT32)IX_QMGR_QUECONFIG_BASE_OFFSET);
|
||||
|
||||
/* Extract the read pointer. Read pointer is a word pointer */
|
||||
readPtr = (UINT32)((configRegWord >>
|
||||
IX_QMGR_Q_CONFIG_RDPTR_OFFSET)&IX_QMGR_RDPTR_MASK);
|
||||
|
||||
/* Read/Write pointers(word pointers) are offsets from the queue buffer space base address.
|
||||
* Calculate the absolute read pointer address. NOTE: Queues are circular buffers.
|
||||
*/
|
||||
readPtr = (readPtr + (entryIndex * qEntrySizeInwords)) & (qSizeInWords - 1); /* Mask by queue size */
|
||||
*address = (UINT32 *)(baseAddress + (readPtr * (IX_QMGR_NUM_BYTES_PER_WORD)));
|
||||
|
||||
switch (qEntrySizeInwords)
|
||||
{
|
||||
case IX_QMGR_Q_ENTRY_SIZE1:
|
||||
IX_OSAL_ASSERT((*address + IX_QMGR_ENTRY1_OFFSET) < topOfAqmSram);
|
||||
break;
|
||||
case IX_QMGR_Q_ENTRY_SIZE2:
|
||||
IX_OSAL_ASSERT((*address + IX_QMGR_ENTRY2_OFFSET) < topOfAqmSram);
|
||||
break;
|
||||
case IX_QMGR_Q_ENTRY_SIZE4:
|
||||
IX_OSAL_ASSERT((*address + IX_QMGR_ENTRY4_OFFSET) < topOfAqmSram);
|
||||
break;
|
||||
default:
|
||||
IX_QMGR_LOG_ERROR0("Invalid Q Entry size passed to ixQMgrAqmIfEntryAddressGet");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
IX_STATUS
|
||||
ixQMgrAqmIfQPeek (IxQMgrQId qId,
|
||||
unsigned int entryIndex,
|
||||
unsigned int *entry)
|
||||
{
|
||||
UINT32 *cfgRegAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_Q_CONFIG_ADDR_GET(qId));
|
||||
UINT32 *entryAddress = NULL;
|
||||
UINT32 configRegWordOnEntry;
|
||||
UINT32 configRegWordOnExit;
|
||||
unsigned int qEntrySizeInwords;
|
||||
unsigned int qSizeInWords;
|
||||
|
||||
/* Get the queue entry size in words */
|
||||
qEntrySizeInwords = ixQMgrQEntrySizeInWordsGet (qId);
|
||||
|
||||
/* Get the queue size in words */
|
||||
qSizeInWords = ixQMgrQSizeInWordsGet (qId);
|
||||
|
||||
/* Read the config register */
|
||||
ixQMgrAqmIfWordRead (cfgRegAddress, &configRegWordOnEntry);
|
||||
|
||||
/* Get the entry address */
|
||||
ixQMgrAqmIfEntryAddressGet (entryIndex,
|
||||
configRegWordOnEntry,
|
||||
qEntrySizeInwords,
|
||||
qSizeInWords,
|
||||
&entryAddress);
|
||||
|
||||
/* Get the lock or return busy */
|
||||
if (IX_SUCCESS != ixOsalFastMutexTryLock(&ixQMgrAqmIfPeekPokeFastMutex[qId]))
|
||||
{
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
while(qEntrySizeInwords--)
|
||||
{
|
||||
ixQMgrAqmIfWordRead (entryAddress++, entry++);
|
||||
}
|
||||
|
||||
/* Release the lock */
|
||||
ixOsalFastMutexUnlock(&ixQMgrAqmIfPeekPokeFastMutex[qId]);
|
||||
|
||||
/* Read the config register */
|
||||
ixQMgrAqmIfWordRead (cfgRegAddress, &configRegWordOnExit);
|
||||
|
||||
/* Check that the read and write pointers have not changed */
|
||||
if (configRegWordOnEntry != configRegWordOnExit)
|
||||
{
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
IX_STATUS
|
||||
ixQMgrAqmIfQPoke (IxQMgrQId qId,
|
||||
unsigned entryIndex,
|
||||
unsigned int *entry)
|
||||
{
|
||||
UINT32 *cfgRegAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_Q_CONFIG_ADDR_GET(qId));
|
||||
UINT32 *entryAddress = NULL;
|
||||
UINT32 configRegWordOnEntry;
|
||||
UINT32 configRegWordOnExit;
|
||||
unsigned int qEntrySizeInwords;
|
||||
unsigned int qSizeInWords;
|
||||
|
||||
/* Get the queue entry size in words */
|
||||
qEntrySizeInwords = ixQMgrQEntrySizeInWordsGet (qId);
|
||||
|
||||
/* Get the queue size in words */
|
||||
qSizeInWords = ixQMgrQSizeInWordsGet (qId);
|
||||
|
||||
/* Read the config register */
|
||||
ixQMgrAqmIfWordRead (cfgRegAddress, &configRegWordOnEntry);
|
||||
|
||||
/* Get the entry address */
|
||||
ixQMgrAqmIfEntryAddressGet (entryIndex,
|
||||
configRegWordOnEntry,
|
||||
qEntrySizeInwords,
|
||||
qSizeInWords,
|
||||
&entryAddress);
|
||||
|
||||
/* Get the lock or return busy */
|
||||
if (IX_SUCCESS != ixOsalFastMutexTryLock(&ixQMgrAqmIfPeekPokeFastMutex[qId]))
|
||||
{
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* Else read the entry directly from SRAM. This will not move the read pointer */
|
||||
while(qEntrySizeInwords--)
|
||||
{
|
||||
ixQMgrAqmIfWordWrite (entryAddress++, *entry++);
|
||||
}
|
||||
|
||||
/* Release the lock */
|
||||
ixOsalFastMutexUnlock(&ixQMgrAqmIfPeekPokeFastMutex[qId]);
|
||||
|
||||
/* Read the config register */
|
||||
ixQMgrAqmIfWordRead (cfgRegAddress, &configRegWordOnExit);
|
||||
|
||||
/* Check that the read and write pointers have not changed */
|
||||
if (configRegWordOnEntry != configRegWordOnExit)
|
||||
{
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
PRIVATE unsigned
|
||||
watermarkToAqmWatermark (IxQMgrWMLevel watermark )
|
||||
{
|
||||
unsigned aqmWatermark = 0;
|
||||
|
||||
/*
|
||||
* Watermarks 0("000"),1("001"),2("010"),4("011"),
|
||||
* 8("100"),16("101"),32("110"),64("111")
|
||||
*/
|
||||
aqmWatermark = ixQMgrAqmIfLog2 (watermark * 2);
|
||||
|
||||
return aqmWatermark;
|
||||
}
|
||||
|
||||
PRIVATE unsigned
|
||||
entrySizeToAqmEntrySize (IxQMgrQEntrySizeInWords entrySize)
|
||||
{
|
||||
/* entrySize 1("00"),2("01"),4("10") */
|
||||
return (ixQMgrAqmIfLog2 (entrySize));
|
||||
}
|
||||
|
||||
PRIVATE unsigned
|
||||
bufferSizeToAqmBufferSize (unsigned bufferSizeInWords)
|
||||
{
|
||||
/* bufferSize 16("00"),32("01),64("10"),128("11") */
|
||||
return (ixQMgrAqmIfLog2 (bufferSizeInWords / IX_QMGR_MIN_BUFFER_SIZE));
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset AQM registers to default values.
|
||||
*/
|
||||
PRIVATE void
|
||||
ixQMgrAqmIfRegistersReset (void)
|
||||
{
|
||||
volatile UINT32 *qConfigWordAddress = NULL;
|
||||
unsigned int i;
|
||||
|
||||
/*
|
||||
* Need to initialize AQM hardware registers to an initial
|
||||
* value as init may have been called as a result of a soft
|
||||
* reset. i.e. soft reset does not reset hardware registers.
|
||||
*/
|
||||
|
||||
/* Reset queues 0..31 status registers 0..3 */
|
||||
ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUELOWSTAT0_OFFSET),
|
||||
IX_QMGR_QUELOWSTAT_RESET_VALUE);
|
||||
ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUELOWSTAT1_OFFSET),
|
||||
IX_QMGR_QUELOWSTAT_RESET_VALUE);
|
||||
ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUELOWSTAT2_OFFSET),
|
||||
IX_QMGR_QUELOWSTAT_RESET_VALUE);
|
||||
ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUELOWSTAT3_OFFSET),
|
||||
IX_QMGR_QUELOWSTAT_RESET_VALUE);
|
||||
|
||||
/* Reset underflow/overflow status registers 0..1 */
|
||||
ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUEUOSTAT0_OFFSET),
|
||||
IX_QMGR_QUEUOSTAT_RESET_VALUE);
|
||||
ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUEUOSTAT1_OFFSET),
|
||||
IX_QMGR_QUEUOSTAT_RESET_VALUE);
|
||||
|
||||
/* Reset queues 32..63 nearly empty status registers */
|
||||
ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUEUPPSTAT0_OFFSET),
|
||||
IX_QMGR_QUEUPPSTAT0_RESET_VALUE);
|
||||
|
||||
/* Reset queues 32..63 full status registers */
|
||||
ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUEUPPSTAT1_OFFSET),
|
||||
IX_QMGR_QUEUPPSTAT1_RESET_VALUE);
|
||||
|
||||
/* Reset int0 status flag source select registers 0..3 */
|
||||
ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_INT0SRCSELREG0_OFFSET),
|
||||
IX_QMGR_INT0SRCSELREG_RESET_VALUE);
|
||||
ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_INT0SRCSELREG1_OFFSET),
|
||||
IX_QMGR_INT0SRCSELREG_RESET_VALUE);
|
||||
ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_INT0SRCSELREG2_OFFSET),
|
||||
IX_QMGR_INT0SRCSELREG_RESET_VALUE);
|
||||
ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_INT0SRCSELREG3_OFFSET),
|
||||
IX_QMGR_INT0SRCSELREG_RESET_VALUE);
|
||||
|
||||
/* Reset queue interrupt enable register 0..1 */
|
||||
ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUEIEREG0_OFFSET),
|
||||
IX_QMGR_QUEIEREG_RESET_VALUE);
|
||||
ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUEIEREG1_OFFSET),
|
||||
IX_QMGR_QUEIEREG_RESET_VALUE);
|
||||
|
||||
/* Reset queue interrupt register 0..1 */
|
||||
ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QINTREG0_OFFSET),
|
||||
IX_QMGR_QINTREG_RESET_VALUE);
|
||||
ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QINTREG1_OFFSET),
|
||||
IX_QMGR_QINTREG_RESET_VALUE);
|
||||
|
||||
/* Reset queue configuration words 0..63 */
|
||||
qConfigWordAddress = (UINT32 *)(aqmBaseAddress + IX_QMGR_QUECONFIG_BASE_OFFSET);
|
||||
for (i = 0; i < (IX_QMGR_QUECONFIG_SIZE / sizeof(UINT32)); i++)
|
||||
{
|
||||
ixQMgrAqmIfWordWrite(qConfigWordAddress,
|
||||
IX_QMGR_QUECONFIG_RESET_VALUE);
|
||||
/* Next word */
|
||||
qConfigWordAddress++;
|
||||
}
|
||||
}
|
||||
|
1347
cpu/ixp/npe/IxQMgrDispatcher.c
Normal file
1347
cpu/ixp/npe/IxQMgrDispatcher.c
Normal file
File diff suppressed because it is too large
Load Diff
233
cpu/ixp/npe/IxQMgrInit.c
Normal file
233
cpu/ixp/npe/IxQMgrInit.c
Normal file
@ -0,0 +1,233 @@
|
||||
/**
|
||||
* @file IxQMgrInit.c
|
||||
*
|
||||
* @author Intel Corporation
|
||||
* @date 30-Oct-2001
|
||||
*
|
||||
* @brief: Provided initialization of the QMgr component and its subcomponents.
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
/*
|
||||
* System defined include files.
|
||||
*/
|
||||
|
||||
/*
|
||||
* User defined include files.
|
||||
*/
|
||||
#include "IxOsal.h"
|
||||
#include "IxQMgr.h"
|
||||
#include "IxQMgrQCfg_p.h"
|
||||
#include "IxQMgrDispatcher_p.h"
|
||||
#include "IxQMgrLog_p.h"
|
||||
#include "IxQMgrQAccess_p.h"
|
||||
#include "IxQMgrDefines_p.h"
|
||||
#include "IxQMgrAqmIf_p.h"
|
||||
|
||||
/*
|
||||
* Set to true if initialized
|
||||
* N.B. global so integration/unit tests can reinitialize
|
||||
*/
|
||||
BOOL qMgrIsInitialized = FALSE;
|
||||
|
||||
/*
|
||||
* Function definitions.
|
||||
*/
|
||||
IX_STATUS
|
||||
ixQMgrInit (void)
|
||||
{
|
||||
if (qMgrIsInitialized)
|
||||
{
|
||||
IX_QMGR_LOG0("ixQMgrInit: IxQMgr already initialised\n");
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* Initialise the QCfg component */
|
||||
ixQMgrQCfgInit ();
|
||||
|
||||
/* Initialise the Dispatcher component */
|
||||
ixQMgrDispatcherInit ();
|
||||
|
||||
/* Initialise the Access component */
|
||||
ixQMgrQAccessInit ();
|
||||
|
||||
/* Initialization complete */
|
||||
qMgrIsInitialized = TRUE;
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
IX_STATUS
|
||||
ixQMgrUnload (void)
|
||||
{
|
||||
if (!qMgrIsInitialized)
|
||||
{
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
/* Uninitialise the QCfg component */
|
||||
ixQMgrQCfgUninit ();
|
||||
|
||||
/* Uninitialization complete */
|
||||
qMgrIsInitialized = FALSE;
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
ixQMgrShow (void)
|
||||
{
|
||||
IxQMgrQCfgStats *qCfgStats = NULL;
|
||||
IxQMgrDispatcherStats *dispatcherStats = NULL;
|
||||
int i;
|
||||
UINT32 lowIntRegRead, upIntRegRead;
|
||||
|
||||
qCfgStats = ixQMgrQCfgStatsGet ();
|
||||
dispatcherStats = ixQMgrDispatcherStatsGet ();
|
||||
ixQMgrAqmIfQInterruptRegRead (IX_QMGR_QUELOW_GROUP, &lowIntRegRead);
|
||||
ixQMgrAqmIfQInterruptRegRead (IX_QMGR_QUEUPP_GROUP, &upIntRegRead);
|
||||
printf("Generic Stats........\n");
|
||||
printf("=====================\n");
|
||||
printf("Loop Run Count..........%u\n",dispatcherStats->loopRunCnt);
|
||||
printf("Watermark set count.....%d\n", qCfgStats->wmSetCnt);
|
||||
printf("===========================================\n");
|
||||
printf("On the fly Interrupt Register Stats........\n");
|
||||
printf("===========================================\n");
|
||||
printf("Lower Interrupt Register............0x%08x\n",lowIntRegRead);
|
||||
printf("Upper Interrupt Register............0x%08x\n",upIntRegRead);
|
||||
printf("==============================================\n");
|
||||
printf("Queue Specific Stats........\n");
|
||||
printf("============================\n");
|
||||
|
||||
for (i=0; i<IX_QMGR_MAX_NUM_QUEUES; i++)
|
||||
{
|
||||
if (ixQMgrQIsConfigured(i))
|
||||
{
|
||||
ixQMgrQShow(i);
|
||||
}
|
||||
}
|
||||
|
||||
printf("============================\n");
|
||||
}
|
||||
|
||||
IX_STATUS
|
||||
ixQMgrQShow (IxQMgrQId qId)
|
||||
{
|
||||
IxQMgrQCfgStats *qCfgStats = NULL;
|
||||
IxQMgrDispatcherStats *dispatcherStats = NULL;
|
||||
|
||||
if (!ixQMgrQIsConfigured(qId))
|
||||
{
|
||||
return IX_QMGR_Q_NOT_CONFIGURED;
|
||||
}
|
||||
|
||||
dispatcherStats = ixQMgrDispatcherStatsGet ();
|
||||
qCfgStats = ixQMgrQCfgQStatsGet (qId);
|
||||
|
||||
printf("QId %d\n", qId);
|
||||
printf("======\n");
|
||||
printf(" IxQMgrQCfg Stats\n");
|
||||
printf(" Name..................... \"%s\"\n", qCfgStats->qStats[qId].qName);
|
||||
printf(" Size in words............ %u\n", qCfgStats->qStats[qId].qSizeInWords);
|
||||
printf(" Entry size in words...... %u\n", qCfgStats->qStats[qId].qEntrySizeInWords);
|
||||
printf(" Nearly empty watermark... %u\n", qCfgStats->qStats[qId].ne);
|
||||
printf(" Nearly full watermark.... %u\n", qCfgStats->qStats[qId].nf);
|
||||
printf(" Number of full entries... %u\n", qCfgStats->qStats[qId].numEntries);
|
||||
printf(" Sram base address........ 0x%X\n", qCfgStats->qStats[qId].baseAddress);
|
||||
printf(" Read pointer............. 0x%X\n", qCfgStats->qStats[qId].readPtr);
|
||||
printf(" Write pointer............ 0x%X\n", qCfgStats->qStats[qId].writePtr);
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (dispatcherStats->queueStats[qId].notificationEnabled)
|
||||
{
|
||||
char *localEvent = "none ????";
|
||||
switch (dispatcherStats->queueStats[qId].srcSel)
|
||||
{
|
||||
case IX_QMGR_Q_SOURCE_ID_E:
|
||||
localEvent = "Empty";
|
||||
break;
|
||||
case IX_QMGR_Q_SOURCE_ID_NE:
|
||||
localEvent = "Nearly Empty";
|
||||
break;
|
||||
case IX_QMGR_Q_SOURCE_ID_NF:
|
||||
localEvent = "Nearly Full";
|
||||
break;
|
||||
case IX_QMGR_Q_SOURCE_ID_F:
|
||||
localEvent = "Full";
|
||||
break;
|
||||
case IX_QMGR_Q_SOURCE_ID_NOT_E:
|
||||
localEvent = "Not Empty";
|
||||
break;
|
||||
case IX_QMGR_Q_SOURCE_ID_NOT_NE:
|
||||
localEvent = "Not Nearly Empty";
|
||||
break;
|
||||
case IX_QMGR_Q_SOURCE_ID_NOT_NF:
|
||||
localEvent = "Not Nearly Full";
|
||||
break;
|
||||
case IX_QMGR_Q_SOURCE_ID_NOT_F:
|
||||
localEvent = "Not Full";
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
printf(" Notifications localEvent...... %s\n", localEvent);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" Notifications............ not enabled\n");
|
||||
}
|
||||
printf(" IxQMgrDispatcher Stats\n");
|
||||
printf(" Callback count................%d\n",
|
||||
dispatcherStats->queueStats[qId].callbackCnt);
|
||||
printf(" Priority change count.........%d\n",
|
||||
dispatcherStats->queueStats[qId].priorityChangeCnt);
|
||||
printf(" Interrupt no callback count...%d\n",
|
||||
dispatcherStats->queueStats[qId].intNoCallbackCnt);
|
||||
printf(" Interrupt lost callback count...%d\n",
|
||||
dispatcherStats->queueStats[qId].intLostCallbackCnt);
|
||||
#endif
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
796
cpu/ixp/npe/IxQMgrQAccess.c
Normal file
796
cpu/ixp/npe/IxQMgrQAccess.c
Normal file
@ -0,0 +1,796 @@
|
||||
/**
|
||||
* @file IxQMgrQAccess.c
|
||||
*
|
||||
* @author Intel Corporation
|
||||
* @date 30-Oct-2001
|
||||
*
|
||||
* @brief This file contains functions for putting entries on a queue and
|
||||
* removing entries from a queue.
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
/*
|
||||
* Inlines are compiled as function when this is defined.
|
||||
* N.B. Must be placed before #include of "IxQMgr.h"
|
||||
*/
|
||||
#ifndef IXQMGR_H
|
||||
# define IXQMGRQACCESS_C
|
||||
#else
|
||||
# error
|
||||
#endif
|
||||
|
||||
/*
|
||||
* System defined include files.
|
||||
*/
|
||||
|
||||
/*
|
||||
* User defined include files.
|
||||
*/
|
||||
#include "IxQMgr.h"
|
||||
#include "IxQMgrAqmIf_p.h"
|
||||
#include "IxQMgrQAccess_p.h"
|
||||
#include "IxQMgrQCfg_p.h"
|
||||
#include "IxQMgrDefines_p.h"
|
||||
|
||||
/*
|
||||
* Global variables and extern definitions
|
||||
*/
|
||||
extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
|
||||
|
||||
/*
|
||||
* Function definitions.
|
||||
*/
|
||||
void
|
||||
ixQMgrQAccessInit (void)
|
||||
{
|
||||
}
|
||||
|
||||
IX_STATUS
|
||||
ixQMgrQReadWithChecks (IxQMgrQId qId,
|
||||
UINT32 *entry)
|
||||
{
|
||||
IxQMgrQEntrySizeInWords entrySizeInWords;
|
||||
IxQMgrQInlinedReadWriteInfo *infoPtr;
|
||||
|
||||
if (NULL == entry)
|
||||
{
|
||||
return IX_QMGR_PARAMETER_ERROR;
|
||||
}
|
||||
|
||||
/* Check QId */
|
||||
if (!ixQMgrQIsConfigured(qId))
|
||||
{
|
||||
return IX_QMGR_Q_NOT_CONFIGURED;
|
||||
}
|
||||
|
||||
/* Get the q entry size in words */
|
||||
entrySizeInWords = ixQMgrQEntrySizeInWordsGet (qId);
|
||||
|
||||
ixQMgrAqmIfQPop (qId, entrySizeInWords, entry);
|
||||
|
||||
/* reset the current read count if the counter wrapped around
|
||||
* (unsigned arithmetic)
|
||||
*/
|
||||
infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
|
||||
if (infoPtr->qReadCount-- > infoPtr->qSizeInEntries)
|
||||
{
|
||||
infoPtr->qReadCount = 0;
|
||||
}
|
||||
|
||||
/* Check if underflow occurred on the read */
|
||||
if (ixQMgrAqmIfUnderflowCheck (qId))
|
||||
{
|
||||
return IX_QMGR_Q_UNDERFLOW;
|
||||
}
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
/* this function reads the remaining of the q entry
|
||||
* for queues configured with many words.
|
||||
* (the first word of the entry is already read
|
||||
* in the inlined function and the entry pointer already
|
||||
* incremented
|
||||
*/
|
||||
IX_STATUS
|
||||
ixQMgrQReadMWordsMinus1 (IxQMgrQId qId,
|
||||
UINT32 *entry)
|
||||
{
|
||||
IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
|
||||
UINT32 entrySize = infoPtr->qEntrySizeInWords;
|
||||
volatile UINT32 *qAccRegAddr = infoPtr->qAccRegAddr;
|
||||
|
||||
while (--entrySize)
|
||||
{
|
||||
/* read the entry and accumulate the result */
|
||||
*(++entry) = IX_OSAL_READ_LONG(++qAccRegAddr);
|
||||
}
|
||||
/* underflow is available for lower queues only */
|
||||
if (qId < IX_QMGR_MIN_QUEUPP_QID)
|
||||
{
|
||||
/* get the queue status */
|
||||
UINT32 status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
|
||||
|
||||
/* check the underflow status */
|
||||
if (status & infoPtr->qUflowStatBitMask)
|
||||
{
|
||||
/* the queue is empty
|
||||
* clear the underflow status bit if it was set
|
||||
*/
|
||||
IX_OSAL_WRITE_LONG(infoPtr->qUOStatRegAddr,
|
||||
status & ~infoPtr->qUflowStatBitMask);
|
||||
return IX_QMGR_Q_UNDERFLOW;
|
||||
}
|
||||
}
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
IX_STATUS
|
||||
ixQMgrQWriteWithChecks (IxQMgrQId qId,
|
||||
UINT32 *entry)
|
||||
{
|
||||
IxQMgrQEntrySizeInWords entrySizeInWords;
|
||||
IxQMgrQInlinedReadWriteInfo *infoPtr;
|
||||
|
||||
if (NULL == entry)
|
||||
{
|
||||
return IX_QMGR_PARAMETER_ERROR;
|
||||
}
|
||||
|
||||
/* Check QId */
|
||||
if (!ixQMgrQIsConfigured(qId))
|
||||
{
|
||||
return IX_QMGR_Q_NOT_CONFIGURED;
|
||||
}
|
||||
|
||||
/* Get the q entry size in words */
|
||||
entrySizeInWords = ixQMgrQEntrySizeInWordsGet (qId);
|
||||
|
||||
ixQMgrAqmIfQPush (qId, entrySizeInWords, entry);
|
||||
|
||||
/* reset the current read count if the counter wrapped around
|
||||
* (unsigned arithmetic)
|
||||
*/
|
||||
infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
|
||||
if (infoPtr->qWriteCount++ >= infoPtr->qSizeInEntries)
|
||||
{
|
||||
infoPtr->qWriteCount = infoPtr->qSizeInEntries;
|
||||
}
|
||||
|
||||
/* Check if overflow occurred on the write*/
|
||||
if (ixQMgrAqmIfOverflowCheck (qId))
|
||||
{
|
||||
return IX_QMGR_Q_OVERFLOW;
|
||||
}
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
IX_STATUS
|
||||
ixQMgrQPeek (IxQMgrQId qId,
|
||||
unsigned int entryIndex,
|
||||
UINT32 *entry)
|
||||
{
|
||||
unsigned int numEntries;
|
||||
|
||||
#ifndef NDEBUG
|
||||
if ((NULL == entry) || (entryIndex >= IX_QMGR_Q_SIZE_INVALID))
|
||||
{
|
||||
return IX_QMGR_PARAMETER_ERROR;
|
||||
}
|
||||
|
||||
if (!ixQMgrQIsConfigured(qId))
|
||||
{
|
||||
return IX_QMGR_Q_NOT_CONFIGURED;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (IX_SUCCESS != ixQMgrQNumEntriesGet (qId, &numEntries))
|
||||
{
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
if (entryIndex >= numEntries) /* entryIndex starts at 0 */
|
||||
{
|
||||
return IX_QMGR_ENTRY_INDEX_OUT_OF_BOUNDS;
|
||||
}
|
||||
|
||||
return ixQMgrAqmIfQPeek (qId, entryIndex, entry);
|
||||
}
|
||||
|
||||
IX_STATUS
|
||||
ixQMgrQPoke (IxQMgrQId qId,
|
||||
unsigned entryIndex,
|
||||
UINT32 *entry)
|
||||
{
|
||||
unsigned int numEntries;
|
||||
|
||||
#ifndef NDEBUG
|
||||
if ((NULL == entry) || (entryIndex > 128))
|
||||
{
|
||||
return IX_QMGR_PARAMETER_ERROR;
|
||||
}
|
||||
|
||||
if (!ixQMgrQIsConfigured(qId))
|
||||
{
|
||||
return IX_QMGR_Q_NOT_CONFIGURED;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (IX_SUCCESS != ixQMgrQNumEntriesGet (qId, &numEntries))
|
||||
{
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
if (numEntries < (entryIndex + 1)) /* entryIndex starts at 0 */
|
||||
{
|
||||
return IX_QMGR_ENTRY_INDEX_OUT_OF_BOUNDS;
|
||||
}
|
||||
|
||||
return ixQMgrAqmIfQPoke (qId, entryIndex, entry);
|
||||
}
|
||||
|
||||
IX_STATUS
|
||||
ixQMgrQStatusGetWithChecks (IxQMgrQId qId,
|
||||
IxQMgrQStatus *qStatus)
|
||||
{
|
||||
if (NULL == qStatus)
|
||||
{
|
||||
return IX_QMGR_PARAMETER_ERROR;
|
||||
}
|
||||
|
||||
if (!ixQMgrQIsConfigured (qId))
|
||||
{
|
||||
return IX_QMGR_Q_NOT_CONFIGURED;
|
||||
}
|
||||
|
||||
ixQMgrAqmIfQueStatRead (qId, qStatus);
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
IX_STATUS
|
||||
ixQMgrQNumEntriesGet (IxQMgrQId qId,
|
||||
unsigned *numEntriesPtr)
|
||||
{
|
||||
UINT32 qPtrs;
|
||||
UINT32 qStatus;
|
||||
unsigned numEntries;
|
||||
IxQMgrQInlinedReadWriteInfo *infoPtr;
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (NULL == numEntriesPtr)
|
||||
{
|
||||
return IX_QMGR_PARAMETER_ERROR;
|
||||
}
|
||||
|
||||
/* Check QId */
|
||||
if (!ixQMgrQIsConfigured(qId))
|
||||
{
|
||||
return IX_QMGR_Q_NOT_CONFIGURED;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* get fast access data */
|
||||
infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
|
||||
|
||||
/* get snapshot */
|
||||
qPtrs = IX_OSAL_READ_LONG(infoPtr->qConfigRegAddr);
|
||||
|
||||
/* Mod subtraction of pointers to get number of words in Q. */
|
||||
numEntries = (qPtrs - (qPtrs >> 7)) & 0x7f;
|
||||
|
||||
if (numEntries == 0)
|
||||
{
|
||||
/*
|
||||
* Could mean either full or empty queue
|
||||
* so look at status
|
||||
*/
|
||||
ixQMgrAqmIfQueStatRead (qId, &qStatus);
|
||||
|
||||
if (qId < IX_QMGR_MIN_QUEUPP_QID)
|
||||
{
|
||||
if (qStatus & IX_QMGR_Q_STATUS_E_BIT_MASK)
|
||||
{
|
||||
/* Empty */
|
||||
*numEntriesPtr = 0;
|
||||
}
|
||||
else if (qStatus & IX_QMGR_Q_STATUS_F_BIT_MASK)
|
||||
{
|
||||
/* Full */
|
||||
*numEntriesPtr = infoPtr->qSizeInEntries;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Queue status and read/write pointers are volatile.
|
||||
* The queue state has changed since we took the
|
||||
* snapshot of the read and write pointers.
|
||||
* Client can retry if they wish
|
||||
*/
|
||||
*numEntriesPtr = 0;
|
||||
return IX_QMGR_WARNING;
|
||||
}
|
||||
}
|
||||
else /* It is an upper queue which does not have an empty status bit maintained */
|
||||
{
|
||||
if (qStatus & IX_QMGR_Q_STATUS_F_BIT_MASK)
|
||||
{
|
||||
/* The queue is Full at the time of snapshot. */
|
||||
*numEntriesPtr = infoPtr->qSizeInEntries;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The queue is either empty, either moving,
|
||||
* Client can retry if they wish
|
||||
*/
|
||||
*numEntriesPtr = 0;
|
||||
return IX_QMGR_WARNING;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*numEntriesPtr = (numEntries / infoPtr->qEntrySizeInWords) & (infoPtr->qSizeInEntries - 1);
|
||||
}
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
#if defined(__wince) && defined(NO_INLINE_APIS)
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixQMgrQRead (IxQMgrQId qId,
|
||||
UINT32 *entryPtr)
|
||||
{
|
||||
extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
|
||||
IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
|
||||
UINT32 entry, entrySize;
|
||||
|
||||
/* get a new entry */
|
||||
entrySize = infoPtr->qEntrySizeInWords;
|
||||
entry = IX_OSAL_READ_LONG(infoPtr->qAccRegAddr);
|
||||
|
||||
if (entrySize != IX_QMGR_Q_ENTRY_SIZE1)
|
||||
{
|
||||
*entryPtr = entry;
|
||||
/* process the remaining part of the entry */
|
||||
return ixQMgrQReadMWordsMinus1(qId, entryPtr);
|
||||
}
|
||||
|
||||
/* underflow is available for lower queues only */
|
||||
if (qId < IX_QMGR_MIN_QUEUPP_QID)
|
||||
{
|
||||
/* the counter of queue entries is decremented. In happy
|
||||
* day scenario there are many entries in the queue
|
||||
* and the counter does not reach zero.
|
||||
*/
|
||||
if (infoPtr->qReadCount-- == 0)
|
||||
{
|
||||
/* There is maybe no entry in the queue
|
||||
* qReadCount is now negative, but will be corrected before
|
||||
* the function returns.
|
||||
*/
|
||||
UINT32 qPtrs; /* queue internal pointers */
|
||||
|
||||
/* when a queue is empty, the hw guarantees to return
|
||||
* a null value. If the value is not null, the queue is
|
||||
* not empty.
|
||||
*/
|
||||
if (entry == 0)
|
||||
{
|
||||
/* get the queue status */
|
||||
UINT32 status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
|
||||
|
||||
/* check the underflow status */
|
||||
if (status & infoPtr->qUflowStatBitMask)
|
||||
{
|
||||
/* the queue is empty
|
||||
* clear the underflow status bit if it was set
|
||||
*/
|
||||
IX_OSAL_WRITE_LONG(infoPtr->qUOStatRegAddr,
|
||||
status & ~infoPtr->qUflowStatBitMask);
|
||||
*entryPtr = 0;
|
||||
infoPtr->qReadCount = 0;
|
||||
return IX_QMGR_Q_UNDERFLOW;
|
||||
}
|
||||
}
|
||||
/* store the result */
|
||||
*entryPtr = entry;
|
||||
|
||||
/* No underflow occured : someone is filling the queue
|
||||
* or the queue contains null entries.
|
||||
* The current counter needs to be
|
||||
* updated from the current number of entries in the queue
|
||||
*/
|
||||
|
||||
/* get snapshot of queue pointers */
|
||||
qPtrs = IX_OSAL_READ_LONG(infoPtr->qConfigRegAddr);
|
||||
|
||||
/* Mod subtraction of pointers to get number of words in Q. */
|
||||
qPtrs = (qPtrs - (qPtrs >> 7)) & 0x7f;
|
||||
|
||||
if (qPtrs == 0)
|
||||
{
|
||||
/* no entry in the queue */
|
||||
infoPtr->qReadCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* convert the number of words inside the queue
|
||||
* to a number of entries
|
||||
*/
|
||||
infoPtr->qReadCount = qPtrs & (infoPtr->qSizeInEntries - 1);
|
||||
}
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
}
|
||||
*entryPtr = entry;
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixQMgrQBurstRead (IxQMgrQId qId,
|
||||
UINT32 numEntries,
|
||||
UINT32 *entries)
|
||||
{
|
||||
extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
|
||||
IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
|
||||
UINT32 nullCheckEntry;
|
||||
|
||||
if (infoPtr->qEntrySizeInWords == IX_QMGR_Q_ENTRY_SIZE1)
|
||||
{
|
||||
volatile UINT32 *qAccRegAddr = infoPtr->qAccRegAddr;
|
||||
|
||||
/* the code is optimized to take care of data dependencies:
|
||||
* Durig a read, there are a few cycles needed to get the
|
||||
* read complete. During these cycles, it is poossible to
|
||||
* do some CPU, e.g. increment pointers and decrement
|
||||
* counters.
|
||||
*/
|
||||
|
||||
/* fetch a queue entry */
|
||||
nullCheckEntry = IX_OSAL_READ_LONG(infoPtr->qAccRegAddr);
|
||||
|
||||
/* iterate the specified number of queue entries */
|
||||
while (--numEntries)
|
||||
{
|
||||
/* check the result of the previous read */
|
||||
if (nullCheckEntry == 0)
|
||||
{
|
||||
/* if we read a NULL entry, stop. We have underflowed */
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* write the entry */
|
||||
*entries = nullCheckEntry;
|
||||
/* fetch next entry */
|
||||
nullCheckEntry = IX_OSAL_READ_LONG(qAccRegAddr);
|
||||
/* increment the write address */
|
||||
entries++;
|
||||
}
|
||||
}
|
||||
/* write the pre-fetched entry */
|
||||
*entries = nullCheckEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
IxQMgrQEntrySizeInWords entrySizeInWords = infoPtr->qEntrySizeInWords;
|
||||
/* read the specified number of queue entries */
|
||||
nullCheckEntry = 0;
|
||||
while (numEntries--)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < entrySizeInWords; i++)
|
||||
{
|
||||
*entries = IX_OSAL_READ_LONG(infoPtr->qAccRegAddr + i);
|
||||
nullCheckEntry |= *entries++;
|
||||
}
|
||||
|
||||
/* if we read a NULL entry, stop. We have underflowed */
|
||||
if (nullCheckEntry == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
nullCheckEntry = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* reset the current read count : next access to the read function
|
||||
* will force a underflow status check
|
||||
*/
|
||||
infoPtr->qWriteCount = 0;
|
||||
|
||||
/* Check if underflow occurred on the read */
|
||||
if (nullCheckEntry == 0 && qId < IX_QMGR_MIN_QUEUPP_QID)
|
||||
{
|
||||
/* get the queue status */
|
||||
UINT32 status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
|
||||
|
||||
if (status & infoPtr->qUflowStatBitMask)
|
||||
{
|
||||
/* clear the underflow status bit if it was set */
|
||||
IX_OSAL_WRITE_LONG(infoPtr->qUOStatRegAddr,
|
||||
status & ~infoPtr->qUflowStatBitMask);
|
||||
return IX_QMGR_Q_UNDERFLOW;
|
||||
}
|
||||
}
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixQMgrQWrite (IxQMgrQId qId,
|
||||
UINT32 *entry)
|
||||
{
|
||||
extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
|
||||
IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
|
||||
UINT32 entrySize;
|
||||
|
||||
/* write the entry */
|
||||
IX_OSAL_WRITE_LONG(infoPtr->qAccRegAddr, *entry);
|
||||
entrySize = infoPtr->qEntrySizeInWords;
|
||||
|
||||
if (entrySize != IX_QMGR_Q_ENTRY_SIZE1)
|
||||
{
|
||||
/* process the remaining part of the entry */
|
||||
volatile UINT32 *qAccRegAddr = infoPtr->qAccRegAddr;
|
||||
while (--entrySize)
|
||||
{
|
||||
++entry;
|
||||
IX_OSAL_WRITE_LONG(++qAccRegAddr, *entry);
|
||||
}
|
||||
entrySize = infoPtr->qEntrySizeInWords;
|
||||
}
|
||||
|
||||
/* overflow is available for lower queues only */
|
||||
if (qId < IX_QMGR_MIN_QUEUPP_QID)
|
||||
{
|
||||
UINT32 qSize = infoPtr->qSizeInEntries;
|
||||
/* increment the current number of entries in the queue
|
||||
* and check for overflow
|
||||
*/
|
||||
if (infoPtr->qWriteCount++ == qSize)
|
||||
{
|
||||
/* the queue may have overflow */
|
||||
UINT32 qPtrs; /* queue internal pointers */
|
||||
|
||||
/* get the queue status */
|
||||
UINT32 status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
|
||||
|
||||
/* read the status twice because the status may
|
||||
* not be immediately ready after the write operation
|
||||
*/
|
||||
if ((status & infoPtr->qOflowStatBitMask) ||
|
||||
((status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr))
|
||||
& infoPtr->qOflowStatBitMask))
|
||||
{
|
||||
/* the queue is full, clear the overflow status
|
||||
* bit if it was set
|
||||
*/
|
||||
IX_OSAL_WRITE_LONG(infoPtr->qUOStatRegAddr,
|
||||
status & ~infoPtr->qOflowStatBitMask);
|
||||
infoPtr->qWriteCount = infoPtr->qSizeInEntries;
|
||||
return IX_QMGR_Q_OVERFLOW;
|
||||
}
|
||||
/* No overflow occured : someone is draining the queue
|
||||
* and the current counter needs to be
|
||||
* updated from the current number of entries in the queue
|
||||
*/
|
||||
|
||||
/* get q pointer snapshot */
|
||||
qPtrs = IX_OSAL_READ_LONG(infoPtr->qConfigRegAddr);
|
||||
|
||||
/* Mod subtraction of pointers to get number of words in Q. */
|
||||
qPtrs = (qPtrs - (qPtrs >> 7)) & 0x7f;
|
||||
|
||||
if (qPtrs == 0)
|
||||
{
|
||||
/* the queue may be full at the time of the
|
||||
* snapshot. Next access will check
|
||||
* the overflow status again.
|
||||
*/
|
||||
infoPtr->qWriteCount = qSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* convert the number of words to a number of entries */
|
||||
if (entrySize == IX_QMGR_Q_ENTRY_SIZE1)
|
||||
{
|
||||
infoPtr->qWriteCount = qPtrs & (qSize - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
infoPtr->qWriteCount = (qPtrs / entrySize) & (qSize - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixQMgrQBurstWrite (IxQMgrQId qId,
|
||||
unsigned numEntries,
|
||||
UINT32 *entries)
|
||||
{
|
||||
extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
|
||||
IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
|
||||
UINT32 status;
|
||||
|
||||
/* update the current write count */
|
||||
infoPtr->qWriteCount += numEntries;
|
||||
|
||||
if (infoPtr->qEntrySizeInWords == IX_QMGR_Q_ENTRY_SIZE1)
|
||||
{
|
||||
volatile UINT32 *qAccRegAddr = infoPtr->qAccRegAddr;
|
||||
while (numEntries--)
|
||||
{
|
||||
IX_OSAL_WRITE_LONG(qAccRegAddr, *entries);
|
||||
entries++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IxQMgrQEntrySizeInWords entrySizeInWords = infoPtr->qEntrySizeInWords;
|
||||
int i;
|
||||
|
||||
/* write each queue entry */
|
||||
while (numEntries--)
|
||||
{
|
||||
/* write the queueEntrySize number of words for each entry */
|
||||
for (i = 0; i < entrySizeInWords; i++)
|
||||
{
|
||||
IX_OSAL_WRITE_LONG((infoPtr->qAccRegAddr + i), *entries);
|
||||
entries++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check if the write count overflows */
|
||||
if (infoPtr->qWriteCount > infoPtr->qSizeInEntries)
|
||||
{
|
||||
/* reset the current write count */
|
||||
infoPtr->qWriteCount = infoPtr->qSizeInEntries;
|
||||
}
|
||||
|
||||
/* Check if overflow occurred on the write operation */
|
||||
if (qId < IX_QMGR_MIN_QUEUPP_QID)
|
||||
{
|
||||
/* get the queue status */
|
||||
status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr);
|
||||
|
||||
/* read the status twice because the status may
|
||||
* not be ready at the time of the write
|
||||
*/
|
||||
if ((status & infoPtr->qOflowStatBitMask) ||
|
||||
((status = IX_OSAL_READ_LONG(infoPtr->qUOStatRegAddr))
|
||||
& infoPtr->qOflowStatBitMask))
|
||||
{
|
||||
/* clear the underflow status bit if it was set */
|
||||
IX_OSAL_WRITE_LONG(infoPtr->qUOStatRegAddr,
|
||||
status & ~infoPtr->qOflowStatBitMask);
|
||||
return IX_QMGR_Q_OVERFLOW;
|
||||
}
|
||||
}
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
PUBLIC IX_STATUS
|
||||
ixQMgrQStatusGet (IxQMgrQId qId,
|
||||
IxQMgrQStatus *qStatus)
|
||||
{
|
||||
/* read the status of a queue in the range 0-31 */
|
||||
if (qId < IX_QMGR_MIN_QUEUPP_QID)
|
||||
{
|
||||
extern UINT32 ixQMgrAqmIfQueLowStatRegAddr[];
|
||||
extern UINT32 ixQMgrAqmIfQueLowStatBitsOffset[];
|
||||
extern UINT32 ixQMgrAqmIfQueLowStatBitsMask;
|
||||
extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
|
||||
IxQMgrQInlinedReadWriteInfo *infoPtr = &ixQMgrQInlinedReadWriteInfo[qId];
|
||||
volatile UINT32 *lowStatRegAddr = (UINT32*)ixQMgrAqmIfQueLowStatRegAddr[qId];
|
||||
volatile UINT32 *qUOStatRegAddr = infoPtr->qUOStatRegAddr;
|
||||
|
||||
UINT32 lowStatBitsOffset = ixQMgrAqmIfQueLowStatBitsOffset[qId];
|
||||
UINT32 lowStatBitsMask = ixQMgrAqmIfQueLowStatBitsMask;
|
||||
UINT32 underflowBitMask = infoPtr->qUflowStatBitMask;
|
||||
UINT32 overflowBitMask = infoPtr->qOflowStatBitMask;
|
||||
|
||||
/* read the status register for this queue */
|
||||
*qStatus = IX_OSAL_READ_LONG(lowStatRegAddr);
|
||||
/* mask out the status bits relevant only to this queue */
|
||||
*qStatus = (*qStatus >> lowStatBitsOffset) & lowStatBitsMask;
|
||||
|
||||
/* Check if the queue has overflowed */
|
||||
if (IX_OSAL_READ_LONG(qUOStatRegAddr) & overflowBitMask)
|
||||
{
|
||||
/* clear the overflow status bit if it was set */
|
||||
IX_OSAL_WRITE_LONG(qUOStatRegAddr,
|
||||
(IX_OSAL_READ_LONG(qUOStatRegAddr) &
|
||||
~overflowBitMask));
|
||||
*qStatus |= IX_QMGR_Q_STATUS_OF_BIT_MASK;
|
||||
}
|
||||
|
||||
/* Check if the queue has underflowed */
|
||||
if (IX_OSAL_READ_LONG(qUOStatRegAddr) & underflowBitMask)
|
||||
{
|
||||
/* clear the underflow status bit if it was set */
|
||||
IX_OSAL_WRITE_LONG(qUOStatRegAddr,
|
||||
(IX_OSAL_READ_LONG(qUOStatRegAddr) &
|
||||
~underflowBitMask));
|
||||
*qStatus |= IX_QMGR_Q_STATUS_UF_BIT_MASK;
|
||||
}
|
||||
}
|
||||
else /* read status of a queue in the range 32-63 */
|
||||
{
|
||||
extern UINT32 ixQMgrAqmIfQueUppStat0RegAddr;
|
||||
extern UINT32 ixQMgrAqmIfQueUppStat1RegAddr;
|
||||
extern UINT32 ixQMgrAqmIfQueUppStat0BitMask[];
|
||||
extern UINT32 ixQMgrAqmIfQueUppStat1BitMask[];
|
||||
|
||||
volatile UINT32 *qNearEmptyStatRegAddr = (UINT32*)ixQMgrAqmIfQueUppStat0RegAddr;
|
||||
volatile UINT32 *qFullStatRegAddr = (UINT32*)ixQMgrAqmIfQueUppStat1RegAddr;
|
||||
int maskIndex = qId - IX_QMGR_MIN_QUEUPP_QID;
|
||||
UINT32 qNearEmptyStatBitMask = ixQMgrAqmIfQueUppStat0BitMask[maskIndex];
|
||||
UINT32 qFullStatBitMask = ixQMgrAqmIfQueUppStat1BitMask[maskIndex];
|
||||
|
||||
/* Reset the status bits */
|
||||
*qStatus = 0;
|
||||
|
||||
/* Check if the queue is nearly empty */
|
||||
if (IX_OSAL_READ_LONG(qNearEmptyStatRegAddr) & qNearEmptyStatBitMask)
|
||||
{
|
||||
*qStatus |= IX_QMGR_Q_STATUS_NE_BIT_MASK;
|
||||
}
|
||||
|
||||
/* Check if the queue is full */
|
||||
if (IX_OSAL_READ_LONG(qFullStatRegAddr) & qFullStatBitMask)
|
||||
{
|
||||
*qStatus |= IX_QMGR_Q_STATUS_F_BIT_MASK;
|
||||
}
|
||||
}
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
#endif /* def NO_INLINE_APIS */
|
543
cpu/ixp/npe/IxQMgrQCfg.c
Normal file
543
cpu/ixp/npe/IxQMgrQCfg.c
Normal file
@ -0,0 +1,543 @@
|
||||
/**
|
||||
* @file QMgrQCfg.c
|
||||
*
|
||||
* @author Intel Corporation
|
||||
* @date 30-Oct-2001
|
||||
*
|
||||
* @brief This modules provides an interface for setting up the static
|
||||
* configuration of AQM queues.This file contains the following
|
||||
* functions:
|
||||
*
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
/*
|
||||
* System defined include files.
|
||||
*/
|
||||
|
||||
/*
|
||||
* User defined include files.
|
||||
*/
|
||||
#include "IxOsal.h"
|
||||
#include "IxQMgr.h"
|
||||
#include "IxQMgrAqmIf_p.h"
|
||||
#include "IxQMgrQCfg_p.h"
|
||||
#include "IxQMgrDefines_p.h"
|
||||
|
||||
/*
|
||||
* #defines and macros used in this file.
|
||||
*/
|
||||
|
||||
#define IX_QMGR_MIN_ENTRY_SIZE_IN_WORDS 16
|
||||
|
||||
/* Total size of SRAM */
|
||||
#define IX_QMGR_AQM_SRAM_SIZE_IN_BYTES 0x4000
|
||||
|
||||
/*
|
||||
* Check that qId is a valid queue identifier. This is provided to
|
||||
* make the code easier to read.
|
||||
*/
|
||||
#define IX_QMGR_QID_IS_VALID(qId) \
|
||||
(((qId) >= (IX_QMGR_MIN_QID)) && ((qId) <= (IX_QMGR_MAX_QID)))
|
||||
|
||||
/*
|
||||
* Typedefs whose scope is limited to this file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This struct describes an AQM queue.
|
||||
* N.b. bufferSizeInWords and qEntrySizeInWords are stored in the queue
|
||||
* as these are requested by Access in the data path. sizeInEntries is
|
||||
* not required by the data path so it can be calculated dynamically.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
char qName[IX_QMGR_MAX_QNAME_LEN+1]; /* Textual description of a queue*/
|
||||
IxQMgrQSizeInWords qSizeInWords; /* The number of words in the queue */
|
||||
IxQMgrQEntrySizeInWords qEntrySizeInWords; /* Number of words per queue entry*/
|
||||
BOOL isConfigured; /* This flag is TRUE if the queue has
|
||||
* been configured
|
||||
*/
|
||||
} IxQMgrCfgQ;
|
||||
|
||||
/*
|
||||
* Variable declarations global to this file. Externs are followed by
|
||||
* statics.
|
||||
*/
|
||||
|
||||
extern UINT32 * ixQMgrAqmIfQueAccRegAddr[];
|
||||
|
||||
/* Store data required to inline read and write access
|
||||
*/
|
||||
IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[IX_QMGR_MAX_NUM_QUEUES];
|
||||
|
||||
static IxQMgrCfgQ cfgQueueInfo[IX_QMGR_MAX_NUM_QUEUES];
|
||||
|
||||
/* This pointer holds the starting address of AQM SRAM not used by
|
||||
* the AQM queues.
|
||||
*/
|
||||
static UINT32 freeSramAddress=0;
|
||||
|
||||
/* 4 words of zeroed memory for inline access */
|
||||
static UINT32 zeroedPlaceHolder[4] = { 0, 0, 0, 0 };
|
||||
|
||||
static BOOL cfgInitialized = FALSE;
|
||||
|
||||
static IxOsalMutex ixQMgrQCfgMutex;
|
||||
|
||||
/*
|
||||
* Statistics
|
||||
*/
|
||||
static IxQMgrQCfgStats stats;
|
||||
|
||||
/*
|
||||
* Function declarations
|
||||
*/
|
||||
PRIVATE BOOL
|
||||
watermarkLevelIsOk (IxQMgrQId qId, IxQMgrWMLevel level);
|
||||
|
||||
PRIVATE BOOL
|
||||
qSizeInWordsIsOk (IxQMgrQSizeInWords qSize);
|
||||
|
||||
PRIVATE BOOL
|
||||
qEntrySizeInWordsIsOk (IxQMgrQEntrySizeInWords entrySize);
|
||||
|
||||
/*
|
||||
* Function definitions.
|
||||
*/
|
||||
void
|
||||
ixQMgrQCfgInit (void)
|
||||
{
|
||||
int loopIndex;
|
||||
|
||||
for (loopIndex=0; loopIndex < IX_QMGR_MAX_NUM_QUEUES;loopIndex++)
|
||||
{
|
||||
/* info for code inlining */
|
||||
ixQMgrAqmIfQueAccRegAddr[loopIndex] = zeroedPlaceHolder;
|
||||
|
||||
/* info for code inlining */
|
||||
ixQMgrQInlinedReadWriteInfo[loopIndex].qReadCount = 0;
|
||||
ixQMgrQInlinedReadWriteInfo[loopIndex].qWriteCount = 0;
|
||||
ixQMgrQInlinedReadWriteInfo[loopIndex].qAccRegAddr = zeroedPlaceHolder;
|
||||
ixQMgrQInlinedReadWriteInfo[loopIndex].qUOStatRegAddr = zeroedPlaceHolder;
|
||||
ixQMgrQInlinedReadWriteInfo[loopIndex].qUflowStatBitMask = 0;
|
||||
ixQMgrQInlinedReadWriteInfo[loopIndex].qOflowStatBitMask = 0;
|
||||
ixQMgrQInlinedReadWriteInfo[loopIndex].qEntrySizeInWords = 0;
|
||||
ixQMgrQInlinedReadWriteInfo[loopIndex].qSizeInEntries = 0;
|
||||
ixQMgrQInlinedReadWriteInfo[loopIndex].qConfigRegAddr = zeroedPlaceHolder;
|
||||
}
|
||||
|
||||
/* Initialise the AqmIf component */
|
||||
ixQMgrAqmIfInit ();
|
||||
|
||||
/* Reset all queues to have queue name = NULL, entry size = 0 and
|
||||
* isConfigured = false
|
||||
*/
|
||||
for (loopIndex=0; loopIndex < IX_QMGR_MAX_NUM_QUEUES;loopIndex++)
|
||||
{
|
||||
strcpy (cfgQueueInfo[loopIndex].qName, "");
|
||||
cfgQueueInfo[loopIndex].qSizeInWords = 0;
|
||||
cfgQueueInfo[loopIndex].qEntrySizeInWords = 0;
|
||||
cfgQueueInfo[loopIndex].isConfigured = FALSE;
|
||||
|
||||
/* Statistics */
|
||||
stats.qStats[loopIndex].isConfigured = FALSE;
|
||||
stats.qStats[loopIndex].qName = cfgQueueInfo[loopIndex].qName;
|
||||
}
|
||||
|
||||
/* Statistics */
|
||||
stats.wmSetCnt = 0;
|
||||
|
||||
ixQMgrAqmIfSramBaseAddressGet (&freeSramAddress);
|
||||
|
||||
ixOsalMutexInit(&ixQMgrQCfgMutex);
|
||||
|
||||
cfgInitialized = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
ixQMgrQCfgUninit (void)
|
||||
{
|
||||
cfgInitialized = FALSE;
|
||||
|
||||
/* Uninitialise the AqmIf component */
|
||||
ixQMgrAqmIfUninit ();
|
||||
}
|
||||
|
||||
IX_STATUS
|
||||
ixQMgrQConfig (char *qName,
|
||||
IxQMgrQId qId,
|
||||
IxQMgrQSizeInWords qSizeInWords,
|
||||
IxQMgrQEntrySizeInWords qEntrySizeInWords)
|
||||
{
|
||||
UINT32 aqmLocalBaseAddress;
|
||||
|
||||
if (!cfgInitialized)
|
||||
{
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
if (!IX_QMGR_QID_IS_VALID(qId))
|
||||
{
|
||||
return IX_QMGR_INVALID_Q_ID;
|
||||
}
|
||||
|
||||
else if (NULL == qName)
|
||||
{
|
||||
return IX_QMGR_PARAMETER_ERROR;
|
||||
}
|
||||
|
||||
else if (strlen (qName) > IX_QMGR_MAX_QNAME_LEN)
|
||||
{
|
||||
return IX_QMGR_PARAMETER_ERROR;
|
||||
}
|
||||
|
||||
else if (!qSizeInWordsIsOk (qSizeInWords))
|
||||
{
|
||||
return IX_QMGR_INVALID_QSIZE;
|
||||
}
|
||||
|
||||
else if (!qEntrySizeInWordsIsOk (qEntrySizeInWords))
|
||||
{
|
||||
return IX_QMGR_INVALID_Q_ENTRY_SIZE;
|
||||
}
|
||||
|
||||
else if (cfgQueueInfo[qId].isConfigured)
|
||||
{
|
||||
return IX_QMGR_Q_ALREADY_CONFIGURED;
|
||||
}
|
||||
|
||||
ixOsalMutexLock(&ixQMgrQCfgMutex, IX_OSAL_WAIT_FOREVER);
|
||||
|
||||
/* Write the config register */
|
||||
ixQMgrAqmIfQueCfgWrite (qId,
|
||||
qSizeInWords,
|
||||
qEntrySizeInWords,
|
||||
freeSramAddress);
|
||||
|
||||
|
||||
strcpy (cfgQueueInfo[qId].qName, qName);
|
||||
cfgQueueInfo[qId].qSizeInWords = qSizeInWords;
|
||||
cfgQueueInfo[qId].qEntrySizeInWords = qEntrySizeInWords;
|
||||
|
||||
/* store pre-computed information in the same cache line
|
||||
* to facilitate inlining of QRead and QWrite functions
|
||||
* in IxQMgr.h
|
||||
*/
|
||||
ixQMgrQInlinedReadWriteInfo[qId].qReadCount = 0;
|
||||
ixQMgrQInlinedReadWriteInfo[qId].qWriteCount = 0;
|
||||
ixQMgrQInlinedReadWriteInfo[qId].qEntrySizeInWords = qEntrySizeInWords;
|
||||
ixQMgrQInlinedReadWriteInfo[qId].qSizeInEntries =
|
||||
(UINT32)qSizeInWords / (UINT32)qEntrySizeInWords;
|
||||
|
||||
/* Calculate the new freeSramAddress from the size of the queue
|
||||
* currently being configured.
|
||||
*/
|
||||
freeSramAddress += (qSizeInWords * IX_QMGR_NUM_BYTES_PER_WORD);
|
||||
|
||||
/* Get the virtual SRAM address */
|
||||
ixQMgrAqmIfBaseAddressGet (&aqmLocalBaseAddress);
|
||||
|
||||
IX_OSAL_ASSERT((freeSramAddress - (aqmLocalBaseAddress + (IX_QMGR_QUEBUFFER_SPACE_OFFSET))) <=
|
||||
IX_QMGR_QUE_BUFFER_SPACE_SIZE);
|
||||
|
||||
/* The queue is now configured */
|
||||
cfgQueueInfo[qId].isConfigured = TRUE;
|
||||
|
||||
ixOsalMutexUnlock(&ixQMgrQCfgMutex);
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* Update statistics */
|
||||
stats.qStats[qId].isConfigured = TRUE;
|
||||
stats.qStats[qId].qName = cfgQueueInfo[qId].qName;
|
||||
#endif
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
IxQMgrQSizeInWords
|
||||
ixQMgrQSizeInWordsGet (IxQMgrQId qId)
|
||||
{
|
||||
/* No parameter checking as this is used on the data path */
|
||||
return (cfgQueueInfo[qId].qSizeInWords);
|
||||
}
|
||||
|
||||
IX_STATUS
|
||||
ixQMgrQSizeInEntriesGet (IxQMgrQId qId,
|
||||
unsigned *qSizeInEntries)
|
||||
{
|
||||
if (!ixQMgrQIsConfigured(qId))
|
||||
{
|
||||
return IX_QMGR_Q_NOT_CONFIGURED;
|
||||
}
|
||||
|
||||
if(NULL == qSizeInEntries)
|
||||
{
|
||||
return IX_QMGR_PARAMETER_ERROR;
|
||||
}
|
||||
|
||||
*qSizeInEntries = (UINT32)(cfgQueueInfo[qId].qSizeInWords) /
|
||||
(UINT32)cfgQueueInfo[qId].qEntrySizeInWords;
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
IxQMgrQEntrySizeInWords
|
||||
ixQMgrQEntrySizeInWordsGet (IxQMgrQId qId)
|
||||
{
|
||||
/* No parameter checking as this is used on the data path */
|
||||
return (cfgQueueInfo[qId].qEntrySizeInWords);
|
||||
}
|
||||
|
||||
IX_STATUS
|
||||
ixQMgrWatermarkSet (IxQMgrQId qId,
|
||||
IxQMgrWMLevel ne,
|
||||
IxQMgrWMLevel nf)
|
||||
{
|
||||
IxQMgrQStatus qStatusOnEntry;/* The queue status on entry/exit */
|
||||
IxQMgrQStatus qStatusOnExit; /* to this function */
|
||||
|
||||
if (!ixQMgrQIsConfigured(qId))
|
||||
{
|
||||
return IX_QMGR_Q_NOT_CONFIGURED;
|
||||
}
|
||||
|
||||
if (!watermarkLevelIsOk (qId, ne))
|
||||
{
|
||||
return IX_QMGR_INVALID_Q_WM;
|
||||
}
|
||||
|
||||
if (!watermarkLevelIsOk (qId, nf))
|
||||
{
|
||||
return IX_QMGR_INVALID_Q_WM;
|
||||
}
|
||||
|
||||
/* Get the current queue status */
|
||||
ixQMgrAqmIfQueStatRead (qId, &qStatusOnEntry);
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* Update statistics */
|
||||
stats.wmSetCnt++;
|
||||
#endif
|
||||
|
||||
ixQMgrAqmIfWatermarkSet (qId,
|
||||
ne,
|
||||
nf);
|
||||
|
||||
/* Get the current queue status */
|
||||
ixQMgrAqmIfQueStatRead (qId, &qStatusOnExit);
|
||||
|
||||
/* If the status has changed return a warning */
|
||||
if (qStatusOnEntry != qStatusOnExit)
|
||||
{
|
||||
return IX_QMGR_WARNING;
|
||||
}
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
IX_STATUS
|
||||
ixQMgrAvailableSramAddressGet (UINT32 *address,
|
||||
unsigned *sizeOfFreeRam)
|
||||
{
|
||||
UINT32 aqmLocalBaseAddress;
|
||||
|
||||
if ((NULL == address)||(NULL == sizeOfFreeRam))
|
||||
{
|
||||
return IX_QMGR_PARAMETER_ERROR;
|
||||
}
|
||||
if (!cfgInitialized)
|
||||
{
|
||||
return IX_FAIL;
|
||||
}
|
||||
|
||||
*address = freeSramAddress;
|
||||
|
||||
/* Get the virtual SRAM address */
|
||||
ixQMgrAqmIfBaseAddressGet (&aqmLocalBaseAddress);
|
||||
|
||||
/*
|
||||
* Calculate the size in bytes of free sram
|
||||
* i.e. current free SRAM virtual pointer from
|
||||
* (base + total size)
|
||||
*/
|
||||
*sizeOfFreeRam =
|
||||
(aqmLocalBaseAddress +
|
||||
IX_QMGR_AQM_SRAM_SIZE_IN_BYTES) -
|
||||
freeSramAddress;
|
||||
|
||||
if (0 == *sizeOfFreeRam)
|
||||
{
|
||||
return IX_QMGR_NO_AVAILABLE_SRAM;
|
||||
}
|
||||
|
||||
return IX_SUCCESS;
|
||||
}
|
||||
|
||||
BOOL
|
||||
ixQMgrQIsConfigured (IxQMgrQId qId)
|
||||
{
|
||||
if (!IX_QMGR_QID_IS_VALID(qId))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return cfgQueueInfo[qId].isConfigured;
|
||||
}
|
||||
|
||||
IxQMgrQCfgStats*
|
||||
ixQMgrQCfgStatsGet (void)
|
||||
{
|
||||
return &stats;
|
||||
}
|
||||
|
||||
IxQMgrQCfgStats*
|
||||
ixQMgrQCfgQStatsGet (IxQMgrQId qId)
|
||||
{
|
||||
unsigned int ne;
|
||||
unsigned int nf;
|
||||
UINT32 baseAddress;
|
||||
UINT32 readPtr;
|
||||
UINT32 writePtr;
|
||||
|
||||
stats.qStats[qId].qSizeInWords = cfgQueueInfo[qId].qSizeInWords;
|
||||
stats.qStats[qId].qEntrySizeInWords = cfgQueueInfo[qId].qEntrySizeInWords;
|
||||
|
||||
if (IX_SUCCESS != ixQMgrQNumEntriesGet (qId, &stats.qStats[qId].numEntries))
|
||||
{
|
||||
if (IX_QMGR_WARNING != ixQMgrQNumEntriesGet (qId, &stats.qStats[qId].numEntries))
|
||||
{
|
||||
IX_QMGR_LOG_WARNING1("Failed to get the number of entries in queue.... %d\n", qId);
|
||||
}
|
||||
}
|
||||
|
||||
ixQMgrAqmIfQueCfgRead (qId,
|
||||
stats.qStats[qId].numEntries,
|
||||
&baseAddress,
|
||||
&ne,
|
||||
&nf,
|
||||
&readPtr,
|
||||
&writePtr);
|
||||
|
||||
stats.qStats[qId].baseAddress = baseAddress;
|
||||
stats.qStats[qId].ne = ne;
|
||||
stats.qStats[qId].nf = nf;
|
||||
stats.qStats[qId].readPtr = readPtr;
|
||||
stats.qStats[qId].writePtr = writePtr;
|
||||
|
||||
return &stats;
|
||||
}
|
||||
|
||||
/*
|
||||
* Static function definitions
|
||||
*/
|
||||
|
||||
PRIVATE BOOL
|
||||
watermarkLevelIsOk (IxQMgrQId qId, IxQMgrWMLevel level)
|
||||
{
|
||||
unsigned qSizeInEntries;
|
||||
|
||||
switch (level)
|
||||
{
|
||||
case IX_QMGR_Q_WM_LEVEL0:
|
||||
case IX_QMGR_Q_WM_LEVEL1:
|
||||
case IX_QMGR_Q_WM_LEVEL2:
|
||||
case IX_QMGR_Q_WM_LEVEL4:
|
||||
case IX_QMGR_Q_WM_LEVEL8:
|
||||
case IX_QMGR_Q_WM_LEVEL16:
|
||||
case IX_QMGR_Q_WM_LEVEL32:
|
||||
case IX_QMGR_Q_WM_LEVEL64:
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Check watermark is not bigger than the qSizeInEntries */
|
||||
ixQMgrQSizeInEntriesGet(qId, &qSizeInEntries);
|
||||
|
||||
if ((unsigned)level > qSizeInEntries)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
PRIVATE BOOL
|
||||
qSizeInWordsIsOk (IxQMgrQSizeInWords qSize)
|
||||
{
|
||||
BOOL status;
|
||||
|
||||
switch (qSize)
|
||||
{
|
||||
case IX_QMGR_Q_SIZE16:
|
||||
case IX_QMGR_Q_SIZE32:
|
||||
case IX_QMGR_Q_SIZE64:
|
||||
case IX_QMGR_Q_SIZE128:
|
||||
status = TRUE;
|
||||
break;
|
||||
default:
|
||||
status = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
PRIVATE BOOL
|
||||
qEntrySizeInWordsIsOk (IxQMgrQEntrySizeInWords entrySize)
|
||||
{
|
||||
BOOL status;
|
||||
|
||||
switch (entrySize)
|
||||
{
|
||||
case IX_QMGR_Q_ENTRY_SIZE1:
|
||||
case IX_QMGR_Q_ENTRY_SIZE2:
|
||||
case IX_QMGR_Q_ENTRY_SIZE4:
|
||||
status = TRUE;
|
||||
break;
|
||||
default:
|
||||
status = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
91
cpu/ixp/npe/Makefile
Normal file
91
cpu/ixp/npe/Makefile
Normal file
@ -0,0 +1,91 @@
|
||||
#
|
||||
# (C) Copyright 2006
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
#
|
||||
# See file CREDITS for list of people who contributed to this
|
||||
# project.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of
|
||||
# the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
# MA 02111-1307 USA
|
||||
#
|
||||
|
||||
include $(TOPDIR)/config.mk
|
||||
|
||||
LIB := libnpe.a
|
||||
|
||||
CFLAGS += -I$(TOPDIR)/cpu/ixp/npe/include -DCONFIG_IXP425_COMPONENT_ETHDB
|
||||
|
||||
OBJS := npe.o \
|
||||
miiphy.o \
|
||||
IxOsalBufferMgt.o \
|
||||
IxOsalIoMem.o \
|
||||
IxOsalOsCacheMMU.o \
|
||||
IxOsalOsMsgQ.o \
|
||||
IxOsalOsSemaphore.o \
|
||||
IxOsalOsServices.o \
|
||||
IxOsalOsThread.o \
|
||||
IxEthAcc.o \
|
||||
IxEthAccCommon.o \
|
||||
IxEthAccControlInterface.o \
|
||||
IxEthAccDataPlane.o \
|
||||
IxEthAccMac.o \
|
||||
IxEthAccMii.o \
|
||||
IxEthDBAPI.o \
|
||||
IxEthDBAPISupport.o \
|
||||
IxEthDBCore.o \
|
||||
IxEthDBEvents.o \
|
||||
IxEthDBFeatures.o \
|
||||
IxEthDBFirewall.o \
|
||||
IxEthDBHashtable.o \
|
||||
IxEthDBLearning.o \
|
||||
IxEthDBMem.o \
|
||||
IxEthDBNPEAdaptor.o \
|
||||
IxEthDBPortUpdate.o \
|
||||
IxEthDBReports.o \
|
||||
IxEthDBSearch.o \
|
||||
IxEthDBSpanningTree.o \
|
||||
IxEthDBUtil.o \
|
||||
IxEthDBVlan.o \
|
||||
IxEthDBWiFi.o \
|
||||
IxEthMii.o \
|
||||
IxQMgrAqmIf.o \
|
||||
IxQMgrDispatcher.o \
|
||||
IxQMgrInit.o \
|
||||
IxQMgrQAccess.o \
|
||||
IxQMgrQCfg.o \
|
||||
IxFeatureCtrl.o \
|
||||
IxNpeDl.o \
|
||||
IxNpeDlImageMgr.o \
|
||||
IxNpeDlNpeMgr.o \
|
||||
IxNpeDlNpeMgrUtils.o \
|
||||
IxNpeMicrocode.o \
|
||||
IxNpeMh.o \
|
||||
IxNpeMhConfig.o \
|
||||
IxNpeMhReceive.o \
|
||||
IxNpeMhSend.o \
|
||||
IxNpeMhSolicitedCbMgr.o \
|
||||
IxNpeMhUnsolicitedCbMgr.o
|
||||
|
||||
all: $(LIB)
|
||||
|
||||
$(LIB): $(OBJS)
|
||||
$(AR) crv $@ $(OBJS)
|
||||
|
||||
#########################################################################
|
||||
|
||||
.depend: Makefile $(OBJS:.o=.c)
|
||||
$(CC) -M $(CFLAGS) $(OBJS:.o=.c) > $@
|
||||
|
||||
sinclude .depend
|
71
cpu/ixp/npe/include/IxAssert.h
Normal file
71
cpu/ixp/npe/include/IxAssert.h
Normal file
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* @file IxAssert.h
|
||||
*
|
||||
* @date 21-MAR-2002 (replaced by OSAL)
|
||||
*
|
||||
* @brief This file contains assert and ensure macros used by the IXP400 software
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup IxAssert IXP400 Assertion Macros (IxAssert) API
|
||||
*
|
||||
* @brief Assertion support
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef IXASSERT_H
|
||||
|
||||
#ifndef __doxygen_HIDE
|
||||
#define IXASSERT_H
|
||||
#endif /* __doxygen_HIDE */
|
||||
|
||||
#include "IxOsalBackward.h"
|
||||
|
||||
#endif /* IXASSERT_H */
|
||||
|
||||
/**
|
||||
* @} addtogroup IxAssert
|
||||
*/
|
||||
|
||||
|
||||
|
504
cpu/ixp/npe/include/IxAtmSch.h
Normal file
504
cpu/ixp/npe/include/IxAtmSch.h
Normal file
@ -0,0 +1,504 @@
|
||||
/**
|
||||
* @file IxAtmSch.h
|
||||
*
|
||||
* @date 23-NOV-2001
|
||||
*
|
||||
* @brief Header file for the IXP400 ATM Traffic Shaper
|
||||
*
|
||||
* This component demonstrates an ATM Traffic Shaper implementation. It
|
||||
* will perform shaping on upto 12 ports and total of 44 VCs accross all ports,
|
||||
* 32 are intended for AAL0/5 and 12 for OAM (1 per port).
|
||||
* The supported traffic types are;1 rt-VBR VC where PCR = SCR.
|
||||
* (Effectively CBR) and Up-to 44 VBR VCs.
|
||||
*
|
||||
* This component models the ATM ports and VCs and is capable of producing
|
||||
* a schedule of ATM cells per port which can be supplied to IxAtmdAcc
|
||||
* for execution on the data path.
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*
|
||||
* @sa IxAtmm.h
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup IxAtmSch IXP400 ATM Transmit Scheduler (IxAtmSch) API
|
||||
*
|
||||
* @brief IXP400 ATM scheduler component Public API
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef IXATMSCH_H
|
||||
#define IXATMSCH_H
|
||||
|
||||
#include "IxOsalTypes.h"
|
||||
#include "IxAtmTypes.h"
|
||||
|
||||
/*
|
||||
* #defines and macros used in this file.
|
||||
*/
|
||||
|
||||
/* Return codes */
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmSch
|
||||
*
|
||||
* @def IX_ATMSCH_RET_NOT_ADMITTED
|
||||
* @brief Indicates that CAC function has rejected VC registration due
|
||||
* to insufficient line capacity.
|
||||
*/
|
||||
#define IX_ATMSCH_RET_NOT_ADMITTED 2
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmSch
|
||||
*
|
||||
* @def IX_ATMSCH_RET_QUEUE_FULL
|
||||
* @brief Indicates that the VC queue is full, no more demand can be
|
||||
* queued at this time.
|
||||
*/
|
||||
#define IX_ATMSCH_RET_QUEUE_FULL 3
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmSch
|
||||
*
|
||||
* @def IX_ATMSCH_RET_QUEUE_EMPTY
|
||||
* @brief Indicates that all VC queues on this port are empty and
|
||||
* therefore there are no cells to be scheduled at this time.
|
||||
*/
|
||||
#define IX_ATMSCH_RET_QUEUE_EMPTY 4
|
||||
|
||||
/*
|
||||
* Function declarations
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmSch
|
||||
*
|
||||
* @fn ixAtmSchInit(void)
|
||||
*
|
||||
* @brief This function is used to initialize the ixAtmSch component. It
|
||||
* should be called before any other IxAtmSch API function.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return
|
||||
* - <b>IX_SUCCESS :</b> indicates that
|
||||
* -# The ATM scheduler component has been successfully initialized.
|
||||
* -# The scheduler is ready to accept Port modelling requests.
|
||||
* - <b>IX_FAIL :</b> Some internal error has prevented the scheduler component
|
||||
* from initialising.
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixAtmSchInit(void);
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmSch
|
||||
*
|
||||
* @fn ixAtmSchPortModelInitialize( IxAtmLogicalPort port,
|
||||
unsigned int portRate,
|
||||
unsigned int minCellsToSchedule)
|
||||
*
|
||||
* @brief This function shall be called first to initialize an ATM port before
|
||||
* any other ixAtmSch API calls may be made for that port.
|
||||
*
|
||||
* @param port @ref IxAtmLogicalPort [in] - The specific port to initialize. Valid
|
||||
* values range from 0 to IX_UTOPIA_MAX_PORTS - 1, representing a
|
||||
* maximum of IX_UTOPIA_MAX_PORTS possible ports.
|
||||
*
|
||||
* @param portRate unsigned int [in] - Value indicating the upstream capacity
|
||||
* of the indicated port. The value should be supplied in
|
||||
* units of ATM (53 bytes) cells per second.
|
||||
* A port rate of 800Kbits/s is the equivalent
|
||||
* of 1886 cells per second
|
||||
*
|
||||
* @param minCellsToSchedule unsigned int [in] - This parameter specifies the minimum
|
||||
* number of cells which the scheduler will put in a schedule
|
||||
* table for this port. This value sets the worst case CDVT for VCs
|
||||
* on this port i.e. CDVT = 1*minCellsToSchedule/portRate.
|
||||
* @return
|
||||
* - <b>IX_SUCCESS :</b> indicates that
|
||||
* -# The ATM scheduler has been successfully initialized.
|
||||
* -# The requested port model has been established.
|
||||
* -# The scheduler is ready to accept VC modelling requests
|
||||
* on the ATM port.
|
||||
* - <b>IX_FAIL :</b> indicates the requested port could not be
|
||||
* initialized. */
|
||||
PUBLIC IX_STATUS
|
||||
ixAtmSchPortModelInitialize( IxAtmLogicalPort port,
|
||||
unsigned int portRate,
|
||||
unsigned int minCellsToSchedule);
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmSch
|
||||
*
|
||||
* @fn ixAtmSchPortRateModify( IxAtmLogicalPort port,
|
||||
unsigned int portRate)
|
||||
*
|
||||
* @brief This function is called to modify the portRate on a
|
||||
* previously initialized port, typically in the event that
|
||||
* the line condition of the port changes.
|
||||
*
|
||||
* @param port @ref IxAtmLogicalPort [in] - Specifies the ATM port which is to be
|
||||
* modified.
|
||||
*
|
||||
* @param portRate unsigned int [in] - Value indicating the new upstream
|
||||
* capacity for this port in cells/second.
|
||||
* A port rate of 800Kbits/s is the equivalent
|
||||
* of 1886 cells per second
|
||||
*
|
||||
* @return
|
||||
* - <b>IX_SUCCESS :</b> The port rate has been successfully modified.<br>
|
||||
* - <b>IX_FAIL :</b> The port rate could not be modified, either
|
||||
* because the input data was invalid, or the new port rate is
|
||||
* insufficient to support established ATM VC contracts on this
|
||||
* port.
|
||||
*
|
||||
* @warning The IxAtmSch component will validate the supplied port
|
||||
* rate is sufficient to support all established VC
|
||||
* contracts on the port. If the new port rate is
|
||||
* insufficient to support all established contracts then
|
||||
* the request to modify the port rate will be rejected.
|
||||
* In this event, the user is expected to remove
|
||||
* established contracts using the ixAtmSchVcModelRemove
|
||||
* interface and then retry this interface.
|
||||
*
|
||||
* @sa ixAtmSchVcModelRemove() */
|
||||
PUBLIC IX_STATUS
|
||||
ixAtmSchPortRateModify( IxAtmLogicalPort port,
|
||||
unsigned int portRate);
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmSch
|
||||
*
|
||||
* @fn ixAtmSchVcModelSetup( IxAtmLogicalPort port,
|
||||
IxAtmTrafficDescriptor *trafficDesc,
|
||||
IxAtmSchedulerVcId *vcId)
|
||||
*
|
||||
* @brief A client calls this interface to set up an upstream
|
||||
* (transmitting) virtual connection model (VC) on the
|
||||
* specified ATM port. This function also provides the
|
||||
* virtual * connection admission control (CAC) service to the
|
||||
* client.
|
||||
*
|
||||
* @param port @ref IxAtmLogicalPort [in] - Specifies the ATM port on which the upstream
|
||||
* VC is to be established.
|
||||
*
|
||||
* @param *trafficDesc @ref IxAtmTrafficDescriptor [in] - Pointer to a structure
|
||||
* describing the requested traffic contract of the VC to be
|
||||
* established. This structure contains the typical ATM
|
||||
* traffic descriptor values (e.g. PCR, SCR, MBS, CDVT, etc.)
|
||||
* defined by the ATM standard.
|
||||
*
|
||||
* @param *vcId @ref IxAtmSchedulerVcId [out] - This value will be filled with the
|
||||
* port-unique identifier for this virtual connection. A
|
||||
* valid identification is a non-negative number.
|
||||
*
|
||||
* @return
|
||||
* - <b>IX_SUCCESS :</b> The VC has been successfully established on
|
||||
* this port. The client may begin to submit demand on this VC.
|
||||
* - <b>IX_ATMSCH_RET_NOT_ADMITTED :</b> The VC cannot be established
|
||||
* on this port because there is insufficient upstream capacity
|
||||
* available to support the requested traffic contract descriptor
|
||||
* - <b>IX_FAIL :</b>Input data are invalid. VC has not been
|
||||
* established.
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixAtmSchVcModelSetup( IxAtmLogicalPort port,
|
||||
IxAtmTrafficDescriptor *trafficDesc,
|
||||
IxAtmSchedulerVcId *vcId);
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmSch
|
||||
*
|
||||
* @fn ixAtmSchVcConnIdSet( IxAtmLogicalPort port,
|
||||
IxAtmSchedulerVcId vcId,
|
||||
IxAtmConnId vcUserConnId)
|
||||
*
|
||||
* @brief A client calls this interface to set the vcUserConnId for a VC on
|
||||
* the specified ATM port. This vcUserConnId will default to
|
||||
* IX_ATM_IDLE_CELLS_CONNID if this function is not called for a VC.
|
||||
* Hence if the client does not call this function for a VC then only idle
|
||||
* cells will be scheduled for this VC.
|
||||
*
|
||||
* @param port @ref IxAtmLogicalPort [in] - Specifies the ATM port on which the upstream
|
||||
* VC is has been established.
|
||||
*
|
||||
* @param vcId @ref IxAtmSchedulerVcId [in] - This is the unique identifier for this virtual
|
||||
* connection. A valid identification is a non-negative number and is
|
||||
* all ports.
|
||||
*
|
||||
* @param vcUserConnId @ref IxAtmConnId [in] - The connId is used to refer to a VC in schedule
|
||||
* table entries. It is treated as the Id by which the scheduler client
|
||||
* knows the VC. It is used in any communicatations from the Scheduler
|
||||
* to the scheduler user e.g. schedule table entries.
|
||||
*
|
||||
* @return
|
||||
* - <b>IX_SUCCESS :</b> The id has successfully been set.
|
||||
* - <b>IX_FAIL :</b>Input data are invalid. connId id is not established.
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixAtmSchVcConnIdSet( IxAtmLogicalPort port,
|
||||
IxAtmSchedulerVcId vcId,
|
||||
IxAtmConnId vcUserConnId);
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmSch
|
||||
*
|
||||
* @fn ixAtmSchVcModelRemove( IxAtmLogicalPort port,
|
||||
IxAtmSchedulerVcId vcId)
|
||||
*
|
||||
* @brief Interface called by the client to remove a previously
|
||||
* established VC on a particular port.
|
||||
*
|
||||
* @param port @ref IxAtmLogicalPort [in] - Specifies the ATM port on which the VC to be
|
||||
* removed is established.
|
||||
*
|
||||
* @param vcId @ref IxAtmSchedulerVcId [in] - Identifies the VC to be removed. This is the
|
||||
* value returned by the @ref ixAtmSchVcModelSetup call which
|
||||
* established the relevant VC.
|
||||
*
|
||||
* @return
|
||||
* - <b>IX_SUCCESS :</b> The VC has been successfully removed from
|
||||
* this port. It is no longer modelled on this port.
|
||||
* - <b>IX_FAIL :</b>Input data are invalid. The VC is still being modeled
|
||||
* by the traffic shaper.
|
||||
*
|
||||
* @sa ixAtmSchVcModelSetup()
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixAtmSchVcModelRemove( IxAtmLogicalPort port,
|
||||
IxAtmSchedulerVcId vcId);
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmSch
|
||||
*
|
||||
* @fn ixAtmSchVcQueueUpdate( IxAtmLogicalPort port,
|
||||
IxAtmSchedulerVcId vcId,
|
||||
unsigned int numberOfCells)
|
||||
*
|
||||
* @brief The client calls this function to notify IxAtmSch that the
|
||||
* user of a VC has submitted cells for transmission.
|
||||
*
|
||||
* This information is stored, aggregated from a number of calls to
|
||||
* ixAtmSchVcQueueUpdate and eventually used in the call to
|
||||
* ixAtmSchTableUpdate.
|
||||
*
|
||||
* Normally IxAtmSch will update the VC queue by adding the number of
|
||||
* cells to the current queue length. However, if IxAtmSch
|
||||
* determines that the user has over-submitted for the VC and
|
||||
* exceeded its transmission quota the queue request can be rejected.
|
||||
* The user should resubmit the request later when the queue has been
|
||||
* depleted.
|
||||
*
|
||||
* This implementation of ixAtmSchVcQueueUpdate uses no operating
|
||||
* system or external facilities, either directly or indirectly.
|
||||
* This allows clients to call this function form within an interrupt handler.
|
||||
*
|
||||
* This interface is structurally compatible with the
|
||||
* IxAtmdAccSchQueueUpdate callback type definition required for
|
||||
* IXP400 ATM scheduler interoperability.
|
||||
*
|
||||
* @param port @ref IxAtmLogicalPort [in] - Specifies the ATM port on which the VC to be
|
||||
* updated is established.
|
||||
*
|
||||
* @param vcId @ref IxAtmSchedulerVcId [in] - Identifies the VC to be updated. This is the
|
||||
* value returned by the @ref ixAtmSchVcModelSetup call which
|
||||
* established the relevant VC.
|
||||
*
|
||||
* @param numberOfCells unsigned int [in] - Indicates how many ATM cells should
|
||||
* be added to the queue for this VC.
|
||||
*
|
||||
* @return
|
||||
* - <b>IX_SUCCESS :</b> The VC queue has been successfully updated.
|
||||
* - <b>IX_ATMSCH_RET_QUEUE_FULL :</b> The VC queue has reached a
|
||||
* preset limit. This indicates the client has over-submitted
|
||||
* and exceeded its transmission quota. The request is
|
||||
* rejected. The VC queue is not updated. The VC user is
|
||||
* advised to resubmit the request later.
|
||||
* - <b>IX_FAIL :</b> The input are invalid. No VC queue is updated.
|
||||
*
|
||||
* @warning IxAtmSch assumes that the calling software ensures that
|
||||
* calls to ixAtmSchVcQueueUpdate, ixAtmSchVcQueueClear and
|
||||
* ixAtmSchTableUpdate are both self and mutually exclusive
|
||||
* for the same port.
|
||||
*
|
||||
* @sa ixAtmSchVcQueueUpdate(), ixAtmSchVcQueueClear(), ixAtmSchTableUpdate(). */
|
||||
PUBLIC IX_STATUS
|
||||
ixAtmSchVcQueueUpdate( IxAtmLogicalPort port,
|
||||
IxAtmSchedulerVcId vcId,
|
||||
unsigned int numberOfCells);
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmSch
|
||||
*
|
||||
* @fn ixAtmSchVcQueueClear( IxAtmLogicalPort port,
|
||||
IxAtmSchedulerVcId vcId)
|
||||
*
|
||||
* @brief The client calls this function to remove all currently
|
||||
* queued cells from a registered VC. The pending cell count
|
||||
* for the specified VC is reset to zero.
|
||||
*
|
||||
* This interface is structurally compatible with the
|
||||
* IxAtmdAccSchQueueClear callback type definition required for
|
||||
* IXP400 ATM scheduler interoperability.
|
||||
*
|
||||
* @param port @ref IxAtmLogicalPort [in] - Specifies the ATM port on which the VC to be
|
||||
* cleared is established.
|
||||
*
|
||||
* @param vcId @ref IxAtmSchedulerVcId [in] - Identifies the VC to be cleared. This is the
|
||||
* value returned by the @ref ixAtmSchVcModelSetup call which
|
||||
* established the relevant VC.
|
||||
*
|
||||
* @return
|
||||
* - <b>IX_SUCCESS :</b> The VC queue has been successfully cleared.
|
||||
* - <b>IX_FAIL :</b> The input are invalid. No VC queue is modified.
|
||||
*
|
||||
* @warning IxAtmSch assumes that the calling software ensures that
|
||||
* calls to ixAtmSchVcQueueUpdate, ixAtmSchVcQueueClear and
|
||||
* ixAtmSchTableUpdate are both self and mutually exclusive
|
||||
* for the same port.
|
||||
*
|
||||
* @sa ixAtmSchVcQueueUpdate(), ixAtmSchVcQueueClear(), ixAtmSchTableUpdate(). */
|
||||
PUBLIC IX_STATUS
|
||||
ixAtmSchVcQueueClear( IxAtmLogicalPort port,
|
||||
IxAtmSchedulerVcId vcId);
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmSch
|
||||
*
|
||||
* @fn ixAtmSchTableUpdate( IxAtmLogicalPort port,
|
||||
unsigned int maxCells,
|
||||
IxAtmScheduleTable **rettable)
|
||||
*
|
||||
* @brief The client calls this function to request an update of the
|
||||
* schedule table for a particular ATM port.
|
||||
*
|
||||
* This is called when the client decides it needs a new sequence of
|
||||
* cells to send (probably because the transmit queue is near to
|
||||
* empty for this ATM port). The scheduler will use its stored
|
||||
* information on the cells submitted for transmit (i.e. data
|
||||
* supplied via @ref ixAtmSchVcQueueUpdate function) with the traffic
|
||||
* descriptor information of all established VCs on the ATM port to
|
||||
* decide the sequence of cells to be sent and fill the schedule
|
||||
* table for a period of time into the future.
|
||||
*
|
||||
* IxAtmSch will guarantee a minimum of minCellsToSchedule if there
|
||||
* is at least one cell ready to send. If there are no cells then
|
||||
* IX_ATMSCH_RET_QUEUE_EMPTY is returned.
|
||||
*
|
||||
* This implementation of ixAtmSchTableUpdate uses no operating
|
||||
* system or external facilities, either directly or indirectly.
|
||||
* This allows clients to call this function form within an FIQ
|
||||
* interrupt handler.
|
||||
*
|
||||
* @param port @ref IxAtmLogicalPort [in] - Specifies the ATM port for which requested
|
||||
* schedule table is to be generated.
|
||||
*
|
||||
* @param maxCells unsigned [in] - Specifies the maximum number of cells
|
||||
* that must be scheduled in the supplied table during any
|
||||
* call to the interface.
|
||||
*
|
||||
* @param **table @ref IxAtmScheduleTable [out] - A pointer to an area of
|
||||
* storage is returned which contains the generated
|
||||
* schedule table. The client should not modify the
|
||||
* contents of this table.
|
||||
*
|
||||
* @return
|
||||
* - <b>IX_SUCCESS :</b> The schedule table has been published.
|
||||
* Currently there is at least one VC queue that is nonempty.
|
||||
* - <b>IX_ATMSCH_RET_QUEUE_EMPTY :</b> Currently all VC queues on
|
||||
* this port are empty. The schedule table returned is set to
|
||||
* NULL. The client is not expected to invoke this function
|
||||
* again until more cells have been submitted on this port
|
||||
* through the @ref ixAtmSchVcQueueUpdate function.
|
||||
* - <b>IX_FAIL :</b> The input are invalid. No action is taken.
|
||||
*
|
||||
* @warning IxAtmSch assumes that the calling software ensures that
|
||||
* calls to ixAtmSchVcQueueUpdate, ixAtmSchVcQueueClear and
|
||||
* ixAtmSchTableUpdate are both self and mutually exclusive
|
||||
* for the same port.
|
||||
*
|
||||
* @warning Subsequent calls to this function for the same port will
|
||||
* overwrite the contents of previously supplied schedule
|
||||
* tables. The client must be completely finished with the
|
||||
* previously supplied schedule table before calling this
|
||||
* function again for the same port.
|
||||
*
|
||||
* @sa ixAtmSchVcQueueUpdate(), ixAtmSchVcQueueClear(), ixAtmSchTableUpdate(). */
|
||||
PUBLIC IX_STATUS
|
||||
ixAtmSchTableUpdate( IxAtmLogicalPort port,
|
||||
unsigned int maxCells,
|
||||
IxAtmScheduleTable **rettable);
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmSch
|
||||
*
|
||||
* @fn ixAtmSchShow(void)
|
||||
*
|
||||
* @brief Utility function which will print statistics on the current
|
||||
* and accumulated state of VCs and traffic in the ATM
|
||||
* scheduler component. Output is sent to the default output
|
||||
* device.
|
||||
*
|
||||
* @param none
|
||||
* @return none
|
||||
*/
|
||||
PUBLIC void
|
||||
ixAtmSchShow(void);
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmSch
|
||||
*
|
||||
* @fn ixAtmSchStatsClear(void)
|
||||
*
|
||||
* @brief Utility function which will reset all counter statistics in
|
||||
* the ATM scheduler to zero.
|
||||
*
|
||||
* @param none
|
||||
* @return none
|
||||
*/
|
||||
PUBLIC void
|
||||
ixAtmSchStatsClear(void);
|
||||
|
||||
#endif
|
||||
/* IXATMSCH_H */
|
||||
|
||||
/** @} */
|
409
cpu/ixp/npe/include/IxAtmTypes.h
Normal file
409
cpu/ixp/npe/include/IxAtmTypes.h
Normal file
@ -0,0 +1,409 @@
|
||||
/**
|
||||
* @file IxAtmTypes.h
|
||||
*
|
||||
* @date 24-MAR-2002
|
||||
*
|
||||
* @brief This file contains Atm types common to a number of Atm components.
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------
|
||||
Doxygen group definitions
|
||||
------------------------------------------------------ */
|
||||
/**
|
||||
* @defgroup IxAtmTypes IXP400 ATM Types (IxAtmTypes)
|
||||
*
|
||||
* @brief The common set of types used in many Atm components
|
||||
*
|
||||
* @{ */
|
||||
|
||||
#ifndef IXATMTYPES_H
|
||||
#define IXATMTYPES_H
|
||||
|
||||
#include "IxNpeA.h"
|
||||
|
||||
/**
|
||||
* @enum IxAtmLogicalPort
|
||||
*
|
||||
* @brief Logical Port Definitions :
|
||||
*
|
||||
* Only 1 port is available in SPHY configuration
|
||||
* 12 ports are enabled in MPHY configuration
|
||||
*
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
IX_UTOPIA_PORT_0 = 0, /**< Port 0 */
|
||||
#ifdef IX_NPE_MPHYMULTIPORT
|
||||
IX_UTOPIA_PORT_1, /**< Port 1 */
|
||||
IX_UTOPIA_PORT_2, /**< Port 2 */
|
||||
IX_UTOPIA_PORT_3, /**< Port 3 */
|
||||
IX_UTOPIA_PORT_4, /**< Port 4 */
|
||||
IX_UTOPIA_PORT_5, /**< Port 5 */
|
||||
IX_UTOPIA_PORT_6, /**< Port 6 */
|
||||
IX_UTOPIA_PORT_7, /**< Port 7 */
|
||||
IX_UTOPIA_PORT_8, /**< Port 8 */
|
||||
IX_UTOPIA_PORT_9, /**< Port 9 */
|
||||
IX_UTOPIA_PORT_10, /**< Port 10 */
|
||||
IX_UTOPIA_PORT_11, /**< Port 11 */
|
||||
#endif /* IX_NPE_MPHY */
|
||||
IX_UTOPIA_MAX_PORTS /**< Not a port - just a definition for the
|
||||
* maximum possible ports
|
||||
*/
|
||||
} IxAtmLogicalPort;
|
||||
|
||||
/**
|
||||
* @def IX_ATM_CELL_PAYLOAD_SIZE
|
||||
* @brief Size of a ATM cell payload
|
||||
*/
|
||||
#define IX_ATM_CELL_PAYLOAD_SIZE (48)
|
||||
|
||||
/**
|
||||
* @def IX_ATM_CELL_SIZE
|
||||
* @brief Size of a ATM cell, including header
|
||||
*/
|
||||
#define IX_ATM_CELL_SIZE (53)
|
||||
|
||||
/**
|
||||
* @def IX_ATM_CELL_SIZE_NO_HEC
|
||||
* @brief Size of a ATM cell, excluding HEC byte
|
||||
*/
|
||||
#define IX_ATM_CELL_SIZE_NO_HEC (IX_ATM_CELL_SIZE - 1)
|
||||
|
||||
/**
|
||||
* @def IX_ATM_OAM_CELL_SIZE_NO_HEC
|
||||
* @brief Size of a OAM cell, excluding HEC byte
|
||||
*/
|
||||
#define IX_ATM_OAM_CELL_SIZE_NO_HEC IX_ATM_CELL_SIZE_NO_HEC
|
||||
|
||||
/**
|
||||
* @def IX_ATM_AAL0_48_CELL_PAYLOAD_SIZE
|
||||
* @brief Size of a AAL0 48 Cell payload
|
||||
*/
|
||||
#define IX_ATM_AAL0_48_CELL_PAYLOAD_SIZE IX_ATM_CELL_PAYLOAD_SIZE
|
||||
|
||||
/**
|
||||
* @def IX_ATM_AAL5_CELL_PAYLOAD_SIZE
|
||||
* @brief Size of a AAL5 Cell payload
|
||||
*/
|
||||
#define IX_ATM_AAL5_CELL_PAYLOAD_SIZE IX_ATM_CELL_PAYLOAD_SIZE
|
||||
|
||||
/**
|
||||
* @def IX_ATM_AAL0_52_CELL_SIZE_NO_HEC
|
||||
* @brief Size of a AAL0 52 Cell, excluding HEC byte
|
||||
*/
|
||||
#define IX_ATM_AAL0_52_CELL_SIZE_NO_HEC IX_ATM_CELL_SIZE_NO_HEC
|
||||
|
||||
|
||||
/**
|
||||
* @def IX_ATM_MAX_VPI
|
||||
* @brief Maximum value of an ATM VPI
|
||||
*/
|
||||
#define IX_ATM_MAX_VPI 255
|
||||
|
||||
/**
|
||||
* @def IX_ATM_MAX_VCI
|
||||
* @brief Maximum value of an ATM VCI
|
||||
*/
|
||||
#define IX_ATM_MAX_VCI 65535
|
||||
|
||||
/**
|
||||
* @def IX_ATM_MAX_NUM_AAL_VCS
|
||||
* @brief Maximum number of active AAL5/AAL0 VCs in the system
|
||||
*/
|
||||
#define IX_ATM_MAX_NUM_AAL_VCS 32
|
||||
|
||||
/**
|
||||
* @def IX_ATM_MAX_NUM_VC
|
||||
* @brief Maximum number of active AAL5/AAL0 VCs in the system
|
||||
* The use of this macro is depreciated, it is retained for
|
||||
* backward compatiblity. For current software release
|
||||
* and beyond the define IX_ATM_MAX_NUM_AAL_VC should be used.
|
||||
*/
|
||||
#define IX_ATM_MAX_NUM_VC IX_ATM_MAX_NUM_AAL_VCS
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @def IX_ATM_MAX_NUM_OAM_TX_VCS
|
||||
* @brief Maximum number of active OAM Tx VCs in the system,
|
||||
* 1 OAM VC per port
|
||||
*/
|
||||
#define IX_ATM_MAX_NUM_OAM_TX_VCS IX_UTOPIA_MAX_PORTS
|
||||
|
||||
/**
|
||||
* @def IX_ATM_MAX_NUM_OAM_RX_VCS
|
||||
* @brief Maximum number of active OAM Rx VCs in the system,
|
||||
* 1 OAM VC shared accross all ports
|
||||
*/
|
||||
#define IX_ATM_MAX_NUM_OAM_RX_VCS 1
|
||||
|
||||
/**
|
||||
* @def IX_ATM_MAX_NUM_AAL_OAM_TX_VCS
|
||||
* @brief Maximum number of active AAL5/AAL0/OAM Tx VCs in the system
|
||||
*/
|
||||
#define IX_ATM_MAX_NUM_AAL_OAM_TX_VCS (IX_ATM_MAX_NUM_AAL_VCS + IX_ATM_MAX_NUM_OAM_TX_VCS)
|
||||
|
||||
/**
|
||||
* @def IX_ATM_MAX_NUM_AAL_OAM_RX_VCS
|
||||
* @brief Maximum number of active AAL5/AAL0/OAM Rx VCs in the system
|
||||
*/
|
||||
#define IX_ATM_MAX_NUM_AAL_OAM_RX_VCS (IX_ATM_MAX_NUM_AAL_VCS + IX_ATM_MAX_NUM_OAM_RX_VCS)
|
||||
|
||||
/**
|
||||
* @def IX_ATM_IDLE_CELLS_CONNID
|
||||
* @brief VC Id used to indicate idle cells in the returned schedule table.
|
||||
*/
|
||||
#define IX_ATM_IDLE_CELLS_CONNID 0
|
||||
|
||||
|
||||
/**
|
||||
* @def IX_ATM_CELL_HEADER_VCI_GET
|
||||
* @brief get the VCI field from a cell header
|
||||
*/
|
||||
#define IX_ATM_CELL_HEADER_VCI_GET(cellHeader) \
|
||||
(((cellHeader) >> 4) & IX_OAM_VCI_BITS_MASK);
|
||||
|
||||
/**
|
||||
* @def IX_ATM_CELL_HEADER_VPI_GET
|
||||
* @brief get the VPI field from a cell header
|
||||
*/
|
||||
#define IX_ATM_CELL_HEADER_VPI_GET(cellHeader) \
|
||||
(((cellHeader) >> 20) & IX_OAM_VPI_BITS_MASK);
|
||||
|
||||
/**
|
||||
* @def IX_ATM_CELL_HEADER_PTI_GET
|
||||
* @brief get the PTI field from a cell header
|
||||
*/
|
||||
#define IX_ATM_CELL_HEADER_PTI_GET(cellHeader) \
|
||||
((cellHeader) >> 1) & IX_OAM_PTI_BITS_MASK;
|
||||
|
||||
/**
|
||||
* @typedef IxAtmCellHeader
|
||||
*
|
||||
* @brief ATM Cell Header, does not contain 4 byte HEC, added by NPE-A
|
||||
*/
|
||||
typedef unsigned int IxAtmCellHeader;
|
||||
|
||||
|
||||
/**
|
||||
* @enum IxAtmServiceCategory
|
||||
*
|
||||
* @brief Enumerated type representing available ATM service categories.
|
||||
* For more informatoin on these categories, see "Traffic Management
|
||||
* Specification" v4.1, published by the ATM Forum -
|
||||
* http://www.atmforum.com
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
IX_ATM_CBR, /**< Constant Bit Rate */
|
||||
IX_ATM_RTVBR, /**< Real Time Variable Bit Rate */
|
||||
IX_ATM_VBR, /**< Variable Bit Rate */
|
||||
IX_ATM_UBR, /**< Unspecified Bit Rate */
|
||||
IX_ATM_ABR /**< Available Bit Rate (not supported) */
|
||||
|
||||
} IxAtmServiceCategory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @enum IxAtmRxQueueId
|
||||
*
|
||||
* @brief Rx Queue Type for RX traffic
|
||||
*
|
||||
* IxAtmRxQueueId defines the queues involved for receiving data.
|
||||
*
|
||||
* There are two queues to facilitate prioritisation handling
|
||||
* and processing the 2 queues with different algorithms and
|
||||
* constraints
|
||||
*
|
||||
* e.g. : one queue can carry voice (or time-critical traffic), the
|
||||
* other queue can carry non-voice traffic
|
||||
*
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
IX_ATM_RX_A = 0, /**< RX queue A */
|
||||
IX_ATM_RX_B, /**< RX queue B */
|
||||
IX_ATM_MAX_RX_STREAMS /**< Maximum number of RX streams */
|
||||
} IxAtmRxQueueId;
|
||||
|
||||
/**
|
||||
* @brief Structure describing an ATM traffic contract for a Virtual
|
||||
* Connection (VC).
|
||||
*
|
||||
* Structure is used to specify the requested traffic contract for a
|
||||
* VC to the IxAtmSch component using the @ref ixAtmSchVcModelSetup
|
||||
* interface.
|
||||
*
|
||||
* These parameters are defined by the ATM forum working group
|
||||
* (http://www.atmforum.com).
|
||||
*
|
||||
* @note Typical values for a voice channel 64 Kbit/s
|
||||
* - atmService @a IX_ATM_RTVBR
|
||||
* - pcr 400 (include IP overhead, and AAL5 trailer)
|
||||
* - cdvt 5000000 (5 ms)
|
||||
* - scr = pcr
|
||||
*
|
||||
* @note Typical values for a data channel 800 Kbit/s
|
||||
* - atmService @a IX_ATM_UBR
|
||||
* - pcr 1962 (include IP overhead, and AAL5 trailer)
|
||||
* - cdvt 5000000 (5 ms)
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
IxAtmServiceCategory atmService; /**< ATM service category */
|
||||
unsigned pcr; /**< Peak Cell Rate - cells per second */
|
||||
unsigned cdvt; /**< Cell Delay Variation Tolerance - in nanoseconds */
|
||||
unsigned scr; /**< Sustained Cell Rate - cells per second */
|
||||
unsigned mbs; /**< Max Burst Size - cells */
|
||||
unsigned mcr; /**< Minimum Cell Rate - cells per second */
|
||||
unsigned mfs; /**< Max Frame Size - cells */
|
||||
} IxAtmTrafficDescriptor;
|
||||
|
||||
/**
|
||||
* @typedef IxAtmConnId
|
||||
*
|
||||
* @brief ATM VC data connection identifier.
|
||||
*
|
||||
* This is is generated by IxAtmdAcc when a successful connection is
|
||||
* made on a VC. The is the ID by which IxAtmdAcc knows an active
|
||||
* VC and should be used in IxAtmdAcc API calls to reference a
|
||||
* specific VC.
|
||||
*/
|
||||
typedef unsigned int IxAtmConnId;
|
||||
|
||||
/**
|
||||
* @typedef IxAtmSchedulerVcId
|
||||
*
|
||||
* @brief ATM VC scheduling connection identifier.
|
||||
*
|
||||
* This id is generated and used by ATM Tx controller, generally
|
||||
* the traffic shaper (e.g. IxAtmSch). The IxAtmdAcc component
|
||||
* will request one of these Ids whenever a data connection on
|
||||
* a Tx VC is requested. This ID will be used in callbacks to
|
||||
* the ATM Transmission Ctrl s/w (e.g. IxAtmm) to reference a
|
||||
* particular VC.
|
||||
*/
|
||||
typedef int IxAtmSchedulerVcId;
|
||||
|
||||
/**
|
||||
* @typedef IxAtmNpeRxVcId
|
||||
*
|
||||
* @brief ATM Rx VC identifier used by the ATM Npe.
|
||||
*
|
||||
* This Id is generated by IxAtmdAcc when a successful data connection
|
||||
* is made on a rx VC.
|
||||
*/
|
||||
typedef unsigned int IxAtmNpeRxVcId;
|
||||
|
||||
/**
|
||||
* @brief ATM Schedule Table entry
|
||||
*
|
||||
* This IxAtmScheduleTableEntry is used by an ATM scheduler to inform
|
||||
* IxAtmdAcc about the data to transmit (in term of cells per VC)
|
||||
*
|
||||
* This structure defines
|
||||
* @li the number of cells to be transmitted (numberOfCells)
|
||||
* @li the VC connection to be used for transmission (connId).
|
||||
*
|
||||
* @note - When the connection Id value is IX_ATM_IDLE_CELLS_CONNID, the
|
||||
* corresponding number of idle cells will be transmitted to the hardware.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
IxAtmConnId connId; /**< connection Id
|
||||
*
|
||||
* Identifier of VC from which cells are to be transmitted.
|
||||
* When this valus is IX_ATM_IDLE_CELLS_CONNID, this indicates
|
||||
* that the system should transmit the specified number
|
||||
* of idle cells. Unknown connIds result in the transmission
|
||||
* idle cells.
|
||||
*/
|
||||
unsigned int numberOfCells; /**< number of cells to transmit
|
||||
*
|
||||
* The number of contiguous cells to schedule from this VC
|
||||
* at this point. The valid range is from 1 to
|
||||
* @a IX_ATM_SCHEDULETABLE_MAXCELLS_PER_ENTRY. This
|
||||
* number can swap over mbufs and pdus. OverSchduling results
|
||||
* in the transmission of idle cells.
|
||||
*/
|
||||
} IxAtmScheduleTableEntry;
|
||||
|
||||
/**
|
||||
* @brief This structure defines a schedule table which gives details
|
||||
* on which data (from which VCs) should be transmitted for a
|
||||
* forthcoming period of time for a particular port and the
|
||||
* order in which that data should be transmitted.
|
||||
*
|
||||
* The schedule table consists of a series of entries each of which
|
||||
* will schedule one or more cells from a particular registered VC.
|
||||
* The total number of cells scheduled and the total number of
|
||||
* entries in the table are also indicated.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
unsigned tableSize; /**< Number of entries
|
||||
*
|
||||
* Indicates the total number of
|
||||
* entries in the table.
|
||||
*/
|
||||
unsigned totalCellSlots; /**< Number of cells
|
||||
*
|
||||
* Indicates the total number of ATM
|
||||
* cells which are scheduled by all the
|
||||
* entries in the table.
|
||||
*/
|
||||
IxAtmScheduleTableEntry *table; /**< Pointer to schedule entries
|
||||
*
|
||||
* Pointer to an array
|
||||
* containing tableSize entries
|
||||
*/
|
||||
} IxAtmScheduleTable;
|
||||
|
||||
#endif /* IXATMTYPES_H */
|
||||
|
||||
/**
|
||||
* @} defgroup IxAtmTypes
|
||||
*/
|
||||
|
||||
|
1194
cpu/ixp/npe/include/IxAtmdAcc.h
Normal file
1194
cpu/ixp/npe/include/IxAtmdAcc.h
Normal file
File diff suppressed because it is too large
Load Diff
1958
cpu/ixp/npe/include/IxAtmdAccCtrl.h
Normal file
1958
cpu/ixp/npe/include/IxAtmdAccCtrl.h
Normal file
File diff suppressed because it is too large
Load Diff
795
cpu/ixp/npe/include/IxAtmm.h
Normal file
795
cpu/ixp/npe/include/IxAtmm.h
Normal file
@ -0,0 +1,795 @@
|
||||
/**
|
||||
* @file IxAtmm.h
|
||||
*
|
||||
* @date 3-DEC-2001
|
||||
*
|
||||
* @brief Header file for the IXP400 ATM Manager component (IxAtmm)
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup IxAtmm IXP400 ATM Manager (IxAtmm) API
|
||||
*
|
||||
* @brief IXP400 ATM Manager component Public API
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef IXATMM_H
|
||||
#define IXATMM_H
|
||||
|
||||
/*
|
||||
* Put the user defined include files required
|
||||
*/
|
||||
#include "IxAtmSch.h"
|
||||
#include "IxOsalTypes.h"
|
||||
|
||||
/*
|
||||
* #defines and macros used in this file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def IX_ATMM_RET_ALREADY_INITIALIZED
|
||||
*
|
||||
* @brief Component has already been initialized
|
||||
*/
|
||||
#define IX_ATMM_RET_ALREADY_INITIALIZED 2
|
||||
|
||||
/**
|
||||
* @def IX_ATMM_RET_INVALID_PORT
|
||||
*
|
||||
* @brief Specified port does not exist or is out of range */
|
||||
#define IX_ATMM_RET_INVALID_PORT 3
|
||||
|
||||
/**
|
||||
* @def IX_ATMM_RET_INVALID_VC_DESCRIPTOR
|
||||
*
|
||||
* @brief The VC description does not adhere to ATM standards */
|
||||
#define IX_ATMM_RET_INVALID_VC_DESCRIPTOR 4
|
||||
|
||||
/**
|
||||
* @def IX_ATMM_RET_VC_CONFLICT
|
||||
*
|
||||
* @brief The VPI/VCI values supplied are either reserved, or they
|
||||
* conflict with a previously registered VC on this port */
|
||||
#define IX_ATMM_RET_VC_CONFLICT 5
|
||||
|
||||
/**
|
||||
* @def IX_ATMM_RET_PORT_CAPACITY_IS_FULL
|
||||
*
|
||||
* @brief The virtual connection cannot be established on the port
|
||||
* because the remaining port capacity is not sufficient to
|
||||
* support it */
|
||||
#define IX_ATMM_RET_PORT_CAPACITY_IS_FULL 6
|
||||
|
||||
/**
|
||||
* @def IX_ATMM_RET_NO_SUCH_VC
|
||||
*
|
||||
* @brief No registered VC, as described by the supplied VCI/VPI or
|
||||
* VC identifier values, exists on this port */
|
||||
#define IX_ATMM_RET_NO_SUCH_VC 7
|
||||
|
||||
/**
|
||||
* @def IX_ATMM_RET_INVALID_VC_ID
|
||||
*
|
||||
* @brief The specified VC identifier is out of range. */
|
||||
#define IX_ATMM_RET_INVALID_VC_ID 8
|
||||
|
||||
/**
|
||||
* @def IX_ATMM_RET_INVALID_PARAM_PTR
|
||||
*
|
||||
* @brief A pointer parameter was NULL. */
|
||||
#define IX_ATMM_RET_INVALID_PARAM_PTR 9
|
||||
|
||||
/**
|
||||
* @def IX_ATMM_UTOPIA_SPHY_ADDR
|
||||
*
|
||||
* @brief The phy address when in SPHY mode */
|
||||
#define IX_ATMM_UTOPIA_SPHY_ADDR 31
|
||||
|
||||
/**
|
||||
* @def IX_ATMM_THREAD_PRI_HIGH
|
||||
*
|
||||
* @brief The value of high priority thread */
|
||||
#define IX_ATMM_THREAD_PRI_HIGH 90
|
||||
|
||||
/*
|
||||
* Typedefs whose scope is limited to this file.
|
||||
*/
|
||||
|
||||
/** @brief Definition for use in the @ref IxAtmmVc structure.
|
||||
* Indicates the direction of a VC */
|
||||
typedef enum
|
||||
{
|
||||
IX_ATMM_VC_DIRECTION_TX=0, /**< Atmm Vc direction transmit*/
|
||||
IX_ATMM_VC_DIRECTION_RX, /**< Atmm Vc direction receive*/
|
||||
IX_ATMM_VC_DIRECTION_INVALID /**< Atmm Vc direction invalid*/
|
||||
} IxAtmmVcDirection;
|
||||
|
||||
/** @brief Definition for use with @ref IxAtmmVcChangeCallback
|
||||
* callback. Indicates that the event type represented by the
|
||||
* callback for this VC. */
|
||||
typedef enum
|
||||
{
|
||||
IX_ATMM_VC_CHANGE_EVENT_REGISTER=0, /**< Atmm Vc event register*/
|
||||
IX_ATMM_VC_CHANGE_EVENT_DEREGISTER, /**< Atmm Vc event de-register*/
|
||||
IX_ATMM_VC_CHANGE_EVENT_INVALID /**< Atmm Vc event invalid*/
|
||||
} IxAtmmVcChangeEvent;
|
||||
|
||||
/** @brief Definitions for use with @ref ixAtmmUTOPIAInit interface to
|
||||
* indicate that UTOPIA loopback should be enabled or disabled
|
||||
* on initialisation. */
|
||||
typedef enum
|
||||
{
|
||||
IX_ATMM_UTOPIA_LOOPBACK_DISABLED=0, /**< Atmm Utopia loopback mode disabled*/
|
||||
IX_ATMM_UTOPIA_LOOPBACK_ENABLED, /**< Atmm Utopia loopback mode enabled*/
|
||||
IX_ATMM_UTOPIA_LOOPBACK_INVALID /**< Atmm Utopia loopback mode invalid*/
|
||||
} IxAtmmUtopiaLoopbackMode;
|
||||
|
||||
/** @brief This structure describes the required attributes of a
|
||||
* virtual connection.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned vpi; /**< VPI value of this virtual connection */
|
||||
unsigned vci; /**< VCI value of this virtual connection. */
|
||||
IxAtmmVcDirection direction; /**< VC direction */
|
||||
|
||||
/** Traffic descriptor of this virtual connection. This structure
|
||||
* is defined by the @ref IxAtmSch component. */
|
||||
IxAtmTrafficDescriptor trafficDesc;
|
||||
} IxAtmmVc;
|
||||
|
||||
|
||||
/** @brief Definitions for use with @ref ixAtmmUtopiaInit interface to
|
||||
* indicate that UTOPIA multi-phy/single-phy mode is used.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
IX_ATMM_MPHY_MODE = 0, /**< Atmm phy mode mphy*/
|
||||
IX_ATMM_SPHY_MODE, /**< Atmm phy mode sphy*/
|
||||
IX_ATMM_PHY_MODE_INVALID /**< Atmm phy mode invalid*/
|
||||
} IxAtmmPhyMode;
|
||||
|
||||
|
||||
/** @brief Structure contains port-specific information required to
|
||||
* initialize IxAtmm, and specifically, the IXP400 UTOPIA
|
||||
* Level-2 device. */
|
||||
typedef struct {
|
||||
unsigned reserved_1:11; /**< [31:21] Should be zero */
|
||||
unsigned UtopiaTxPhyAddr:5; /**< [20:16] Address of the
|
||||
* transmit (Tx) PHY for this
|
||||
* port on the 5-bit UTOPIA
|
||||
* Level-2 address bus */
|
||||
unsigned reserved_2:11; /**< [15:5] Should be zero */
|
||||
unsigned UtopiaRxPhyAddr:5; /**< [4:0] Address of the receive
|
||||
* (Rx) PHY for this port on the
|
||||
* 5-bit UTOPIA Level-2
|
||||
* address bus */
|
||||
} IxAtmmPortCfg;
|
||||
|
||||
/** @brief Callback type used with @ref ixAtmmVcChangeCallbackRegister interface
|
||||
* Defines a callback type which will be used to notify registered
|
||||
* users of registration/deregistration events on a particular port
|
||||
*
|
||||
* @param eventType @ref IxAtmmVcChangeEvent [in] - Event indicating
|
||||
* whether the VC supplied has been added or
|
||||
* removed
|
||||
*
|
||||
* @param port @ref IxAtmLogicalPort [in] - Specifies the port on which the event has
|
||||
* occurred
|
||||
*
|
||||
* @param vcChanged @ref IxAtmmVc* [in] - Pointer to a structure which gives
|
||||
* details of the VC which has been added
|
||||
* or removed on the port
|
||||
*/
|
||||
typedef void (*IxAtmmVcChangeCallback) (IxAtmmVcChangeEvent eventType,
|
||||
IxAtmLogicalPort port,
|
||||
const IxAtmmVc* vcChanged);
|
||||
|
||||
/*
|
||||
* Variable declarations global to this file only. Externs are followed by
|
||||
* static variables.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Extern function prototypes
|
||||
*/
|
||||
|
||||
/*
|
||||
* Function declarations
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmm
|
||||
*
|
||||
* @fn ixAtmmInit (void)
|
||||
*
|
||||
* @brief Interface to initialize the IxAtmm software component. Can
|
||||
* be called once only.
|
||||
*
|
||||
* Must be called before any other IxAtmm API is called.
|
||||
*
|
||||
* @param "none"
|
||||
*
|
||||
* @return @li IX_SUCCESS : IxAtmm has been successfully initialized.
|
||||
* Calls to other IxAtmm interfaces may now be performed.
|
||||
* @return @li IX_FAIL : IxAtmm has already been initialized.
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixAtmmInit (void);
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmm
|
||||
*
|
||||
* @fn ixAtmmUtopiaInit (unsigned numPorts,
|
||||
IxAtmmPhyMode phyMode,
|
||||
IxAtmmPortCfg portCfgs[],
|
||||
IxAtmmUtopiaLoopbackMode loopbackMode)
|
||||
*
|
||||
* @brief Interface to initialize the UTOPIA Level-2 ATM coprocessor
|
||||
* for the specified number of physical ports. The function
|
||||
* must be called before the ixAtmmPortInitialize interface
|
||||
* can operate successfully.
|
||||
*
|
||||
* @param numPorts unsigned [in] - Indicates the total number of logical
|
||||
* ports that are active on the device. Up to 12 ports are
|
||||
* supported.
|
||||
*
|
||||
* @param phyMode @ref IxAtmmPhyMode [in] - Put the Utopia coprocessor in SPHY
|
||||
* or MPHY mode.
|
||||
*
|
||||
* @param portCfgs[] @ref IxAtmmPortCfg [in] - Pointer to an array of elements
|
||||
* detailing the UTOPIA specific port characteristics. The
|
||||
* length of the array must be equal to the number of ports
|
||||
* activated. ATM ports are referred to by the relevant
|
||||
* offset in this array in all subsequent IxAtmm interface
|
||||
* calls.
|
||||
*
|
||||
* @param loopbackMode @ref IxAtmmUtopiaLoopbackMode [in] - Value must be one of
|
||||
* @ref IX_ATMM_UTOPIA_LOOPBACK_ENABLED or @ref
|
||||
* IX_ATMM_UTOPIA_LOOPBACK_DISABLED indicating whether
|
||||
* loopback should be enabled on the device. Loopback can
|
||||
* only be supported on a single PHY, therefore the numPorts
|
||||
* parameter must be 1 if loopback is enabled.
|
||||
*
|
||||
* @return @li IX_SUCCESS : Indicates that the UTOPIA device has been
|
||||
* successfully initialized for the supplied ports.
|
||||
* @return @li IX_ATMM_RET_ALREADY_INITIALIZED : The UTOPIA device has
|
||||
* already been initialized.
|
||||
* @return @li IX_FAIL : The supplied parameters are invalid or have been
|
||||
* rejected by the UTOPIA-NPE device.
|
||||
*
|
||||
* @warning
|
||||
* This interface may only be called once.
|
||||
* Port identifiers are assumed to range from 0 to (numPorts - 1) in all
|
||||
* instances.
|
||||
* In all subsequent calls to interfaces supplied by IxAtmm, the specified
|
||||
* port value is expected to represent the offset in the portCfgs array
|
||||
* specified in this interface. i.e. The first port in this array will
|
||||
* subsequently be represented as port 0, the second port as port 1,
|
||||
* and so on.*/
|
||||
PUBLIC IX_STATUS
|
||||
ixAtmmUtopiaInit (unsigned numPorts,
|
||||
IxAtmmPhyMode phyMode,
|
||||
IxAtmmPortCfg portCfgs[],
|
||||
IxAtmmUtopiaLoopbackMode loopbackMode);
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmm
|
||||
*
|
||||
* @fn ixAtmmPortInitialize (IxAtmLogicalPort port,
|
||||
unsigned txPortRate,
|
||||
unsigned rxPortRate)
|
||||
*
|
||||
* @brief The interface is called following @ref ixAtmmUtopiaInit ()
|
||||
* and before calls to any other IxAtmm interface. It serves
|
||||
* to activate the registered ATM port with IxAtmm.
|
||||
*
|
||||
* The transmit and receive port rates are specified in bits per
|
||||
* second. This translates to ATM cells per second according to the
|
||||
* following formula: CellsPerSecond = portRate / (53*8) The
|
||||
* IXP400 device supports only 53 byte cells. The client shall make
|
||||
* sure that the off-chip physical layer device has already been
|
||||
* initialized.
|
||||
*
|
||||
* IxAtmm will configure IxAtmdAcc and IxAtmSch to enable scheduling
|
||||
* on the port.
|
||||
*
|
||||
* This interface must be called once for each active port in the
|
||||
* system. The first time the interface is invoked, it will configure
|
||||
* the mechanism by which the handling of transmit, transmit-done and
|
||||
* receive are driven with the IxAtmdAcc component.
|
||||
*
|
||||
* This function is reentrant.
|
||||
*
|
||||
* @note The minimum tx rate that will be accepted is 424 bit/s which equates
|
||||
* to 1 cell (53 bytes) per second.
|
||||
*
|
||||
* @param port @ref IxAtmLogicalPort [in] - Identifies the port which is to be
|
||||
* initialized.
|
||||
*
|
||||
* @param txPortRate unsigned [in] - Value specifies the
|
||||
* transmit port rate for this port in
|
||||
* bits/second. This value is used by the ATM Scheduler
|
||||
* component is evaluating VC access requests for the port.
|
||||
*
|
||||
* @param rxPortRate unsigned [in] - Value specifies the
|
||||
* receive port rate for this port in bits/second.
|
||||
*
|
||||
* @return @li IX_SUCCESS : The specificed ATM port has been successfully
|
||||
* initialized. IxAtmm is ready to accept VC registrations on
|
||||
* this port.
|
||||
*
|
||||
* @return @li IX_ATMM_RET_ALREADY_INITIALIZED : ixAtmmPortInitialize has
|
||||
* already been called successfully on this port. The current
|
||||
* call is rejected.
|
||||
*
|
||||
* @return @li IX_ATMM_RET_INVALID_PORT : The port value indicated in the
|
||||
* input is not valid. The request is rejected.
|
||||
*
|
||||
* @return @li IX_FAIL : IxAtmm could not initialize the port because the
|
||||
* inputs are not understood.
|
||||
*
|
||||
* @sa ixAtmmPortEnable, ixAtmmPortDisable
|
||||
*
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixAtmmPortInitialize (IxAtmLogicalPort port,
|
||||
unsigned txPortRate,
|
||||
unsigned rxPortRate);
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmm
|
||||
*
|
||||
* @fn ixAtmmPortModify (IxAtmLogicalPort port,
|
||||
unsigned txPortRate,
|
||||
unsigned rxPortRate)
|
||||
*
|
||||
* @brief A client may call this interface to change the existing
|
||||
* port rate (expressed in bits/second) on an established ATM
|
||||
* port.
|
||||
*
|
||||
* @param port @ref IxAtmLogicalPort [in] - Identifies the port which is to be
|
||||
* initialized.
|
||||
*
|
||||
* @param txPortRate unsigned [in] - Value specifies the``
|
||||
* transmit port rate for this port in
|
||||
* bits/second. This value is used by the ATM Scheduler
|
||||
* component is evaluating VC access requests for the port.
|
||||
*
|
||||
* @param rxPortRate unsigned [in] - Value specifies the
|
||||
* receive port rate for this port in
|
||||
* bits/second.
|
||||
*
|
||||
* @return @li IX_SUCCESS : The indicated ATM port rates have been
|
||||
* successfully modified.
|
||||
*
|
||||
* @return @li IX_ATMM_RET_INVALID_PORT : The port value indicated in the
|
||||
* input is not valid. The request is rejected.
|
||||
*
|
||||
* @return @li IX_FAIL : IxAtmm could not update the port because the
|
||||
* inputs are not understood, or the interface was called before
|
||||
* the port was initialized. */
|
||||
PUBLIC IX_STATUS
|
||||
ixAtmmPortModify (IxAtmLogicalPort port,
|
||||
unsigned txPortRate,
|
||||
unsigned rxPortRate);
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmm
|
||||
*
|
||||
* @fn ixAtmmPortQuery (IxAtmLogicalPort port,
|
||||
unsigned *txPortRate,
|
||||
unsigned *rxPortRate);
|
||||
|
||||
*
|
||||
* @brief The client may call this interface to request details on
|
||||
* currently registered transmit and receive rates for an ATM
|
||||
* port.
|
||||
*
|
||||
* @param port @ref IxAtmLogicalPort [in] - Value identifies the port from which the
|
||||
* rate details are requested.
|
||||
*
|
||||
* @param *txPortRate unsigned [out] - Pointer to a value
|
||||
* which will be filled with the value of the transmit port
|
||||
* rate specified in bits/second.
|
||||
*
|
||||
* @param *rxPortRate unsigned [out] - Pointer to a value
|
||||
* which will be filled with the value of the receive port
|
||||
* rate specified in bits/second.
|
||||
*
|
||||
* @return @li IX_SUCCESS : The information requested on the specified
|
||||
* port has been successfully supplied in the output.
|
||||
*
|
||||
* @return @li IX_ATMM_RET_INVALID_PORT : The port value indicated in the
|
||||
* input is not valid. The request is rejected.
|
||||
*
|
||||
* @return @li IX_ATMM_RET_INVALID_PARAM_PTR : A pointer parameter was
|
||||
* NULL.
|
||||
*
|
||||
* @return @li IX_FAIL : IxAtmm could not update the port because the
|
||||
* inputs are not understood, or the interface was called before
|
||||
* the port was initialized. */
|
||||
PUBLIC IX_STATUS
|
||||
ixAtmmPortQuery (IxAtmLogicalPort port,
|
||||
unsigned *txPortRate,
|
||||
unsigned *rxPortRate);
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmm
|
||||
*
|
||||
* @fn ixAtmmPortEnable(IxAtmLogicalPort port)
|
||||
*
|
||||
* @brief The client call this interface to enable transmit for an ATM
|
||||
* port. At initialisation, all the ports are disabled.
|
||||
*
|
||||
* @param port @ref IxAtmLogicalPort [in] - Value identifies the port
|
||||
*
|
||||
* @return @li IX_SUCCESS : Transmission over this port is started.
|
||||
*
|
||||
* @return @li IX_FAIL : The port parameter is not valid, or the
|
||||
* port is already enabled
|
||||
*
|
||||
* @note - When a port is disabled, Rx and Tx VC Connect requests will fail
|
||||
*
|
||||
* @note - This function uses system resources and should not be used
|
||||
* inside an interrupt context.
|
||||
*
|
||||
* @sa ixAtmmPortDisable */
|
||||
PUBLIC IX_STATUS
|
||||
ixAtmmPortEnable(IxAtmLogicalPort port);
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmm
|
||||
*
|
||||
* @fn ixAtmmPortDisable(IxAtmLogicalPort port)
|
||||
*
|
||||
* @brief The client call this interface to disable transmit for an ATM
|
||||
* port. At initialisation, all the ports are disabled.
|
||||
*
|
||||
* @param port @ref IxAtmLogicalPort [in] - Value identifies the port
|
||||
*
|
||||
* @return @li IX_SUCCESS : Transmission over this port is stopped.
|
||||
*
|
||||
* @return @li IX_FAIL : The port parameter is not valid, or the
|
||||
* port is already disabled
|
||||
*
|
||||
* @note - When a port is disabled, Rx and Tx VC Connect requests will fail
|
||||
*
|
||||
* @note - This function call does not stop RX traffic. It is supposed
|
||||
* that this function is invoked when a serious problem
|
||||
* is detected (e.g. physical layer broken). Then, the RX traffic
|
||||
* is not passing.
|
||||
*
|
||||
* @note - This function is blocking until the hw acknowledge that the
|
||||
* transmission is stopped.
|
||||
*
|
||||
* @note - This function uses system resources and should not be used
|
||||
* inside an interrupt context.
|
||||
*
|
||||
* @sa ixAtmmPortEnable */
|
||||
PUBLIC IX_STATUS
|
||||
ixAtmmPortDisable(IxAtmLogicalPort port);
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmm
|
||||
*
|
||||
* @fn ixAtmmVcRegister (IxAtmLogicalPort port,
|
||||
IxAtmmVc *vcToAdd,
|
||||
IxAtmSchedulerVcId *vcId)
|
||||
*
|
||||
* @brief This interface is used to register an ATM Virtual
|
||||
* Connection on the specified ATM port.
|
||||
*
|
||||
* Each call to this interface registers a unidirectional virtual
|
||||
* connection with the parameters specified. If a bi-directional VC
|
||||
* is needed, the function should be called twice (once for each
|
||||
* direction, Tx & Rx) where the VPI and VCI and port parameters in
|
||||
* each call are identical.
|
||||
*
|
||||
* With the addition of each new VC to a port, a series of
|
||||
* callback functions are invoked by the IxAtmm component to notify
|
||||
* possible external components of the change. The callback functions
|
||||
* are registered using the @ref ixAtmmVcChangeCallbackRegister interface.
|
||||
*
|
||||
* The IxAtmSch component is notified of the registration of transmit
|
||||
* VCs.
|
||||
*
|
||||
* @param port @ref IxAtmLogicalPort [in] - Identifies port on which the specified VC is
|
||||
* to be registered.
|
||||
*
|
||||
* @param *vcToAdd @ref IxAtmmVc [in] - Pointer to an @ref IxAtmmVc structure
|
||||
* containing a description of the VC to be registered. The
|
||||
* client shall fill the vpi, vci and direction and relevant
|
||||
* trafficDesc members of this structure before calling this
|
||||
* function.
|
||||
*
|
||||
* @param *vcId @ref IxAtmSchedulerVcId [out] - Pointer to an integer value which is filled
|
||||
* with the per-port unique identifier value for this VC.
|
||||
* This identifier will be required when a request is
|
||||
* made to deregister or change this VC. VC identifiers
|
||||
* for transmit VCs will have a value between 0-43,
|
||||
* i.e. 32 data Tx VCs + 12 OAM Tx Port VCs.
|
||||
* Receive VCs will have a value between 44-66,
|
||||
* i.e. 32 data Rx VCs + 1 OAM Rx VC.
|
||||
*
|
||||
* @return @li IX_SUCCESS : The VC has been successfully registered on
|
||||
* this port. The VC is ready for a client to configure IxAtmdAcc
|
||||
* for receive and transmit operations on the VC.
|
||||
* @return @li IX_ATMM_RET_INVALID_PORT : The port value indicated in the
|
||||
* input is not valid or has not been initialized. The request
|
||||
* is rejected.
|
||||
* @return @li IX_ATMM_RET_INVALID_VC_DESCRIPTOR : The descriptor
|
||||
* pointed to by vcToAdd is invalid. The registration request
|
||||
* is rejected.
|
||||
* @return @li IX_ATMM_RET_VC_CONFLICT : The VC requested conflicts with
|
||||
* reserved VPI and/or VCI values or with another VC already activated
|
||||
* on this port.
|
||||
* @return @li IX_ATMM_RET_PORT_CAPACITY_IS_FULL : The VC cannot be
|
||||
* registered in the port becuase the port capacity is
|
||||
* insufficient to support the requested ATM traffic contract.
|
||||
* The registration request is rejected.
|
||||
* @return @li IX_ATMM_RET_INVALID_PARAM_PTR : A pointer parameter was
|
||||
* NULL.
|
||||
*
|
||||
* @warning IxAtmm has no capability of signaling or negotiating a virtual
|
||||
* connection. Negotiation of the admission of the VC to the network
|
||||
* is beyond the scope of this function. This is assumed to be
|
||||
* performed by the calling client, if appropriate,
|
||||
* before or after this function is called.
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixAtmmVcRegister (IxAtmLogicalPort port,
|
||||
IxAtmmVc *vcToAdd,
|
||||
IxAtmSchedulerVcId *vcId);
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmm
|
||||
*
|
||||
* @fn ixAtmmVcDeregister (IxAtmLogicalPort port, IxAtmSchedulerVcId vcId)
|
||||
*
|
||||
* @brief Function called by a client to deregister a VC from the
|
||||
* system.
|
||||
*
|
||||
* With the removal of each new VC from a port, a series of
|
||||
* registered callback functions are invoked by the IxAtmm component
|
||||
* to notify possible external components of the change. The callback
|
||||
* functions are registered using the @ref ixAtmmVcChangeCallbackRegister.
|
||||
*
|
||||
* The IxAtmSch component is notified of the removal of transmit VCs.
|
||||
*
|
||||
* @param port @ref IxAtmLogicalPort [in] - Identifies port on which the VC to be
|
||||
* removed is currently registered.
|
||||
*
|
||||
* @param vcId @ref IxAtmSchedulerVcId [in] - VC identifier value of the VC to
|
||||
* be deregistered. This value was supplied to the client when
|
||||
the VC was originally registered. This value can also be
|
||||
queried from the IxAtmm component through the @ref ixAtmmVcQuery
|
||||
* interface.
|
||||
*
|
||||
* @return @li IX_SUCCESS : The specified VC has been successfully
|
||||
* removed from this port.
|
||||
* @return @li IX_ATMM_RET_INVALID_PORT : The port value indicated in the
|
||||
* input is not valid or has not been initialized. The request
|
||||
* is rejected.
|
||||
* @return @li IX_FAIL : There is no registered VC associated with the
|
||||
* supplied identifier registered on this port. */
|
||||
PUBLIC IX_STATUS
|
||||
ixAtmmVcDeregister (IxAtmLogicalPort port, IxAtmSchedulerVcId vcId);
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmm
|
||||
*
|
||||
* @fn ixAtmmVcQuery (IxAtmLogicalPort port,
|
||||
unsigned vpi,
|
||||
unsigned vci,
|
||||
IxAtmmVcDirection direction,
|
||||
IxAtmSchedulerVcId *vcId,
|
||||
IxAtmmVc *vcDesc)
|
||||
*
|
||||
* @brief This interface supplies information about an active VC on a
|
||||
* particular port when supplied with the VPI, VCI and
|
||||
* direction of that VC.
|
||||
*
|
||||
* @param port @ref IxAtmLogicalPort [in] - Identifies port on which the VC to be
|
||||
* queried is currently registered.
|
||||
*
|
||||
* @param vpi unsigned [in] - ATM VPI value of the requested VC.
|
||||
*
|
||||
* @param vci unsigned [in] - ATM VCI value of the requested VC.
|
||||
*
|
||||
* @param direction @ref IxAtmmVcDirection [in] - One of @ref
|
||||
* IX_ATMM_VC_DIRECTION_TX or @ref IX_ATMM_VC_DIRECTION_RX
|
||||
* indicating the direction (Tx or Rx) of the requested VC.
|
||||
*
|
||||
* @param *vcId @ref IxAtmSchedulerVcId [out] - Pointer to an integer value which will be
|
||||
* filled with the VC identifier value for the requested
|
||||
* VC (as returned by @ref ixAtmmVcRegister), if it
|
||||
* exists on this port.
|
||||
*
|
||||
* @param *vcDesc @ref IxAtmmVc [out] - Pointer to an @ref IxAtmmVc structure
|
||||
* which will be filled with the specific details of the
|
||||
* requested VC, if it exists on this port.
|
||||
*
|
||||
* @return @li IX_SUCCESS : The specified VC has been found on this port
|
||||
* and the requested details have been returned.
|
||||
* @return @li IX_ATMM_RET_INVALID_PORT : The port value indicated in the
|
||||
* input is not valid or has not been initialized. The request
|
||||
* is rejected.
|
||||
* @return @li IX_ATMM_RET_NO_SUCH_VC : No VC exists on the specified
|
||||
* port which matches the search criteria (VPI, VCI, direction)
|
||||
* given. No data is returned.
|
||||
* @return @li IX_ATMM_RET_INVALID_PARAM_PTR : A pointer parameter was
|
||||
* NULL.
|
||||
*
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixAtmmVcQuery (IxAtmLogicalPort port,
|
||||
unsigned vpi,
|
||||
unsigned vci,
|
||||
IxAtmmVcDirection direction,
|
||||
IxAtmSchedulerVcId *vcId,
|
||||
IxAtmmVc *vcDesc);
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmm
|
||||
*
|
||||
* @fn ixAtmmVcIdQuery (IxAtmLogicalPort port, IxAtmSchedulerVcId vcId, IxAtmmVc *vcDesc)
|
||||
*
|
||||
* @brief This interface supplies information about an active VC on a
|
||||
* particular port when supplied with a vcId for that VC.
|
||||
*
|
||||
* @param port @ref IxAtmLogicalPort [in] - Identifies port on which the VC to be
|
||||
* queried is currently registered.
|
||||
*
|
||||
* @param vcId @ref IxAtmSchedulerVcId [in] - Value returned by @ref ixAtmmVcRegister which
|
||||
* uniquely identifies the requested VC on this port.
|
||||
*
|
||||
* @param *vcDesc @ref IxAtmmVc [out] - Pointer to an @ref IxAtmmVc structure
|
||||
* which will be filled with the specific details of the
|
||||
* requested VC, if it exists on this port.
|
||||
*
|
||||
* @return @li IX_SUCCESS : The specified VC has been found on this port
|
||||
* and the requested details have been returned.
|
||||
* @return @li IX_ATMM_RET_INVALID_PORT : The port value indicated in the
|
||||
* input is not valid or has not been initialized. The request
|
||||
* is rejected.
|
||||
* @return @li IX_ATMM_RET_NO_SUCH_VC : No VC exists on the specified
|
||||
* port which matches the supplied identifier. No data is
|
||||
* returned.
|
||||
* @return @li IX_ATMM_RET_INVALID_PARAM_PTR : A pointer parameter was
|
||||
* NULL.
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixAtmmVcIdQuery (IxAtmLogicalPort port, IxAtmSchedulerVcId vcId, IxAtmmVc *vcDesc);
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmm
|
||||
*
|
||||
* @fn ixAtmmVcChangeCallbackRegister (IxAtmmVcChangeCallback callback)
|
||||
*
|
||||
* @brief This interface is invoked to supply a function to IxAtmm
|
||||
* which will be called to notify the client if a new VC is
|
||||
* registered with IxAtmm or an existing VC is removed.
|
||||
*
|
||||
* The callback, when invoked, will run within the context of the call
|
||||
* to @ref ixAtmmVcRegister or @ref ixAtmmVcDeregister which caused
|
||||
* the change of state.
|
||||
*
|
||||
* A maximum of 32 calbacks may be registered in with IxAtmm.
|
||||
*
|
||||
* @param callback @ref IxAtmmVcChangeCallback [in] - Callback which complies
|
||||
* with the @ref IxAtmmVcChangeCallback definition. This
|
||||
* function will be invoked by IxAtmm with the appropiate
|
||||
* parameters for the relevant VC when any VC has been
|
||||
* registered or deregistered with IxAtmm.
|
||||
*
|
||||
* @return @li IX_SUCCESS : The specified callback has been registered
|
||||
* successfully with IxAtmm and will be invoked when appropriate.
|
||||
* @return @li IX_FAIL : Either the supplied callback is invalid, or
|
||||
* IxAtmm has already registered 32 and connot accommodate
|
||||
* any further registrations of this type. The request is
|
||||
* rejected.
|
||||
*
|
||||
* @warning The client must not call either the @ref
|
||||
* ixAtmmVcRegister or @ref ixAtmmVcDeregister interfaces
|
||||
* from within the supplied callback function. */
|
||||
PUBLIC IX_STATUS ixAtmmVcChangeCallbackRegister (IxAtmmVcChangeCallback callback);
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmm
|
||||
*
|
||||
* @fn ixAtmmVcChangeCallbackDeregister (IxAtmmVcChangeCallback callback)
|
||||
*
|
||||
* @brief This interface is invoked to deregister a previously supplied
|
||||
* callback function.
|
||||
*
|
||||
* @param callback @ref IxAtmmVcChangeCallback [in] - Callback which complies
|
||||
* with the @ref IxAtmmVcChangeCallback definition. This
|
||||
* function will removed from the table of callbacks.
|
||||
*
|
||||
* @return @li IX_SUCCESS : The specified callback has been deregistered
|
||||
* successfully from IxAtmm.
|
||||
* @return @li IX_FAIL : Either the supplied callback is invalid, or
|
||||
* is not currently registered with IxAtmm.
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixAtmmVcChangeCallbackDeregister (IxAtmmVcChangeCallback callback);
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmm
|
||||
*
|
||||
* @fn ixAtmmUtopiaStatusShow (void)
|
||||
*
|
||||
* @brief Display utopia status counters
|
||||
*
|
||||
* @param "none"
|
||||
*
|
||||
* @return @li IX_SUCCESS : Show function was successful
|
||||
* @return @li IX_FAIL : Internal failure
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixAtmmUtopiaStatusShow (void);
|
||||
|
||||
/**
|
||||
* @ingroup IxAtmm
|
||||
*
|
||||
* @fn ixAtmmUtopiaCfgShow (void)
|
||||
*
|
||||
* @brief Display utopia information(config registers and status registers)
|
||||
*
|
||||
* @param "none"
|
||||
*
|
||||
* @return @li IX_SUCCESS : Show function was successful
|
||||
* @return @li IX_FAIL : Internal failure
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixAtmmUtopiaCfgShow (void);
|
||||
|
||||
#endif
|
||||
/* IXATMM_H */
|
||||
|
||||
/** @} */
|
260
cpu/ixp/npe/include/IxDmaAcc.h
Normal file
260
cpu/ixp/npe/include/IxDmaAcc.h
Normal file
@ -0,0 +1,260 @@
|
||||
/**
|
||||
* @file IxDmaAcc.h
|
||||
*
|
||||
* @date 15 October 2002
|
||||
*
|
||||
* @brief API of the IXP400 DMA Access Driver Component (IxDma)
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
Doxygen group definitions
|
||||
---------------------------------------------------------------------*/
|
||||
|
||||
#ifndef IXDMAACC_H
|
||||
#define IXDMAACC_H
|
||||
|
||||
#include "IxOsal.h"
|
||||
#include "IxNpeDl.h"
|
||||
/**
|
||||
* @defgroup IxDmaTypes IXP400 DMA Types (IxDmaTypes)
|
||||
* @brief The common set of types used in the DMA component
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup IxDmaTypes
|
||||
* @enum IxDmaReturnStatus
|
||||
* @brief Dma return status definitions
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
IX_DMA_SUCCESS = IX_SUCCESS, /**< DMA Transfer Success */
|
||||
IX_DMA_FAIL = IX_FAIL, /**< DMA Transfer Fail */
|
||||
IX_DMA_INVALID_TRANSFER_WIDTH, /**< Invalid transfer width */
|
||||
IX_DMA_INVALID_TRANSFER_LENGTH, /**< Invalid transfer length */
|
||||
IX_DMA_INVALID_TRANSFER_MODE, /**< Invalid transfer mode */
|
||||
IX_DMA_INVALID_ADDRESS_MODE, /**< Invalid address mode */
|
||||
IX_DMA_REQUEST_FIFO_FULL /**< DMA request queue is full */
|
||||
} IxDmaReturnStatus;
|
||||
|
||||
/**
|
||||
* @ingroup IxDmaTypes
|
||||
* @enum IxDmaTransferMode
|
||||
* @brief Dma transfer mode definitions
|
||||
* @note Copy and byte swap, and copy and reverse modes only support multiples of word data length.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
IX_DMA_COPY_CLEAR = 0, /**< copy and clear source*/
|
||||
IX_DMA_COPY, /**< copy */
|
||||
IX_DMA_COPY_BYTE_SWAP, /**< copy and byte swap (endian) */
|
||||
IX_DMA_COPY_REVERSE, /**< copy and reverse */
|
||||
IX_DMA_TRANSFER_MODE_INVALID /**< Invalid transfer mode */
|
||||
} IxDmaTransferMode;
|
||||
|
||||
/**
|
||||
* @ingroup IxDmaTypes
|
||||
* @enum IxDmaAddressingMode
|
||||
* @brief Dma addressing mode definitions
|
||||
* @note Fixed source address to fixed destination address addressing mode is not supported.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
IX_DMA_INC_SRC_INC_DST = 0, /**< Incremental source address to incremental destination address */
|
||||
IX_DMA_INC_SRC_FIX_DST, /**< Incremental source address to incremental destination address */
|
||||
IX_DMA_FIX_SRC_INC_DST, /**< Incremental source address to incremental destination address */
|
||||
IX_DMA_FIX_SRC_FIX_DST, /**< Incremental source address to incremental destination address */
|
||||
IX_DMA_ADDRESSING_MODE_INVALID /**< Invalid Addressing Mode */
|
||||
} IxDmaAddressingMode;
|
||||
|
||||
/**
|
||||
* @ingroup IxDmaTypes
|
||||
* @enum IxDmaTransferWidth
|
||||
* @brief Dma transfer width definitions
|
||||
* @Note Fixed addresses (either source or destination) do not support burst transfer width.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
IX_DMA_32_SRC_32_DST = 0, /**< 32-bit src to 32-bit dst */
|
||||
IX_DMA_32_SRC_16_DST, /**< 32-bit src to 16-bit dst */
|
||||
IX_DMA_32_SRC_8_DST, /**< 32-bit src to 8-bit dst */
|
||||
IX_DMA_16_SRC_32_DST, /**< 16-bit src to 32-bit dst */
|
||||
IX_DMA_16_SRC_16_DST, /**< 16-bit src to 16-bit dst */
|
||||
IX_DMA_16_SRC_8_DST, /**< 16-bit src to 8-bit dst */
|
||||
IX_DMA_8_SRC_32_DST, /**< 8-bit src to 32-bit dst */
|
||||
IX_DMA_8_SRC_16_DST, /**< 8-bit src to 16-bit dst */
|
||||
IX_DMA_8_SRC_8_DST, /**< 8-bit src to 8-bit dst */
|
||||
IX_DMA_8_SRC_BURST_DST, /**< 8-bit src to burst dst - Not supported for fixed destination address */
|
||||
IX_DMA_16_SRC_BURST_DST, /**< 16-bit src to burst dst - Not supported for fixed destination address */
|
||||
IX_DMA_32_SRC_BURST_DST, /**< 32-bit src to burst dst - Not supported for fixed destination address */
|
||||
IX_DMA_BURST_SRC_8_DST, /**< burst src to 8-bit dst - Not supported for fixed source address */
|
||||
IX_DMA_BURST_SRC_16_DST, /**< burst src to 16-bit dst - Not supported for fixed source address */
|
||||
IX_DMA_BURST_SRC_32_DST, /**< burst src to 32-bit dst - Not supported for fixed source address*/
|
||||
IX_DMA_BURST_SRC_BURST_DST, /**< burst src to burst dst - Not supported for fixed source and destination address
|
||||
*/
|
||||
IX_DMA_TRANSFER_WIDTH_INVALID /**< Invalid transfer width */
|
||||
} IxDmaTransferWidth;
|
||||
|
||||
/**
|
||||
* @ingroup IxDmaTypes
|
||||
* @enum IxDmaNpeId
|
||||
* @brief NpeId numbers to identify NPE A, B or C
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
IX_DMA_NPEID_NPEA = 0, /**< Identifies NPE A */
|
||||
IX_DMA_NPEID_NPEB, /**< Identifies NPE B */
|
||||
IX_DMA_NPEID_NPEC, /**< Identifies NPE C */
|
||||
IX_DMA_NPEID_MAX /**< Total Number of NPEs */
|
||||
} IxDmaNpeId;
|
||||
/* @} */
|
||||
/**
|
||||
* @defgroup IxDmaAcc IXP400 DMA Access Driver (IxDmaAcc) API
|
||||
*
|
||||
* @brief The public API for the IXP400 IxDmaAcc component
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup IxDmaAcc
|
||||
* @brief DMA Request Id type
|
||||
*/
|
||||
typedef UINT32 IxDmaAccRequestId;
|
||||
|
||||
/**
|
||||
* @ingroup IxDmaAcc
|
||||
* @def IX_DMA_REQUEST_FULL
|
||||
* @brief DMA request queue is full
|
||||
* This constant is a return value used to tell the user that the IxDmaAcc
|
||||
* queue is full.
|
||||
*
|
||||
*/
|
||||
#define IX_DMA_REQUEST_FULL 16
|
||||
|
||||
/**
|
||||
* @ingroup IxDmaAcc
|
||||
* @brief DMA completion notification
|
||||
* This function is called to notify a client that the DMA has been completed
|
||||
* @param status @ref IxDmaReturnStatus [out] - reporting to client
|
||||
*
|
||||
*/
|
||||
typedef void (*IxDmaAccDmaCompleteCallback) (IxDmaReturnStatus status);
|
||||
|
||||
/**
|
||||
* @ingroup IxDmaAcc
|
||||
*
|
||||
* @fn ixDmaAccInit(IxNpeDlNpeId npeId)
|
||||
*
|
||||
* @brief Initialise the DMA Access component
|
||||
* This function will initialise the DMA Access component internals
|
||||
* @param npeId @ref IxNpeDlNpeId [in] - NPE to use for Dma Transfer
|
||||
* @return @li IX_SUCCESS succesfully initialised the component
|
||||
* @return @li IX_FAIL Initialisation failed for some unspecified
|
||||
* internal reason.
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixDmaAccInit(IxNpeDlNpeId npeId);
|
||||
|
||||
/**
|
||||
* @ingroup IxDmaAcc
|
||||
*
|
||||
* @fn ixDmaAccDmaTransfer(
|
||||
IxDmaAccDmaCompleteCallback callback,
|
||||
UINT32 SourceAddr,
|
||||
UINT32 DestinationAddr,
|
||||
UINT16 TransferLength,
|
||||
IxDmaTransferMode TransferMode,
|
||||
IxDmaAddressingMode AddressingMode,
|
||||
IxDmaTransferWidth TransferWidth)
|
||||
*
|
||||
* @brief Perform DMA transfer
|
||||
* This function will perform DMA transfer between devices within the
|
||||
* IXP400 memory map.
|
||||
* @note The following are restrictions for IxDmaAccDmaTransfer:
|
||||
* @li The function is non re-entrant.
|
||||
* @li The function assumes host devices are operating in big-endian mode.
|
||||
* @li Fixed address does not suport burst transfer width
|
||||
* @li Fixed source address to fixed destinatiom address mode is not suported
|
||||
* @li The incrementing source address for expansion bus will not support a burst transfer width and copy and clear mode
|
||||
*
|
||||
* @param callback @ref IxDmaAccDmaCompleteCallback [in] - function pointer to be stored and called when the DMA transfer is completed. This cannot be NULL.
|
||||
* @param SourceAddr UINT32 [in] - Starting address of DMA source. Must be a valid IXP400 memory map address.
|
||||
* @param DestinationAddr UINT32 [in] - Starting address of DMA destination. Must be a valid IXP400 memory map address.
|
||||
* @param TransferLength UINT16 [in] - The size of DMA data transfer. The range must be from 1-64Kbyte
|
||||
* @param TransferMode @ref IxDmaTransferMode [in] - The DMA transfer mode
|
||||
* @param AddressingMode @ref IxDmaAddressingMode [in] - The DMA addressing mode
|
||||
* @param TransferWidth @ref IxDmaTransferWidth [in] - The DMA transfer width
|
||||
*
|
||||
* @return @li IX_DMA_SUCCESS Notification that the DMA request is succesful
|
||||
* @return @li IX_DMA_FAIL IxDmaAcc not yet initialised or some internal error has occured
|
||||
* @return @li IX_DMA_INVALID_TRANSFER_WIDTH Transfer width is nit valid
|
||||
* @return @li IX_DMA_INVALID_TRANSFER_LENGTH Transfer length outside of valid range
|
||||
* @return @li IX_DMA_INVALID_TRANSFER_MODE Transfer Mode not valid
|
||||
* @return @li IX_DMA_REQUEST_FIFO_FULL IxDmaAcc request queue is full
|
||||
*/
|
||||
PUBLIC IxDmaReturnStatus
|
||||
ixDmaAccDmaTransfer(
|
||||
IxDmaAccDmaCompleteCallback callback,
|
||||
UINT32 SourceAddr,
|
||||
UINT32 DestinationAddr,
|
||||
UINT16 TransferLength,
|
||||
IxDmaTransferMode TransferMode,
|
||||
IxDmaAddressingMode AddressingMode,
|
||||
IxDmaTransferWidth TransferWidth);
|
||||
/**
|
||||
* @ingroup IxDmaAcc
|
||||
*
|
||||
* @fn ixDmaAccShow(void)
|
||||
*
|
||||
* @brief Display some component information for debug purposes
|
||||
* Show some internal operation information relating to the DMA service.
|
||||
* At a minimum the following will show.
|
||||
* - the number of the DMA pend (in queue)
|
||||
* @param None
|
||||
* @return @li None
|
||||
*/
|
||||
PUBLIC IX_STATUS
|
||||
ixDmaAccShow(void);
|
||||
|
||||
#endif /* IXDMAACC_H */
|
||||
|
2512
cpu/ixp/npe/include/IxEthAcc.h
Normal file
2512
cpu/ixp/npe/include/IxEthAcc.h
Normal file
File diff suppressed because it is too large
Load Diff
245
cpu/ixp/npe/include/IxEthAccDataPlane_p.h
Normal file
245
cpu/ixp/npe/include/IxEthAccDataPlane_p.h
Normal file
@ -0,0 +1,245 @@
|
||||
/**
|
||||
* @file IxEthAccDataPlane_p.h
|
||||
*
|
||||
* @author Intel Corporation
|
||||
* @date 12-Feb-2002
|
||||
*
|
||||
* @brief Internal Header file for IXP425 Ethernet Access component.
|
||||
*
|
||||
* Design Notes:
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef IxEthAccDataPlane_p_H
|
||||
#define IxEthAccDataPlane_p_H
|
||||
|
||||
#include <IxOsal.h>
|
||||
#include <IxQMgr.h>
|
||||
|
||||
/**
|
||||
* @addtogroup IxEthAccPri
|
||||
*@{
|
||||
*/
|
||||
|
||||
/* typedefs global to this file*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
IX_OSAL_MBUF *pHead;
|
||||
IX_OSAL_MBUF *pTail;
|
||||
}IxEthAccDataPlaneQList;
|
||||
|
||||
|
||||
/**
|
||||
* @struct IxEthAccDataPlaneStats
|
||||
* @brief Statistics data structure associated with the data plane
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UINT32 addToSwQ;
|
||||
UINT32 removeFromSwQ;
|
||||
UINT32 unchainedTxMBufs;
|
||||
UINT32 chainedTxMBufs;
|
||||
UINT32 unchainedTxDoneMBufs;
|
||||
UINT32 chainedTxDoneMBufs;
|
||||
UINT32 unchainedRxMBufs;
|
||||
UINT32 chainedRxMBufs;
|
||||
UINT32 unchainedRxFreeMBufs;
|
||||
UINT32 chainedRxFreeMBufs;
|
||||
UINT32 rxCallbackCounter;
|
||||
UINT32 rxCallbackBurstRead;
|
||||
UINT32 txDoneCallbackCounter;
|
||||
UINT32 unexpectedError;
|
||||
} IxEthAccDataPlaneStats;
|
||||
|
||||
/**
|
||||
* @fn ixEthAccMbufFromSwQ
|
||||
* @brief used during disable steps to convert mbufs from
|
||||
* swq format, ready to be pushed into hw queues for NPE,
|
||||
* back into XScale format
|
||||
*/
|
||||
IX_OSAL_MBUF *ixEthAccMbufFromSwQ(IX_OSAL_MBUF *mbuf);
|
||||
|
||||
/**
|
||||
* @fn ixEthAccDataPlaneShow
|
||||
* @brief Show function (for data plane statistics
|
||||
*/
|
||||
void ixEthAccDataPlaneShow(void);
|
||||
|
||||
/*
|
||||
* lock dataplane when atomic operation is required
|
||||
*/
|
||||
#define IX_ETH_ACC_DATA_PLANE_LOCK(arg) arg = ixOsalIrqLock();
|
||||
#define IX_ETH_ACC_DATA_PLANE_UNLOCK(arg) ixOsalIrqUnlock(arg);
|
||||
|
||||
/*
|
||||
* Use MBUF fields
|
||||
*/
|
||||
#define IX_ETHACC_NE_SHARED(mBufPtr) \
|
||||
((IxEthAccNe *)&((mBufPtr)->ix_ne))
|
||||
|
||||
#if 1
|
||||
|
||||
#define IX_ETHACC_NE_NEXT(mBufPtr) (mBufPtr)->ix_ne.reserved[0]
|
||||
|
||||
/* tm - wrong!! len and pkt_len are in the second word - #define IX_ETHACC_NE_LEN(mBufPtr) (mBufPtr)->ix_ne.reserved[3] */
|
||||
#define IX_ETHACC_NE_LEN(mBufPtr) (mBufPtr)->ix_ne.reserved[1]
|
||||
|
||||
#define IX_ETHACC_NE_DATA(mBufPtr)(mBufPtr)->ix_ne.reserved[2]
|
||||
|
||||
#else
|
||||
|
||||
#define IX_ETHACC_NE_NEXT(mBufPtr) \
|
||||
IX_ETHACC_NE_SHARED(mBufPtr)->ixReserved_next
|
||||
|
||||
#define IX_ETHACC_NE_LEN(mBufPtr) \
|
||||
IX_ETHACC_NE_SHARED(mBufPtr)->ixReserved_lengths
|
||||
|
||||
#define IX_ETHACC_NE_DATA(mBufPtr) \
|
||||
IX_ETHACC_NE_SHARED(mBufPtr)->ixReserved_data
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Use MBUF next pointer field to chain data.
|
||||
*/
|
||||
#define IX_ETH_ACC_MBUF_NEXT_PKT_CHAIN_MEMBER(mbuf) (mbuf)->ix_ctrl.ix_chain
|
||||
|
||||
|
||||
|
||||
#define IX_ETH_ACC_DATAPLANE_IS_Q_EMPTY(mbuf_list) ((mbuf_list.pHead) == NULL)
|
||||
|
||||
|
||||
#define IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_HEAD(mbuf_list,mbuf_to_add) \
|
||||
do { \
|
||||
int lockVal; \
|
||||
IX_ETH_ACC_DATA_PLANE_LOCK(lockVal); \
|
||||
IX_ETH_ACC_STATS_INC(ixEthAccDataStats.addToSwQ); \
|
||||
if ( (mbuf_list.pHead) != NULL ) \
|
||||
{ \
|
||||
(IX_ETH_ACC_MBUF_NEXT_PKT_CHAIN_MEMBER((mbuf_to_add))) = (mbuf_list.pHead);\
|
||||
(mbuf_list.pHead) = (mbuf_to_add); \
|
||||
} \
|
||||
else { \
|
||||
(mbuf_list.pTail) = (mbuf_list.pHead) = (mbuf_to_add); \
|
||||
IX_ETH_ACC_MBUF_NEXT_PKT_CHAIN_MEMBER((mbuf_to_add)) = NULL; \
|
||||
} \
|
||||
IX_ETH_ACC_DATA_PLANE_UNLOCK(lockVal); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_TAIL(mbuf_list,mbuf_to_add) \
|
||||
do { \
|
||||
int lockVal; \
|
||||
IX_ETH_ACC_DATA_PLANE_LOCK(lockVal); \
|
||||
IX_ETH_ACC_STATS_INC(ixEthAccDataStats.addToSwQ); \
|
||||
if ( (mbuf_list.pHead) == NULL ) \
|
||||
{ \
|
||||
(mbuf_list.pHead) = mbuf_to_add; \
|
||||
IX_ETH_ACC_MBUF_NEXT_PKT_CHAIN_MEMBER((mbuf_to_add)) = NULL; \
|
||||
} \
|
||||
else { \
|
||||
IX_ETH_ACC_MBUF_NEXT_PKT_CHAIN_MEMBER((mbuf_list.pTail)) = (mbuf_to_add); \
|
||||
IX_ETH_ACC_MBUF_NEXT_PKT_CHAIN_MEMBER((mbuf_to_add)) = NULL; \
|
||||
} \
|
||||
(mbuf_list.pTail) = mbuf_to_add; \
|
||||
IX_ETH_ACC_DATA_PLANE_UNLOCK(lockVal); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define IX_ETH_ACC_DATAPLANE_REMOVE_MBUF_FROM_Q_HEAD(mbuf_list,mbuf_to_rem) \
|
||||
do { \
|
||||
int lockVal; \
|
||||
IX_ETH_ACC_DATA_PLANE_LOCK(lockVal); \
|
||||
if ( (mbuf_list.pHead) != NULL ) \
|
||||
{ \
|
||||
IX_ETH_ACC_STATS_INC(ixEthAccDataStats.removeFromSwQ); \
|
||||
(mbuf_to_rem) = (mbuf_list.pHead) ; \
|
||||
(mbuf_list.pHead) = (IX_ETH_ACC_MBUF_NEXT_PKT_CHAIN_MEMBER((mbuf_to_rem)));\
|
||||
} \
|
||||
else { \
|
||||
(mbuf_to_rem) = NULL; \
|
||||
} \
|
||||
IX_ETH_ACC_DATA_PLANE_UNLOCK(lockVal); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/**
|
||||
* @brief message handler QManager entries for NPE id => port ID conversion (NPE_B => 0, NPE_C => 1)
|
||||
*/
|
||||
#define IX_ETH_ACC_PORT_TO_NPE_ID(port) \
|
||||
ixEthAccPortData[(port)].npeId
|
||||
|
||||
#define IX_ETH_ACC_NPE_TO_PORT_ID(npe) ((npe == 0 ? 2 : (npe == 1 ? 0 : ( npe == 2 ? 1 : -1 ))))
|
||||
|
||||
#define IX_ETH_ACC_PORT_TO_TX_Q_ID(port) \
|
||||
ixEthAccPortData[(port)].ixEthAccTxData.txQueue
|
||||
|
||||
#define IX_ETH_ACC_PORT_TO_RX_FREE_Q_ID(port) \
|
||||
ixEthAccPortData[(port)].ixEthAccRxData.rxFreeQueue
|
||||
|
||||
#define IX_ETH_ACC_PORT_TO_TX_Q_SOURCE(port) (port == IX_ETH_PORT_1 ? IX_ETH_ACC_TX_FRAME_ENET0_Q_SOURCE : (port == IX_ETH_PORT_2 ? IX_ETH_ACC_TX_FRAME_ENET1_Q_SOURCE : IX_ETH_ACC_TX_FRAME_ENET2_Q_SOURCE))
|
||||
|
||||
#define IX_ETH_ACC_PORT_TO_RX_FREE_Q_SOURCE(port) (port == IX_ETH_PORT_1 ? IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q_SOURCE : (port == IX_ETH_PORT_2 ? IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q_SOURCE : IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q_SOURCE ))
|
||||
|
||||
/* Flush the mbufs chain and all data pointed to by the mbuf */
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define IX_ETH_ACC_STATS_INC(x) (x++)
|
||||
#else
|
||||
#define IX_ETH_ACC_STATS_INC(x)
|
||||
#endif
|
||||
|
||||
#define IX_ETH_ACC_MAX_TX_FRAMES_TO_SUBMIT 128
|
||||
|
||||
void ixEthRxFrameQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId);
|
||||
void ixEthRxMultiBufferQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId);
|
||||
void ixEthTxFrameDoneQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId);
|
||||
|
||||
#endif /* IxEthAccDataPlane_p_H */
|
||||
|
||||
|
||||
/**
|
||||
*@}
|
||||
*/
|
||||
|
248
cpu/ixp/npe/include/IxEthAccMac_p.h
Normal file
248
cpu/ixp/npe/include/IxEthAccMac_p.h
Normal file
@ -0,0 +1,248 @@
|
||||
/*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
|
||||
#ifndef IxEthAccMac_p_H
|
||||
#define IxEthAccMac_p_H
|
||||
|
||||
#include "IxOsal.h"
|
||||
|
||||
#define IX_ETH_ACC_MAX_MULTICAST_ADDRESSES 256
|
||||
#define IX_ETH_ACC_NUM_PORTS 3
|
||||
#define IX_ETH_ACC_MAX_FRAME_SIZE_DEFAULT 1536
|
||||
#define IX_ETH_ACC_MAX_FRAME_SIZE_UPPER_RANGE (65536-64)
|
||||
#define IX_ETH_ACC_MAX_FRAME_SIZE_LOWER_RANGE 64
|
||||
|
||||
/*
|
||||
*
|
||||
* MAC register definitions
|
||||
*
|
||||
*/
|
||||
#define IX_ETH_ACC_MAC_0_BASE IX_OSAL_IXP400_ETHA_PHYS_BASE
|
||||
#define IX_ETH_ACC_MAC_1_BASE IX_OSAL_IXP400_ETHB_PHYS_BASE
|
||||
#define IX_ETH_ACC_MAC_2_BASE IX_OSAL_IXP400_ETH_NPEA_PHYS_BASE
|
||||
|
||||
#define IX_ETH_ACC_MAC_TX_CNTRL1 0x000
|
||||
#define IX_ETH_ACC_MAC_TX_CNTRL2 0x004
|
||||
#define IX_ETH_ACC_MAC_RX_CNTRL1 0x010
|
||||
#define IX_ETH_ACC_MAC_RX_CNTRL2 0x014
|
||||
#define IX_ETH_ACC_MAC_RANDOM_SEED 0x020
|
||||
#define IX_ETH_ACC_MAC_THRESH_P_EMPTY 0x030
|
||||
#define IX_ETH_ACC_MAC_THRESH_P_FULL 0x038
|
||||
#define IX_ETH_ACC_MAC_BUF_SIZE_TX 0x040
|
||||
#define IX_ETH_ACC_MAC_TX_DEFER 0x050
|
||||
#define IX_ETH_ACC_MAC_RX_DEFER 0x054
|
||||
#define IX_ETH_ACC_MAC_TX_TWO_DEFER_1 0x060
|
||||
#define IX_ETH_ACC_MAC_TX_TWO_DEFER_2 0x064
|
||||
#define IX_ETH_ACC_MAC_SLOT_TIME 0x070
|
||||
#define IX_ETH_ACC_MAC_MDIO_CMD_1 0x080
|
||||
#define IX_ETH_ACC_MAC_MDIO_CMD_2 0x084
|
||||
#define IX_ETH_ACC_MAC_MDIO_CMD_3 0x088
|
||||
#define IX_ETH_ACC_MAC_MDIO_CMD_4 0x08c
|
||||
#define IX_ETH_ACC_MAC_MDIO_STS_1 0x090
|
||||
#define IX_ETH_ACC_MAC_MDIO_STS_2 0x094
|
||||
#define IX_ETH_ACC_MAC_MDIO_STS_3 0x098
|
||||
#define IX_ETH_ACC_MAC_MDIO_STS_4 0x09c
|
||||
#define IX_ETH_ACC_MAC_ADDR_MASK_1 0x0A0
|
||||
#define IX_ETH_ACC_MAC_ADDR_MASK_2 0x0A4
|
||||
#define IX_ETH_ACC_MAC_ADDR_MASK_3 0x0A8
|
||||
#define IX_ETH_ACC_MAC_ADDR_MASK_4 0x0AC
|
||||
#define IX_ETH_ACC_MAC_ADDR_MASK_5 0x0B0
|
||||
#define IX_ETH_ACC_MAC_ADDR_MASK_6 0x0B4
|
||||
#define IX_ETH_ACC_MAC_ADDR_1 0x0C0
|
||||
#define IX_ETH_ACC_MAC_ADDR_2 0x0C4
|
||||
#define IX_ETH_ACC_MAC_ADDR_3 0x0C8
|
||||
#define IX_ETH_ACC_MAC_ADDR_4 0x0CC
|
||||
#define IX_ETH_ACC_MAC_ADDR_5 0x0D0
|
||||
#define IX_ETH_ACC_MAC_ADDR_6 0x0D4
|
||||
#define IX_ETH_ACC_MAC_INT_CLK_THRESH 0x0E0
|
||||
#define IX_ETH_ACC_MAC_UNI_ADDR_1 0x0F0
|
||||
#define IX_ETH_ACC_MAC_UNI_ADDR_2 0x0F4
|
||||
#define IX_ETH_ACC_MAC_UNI_ADDR_3 0x0F8
|
||||
#define IX_ETH_ACC_MAC_UNI_ADDR_4 0x0FC
|
||||
#define IX_ETH_ACC_MAC_UNI_ADDR_5 0x100
|
||||
#define IX_ETH_ACC_MAC_UNI_ADDR_6 0x104
|
||||
#define IX_ETH_ACC_MAC_CORE_CNTRL 0x1FC
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
*Bit definitions
|
||||
*
|
||||
*/
|
||||
|
||||
/* TX Control Register 1*/
|
||||
|
||||
#define IX_ETH_ACC_TX_CNTRL1_TX_EN BIT(0)
|
||||
#define IX_ETH_ACC_TX_CNTRL1_DUPLEX BIT(1)
|
||||
#define IX_ETH_ACC_TX_CNTRL1_RETRY BIT(2)
|
||||
#define IX_ETH_ACC_TX_CNTRL1_PAD_EN BIT(3)
|
||||
#define IX_ETH_ACC_TX_CNTRL1_FCS_EN BIT(4)
|
||||
#define IX_ETH_ACC_TX_CNTRL1_2DEFER BIT(5)
|
||||
#define IX_ETH_ACC_TX_CNTRL1_RMII BIT(6)
|
||||
|
||||
/* TX Control Register 2 */
|
||||
#define IX_ETH_ACC_TX_CNTRL2_RETRIES_MASK 0xf
|
||||
|
||||
/* RX Control Register 1 */
|
||||
#define IX_ETH_ACC_RX_CNTRL1_RX_EN BIT(0)
|
||||
#define IX_ETH_ACC_RX_CNTRL1_PADSTRIP_EN BIT(1)
|
||||
#define IX_ETH_ACC_RX_CNTRL1_CRC_EN BIT(2)
|
||||
#define IX_ETH_ACC_RX_CNTRL1_PAUSE_EN BIT(3)
|
||||
#define IX_ETH_ACC_RX_CNTRL1_LOOP_EN BIT(4)
|
||||
#define IX_ETH_ACC_RX_CNTRL1_ADDR_FLTR_EN BIT(5)
|
||||
#define IX_ETH_ACC_RX_CNTRL1_RX_RUNT_EN BIT(6)
|
||||
#define IX_ETH_ACC_RX_CNTRL1_BCAST_DIS BIT(7)
|
||||
|
||||
/* RX Control Register 2 */
|
||||
#define IX_ETH_ACC_RX_CNTRL2_DEFER_EN BIT(0)
|
||||
|
||||
|
||||
|
||||
/* Core Control Register */
|
||||
#define IX_ETH_ACC_CORE_RESET BIT(0)
|
||||
#define IX_ETH_ACC_CORE_RX_FIFO_FLUSH BIT(1)
|
||||
#define IX_ETH_ACC_CORE_TX_FIFO_FLUSH BIT(2)
|
||||
#define IX_ETH_ACC_CORE_SEND_JAM BIT(3)
|
||||
#define IX_ETH_ACC_CORE_MDC_EN BIT(4)
|
||||
|
||||
/* 1st bit of 1st MAC octet */
|
||||
#define IX_ETH_ACC_ETH_MAC_BCAST_MCAST_BIT ( 1)
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Default values
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#define IX_ETH_ACC_TX_CNTRL1_DEFAULT (IX_ETH_ACC_TX_CNTRL1_TX_EN | \
|
||||
IX_ETH_ACC_TX_CNTRL1_RETRY | \
|
||||
IX_ETH_ACC_TX_CNTRL1_FCS_EN | \
|
||||
IX_ETH_ACC_TX_CNTRL1_2DEFER | \
|
||||
IX_ETH_ACC_TX_CNTRL1_PAD_EN)
|
||||
|
||||
#define IX_ETH_ACC_TX_MAX_RETRIES_DEFAULT 0x0f
|
||||
|
||||
#define IX_ETH_ACC_RX_CNTRL1_DEFAULT (IX_ETH_ACC_RX_CNTRL1_CRC_EN \
|
||||
| IX_ETH_ACC_RX_CNTRL1_RX_EN)
|
||||
|
||||
#define IX_ETH_ACC_RX_CNTRL2_DEFAULT 0x0
|
||||
|
||||
/* Thresholds determined by NPE firmware FS */
|
||||
#define IX_ETH_ACC_MAC_THRESH_P_EMPTY_DEFAULT 0x12
|
||||
#define IX_ETH_ACC_MAC_THRESH_P_FULL_DEFAULT 0x30
|
||||
|
||||
/* Number of bytes that must be in the tx fifo before
|
||||
transmission commences*/
|
||||
#define IX_ETH_ACC_MAC_BUF_SIZE_TX_DEFAULT 0x8
|
||||
|
||||
/* One-part deferral values */
|
||||
#define IX_ETH_ACC_MAC_TX_DEFER_DEFAULT 0x15
|
||||
#define IX_ETH_ACC_MAC_RX_DEFER_DEFAULT 0x16
|
||||
|
||||
/* Two-part deferral values... */
|
||||
#define IX_ETH_ACC_MAC_TX_TWO_DEFER_1_DEFAULT 0x08
|
||||
#define IX_ETH_ACC_MAC_TX_TWO_DEFER_2_DEFAULT 0x07
|
||||
|
||||
/* This value applies to MII */
|
||||
#define IX_ETH_ACC_MAC_SLOT_TIME_DEFAULT 0x80
|
||||
|
||||
/* This value applies to RMII */
|
||||
#define IX_ETH_ACC_MAC_SLOT_TIME_RMII_DEFAULT 0xFF
|
||||
|
||||
#define IX_ETH_ACC_MAC_ADDR_MASK_DEFAULT 0xFF
|
||||
|
||||
#define IX_ETH_ACC_MAC_INT_CLK_THRESH_DEFAULT 0x1
|
||||
/*The following is a value chosen at random*/
|
||||
#define IX_ETH_ACC_RANDOM_SEED_DEFAULT 0x8
|
||||
|
||||
/*By default we must configure the MAC to generate the
|
||||
MDC clock*/
|
||||
#define IX_ETH_ACC_CORE_DEFAULT (IX_ETH_ACC_CORE_MDC_EN)
|
||||
|
||||
#define IXP425_ETH_ACC_MAX_PHY 2
|
||||
#define IXP425_ETH_ACC_MAX_AN_ENTRIES 20
|
||||
#define IX_ETH_ACC_MAC_RESET_DELAY 1
|
||||
|
||||
#define IX_ETH_ACC_MAC_ALL_BITS_SET 0xFF
|
||||
|
||||
#define IX_ETH_ACC_MAC_MSGID_SHL 24
|
||||
|
||||
#define IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS 20
|
||||
#define IX_ETH_ACC_PORT_DISABLE_DELAY_COUNT 200 /* 4 seconds timeout */
|
||||
#define IX_ETH_ACC_PORT_DISABLE_RETRY_COUNT 3
|
||||
#define IX_ETH_ACC_MIB_STATS_DELAY_MSECS 2000 /* 2 seconds delay for ethernet stats */
|
||||
|
||||
/*Register access macros*/
|
||||
#if (CPU == SIMSPARCSOLARIS)
|
||||
extern void registerWriteStub (UINT32 base, UINT32 offset, UINT32 val);
|
||||
extern UINT32 registerReadStub (UINT32 base, UINT32 offset);
|
||||
|
||||
#define REG_WRITE(b,o,v) registerWriteStub(b, o, v)
|
||||
#define REG_READ(b,o,v) do { v = registerReadStub(b, o); } while (0)
|
||||
#else
|
||||
#define REG_WRITE(b,o,v) IX_OSAL_WRITE_LONG((volatile UINT32 *)(b + o), v)
|
||||
#define REG_READ(b,o,v) (v = IX_OSAL_READ_LONG((volatile UINT32 *)(b + o)))
|
||||
|
||||
#endif
|
||||
|
||||
void ixEthAccMacUnload(void);
|
||||
IxEthAccStatus ixEthAccMacMemInit(void);
|
||||
|
||||
/* MAC core loopback */
|
||||
IxEthAccStatus ixEthAccPortLoopbackEnable(IxEthAccPortId portId);
|
||||
IxEthAccStatus ixEthAccPortLoopbackDisable(IxEthAccPortId portId);
|
||||
|
||||
/* MAC core traffic control */
|
||||
IxEthAccStatus ixEthAccPortTxEnablePriv(IxEthAccPortId portId);
|
||||
IxEthAccStatus ixEthAccPortTxDisablePriv(IxEthAccPortId portId);
|
||||
IxEthAccStatus ixEthAccPortRxEnablePriv(IxEthAccPortId portId);
|
||||
IxEthAccStatus ixEthAccPortRxDisablePriv(IxEthAccPortId portId);
|
||||
IxEthAccStatus ixEthAccPortMacResetPriv(IxEthAccPortId portId);
|
||||
|
||||
/* NPE software loopback */
|
||||
IxEthAccStatus ixEthAccNpeLoopbackDisablePriv(IxEthAccPortId portId);
|
||||
IxEthAccStatus ixEthAccNpeLoopbackEnablePriv(IxEthAccPortId portId);
|
||||
|
||||
#endif /*IxEthAccMac_p_H*/
|
||||
|
97
cpu/ixp/npe/include/IxEthAccMii_p.h
Normal file
97
cpu/ixp/npe/include/IxEthAccMii_p.h
Normal file
@ -0,0 +1,97 @@
|
||||
/**
|
||||
* @file IxEthAccMii_p.h
|
||||
*
|
||||
* @author Intel Corporation
|
||||
* @date
|
||||
*
|
||||
* @brief MII Header file
|
||||
*
|
||||
* Design Notes:
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
#ifndef IxEthAccMii_p_H
|
||||
#define IxEthAccMii_p_H
|
||||
|
||||
/* MII definitions - these have been verified against the LXT971 and LXT972 PHYs*/
|
||||
|
||||
#define IXP425_ETH_ACC_MII_MAX_REG 32 /* max register per phy */
|
||||
|
||||
#define IX_ETH_ACC_MII_REG_SHL 16
|
||||
#define IX_ETH_ACC_MII_ADDR_SHL 21
|
||||
|
||||
/* Definitions for MII access routines*/
|
||||
|
||||
#define IX_ETH_ACC_MII_GO BIT(31)
|
||||
#define IX_ETH_ACC_MII_WRITE BIT(26)
|
||||
#define IX_ETH_ACC_MII_TIMEOUT_10TH_SECS 5
|
||||
#define IX_ETH_ACC_MII_10TH_SEC_IN_MILLIS 100
|
||||
#define IX_ETH_ACC_MII_READ_FAIL BIT(31)
|
||||
|
||||
#define IX_ETH_ACC_MII_PHY_DEF_DELAY 300 /* max delay before link up, etc. */
|
||||
#define IX_ETH_ACC_MII_PHY_NO_DELAY 0x0 /* do not delay */
|
||||
#define IX_ETH_ACC_MII_PHY_NULL 0xff /* PHY is not present */
|
||||
#define IX_ETH_ACC_MII_PHY_DEF_ADDR 0x0 /* default PHY's logical address */
|
||||
|
||||
#ifndef IX_ETH_ACC_MII_MONITOR_DELAY
|
||||
# define IX_ETH_ACC_MII_MONITOR_DELAY 0x5 /* in seconds */
|
||||
#endif
|
||||
|
||||
/* Register definition */
|
||||
|
||||
#define IX_ETH_ACC_MII_CTRL_REG 0x0 /* Control Register */
|
||||
#define IX_ETH_ACC_MII_STAT_REG 0x1 /* Status Register */
|
||||
#define IX_ETH_ACC_MII_PHY_ID1_REG 0x2 /* PHY identifier 1 Register */
|
||||
#define IX_ETH_ACC_MII_PHY_ID2_REG 0x3 /* PHY identifier 2 Register */
|
||||
#define IX_ETH_ACC_MII_AN_ADS_REG 0x4 /* Auto-Negotiation */
|
||||
/* Advertisement Register */
|
||||
#define IX_ETH_ACC_MII_AN_PRTN_REG 0x5 /* Auto-Negotiation */
|
||||
/* partner ability Register */
|
||||
#define IX_ETH_ACC_MII_AN_EXP_REG 0x6 /* Auto-Negotiation */
|
||||
/* Expansion Register */
|
||||
#define IX_ETH_ACC_MII_AN_NEXT_REG 0x7 /* Auto-Negotiation */
|
||||
/* next-page transmit Register */
|
||||
|
||||
IxEthAccStatus ixEthAccMdioShow (void);
|
||||
IxEthAccStatus ixEthAccMiiInit(void);
|
||||
void ixEthAccMiiUnload(void);
|
||||
|
||||
#endif /*IxEthAccMii_p_H*/
|
137
cpu/ixp/npe/include/IxEthAccQueueAssign_p.h
Normal file
137
cpu/ixp/npe/include/IxEthAccQueueAssign_p.h
Normal file
@ -0,0 +1,137 @@
|
||||
/**
|
||||
* @file IxEthAccQueueAssign_p.h
|
||||
*
|
||||
* @author Intel Corporation
|
||||
* @date 06-Mar-2002
|
||||
*
|
||||
* @brief Mapping from QMgr Q's to internal assignment
|
||||
*
|
||||
* Design Notes:
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup IxEthAccPri
|
||||
*@{
|
||||
*/
|
||||
|
||||
/*
|
||||
* Os/System dependancies.
|
||||
*/
|
||||
#include "IxOsal.h"
|
||||
|
||||
/*
|
||||
* Intermodule dependancies
|
||||
*/
|
||||
#include "IxQMgr.h"
|
||||
#include "IxQueueAssignments.h"
|
||||
|
||||
/* Check range of Q's assigned to this component. */
|
||||
#if IX_ETH_ACC_RX_FRAME_ETH_Q >= (IX_QMGR_MIN_QUEUPP_QID ) | \
|
||||
IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q >= (IX_QMGR_MIN_QUEUPP_QID) | \
|
||||
IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q >= (IX_QMGR_MIN_QUEUPP_QID) | \
|
||||
IX_ETH_ACC_TX_FRAME_ENET0_Q >= (IX_QMGR_MIN_QUEUPP_QID) | \
|
||||
IX_ETH_ACC_TX_FRAME_ENET1_Q >= (IX_QMGR_MIN_QUEUPP_QID) | \
|
||||
IX_ETH_ACC_TX_FRAME_DONE_ETH_Q >= (IX_QMGR_MIN_QUEUPP_QID)
|
||||
#error "Not all Ethernet Access Queues are betweem 1-31, requires full functionalty Q's unless otherwise validated "
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
* @typedef IxEthAccQregInfo
|
||||
*
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
IxQMgrQId qId;
|
||||
char *qName;
|
||||
IxQMgrCallback qCallback;
|
||||
IxQMgrCallbackId callbackTag;
|
||||
IxQMgrQSizeInWords qSize;
|
||||
IxQMgrQEntrySizeInWords qWords;
|
||||
BOOL qNotificationEnableAtStartup;
|
||||
IxQMgrSourceId qConditionSource;
|
||||
IxQMgrWMLevel AlmostEmptyThreshold;
|
||||
IxQMgrWMLevel AlmostFullThreshold;
|
||||
|
||||
} IxEthAccQregInfo;
|
||||
|
||||
/*
|
||||
* Prototypes for all QM callbacks.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Rx Callbacks
|
||||
*/
|
||||
IX_ETH_ACC_PUBLIC
|
||||
void ixEthRxFrameQMCallback(IxQMgrQId, IxQMgrCallbackId);
|
||||
|
||||
IX_ETH_ACC_PUBLIC
|
||||
void ixEthRxMultiBufferQMCallback(IxQMgrQId, IxQMgrCallbackId);
|
||||
|
||||
IX_ETH_ACC_PUBLIC
|
||||
void ixEthRxFreeQMCallback(IxQMgrQId, IxQMgrCallbackId);
|
||||
|
||||
/*
|
||||
* Tx Callback.
|
||||
*/
|
||||
IX_ETH_ACC_PUBLIC
|
||||
void ixEthTxFrameQMCallback(IxQMgrQId, IxQMgrCallbackId);
|
||||
|
||||
IX_ETH_ACC_PUBLIC
|
||||
void ixEthTxFrameDoneQMCallback(IxQMgrQId, IxQMgrCallbackId );
|
||||
|
||||
|
||||
#define IX_ETH_ACC_QM_QUEUE_DISPATCH_PRIORITY (IX_QMGR_Q_PRIORITY_0) /* Highest priority */
|
||||
|
||||
/*
|
||||
* Queue watermarks
|
||||
*/
|
||||
#define IX_ETH_ACC_RX_FRAME_ETH_Q_SOURCE (IX_QMGR_Q_SOURCE_ID_NOT_E )
|
||||
#define IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q_SOURCE (IX_QMGR_Q_SOURCE_ID_E )
|
||||
#define IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q_SOURCE (IX_QMGR_Q_SOURCE_ID_E )
|
||||
#define IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q_SOURCE (IX_QMGR_Q_SOURCE_ID_E )
|
||||
#define IX_ETH_ACC_TX_FRAME_ENET0_Q_SOURCE (IX_QMGR_Q_SOURCE_ID_E )
|
||||
#define IX_ETH_ACC_TX_FRAME_ENET1_Q_SOURCE (IX_QMGR_Q_SOURCE_ID_E )
|
||||
#define IX_ETH_ACC_TX_FRAME_ENET2_Q_SOURCE (IX_QMGR_Q_SOURCE_ID_E )
|
||||
#define IX_ETH_ACC_TX_FRAME_DONE_ETH_Q_SOURCE (IX_QMGR_Q_SOURCE_ID_NOT_E )
|
325
cpu/ixp/npe/include/IxEthAcc_p.h
Normal file
325
cpu/ixp/npe/include/IxEthAcc_p.h
Normal file
@ -0,0 +1,325 @@
|
||||
/**
|
||||
* @file IxEthAcc_p.h
|
||||
*
|
||||
* @author Intel Corporation
|
||||
* @date 12-Feb-2002
|
||||
*
|
||||
* @brief Internal Header file for IXP425 Ethernet Access component.
|
||||
*
|
||||
* Design Notes:
|
||||
*
|
||||
*
|
||||
* @par
|
||||
* IXP400 SW Release version 2.0
|
||||
*
|
||||
* -- Copyright Notice --
|
||||
*
|
||||
* @par
|
||||
* Copyright 2001-2005, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
*
|
||||
* @par
|
||||
* -- End of Copyright Notice --
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup IxEthAccPri
|
||||
*@{
|
||||
*/
|
||||
|
||||
#ifndef IxEthAcc_p_H
|
||||
#define IxEthAcc_p_H
|
||||
|
||||
/*
|
||||
* Os/System dependancies.
|
||||
*/
|
||||
#include "IxOsal.h"
|
||||
|
||||
/*
|
||||
* Intermodule dependancies
|
||||
*/
|
||||
#include "IxNpeDl.h"
|
||||
#include "IxQMgr.h"
|
||||
|
||||
#include "IxEthNpe.h"
|
||||
|
||||
/*
|
||||
* Intra module dependancies
|
||||
*/
|
||||
|
||||
#include "IxEthAccDataPlane_p.h"
|
||||
#include "IxEthAccMac_p.h"
|
||||
|
||||
|
||||
#define INLINE __inline__
|
||||
|
||||
#ifdef NDEBUG
|
||||
|
||||
#define IX_ETH_ACC_PRIVATE static
|
||||
|
||||
#else
|
||||
|
||||
#define IX_ETH_ACC_PRIVATE
|
||||
|
||||
#endif /* ndef NDEBUG */
|
||||
|
||||
#define IX_ETH_ACC_PUBLIC
|
||||
|
||||
|
||||
#define IX_ETH_ACC_IS_PORT_VALID(port) ((port) < IX_ETH_ACC_NUMBER_OF_PORTS ? TRUE : FALSE )
|
||||
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define IX_ETH_ACC_FATAL_LOG(a,b,c,d,e,f,g) { ixOsalLog ( IX_OSAL_LOG_LVL_FATAL,IX_OSAL_LOG_DEV_STDOUT,a,b,c,d,e,f,g);}
|
||||
#define IX_ETH_ACC_WARNING_LOG(a,b,c,d,e,f,g) { ixOsalLog ( IX_OSAL_LOG_LVL_WARNING,IX_OSAL_LOG_DEV_STDOUT,a,b,c,d,e,f,g);}
|
||||
#define IX_ETH_ACC_DEBUG_LOG(a,b,c,d,e,f,g) { ixOsalLog ( IX_OSAL_LOG_LVL_FATAL,IX_OSAL_LOG_DEV_STDOUT,a,b,c,d,e,f,g);}
|
||||
#else
|
||||
#define IX_ETH_ACC_FATAL_LOG(a,b,c,d,e,f,g) { ixOsalLog ( IX_OSAL_LOG_LVL_FATAL,IX_OSAL_LOG_DEV_STDOUT,a,b,c,d,e,f,g);}
|
||||
#define IX_ETH_ACC_WARNING_LOG(a,b,c,d,e,f,g) { ixOsalLog ( IX_OSAL_LOG_LVL_WARNING,IX_OSAL_LOG_DEV_STDOUT,a,b,c,d,e,f,g);}
|
||||
#define IX_ETH_ACC_DEBUG_LOG(a,b,c,d,e,f,g) {}
|
||||
#endif
|
||||
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccInitDataPlane(void);
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccQMgrQueuesConfig(void);
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccQMgrRxCallbacksRegister(IxQMgrCallback ixQMgrCallback);
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccSingleEthNpeCheck(IxEthAccPortId portId);
|
||||
IX_ETH_ACC_PUBLIC void ixEthAccQMgrRxQEntryGet(UINT32 *numRxQueueEntries);
|
||||
|
||||
/* prototypes for the private control plane functions (used by the control interface wrapper) */
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccPortEnablePriv(IxEthAccPortId portId);
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccPortDisablePriv(IxEthAccPortId portId);
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccPortEnabledQueryPriv(IxEthAccPortId portId, BOOL *enabled);
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccPortPromiscuousModeClearPriv(IxEthAccPortId portId);
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccPortPromiscuousModeSetPriv(IxEthAccPortId portId);
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccPortUnicastMacAddressSetPriv(IxEthAccPortId portId, IxEthAccMacAddr *macAddr);
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccPortUnicastMacAddressGetPriv(IxEthAccPortId portId, IxEthAccMacAddr *macAddr);
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccPortMulticastAddressJoinPriv(IxEthAccPortId portId, IxEthAccMacAddr *macAddr);
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccPortMulticastAddressJoinAllPriv(IxEthAccPortId portId);
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccPortMulticastAddressLeavePriv(IxEthAccPortId portId, IxEthAccMacAddr *macAddr);
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccPortMulticastAddressLeaveAllPriv(IxEthAccPortId portId);
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccPortUnicastAddressShowPriv(IxEthAccPortId portId);
|
||||
IX_ETH_ACC_PUBLIC void ixEthAccPortMulticastAddressShowPriv(IxEthAccPortId portId);
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccPortDuplexModeSetPriv(IxEthAccPortId portId, IxEthAccDuplexMode mode);
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccPortDuplexModeGetPriv(IxEthAccPortId portId, IxEthAccDuplexMode *mode);
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccPortTxFrameAppendPaddingEnablePriv(IxEthAccPortId portId);
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccPortTxFrameAppendPaddingDisablePriv(IxEthAccPortId portId);
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccPortTxFrameAppendFCSEnablePriv(IxEthAccPortId portId);
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccPortTxFrameAppendFCSDisablePriv(IxEthAccPortId portId);
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccPortRxFrameAppendFCSEnablePriv(IxEthAccPortId portId);
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccPortRxFrameAppendFCSDisablePriv(IxEthAccPortId portId);
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccTxSchedulingDisciplineSetPriv(IxEthAccPortId portId, IxEthAccSchedulerDiscipline sched);
|
||||
IX_ETH_ACC_PUBLIC IxEthAccStatus ixEthAccRxSchedulingDisciplineSetPriv(IxEthAccSchedulerDiscipline sched);
|
||||
|
||||
/**
|
||||
* @struct ixEthAccRxDataStats
|
||||
* @brief Stats data structures for data path. - Not obtained from h/w
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UINT32 rxFrameClientCallback;
|
||||
UINT32 rxFreeRepOK;
|
||||
UINT32 rxFreeRepDelayed;
|
||||
UINT32 rxFreeRepFromSwQOK;
|
||||
UINT32 rxFreeRepFromSwQDelayed;
|
||||
UINT32 rxFreeLateNotificationEnabled;
|
||||
UINT32 rxFreeLowCallback;
|
||||
UINT32 rxFreeOverflow;
|
||||
UINT32 rxFreeLock;
|
||||
UINT32 rxDuringDisable;
|
||||
UINT32 rxSwQDuringDisable;
|
||||
UINT32 rxUnlearnedMacAddress;
|
||||
UINT32 rxPriority[IX_ETH_ACC_TX_PRIORITY_7 + 1];
|
||||
UINT32 rxUnexpectedError;
|
||||
UINT32 rxFiltered;
|
||||
} IxEthAccRxDataStats;
|
||||
|
||||
/**
|
||||
* @struct IxEthAccTxDataStats
|
||||
* @brief Stats data structures for data path. - Not obtained from h/w
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UINT32 txQOK;
|
||||
UINT32 txQDelayed;
|
||||
UINT32 txFromSwQOK;
|
||||
UINT32 txFromSwQDelayed;
|
||||
UINT32 txLowThreshCallback;
|
||||
UINT32 txDoneClientCallback;
|
||||
UINT32 txDoneClientCallbackDisable;
|
||||
UINT32 txOverflow;
|
||||
UINT32 txLock;
|
||||
UINT32 txPriority[IX_ETH_ACC_TX_PRIORITY_7 + 1];
|
||||
UINT32 txLateNotificationEnabled;
|
||||
UINT32 txDoneDuringDisable;
|
||||
UINT32 txDoneSwQDuringDisable;
|
||||
UINT32 txUnexpectedError;
|
||||
} IxEthAccTxDataStats;
|
||||
|
||||
/* port Disable state machine : list of states */
|
||||
typedef enum
|
||||
{
|
||||
/* general port states */
|
||||
DISABLED = 0,
|
||||
ACTIVE,
|
||||
|
||||
/* particular Tx/Rx states */
|
||||
REPLENISH,
|
||||
RECEIVE,
|
||||
TRANSMIT,
|
||||
TRANSMIT_DONE
|
||||
} IxEthAccPortDisableState;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BOOL fullDuplex;
|
||||
BOOL rxFCSAppend;
|
||||
BOOL txFCSAppend;
|
||||
BOOL txPADAppend;
|
||||
BOOL enabled;
|
||||
BOOL promiscuous;
|
||||
BOOL joinAll;
|
||||
IxOsalMutex ackMIBStatsLock;
|
||||
IxOsalMutex ackMIBStatsResetLock;
|
||||
IxOsalMutex MIBStatsGetAccessLock;
|
||||
IxOsalMutex MIBStatsGetResetAccessLock;
|
||||
IxOsalMutex npeLoopbackMessageLock;
|
||||
IxEthAccMacAddr mcastAddrsTable[IX_ETH_ACC_MAX_MULTICAST_ADDRESSES];
|
||||
UINT32 mcastAddrIndex;
|
||||
IX_OSAL_MBUF *portDisableTxMbufPtr;
|
||||
IX_OSAL_MBUF *portDisableRxMbufPtr;
|
||||
|
||||
volatile IxEthAccPortDisableState portDisableState;
|
||||
volatile IxEthAccPortDisableState rxState;
|
||||
volatile IxEthAccPortDisableState txState;
|
||||
|
||||
BOOL initDone;
|
||||
BOOL macInitialised;
|
||||
} IxEthAccMacState;
|
||||
|
||||
/**
|
||||
* @struct IxEthAccRxInfo
|
||||
* @brief System-wide data structures associated with the data plane.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
IxQMgrQId higherPriorityQueue[IX_QMGR_MAX_NUM_QUEUES]; /**< higher priority queue list */
|
||||
IxEthAccSchedulerDiscipline schDiscipline; /**< Receive Xscale QoS type */
|
||||
} IxEthAccInfo;
|
||||
|
||||
/**
|
||||
* @struct IxEthAccRxDataInfo
|
||||
* @brief Per Port data structures associated with the receive data plane.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
IxQMgrQId rxFreeQueue; /**< rxFree Queue for this port */
|
||||
IxEthAccPortRxCallback rxCallbackFn;
|
||||
UINT32 rxCallbackTag;
|
||||
IxEthAccDataPlaneQList freeBufferList;
|
||||
IxEthAccPortMultiBufferRxCallback rxMultiBufferCallbackFn;
|
||||
UINT32 rxMultiBufferCallbackTag;
|
||||
BOOL rxMultiBufferCallbackInUse;
|
||||
IxEthAccRxDataStats stats; /**< Receive s/w stats */
|
||||
} IxEthAccRxDataInfo;
|
||||
|
||||
/**
|
||||
* @struct IxEthAccTxDataInfo
|
||||
* @brief Per Port data structures associated with the transmit data plane.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
IxEthAccPortTxDoneCallback txBufferDoneCallbackFn;
|
||||
UINT32 txCallbackTag;
|
||||
IxEthAccDataPlaneQList txQ[IX_ETH_ACC_NUM_TX_PRIORITIES]; /**< Transmit Q */
|
||||
IxEthAccSchedulerDiscipline schDiscipline; /**< Transmit Xscale QoS */
|
||||
IxQMgrQId txQueue; /**< txQueue for this port */
|
||||
IxEthAccTxDataStats stats; /**< Transmit s/w stats */
|
||||
} IxEthAccTxDataInfo;
|
||||
|
||||
|
||||
/**
|
||||
* @struct IxEthAccPortDataInfo
|
||||
* @brief Per Port data structures associated with the port data plane.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
BOOL portInitialized;
|
||||
UINT32 npeId; /**< NpeId for this port */
|
||||
IxEthAccTxDataInfo ixEthAccTxData; /**< Transmit data control structures */
|
||||
IxEthAccRxDataInfo ixEthAccRxData; /**< Recieve data control structures */
|
||||
} IxEthAccPortDataInfo;
|
||||
|
||||
extern IxEthAccPortDataInfo ixEthAccPortData[];
|
||||
#define IX_ETH_IS_PORT_INITIALIZED(port) (ixEthAccPortData[port].portInitialized)
|
||||
|
||||
extern BOOL ixEthAccServiceInit;
|
||||
#define IX_ETH_ACC_IS_SERVICE_INITIALIZED() (ixEthAccServiceInit == TRUE )
|
||||
|
||||
/*
|
||||
* Maximum number of frames to consume from the Rx Frame Q.
|
||||
*/
|
||||
|
||||
#define IX_ETH_ACC_MAX_RX_FRAME_CONSUME_PER_CALLBACK (128)
|
||||
|
||||
/*
|
||||
* Max number of times to load the Rx Free Q from callback.
|
||||
*/
|
||||
#define IX_ETH_ACC_MAX_RX_FREE_BUFFERS_LOAD (256) /* Set greater than depth of h/w Q + drain time at line rate */
|
||||
|
||||
/*
|
||||
* Max number of times to read from the Tx Done Q in one sitting.
|
||||
*/
|
||||
|
||||
#define IX_ETH_ACC_MAX_TX_FRAME_DONE_CONSUME_PER_CALLBACK (256)
|
||||
|
||||
/*
|
||||
* Max number of times to take buffers from S/w queues and write them to the H/w Tx
|
||||
* queues on receipt of a Tx low threshold callback
|
||||
*/
|
||||
|
||||
#define IX_ETH_ACC_MAX_TX_FRAME_TX_CONSUME_PER_CALLBACK (16)
|
||||
|
||||
|
||||
#define IX_ETH_ACC_FLUSH_CACHE(addr,size) IX_OSAL_CACHE_FLUSH((addr),(size))
|
||||
#define IX_ETH_ACC_INVALIDATE_CACHE(addr,size) IX_OSAL_CACHE_INVALIDATE((addr),(size))
|
||||
|
||||
|
||||
#define IX_ETH_ACC_MEMSET(start,value,size) memset(start,value,size)
|
||||
|
||||
#endif /* ndef IxEthAcc_p_H */
|
||||
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user