9
0
Fork 0
This commit is contained in:
Jon Loeliger 2006-06-07 08:49:38 -05:00
commit 72ed528a94
225 changed files with 75292 additions and 274 deletions

View File

@ -2,6 +2,80 @@
Changes since U-Boot 1.1.4: 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. * Fix watchdog issues for ColdFire boards.
* Add M5271EVB board support. * Add M5271EVB board support.

View File

@ -283,6 +283,7 @@ Stefan Roese <sr@denx.de>
ebony PPC440GP ebony PPC440GP
ocotea PPC440GX ocotea PPC440GX
p3p440 PPC440GP p3p440 PPC440GP
pcs440ep PPC440EP
sycamore PPC405GPr sycamore PPC405GPr
walnut PPC405GP walnut PPC405GP
yellowstone PPC440GR yellowstone PPC440GR
@ -434,6 +435,11 @@ Dave Peverley <dpeverley@mpc-data.co.uk>
omap730p2 ARM926EJS omap730p2 ARM926EJS
Stefan Roese <sr@denx.de>
ixdpg425 xscale
pdnb3 xscale
Robert Schwebel <r.schwebel@pengutronix.de> Robert Schwebel <r.schwebel@pengutronix.de>
csb226 xscale csb226 xscale

12
MAKEALL
View File

@ -71,11 +71,11 @@ LIST_4xx=" \
HH405 HUB405 JSE KAREF \ HH405 HUB405 JSE KAREF \
luan METROBOX MIP405 MIP405T \ luan METROBOX MIP405 MIP405T \
ML2 ml300 ocotea OCRTC \ ML2 ml300 ocotea OCRTC \
ORSG p3p440 PCI405 PIP405 \ ORSG p3p440 PCI405 pcs440ep \
PLU405 PMC405 PPChameleonEVB sbc405 \ PIP405 PLU405 PMC405 PPChameleonEVB \
VOH405 VOM405 W7OLMC W7OLMG \ sbc405 VOH405 VOM405 W7OLMC \
walnut WUH405 XPEDITE1K yellowstone \ W7OLMG walnut WUH405 XPEDITE1K \
yosemite \ yellowstone yosemite \
" "
######################################################################### #########################################################################
@ -209,7 +209,7 @@ LIST_pxa=" \
zylonite \ zylonite \
" "
LIST_ixp="ixdp425" LIST_ixp="ixdp425 ixdpg425 pdnb3"
LIST_arm=" \ LIST_arm=" \

View File

@ -759,7 +759,8 @@ TQM850M_config \
TQM855M_config \ TQM855M_config \
TQM860M_config \ TQM860M_config \
TQM862M_config \ TQM862M_config \
TQM866M_config: unconfig TQM866M_config \
virtlab2_config: unconfig
@ >include/config.h @ >include/config.h
@[ -z "$(findstring _LCD,$@)" ] || \ @[ -z "$(findstring _LCD,$@)" ] || \
{ echo "#define CONFIG_LCD" >>include/config.h ; \ { echo "#define CONFIG_LCD" >>include/config.h ; \
@ -921,6 +922,9 @@ p3p440_config: unconfig
PCI405_config: unconfig PCI405_config: unconfig
@./mkconfig $(@:_config=) ppc ppc4xx pci405 esd @./mkconfig $(@:_config=) ppc ppc4xx pci405 esd
pcs440ep_config: unconfig
@./mkconfig $(@:_config=) ppc ppc4xx pcs440ep
PIP405_config: unconfig PIP405_config: unconfig
@./mkconfig $(@:_config=) ppc ppc4xx pip405 mpl @./mkconfig $(@:_config=) ppc ppc4xx pip405 mpl
@ -1718,12 +1722,18 @@ innokom_config : unconfig
ixdp425_config : unconfig ixdp425_config : unconfig
@./mkconfig $(@:_config=) arm ixp ixdp425 @./mkconfig $(@:_config=) arm ixp ixdp425
ixdpg425_config : unconfig
@./mkconfig $(@:_config=) arm ixp ixdp425
lubbock_config : unconfig lubbock_config : unconfig
@./mkconfig $(@:_config=) arm pxa lubbock @./mkconfig $(@:_config=) arm pxa lubbock
logodl_config : unconfig logodl_config : unconfig
@./mkconfig $(@:_config=) arm pxa logodl @./mkconfig $(@:_config=) arm pxa logodl
pdnb3_config : unconfig
@./mkconfig $(@:_config=) arm ixp pdnb3 prodrive
pxa255_idp_config: unconfig pxa255_idp_config: unconfig
@./mkconfig $(@:_config=) arm pxa pxa255_idp @./mkconfig $(@:_config=) arm pxa pxa255_idp

View File

@ -79,8 +79,8 @@ int board_early_init_f(void)
out32(GPIO1_ISR2L, in32(GPIO1_ISR2L) | 0x00010000); out32(GPIO1_ISR2L, in32(GPIO1_ISR2L) | 0x00010000);
/* external interrupts IRQ0...3 */ /* external interrupts IRQ0...3 */
out32(GPIO1_TCR, in32(GPIO1_TCR) & ~0x0f000000); out32(GPIO1_TCR, in32(GPIO1_TCR) & ~0x00f00000);
out32(GPIO1_TSRL, in32(GPIO1_TSRL) & ~0x00005500); out32(GPIO1_TSRL, in32(GPIO1_TSRL) & ~0x0000ff00);
out32(GPIO1_ISR1L, in32(GPIO1_ISR1L) | 0x00005500); out32(GPIO1_ISR1L, in32(GPIO1_ISR1L) | 0x00005500);
#if 0 /* test-only */ #if 0 /* test-only */

View File

@ -79,8 +79,8 @@ int board_early_init_f(void)
out32(GPIO1_ISR2L, in32(GPIO1_ISR2L) | 0x00010000); out32(GPIO1_ISR2L, in32(GPIO1_ISR2L) | 0x00010000);
/* external interrupts IRQ0...3 */ /* external interrupts IRQ0...3 */
out32(GPIO1_TCR, in32(GPIO1_TCR) & ~0x0f000000); out32(GPIO1_TCR, in32(GPIO1_TCR) & ~0x00f00000);
out32(GPIO1_TSRL, in32(GPIO1_TSRL) & ~0x00005500); out32(GPIO1_TSRL, in32(GPIO1_TSRL) & ~0x0000ff00);
out32(GPIO1_ISR1L, in32(GPIO1_ISR1L) | 0x00005500); out32(GPIO1_ISR1L, in32(GPIO1_ISR1L) | 0x00005500);
/*setup USB 2.0 */ /*setup USB 2.0 */

View File

@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk
LIB = lib$(BOARD).a LIB = lib$(BOARD).a
OBJS := ixdp425.o flash.o OBJS := ixdp425.o
$(LIB): $(OBJS) $(SOBJS) $(LIB): $(OBJS) $(SOBJS)
$(AR) crv $@ $^ $(AR) crv $@ $^

View File

@ -1,2 +1,4 @@
#TEXT_BASE = 0x00100000
TEXT_BASE = 0x00f80000 TEXT_BASE = 0x00f80000
# include NPE ethernet driver
BOARDLIBS = cpu/ixp/npe/libnpe.a

View File

@ -1,4 +1,7 @@
/* /*
* (C) Copyright 2006
* Stefan Roese, DENX Software Engineering, sr@denx.de.
*
* (C) Copyright 2002 * (C) Copyright 2002
* Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
* *
@ -25,24 +28,21 @@
* MA 02111-1307 USA * MA 02111-1307 USA
*/ */
#include <asm/arch/ixp425.h>
#include <common.h> #include <common.h>
#include <command.h>
#include <malloc.h>
#include <asm/arch/ixp425.h>
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
/* /*
* Miscelaneous platform dependent initialisations * Miscelaneous platform dependent initialisations
*/ */
/**********************************************************/
int board_post_init (void) int board_post_init (void)
{ {
return (0); return (0);
} }
/**********************************************************/
int board_init (void) int board_init (void)
{ {
/* arch number of IXDP */ /* arch number of IXDP */
@ -51,10 +51,58 @@ int board_init (void)
/* adress of boot parameters */ /* adress of boot parameters */
gd->bd->bi_boot_params = 0x00000100; 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; 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) int dram_init (void)
{ {
@ -64,8 +112,7 @@ int dram_init (void)
return (0); return (0);
} }
/**********************************************************/ #if (CONFIG_COMMANDS & CFG_CMD_PCI) || defined(CONFIG_PCI)
extern struct pci_controller hose; extern struct pci_controller hose;
extern void pci_ixp_init(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); pci_ixp_init(&hose);
} }
#endif

View File

@ -53,10 +53,9 @@ long int initdram (int board_type) {
* Check to see if the SDRAM has already been initialized * Check to see if the SDRAM has already been initialized
* by a run control tool * 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 */ /* Initialize DRAM Control Register: DCR */
mbar_writeShort(MCF_SDRAMC_DCR, mbar_writeShort(MCF_SDRAMC_DCR,
MCF_SDRAMC_DCR_RTIM(0x01) MCF_SDRAMC_DCR_RTIM(0x01)
| MCF_SDRAMC_DCR_RC(0x30)); | MCF_SDRAMC_DCR_RC(0x30));
@ -74,7 +73,7 @@ long int initdram (int board_type) {
| MCF_SDRAMC_DACRn_PS(0)); | MCF_SDRAMC_DACRn_PS(0));
/* Initialize DMR0 */ /* Initialize DMR0 */
mbar_writeLong(MCF_SDRAMC_DMR0, mbar_writeLong(MCF_SDRAMC_DMR0,
MCF_SDRAMC_DMRn_BAM_16M MCF_SDRAMC_DMRn_BAM_16M
| MCF_SDRAMC_DMRn_V); | MCF_SDRAMC_DMRn_V);

View File

@ -382,7 +382,7 @@ REG_WATCHDOG:
.word 0xfffec808 .word 0xfffec808
REG_MPU_LOAD_TIMER: REG_MPU_LOAD_TIMER:
.word 0xfffec600 .word 0xfffec504
REG_MPU_CNTL_TIMER: REG_MPU_CNTL_TIMER:
.word 0xfffec500 .word 0xfffec500

View File

@ -41,6 +41,13 @@ _TEXT_BASE:
.globl lowlevel_init .globl lowlevel_init
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* *mask all IRQs by setting all bits in the INTMR default*
@ -59,33 +66,34 @@ lowlevel_init:
str r1, [r0] str r1, [r0]
/*------------------------------------------------------* /*------------------------------------------------------*
* Set up ARM CLM registers (IDLECT2) * * Set up ARM CLM registers (IDLECT2) *
*------------------------------------------------------*/ *------------------------------------------------------*/
ldr r0, REG_ARM_IDLECT2 ldr r0, REG_ARM_IDLECT2
ldr r1, VAL_ARM_IDLECT2 ldr r1, VAL_ARM_IDLECT2
str r1, [r0] str r1, [r0]
/*------------------------------------------------------* /*------------------------------------------------------*
* Set up ARM CLM registers (IDLECT3) * * Set up ARM CLM registers (IDLECT3) *
*------------------------------------------------------*/ *------------------------------------------------------*/
ldr r0, REG_ARM_IDLECT3 ldr r0, REG_ARM_IDLECT3
ldr r1, VAL_ARM_IDLECT3 ldr r1, VAL_ARM_IDLECT3
str r1, [r0] str r1, [r0]
mov r1, #0x01 /* PER_EN bit */
mov r1, #0x01 /* PER_EN bit */
ldr r0, REG_ARM_RSTCT2 ldr r0, REG_ARM_RSTCT2
strh r1, [r0] /* CLKM; Peripheral reset. */ strh r1, [r0] /* CLKM; Peripheral reset. */
/* Set CLKM to Sync-Scalable */ /* Set CLKM to Sync-Scalable */
/* I supposedly need to enable the dsp clock before switching */ mov r1, #0x1000
mov r1, #0x0000
ldr r0, REG_ARM_SYSST ldr r0, REG_ARM_SYSST
strh r1, [r0]
mov r0, #0x400 mov r2, #0
1: 1: cmp r2, #1
subs r0, r0, #0x1 /* wait for any bubbles to finish */ streqh r1, [r0]
add r2, r2, #1
cmp r2, #0x100 /* wait for any bubbles to finish */
bne 1b bne 1b
ldr r1, VAL_ARM_CKCTL ldr r1, VAL_ARM_CKCTL
ldr r0, REG_ARM_CKCTL ldr r0, REG_ARM_CKCTL
strh r1, [r0] strh r1, [r0]
@ -107,17 +115,16 @@ lowlevel_init:
ldr r1, VAL_DPLL1_CTL ldr r1, VAL_DPLL1_CTL
ldr r0, REG_DPLL1_CTL ldr r0, REG_DPLL1_CTL
strh r1, [r0] strh r1, [r0]
ands r1, r1, #0x10 /* Check if PLL is enabled. */ ands r1, r1, #0x10 /* Check if PLL is enabled. */
beq lock_end /* Do not look for lock if BYPASS selected */ beq lock_end /* Do not look for lock if BYPASS selected */
2: 2:
ldrh r1, [r0] ldrh r1, [r0]
ands r1, r1, #0x01 /* Check the LOCK bit.*/ ands r1, r1, #0x01 /* Check the LOCK bit.*/
beq 2b /* loop until bit goes hi. */ beq 2b /* loop until bit goes hi. */
lock_end: lock_end:
/*------------------------------------------------------* /*------------------------------------------------------*
* Turn off the watchdog during init... * * Turn off the watchdog during init... *
*------------------------------------------------------*/ *------------------------------------------------------*/
ldr r0, REG_WATCHDOG ldr r0, REG_WATCHDOG
ldr r1, WATCHDOG_VAL1 ldr r1, WATCHDOG_VAL1
@ -143,30 +150,49 @@ watch2Wait:
tst r1, #0x10 tst r1, #0x10
bne watch2Wait bne watch2Wait
/* Set memory timings corresponding to the new clock speed */ /* Set memory timings corresponding to the new clock speed */
ldr r3, VAL_SDRAM_CONFIG_SDF0
/* Check execution location to determine current execution location /* Check execution location to determine current execution location
* and branch to appropriate initialization code. * and branch to appropriate initialization code.
*/ */
/* Load physical SDRAM base. */ mov r0, #0x10000000 /* Load physical SDRAM base. */
mov r0, #0x10000000 mov r1, pc /* Get current execution location. */
/* Get current execution location. */ cmp r1, r0 /* Compare. */
mov r1, pc bge skip_sdram /* Skip over EMIF-fast initialization if running from SDRAM. */
/* Compare. */
cmp r1, r0 /* identify the device revision, -- TMX or TMP(TMS) */
/* Skip over EMIF-fast initialization if running from SDRAM. */ ldr r0, REG_DEVICE_ID
bge skip_sdram 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. * Delay for SDRAM initialization.
*/ */
mov r3, #0x1800 /* value should be checked */ mov r0, #0x1800 /* value should be checked */
3: 3:
subs r3, r3, #0x1 /* Decrement count */ subs r0, r0, #0x1 /* Decrement count */
bne 3b bne 3b
/* /*
* Set SDRAM control values. Disable refresh before MRS command. * Set SDRAM control values. Disable refresh before MRS command.
*/ */
@ -178,14 +204,15 @@ watch2Wait:
/* config register */ /* config register */
ldr r0, REG_SDRAM_CONFIG ldr r0, REG_SDRAM_CONFIG
ldr r1, SDRAM_CONFIG_VAL str r3, [r0]
str r1, [r0]
/* manual command register */ /* manual command register */
ldr r0, REG_SDRAM_MANUAL_CMD ldr r0, REG_SDRAM_MANUAL_CMD
/* issue set cke high */ /* issue set cke high */
mov r1, #CMD_SDRAM_CKE_SET_HIGH mov r1, #CMD_SDRAM_CKE_SET_HIGH
str r1, [r0] str r1, [r0]
/* issue nop */ /* issue nop */
mov r1, #CMD_SDRAM_NOP mov r1, #CMD_SDRAM_NOP
str r1, [r0] str r1, [r0]
@ -228,25 +255,23 @@ waitMDDR1:
str r1, [r0] str r1, [r0]
/* delay loop */ /* delay loop */
mov r2, #0x0100 mov r0, #0x0100
waitMDDR2: waitMDDR2:
subs r2, r2, #1 subs r0, r0, #1
bne waitMDDR2 bne waitMDDR2
/* /*
* Delay for SDRAM initialization. * Delay for SDRAM initialization.
*/ */
mov r3, #0x1800 mov r0, #0x1800
4: 4:
subs r3, r3, #1 /* Decrement count. */ subs r0, r0, #1 /* Decrement count. */
bne 4b bne 4b
b common_tc b common_tc
skip_sdram: skip_sdram:
ldr r0, REG_SDRAM_CONFIG ldr r0, REG_SDRAM_CONFIG
ldr r1, SDRAM_CONFIG_VAL str r3, [r0]
str r1, [r0]
common_tc: common_tc:
/* slow interface */ /* slow interface */
@ -257,10 +282,15 @@ common_tc:
ldr r1, VAL_TC_EMIFS_CS1_CONFIG ldr r1, VAL_TC_EMIFS_CS1_CONFIG
ldr r0, REG_TC_EMIFS_CS1_CONFIG ldr r0, REG_TC_EMIFS_CS1_CONFIG
str r1, [r0] /* Chip Select 1 */ str r1, [r0] /* Chip Select 1 */
ldr r1, VAL_TC_EMIFS_CS3_CONFIG ldr r1, VAL_TC_EMIFS_CS3_CONFIG
ldr r0, REG_TC_EMIFS_CS3_CONFIG ldr r0, REG_TC_EMIFS_CS3_CONFIG
str r1, [r0] /* Chip Select 3 */ 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 #ifdef CONFIG_H2_OMAP1610
/* inserting additional 2 clock cycle hold time for LAN */ /* inserting additional 2 clock cycle hold time for LAN */
ldr r0, REG_TC_EMIFS_CS1_ADVANCED ldr r0, REG_TC_EMIFS_CS1_ADVANCED
@ -282,8 +312,9 @@ common_tc:
/* the literal pools origin */ /* the literal pools origin */
.ltorg .ltorg
REG_DEVICE_ID: /* 32 bits */
REG_TC_EMIFS_CONFIG: /* 32 bits */ .word 0xfffe2004
REG_TC_EMIFS_CONFIG:
.word 0xfffecc0c .word 0xfffecc0c
REG_TC_EMIFS_CS0_CONFIG: /* 32 bits */ REG_TC_EMIFS_CS0_CONFIG: /* 32 bits */
.word 0xfffecc10 .word 0xfffecc10
@ -293,7 +324,8 @@ REG_TC_EMIFS_CS2_CONFIG: /* 32 bits */
.word 0xfffecc18 .word 0xfffecc18
REG_TC_EMIFS_CS3_CONFIG: /* 32 bits */ REG_TC_EMIFS_CS3_CONFIG: /* 32 bits */
.word 0xfffecc1c .word 0xfffecc1c
REG_TC_EMIFS_DWS: /* 32 bits */
.word 0xfffecc40
#ifdef CONFIG_H2_OMAP1610 #ifdef CONFIG_H2_OMAP1610
REG_TC_EMIFS_CS1_ADVANCED: /* 32 bits */ REG_TC_EMIFS_CS1_ADVANCED: /* 32 bits */
.word 0xfffecc54 .word 0xfffecc54
@ -302,18 +334,17 @@ REG_TC_EMIFS_CS1_ADVANCED: /* 32 bits */
/* MPU clock/reset/power mode control registers */ /* MPU clock/reset/power mode control registers */
REG_ARM_CKCTL: /* 16 bits */ REG_ARM_CKCTL: /* 16 bits */
.word 0xfffece00 .word 0xfffece00
REG_ARM_IDLECT3: /* 16 bits */ REG_ARM_IDLECT3: /* 16 bits */
.word 0xfffece24 .word 0xfffece24
REG_ARM_IDLECT2: /* 16 bits */ REG_ARM_IDLECT2: /* 16 bits */
.word 0xfffece08 .word 0xfffece08
REG_ARM_IDLECT1: /* 16 bits */ REG_ARM_IDLECT1: /* 16 bits */
.word 0xfffece04 .word 0xfffece04
REG_ARM_RSTCT2: /* 16 bits */ REG_ARM_RSTCT2: /* 16 bits */
.word 0xfffece14 .word 0xfffece14
REG_ARM_SYSST: /* 16 bits */ REG_ARM_SYSST: /* 16 bits */
.word 0xfffece18 .word 0xfffece18
/* DPLL control registers */ /* DPLL control registers */
REG_DPLL1_CTL: /* 16 bits */ REG_DPLL1_CTL: /* 16 bits */
.word 0xfffecf00 .word 0xfffecf00
@ -335,6 +366,10 @@ WSPRDOG_VAL2:
counter @8192 rows, 10 ns, 8 burst */ counter @8192 rows, 10 ns, 8 burst */
REG_SDRAM_CONFIG: REG_SDRAM_CONFIG:
.word 0xfffecc20 .word 0xfffecc20
REG_SDRAM_CONFIG2:
.word 0xfffecc3c
REG_TC_EMIFF_DOUBLER: /* 32 bits */
.word 0xfffecc60
/* Operation register */ /* Operation register */
REG_SDRAM_OPERATION: REG_SDRAM_OPERATION:
@ -356,35 +391,47 @@ REG_SDRAM_EMRS1:
REG_DLL_WRT_CONTROL: REG_DLL_WRT_CONTROL:
.word 0xfffecc68 .word 0xfffecc68
DLL_WRT_CONTROL_VAL: DLL_WRT_CONTROL_VAL:
.word 0x03f00002 .word 0x03f00002 /* Phase of 72deg, write offset +31 */
/* URD DLL register */ /* URD DLL register */
REG_DLL_URD_CONTROL: REG_DLL_URD_CONTROL:
.word 0xfffeccc0 .word 0xfffeccc0
DLL_URD_CONTROL_VAL: DLL_URD_CONTROL_VAL:
.word 0x00800002 .word 0x00800002 /* Phase of 72deg, read offset +31 */
/* LRD DLL register */ /* LRD DLL register */
REG_DLL_LRD_CONTROL: REG_DLL_LRD_CONTROL:
.word 0xfffecccc .word 0xfffecccc
DLL_LRD_CONTROL_VAL:
.word 0x00800002 /* read offset +31 */
REG_WATCHDOG: REG_WATCHDOG:
.word 0xfffec808 .word 0xfffec808
WATCHDOG_VAL1:
.word 0x000000f5
WATCHDOG_VAL2:
.word 0x000000a0
REG_MPU_LOAD_TIMER: REG_MPU_LOAD_TIMER:
.word 0xfffec600 .word 0xfffec504
REG_MPU_CNTL_TIMER: REG_MPU_CNTL_TIMER:
.word 0xfffec500 .word 0xfffec500
VAL_MPU_LOAD_TIMER:
.word 0xffffffff
VAL_MPU_CNTL_TIMER:
.word 0xffffffa1
/* 96 MHz Samsung Mobile DDR */ /* 96 MHz Samsung Mobile DDR */
SDRAM_CONFIG_VAL: /* Original setting for TMX device */
.word 0x001200f4 VAL_SDRAM_CONFIG_SDF0:
.word 0x0014e6fe
DLL_LRD_CONTROL_VAL: /* NEW_SYS_FREQ mode (valid only TMP/TMS devices) */
.word 0x00800002 VAL_SDRAM_CONFIG_SDF1:
.word 0x0114e6fe
VAL_ARM_CKCTL: VAL_ARM_CKCTL:
.word 0x3000 .word 0x2000 /* was: 0x3000, now use CLK_REF for timer input */
VAL_DPLL1_CTL: VAL_DPLL1_CTL:
.word 0x2830 .word 0x2830
@ -392,11 +439,15 @@ VAL_DPLL1_CTL:
VAL_TC_EMIFS_CS0_CONFIG: VAL_TC_EMIFS_CS0_CONFIG:
.word 0x002130b0 .word 0x002130b0
VAL_TC_EMIFS_CS1_CONFIG: VAL_TC_EMIFS_CS1_CONFIG:
.word 0x00001131 .word 0x00001133
VAL_TC_EMIFS_CS2_CONFIG: VAL_TC_EMIFS_CS2_CONFIG:
.word 0x000055f0 .word 0x000055f0
VAL_TC_EMIFS_CS3_CONFIG: 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 #endif
#ifdef CONFIG_H2_OMAP1610 #ifdef CONFIG_H2_OMAP1610
@ -407,36 +458,20 @@ VAL_TC_EMIFS_CS1_CONFIG:
VAL_TC_EMIFS_CS2_CONFIG: VAL_TC_EMIFS_CS2_CONFIG:
.word 0xf800f22a .word 0xf800f22a
VAL_TC_EMIFS_CS3_CONFIG: VAL_TC_EMIFS_CS3_CONFIG:
.word 0x88011131 .word 0x88013141
VAL_TC_EMIFS_CS1_ADVANCED: VAL_TC_EMIFS_CS1_ADVANCED:
.word 0x00000022 .word 0x00000022
#endif #endif
VAL_TC_EMIFF_SDRAM_CONFIG:
.word 0x010290fc
VAL_TC_EMIFF_MRS:
.word 0x00000027
VAL_ARM_IDLECT1: VAL_ARM_IDLECT1:
.word 0x00000400 .word 0x00000400
VAL_ARM_IDLECT2: VAL_ARM_IDLECT2:
.word 0x00000886 .word 0x00000886
VAL_ARM_IDLECT3: VAL_ARM_IDLECT3:
.word 0x00000015 .word 0x00000015
WATCHDOG_VAL1:
.word 0x000000f5
WATCHDOG_VAL2:
.word 0x000000a0
VAL_MPU_LOAD_TIMER:
.word 0xffffffff
VAL_MPU_CNTL_TIMER:
.word 0xffffffa1
/* command values */ /* command values */
.equ CMD_SDRAM_NOP, 0x00000000 .equ CMD_SDRAM_NOP, 0x00000000
.equ CMD_SDRAM_PRECHARGE, 0x00000001 .equ CMD_SDRAM_PRECHARGE, 0x00000001
.equ CMD_SDRAM_AUTOREFRESH, 0x00000002 .equ CMD_SDRAM_AUTOREFRESH, 0x00000002
.equ CMD_SDRAM_CKE_SET_HIGH, 0x00000007 .equ CMD_SDRAM_CKE_SET_HIGH, 0x00000007

View File

@ -288,3 +288,21 @@ void peripheral_power_enable (void)
*SW_CLOCK_REQUEST |= UART1_48MHZ_ENABLE; *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);
}

View File

@ -317,7 +317,7 @@ REG_WATCHDOG:
.word 0xfffec808 .word 0xfffec808
REG_MPU_LOAD_TIMER: REG_MPU_LOAD_TIMER:
.word 0xfffec600 .word 0xfffec504
REG_MPU_CNTL_TIMER: REG_MPU_CNTL_TIMER:
.word 0xfffec500 .word 0xfffec500

47
board/pcs440ep/Makefile Normal file
View 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
View 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
View 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
View 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
View 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
View 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 = .);
}

View 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);
}

View 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;
}

View 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
#########################################################################

View File

@ -0,0 +1,4 @@
TEXT_BASE = 0x01f00000
# include NPE ethernet driver
BOARDLIBS = cpu/ixp/npe/libnpe.a

View 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
View 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

View 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

View 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 = .;
}

View File

@ -47,8 +47,7 @@ long int initdram (int board_type) {
* Check to see if the SDRAM has already been initialized * Check to see if the SDRAM has already been initialized
* by a run control tool * 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 * Initialize DRAM Control Register: DCR
*/ */
@ -67,7 +66,7 @@ long int initdram (int board_type) {
/* /*
* Initialize DMR0 * Initialize DMR0
*/ */
mbar_writeLong(MCF_SDRAMC_DMR0, mbar_writeLong(MCF_SDRAMC_DMR0,
MCF_SDRAMC_DMRn_BAM_8M MCF_SDRAMC_DMRn_BAM_8M
| MCF_SDRAMC_DMRn_V); | MCF_SDRAMC_DMRn_V);

View File

@ -1,5 +1,5 @@
/* /*
* (C) Copyright 2000-2004 * (C) Copyright 2000-2006
* Wolfgang Denk, DENX Software Engineering, wd@denx.de. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
* *
* See file CREDITS for list of people who contributed to this * See file CREDITS for list of people who contributed to this
@ -124,6 +124,9 @@ int checkboard (void)
break; break;
putc (*s); putc (*s);
} }
#ifdef CONFIG_VIRTLAB2
puts (" (Virtlab2)");
#endif
putc ('\n'); putc ('\n');
return (0); return (0);

View File

@ -1,5 +1,5 @@
/* /*
* (C) Copyright 2000-2004 * (C) Copyright 2000-2006
* Wolfgang Denk, DENX Software Engineering, wd@denx.de. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
* *
* See file CREDITS for list of people who contributed to this * 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 */ /* 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) #if defined(CONFIG_TQM8xxL)
#define PCMCIA_BOARD_MSG "TQM8xxL" #define PCMCIA_BOARD_MSG "TQM8xxL"
@ -1021,6 +1022,183 @@ done:
#endif /* TQM8xxL */ #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 */ /* LWMON Board */

View File

@ -33,6 +33,9 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/arch/hardware.h> #include <asm/arch/hardware.h>
#endif #endif
#ifdef CONFIG_IXP425 /* only valid for IXP425 */
#include <asm/arch/ixp425.h>
#endif
#include <i2c.h> #include <i2c.h>
#if defined(CONFIG_SOFT_I2C) #if defined(CONFIG_SOFT_I2C)

View File

@ -379,13 +379,13 @@ xyzModem_get_hdr(void)
} }
/* Header found, now read the data */ /* 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)); ZM_DEBUG(zm_save(xyz.blk));
if (!res) { if (!res) {
ZM_DEBUG(zm_dump(__LINE__)); ZM_DEBUG(zm_dump(__LINE__));
return xyzModem_timeout; 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)); ZM_DEBUG(zm_save(xyz.cblk));
if (!res) { if (!res) {
ZM_DEBUG(zm_dump(__LINE__)); ZM_DEBUG(zm_dump(__LINE__));
@ -403,14 +403,14 @@ xyzModem_get_hdr(void)
return xyzModem_timeout; 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)); ZM_DEBUG(zm_save(xyz.crc1));
if (!res) { if (!res) {
ZM_DEBUG(zm_dump(__LINE__)); ZM_DEBUG(zm_dump(__LINE__));
return xyzModem_timeout; return xyzModem_timeout;
} }
if (xyz.crc_mode) { 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)); ZM_DEBUG(zm_save(xyz.crc2));
if (!res) { if (!res) {
ZM_DEBUG(zm_dump(__LINE__)); ZM_DEBUG(zm_dump(__LINE__));
@ -450,7 +450,10 @@ xyzModem_get_hdr(void)
int int
xyzModem_stream_open(connection_info_t *info, int *err) 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 retries = xyzModem_MAX_RETRIES;
int crc_retries = xyzModem_MAX_RETRIES_WITH_CRC; int crc_retries = xyzModem_MAX_RETRIES_WITH_CRC;
@ -510,7 +513,7 @@ xyzModem_stream_open(connection_info_t *info, int *err)
/* skip filename */ /* skip filename */
while (*xyz.bufp++); while (*xyz.bufp++);
/* get the length */ /* get the length */
parse_num(xyz.bufp, &xyz.file_length, NULL, " "); parse_num((char *)xyz.bufp, &xyz.file_length, NULL, " ");
#endif #endif
/* The rest of the file name data block quietly discarded */ /* The rest of the file name data block quietly discarded */
xyz.tx_ack = true; xyz.tx_ack = true;

View File

@ -143,14 +143,15 @@ CFLAGS := $(CPPFLAGS) -Wall -Wno-trigraphs
endif endif
endif endif
AFLAGS_DEBUG := -Wa,-gstabs
# turn jbsr into jsr for m68k # turn jbsr into jsr for m68k
ifeq ($(ARCH),m68k) ifeq ($(ARCH),m68k)
ifeq ($(findstring 3.4,$(shell $(CC) --version)),3.4) ifeq ($(findstring 3.4,$(shell $(CC) --version)),3.4)
AFLAGS_DEBUG := -Wa,-gstabs,-S AFLAGS_DEBUG := -Wa,-gstabs,-S
endif endif
else
AFLAGS_DEBUG := -Wa,-gstabs
endif endif
AFLAGS := $(AFLAGS_DEBUG) -D__ASSEMBLY__ $(CPPFLAGS) AFLAGS := $(AFLAGS_DEBUG) -D__ASSEMBLY__ $(CPPFLAGS)
LDFLAGS += -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS) LDFLAGS += -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS)

View File

@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk
LIB = lib$(CPU).a LIB = lib$(CPU).a
START = start.o START = start.o
OBJS = interrupts.o cpu.o OBJS = interrupts.o cpu.o cpuinfo.o
all: .depend $(START) $(LIB) all: .depend $(START) $(LIB)

244
cpu/arm926ejs/cpuinfo.c Normal file
View 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) */

View File

@ -27,7 +27,7 @@ BIG_ENDIAN = y
PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 \ PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 \
-msoft-float -mbig-endian -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 # Supply options according to compiler version

View File

@ -34,10 +34,47 @@
#include <command.h> #include <command.h>
#include <asm/arch/ixp425.h> #include <asm/arch/ixp425.h>
ulong loops_per_jiffy;
#ifdef CONFIG_USE_IRQ #ifdef CONFIG_USE_IRQ
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
#endif #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) int cpu_init (void)
{ {
/* /*
@ -48,7 +85,9 @@ int cpu_init (void)
FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ; FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ;
#endif #endif
#if (CONFIG_COMMANDS & CFG_CMD_PCI) || defined (CONFIG_PCI)
pci_init(); pci_init();
#endif
return 0; return 0;
} }
@ -154,3 +193,25 @@ void pci_init(void)
return; 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 */

View File

@ -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 * (C) Copyright 2002
* Sysgo Real-Time Solutions, GmbH <www.elinos.com> * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Marius Groeger <mgroeger@sysgo.de> * Marius Groeger <mgroeger@sysgo.de>
@ -31,22 +33,85 @@
#include <asm/arch/ixp425.h> #include <asm/arch/ixp425.h>
#ifdef CONFIG_USE_IRQ #ifdef CONFIG_USE_IRQ
/* enable IRQ/FIQ interrupts */ /*
void enable_interrupts (void) * When interrupts are enabled, use timer 2 for time/delay generation...
{ */
#error: interrupts not implemented yet
}
#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 * disable IRQ/FIQ interrupts
* returns true if interrupts had been enabled before we disabled them * 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) void enable_interrupts (void)
{ {
return; return;
@ -55,8 +120,7 @@ int disable_interrupts (void)
{ {
return 0; return 0;
} }
#endif #endif /* #ifdef CONFIG_USE_IRQ */
void bad_mode (void) void bad_mode (void)
{ {
@ -140,19 +204,46 @@ void do_fiq (struct pt_regs *pt_regs)
{ {
printf ("fast interrupt request\n"); printf ("fast interrupt request\n");
show_regs (pt_regs); show_regs (pt_regs);
bad_mode (); printf("IRQ=%08lx FIQ=%08lx\n", *IXP425_ICIH, *IXP425_ICFH);
} }
void do_irq (struct pt_regs *pt_regs) 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"); printf ("interrupt request\n");
show_regs (pt_regs); show_regs (pt_regs);
bad_mode (); bad_mode ();
#endif
} }
int interrupt_init (void) 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 *)&timestamp;
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); return (0);
} }

261
cpu/ixp/npe/IxEthAcc.c Normal file
View 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

File diff suppressed because it is too large Load Diff

View 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;
}

File diff suppressed because it is too large Load Diff

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
View 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(&regval);
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(&regval);
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(&regval);
/*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, &regval);
printf(" Control Register : 0x%4.4x\n", regval);
ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_STAT_REG, &regval);
printf(" Status Register : 0x%4.4x\n", regval);
ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_PHY_ID1_REG, &regval);
printf(" PHY ID1 Register : 0x%4.4x\n", regval);
ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_PHY_ID2_REG, &regval);
printf(" PHY ID2 Register : 0x%4.4x\n", regval);
ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_AN_ADS_REG, &regval);
printf(" Auto Neg ADS Register : 0x%4.4x\n", regval);
ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_AN_PRTN_REG, &regval);
printf(" Auto Neg Partner Ability Register : 0x%4.4x\n", regval);
ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_AN_EXP_REG, &regval);
printf(" Auto Neg Expansion Register : 0x%4.4x\n", regval);
ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_AN_NEXT_REG, &regval);
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(&regval);
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(&regval);
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
View 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;
}

View 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
View 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
View 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);
}

View 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;
}

View 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;
}

View 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;
}
/**
* @}
*/

View 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
View 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
*/

View 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

View 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;
}

View 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
View 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;
}

View 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
View 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

File diff suppressed because it is too large Load Diff

480
cpu/ixp/npe/IxEthDBWiFi.c Normal file
View 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
View 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,
&regval) == 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, &regvalId1);
ixEthAccMiiReadRtn(i, IX_ETH_MII_PHY_ID1_REG, &regvalId1);
ixEthAccMiiReadRtn(i, IX_ETH_MII_PHY_ID2_REG, &regvalId2);
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,
&regval)
== 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,
&regval)
== 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,
&regval);
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,
&regval) != 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, &regval4);
ixEthAccMiiReadRtn(phyAddr, IX_ETH_MII_AN_PRTN_REG, &regval5);
/* 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
View 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
View 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;
}
}

View 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
View 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,
&regVal);
}
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,
&regVal);
}
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, &regVal);
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 ();
}

View 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
View 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
View 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;
}

View 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
View 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;
}

View 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;
}

View 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;
}

View 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
View 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);
}
}

View 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);
}

View 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;
}

View 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);
}

View 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));
}

View 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
View 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, &registerWord);
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, &registerWord);
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, &registerWord);
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, &registerWord);
/* 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++;
}
}

File diff suppressed because it is too large Load Diff

233
cpu/ixp/npe/IxQMgrInit.c Normal file
View 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
View 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
View 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
View 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

View 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
*/

View 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 */
/** @} */

View 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
*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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 */
/** @} */

View 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 */

File diff suppressed because it is too large Load Diff

View 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 */
/**
*@}
*/

View 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*/

View 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*/

View 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 )

View 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