From: Jon Loeliger Date: Fri, 16 Jun 2006 02:56:28 +0000 (-0500) Subject: Merge branch 'mpc86xx' X-Git-Tag: v2008.10-rc1~1125^2~1^2~55 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bee01a3c166bc7ef4903e4e756d58a109067283f;hp=0e4c2a17ca34001ed36d259f13cb88ada4611a8c;p=platform%2Fkernel%2Fu-boot.git Merge branch 'mpc86xx' --- diff --git a/CHANGELOG b/CHANGELOG index c479e5d..dda7676 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,8 +2,122 @@ Changes since U-Boot 1.1.4: ====================================================================== +* Minor cleanup for PCS440EP board + +* Update PCS440EP port to fit into one flash device (incl. environment) + Patch by Stefan Roese, 06 Jun 2006 + +* Add support for PCS440EP board + Patch by Stefan Roese, 02 Jun 2006 + +* Fix examples/Makefile; some build targets were lost + +* Fix watchdog handling in CFI flash driver + Just use udelay() when waiting for status changes which will + implicitely trigger the watchdog. + +* Fix PCI to memory window size problems on PM82x boards + We use the "automatic" mode that was used for the MPC8266ADS and + MPC8272 boards. Eventually this should be used on all boards?] + Patch by Wolfgang Grandegger, 17 Jan 2006 + +* Correct GPIO setup (UART1/IRQ's) on yosemite & yellowstone + Patch by Stefan Roese, 29 May 2006 + +* Update Intel IXP4xx support + - Add IXP4xx NPE ethernet MAC support + - Add support for Intel IXDPG425 board + - Add support for Prodrive PDNB3 board + - Add IRQ support + Patch by Stefan Roese, 23 May 2006 + +* Fix problem in PVR detection for 440GR + Patch by Stefan Roese, 18 May 2006 + +* Fix gcc 3.4.x AFLAGS setting for m68k platform. + +* Enable autoboot for M5271EVB board. + +* Changed default ramdisk addr in yosemite/yellowstone ports + Patch by Stefan Roese, 15 May 2006 + +* Fix PCMCIA support on virtlab2 + +* Add support for VirtLab2 board + (needed because of differences in the PCMCIA hardware). + +* Minor cleanup. + +* Update yosemite configuration to enable flash write buffer support + Patch by Stefan Roese, 10 May 2006 + +* Fix compile warnings in common/xyzModem.c + Patch by Stefan Roese, 10 May 2006 + +* Add support for AMCC 440EP Rev C and 440GR Rev B + Patch by John Otken, 08 May 2006 + +* OMAP 5912/OSK: update EMIFS CS1 timings: + Problems have been seen in the linux kernel's smc91x network driver + due to improper bus timings. The latest 2.6 OMAP kernels currently + have a workaround, but this fix belongs in u-boot. + Patch by Kevin Hilman, 13 Oct 2005 + +* Fix REG_MPU_LOAD_TIMER definition in multiple OMAP ports + Patch by Hiroki Kaminaga, 11 Mar 2006 + +* Update omap5912osk board support + - Fix OMAP support that omap5912osk compiles in current source tree + - Update with code from "http://omap.spectrumdigital.com/osk5912" + to fix problems with DDR initialization + - Fix timer setup + - Use CFI flash driver and support complete 32MB of onboard flash + - Add "print_cpuinfo()" and "checkboard()" functions to display + CPU (with frequency) and Board infos + Patch by Stefan Roese, 10 May 2006 + +* Fix watchdog issues for ColdFire boards. + +* Add M5271EVB board support. + +* Make R5200 specific low level initialization board conditional. + +* Update CPU target identification strings for ColdFire family. + +* Update register definitions for MCF5271. + +* Fix serial console support for MCF5271. + +* Fixes for gcc 3.4 based m68k toolchain, + based on patch by Jate Sujjavanich. + +* Fix lowboot support on MCC200 board + +* Merged MPC8349ADS and MPC8349EMDS ports into MPC8349EMDS port: + - Removed MPC8349ADS port + - Added PCI support to MPC8349ADS + - reworked memory map to allow mapping of all regions with BATs + Patch by Kumar Gala, 20 Apr 2006 + +* Coding Style cleanup + +* Write RTC seconds first to maintain settings integrity per + Maxim/Dallas DS1306 data sheet. + Patch by Alan J. Luse, 02 May 2006 + +* Scheduled for removal: strnicmp() which is unused + +* Update for Intel Monahans boards: + - support for magic key detection and handling on delta board + - NAND support for zylonite board + some minor cleanup + +* Declare load_serial_ymodem() when using CFG_CMD_LOADB. + Patch by Jon Loeliger, 01 May 2006 + +* Fixed handling of bad checksums with "mkimage -l" + * Added support for BC3450 board - Patch by Stefan Strobl, 21. Oct 2005 + Patch by Stefan Strobl, 21 Oct 2005 * Update for NC650 board: - Support rev1 and rev2 hardware @@ -469,6 +583,15 @@ Changes since U-Boot 1.1.4: PMC405 and CPCI2DP: Added firmware download and booting via pci. Patch by Matthias Fuchs, 20 Dec 2005 +* Add ColdFire targets to MAKEALL script + Patch by Zachary Landau, 26 Jan 2006 + +* Add support for r5200 board + Patch by Zachary Landau, 26 Jan 2006 + +* Add support for Freescale M5271 processor + Patch by Zachary Landau, 26 Jan 2006 + * Fix 28F256J3A support on PM520 board (without bank-switching only 32 MB can be accessed) @@ -1766,7 +1889,7 @@ Changes for U-Boot 1.1.3: - use -mtune=xscale and -march=armv5 options for PXA * Patch by Florian Schlote, 08 Sep 2004: - Add support for SenTec-COBRA5272-board (Coldfire). + Add support for SenTec-COBRA5272-board (ColdFire). * Patch by Gleb Natapov, 07 Sep 2004: mpc824x: set PCI latency timer to a sane value @@ -1824,7 +1947,7 @@ Changes for U-Boot 1.1.2: * Patch by Stefan Roese, 16 Dez 2004: - ext2fs support added - Tundra universe support added - - Coldfire MCF5249 support added (no preloader needed!) + - ColdFire MCF5249 support added (no preloader needed!) - MCF5249 board TASREG added - PPC boards added: APC405, CPCI405DT, CPCI750, G2000, HH405, VOM405, WUH405 @@ -2146,7 +2269,7 @@ Changes for U-Boot 1.1.2: * Fix NSCU config; add ethernet wakeup code. -* Add link for preloader for Motorola Coldfire to README.m68k +* Add link for preloader for Motorola ColdFire to README.m68k * Patch by Michael Bendzick, 12 Jul 2004: fix output formatting in drivers/cfi_flash.c @@ -3093,7 +3216,7 @@ Changes for U-Boot 1.1.0: * Some code cleanup * Patch by Josef Baumgartner, 10 Feb 2004: - Fixes for Coldfire port + Fixes for ColdFire port * Patch by Brad Kemp, 11 Feb 2004: Fix CFI flash driver problems @@ -3359,7 +3482,7 @@ Changes for U-Boot 1.0.1: - 4xx: removed spurious MII error messages on "mii info" command. * Patch by Bernhard Kuhn, 28 Nov 2003: - add support for Coldfire CPU + add support for ColdFire CPU add support for Motorola M5272C3 and M5282EVB boards * Patch by Pierre Aubert, 24 Nov 2003: diff --git a/MAINTAINERS b/MAINTAINERS index 0ef9e03..2e5bfe2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -283,6 +283,7 @@ Stefan Roese ebony PPC440GP ocotea PPC440GX p3p440 PPC440GP + pcs440ep PPC440EP sycamore PPC405GPr walnut PPC405GP yellowstone PPC440GR @@ -434,6 +435,11 @@ Dave Peverley omap730p2 ARM926EJS +Stefan Roese + + ixdpg425 xscale + pdnb3 xscale + Robert Schwebel csb226 xscale @@ -534,6 +540,10 @@ Matthias Fuchs TASREG MCF5249 +Zachary P. Landau + + r5200 mcf52x2 + ######################################################################### # End of MAINTAINERS list # ######################################################################### diff --git a/MAKEALL b/MAKEALL index 6e620dd..5b56377 100755 --- a/MAKEALL +++ b/MAKEALL @@ -71,11 +71,11 @@ LIST_4xx=" \ HH405 HUB405 JSE KAREF \ luan METROBOX MIP405 MIP405T \ ML2 ml300 ocotea OCRTC \ - ORSG p3p440 PCI405 PIP405 \ - PLU405 PMC405 PPChameleonEVB sbc405 \ - VOH405 VOM405 W7OLMC W7OLMG \ - walnut WUH405 XPEDITE1K yellowstone \ - yosemite \ + ORSG p3p440 PCI405 pcs440ep \ + PIP405 PLU405 PMC405 PPChameleonEVB \ + sbc405 VOH405 VOM405 W7OLMC \ + W7OLMG walnut WUH405 XPEDITE1K \ + yellowstone yosemite \ " ######################################################################### @@ -117,7 +117,7 @@ LIST_8260=" \ ######################################################################### LIST_83xx=" \ - MPC8349ADS TQM834x MPC8349EMDS \ + TQM834x MPC8349EMDS \ " @@ -209,7 +209,7 @@ LIST_pxa=" \ zylonite \ " -LIST_ixp="ixdp425" +LIST_ixp="ixdp425 ixdpg425 pdnb3" LIST_arm=" \ @@ -273,6 +273,12 @@ LIST_nios2="PCI5441 PK1C20" LIST_microblaze="suzaku" +######################################################################### +## ColdFire Systems +######################################################################### + +LIST_coldfire="cobra5272 M5272C3 M5282EVB TASREG r5200 M5271EVB" + #----------------------------------------------------------------------- #----- for now, just run PPC by default ----- @@ -300,7 +306,8 @@ do microblaze| \ mips|mips_el| \ nios|nios2| \ - x86|I486) + x86|I486| \ + coldfire) for target in `eval echo '$LIST_'${arg}` do build_target ${target} diff --git a/Makefile b/Makefile index acfa5bd..7de890e 100644 --- a/Makefile +++ b/Makefile @@ -329,7 +329,7 @@ mcc200_config \ mcc200_lowboot_config: unconfig @ >include/config.h @[ -z "$(findstring lowboot_,$@)" ] || \ - { echo "TEXT_BASE = 0xFE000000" >board/mcc200/config.tmp ; \ + { echo "TEXT_BASE = 0xFC000000" >board/mcc200/config.tmp ; \ echo "... with lowboot configuration" ; \ } @./mkconfig mcc200 ppc mpc5xxx mcc200 @@ -759,7 +759,8 @@ TQM850M_config \ TQM855M_config \ TQM860M_config \ TQM862M_config \ -TQM866M_config: unconfig +TQM866M_config \ +virtlab2_config: unconfig @ >include/config.h @[ -z "$(findstring _LCD,$@)" ] || \ { echo "#define CONFIG_LCD" >>include/config.h ; \ @@ -921,6 +922,9 @@ p3p440_config: unconfig PCI405_config: unconfig @./mkconfig $(@:_config=) ppc ppc4xx pci405 esd +pcs440ep_config: unconfig + @./mkconfig $(@:_config=) ppc ppc4xx pcs440ep + PIP405_config: unconfig @./mkconfig $(@:_config=) ppc ppc4xx pip405 mpl @@ -1318,6 +1322,12 @@ M5282EVB_config : unconfig TASREG_config : unconfig @./mkconfig $(@:_config=) m68k mcf52x2 tasreg esd +r5200_config : unconfig + @./mkconfig $(@:_config=) m68k mcf52x2 r5200 + +M5271EVB_config : unconfig + @./mkconfig $(@:_config=) m68k mcf52x2 m5271evb + ######################################################################### ## MPC83xx Systems ######################################################################### @@ -1712,12 +1722,18 @@ innokom_config : unconfig ixdp425_config : unconfig @./mkconfig $(@:_config=) arm ixp ixdp425 +ixdpg425_config : unconfig + @./mkconfig $(@:_config=) arm ixp ixdp425 + lubbock_config : unconfig @./mkconfig $(@:_config=) arm pxa lubbock logodl_config : unconfig @./mkconfig $(@:_config=) arm pxa logodl +pdnb3_config : unconfig + @./mkconfig $(@:_config=) arm ixp pdnb3 prodrive + pxa255_idp_config: unconfig @./mkconfig $(@:_config=) arm pxa pxa255_idp diff --git a/board/amcc/yellowstone/yellowstone.c b/board/amcc/yellowstone/yellowstone.c index 20965c8..86d0db7 100644 --- a/board/amcc/yellowstone/yellowstone.c +++ b/board/amcc/yellowstone/yellowstone.c @@ -79,8 +79,8 @@ int board_early_init_f(void) out32(GPIO1_ISR2L, in32(GPIO1_ISR2L) | 0x00010000); /* external interrupts IRQ0...3 */ - out32(GPIO1_TCR, in32(GPIO1_TCR) & ~0x0f000000); - out32(GPIO1_TSRL, in32(GPIO1_TSRL) & ~0x00005500); + out32(GPIO1_TCR, in32(GPIO1_TCR) & ~0x00f00000); + out32(GPIO1_TSRL, in32(GPIO1_TSRL) & ~0x0000ff00); out32(GPIO1_ISR1L, in32(GPIO1_ISR1L) | 0x00005500); #if 0 /* test-only */ diff --git a/board/amcc/yosemite/yosemite.c b/board/amcc/yosemite/yosemite.c index 392d0dc..6742441 100644 --- a/board/amcc/yosemite/yosemite.c +++ b/board/amcc/yosemite/yosemite.c @@ -79,8 +79,8 @@ int board_early_init_f(void) out32(GPIO1_ISR2L, in32(GPIO1_ISR2L) | 0x00010000); /* external interrupts IRQ0...3 */ - out32(GPIO1_TCR, in32(GPIO1_TCR) & ~0x0f000000); - out32(GPIO1_TSRL, in32(GPIO1_TSRL) & ~0x00005500); + out32(GPIO1_TCR, in32(GPIO1_TCR) & ~0x00f00000); + out32(GPIO1_TSRL, in32(GPIO1_TSRL) & ~0x0000ff00); out32(GPIO1_ISR1L, in32(GPIO1_ISR1L) | 0x00005500); /*setup USB 2.0 */ diff --git a/board/bc3450/bc3450.c b/board/bc3450/bc3450.c index a030b82..0d86518 100644 --- a/board/bc3450/bc3450.c +++ b/board/bc3450/bc3450.c @@ -1,6 +1,4 @@ /* - * -- Version 1.1 -- - * * (C) Copyright 2003-2004 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * @@ -13,9 +11,6 @@ * (C) Copyright 2006 * Stefan Strobl, GERSYS GmbH, stefan.strobl@gersys.de * - * History: - * 1.1 - improved SM501 init to meet spec timing - * * See file CREDITS for list of people who contributed to this * project. * @@ -51,7 +46,7 @@ #ifdef CONFIG_RTC_MPC5200 #include -#endif +#endif #ifdef CONFIG_PS2MULT void ps2mult_early_init(void); @@ -375,7 +370,7 @@ ulong post_word_load (void) int board_early_init_r (void) { #ifdef CONFIG_RTC_MPC5200 - struct rtc_time t; + struct rtc_time t; /* set to Wed Dec 31 19:00:00 1969 */ t.tm_sec = t.tm_min = 0; @@ -384,7 +379,7 @@ int board_early_init_r (void) t.tm_mon = 12; t.tm_year = 1969; t.tm_wday = 3; - + rtc_set(&t); #endif /* CONFIG_RTC_MPC5200 */ @@ -482,7 +477,7 @@ int last_stage_init (void) } else { puts ("VGA: SMI501 (Voyager) with 8 MB\n"); } - /* restore origianl FB content */ + /* restore origianl FB content */ if (restore) { *(volatile u16 *)CFG_CS1_START = save; __asm__ volatile ("sync"); @@ -493,8 +488,8 @@ int last_stage_init (void) #ifdef CONFIG_VIDEO_SM501 -#define DISPLAY_WIDTH 640 -#define DISPLAY_HEIGHT 480 +#define DISPLAY_WIDTH 640 +#define DISPLAY_HEIGHT 480 #ifdef CONFIG_VIDEO_SM501_8BPP #error CONFIG_VIDEO_SM501_8BPP not supported. @@ -633,7 +628,7 @@ unsigned int board_video_init (void) } else { ret = SM501_MMIO_BASE; } - + if (restore) { *(volatile u16 *)CFG_CS1_START = save; __asm__ volatile ("sync"); diff --git a/board/bc3450/cmd_bc3450.c b/board/bc3450/cmd_bc3450.c index 1442b68..6bbe4e6 100644 --- a/board/bc3450/cmd_bc3450.c +++ b/board/bc3450/cmd_bc3450.c @@ -27,7 +27,7 @@ #include #include -/* +/* * BC3450 specific commands */ #if (CONFIG_COMMANDS & CFG_CMD_BSP) @@ -39,7 +39,7 @@ # define dprintf(fmt,args...) #endif -/* +/* * Definitions for DS1620 chip */ #define THERM_START_CONVERT 0xee @@ -57,8 +57,8 @@ #define CFG_STANDALONE 0 struct therm { - int hi; - int lo; + int hi; + int lo; }; /* @@ -124,36 +124,46 @@ struct therm { * Yet, the initialisation sequence is executed only the first * time the function is called. */ -int sm501_gpio_init(void) +int sm501_gpio_init (void) { - static int init_done = 0; + static int init_done = 0; - if(init_done) { + if (init_done) { /* dprintf("sm501_gpio_init: nothing to be done.\n"); */ - return 1; - } - - /* enable SM501 GPIO control (in both power modes) */ - *(vu_long *) (SM501_MMIO_BASE + SM501_POWER_MODE0_GATE) |= POWER_MODE_GATE_GPIO_PWM_I2C; - *(vu_long *) (SM501_MMIO_BASE + SM501_POWER_MODE1_GATE) |= POWER_MODE_GATE_GPIO_PWM_I2C; - - /* set up default O/Ps */ - *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) &= ~(DS1620_RES | DS1620_CLK); - *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) |= DS1620_DQ; - *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_HIGH) &= ~(FP_DATA_TRI); - *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_HIGH) |= (BUZZER | PWR_OFF); - - /* configure directions for SM501 GPIO pins */ - *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_CTRL_LOW) &= ~(0xFF << 24); - *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_CTRL_HIGH) &= ~(0x3F << 14); - *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_DIR_LOW) &= ~(DIP | DS1620_DQ); - *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_DIR_LOW) |= (DS1620_RES | DS1620_CLK); - *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_DIR_HIGH) &= ~DS1620_TLOW; - *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_DIR_HIGH) |= (PWR_OFF | BUZZER | FP_DATA_TRI); - - init_done = 1; + return 1; + } + + /* enable SM501 GPIO control (in both power modes) */ + *(vu_long *) (SM501_MMIO_BASE + SM501_POWER_MODE0_GATE) |= + POWER_MODE_GATE_GPIO_PWM_I2C; + *(vu_long *) (SM501_MMIO_BASE + SM501_POWER_MODE1_GATE) |= + POWER_MODE_GATE_GPIO_PWM_I2C; + + /* set up default O/Ps */ + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) &= + ~(DS1620_RES | DS1620_CLK); + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) |= DS1620_DQ; + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_HIGH) &= + ~(FP_DATA_TRI); + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_HIGH) |= + (BUZZER | PWR_OFF); + + /* configure directions for SM501 GPIO pins */ + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_CTRL_LOW) &= ~(0xFF << 24); + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_CTRL_HIGH) &= + ~(0x3F << 14); + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_DIR_LOW) &= + ~(DIP | DS1620_DQ); + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_DIR_LOW) |= + (DS1620_RES | DS1620_CLK); + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_DIR_HIGH) &= + ~DS1620_TLOW; + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_DIR_HIGH) |= + (PWR_OFF | BUZZER | FP_DATA_TRI); + + init_done = 1; /* dprintf("sm501_gpio_init: done.\n"); */ - return 0; + return 0; } @@ -163,347 +173,358 @@ int sm501_gpio_init(void) * read and prints the dip switch * and/or external config inputs (4bits) 0...0x0F */ -int cmd_dip (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +int cmd_dip (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { - vu_long rc = 0; + vu_long rc = 0; - sm501_gpio_init(); + sm501_gpio_init (); - /* read dip switch */ - rc = *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW); - rc = ~rc; - rc &= DIP; - rc = (int)(rc >> 24); + /* read dip switch */ + rc = *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW); + rc = ~rc; + rc &= DIP; + rc = (int) (rc >> 24); - /* plausibility check */ - if (rc > 0x0F) - return -1; + /* plausibility check */ + if (rc > 0x0F) + return -1; - printf ("0x%x\n", rc); - return 0; + printf ("0x%x\n", rc); + return 0; } -U_BOOT_CMD( - dip , 1, 1, cmd_dip, - "dip - read dip switch and config inputs\n", - "\n" - " - prints the state of the dip switch and/or\n" - " external configuration inputs as hex value.\n" - " - \"Config 1\" is the LSB\n" - ); +U_BOOT_CMD (dip, 1, 1, cmd_dip, + "dip - read dip switch and config inputs\n", + "\n" + " - prints the state of the dip switch and/or\n" + " external configuration inputs as hex value.\n" + " - \"Config 1\" is the LSB\n"); /* * buz - turns Buzzer on/off */ #ifdef CONFIG_BC3450_BUZZER -static int cmd_buz (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +static int cmd_buz (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { - if (argc != 2) { - printf ("Usage:\nspecify one argument: \"on\" or \"off\"\n"); - return 1; - } + if (argc != 2) { + printf ("Usage:\nspecify one argument: \"on\" or \"off\"\n"); + return 1; + } - sm501_gpio_init(); + sm501_gpio_init (); - if (strncmp (argv[1], "on", 2) == 0) { - *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_HIGH) &= ~(BUZZER); - return 0; - } - else if (strncmp (argv[1], "off", 3) == 0) { - *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_HIGH) |= BUZZER; - return 0; - } - printf ("Usage:\nspecify one argument: \"on\" or \"off\"\n"); - return 1; + if (strncmp (argv[1], "on", 2) == 0) { + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_HIGH) &= + ~(BUZZER); + return 0; + } else if (strncmp (argv[1], "off", 3) == 0) { + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_HIGH) |= + BUZZER; + return 0; + } + printf ("Usage:\nspecify one argument: \"on\" or \"off\"\n"); + return 1; } -U_BOOT_CMD( - buz , 2, 1, cmd_buz, - "buz - turns buzzer on/off\n", - "\n" - "buz \n" - " - turns the buzzer on or off\n" - ); +U_BOOT_CMD (buz, 2, 1, cmd_buz, + "buz - turns buzzer on/off\n", + "\n" "buz \n" " - turns the buzzer on or off\n"); #endif /* CONFIG_BC3450_BUZZER */ /* * fp - front panel commands */ -static int cmd_fp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +static int cmd_fp (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { - sm501_gpio_init(); - - if (strncmp (argv[1], "on", 2) == 0) { - /* turn on VDD first */ - *(vu_long *)(SM501_MMIO_BASE + SM501_PANEL_DISPLAY_CONTROL) |= SM501_PDC_VDDEN; - udelay(1000); - /* then put data on */ - *(vu_long *)(SM501_MMIO_BASE + SM501_PANEL_DISPLAY_CONTROL) |= SM501_PDC_DATA; - /* wait some time and enable backlight */ - udelay(1000); - *(vu_long *)(SM501_MMIO_BASE + SM501_PANEL_DISPLAY_CONTROL) |= SM501_PDC_BIAS; - udelay(1000); - *(vu_long *)(SM501_MMIO_BASE + SM501_PANEL_DISPLAY_CONTROL) |= SM501_PDC_FPEN; - return 0; - } - else if (strncmp (argv[1], "off", 3) == 0) { - /* turn off the backlight first */ - *(vu_long *)(SM501_MMIO_BASE + SM501_PANEL_DISPLAY_CONTROL) &= ~SM501_PDC_FPEN; - udelay(1000); - *(vu_long *)(SM501_MMIO_BASE + SM501_PANEL_DISPLAY_CONTROL) &= ~SM501_PDC_BIAS; - udelay(200000); - /* wait some time, then remove data */ - *(vu_long *)(SM501_MMIO_BASE + SM501_PANEL_DISPLAY_CONTROL) &= ~SM501_PDC_DATA; - udelay(1000); - /* and remove VDD last */ - *(vu_long *)(SM501_MMIO_BASE + SM501_PANEL_DISPLAY_CONTROL) &= ~SM501_PDC_VDDEN; - return 0; - } - else if (strncmp (argv[1], "bl", 2) == 0) { - /* turn on/off backlight only */ - if (strncmp (argv[2], "on", 2) == 0) { - *(vu_long *)(SM501_MMIO_BASE + SM501_PANEL_DISPLAY_CONTROL) |= SM501_PDC_BIAS; - udelay(1000); - *(vu_long *)(SM501_MMIO_BASE + SM501_PANEL_DISPLAY_CONTROL) |= SM501_PDC_FPEN; - return 0; - } - else if (strncmp (argv[2], "off", 3) == 0) { - *(vu_long *)(SM501_MMIO_BASE + SM501_PANEL_DISPLAY_CONTROL) &= ~SM501_PDC_FPEN; - udelay(1000); - *(vu_long *)(SM501_MMIO_BASE + SM501_PANEL_DISPLAY_CONTROL) &= ~SM501_PDC_BIAS; - return 0; + sm501_gpio_init (); + + if (strncmp (argv[1], "on", 2) == 0) { + /* turn on VDD first */ + *(vu_long *) (SM501_MMIO_BASE + + SM501_PANEL_DISPLAY_CONTROL) |= SM501_PDC_VDDEN; + udelay (1000); + /* then put data on */ + *(vu_long *) (SM501_MMIO_BASE + + SM501_PANEL_DISPLAY_CONTROL) |= SM501_PDC_DATA; + /* wait some time and enable backlight */ + udelay (1000); + *(vu_long *) (SM501_MMIO_BASE + + SM501_PANEL_DISPLAY_CONTROL) |= SM501_PDC_BIAS; + udelay (1000); + *(vu_long *) (SM501_MMIO_BASE + + SM501_PANEL_DISPLAY_CONTROL) |= SM501_PDC_FPEN; + return 0; + } else if (strncmp (argv[1], "off", 3) == 0) { + /* turn off the backlight first */ + *(vu_long *) (SM501_MMIO_BASE + + SM501_PANEL_DISPLAY_CONTROL) &= ~SM501_PDC_FPEN; + udelay (1000); + *(vu_long *) (SM501_MMIO_BASE + + SM501_PANEL_DISPLAY_CONTROL) &= ~SM501_PDC_BIAS; + udelay (200000); + /* wait some time, then remove data */ + *(vu_long *) (SM501_MMIO_BASE + + SM501_PANEL_DISPLAY_CONTROL) &= ~SM501_PDC_DATA; + udelay (1000); + /* and remove VDD last */ + *(vu_long *) (SM501_MMIO_BASE + + SM501_PANEL_DISPLAY_CONTROL) &= + ~SM501_PDC_VDDEN; + return 0; + } else if (strncmp (argv[1], "bl", 2) == 0) { + /* turn on/off backlight only */ + if (strncmp (argv[2], "on", 2) == 0) { + *(vu_long *) (SM501_MMIO_BASE + + SM501_PANEL_DISPLAY_CONTROL) |= + SM501_PDC_BIAS; + udelay (1000); + *(vu_long *) (SM501_MMIO_BASE + + SM501_PANEL_DISPLAY_CONTROL) |= + SM501_PDC_FPEN; + return 0; + } else if (strncmp (argv[2], "off", 3) == 0) { + *(vu_long *) (SM501_MMIO_BASE + + SM501_PANEL_DISPLAY_CONTROL) &= + ~SM501_PDC_FPEN; + udelay (1000); + *(vu_long *) (SM501_MMIO_BASE + + SM501_PANEL_DISPLAY_CONTROL) &= + ~SM501_PDC_BIAS; + return 0; + } } - } #ifdef CONFIG_BC3450_CRT - else if (strncmp (argv[1], "crt", 3) == 0) { - /* enables/disables the crt output (debug only) */ - if(strncmp (argv[2], "on", 2) == 0) { - *(vu_long *)(SM501_MMIO_BASE + SM501_CRT_DISPLAY_CONTROL) |= - (SM501_CDC_TE | SM501_CDC_E); - *(vu_long *)(SM501_MMIO_BASE + SM501_CRT_DISPLAY_CONTROL) &= - ~SM501_CDC_SEL; - return 0; - } - else if (strncmp (argv[2], "off", 3) == 0) { - *(vu_long *)(SM501_MMIO_BASE + SM501_CRT_DISPLAY_CONTROL) &= - ~(SM501_CDC_TE | SM501_CDC_E); - *(vu_long *)(SM501_MMIO_BASE + SM501_CRT_DISPLAY_CONTROL) |= - SM501_CDC_SEL; - return 0; + else if (strncmp (argv[1], "crt", 3) == 0) { + /* enables/disables the crt output (debug only) */ + if (strncmp (argv[2], "on", 2) == 0) { + *(vu_long *) (SM501_MMIO_BASE + + SM501_CRT_DISPLAY_CONTROL) |= + (SM501_CDC_TE | SM501_CDC_E); + *(vu_long *) (SM501_MMIO_BASE + + SM501_CRT_DISPLAY_CONTROL) &= + ~SM501_CDC_SEL; + return 0; + } else if (strncmp (argv[2], "off", 3) == 0) { + *(vu_long *) (SM501_MMIO_BASE + + SM501_CRT_DISPLAY_CONTROL) &= + ~(SM501_CDC_TE | SM501_CDC_E); + *(vu_long *) (SM501_MMIO_BASE + + SM501_CRT_DISPLAY_CONTROL) |= + SM501_CDC_SEL; + return 0; + } } - } #endif /* CONFIG_BC3450_CRT */ - printf("Usage:%s\n", cmdtp->help); - return 1; + printf ("Usage:%s\n", cmdtp->help); + return 1; } -U_BOOT_CMD( - fp , 3, 1, cmd_fp, - "fp - front panes access functions\n", - "\n" - "fp bl \n" - " - turns the CCFL backlight of the display on/off\n" - "fp \n" - " - turns the whole display on/off\n" +U_BOOT_CMD (fp, 3, 1, cmd_fp, + "fp - front panes access functions\n", + "\n" + "fp bl \n" + " - turns the CCFL backlight of the display on/off\n" + "fp \n" " - turns the whole display on/off\n" #ifdef CONFIG_BC3450_CRT - "fp crt \n" - " - enables/disables the crt output (debug only)\n" + "fp crt \n" + " - enables/disables the crt output (debug only)\n" #endif /* CONFIG_BC3450_CRT */ - ); + ); /* * temp - DS1620 thermometer */ /* GERSYS BC3450 specific functions */ -static inline void bc_ds1620_set_clk(int clk) +static inline void bc_ds1620_set_clk (int clk) { - if(clk) - *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) |= DS1620_CLK; - else - *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) &= ~DS1620_CLK; + if (clk) + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) |= + DS1620_CLK; + else + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) &= + ~DS1620_CLK; } -static inline void bc_ds1620_set_data(int dat) +static inline void bc_ds1620_set_data (int dat) { - if(dat) - *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) |= DS1620_DQ; - else - *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) &= ~DS1620_DQ; + if (dat) + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) |= + DS1620_DQ; + else + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) &= + ~DS1620_DQ; } -static inline int bc_ds1620_get_data(void) +static inline int bc_ds1620_get_data (void) { - vu_long rc; - rc = *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW); - rc &= DS1620_DQ; - if(rc != 0) - rc = 1; - return (int)rc; + vu_long rc; + + rc = *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW); + rc &= DS1620_DQ; + if (rc != 0) + rc = 1; + return (int) rc; } -static inline void bc_ds1620_set_data_dir(int dir) +static inline void bc_ds1620_set_data_dir (int dir) { - if(dir) /* in */ - *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_DIR_LOW) &= ~DS1620_DQ; - else /* out */ - *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_DIR_LOW) |= DS1620_DQ; + if (dir) /* in */ + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_DIR_LOW) &= ~DS1620_DQ; + else /* out */ + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_DIR_LOW) |= DS1620_DQ; } -static inline void bc_ds1620_set_reset(int res) +static inline void bc_ds1620_set_reset (int res) { - if(res) - *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) |= DS1620_RES; - else - *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) &= ~DS1620_RES; + if (res) + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) |= DS1620_RES; + else + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) &= ~DS1620_RES; } /* hardware independent functions */ -static void ds1620_send_bits(int nr, int value) +static void ds1620_send_bits (int nr, int value) { - int i; - - for (i = 0; i < nr; i++) { - bc_ds1620_set_data(value & 1); - bc_ds1620_set_clk(0); - udelay(1); - bc_ds1620_set_clk(1); - udelay(1); - - value >>= 1; - } + int i; + + for (i = 0; i < nr; i++) { + bc_ds1620_set_data (value & 1); + bc_ds1620_set_clk (0); + udelay (1); + bc_ds1620_set_clk (1); + udelay (1); + + value >>= 1; + } } -static unsigned int ds1620_recv_bits(int nr) +static unsigned int ds1620_recv_bits (int nr) { - unsigned int value = 0, mask = 1; - int i; + unsigned int value = 0, mask = 1; + int i; - bc_ds1620_set_data(0); + bc_ds1620_set_data (0); - for (i = 0; i < nr; i++) { - bc_ds1620_set_clk(0); - udelay(1); + for (i = 0; i < nr; i++) { + bc_ds1620_set_clk (0); + udelay (1); - if (bc_ds1620_get_data()) - value |= mask; + if (bc_ds1620_get_data ()) + value |= mask; - mask <<= 1; + mask <<= 1; - bc_ds1620_set_clk(1); - udelay(1); - } + bc_ds1620_set_clk (1); + udelay (1); + } - return value; + return value; } -static void ds1620_out(int cmd, int bits, int value) +static void ds1620_out (int cmd, int bits, int value) { - bc_ds1620_set_clk(1); - bc_ds1620_set_data_dir(0); + bc_ds1620_set_clk (1); + bc_ds1620_set_data_dir (0); - bc_ds1620_set_reset(0); - udelay(1); - bc_ds1620_set_reset(1); + bc_ds1620_set_reset (0); + udelay (1); + bc_ds1620_set_reset (1); - udelay(1); + udelay (1); - ds1620_send_bits(8, cmd); - if (bits) - ds1620_send_bits(bits, value); + ds1620_send_bits (8, cmd); + if (bits) + ds1620_send_bits (bits, value); - udelay(1); + udelay (1); - /* go stand alone */ - bc_ds1620_set_data_dir(1); - bc_ds1620_set_reset(0); - bc_ds1620_set_clk(0); + /* go stand alone */ + bc_ds1620_set_data_dir (1); + bc_ds1620_set_reset (0); + bc_ds1620_set_clk (0); - udelay(10000); + udelay (10000); } -static unsigned int ds1620_in(int cmd, int bits) +static unsigned int ds1620_in (int cmd, int bits) { - unsigned int value; + unsigned int value; - bc_ds1620_set_clk(1); - bc_ds1620_set_data_dir(0); + bc_ds1620_set_clk (1); + bc_ds1620_set_data_dir (0); - bc_ds1620_set_reset(0); - udelay(1); - bc_ds1620_set_reset(1); + bc_ds1620_set_reset (0); + udelay (1); + bc_ds1620_set_reset (1); - udelay(1); + udelay (1); - ds1620_send_bits(8, cmd); + ds1620_send_bits (8, cmd); - bc_ds1620_set_data_dir(1); - value = ds1620_recv_bits(bits); + bc_ds1620_set_data_dir (1); + value = ds1620_recv_bits (bits); - /* go stand alone */ - bc_ds1620_set_data_dir(1); - bc_ds1620_set_reset(0); - bc_ds1620_set_clk(0); + /* go stand alone */ + bc_ds1620_set_data_dir (1); + bc_ds1620_set_reset (0); + bc_ds1620_set_clk (0); - return value; + return value; } -static int cvt_9_to_int(unsigned int val) +static int cvt_9_to_int (unsigned int val) { - if (val & 0x100) - val |= 0xfffffe00; + if (val & 0x100) + val |= 0xfffffe00; - return val; + return val; } /* set thermostate thresholds */ -static void ds1620_write_state(struct therm *therm) +static void ds1620_write_state (struct therm *therm) { - ds1620_out(THERM_WRITE_TL, 9, therm->lo); - ds1620_out(THERM_WRITE_TH, 9, therm->hi); - ds1620_out(THERM_START_CONVERT, 0, 0); + ds1620_out (THERM_WRITE_TL, 9, therm->lo); + ds1620_out (THERM_WRITE_TH, 9, therm->hi); + ds1620_out (THERM_START_CONVERT, 0, 0); } -static int cmd_temp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +static int cmd_temp (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { - int i; - struct therm therm; + int i; + struct therm therm; - sm501_gpio_init(); + sm501_gpio_init (); - /* print temperature */ - if (argc == 1) { - i = cvt_9_to_int(ds1620_in(THERM_READ_TEMP, 9)); - printf("%d.%d C\n", i >> 1, i & 1 ? 5 : 0); - return 0; - } - - /* set to default operation */ - if (strncmp (argv[1], "set", 3) == 0) { - if(strncmp (argv[2], "default", 3) == 0) { - therm.hi = +88; - therm.lo = -20; - therm.hi <<= 1; - therm.lo <<= 1; - ds1620_write_state(&therm); - ds1620_out(THERM_WRITE_CONFIG, 8, CFG_STANDALONE); - return 0; + /* print temperature */ + if (argc == 1) { + i = cvt_9_to_int (ds1620_in (THERM_READ_TEMP, 9)); + printf ("%d.%d C\n", i >> 1, i & 1 ? 5 : 0); + return 0; } - } - printf ("Usage:%s\n", cmdtp->help); - return 1; + /* set to default operation */ + if (strncmp (argv[1], "set", 3) == 0) { + if (strncmp (argv[2], "default", 3) == 0) { + therm.hi = +88; + therm.lo = -20; + therm.hi <<= 1; + therm.lo <<= 1; + ds1620_write_state (&therm); + ds1620_out (THERM_WRITE_CONFIG, 8, CFG_STANDALONE); + return 0; + } + } + + printf ("Usage:%s\n", cmdtp->help); + return 1; } -U_BOOT_CMD( - temp , 3, 1, cmd_temp, - "temp - print current temperature\n", - "\n" - "temp\n" - " - print current temperature\n" -); +U_BOOT_CMD (temp, 3, 1, cmd_temp, + "temp - print current temperature\n", + "\n" "temp\n" " - print current temperature\n"); #ifdef CONFIG_BC3450_CAN /* @@ -512,40 +533,40 @@ U_BOOT_CMD( * return 1 on CAN initialization failure * return 0 if no failure */ -int can_init(void) +int can_init (void) { static int init_done = 0; int i; struct mpc5xxx_mscan *can1 = - (struct mpc5xxx_mscan *)(CFG_MBAR + 0x0900); + (struct mpc5xxx_mscan *) (CFG_MBAR + 0x0900); struct mpc5xxx_mscan *can2 = - (struct mpc5xxx_mscan *)(CFG_MBAR + 0x0980); + (struct mpc5xxx_mscan *) (CFG_MBAR + 0x0980); /* GPIO configuration of the CAN pins is done in BC3450.h */ if (!init_done) { /* init CAN 1 */ can1->canctl1 |= 0x80; /* CAN enable */ - udelay(100); + udelay (100); i = 0; can1->canctl0 |= 0x02; /* sleep mode */ /* wait until sleep mode reached */ while (!(can1->canctl1 & 0x02)) { - udelay(10); - i++; - if (i == 10) { - printf ("%s: CAN1 initialize error, " - "can not enter sleep mode!\n", - __FUNCTION__); - return 1; - } + udelay (10); + i++; + if (i == 10) { + printf ("%s: CAN1 initialize error, " + "can not enter sleep mode!\n", + __FUNCTION__); + return 1; + } } i = 0; can1->canctl0 = 0x01; /* enter init mode */ /* wait until init mode reached */ while (!(can1->canctl1 & 0x01)) { - udelay(10); + udelay (10); i++; if (i == 10) { printf ("%s: CAN1 initialize error, " @@ -577,7 +598,7 @@ int can_init(void) can1->canctl0 &= ~(0x02); /* wait until init and sleep mode left */ while ((can1->canctl1 & 0x01) || (can1->canctl1 & 0x02)) { - udelay(10); + udelay (10); i++; if (i == 10) { printf ("%s: CAN1 initialize error, " @@ -589,13 +610,13 @@ int can_init(void) /* init CAN 2 */ can2->canctl1 |= 0x80; /* CAN enable */ - udelay(100); + udelay (100); i = 0; can2->canctl0 |= 0x02; /* sleep mode */ /* wait until sleep mode reached */ - while (!(can2->canctl1 & 0x02)) { - udelay(10); + while (!(can2->canctl1 & 0x02)) { + udelay (10); i++; if (i == 10) { printf ("%s: CAN2 initialize error, " @@ -607,8 +628,8 @@ int can_init(void) i = 0; can2->canctl0 = 0x01; /* enter init mode */ /* wait until init mode reached */ - while (!(can2->canctl1 & 0x01)) { - udelay(10); + while (!(can2->canctl1 & 0x01)) { + udelay (10); i++; if (i == 10) { printf ("%s: CAN2 initialize error, " @@ -640,7 +661,7 @@ int can_init(void) i = 0; /* wait until init mode left */ while ((can2->canctl1 & 0x01) || (can2->canctl1 & 0x02)) { - udelay(10); + udelay (10); i++; if (i == 10) { printf ("%s: CAN2 initialize error, " @@ -661,13 +682,13 @@ int can_init(void) * return 1 on CAN failure * return 0 if no failure */ -int do_can(char *argv[]) +int do_can (char *argv[]) { int i; - struct mpc5xxx_mscan *can1 = - (struct mpc5xxx_mscan *)(CFG_MBAR + 0x0900); - struct mpc5xxx_mscan *can2 = - (struct mpc5xxx_mscan *)(CFG_MBAR + 0x0980); + struct mpc5xxx_mscan *can1 = + (struct mpc5xxx_mscan *) (CFG_MBAR + 0x0900); + struct mpc5xxx_mscan *can2 = + (struct mpc5xxx_mscan *) (CFG_MBAR + 0x0980); /* send a message on CAN1 */ can1->cantbsel = 0x01; @@ -685,30 +706,27 @@ int do_can(char *argv[]) i++; if (i == 10) { printf ("%s: CAN1 send timeout, " - "can not send message!\n", - __FUNCTION__); + "can not send message!\n", __FUNCTION__); return 1; } - udelay(1000); + udelay (1000); } - udelay(1000); + udelay (1000); i = 0; - while (!(can2->canrflg & 0x01)) { + while (!(can2->canrflg & 0x01)) { i++; if (i == 10) { printf ("%s: CAN2 receive timeout, " - "no message received!\n", - __FUNCTION__); + "no message received!\n", __FUNCTION__); return 1; } - udelay(1000); + udelay (1000); } - + if (can2->canrxfg.dsr[0] != 0xCC) { printf ("%s: CAN2 receive error, " - "data mismatch!\n", - __FUNCTION__); + "data mismatch!\n", __FUNCTION__); return 1; } @@ -728,24 +746,22 @@ int do_can(char *argv[]) i++; if (i == 10) { printf ("%s: CAN2 send error, " - "can not send message!\n", - __FUNCTION__); + "can not send message!\n", __FUNCTION__); return 1; } - udelay(1000); + udelay (1000); } - udelay(1000); + udelay (1000); i = 0; - while (!(can1->canrflg & 0x01)) { + while (!(can1->canrflg & 0x01)) { i++; if (i == 10) { printf ("%s: CAN1 receive timeout, " - "no message received!\n", - __FUNCTION__); + "no message received!\n", __FUNCTION__); return 1; } - udelay(1000); + udelay (1000); } if (can1->canrxfg.dsr[0] != 0xCC) { @@ -761,53 +777,51 @@ int do_can(char *argv[]) /* * test - BC3450 HW test routines */ -int cmd_test(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +int cmd_test (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { #ifdef CONFIG_BC3450_CAN - int rcode; - can_init(); + int rcode; + + can_init (); #endif /* CONFIG_BC3450_CAN */ - sm501_gpio_init(); + sm501_gpio_init (); - if (argc != 2) { - printf ("Usage:%s\n", cmdtp->help); - return 1; - } + if (argc != 2) { + printf ("Usage:%s\n", cmdtp->help); + return 1; + } - if (strncmp (argv[1], "unit-off", 8) == 0) { - printf ("waiting 2 seconds...\n"); - udelay(2000000); - *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_HIGH) &= ~PWR_OFF; - return 0; - } + if (strncmp (argv[1], "unit-off", 8) == 0) { + printf ("waiting 2 seconds...\n"); + udelay (2000000); + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_HIGH) &= + ~PWR_OFF; + return 0; + } #ifdef CONFIG_BC3450_CAN - else if (strncmp (argv[1], "can", 2) == 0) { - rcode = do_can (argv); - if (simple_strtoul(argv[2], NULL, 10) == 2) { - if (rcode == 0) - printf ("OK\n"); - else - printf ("Error\n"); + else if (strncmp (argv[1], "can", 2) == 0) { + rcode = do_can (argv); + if (simple_strtoul (argv[2], NULL, 10) == 2) { + if (rcode == 0) + printf ("OK\n"); + else + printf ("Error\n"); + } + return rcode; } - return rcode; - } #endif /* CONFIG_BC3450_CAN */ - printf ("Usage:%s\n", cmdtp->help); - return 1; + printf ("Usage:%s\n", cmdtp->help); + return 1; } -U_BOOT_CMD( - test , 2, 1, cmd_test, - "test - unit test routines\n", - "\n" +U_BOOT_CMD (test, 2, 1, cmd_test, "test - unit test routines\n", "\n" #ifdef CONFIG_BC3450_CAN - "test can\n" - " - connect CAN1 (X8) with CAN2 (X9) for this test\n" + "test can\n" + " - connect CAN1 (X8) with CAN2 (X9) for this test\n" #endif /* CONFIG_BC3450_CAN */ - "test unit-off\n" - " - turns off the BC3450 unit\n" - " WARNING: Unsaved environment variables will be lost!\n" - ); + "test unit-off\n" + " - turns off the BC3450 unit\n" + " WARNING: Unsaved environment variables will be lost!\n"); #endif /* CFG_CMD_BSP */ diff --git a/board/cobra5272/flash.c b/board/cobra5272/flash.c index 73cc2f2..82452e2 100644 --- a/board/cobra5272/flash.c +++ b/board/cobra5272/flash.c @@ -65,6 +65,7 @@ void flash_print_info (flash_info_t * info) printf ("\n"); Done: + return; } diff --git a/board/delta/delta.c b/board/delta/delta.c index b7671dd..b127ac8 100644 --- a/board/delta/delta.c +++ b/board/delta/delta.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include DECLARE_GLOBAL_DATA_PTR; @@ -35,6 +37,9 @@ DECLARE_GLOBAL_DATA_PTR; /* ------------------------------------------------------------------------- */ static void init_DA9030(void); +static void keys_init(void); +static void get_pressed_keys(uchar *s); +static uchar *key_match(uchar *kbd_data); /* * Miscelaneous platform dependent initialisations @@ -56,13 +61,216 @@ int board_init (void) int board_late_init(void) { +#ifdef DELTA_CHECK_KEYBD + uchar kbd_data[KEYBD_DATALEN]; + char keybd_env[2 * KEYBD_DATALEN + 1]; + char *str; + int i; +#endif /* DELTA_CHECK_KEYBD */ + setenv("stdout", "serial"); setenv("stderr", "serial"); + +#ifdef DELTA_CHECK_KEYBD + keys_init(); + + memset(kbd_data, '\0', KEYBD_DATALEN); + + /* check for pressed keys and setup keybd_env */ + get_pressed_keys(kbd_data); + + for (i = 0; i < KEYBD_DATALEN; ++i) { + sprintf (keybd_env + i + i, "%02X", kbd_data[i]); + } + setenv ("keybd", keybd_env); + + str = strdup ((char *)key_match (kbd_data)); /* decode keys */ + +# ifdef CONFIG_PREBOOT /* automatically configure "preboot" command on key match */ + setenv ("preboot", str); /* set or delete definition */ +# endif /* CONFIG_PREBOOT */ + if (str != NULL) { + free (str); + } +#endif /* DELTA_CHECK_KEYBD */ + init_DA9030(); return 0; } +/* + * Magic Key Handling, mainly copied from board/lwmon/lwmon.c + */ +#ifdef DELTA_CHECK_KEYBD + +static uchar kbd_magic_prefix[] = "key_magic"; +static uchar kbd_command_prefix[] = "key_cmd"; + +/* + * Get pressed keys + * s is a buffer of size KEYBD_DATALEN-1 + */ +static void get_pressed_keys(uchar *s) +{ + unsigned long val; + val = GPLR3; + + if(val & (1<<31)) + *s++ = KEYBD_KP_DKIN0; + if(val & (1<<18)) + *s++ = KEYBD_KP_DKIN1; + if(val & (1<<29)) + *s++ = KEYBD_KP_DKIN2; + if(val & (1<<22)) + *s++ = KEYBD_KP_DKIN5; +} + +static void keys_init() +{ + CKENB |= CKENB_7_GPIO; + udelay(100); + + /* Configure GPIOs */ + GPIO127 = 0xa840; /* KP_DKIN0 */ + GPIO114 = 0xa840; /* KP_DKIN1 */ + GPIO125 = 0xa840; /* KP_DKIN2 */ + GPIO118 = 0xa840; /* KP_DKIN5 */ + + /* Configure GPIOs as inputs */ + GPDR3 &= ~(1<<31 | 1<<18 | 1<<29 | 1<<22); + GCDR3 = (1<<31 | 1<<18 | 1<<29 | 1<<22); + + udelay(100); +} + +static int compare_magic (uchar *kbd_data, uchar *str) +{ + /* uchar compare[KEYBD_DATALEN-1]; */ + uchar compare[KEYBD_DATALEN]; + char *nxt; + int i; + + /* Don't include modifier byte */ + /* memcpy (compare, kbd_data+1, KEYBD_DATALEN-1); */ + memcpy (compare, kbd_data, KEYBD_DATALEN); + + for (; str != NULL; str = (*nxt) ? (uchar *)(nxt+1) : (uchar *)nxt) { + uchar c; + int k; + + c = (uchar) simple_strtoul ((char *)str, (char **) (&nxt), 16); + + if (str == (uchar *)nxt) { /* invalid character */ + break; + } + + /* + * Check if this key matches the input. + * Set matches to zero, so they match only once + * and we can find duplicates or extra keys + */ + for (k = 0; k < sizeof(compare); ++k) { + if (compare[k] == '\0') /* only non-zero entries */ + continue; + if (c == compare[k]) { /* found matching key */ + compare[k] = '\0'; + break; + } + } + if (k == sizeof(compare)) { + return -1; /* unmatched key */ + } + } + + /* + * A full match leaves no keys in the `compare' array, + */ + for (i = 0; i < sizeof(compare); ++i) { + if (compare[i]) + { + return -1; + } + } + + return 0; +} + + +static uchar *key_match (uchar *kbd_data) +{ + char magic[sizeof (kbd_magic_prefix) + 1]; + uchar *suffix; + char *kbd_magic_keys; + + /* + * The following string defines the characters that can pe appended + * to "key_magic" to form the names of environment variables that + * hold "magic" key codes, i. e. such key codes that can cause + * pre-boot actions. If the string is empty (""), then only + * "key_magic" is checked (old behaviour); the string "125" causes + * checks for "key_magic1", "key_magic2" and "key_magic5", etc. + */ + if ((kbd_magic_keys = getenv ("magic_keys")) == NULL) + kbd_magic_keys = ""; + + /* loop over all magic keys; + * use '\0' suffix in case of empty string + */ + for (suffix=(uchar *)kbd_magic_keys; *suffix || suffix==(uchar *)kbd_magic_keys; ++suffix) { + sprintf (magic, "%s%c", kbd_magic_prefix, *suffix); +#if 0 + printf ("### Check magic \"%s\"\n", magic); +#endif + if (compare_magic(kbd_data, (uchar *)getenv(magic)) == 0) { + char cmd_name[sizeof (kbd_command_prefix) + 1]; + char *cmd; + + sprintf (cmd_name, "%s%c", kbd_command_prefix, *suffix); + + cmd = getenv (cmd_name); +#if 0 + printf ("### Set PREBOOT to $(%s): \"%s\"\n", + cmd_name, cmd ? cmd : "<>"); +#endif + *kbd_data = *suffix; + return ((uchar *)cmd); + } + } +#if 0 + printf ("### Delete PREBOOT\n"); +#endif + *kbd_data = '\0'; + return (NULL); +} + +int do_kbd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + uchar kbd_data[KEYBD_DATALEN]; + char keybd_env[2 * KEYBD_DATALEN + 1]; + int i; + + /* Read keys */ + get_pressed_keys(kbd_data); + puts ("Keys:"); + for (i = 0; i < KEYBD_DATALEN; ++i) { + sprintf (keybd_env + i + i, "%02X", kbd_data[i]); + printf (" %02x", kbd_data[i]); + } + putc ('\n'); + setenv ("keybd", keybd_env); + return 0; +} + +U_BOOT_CMD( + kbd, 1, 1, do_kbd, + "kbd - read keyboard status\n", + NULL +); + +#endif /* DELTA_CHECK_KEYBD */ + + int dram_init (void) { gd->bd->bi_dram[0].start = PHYS_SDRAM_1; diff --git a/board/ixdp425/Makefile b/board/ixdp425/Makefile index e4282c4..59d6964 100644 --- a/board/ixdp425/Makefile +++ b/board/ixdp425/Makefile @@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk LIB = lib$(BOARD).a -OBJS := ixdp425.o flash.o +OBJS := ixdp425.o $(LIB): $(OBJS) $(SOBJS) $(AR) crv $@ $^ diff --git a/board/ixdp425/config.mk b/board/ixdp425/config.mk index 9f616f3..3420586 100644 --- a/board/ixdp425/config.mk +++ b/board/ixdp425/config.mk @@ -1,2 +1,4 @@ -#TEXT_BASE = 0x00100000 TEXT_BASE = 0x00f80000 + +# include NPE ethernet driver +BOARDLIBS = cpu/ixp/npe/libnpe.a diff --git a/board/ixdp425/ixdp425.c b/board/ixdp425/ixdp425.c index aa96591..eaf7cde 100644 --- a/board/ixdp425/ixdp425.c +++ b/board/ixdp425/ixdp425.c @@ -1,4 +1,7 @@ /* + * (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * * (C) Copyright 2002 * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net * @@ -25,24 +28,21 @@ * MA 02111-1307 USA */ -#include #include +#include +#include +#include DECLARE_GLOBAL_DATA_PTR; /* * Miscelaneous platform dependent initialisations */ - -/**********************************************************/ - int board_post_init (void) { return (0); } -/**********************************************************/ - int board_init (void) { /* arch number of IXDP */ @@ -51,10 +51,58 @@ int board_init (void) /* adress of boot parameters */ gd->bd->bi_boot_params = 0x00000100; +#ifdef CONFIG_IXDPG425 + /* arch number of IXDP */ + gd->bd->bi_arch_number = MACH_TYPE_IXDPG425; + + /* + * Get realtek RTL8305 switch and SLIC out of reset + */ + GPIO_OUTPUT_SET(CFG_GPIO_SWITCH_RESET_N); + GPIO_OUTPUT_ENABLE(CFG_GPIO_SWITCH_RESET_N); + GPIO_OUTPUT_SET(CFG_GPIO_SLIC_RESET_N); + GPIO_OUTPUT_ENABLE(CFG_GPIO_SLIC_RESET_N); + + /* + * Setup GPIO's for PCI INTA & INTB + */ + GPIO_OUTPUT_DISABLE(CFG_GPIO_PCI_INTA_N); + GPIO_INT_ACT_LOW_SET(CFG_GPIO_PCI_INTA_N); + GPIO_OUTPUT_DISABLE(CFG_GPIO_PCI_INTB_N); + GPIO_INT_ACT_LOW_SET(CFG_GPIO_PCI_INTB_N); + + /* + * Setup GPIO's for 33MHz clock output + */ + *IXP425_GPIO_GPCLKR = 0x01FF01FF; + GPIO_OUTPUT_ENABLE(CFG_GPIO_PCI_CLK); + GPIO_OUTPUT_ENABLE(CFG_GPIO_EXTBUS_CLK); +#endif + return 0; } -/**********************************************************/ +/* + * Check Board Identity + */ +int checkboard(void) +{ + char *s = getenv("serial#"); + +#ifdef CONFIG_IXDPG425 + puts("Board: IXDPG425 - Intel Network Gateway Reference Platform"); +#else + puts("Board: IXDP425 - Intel Development Platform"); +#endif + + if (s != NULL) { + puts(", serial# "); + puts(s); + } + putc('\n'); + + return (0); +} int dram_init (void) { @@ -64,8 +112,7 @@ int dram_init (void) return (0); } -/**********************************************************/ - +#if (CONFIG_COMMANDS & CFG_CMD_PCI) || defined(CONFIG_PCI) extern struct pci_controller hose; extern void pci_ixp_init(struct pci_controller * hose); @@ -75,3 +122,4 @@ void pci_init_board(void) pci_ixp_init(&hose); } +#endif diff --git a/board/m5271evb/Makefile b/board/m5271evb/Makefile new file mode 100644 index 0000000..34de983 --- /dev/null +++ b/board/m5271evb/Makefile @@ -0,0 +1,40 @@ +# +# (C) Copyright 2000-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 + +$(LIB): .depend $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/mpc8349ads/config.mk b/board/m5271evb/config.mk similarity index 82% rename from board/mpc8349ads/config.mk rename to board/m5271evb/config.mk index 4602169..9a7af7c 100644 --- a/board/mpc8349ads/config.mk +++ b/board/m5271evb/config.mk @@ -1,5 +1,7 @@ # -# Copyright 2004 Freescale Semiconductor, Inc. +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# Coldfire contribution by Bernhard Kuhn # # See file CREDITS for list of people who contributed to this # project. @@ -20,8 +22,4 @@ # MA 02111-1307 USA # -# -# MPC83xxADS -# - -TEXT_BASE = 0xFE700000 +TEXT_BASE = 0xffe00000 diff --git a/board/m5271evb/m5271evb.c b/board/m5271evb/m5271evb.c new file mode 100644 index 0000000..c26c91d --- /dev/null +++ b/board/m5271evb/m5271evb.c @@ -0,0 +1,124 @@ +/* + * (C) Copyright 2000-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 +#include +#include + +int checkboard (void) { + puts ("Board: Freescale M5271EVB\n"); + return 0; +}; + +long int initdram (int board_type) { + + int i; + + /* Enable Address lines 23-21 and lower 16bits of data path */ + mbar_writeByte(MCF_GPIO_PAR_AD, MCF_GPIO_AD_ADDR23 | + MCF_GPIO_AD_ADDR22 | MCF_GPIO_AD_ADDR21 | + MCF_GPIO_AD_DATAL); + + /* Set CS2 pin to be SD_CS0 */ + mbar_writeByte(MCF_GPIO_PAR_CS, mbar_readByte(MCF_GPIO_PAR_CS) + | MCF_GPIO_PAR_CS_PAR_CS2); + + /* Configure SDRAM Control Pin Assignemnt Register */ + mbar_writeByte(MCF_GPIO_PAR_SDRAM, MCF_GPIO_SDRAM_CSSDCS_00 | + MCF_GPIO_SDRAM_SDWE | MCF_GPIO_SDRAM_SCAS | + MCF_GPIO_SDRAM_SRAS | MCF_GPIO_SDRAM_SCKE | + MCF_GPIO_SDRAM_SDCS_11); + + /* + * Check to see if the SDRAM has already been initialized + * by a run control tool + */ + if (!(mbar_readLong(MCF_SDRAMC_DACR0) & MCF_SDRAMC_DACRn_RE)) { + /* Initialize DRAM Control Register: DCR */ + mbar_writeShort(MCF_SDRAMC_DCR, + MCF_SDRAMC_DCR_RTIM(0x01) + | MCF_SDRAMC_DCR_RC(0x30)); + + /* + * Initialize DACR0 + * + * CASL: 01 + * CBM: cmd at A20, bank select bits 21 and up + * PS: 32bit port size + */ + mbar_writeLong(MCF_SDRAMC_DACR0, + MCF_SDRAMC_DACRn_BA(CFG_SDRAM_BASE>>18) + | MCF_SDRAMC_DACRn_CASL(1) + | MCF_SDRAMC_DACRn_CBM(3) + | MCF_SDRAMC_DACRn_PS(0)); + + /* Initialize DMR0 */ + mbar_writeLong(MCF_SDRAMC_DMR0, + MCF_SDRAMC_DMRn_BAM_16M + | MCF_SDRAMC_DMRn_V); + + /* Set IP bit in DACR */ + mbar_writeLong(MCF_SDRAMC_DACR0, mbar_readLong(MCF_SDRAMC_DACR0) + | MCF_SDRAMC_DACRn_IP); + + /* Wait at least 20ns to allow banks to precharge */ + for (i = 0; i < 5; i++) + asm(" nop"); + + /* Write to this block to initiate precharge */ + *(u32 *)(CFG_SDRAM_BASE) = 0xa5a5a5a5; + + /* Set RE bit in DACR */ + mbar_writeLong(MCF_SDRAMC_DACR0, mbar_readLong(MCF_SDRAMC_DACR0) + | MCF_SDRAMC_DACRn_RE); + + /* Wait for at least 8 auto refresh cycles to occur */ + for (i = 0; i < 2000; i++) + asm(" nop"); + + /* Finish the configuration by issuing the MRS */ + mbar_writeLong(MCF_SDRAMC_DACR0, mbar_readLong(MCF_SDRAMC_DACR0) + | MCF_SDRAMC_DACRn_MRS); + + /* + * Write to the SDRAM Mode Register A0-A11 = 0x400 + * + * Write Burst Mode = Programmed Burst Length + * Op Mode = Standard Op + * CAS Latency = 2 + * Burst Type = Sequential + * Burst Length = 1 + */ + *(u32 *)(CFG_SDRAM_BASE + 0x400) = 0xa5a5a5a5; + } + + return CFG_SDRAM_SIZE * 1024 * 1024; +}; + +int testdram (void) { + + /* TODO: XXX XXX XXX */ + printf ("DRAM test not implemented!\n"); + + return (0); +} diff --git a/board/m5271evb/u-boot.lds b/board/m5271evb/u-boot.lds new file mode 100644 index 0000000..69f3179 --- /dev/null +++ b/board/m5271evb/u-boot.lds @@ -0,0 +1,145 @@ +/* + * (C) Copyright 2000 + * 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(m68k) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +GROUP(libgcc.a) +SECTIONS +{ + /* 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 : + { + /* WARNING - the following is hand-optimized to fit within */ + /* the sector layout of our flash chips! XXX FIXME XXX */ + + cpu/mcf52x2/start.o (.text) + lib_m68k/traps.o (.text) + cpu/mcf52x2/interrupts.o (.text) + common/dlmalloc.o (.text) + lib_generic/zlib.o (.text) + + . = DEFINED(env_offset) ? env_offset : .; + common/environment.o (.ppcenv) + + *(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x00FF) & 0xFFFFFF00; + _erotext = .; + PROVIDE (erotext = .); + + .reloc : + { + __got_start = .; + *(.got) + __got_end = .; + _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 = .; + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + . = ALIGN(4); + _ebss = .; + } + _end = . ; + PROVIDE (end = .); +} diff --git a/board/m5272c3/flash.c b/board/m5272c3/flash.c index f156342..ea0b1fd 100644 --- a/board/m5272c3/flash.c +++ b/board/m5272c3/flash.c @@ -65,6 +65,7 @@ void flash_print_info (flash_info_t * info) printf ("\n"); Done: + return; } diff --git a/board/m5282evb/flash.c b/board/m5282evb/flash.c index 95f35ad..36a7c31 100644 --- a/board/m5282evb/flash.c +++ b/board/m5282evb/flash.c @@ -65,6 +65,7 @@ void flash_print_info (flash_info_t * info) printf ("\n"); Done: + return; } diff --git a/board/mpc8349ads/mpc8349ads.c b/board/mpc8349ads/mpc8349ads.c deleted file mode 100644 index 9841298..0000000 --- a/board/mpc8349ads/mpc8349ads.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright Freescale Semiconductor, Inc. - * - * 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 - * - * Change log: - * 20050101: Eran Liberty (liberty@freescale.com) - * Initial file creating (porting from 85XX & 8260) - */ - -#include -#include -#include -#include -#include -#include -#include -#if defined(CONFIG_PCI) -#include -#endif -#if defined(CONFIG_SPD_EEPROM) -#include -#endif -int fixed_sdram(void); -void sdram_init(void); - -int board_early_init_f (void) -{ - volatile u8* bcsr = (volatile u8*)CFG_BCSR; - - /* Enable flash write */ - bcsr[1] &= ~0x01; - - return 0; -} - - -#define ns2clk(ns) (ns / (1000000000 / CONFIG_8349_CLKIN) + 1) - -long int initdram (int board_type) -{ - volatile immap_t *im = (immap_t *)CFG_IMMRBAR; - u32 msize = 0; - - if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32)im) - return -1; - - /* DDR SDRAM - Main SODIMM */ - im->sysconf.ddrlaw[0].bar = CFG_DDR_BASE & LAWBAR_BAR; -#if defined(CONFIG_SPD_EEPROM) - msize = spd_sdram(); -#else - msize = fixed_sdram(); -#endif - /* - * Initialize SDRAM if it is on local bus. - */ - sdram_init(); - puts(" DDR RAM: "); - /* return total bus SDRAM size(bytes) -- DDR */ - return (msize * 1024 * 1024); -} - - -#if !defined(CONFIG_SPD_EEPROM) -/************************************************************************* - * fixed sdram init -- doesn't use serial presence detect. - ************************************************************************/ -int fixed_sdram(void) -{ - volatile immap_t *im = (immap_t *)CFG_IMMRBAR; - u32 msize = 0; - u32 ddr_size; - u32 ddr_size_log2; - - msize = CFG_DDR_SIZE; - for (ddr_size = msize << 20, ddr_size_log2 = 0; - (ddr_size > 1); - ddr_size = ddr_size>>1, ddr_size_log2++) { - if (ddr_size & 1) { - return -1; - } - } - im->sysconf.ddrlaw[0].ar = LAWAR_EN | ((ddr_size_log2 - 1) & LAWAR_SIZE); -#if (CFG_DDR_SIZE != 256) -#warning Currenly any ddr size other than 256 is not supported -#endif - - im->ddr.csbnds[0].csbnds = 0x00100017; - im->ddr.csbnds[1].csbnds = 0x0018001f; - im->ddr.csbnds[2].csbnds = 0x00000007; - im->ddr.csbnds[3].csbnds = 0x0008000f; - im->ddr.cs_config[0] = CFG_DDR_CONFIG; - im->ddr.cs_config[1] = CFG_DDR_CONFIG; - im->ddr.cs_config[2] = CFG_DDR_CONFIG; - im->ddr.cs_config[3] = CFG_DDR_CONFIG; - im->ddr.timing_cfg_1 = - 3 << TIMING_CFG1_PRETOACT_SHIFT | - 7 << TIMING_CFG1_ACTTOPRE_SHIFT | - 3 << TIMING_CFG1_ACTTORW_SHIFT | - 4 << TIMING_CFG1_CASLAT_SHIFT | - 3 << TIMING_CFG1_REFREC_SHIFT | - 3 << TIMING_CFG1_WRREC_SHIFT | - 2 << TIMING_CFG1_ACTTOACT_SHIFT | - 1 << TIMING_CFG1_WRTORD_SHIFT; - im->ddr.timing_cfg_2 = 2 << TIMING_CFG2_WR_DATA_DELAY_SHIFT; - im->ddr.sdram_cfg = - SDRAM_CFG_SREN -#if defined(CONFIG_DDR_2T_TIMING) - | SDRAM_CFG_2T_EN -#endif - | 2 << SDRAM_CFG_SDRAM_TYPE_SHIFT; - im->ddr.sdram_mode = - 0x2000 << SDRAM_MODE_ESD_SHIFT | - 0x0162 << SDRAM_MODE_SD_SHIFT; - - im->ddr.sdram_interval = 0x045B << SDRAM_INTERVAL_REFINT_SHIFT | - 0x0100 << SDRAM_INTERVAL_BSTOPRE_SHIFT; - udelay(200); - - im->ddr.sdram_cfg |= SDRAM_CFG_MEM_EN; - - return msize; -} -#endif/*!CFG_SPD_EEPROM*/ - - -int checkboard (void) -{ - puts("Board: Freescale MPC8349ADS\n"); - return 0; -} - -/* - * if MPC8349ADS is soldered with SDRAM - */ -#if defined(CFG_BR2_PRELIM) \ - && defined(CFG_OR2_PRELIM) \ - && defined(CFG_LBLAWBAR2_PRELIM) \ - && defined(CFG_LBLAWAR2_PRELIM) -/* - * Initialize SDRAM memory on the Local Bus. - */ - -void -sdram_init(void) -{ - volatile immap_t *immap = (immap_t *)CFG_IMMRBAR; - volatile lbus8349_t *lbc= &immap->lbus; - uint *sdram_addr = (uint *)CFG_LBC_SDRAM_BASE; - - puts("\n SDRAM on Local Bus: "); - print_size (CFG_LBC_SDRAM_SIZE * 1024 * 1024, "\n"); - - /* - * Setup SDRAM Base and Option Registers, already done in cpu_init.c - */ - - /*setup mtrpt, lsrt and lbcr for LB bus*/ - lbc->lbcr = CFG_LBC_LBCR; - lbc->mrtpr = CFG_LBC_MRTPR; - lbc->lsrt = CFG_LBC_LSRT; - asm("sync"); - - /* - * Configure the SDRAM controller Machine Mode Register. - */ - lbc->lsdmr = CFG_LBC_LSDMR_5; /* 0x40636733; normal operation*/ - - lbc->lsdmr = CFG_LBC_LSDMR_1; /*0x68636733;precharge all the banks*/ - asm("sync"); - *sdram_addr = 0xff; - udelay(100); - - lbc->lsdmr = CFG_LBC_LSDMR_2;/*0x48636733;auto refresh*/ - asm("sync"); - /*1 times*/ - *sdram_addr = 0xff; - udelay(100); - /*2 times*/ - *sdram_addr = 0xff; - udelay(100); - /*3 times*/ - *sdram_addr = 0xff; - udelay(100); - /*4 times*/ - *sdram_addr = 0xff; - udelay(100); - /*5 times*/ - *sdram_addr = 0xff; - udelay(100); - /*6 times*/ - *sdram_addr = 0xff; - udelay(100); - /*7 times*/ - *sdram_addr = 0xff; - udelay(100); - /*8 times*/ - *sdram_addr = 0xff; - udelay(100); - - /* 0x58636733;mode register write operation */ - lbc->lsdmr = CFG_LBC_LSDMR_4; - asm("sync"); - *sdram_addr = 0xff; - udelay(100); - - lbc->lsdmr = CFG_LBC_LSDMR_5; /*0x40636733;normal operation*/ - asm("sync"); - *sdram_addr = 0xff; - udelay(100); -} -#else -void -sdram_init(void) -{ - put("SDRAM on Local Bus is NOT available!\n"); -} -#endif diff --git a/board/mpc8349emds/mpc8349emds.c b/board/mpc8349emds/mpc8349emds.c index 7ece7db..b5ccb53 100644 --- a/board/mpc8349emds/mpc8349emds.c +++ b/board/mpc8349emds/mpc8349emds.c @@ -30,9 +30,6 @@ #include #include #include -#if defined(CONFIG_PCI) -#include -#endif #if defined(CONFIG_SPD_EEPROM) #include #endif @@ -50,6 +47,11 @@ int board_early_init_f (void) /* Enable flash write */ bcsr[1] &= ~0x01; +#ifdef CFG_USE_MPC834XSYS_USB_PHY + /* Use USB PHY on SYS board */ + bcsr[5] |= 0x02; +#endif + return 0; } @@ -152,44 +154,6 @@ int checkboard (void) return 0; } -#if defined(CONFIG_PCI) -/* - * Initialize PCI Devices, report devices found - */ -#ifndef CONFIG_PCI_PNP -static struct pci_config_table pci_mpc8349emds_config_table[] = { - {PCI_ANY_ID,PCI_ANY_ID,PCI_ANY_ID,PCI_ANY_ID, - pci_cfgfunc_config_device, {PCI_ENET0_IOADDR, - PCI_ENET0_MEMADDR, - PCI_COMMON_MEMORY | PCI_COMMAND_MASTER - } }, - {} -} -#endif - -volatile static struct pci_controller hose[] = { - { -#ifndef CONFIG_PCI_PNP - config_table:pci_mpc8349emds_config_table, -#endif - }, - { -#ifndef CONFIG_PCI_PNP - config_table:pci_mpc8349emds_config_table, -#endif - } -}; -#endif /* CONFIG_PCI */ - -void pci_init_board(void) -{ -#ifdef CONFIG_PCI - extern void pci_mpc83xx_init(volatile struct pci_controller *hose); - - pci_mpc83xx_init(hose); -#endif /* CONFIG_PCI */ -} - /* * if MPC8349EMDS is soldered with SDRAM */ diff --git a/board/mpc8349ads/pci.c b/board/mpc8349emds/pci.c similarity index 97% rename from board/mpc8349ads/pci.c rename to board/mpc8349emds/pci.c index 319e35c..63e4405 100644 --- a/board/mpc8349ads/pci.c +++ b/board/mpc8349emds/pci.c @@ -35,7 +35,7 @@ DECLARE_GLOBAL_DATA_PTR; #define CONFIG_PCI_SYS_MEM_PHYS CFG_SDRAM_BASE #ifndef CONFIG_PCI_PNP -static struct pci_config_table pci_mpc83xxads_config_table[] = { +static struct pci_config_table pci_mpc8349emds_config_table[] = { {PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_IDSEL_NUMBER, PCI_ANY_ID, pci_cfgfunc_config_device, {PCI_ENET0_IOADDR, @@ -50,12 +50,12 @@ static struct pci_config_table pci_mpc83xxads_config_table[] = { static struct pci_controller pci_hose[] = { { #ifndef CONFIG_PCI_PNP - config_table:pci_mpc83xxads_config_table, + config_table:pci_mpc8349emds_config_table, #endif }, { #ifndef CONFIG_PCI_PNP - config_table:pci_mpc83xxads_config_table, + config_table:pci_mpc8349emds_config_table, #endif } }; @@ -188,7 +188,7 @@ pci_init_board(void) pci_law[0].ar = LAWAR_EN | LAWAR_SIZE_1G; pci_law[1].bar = CFG_PCI1_IO_PHYS & LAWBAR_BAR; - pci_law[1].ar = LAWAR_EN | LAWAR_SIZE_32M; + pci_law[1].ar = LAWAR_EN | LAWAR_SIZE_4M; /* * Configure PCI Outbound Translation Windows @@ -378,4 +378,5 @@ pci_init_board(void) #endif } + #endif /* CONFIG_PCI */ diff --git a/board/nc650/nand.c b/board/nc650/nand.c index f27e536..de54386 100644 --- a/board/nc650/nand.c +++ b/board/nc650/nand.c @@ -37,22 +37,22 @@ static void nc650_hwcontrol(struct mtd_info *mtd, int cmd) struct nand_chip *this = mtd->priv; switch(cmd) { - case NAND_CTL_SETCLE: - this->IO_ADDR_W += 2; - break; - case NAND_CTL_CLRCLE: - this->IO_ADDR_W -= 2; - break; - case NAND_CTL_SETALE: - this->IO_ADDR_W += 1; - break; - case NAND_CTL_CLRALE: - this->IO_ADDR_W -= 1; - break; - case NAND_CTL_SETNCE: - case NAND_CTL_CLRNCE: - /* nop */ - break; + case NAND_CTL_SETCLE: + this->IO_ADDR_W += 2; + break; + case NAND_CTL_CLRCLE: + this->IO_ADDR_W -= 2; + break; + case NAND_CTL_SETALE: + this->IO_ADDR_W += 1; + break; + case NAND_CTL_CLRALE: + this->IO_ADDR_W -= 1; + break; + case NAND_CTL_SETNCE: + case NAND_CTL_CLRNCE: + /* nop */ + break; } } #elif defined(CONFIG_IDS852_REV2) @@ -64,24 +64,24 @@ static void nc650_hwcontrol(struct mtd_info *mtd, int cmd) struct nand_chip *this = mtd->priv; switch(cmd) { - case NAND_CTL_SETCLE: - *(((volatile __u8 *) this->IO_ADDR_W) + 0xa) = 0; - break; - case NAND_CTL_CLRCLE: - *(((volatile __u8 *) this->IO_ADDR_W) + 0x8) = 0; - break; - case NAND_CTL_SETALE: - *(((volatile __u8 *) this->IO_ADDR_W) + 0x9) = 0; - break; - case NAND_CTL_CLRALE: - *(((volatile __u8 *) this->IO_ADDR_W) + 0x8) = 0; - break; - case NAND_CTL_SETNCE: - *(((volatile __u8 *) this->IO_ADDR_W) + 0x8) = 0; - break; - case NAND_CTL_CLRNCE: - *(((volatile __u8 *) this->IO_ADDR_W) + 0xc) = 0; - break; + case NAND_CTL_SETCLE: + *(((volatile __u8 *) this->IO_ADDR_W) + 0xa) = 0; + break; + case NAND_CTL_CLRCLE: + *(((volatile __u8 *) this->IO_ADDR_W) + 0x8) = 0; + break; + case NAND_CTL_SETALE: + *(((volatile __u8 *) this->IO_ADDR_W) + 0x9) = 0; + break; + case NAND_CTL_CLRALE: + *(((volatile __u8 *) this->IO_ADDR_W) + 0x8) = 0; + break; + case NAND_CTL_SETNCE: + *(((volatile __u8 *) this->IO_ADDR_W) + 0x8) = 0; + break; + case NAND_CTL_CLRNCE: + *(((volatile __u8 *) this->IO_ADDR_W) + 0xc) = 0; + break; } } #else diff --git a/board/nc650/nc650.c b/board/nc650/nc650.c index c90ac9c..8a6b5b0 100644 --- a/board/nc650/nc650.c +++ b/board/nc650/nc650.c @@ -265,8 +265,8 @@ int misc_init_r(void) int iCompatMode = 0; char *pParam = NULL; char *envlb; - - /* + + /* First byte in CPLD read address space signals compatibility mode 0 - cp850 1 - kp852 @@ -274,9 +274,9 @@ int misc_init_r(void) pParam = (char*)(CFG_CPLD_BASE); if( *pParam != 0) iCompatMode = 1; - + if ( iCompatMode != 0) { - /* + /* In KP852 compatibility mode we have to write to DPRAM as early as possible the binary coded line config and board name. @@ -288,7 +288,7 @@ int misc_init_r(void) setenv( DPRAM_VARNAME, DEFAULT_LB); envlb = DEFAULT_LB; } - + /* Status string */ printf("Mode: KP852(LB=%s)\n", envlb); @@ -305,7 +305,7 @@ int misc_init_r(void) } else { puts("Mode: CP850\n"); } - + return 0; } #endif diff --git a/board/omap1610inn/lowlevel_init.S b/board/omap1610inn/lowlevel_init.S index eaf1742..cc8347f 100644 --- a/board/omap1610inn/lowlevel_init.S +++ b/board/omap1610inn/lowlevel_init.S @@ -382,7 +382,7 @@ REG_WATCHDOG: .word 0xfffec808 REG_MPU_LOAD_TIMER: - .word 0xfffec600 + .word 0xfffec504 REG_MPU_CNTL_TIMER: .word 0xfffec500 diff --git a/board/omap5912osk/lowlevel_init.S b/board/omap5912osk/lowlevel_init.S index 3b9633a..a1fa097 100644 --- a/board/omap5912osk/lowlevel_init.S +++ b/board/omap5912osk/lowlevel_init.S @@ -41,6 +41,13 @@ _TEXT_BASE: .globl lowlevel_init lowlevel_init: + /*------------------------------------------------------* + * Ensure i-cache is enabled * + * To configure TC regs without fetching instruction * + *------------------------------------------------------*/ + mrc p15, 0, r0, c1, c0 + orr r0, r0, #0x1000 + mcr p15, 0, r0, c1, c0 /*------------------------------------------------------* *mask all IRQs by setting all bits in the INTMR default* @@ -59,33 +66,34 @@ lowlevel_init: str r1, [r0] /*------------------------------------------------------* - * Set up ARM CLM registers (IDLECT2) * + * Set up ARM CLM registers (IDLECT2) * *------------------------------------------------------*/ ldr r0, REG_ARM_IDLECT2 ldr r1, VAL_ARM_IDLECT2 str r1, [r0] /*------------------------------------------------------* - * Set up ARM CLM registers (IDLECT3) * + * Set up ARM CLM registers (IDLECT3) * *------------------------------------------------------*/ ldr r0, REG_ARM_IDLECT3 ldr r1, VAL_ARM_IDLECT3 str r1, [r0] - - mov r1, #0x01 /* PER_EN bit */ + mov r1, #0x01 /* PER_EN bit */ ldr r0, REG_ARM_RSTCT2 - strh r1, [r0] /* CLKM; Peripheral reset. */ + strh r1, [r0] /* CLKM; Peripheral reset. */ - /* Set CLKM to Sync-Scalable */ - /* I supposedly need to enable the dsp clock before switching */ - mov r1, #0x0000 + /* Set CLKM to Sync-Scalable */ + mov r1, #0x1000 ldr r0, REG_ARM_SYSST - strh r1, [r0] - mov r0, #0x400 -1: - subs r0, r0, #0x1 /* wait for any bubbles to finish */ + + mov r2, #0 +1: cmp r2, #1 + streqh r1, [r0] + add r2, r2, #1 + cmp r2, #0x100 /* wait for any bubbles to finish */ bne 1b + ldr r1, VAL_ARM_CKCTL ldr r0, REG_ARM_CKCTL strh r1, [r0] @@ -107,17 +115,16 @@ lowlevel_init: ldr r1, VAL_DPLL1_CTL ldr r0, REG_DPLL1_CTL strh r1, [r0] - ands r1, r1, #0x10 /* Check if PLL is enabled. */ - beq lock_end /* Do not look for lock if BYPASS selected */ + ands r1, r1, #0x10 /* Check if PLL is enabled. */ + beq lock_end /* Do not look for lock if BYPASS selected */ 2: ldrh r1, [r0] - ands r1, r1, #0x01 /* Check the LOCK bit.*/ - beq 2b /* loop until bit goes hi. */ + ands r1, r1, #0x01 /* Check the LOCK bit.*/ + beq 2b /* loop until bit goes hi. */ lock_end: - /*------------------------------------------------------* - * Turn off the watchdog during init... * + * Turn off the watchdog during init... * *------------------------------------------------------*/ ldr r0, REG_WATCHDOG ldr r1, WATCHDOG_VAL1 @@ -143,30 +150,49 @@ watch2Wait: tst r1, #0x10 bne watch2Wait - /* Set memory timings corresponding to the new clock speed */ + ldr r3, VAL_SDRAM_CONFIG_SDF0 /* Check execution location to determine current execution location * and branch to appropriate initialization code. */ - /* Load physical SDRAM base. */ - mov r0, #0x10000000 - /* Get current execution location. */ - mov r1, pc - /* Compare. */ - cmp r1, r0 - /* Skip over EMIF-fast initialization if running from SDRAM. */ - bge skip_sdram + mov r0, #0x10000000 /* Load physical SDRAM base. */ + mov r1, pc /* Get current execution location. */ + cmp r1, r0 /* Compare. */ + bge skip_sdram /* Skip over EMIF-fast initialization if running from SDRAM. */ + + /* identify the device revision, -- TMX or TMP(TMS) */ + ldr r0, REG_DEVICE_ID + ldr r1, [r0] + + ldr r0, VAL_DEVICE_ID_TMP + mov r1, r1, lsl #15 + mov r1, r1, lsr #16 + cmp r0, r1 + bne skip_TMP_Patch + + /* Enable TMP/TMS device new features */ + mov r0, #1 + ldr r1, REG_TC_EMIFF_DOUBLER + str r0, [r1] + + /* Enable new ac parameters */ + mov r0, #0x0b + ldr r1, REG_SDRAM_CONFIG2 + str r0, [r1] + + ldr r3, VAL_SDRAM_CONFIG_SDF1 + +skip_TMP_Patch: /* * Delay for SDRAM initialization. */ - mov r3, #0x1800 /* value should be checked */ + mov r0, #0x1800 /* value should be checked */ 3: - subs r3, r3, #0x1 /* Decrement count */ + subs r0, r0, #0x1 /* Decrement count */ bne 3b - /* * Set SDRAM control values. Disable refresh before MRS command. */ @@ -178,14 +204,15 @@ watch2Wait: /* config register */ ldr r0, REG_SDRAM_CONFIG - ldr r1, SDRAM_CONFIG_VAL - str r1, [r0] + str r3, [r0] /* manual command register */ ldr r0, REG_SDRAM_MANUAL_CMD + /* issue set cke high */ mov r1, #CMD_SDRAM_CKE_SET_HIGH str r1, [r0] + /* issue nop */ mov r1, #CMD_SDRAM_NOP str r1, [r0] @@ -228,25 +255,23 @@ waitMDDR1: str r1, [r0] /* delay loop */ - mov r2, #0x0100 + mov r0, #0x0100 waitMDDR2: - subs r2, r2, #1 + subs r0, r0, #1 bne waitMDDR2 /* * Delay for SDRAM initialization. */ - mov r3, #0x1800 + mov r0, #0x1800 4: - subs r3, r3, #1 /* Decrement count. */ + subs r0, r0, #1 /* Decrement count. */ bne 4b b common_tc skip_sdram: - ldr r0, REG_SDRAM_CONFIG - ldr r1, SDRAM_CONFIG_VAL - str r1, [r0] + str r3, [r0] common_tc: /* slow interface */ @@ -257,10 +282,15 @@ common_tc: ldr r1, VAL_TC_EMIFS_CS1_CONFIG ldr r0, REG_TC_EMIFS_CS1_CONFIG str r1, [r0] /* Chip Select 1 */ + ldr r1, VAL_TC_EMIFS_CS3_CONFIG ldr r0, REG_TC_EMIFS_CS3_CONFIG str r1, [r0] /* Chip Select 3 */ + ldr r1, VAL_TC_EMIFS_DWS + ldr r0, REG_TC_EMIFS_DWS + str r1, [r0] /* Enable EMIFS.RDY for CS1 (ether) */ + #ifdef CONFIG_H2_OMAP1610 /* inserting additional 2 clock cycle hold time for LAN */ ldr r0, REG_TC_EMIFS_CS1_ADVANCED @@ -282,8 +312,9 @@ common_tc: /* the literal pools origin */ .ltorg - -REG_TC_EMIFS_CONFIG: /* 32 bits */ +REG_DEVICE_ID: /* 32 bits */ + .word 0xfffe2004 +REG_TC_EMIFS_CONFIG: .word 0xfffecc0c REG_TC_EMIFS_CS0_CONFIG: /* 32 bits */ .word 0xfffecc10 @@ -293,7 +324,8 @@ REG_TC_EMIFS_CS2_CONFIG: /* 32 bits */ .word 0xfffecc18 REG_TC_EMIFS_CS3_CONFIG: /* 32 bits */ .word 0xfffecc1c - +REG_TC_EMIFS_DWS: /* 32 bits */ + .word 0xfffecc40 #ifdef CONFIG_H2_OMAP1610 REG_TC_EMIFS_CS1_ADVANCED: /* 32 bits */ .word 0xfffecc54 @@ -302,18 +334,17 @@ REG_TC_EMIFS_CS1_ADVANCED: /* 32 bits */ /* MPU clock/reset/power mode control registers */ REG_ARM_CKCTL: /* 16 bits */ .word 0xfffece00 - REG_ARM_IDLECT3: /* 16 bits */ .word 0xfffece24 REG_ARM_IDLECT2: /* 16 bits */ .word 0xfffece08 REG_ARM_IDLECT1: /* 16 bits */ .word 0xfffece04 - REG_ARM_RSTCT2: /* 16 bits */ .word 0xfffece14 REG_ARM_SYSST: /* 16 bits */ .word 0xfffece18 + /* DPLL control registers */ REG_DPLL1_CTL: /* 16 bits */ .word 0xfffecf00 @@ -335,6 +366,10 @@ WSPRDOG_VAL2: counter @8192 rows, 10 ns, 8 burst */ REG_SDRAM_CONFIG: .word 0xfffecc20 +REG_SDRAM_CONFIG2: + .word 0xfffecc3c +REG_TC_EMIFF_DOUBLER: /* 32 bits */ + .word 0xfffecc60 /* Operation register */ REG_SDRAM_OPERATION: @@ -356,35 +391,47 @@ REG_SDRAM_EMRS1: REG_DLL_WRT_CONTROL: .word 0xfffecc68 DLL_WRT_CONTROL_VAL: - .word 0x03f00002 + .word 0x03f00002 /* Phase of 72deg, write offset +31 */ /* URD DLL register */ REG_DLL_URD_CONTROL: .word 0xfffeccc0 DLL_URD_CONTROL_VAL: - .word 0x00800002 + .word 0x00800002 /* Phase of 72deg, read offset +31 */ /* LRD DLL register */ REG_DLL_LRD_CONTROL: .word 0xfffecccc +DLL_LRD_CONTROL_VAL: + .word 0x00800002 /* read offset +31 */ REG_WATCHDOG: .word 0xfffec808 +WATCHDOG_VAL1: + .word 0x000000f5 +WATCHDOG_VAL2: + .word 0x000000a0 REG_MPU_LOAD_TIMER: - .word 0xfffec600 + .word 0xfffec504 REG_MPU_CNTL_TIMER: .word 0xfffec500 +VAL_MPU_LOAD_TIMER: + .word 0xffffffff +VAL_MPU_CNTL_TIMER: + .word 0xffffffa1 /* 96 MHz Samsung Mobile DDR */ -SDRAM_CONFIG_VAL: - .word 0x001200f4 +/* Original setting for TMX device */ +VAL_SDRAM_CONFIG_SDF0: + .word 0x0014e6fe -DLL_LRD_CONTROL_VAL: - .word 0x00800002 +/* NEW_SYS_FREQ mode (valid only TMP/TMS devices) */ +VAL_SDRAM_CONFIG_SDF1: + .word 0x0114e6fe VAL_ARM_CKCTL: - .word 0x3000 + .word 0x2000 /* was: 0x3000, now use CLK_REF for timer input */ VAL_DPLL1_CTL: .word 0x2830 @@ -392,11 +439,15 @@ VAL_DPLL1_CTL: VAL_TC_EMIFS_CS0_CONFIG: .word 0x002130b0 VAL_TC_EMIFS_CS1_CONFIG: - .word 0x00001131 + .word 0x00001133 VAL_TC_EMIFS_CS2_CONFIG: .word 0x000055f0 VAL_TC_EMIFS_CS3_CONFIG: - .word 0x88011131 + .word 0x88013141 +VAL_TC_EMIFS_DWS: /* Enable EMIFS.RDY for CS1 access (ether) */ + .word 0x000000c0 +VAL_DEVICE_ID_TMP: /* TMP/TMS=0xb65f, TMX=0xb58c */ + .word 0xb65f #endif #ifdef CONFIG_H2_OMAP1610 @@ -407,36 +458,20 @@ VAL_TC_EMIFS_CS1_CONFIG: VAL_TC_EMIFS_CS2_CONFIG: .word 0xf800f22a VAL_TC_EMIFS_CS3_CONFIG: - .word 0x88011131 + .word 0x88013141 VAL_TC_EMIFS_CS1_ADVANCED: .word 0x00000022 #endif -VAL_TC_EMIFF_SDRAM_CONFIG: - .word 0x010290fc -VAL_TC_EMIFF_MRS: - .word 0x00000027 - VAL_ARM_IDLECT1: .word 0x00000400 - VAL_ARM_IDLECT2: .word 0x00000886 VAL_ARM_IDLECT3: .word 0x00000015 -WATCHDOG_VAL1: - .word 0x000000f5 -WATCHDOG_VAL2: - .word 0x000000a0 - -VAL_MPU_LOAD_TIMER: - .word 0xffffffff -VAL_MPU_CNTL_TIMER: - .word 0xffffffa1 - /* command values */ -.equ CMD_SDRAM_NOP, 0x00000000 -.equ CMD_SDRAM_PRECHARGE, 0x00000001 -.equ CMD_SDRAM_AUTOREFRESH, 0x00000002 -.equ CMD_SDRAM_CKE_SET_HIGH, 0x00000007 +.equ CMD_SDRAM_NOP, 0x00000000 +.equ CMD_SDRAM_PRECHARGE, 0x00000001 +.equ CMD_SDRAM_AUTOREFRESH, 0x00000002 +.equ CMD_SDRAM_CKE_SET_HIGH, 0x00000007 diff --git a/board/omap5912osk/omap5912osk.c b/board/omap5912osk/omap5912osk.c index e9e6b0e..6993b13 100644 --- a/board/omap5912osk/omap5912osk.c +++ b/board/omap5912osk/omap5912osk.c @@ -288,3 +288,21 @@ void peripheral_power_enable (void) *SW_CLOCK_REQUEST |= UART1_48MHZ_ENABLE; } + +/* + * Check Board Identity + */ +int checkboard(void) +{ + char *s = getenv("serial#"); + + puts("Board: OSK5912"); + + if (s != NULL) { + puts(", serial# "); + puts(s); + } + putc('\n'); + + return (0); +} diff --git a/board/omap730p2/lowlevel_init.S b/board/omap730p2/lowlevel_init.S index 6c6f482..9ab71cf 100644 --- a/board/omap730p2/lowlevel_init.S +++ b/board/omap730p2/lowlevel_init.S @@ -317,7 +317,7 @@ REG_WATCHDOG: .word 0xfffec808 REG_MPU_LOAD_TIMER: - .word 0xfffec600 + .word 0xfffec504 REG_MPU_CNTL_TIMER: .word 0xfffec500 diff --git a/board/pcs440ep/Makefile b/board/pcs440ep/Makefile new file mode 100644 index 0000000..4a2a388 --- /dev/null +++ b/board/pcs440ep/Makefile @@ -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 + +######################################################################### diff --git a/board/pcs440ep/config.mk b/board/pcs440ep/config.mk new file mode 100644 index 0000000..319c4fa --- /dev/null +++ b/board/pcs440ep/config.mk @@ -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 diff --git a/board/pcs440ep/flash.c b/board/pcs440ep/flash.c new file mode 100644 index 0000000..ece5478 --- /dev/null +++ b/board/pcs440ep/flash.c @@ -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 +#include + +#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; isector_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; kstart[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; i0; ++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); +} diff --git a/board/pcs440ep/init.S b/board/pcs440ep/init.S new file mode 100644 index 0000000..0eee4d8 --- /dev/null +++ b/board/pcs440ep/init.S @@ -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 +#include + +/* 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 diff --git a/board/pcs440ep/pcs440ep.c b/board/pcs440ep/pcs440ep.c new file mode 100644 index 0000000..8858f0a --- /dev/null +++ b/board/pcs440ep/pcs440ep.c @@ -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 +#include +#include +#include + +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 diff --git a/board/mpc8349ads/u-boot.lds b/board/pcs440ep/u-boot.lds similarity index 82% rename from board/mpc8349ads/u-boot.lds rename to board/pcs440ep/u-boot.lds index 020cfa6..6ab476a 100644 --- a/board/mpc8349ads/u-boot.lds +++ b/board/pcs440ep/u-boot.lds @@ -1,5 +1,6 @@ /* - * Copyright 2004 Freescale Semiconductor, Inc. + * (C) Copyright 2006 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this * project. @@ -21,8 +22,21 @@ */ 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) } @@ -49,11 +63,17 @@ SECTIONS .plt : { *(.plt) } .text : { - cpu/mpc83xx/start.o (.text) + cpu/ppc4xx/start.o (.text) + board/pcs440ep/init.o (.text) + *(.text) *(.fixup) *(.got1) - . = ALIGN(16); + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { *(.rodata) *(.rodata1) *(.rodata.str1.4) @@ -64,7 +84,7 @@ SECTIONS .dtors : { *(.dtors) } /* Read-write section, merged into data segment: */ - . = (. + 0x0FFF) & 0xFFFFF000; + . = (. + 0x00FF) & 0xFFFFFF00; _erotext = .; PROVIDE (erotext = .); .reloc : @@ -95,17 +115,16 @@ SECTIONS .u_boot_cmd : { *(.u_boot_cmd) } __u_boot_cmd_end = .; - . = .; __start___ex_table = .; __ex_table : { *(__ex_table) } __stop___ex_table = .; - . = ALIGN(4096); + . = ALIGN(256); __init_begin = .; .text.init : { *(.text.init) } .data.init : { *(.data.init) } - . = ALIGN(4096); + . = ALIGN(256); __init_end = .; __bss_start = .; @@ -116,7 +135,7 @@ SECTIONS *(.bss) *(COMMON) } + _end = . ; PROVIDE (end = .); } -ENTRY(_start) diff --git a/board/prodrive/common/flash.c b/board/prodrive/common/flash.c new file mode 100644 index 0000000..8630cc1 --- /dev/null +++ b/board/prodrive/common/flash.c @@ -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 +#include + +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; isector_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; kstart[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; i0; ++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); +} diff --git a/board/prodrive/common/fpga.c b/board/prodrive/common/fpga.c new file mode 100644 index 0000000..f9412a2 --- /dev/null +++ b/board/prodrive/common/fpga.c @@ -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 +#include +#include + +/* ------------------------------------------------------------------------- */ + +#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 3) { + DBG("FPGA: Booting failed!\n"); + return ERROR_FPGA_PRG_DONE; + } + } + + DBG("FPGA: Booting successful!\n"); + return 0; +} diff --git a/board/mpc8349ads/Makefile b/board/prodrive/pdnb3/Makefile similarity index 90% rename from board/mpc8349ads/Makefile rename to board/prodrive/pdnb3/Makefile index f865f9c..f3cd5a3 100644 --- a/board/mpc8349ads/Makefile +++ b/board/prodrive/pdnb3/Makefile @@ -1,5 +1,6 @@ # -# Copyright 2004 Freescale Semiconductor, Inc. +# (C) Copyright 2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. # # See file CREDITS for list of people who contributed to this # project. @@ -24,10 +25,10 @@ include $(TOPDIR)/config.mk LIB = lib$(BOARD).a -OBJS := $(BOARD).o pci.o +OBJS := flash.o pdnb3.o nand.o $(LIB): $(OBJS) $(SOBJS) - $(AR) crv $@ $(OBJS) + $(AR) crv $@ $^ clean: rm -f $(SOBJS) $(OBJS) diff --git a/board/prodrive/pdnb3/config.mk b/board/prodrive/pdnb3/config.mk new file mode 100644 index 0000000..6b0f18b --- /dev/null +++ b/board/prodrive/pdnb3/config.mk @@ -0,0 +1,4 @@ +TEXT_BASE = 0x01f00000 + +# include NPE ethernet driver +BOARDLIBS = cpu/ixp/npe/libnpe.a diff --git a/board/prodrive/pdnb3/flash.c b/board/prodrive/pdnb3/flash.c new file mode 100644 index 0000000..d0e5fe7 --- /dev/null +++ b/board/prodrive/pdnb3/flash.c @@ -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 +#include + +/* + * 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 + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) + +#include + +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 diff --git a/board/prodrive/pdnb3/pdnb3.c b/board/prodrive/pdnb3/pdnb3.c new file mode 100644 index 0000000..e2fed5d --- /dev/null +++ b/board/prodrive/pdnb3/pdnb3.c @@ -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 +#include +#include +#include + +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
\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 diff --git a/board/prodrive/pdnb3/u-boot.lds b/board/prodrive/pdnb3/u-boot.lds new file mode 100644 index 0000000..f05f093 --- /dev/null +++ b/board/prodrive/pdnb3/u-boot.lds @@ -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 = .; +} diff --git a/board/r5200/Makefile b/board/r5200/Makefile new file mode 100644 index 0000000..d0364ed --- /dev/null +++ b/board/r5200/Makefile @@ -0,0 +1,40 @@ +# +# (C) Copyright 2000-2003 +# 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 + +$(LIB): .depend $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/r5200/config.mk b/board/r5200/config.mk new file mode 100644 index 0000000..8fc5319 --- /dev/null +++ b/board/r5200/config.mk @@ -0,0 +1,25 @@ +# +# (C) Copyright 2000-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# Coldfire contribution by Bernhard Kuhn +# +# 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 +# + +TEXT_BASE = 0x10000000 diff --git a/board/r5200/r5200.c b/board/r5200/r5200.c new file mode 100644 index 0000000..69f3a76 --- /dev/null +++ b/board/r5200/r5200.c @@ -0,0 +1,124 @@ +/* + * (C) Copyright 2000-2003 + * 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 +#include +#include + + +int checkboard (void) { + puts ("Board: R5200 Ethernet Module\n"); + return 0; +}; + +long int initdram (int board_type) { + int i; + + /* + * Set CS2 pin to be SD_CS0 + */ + mbar_writeByte(MCF_GPIO_PAR_CS, mbar_readByte(MCF_GPIO_PAR_CS) + | MCF_GPIO_PAR_CS_PAR_CS2); + + mbar_writeByte(MCF_GPIO_PAR_SDRAM, mbar_readByte(MCF_GPIO_PAR_SDRAM) + | MCF_GPIO_PAR_SDRAM_PAR_CSSDCS(0x01)); + + /* + * Check to see if the SDRAM has already been initialized + * by a run control tool + */ + if (!(mbar_readLong(MCF_SDRAMC_DACR0) & MCF_SDRAMC_DACRn_RE)) { + /* + * Initialize DRAM Control Register: DCR + */ + mbar_writeShort(MCF_SDRAMC_DCR, MCF_SDRAMC_DCR_RTIM(0x01) + | MCF_SDRAMC_DCR_RC(0x30)); + + /* + * Initialize DACR0 + */ + mbar_writeLong(MCF_SDRAMC_DACR0, + MCF_SDRAMC_DACRn_BA(CFG_SDRAM_BASE>>18) + | MCF_SDRAMC_DACRn_CASL(0) + | MCF_SDRAMC_DACRn_CBM(3) + | MCF_SDRAMC_DACRn_PS(2)); + + /* + * Initialize DMR0 + */ + mbar_writeLong(MCF_SDRAMC_DMR0, + MCF_SDRAMC_DMRn_BAM_8M + | MCF_SDRAMC_DMRn_V); + + /* + * Set IP bit in DACR + */ + mbar_writeLong(MCF_SDRAMC_DACR0, mbar_readLong(MCF_SDRAMC_DACR0) + | MCF_SDRAMC_DACRn_IP); + + /* + * Wait at least 20ns to allow banks to precharge + */ + for (i = 0; i < 5; i++) + asm(" nop"); + + /* + * Write to this block to initiate precharge + */ + *(u16 *)(CFG_SDRAM_BASE) = 0x9696; + + /* + * Set RE bit in DACR + */ + mbar_writeLong(MCF_SDRAMC_DACR0, mbar_readLong(MCF_SDRAMC_DACR0) + | MCF_SDRAMC_DACRn_RE); + + + /* + * Wait for at least 8 auto refresh cycles to occur + */ + for (i = 0; i < 2000; i++) + asm(" nop"); + + /* + * Finish the configuration by issuing the MRS. + */ + mbar_writeLong(MCF_SDRAMC_DACR0, mbar_readLong(MCF_SDRAMC_DACR0) + | MCF_SDRAMC_DACRn_MRS); + + + /* + * Write to the SDRAM Mode Register + */ + *(u16 *)(CFG_SDRAM_BASE + 0x1000) = 0x9696; + } + + return CFG_SDRAM_SIZE * 1024 * 1024; +}; + +int testdram (void) { + /* TODO: XXX XXX XXX */ + printf ("DRAM test not implemented!\n"); + + return (0); +} diff --git a/board/r5200/u-boot.lds b/board/r5200/u-boot.lds new file mode 100644 index 0000000..f7dc070 --- /dev/null +++ b/board/r5200/u-boot.lds @@ -0,0 +1,144 @@ +/* + * (C) Copyright 2000 + * 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(m68k) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +SECTIONS +{ + /* 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 : + { + /* WARNING - the following is hand-optimized to fit within */ + /* the sector layout of our flash chips! XXX FIXME XXX */ + + cpu/mcf52x2/start.o (.text) + lib_m68k/traps.o (.text) + cpu/mcf52x2/interrupts.o (.text) + common/dlmalloc.o (.text) + lib_generic/zlib.o (.text) + + . = DEFINED(env_offset) ? env_offset : .; + common/environment.o (.text) + + *(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x00FF) & 0xFFFFFF00; + _erotext = .; + PROVIDE (erotext = .); + + .reloc : + { + __got_start = .; + *(.got) + __got_end = .; + _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 = .; + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + . = ALIGN(4); + _ebss = .; + } + _end = . ; + PROVIDE (end = .); +} diff --git a/board/tqm8xx/tqm8xx.c b/board/tqm8xx/tqm8xx.c index 520bea8..b292231 100644 --- a/board/tqm8xx/tqm8xx.c +++ b/board/tqm8xx/tqm8xx.c @@ -1,5 +1,5 @@ /* - * (C) Copyright 2000-2004 + * (C) Copyright 2000-2006 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this @@ -124,6 +124,9 @@ int checkboard (void) break; putc (*s); } +#ifdef CONFIG_VIRTLAB2 + puts (" (Virtlab2)"); +#endif putc ('\n'); return (0); diff --git a/board/zylonite/Makefile b/board/zylonite/Makefile index 999647f..f3ad674 100644 --- a/board/zylonite/Makefile +++ b/board/zylonite/Makefile @@ -1,4 +1,3 @@ - # # (C) Copyright 2000 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. @@ -21,12 +20,11 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, # MA 02111-1307 USA # - include $(TOPDIR)/config.mk LIB = lib$(BOARD).a -OBJS := zylonite.o flash.o +OBJS := zylonite.o nand.o SOBJS := lowlevel_init.o $(LIB): $(OBJS) $(SOBJS) diff --git a/board/zylonite/config.mk b/board/zylonite/config.mk index 09b0f71..b5d5955 100644 --- a/board/zylonite/config.mk +++ b/board/zylonite/config.mk @@ -2,3 +2,5 @@ #TEXT_BASE = 0xa1700000 #TEXT_BASE = 0xa3080000 TEXT_BASE = 0xa3008000 + +BOARDLIBS = drivers/nand/libnand.a diff --git a/board/zylonite/lowlevel_init.S b/board/zylonite/lowlevel_init.S index c3bb4eb..da01765 100644 --- a/board/zylonite/lowlevel_init.S +++ b/board/zylonite/lowlevel_init.S @@ -235,6 +235,7 @@ mem_init: orr r1, r1, #0x40000000 @ enable SDRAM for Normal Access str r1, [r0] +#ifndef CFG_SKIP_DRAM_SCRUB /* scrub/init SDRAM if enabled/present */ /* ldr r11, =0xa0000000 /\* base address of SDRAM (CFG_DRAM_BASE) *\/ */ /* ldr r12, =0x04000000 /\* size of memory to scrub (CFG_DRAM_SIZE) *\/ */ @@ -254,6 +255,7 @@ mem_init: stmia r8!, {r0-r7} beq 15f b 10b +#endif /* CFG_SKIP_DRAM_SCRUB */ 15: /* Mask all interrupts */ diff --git a/board/zylonite/nand.c b/board/zylonite/nand.c new file mode 100644 index 0000000..5d2cd65 --- /dev/null +++ b/board/zylonite/nand.c @@ -0,0 +1,584 @@ +/* + * (C) Copyright 2006 DENX Software Engineering + * + * 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 + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) +#ifdef CONFIG_NEW_NAND_CODE + +#include +#include + +#ifdef CFG_DFC_DEBUG1 +# define DFC_DEBUG1(fmt, args...) printf(fmt, ##args) +#else +# define DFC_DEBUG1(fmt, args...) +#endif + +#ifdef CFG_DFC_DEBUG2 +# define DFC_DEBUG2(fmt, args...) printf(fmt, ##args) +#else +# define DFC_DEBUG2(fmt, args...) +#endif + +#ifdef CFG_DFC_DEBUG3 +# define DFC_DEBUG3(fmt, args...) printf(fmt, ##args) +#else +# define DFC_DEBUG3(fmt, args...) +#endif + +#define MIN(x, y) ((x < y) ? x : y) + +/* These really don't belong here, as they are specific to the NAND Model */ +static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; + +static struct nand_bbt_descr delta_bbt_descr = { + .options = 0, + .offs = 0, + .len = 2, + .pattern = scan_ff_pattern +}; + +static struct nand_oobinfo delta_oob = { + .useecc = MTD_NANDECC_AUTOPL_USR, /* MTD_NANDECC_PLACEONLY, */ + .eccbytes = 6, + .eccpos = {2, 3, 4, 5, 6, 7}, + .oobfree = { {8, 2}, {12, 4} } +}; + + +/* + * not required for Monahans DFC + */ +static void dfc_hwcontrol(struct mtd_info *mtdinfo, int cmd) +{ + return; +} + +#if 0 +/* read device ready pin */ +static int dfc_device_ready(struct mtd_info *mtdinfo) +{ + if(NDSR & NDSR_RDY) + return 1; + else + return 0; + return 0; +} +#endif + +/* + * Write buf to the DFC Controller Data Buffer + */ +static void dfc_write_buf(struct mtd_info *mtd, const u_char *buf, int len) +{ + unsigned long bytes_multi = len & 0xfffffffc; + unsigned long rest = len & 0x3; + unsigned long *long_buf; + int i; + + DFC_DEBUG2("dfc_write_buf: writing %d bytes starting with 0x%x.\n", len, *((unsigned long*) buf)); + if(bytes_multi) { + for(i=0; i>j) & 0xff); + } + + return; +} + +/* + * read a word. Not implemented as not used in NAND code. + */ +static u16 dfc_read_word(struct mtd_info *mtd) +{ + printf("dfc_write_byte: UNIMPLEMENTED.\n"); + return 0; +} + +/* global var, too bad: mk@tbd: move to ->priv pointer */ +static unsigned long read_buf = 0; +static int bytes_read = -1; + +/* + * read a byte from NDDB Because we can only read 4 bytes from NDDB at + * a time, we buffer the remaining bytes. The buffer is reset when a + * new command is sent to the chip. + * + * WARNING: + * This function is currently only used to read status and id + * bytes. For these commands always 8 bytes need to be read from + * NDDB. So we read and discard these bytes right now. In case this + * function is used for anything else in the future, we must check + * what was the last command issued and read the appropriate amount of + * bytes respectively. + */ +static u_char dfc_read_byte(struct mtd_info *mtd) +{ + unsigned char byte; + unsigned long dummy; + + if(bytes_read < 0) { + read_buf = NDDB; + dummy = NDDB; + bytes_read = 0; + } + byte = (unsigned char) (read_buf>>(8 * bytes_read++)); + if(bytes_read >= 4) + bytes_read = -1; + + DFC_DEBUG2("dfc_read_byte: byte %u: 0x%x of (0x%x).\n", bytes_read - 1, byte, read_buf); + return byte; +} + +/* calculate delta between OSCR values start and now */ +static unsigned long get_delta(unsigned long start) +{ + unsigned long cur = OSCR; + + if(cur < start) /* OSCR overflowed */ + return (cur + (start^0xffffffff)); + else + return (cur - start); +} + +/* delay function, this doesn't belong here */ +static void wait_us(unsigned long us) +{ + unsigned long start = OSCR; + us *= OSCR_CLK_FREQ; + + while (get_delta(start) < us) { + /* do nothing */ + } +} + +static void dfc_clear_nddb(void) +{ + NDCR &= ~NDCR_ND_RUN; + wait_us(CFG_NAND_OTHER_TO); +} + +/* wait_event with timeout */ +static unsigned long dfc_wait_event(unsigned long event) +{ + unsigned long ndsr, timeout, start = OSCR; + + if(!event) + return 0xff000000; + else if(event & (NDSR_CS0_CMDD | NDSR_CS0_BBD)) + timeout = CFG_NAND_PROG_ERASE_TO * OSCR_CLK_FREQ; + else + timeout = CFG_NAND_OTHER_TO * OSCR_CLK_FREQ; + + while(1) { + ndsr = NDSR; + if(ndsr & event) { + NDSR |= event; + break; + } + if(get_delta(start) > timeout) { + DFC_DEBUG1("dfc_wait_event: TIMEOUT waiting for event: 0x%x.\n", event); + return 0xff000000; + } + + } + return ndsr; +} + +/* we don't always wan't to do this */ +static void dfc_new_cmd(void) +{ + int retry = 0; + unsigned long status; + + while(retry++ <= CFG_NAND_SENDCMD_RETRY) { + /* Clear NDSR */ + NDSR = 0xFFF; + + /* set NDCR[NDRUN] */ + if(!(NDCR & NDCR_ND_RUN)) + NDCR |= NDCR_ND_RUN; + + status = dfc_wait_event(NDSR_WRCMDREQ); + + if(status & NDSR_WRCMDREQ) + return; + + DFC_DEBUG2("dfc_new_cmd: FAILED to get WRITECMDREQ, retry: %d.\n", retry); + dfc_clear_nddb(); + } + DFC_DEBUG1("dfc_new_cmd: giving up after %d retries.\n", retry); +} + +/* this function is called after Programm and Erase Operations to + * check for success or failure */ +static int dfc_wait(struct mtd_info *mtd, struct nand_chip *this, int state) +{ + unsigned long ndsr=0, event=0; + + if(state == FL_WRITING) { + event = NDSR_CS0_CMDD | NDSR_CS0_BBD; + } else if(state == FL_ERASING) { + event = NDSR_CS0_CMDD | NDSR_CS0_BBD; + } + + ndsr = dfc_wait_event(event); + + if((ndsr & NDSR_CS0_BBD) || (ndsr & 0xff000000)) + return(0x1); /* Status Read error */ + return 0; +} + +/* cmdfunc send commands to the DFC */ +static void dfc_cmdfunc(struct mtd_info *mtd, unsigned command, + int column, int page_addr) +{ + /* register struct nand_chip *this = mtd->priv; */ + unsigned long ndcb0=0, ndcb1=0, ndcb2=0, event=0; + + /* clear the ugly byte read buffer */ + bytes_read = -1; + read_buf = 0; + + switch (command) { + case NAND_CMD_READ0: + DFC_DEBUG3("dfc_cmdfunc: NAND_CMD_READ0, page_addr: 0x%x, column: 0x%x.\n", page_addr, (column>>1)); + dfc_new_cmd(); + ndcb0 = (NAND_CMD_READ0 | (4<<16)); + column >>= 1; /* adjust for 16 bit bus */ + ndcb1 = (((column>>1) & 0xff) | + ((page_addr<<8) & 0xff00) | + ((page_addr<<8) & 0xff0000) | + ((page_addr<<8) & 0xff000000)); /* make this 0x01000000 ? */ + event = NDSR_RDDREQ; + goto write_cmd; + case NAND_CMD_READ1: + DFC_DEBUG2("dfc_cmdfunc: NAND_CMD_READ1 unimplemented!\n"); + goto end; + case NAND_CMD_READOOB: + DFC_DEBUG1("dfc_cmdfunc: NAND_CMD_READOOB unimplemented!\n"); + goto end; + case NAND_CMD_READID: + dfc_new_cmd(); + DFC_DEBUG2("dfc_cmdfunc: NAND_CMD_READID.\n"); + ndcb0 = (NAND_CMD_READID | (3 << 21) | (1 << 16)); /* addr cycles*/ + event = NDSR_RDDREQ; + goto write_cmd; + case NAND_CMD_PAGEPROG: + /* sent as a multicommand in NAND_CMD_SEQIN */ + DFC_DEBUG2("dfc_cmdfunc: NAND_CMD_PAGEPROG empty due to multicmd.\n"); + goto end; + case NAND_CMD_ERASE1: + DFC_DEBUG2("dfc_cmdfunc: NAND_CMD_ERASE1, page_addr: 0x%x, column: 0x%x.\n", page_addr, (column>>1)); + dfc_new_cmd(); + ndcb0 = (0xd060 | (1<<25) | (2<<21) | (1<<19) | (3<<16)); + ndcb1 = (page_addr & 0x00ffffff); + goto write_cmd; + case NAND_CMD_ERASE2: + DFC_DEBUG2("dfc_cmdfunc: NAND_CMD_ERASE2 empty due to multicmd.\n"); + goto end; + case NAND_CMD_SEQIN: + /* send PAGE_PROG command(0x1080) */ + dfc_new_cmd(); + DFC_DEBUG2("dfc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, page_addr: 0x%x, column: 0x%x.\n", page_addr, (column>>1)); + ndcb0 = (0x1080 | (1<<25) | (1<<21) | (1<<19) | (4<<16)); + column >>= 1; /* adjust for 16 bit bus */ + ndcb1 = (((column>>1) & 0xff) | + ((page_addr<<8) & 0xff00) | + ((page_addr<<8) & 0xff0000) | + ((page_addr<<8) & 0xff000000)); /* make this 0x01000000 ? */ + event = NDSR_WRDREQ; + goto write_cmd; + case NAND_CMD_STATUS: + DFC_DEBUG2("dfc_cmdfunc: NAND_CMD_STATUS.\n"); + dfc_new_cmd(); + ndcb0 = NAND_CMD_STATUS | (4<<21); + event = NDSR_RDDREQ; + goto write_cmd; + case NAND_CMD_RESET: + DFC_DEBUG2("dfc_cmdfunc: NAND_CMD_RESET.\n"); + ndcb0 = NAND_CMD_RESET | (5<<21); + event = NDSR_CS0_CMDD; + goto write_cmd; + default: + printk("dfc_cmdfunc: error, unsupported command.\n"); + goto end; + } + + write_cmd: + NDCB0 = ndcb0; + NDCB0 = ndcb1; + NDCB0 = ndcb2; + + /* wait_event: */ + dfc_wait_event(event); + end: + return; +} + +static void dfc_gpio_init(void) +{ + DFC_DEBUG2("Setting up DFC GPIO's.\n"); + + /* no idea what is done here, see zylonite.c */ + GPIO4 = 0x1; + + DF_ALE_WE1 = 0x00000001; + DF_ALE_WE2 = 0x00000001; + DF_nCS0 = 0x00000001; + DF_nCS1 = 0x00000001; + DF_nWE = 0x00000001; + DF_nRE = 0x00000001; + DF_IO0 = 0x00000001; + DF_IO8 = 0x00000001; + DF_IO1 = 0x00000001; + DF_IO9 = 0x00000001; + DF_IO2 = 0x00000001; + DF_IO10 = 0x00000001; + DF_IO3 = 0x00000001; + DF_IO11 = 0x00000001; + DF_IO4 = 0x00000001; + DF_IO12 = 0x00000001; + DF_IO5 = 0x00000001; + DF_IO13 = 0x00000001; + DF_IO6 = 0x00000001; + DF_IO14 = 0x00000001; + DF_IO7 = 0x00000001; + DF_IO15 = 0x00000001; + + DF_nWE = 0x1901; + DF_nRE = 0x1901; + DF_CLE_NOE = 0x1900; + DF_ALE_WE1 = 0x1901; + DF_INT_RnB = 0x1900; +} + +/* + * Board-specific NAND initialization. The following members of the + * argument are board-specific (per include/linux/mtd/nand_new.h): + * - IO_ADDR_R?: address to read the 8 I/O lines of the flash device + * - IO_ADDR_W?: address to write the 8 I/O lines of the flash device + * - hwcontrol: hardwarespecific function for accesing control-lines + * - dev_ready: hardwarespecific function for accesing device ready/busy line + * - enable_hwecc?: function to enable (reset) hardware ecc generator. Must + * only be provided if a hardware ECC is available + * - eccmode: mode of ecc, see defines + * - chip_delay: chip dependent delay for transfering data from array to + * read regs (tR) + * - options: various chip options. They can partly be set to inform + * nand_scan about special functionality. See the defines for further + * explanation + * Members with a "?" were not set in the merged testing-NAND branch, + * so they are not set here either. + */ +void board_nand_init(struct nand_chip *nand) +{ + unsigned long tCH, tCS, tWH, tWP, tRH, tRP, tRP_high, tR, tWHR, tAR; + + /* set up GPIO Control Registers */ + dfc_gpio_init(); + + /* turn on the NAND Controller Clock (104 MHz @ D0) */ + CKENA |= (CKENA_4_NAND | CKENA_9_SMC); + +#undef CFG_TIMING_TIGHT +#ifndef CFG_TIMING_TIGHT + tCH = MIN(((unsigned long) (NAND_TIMING_tCH * DFC_CLK_PER_US) + 1), + DFC_MAX_tCH); + tCS = MIN(((unsigned long) (NAND_TIMING_tCS * DFC_CLK_PER_US) + 1), + DFC_MAX_tCS); + tWH = MIN(((unsigned long) (NAND_TIMING_tWH * DFC_CLK_PER_US) + 1), + DFC_MAX_tWH); + tWP = MIN(((unsigned long) (NAND_TIMING_tWP * DFC_CLK_PER_US) + 1), + DFC_MAX_tWP); + tRH = MIN(((unsigned long) (NAND_TIMING_tRH * DFC_CLK_PER_US) + 1), + DFC_MAX_tRH); + tRP = MIN(((unsigned long) (NAND_TIMING_tRP * DFC_CLK_PER_US) + 1), + DFC_MAX_tRP); + tR = MIN(((unsigned long) (NAND_TIMING_tR * DFC_CLK_PER_US) + 1), + DFC_MAX_tR); + tWHR = MIN(((unsigned long) (NAND_TIMING_tWHR * DFC_CLK_PER_US) + 1), + DFC_MAX_tWHR); + tAR = MIN(((unsigned long) (NAND_TIMING_tAR * DFC_CLK_PER_US) + 1), + DFC_MAX_tAR); +#else /* this is the tight timing */ + + tCH = MIN(((unsigned long) (NAND_TIMING_tCH * DFC_CLK_PER_US)), + DFC_MAX_tCH); + tCS = MIN(((unsigned long) (NAND_TIMING_tCS * DFC_CLK_PER_US)), + DFC_MAX_tCS); + tWH = MIN(((unsigned long) (NAND_TIMING_tWH * DFC_CLK_PER_US)), + DFC_MAX_tWH); + tWP = MIN(((unsigned long) (NAND_TIMING_tWP * DFC_CLK_PER_US)), + DFC_MAX_tWP); + tRH = MIN(((unsigned long) (NAND_TIMING_tRH * DFC_CLK_PER_US)), + DFC_MAX_tRH); + tRP = MIN(((unsigned long) (NAND_TIMING_tRP * DFC_CLK_PER_US)), + DFC_MAX_tRP); + tR = MIN(((unsigned long) (NAND_TIMING_tR * DFC_CLK_PER_US) - tCH - 2), + DFC_MAX_tR); + tWHR = MIN(((unsigned long) (NAND_TIMING_tWHR * DFC_CLK_PER_US) - tCH - 2), + DFC_MAX_tWHR); + tAR = MIN(((unsigned long) (NAND_TIMING_tAR * DFC_CLK_PER_US) - 2), + DFC_MAX_tAR); +#endif /* CFG_TIMING_TIGHT */ + + + DFC_DEBUG2("tCH=%u, tCS=%u, tWH=%u, tWP=%u, tRH=%u, tRP=%u, tR=%u, tWHR=%u, tAR=%u.\n", tCH, tCS, tWH, tWP, tRH, tRP, tR, tWHR, tAR); + + /* tRP value is split in the register */ + if(tRP & (1 << 4)) { + tRP_high = 1; + tRP &= ~(1 << 4); + } else { + tRP_high = 0; + } + + NDTR0CS0 = (tCH << 19) | + (tCS << 16) | + (tWH << 11) | + (tWP << 8) | + (tRP_high << 6) | + (tRH << 3) | + (tRP << 0); + + NDTR1CS0 = (tR << 16) | + (tWHR << 4) | + (tAR << 0); + + /* If it doesn't work (unlikely) think about: + * - ecc enable + * - chip select don't care + * - read id byte count + * + * Intentionally enabled by not setting bits: + * - dma (DMA_EN) + * - page size = 512 + * - cs don't care, see if we can enable later! + * - row address start position (after second cycle) + * - pages per block = 32 + * - ND_RDY : clears command buffer + */ + /* NDCR_NCSX | /\* Chip select busy don't care *\/ */ + + NDCR = (NDCR_SPARE_EN | /* use the spare area */ + NDCR_DWIDTH_C | /* 16bit DFC data bus width */ + NDCR_DWIDTH_M | /* 16 bit Flash device data bus width */ + (2 << 16) | /* read id count = 7 ???? mk@tbd */ + NDCR_ND_ARB_EN | /* enable bus arbiter */ + NDCR_RDYM | /* flash device ready ir masked */ + NDCR_CS0_PAGEDM | /* ND_nCSx page done ir masked */ + NDCR_CS1_PAGEDM | + NDCR_CS0_CMDDM | /* ND_CSx command done ir masked */ + NDCR_CS1_CMDDM | + NDCR_CS0_BBDM | /* ND_CSx bad block detect ir masked */ + NDCR_CS1_BBDM | + NDCR_DBERRM | /* double bit error ir masked */ + NDCR_SBERRM | /* single bit error ir masked */ + NDCR_WRDREQM | /* write data request ir masked */ + NDCR_RDDREQM | /* read data request ir masked */ + NDCR_WRCMDREQM); /* write command request ir masked */ + + + /* wait 10 us due to cmd buffer clear reset */ + /* wait(10); */ + + + nand->hwcontrol = dfc_hwcontrol; +/* nand->dev_ready = dfc_device_ready; */ + nand->eccmode = NAND_ECC_SOFT; + nand->options = NAND_BUSWIDTH_16; + nand->waitfunc = dfc_wait; + nand->read_byte = dfc_read_byte; + nand->write_byte = dfc_write_byte; + nand->read_word = dfc_read_word; + nand->write_word = dfc_write_word; + nand->read_buf = dfc_read_buf; + nand->write_buf = dfc_write_buf; + + nand->cmdfunc = dfc_cmdfunc; + nand->autooob = &delta_oob; + nand->badblock_pattern = &delta_bbt_descr; +} + +#else + #error "U-Boot legacy NAND support not available for Monahans DFC." +#endif +#endif diff --git a/common/cmd_load.c b/common/cmd_load.c index 2432ee2..f63b8e8 100644 --- a/common/cmd_load.c +++ b/common/cmd_load.c @@ -33,9 +33,12 @@ DECLARE_GLOBAL_DATA_PTR; +#if (CONFIG_COMMANDS & CFG_CMD_LOADB) +static ulong load_serial_ymodem (ulong offset); +#endif + #if (CONFIG_COMMANDS & CFG_CMD_LOADS) static ulong load_serial (ulong offset); -static ulong load_serial_ymodem (ulong offset); static int read_record (char *buf, ulong len); # if (CONFIG_COMMANDS & CFG_CMD_SAVES) static int save_serial (ulong offset, ulong size); diff --git a/common/cmd_pcmcia.c b/common/cmd_pcmcia.c index 62446d4..8e3e84b 100644 --- a/common/cmd_pcmcia.c +++ b/common/cmd_pcmcia.c @@ -1,5 +1,5 @@ /* - * (C) Copyright 2000-2004 + * (C) Copyright 2000-2006 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this @@ -718,7 +718,8 @@ static int hardware_disable(int slot) /* SC8xx Boards by SinoVee Microsystems */ /* -------------------------------------------------------------------- */ -#if defined(CONFIG_TQM8xxL) || defined(CONFIG_SVM_SC8xx) +#if (defined(CONFIG_TQM8xxL) || defined(CONFIG_SVM_SC8xx)) \ + && !defined(CONFIG_VIRTLAB2) #if defined(CONFIG_TQM8xxL) #define PCMCIA_BOARD_MSG "TQM8xxL" @@ -1021,6 +1022,183 @@ done: #endif /* TQM8xxL */ +/* -------------------------------------------------------------------- */ +/* Virtlab2 Board by TQ Components */ +/* -------------------------------------------------------------------- */ + +#if defined(CONFIG_VIRTLAB2) +#define PCMCIA_BOARD_MSG "Virtlab2" + +static int hardware_enable(int slot) +{ + volatile pcmconf8xx_t *pcmp = + (pcmconf8xx_t *)&(((immap_t *)CFG_IMMR)->im_pcmcia); + volatile unsigned char *powerctl = + (volatile unsigned char *)PCMCIA_CTRL; + volatile sysconf8xx_t *sysp = + (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf)); + unsigned int reg, mask; + + debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot); + + udelay(10000); + + /* + * Configure SIUMCR to enable PCMCIA port B + */ + sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */ + + /* clear interrupt state, and disable interrupts */ + pcmp->pcmc_pscr = PCMCIA_MASK(slot); + pcmp->pcmc_per &= ~PCMCIA_MASK(slot); + + /* + * Disable interrupts, DMA, and PCMCIA buffers + * (isolate the interface) and assert RESET signal + */ + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + + PCMCIA_PGCRX(slot) = reg; + udelay(500); + + /* remove all power */ + *powerctl = 0; + + /* + * Make sure there is a card in the slot, then configure the interface. + */ + udelay(10000); + debug ("[%d] %s: PIPR(%p)=0x%x\n", __LINE__,__FUNCTION__, + &(pcmp->pcmc_pipr),pcmp->pcmc_pipr); + + if (pcmp->pcmc_pipr & (0x18000000 >> (slot << 4))) { + printf (" No Card found\n"); + return (1); + } + + /* + * Power On. + */ + mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot); + reg = pcmp->pcmc_pipr; + debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n", reg, + (reg&PCMCIA_VS1(slot))?"n":"ff", + (reg&PCMCIA_VS2(slot))?"n":"ff"); + + if ((reg & mask) == mask) { + *powerctl = 2; /* Enable 5V Vccout */ + puts (" 5.0V card found: "); + } else { + *powerctl = 1; /* Enable 3.3 V Vccout */ + puts (" 3.3V card found: "); + } + + udelay(1000); + debug ("Enable PCMCIA buffers and stop RESET\n"); + reg = PCMCIA_PGCRX(slot); + reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */ + + PCMCIA_PGCRX(slot) = reg; + + udelay(250000); /* some cards need >150 ms to come up :-( */ + + debug ("# hardware_enable done\n"); + + return (0); +} + +#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) +static int hardware_disable(int slot) +{ + volatile unsigned char *powerctl = + (volatile unsigned char *)PCMCIA_CTRL; + unsigned long reg; + + debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot); + + /* remove all power */ + *powerctl = 0; + + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + + PCMCIA_PGCRX(slot) = reg; + + udelay(10000); + + return (0); +} +#endif + +static int voltage_set(int slot, int vcc, int vpp) +{ +#ifdef DEBUG + volatile pcmconf8xx_t *pcmp = + (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); +#endif + volatile unsigned char *powerctl = + (volatile unsigned char *)PCMCIA_CTRL; + unsigned long reg; + + debug ("voltage_set: " PCMCIA_BOARD_MSG + " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n", + 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10); + + /* + * Disable PCMCIA buffers (isolate the interface) + * and assert RESET signal + */ + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = PCMCIA_PGCRX(slot); + reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + + PCMCIA_PGCRX(slot) = reg; + udelay(500); + + /* + * Configure pins for 5 Volts Enable and 3 Volts enable, + * Turn off all power. + */ + debug ("PCMCIA power OFF\n"); + reg = 0; + switch(vcc) { + case 0: break; + case 33: reg = 0x0001; break; + case 50: reg = 0x0002; break; + default: goto done; + } + + /* Checking supported voltages */ + + debug ("PIPR: 0x%x --> %s\n", pcmp->pcmc_pipr, + (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V"); + + *powerctl = reg; + + if (reg) { + debug ("PCMCIA powered at %sV\n", (reg&0x0004) ? "5.0" : "3.3"); + } else { + debug ("PCMCIA powered down\n"); + } + +done: + debug ("Enable PCMCIA buffers and stop RESET\n"); + reg = PCMCIA_PGCRX(slot); + reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */ + + PCMCIA_PGCRX(slot) = reg; + udelay(500); + + debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n", slot+'A'); + return (0); +} +#endif /* CONFIG_VIRTLAB2 */ /* -------------------------------------------------------------------- */ /* LWMON Board */ diff --git a/common/environment.c b/common/environment.c index c7f54c6..81471ce 100644 --- a/common/environment.c +++ b/common/environment.c @@ -59,7 +59,8 @@ defined(CONFIG_TQM8xxL) || \ defined(CONFIG_RRVISION) || \ defined(CONFIG_TRAB) || \ - defined(CONFIG_PPCHAMELEONEVB) ) && \ + defined(CONFIG_PPCHAMELEONEVB) || \ + defined(CONFIG_M5271EVB)) && \ defined(ENV_CRC) /* Environment embedded in U-Boot .ppcenv section */ /* XXX - This only works with GNU C */ # define __PPCENV__ __attribute__ ((section(".ppcenv"))) diff --git a/common/soft_i2c.c b/common/soft_i2c.c index bffcd44..edad51b 100644 --- a/common/soft_i2c.c +++ b/common/soft_i2c.c @@ -33,6 +33,9 @@ #include #include #endif +#ifdef CONFIG_IXP425 /* only valid for IXP425 */ +#include +#endif #include #if defined(CONFIG_SOFT_I2C) diff --git a/common/xyzModem.c b/common/xyzModem.c index 4a137bf..9b455a3 100644 --- a/common/xyzModem.c +++ b/common/xyzModem.c @@ -379,13 +379,13 @@ xyzModem_get_hdr(void) } /* Header found, now read the data */ - res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, &xyz.blk); + res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, (char *)&xyz.blk); ZM_DEBUG(zm_save(xyz.blk)); if (!res) { ZM_DEBUG(zm_dump(__LINE__)); return xyzModem_timeout; } - res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, &xyz.cblk); + res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, (char *)&xyz.cblk); ZM_DEBUG(zm_save(xyz.cblk)); if (!res) { ZM_DEBUG(zm_dump(__LINE__)); @@ -403,14 +403,14 @@ xyzModem_get_hdr(void) return xyzModem_timeout; } } - res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, &xyz.crc1); + res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, (char *)&xyz.crc1); ZM_DEBUG(zm_save(xyz.crc1)); if (!res) { ZM_DEBUG(zm_dump(__LINE__)); return xyzModem_timeout; } if (xyz.crc_mode) { - res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, &xyz.crc2); + res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, (char *)&xyz.crc2); ZM_DEBUG(zm_save(xyz.crc2)); if (!res) { ZM_DEBUG(zm_dump(__LINE__)); @@ -450,7 +450,10 @@ xyzModem_get_hdr(void) int xyzModem_stream_open(connection_info_t *info, int *err) { - int console_chan, stat=0; +#ifdef REDBOOT + int console_chan; +#endif + int stat = 0; int retries = xyzModem_MAX_RETRIES; int crc_retries = xyzModem_MAX_RETRIES_WITH_CRC; @@ -510,7 +513,7 @@ xyzModem_stream_open(connection_info_t *info, int *err) /* skip filename */ while (*xyz.bufp++); /* get the length */ - parse_num(xyz.bufp, &xyz.file_length, NULL, " "); + parse_num((char *)xyz.bufp, &xyz.file_length, NULL, " "); #endif /* The rest of the file name data block quietly discarded */ xyz.tx_ack = true; diff --git a/config.mk b/config.mk index dfbb1b7..c7b841d 100644 --- a/config.mk +++ b/config.mk @@ -144,6 +144,14 @@ endif endif AFLAGS_DEBUG := -Wa,-gstabs + +# turn jbsr into jsr for m68k +ifeq ($(ARCH),m68k) +ifeq ($(findstring 3.4,$(shell $(CC) --version)),3.4) +AFLAGS_DEBUG := -Wa,-gstabs,-S +endif +endif + AFLAGS := $(AFLAGS_DEBUG) -D__ASSEMBLY__ $(CPPFLAGS) LDFLAGS += -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS) diff --git a/cpu/arm926ejs/Makefile b/cpu/arm926ejs/Makefile index 203278e..060fd20 100644 --- a/cpu/arm926ejs/Makefile +++ b/cpu/arm926ejs/Makefile @@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk LIB = lib$(CPU).a START = start.o -OBJS = interrupts.o cpu.o +OBJS = interrupts.o cpu.o cpuinfo.o all: .depend $(START) $(LIB) diff --git a/cpu/arm926ejs/cpuinfo.c b/cpu/arm926ejs/cpuinfo.c new file mode 100644 index 0000000..8c98631 --- /dev/null +++ b/cpu/arm926ejs/cpuinfo.c @@ -0,0 +1,244 @@ +/* + * OMAP1 CPU identification code + * + * Copyright (C) 2004 Nokia Corporation + * Written by Tony Lindgren + * + * 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 +#include +#include + +#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) */ diff --git a/cpu/ixp/config.mk b/cpu/ixp/config.mk index eddda39..a71a20b 100644 --- a/cpu/ixp/config.mk +++ b/cpu/ixp/config.mk @@ -27,7 +27,7 @@ BIG_ENDIAN = y PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 \ -msoft-float -mbig-endian -PLATFORM_CPPFLAGS += -mbig-endian -march=armv4 -mtune=strongarm1100 +PLATFORM_CPPFLAGS += -mbig-endian -march=armv5te -mtune=strongarm1100 # ========================================================================= # # Supply options according to compiler version diff --git a/cpu/ixp/cpu.c b/cpu/ixp/cpu.c index 2a2bd50..7f9f334 100644 --- a/cpu/ixp/cpu.c +++ b/cpu/ixp/cpu.c @@ -34,10 +34,47 @@ #include #include +ulong loops_per_jiffy; + #ifdef CONFIG_USE_IRQ DECLARE_GLOBAL_DATA_PTR; #endif +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo (void) +{ + unsigned long id; + int speed = 0; + + asm ("mrc p15, 0, %0, c0, c0, 0":"=r" (id)); + + puts("CPU: Intel IXP425 at "); + switch ((id & 0x000003f0) >> 4) { + case 0x1c: + loops_per_jiffy = 887467; + speed = 533; + break; + + case 0x1d: + loops_per_jiffy = 666016; + speed = 400; + break; + + case 0x1f: + loops_per_jiffy = 442901; + speed = 266; + break; + } + + if (speed) + printf("%d MHz\n", speed); + else + puts("unknown revision\n"); + + return 0; +} +#endif /* CONFIG_DISPLAY_CPUINFO */ + int cpu_init (void) { /* @@ -48,7 +85,9 @@ int cpu_init (void) FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ; #endif +#if (CONFIG_COMMANDS & CFG_CMD_PCI) || defined (CONFIG_PCI) pci_init(); +#endif return 0; } @@ -154,3 +193,25 @@ void pci_init(void) return; } */ + +#ifdef CONFIG_BOOTCOUNT_LIMIT + +void bootcount_store (ulong a) +{ + volatile ulong *save_addr = (volatile ulong *)(CFG_BOOTCOUNT_ADDR); + + save_addr[0] = a; + save_addr[1] = BOOTCOUNT_MAGIC; +} + +ulong bootcount_load (void) +{ + volatile ulong *save_addr = (volatile ulong *)(CFG_BOOTCOUNT_ADDR); + + if (save_addr[1] != BOOTCOUNT_MAGIC) + return 0; + else + return save_addr[0]; +} + +#endif /* CONFIG_BOOTCOUNT_LIMIT */ diff --git a/cpu/ixp/interrupts.c b/cpu/ixp/interrupts.c index e260dea..2dd9561 100644 --- a/cpu/ixp/interrupts.c +++ b/cpu/ixp/interrupts.c @@ -1,5 +1,7 @@ -/* vi: set ts=8 sw=8 noet: */ /* + * (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * * (C) Copyright 2002 * Sysgo Real-Time Solutions, GmbH * Marius Groeger @@ -31,22 +33,85 @@ #include #ifdef CONFIG_USE_IRQ +/* + * When interrupts are enabled, use timer 2 for time/delay generation... + */ + +#define FREQ 66666666 +#define CLOCK_TICK_RATE (((FREQ / CFG_HZ & ~IXP425_OST_RELOAD_MASK) + 1) * CFG_HZ) +#define LATCH ((CLOCK_TICK_RATE + CFG_HZ/2) / CFG_HZ) /* For divider */ + +struct _irq_handler { + void *m_data; + void (*m_func)( void *data); +}; + +static struct _irq_handler IRQ_HANDLER[N_IRQS]; + +static volatile ulong timestamp; + /* enable IRQ/FIQ interrupts */ -void enable_interrupts (void) +void enable_interrupts(void) { -#error: interrupts not implemented yet + unsigned long temp; + __asm__ __volatile__("mrs %0, cpsr\n" + "bic %0, %0, #0x80\n" + "msr cpsr_c, %0" + : "=r" (temp) + : + : "memory"); } - /* * disable IRQ/FIQ interrupts * returns true if interrupts had been enabled before we disabled them */ -int disable_interrupts (void) +int disable_interrupts(void) { -#error: interrupts not implemented yet + unsigned long old,temp; + __asm__ __volatile__("mrs %0, cpsr\n" + "orr %1, %0, #0x80\n" + "msr cpsr_c, %1" + : "=r" (old), "=r" (temp) + : + : "memory"); + return (old & 0x80) == 0; } -#else + +static void default_isr(void *data) +{ + printf("default_isr(): called for IRQ %d, Interrupt Status=%x PR=%x\n", + (int)data, *IXP425_ICIP, *IXP425_ICIH); +} + +static int next_irq(void) +{ + return (((*IXP425_ICIH & 0x000000fc) >> 2) - 1); +} + +static void timer_isr(void *data) +{ + unsigned int *pTime = (unsigned int *)data; + + (*pTime)++; + + /* + * Reset IRQ source + */ + *IXP425_OSST = IXP425_OSST_TIMER_2_PEND; +} + +ulong get_timer (ulong base) +{ + return timestamp - base; +} + +void reset_timer (void) +{ + timestamp = 0; +} + +#else /* #ifdef CONFIG_USE_IRQ */ void enable_interrupts (void) { return; @@ -55,8 +120,7 @@ int disable_interrupts (void) { return 0; } -#endif - +#endif /* #ifdef CONFIG_USE_IRQ */ void bad_mode (void) { @@ -140,19 +204,46 @@ void do_fiq (struct pt_regs *pt_regs) { printf ("fast interrupt request\n"); show_regs (pt_regs); - bad_mode (); + printf("IRQ=%08lx FIQ=%08lx\n", *IXP425_ICIH, *IXP425_ICFH); } void do_irq (struct pt_regs *pt_regs) { +#ifdef CONFIG_USE_IRQ + int irq = next_irq(); + + IRQ_HANDLER[irq].m_func(IRQ_HANDLER[irq].m_data); +#else printf ("interrupt request\n"); show_regs (pt_regs); bad_mode (); +#endif } - int interrupt_init (void) { - /* nothing happens here - we don't setup any IRQs */ +#ifdef CONFIG_USE_IRQ + int i; + + /* install default interrupt handlers */ + for (i = 0; i < N_IRQS; i++) { + IRQ_HANDLER[i].m_data = (void *)i; + IRQ_HANDLER[i].m_func = default_isr; + } + + /* install interrupt handler for timer */ + IRQ_HANDLER[IXP425_TIMER_2_IRQ].m_data = (void *)×tamp; + IRQ_HANDLER[IXP425_TIMER_2_IRQ].m_func = timer_isr; + + /* setup the Timer counter value */ + *IXP425_OSRT2 = (LATCH & ~IXP425_OST_RELOAD_MASK) | IXP425_OST_ENABLE; + + /* configure interrupts for IRQ mode */ + *IXP425_ICLR = 0x00000000; + + /* enable timer irq */ + *IXP425_ICMR = (1 << IXP425_TIMER_2_IRQ); +#endif + return (0); } diff --git a/cpu/ixp/npe/IxEthAcc.c b/cpu/ixp/npe/IxEthAcc.c new file mode 100644 index 0000000..d981649 --- /dev/null +++ b/cpu/ixp/npe/IxEthAcc.c @@ -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); +} + + diff --git a/cpu/ixp/npe/IxEthAccCommon.c b/cpu/ixp/npe/IxEthAccCommon.c new file mode 100644 index 0000000..bda2c44 --- /dev/null +++ b/cpu/ixp/npe/IxEthAccCommon.c @@ -0,0 +1,1049 @@ +/** + * @file IxEthAccCommon.c + * + * @author Intel Corporation + * @date 12-Feb-2002 + * + * @brief This file contains the implementation common support routines for the 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 -- + */ + +/* + * Component header files + */ + +#include "IxOsal.h" +#include "IxEthAcc.h" +#include "IxEthDB.h" +#include "IxNpeMh.h" +#include "IxEthDBPortDefs.h" +#include "IxFeatureCtrl.h" +#include "IxEthAcc_p.h" +#include "IxEthAccQueueAssign_p.h" + +#include "IxEthAccDataPlane_p.h" +#include "IxEthAccMii_p.h" + +/** + * @addtogroup IxEthAccPri + *@{ + */ + +extern IxEthAccInfo ixEthAccDataInfo; + +/** + * + * @brief Maximum number of RX queues set to be the maximum number + * of traffic calsses. + * + */ +#define IX_ETHACC_MAX_RX_QUEUES \ + (IX_ETH_DB_QOS_TRAFFIC_CLASS_7_RX_QUEUE_PROPERTY \ + - IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY \ + + 1) + +/** + * + * @brief Maximum number of 128 entry RX queues + * + */ +#define IX_ETHACC_MAX_LARGE_RX_QUEUES 4 + +/** + * + * @brief Data structure template for Default RX Queues + * + */ +IX_ETH_ACC_PRIVATE +IxEthAccQregInfo ixEthAccQmgrRxDefaultTemplate = + { + IX_ETH_ACC_RX_FRAME_ETH_Q, /**< Queue ID */ + "Eth Rx Q", + ixEthRxFrameQMCallback, /**< Functional callback */ + (IxQMgrCallbackId) 0, /**< Callback tag */ + IX_QMGR_Q_SIZE128, /**< Allocate Max Size Q */ + IX_QMGR_Q_ENTRY_SIZE1, /**< Queue Entry Sizes - all Q entries are single word entries */ + TRUE, /**< Enable Q notification at startup */ + IX_ETH_ACC_RX_FRAME_ETH_Q_SOURCE,/**< Q Condition to drive callback */ + IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */ + IX_QMGR_Q_WM_LEVEL1, /**< Q High water mark - needed by NPE */ + }; + +/** + * + * @brief Data structure template for Small RX Queues + * + */ +IX_ETH_ACC_PRIVATE +IxEthAccQregInfo ixEthAccQmgrRxSmallTemplate = + { + IX_ETH_ACC_RX_FRAME_ETH_Q, /**< Queue ID */ + "Eth Rx Q", + ixEthRxFrameQMCallback, /**< Functional callback */ + (IxQMgrCallbackId) 0, /**< Callback tag */ + IX_QMGR_Q_SIZE64, /**< Allocate Smaller Q */ + IX_QMGR_Q_ENTRY_SIZE1, /**< Queue Entry Sizes - all Q entries are single word entries */ + TRUE, /**< Enable Q notification at startup */ + IX_ETH_ACC_RX_FRAME_ETH_Q_SOURCE,/**< Q Condition to drive callback */ + IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */ + IX_QMGR_Q_WM_LEVEL1, /**< Q High water mark - needed by NPE */ + }; + + +/** + * + * @brief Data structure used to register & initialize the Queues + * + */ +IX_ETH_ACC_PRIVATE +IxEthAccQregInfo ixEthAccQmgrStaticInfo[]= +{ + { + IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q, + "Eth Rx Fr Q 1", + ixEthRxFreeQMCallback, + (IxQMgrCallbackId) IX_ETH_PORT_1, + IX_QMGR_Q_SIZE128, /**< Allocate Max Size Q */ + IX_QMGR_Q_ENTRY_SIZE1, /**< Queue Entry Sizes - all Q entries are single word entries */ + FALSE, /**< Disable Q notification at startup */ + IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q_SOURCE, /**< Q Condition to drive callback */ + IX_QMGR_Q_WM_LEVEL0, /***< Q Low water mark */ + IX_QMGR_Q_WM_LEVEL64, /**< Q High water mark */ + }, + + { + IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q, + "Eth Rx Fr Q 2", + ixEthRxFreeQMCallback, + (IxQMgrCallbackId) IX_ETH_PORT_2, + IX_QMGR_Q_SIZE128, /**< Allocate Max Size Q */ + IX_QMGR_Q_ENTRY_SIZE1, /**< Queue Entry Sizes - all Q entries are single word entries */ + FALSE, /**< Disable Q notification at startup */ + IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q_SOURCE, /**< Q Condition to drive callback */ + IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */ + IX_QMGR_Q_WM_LEVEL64, /**< Q High water mark */ + }, +#ifdef __ixp46X + { + IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q, + "Eth Rx Fr Q 3", + ixEthRxFreeQMCallback, + (IxQMgrCallbackId) IX_ETH_PORT_3, + IX_QMGR_Q_SIZE128, /**< Allocate Max Size Q */ + IX_QMGR_Q_ENTRY_SIZE1, /**< Queue Entry Sizes - all Q entries are single word entries */ + FALSE, /**< Disable Q notification at startup */ + IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q_SOURCE, /**< Q Condition to drive callback */ + IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */ + IX_QMGR_Q_WM_LEVEL64, /**< Q High water mark */ + }, +#endif + { + IX_ETH_ACC_TX_FRAME_ENET0_Q, + "Eth Tx Q 1", + ixEthTxFrameQMCallback, + (IxQMgrCallbackId) IX_ETH_PORT_1, + IX_QMGR_Q_SIZE128, /**< Allocate Max Size Q */ + IX_QMGR_Q_ENTRY_SIZE1, /**< Queue Entry Sizes - all Q entries are single word entries */ + FALSE, /**< Disable Q notification at startup */ + IX_ETH_ACC_TX_FRAME_ENET0_Q_SOURCE, /**< Q Condition to drive callback */ + IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */ + IX_QMGR_Q_WM_LEVEL64, /**< Q High water mark */ + }, + + { + IX_ETH_ACC_TX_FRAME_ENET1_Q, + "Eth Tx Q 2", + ixEthTxFrameQMCallback, + (IxQMgrCallbackId) IX_ETH_PORT_2, + IX_QMGR_Q_SIZE128, /**< Allocate Max Size Q */ + IX_QMGR_Q_ENTRY_SIZE1, /**< Queue Entry Sizes - all Q entries are single word entries */ + FALSE, /**< Disable Q notification at startup */ + IX_ETH_ACC_TX_FRAME_ENET1_Q_SOURCE, /**< Q Condition to drive callback */ + IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */ + IX_QMGR_Q_WM_LEVEL64, /**< Q High water mark */ + }, +#ifdef __ixp46X + { + IX_ETH_ACC_TX_FRAME_ENET2_Q, + "Eth Tx Q 3", + ixEthTxFrameQMCallback, + (IxQMgrCallbackId) IX_ETH_PORT_3, + IX_QMGR_Q_SIZE128, /**< Allocate Max Size Q */ + IX_QMGR_Q_ENTRY_SIZE1, /** Queue Entry Sizes - all Q entries are single ord entries */ + FALSE, /** Disable Q notification at startup */ + IX_ETH_ACC_TX_FRAME_ENET2_Q_SOURCE, /** Q Condition to drive callback */ + IX_QMGR_Q_WM_LEVEL0, /* No queues use almost empty */ + IX_QMGR_Q_WM_LEVEL64, /** Q High water mark - needed used */ + }, +#endif + { + IX_ETH_ACC_TX_FRAME_DONE_ETH_Q, + "Eth Tx Done Q", + ixEthTxFrameDoneQMCallback, + (IxQMgrCallbackId) 0, + IX_QMGR_Q_SIZE128, /**< Allocate Max Size Q */ + IX_QMGR_Q_ENTRY_SIZE1, /**< Queue Entry Sizes - all Q entries are single word entries */ + TRUE, /**< Enable Q notification at startup */ + IX_ETH_ACC_TX_FRAME_DONE_ETH_Q_SOURCE, /**< Q Condition to drive callback */ + IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */ + IX_QMGR_Q_WM_LEVEL2, /**< Q High water mark - needed by NPE */ + }, + + { /* Null Termination entry + */ + (IxQMgrQId)0, + (char *) NULL, + (IxQMgrCallback) NULL, + (IxQMgrCallbackId) 0, + 0, + 0, + 0, + 0, + 0, + 0 + } + +}; + +/** + * + * @brief Data structure used to register & initialize the Queues + * + * The structure will be filled at run time depending on the NPE + * image already loaded and the QoS configured in ethDB. + * + */ +IX_ETH_ACC_PRIVATE +IxEthAccQregInfo ixEthAccQmgrRxQueuesInfo[IX_ETHACC_MAX_RX_QUEUES+1]= +{ + { /* PlaceHolder for rx queues + * depending on the QoS configured + */ + (IxQMgrQId)0, + (char *) NULL, + (IxQMgrCallback) NULL, + (IxQMgrCallbackId) 0, + 0, + 0, + 0, + 0, + 0, + 0 + }, + + { /* PlaceHolder for rx queues + * depending on the QoS configured + */ + (IxQMgrQId)0, + (char *) NULL, + (IxQMgrCallback) NULL, + (IxQMgrCallbackId) 0, + 0, + 0, + 0, + 0, + 0, + 0 + }, + + { /* PlaceHolder for rx queues + * depending on the QoS configured + */ + (IxQMgrQId)0, + (char *) NULL, + (IxQMgrCallback) NULL, + (IxQMgrCallbackId) 0, + 0, + 0, + 0, + 0, + 0, + 0 + }, + + { /* PlaceHolder for rx queues + * depending on the QoS configured + */ + (IxQMgrQId)0, + (char *) NULL, + (IxQMgrCallback) NULL, + (IxQMgrCallbackId) 0, + 0, + 0, + 0, + 0, + 0, + 0 + }, + + { /* PlaceHolder for rx queues + * depending on the QoS configured + */ + (IxQMgrQId)0, + (char *) NULL, + (IxQMgrCallback) NULL, + (IxQMgrCallbackId) 0, + 0, + 0, + 0, + 0, + 0, + 0 + }, + + { /* PlaceHolder for rx queues + * depending on the QoS configured + */ + (IxQMgrQId)0, + (char *) NULL, + (IxQMgrCallback) NULL, + (IxQMgrCallbackId) 0, + 0, + 0, + 0, + 0, + 0, + 0 + }, + + { /* PlaceHolder for rx queues + * depending on the QoS configured + */ + (IxQMgrQId)0, + (char *) NULL, + (IxQMgrCallback) NULL, + (IxQMgrCallbackId) 0, + 0, + 0, + 0, + 0, + 0, + 0 + }, + + { /* PlaceHolder for rx queues + * depending on the QoS configured + */ + (IxQMgrQId)0, + (char *) NULL, + (IxQMgrCallback) NULL, + (IxQMgrCallbackId) 0, + 0, + 0, + 0, + 0, + 0, + 0 + }, + + { /* Null Termination entry + */ + (IxQMgrQId)0, + (char *) NULL, + (IxQMgrCallback) NULL, + (IxQMgrCallbackId) 0, + 0, + 0, + 0, + 0, + 0, + 0 + } + +}; + +/* forward declarations */ +IX_ETH_ACC_PRIVATE IxEthAccStatus +ixEthAccQMgrQueueSetup(IxEthAccQregInfo *qInfoDes); + +/** + * @fn ixEthAccQMgrQueueSetup(void) + * + * @brief Setup one queue and its event, and register the callback required + * by this component to the QMgr + * + * @internal + */ +IX_ETH_ACC_PRIVATE IxEthAccStatus +ixEthAccQMgrQueueSetup(IxEthAccQregInfo *qInfoDes) +{ + /* + * Configure each Q. + */ + if ( ixQMgrQConfig( qInfoDes->qName, + qInfoDes->qId, + qInfoDes->qSize, + qInfoDes->qWords) != IX_SUCCESS) + { + return IX_ETH_ACC_FAIL; + } + + if ( ixQMgrWatermarkSet( qInfoDes->qId, + qInfoDes->AlmostEmptyThreshold, + qInfoDes->AlmostFullThreshold + ) != IX_SUCCESS) + { + return IX_ETH_ACC_FAIL; + } + + /* + * Set dispatcher priority. + */ + if ( ixQMgrDispatcherPrioritySet( qInfoDes->qId, + IX_ETH_ACC_QM_QUEUE_DISPATCH_PRIORITY) + != IX_SUCCESS) + { + return IX_ETH_ACC_FAIL; + } + + /* + * Register callbacks for each Q. + */ + if ( ixQMgrNotificationCallbackSet(qInfoDes->qId, + qInfoDes->qCallback, + qInfoDes->callbackTag) + != IX_SUCCESS ) + { + return IX_ETH_ACC_FAIL; + } + + /* + * Set notification condition for Q + */ + if ( qInfoDes->qNotificationEnableAtStartup == TRUE ) + { + if ( ixQMgrNotificationEnable(qInfoDes->qId, + qInfoDes->qConditionSource) + != IX_SUCCESS ) + { + return IX_ETH_ACC_FAIL; + } + } + + return(IX_ETH_ACC_SUCCESS); +} + +/** + * @fn ixEthAccQMgrQueuesConfig(void) + * + * @brief Setup all the queues and register all callbacks required + * by this component to the QMgr + * + * The RxFree queues, tx queues, rx queues are configured statically + * + * Rx queues configuration is driven by QoS setup. + * Many Rx queues may be required when QoS is enabled (this depends + * on IxEthDB setup and the images being downloaded). The configuration + * of the rxQueues is done in many steps as follows: + * + * @li select all Rx queues as configured by ethDB for all ports + * @li sort the queues by traffic class + * @li build the priority dependency for all queues + * @li fill the configuration for all rx queues + * @li configure all statically configured queues + * @li configure all dynamically configured queues + * + * @param none + * + * @return IxEthAccStatus + * + * @internal + */ +IX_ETH_ACC_PUBLIC +IxEthAccStatus ixEthAccQMgrQueuesConfig(void) +{ + struct + { + int npeCount; + UINT32 npeId; + IxQMgrQId qId; + IxEthDBProperty trafficClass; + } rxQueues[IX_ETHACC_MAX_RX_QUEUES]; + + UINT32 rxQueue = 0; + UINT32 rxQueueCount = 0; + IxQMgrQId ixQId =IX_QMGR_MAX_NUM_QUEUES; + IxEthDBStatus ixEthDBStatus = IX_ETH_DB_SUCCESS; + IxEthDBPortId ixEthDbPortId = 0; + IxEthAccPortId ixEthAccPortId = 0; + UINT32 ixNpeId = 0; + UINT32 ixHighestNpeId = 0; + UINT32 sortIterations = 0; + IxEthAccStatus ret = IX_ETH_ACC_SUCCESS; + IxEthAccQregInfo *qInfoDes = NULL; + IxEthDBProperty ixEthDBTrafficClass = IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY; + IxEthDBPropertyType ixEthDBPropertyType = IX_ETH_DB_INTEGER_PROPERTY; + UINT32 ixEthDBParameter = 0; + BOOL completelySorted = FALSE; + + /* Fill the corspondance between ports and queues + * This defines the mapping from port to queue Ids. + */ + + ixEthAccPortData[IX_ETH_PORT_1].ixEthAccRxData.rxFreeQueue + = IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q; + ixEthAccPortData[IX_ETH_PORT_2].ixEthAccRxData.rxFreeQueue + = IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q; +#ifdef __ixp46X + ixEthAccPortData[IX_ETH_PORT_3].ixEthAccRxData.rxFreeQueue + = IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q; +#endif + ixEthAccPortData[IX_ETH_PORT_1].ixEthAccTxData.txQueue + = IX_ETH_ACC_TX_FRAME_ENET0_Q; + ixEthAccPortData[IX_ETH_PORT_2].ixEthAccTxData.txQueue + = IX_ETH_ACC_TX_FRAME_ENET1_Q; +#ifdef __ixp46X + ixEthAccPortData[IX_ETH_PORT_3].ixEthAccTxData.txQueue + = IX_ETH_ACC_TX_FRAME_ENET2_Q; +#endif + /* Fill the corspondance between ports and NPEs + * This defines the mapping from port to npeIds. + */ + + ixEthAccPortData[IX_ETH_PORT_1].npeId = IX_NPEMH_NPEID_NPEB; + ixEthAccPortData[IX_ETH_PORT_2].npeId = IX_NPEMH_NPEID_NPEC; +#ifdef __ixp46X + ixEthAccPortData[IX_ETH_PORT_3].npeId = IX_NPEMH_NPEID_NPEA; +#endif + /* set the default rx scheduling discipline */ + ixEthAccDataInfo.schDiscipline = FIFO_NO_PRIORITY; + + /* + * Queue Selection step: + * + * The following code selects all the queues and build + * a temporary array which contains for each queue + * - the queue Id, + * - the highest traffic class (in case of many + * priorities configured for the same queue on different + * ports) + * - the number of different Npes which are + * configured to write to this queue. + * + * The output of this loop is a temporary array of RX queues + * in any order. + * + */ +#ifdef CONFIG_IXP425_COMPONENT_ETHDB + for (ixEthAccPortId = 0; + (ixEthAccPortId < IX_ETH_ACC_NUMBER_OF_PORTS) + && (ret == IX_ETH_ACC_SUCCESS); + ixEthAccPortId++) + { + /* map between ethDb and ethAcc port Ids */ + ixEthDbPortId = (IxEthDBPortId)ixEthAccPortId; + + /* map between npeId and ethAcc port Ids */ + ixNpeId = IX_ETH_ACC_PORT_TO_NPE_ID(ixEthAccPortId); + + /* Iterate thru the different priorities */ + for (ixEthDBTrafficClass = IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY; + ixEthDBTrafficClass <= IX_ETH_DB_QOS_TRAFFIC_CLASS_7_RX_QUEUE_PROPERTY; + ixEthDBTrafficClass++) + { + ixEthDBStatus = ixEthDBFeaturePropertyGet( + ixEthDbPortId, + IX_ETH_DB_VLAN_QOS, + ixEthDBTrafficClass, + &ixEthDBPropertyType, + (void *)&ixEthDBParameter); + + if (ixEthDBStatus == IX_ETH_DB_SUCCESS) + { + /* This port and QoS class are mapped to + * a RX queue. + */ + if (ixEthDBPropertyType == IX_ETH_DB_INTEGER_PROPERTY) + { + /* remember the highest npe Id supporting ethernet */ + if (ixNpeId > ixHighestNpeId) + { + ixHighestNpeId = ixNpeId; + } + + /* search the queue in the list of queues + * already used by an other port or QoS + */ + for (rxQueue = 0; + rxQueue < rxQueueCount; + rxQueue++) + { + if (rxQueues[rxQueue].qId == (IxQMgrQId)ixEthDBParameter) + { + /* found an existing setup, update the number of ports + * for this queue if the port maps to + * a different NPE. + */ + if (rxQueues[rxQueue].npeId != ixNpeId) + { + rxQueues[rxQueue].npeCount++; + rxQueues[rxQueue].npeId = ixNpeId; + } + /* get the highest traffic class for this queue */ + if (rxQueues[rxQueue].trafficClass > ixEthDBTrafficClass) + { + rxQueues[rxQueue].trafficClass = ixEthDBTrafficClass; + } + break; + } + } + if (rxQueue == rxQueueCount) + { + /* new queue not found in the current list, + * add a new entry. + */ + IX_OSAL_ASSERT(rxQueueCount < IX_ETHACC_MAX_RX_QUEUES); + rxQueues[rxQueueCount].qId = ixEthDBParameter; + rxQueues[rxQueueCount].npeCount = 1; + rxQueues[rxQueueCount].npeId = ixNpeId; + rxQueues[rxQueueCount].trafficClass = ixEthDBTrafficClass; + rxQueueCount++; + } + } + else + { + /* unexpected property type (not Integer) */ + ret = IX_ETH_ACC_FAIL; + + IX_ETH_ACC_WARNING_LOG("ixEthAccQMgrQueuesConfig: unexpected property type returned by EthDB\n", 0, 0, 0, 0, 0, 0); + + /* no point to continue to iterate */ + break; + } + } + else + { + /* No Rx queue configured for this port + * and this traffic class. Do nothing. + */ + } + } + + /* notify EthDB that queue initialization is complete and traffic class allocation is frozen */ + ixEthDBFeaturePropertySet(ixEthDbPortId, + IX_ETH_DB_VLAN_QOS, + IX_ETH_DB_QOS_QUEUE_CONFIGURATION_COMPLETE, + NULL /* ignored */); + } + +#else + + ixNpeId = IX_ETH_ACC_PORT_TO_NPE_ID(ixEthAccPortId); + rxQueues[0].qId = 4; + rxQueues[0].npeCount = 1; + rxQueues[0].npeId = ixNpeId; + rxQueues[0].trafficClass = IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY; + rxQueueCount++; + +#endif + + /* check there is at least 1 rx queue : there is no point + * to continue if there is no rx queue configured + */ + if ((rxQueueCount == 0) || (ret == IX_ETH_ACC_FAIL)) + { + IX_ETH_ACC_WARNING_LOG("ixEthAccQMgrQueuesConfig: no queues configured, bailing out\n", 0, 0, 0, 0, 0, 0); + return (IX_ETH_ACC_FAIL); + } + + /* Queue sort step: + * + * Re-order the array of queues by decreasing traffic class + * using a bubble sort. (trafficClass 0 is the lowest + * priority traffic, trafficClass 7 is the highest priority traffic) + * + * Primary sort order is traffic class + * Secondary sort order is npeId + * + * Note that a bubble sort algorithm is not very efficient when + * the number of queues grows . However, this is not a very bad choice + * considering the very small number of entries to sort. Also, bubble + * sort is extremely fast when the list is already sorted. + * + * The output of this loop is a sorted array of queues. + * + */ + sortIterations = 0; + do + { + sortIterations++; + completelySorted = TRUE; + for (rxQueue = 0; + rxQueue < rxQueueCount - sortIterations; + rxQueue++) + { + /* compare adjacent elements */ + if ((rxQueues[rxQueue].trafficClass < + rxQueues[rxQueue+1].trafficClass) + || ((rxQueues[rxQueue].trafficClass == + rxQueues[rxQueue+1].trafficClass) + &&(rxQueues[rxQueue].npeId < + rxQueues[rxQueue+1].npeId))) + { + /* swap adjacent elements */ + int npeCount = rxQueues[rxQueue].npeCount; + UINT32 npeId = rxQueues[rxQueue].npeId; + IxQMgrQId qId = rxQueues[rxQueue].qId; + IxEthDBProperty trafficClass = rxQueues[rxQueue].trafficClass; + rxQueues[rxQueue].npeCount = rxQueues[rxQueue+1].npeCount; + rxQueues[rxQueue].npeId = rxQueues[rxQueue+1].npeId; + rxQueues[rxQueue].qId = rxQueues[rxQueue+1].qId; + rxQueues[rxQueue].trafficClass = rxQueues[rxQueue+1].trafficClass; + rxQueues[rxQueue+1].npeCount = npeCount; + rxQueues[rxQueue+1].npeId = npeId; + rxQueues[rxQueue+1].qId = qId; + rxQueues[rxQueue+1].trafficClass = trafficClass; + completelySorted = FALSE; + } + } + } + while (!completelySorted); + + /* Queue traffic class list: + * + * Fill an array of rx queues linked by ascending traffic classes. + * + * If the queues are configured as follows + * qId 6 -> traffic class 0 (lowest) + * qId 7 -> traffic class 0 + * qId 8 -> traffic class 6 + * qId 12 -> traffic class 7 (highest) + * + * Then the output of this loop will be + * + * higherPriorityQueue[6] = 8 + * higherPriorityQueue[7] = 8 + * higherPriorityQueue[8] = 12 + * higherPriorityQueue[12] = Invalid queueId + * higherPriorityQueue[...] = Invalid queueId + * + * Note that this queue ordering does not handle all possibilities + * that could result from different rules associated with different + * ports, and inconsistencies in the rules. In all cases, the + * output of this algorithm is a simple linked list of queues, + * without closed circuit. + + * This list is implemented as an array with invalid values initialized + * with an "invalid" queue id which is the maximum number of queues. + * + */ + + /* + * Initialise the rx queue list. + */ + for (rxQueue = 0; rxQueue < IX_QMGR_MAX_NUM_QUEUES; rxQueue++) + { + ixEthAccDataInfo.higherPriorityQueue[rxQueue] = IX_QMGR_MAX_NUM_QUEUES; + } + + /* build the linked list for this NPE. + */ + for (ixNpeId = 0; + ixNpeId <= ixHighestNpeId; + ixNpeId++) + { + /* iterate thru the sorted list of queues + */ + ixQId = IX_QMGR_MAX_NUM_QUEUES; + for (rxQueue = 0; + rxQueue < rxQueueCount; + rxQueue++) + { + if (rxQueues[rxQueue].npeId == ixNpeId) + { + ixEthAccDataInfo.higherPriorityQueue[rxQueues[rxQueue].qId] = ixQId; + /* iterate thru queues with the same traffic class + * than the current queue. (queues are ordered by descending + * traffic classes and npeIds). + */ + while ((rxQueue < rxQueueCount - 1) + && (rxQueues[rxQueue].trafficClass + == rxQueues[rxQueue+1].trafficClass) + && (ixNpeId == rxQueues[rxQueue].npeId)) + { + rxQueue++; + ixEthAccDataInfo.higherPriorityQueue[rxQueues[rxQueue].qId] = ixQId; + } + ixQId = rxQueues[rxQueue].qId; + } + } + } + + /* point on the first dynamic queue description */ + qInfoDes = ixEthAccQmgrRxQueuesInfo; + + /* update the list of queues with the rx queues */ + for (rxQueue = 0; + (rxQueue < rxQueueCount) && (ret == IX_ETH_ACC_SUCCESS); + rxQueue++) + { + /* Don't utilize more than IX_ETHACC_MAX_LARGE_RX_QUEUES queues + * with the full 128 entries. For the lower priority queues, use + * a smaller number of entries. This ensures queue resources + * remain available for other components. + */ + if( (rxQueueCount > IX_ETHACC_MAX_LARGE_RX_QUEUES) && + (rxQueue < rxQueueCount - IX_ETHACC_MAX_LARGE_RX_QUEUES) ) + { + /* add the small RX Queue setup template to the list of queues */ + memcpy(qInfoDes, &ixEthAccQmgrRxSmallTemplate, sizeof(*qInfoDes)); + } else { + /* add the default RX Queue setup template to the list of queues */ + memcpy(qInfoDes, &ixEthAccQmgrRxDefaultTemplate, sizeof(*qInfoDes)); + } + + /* setup the RxQueue ID */ + qInfoDes->qId = rxQueues[rxQueue].qId; + + /* setup the RxQueue watermark level + * + * Each queue can be filled by many NPEs. To avoid the + * NPEs to write to a full queue, need to set the + * high watermark level for nearly full condition. + * (the high watermark level are a power of 2 + * starting from the top of the queue) + * + * Number of watermark + * ports level + * 1 0 + * 2 1 + * 3 2 + * 4 4 + * 5 4 + * 6 8 + * n approx. 2**ceil(log2(n)) + */ + if (rxQueues[rxQueue].npeCount == 1) + { + qInfoDes->AlmostFullThreshold = IX_QMGR_Q_WM_LEVEL0; + } + else if (rxQueues[rxQueue].npeCount == 2) + { + qInfoDes->AlmostFullThreshold = IX_QMGR_Q_WM_LEVEL1; + } + else if (rxQueues[rxQueue].npeCount == 3) + { + qInfoDes->AlmostFullThreshold = IX_QMGR_Q_WM_LEVEL2; + } + else + { + /* reach the maximum number for CSR 2.0 */ + IX_ETH_ACC_WARNING_LOG("ixEthAccQMgrQueuesConfig: maximum number of NPEs per queue reached, bailing out\n", 0, 0, 0, 0, 0, 0); + ret = IX_ETH_ACC_FAIL; + break; + } + + /* move to next queue entry */ + ++qInfoDes; + } + + /* configure the static list (RxFree, Tx and TxDone queues) */ + for (qInfoDes = ixEthAccQmgrStaticInfo; + (qInfoDes->qCallback != (IxQMgrCallback) NULL ) + && (ret == IX_ETH_ACC_SUCCESS); + ++qInfoDes) + { + ret = ixEthAccQMgrQueueSetup(qInfoDes); + } + + /* configure the dynamic list (Rx queues) */ + for (qInfoDes = ixEthAccQmgrRxQueuesInfo; + (qInfoDes->qCallback != (IxQMgrCallback) NULL ) + && (ret == IX_ETH_ACC_SUCCESS); + ++qInfoDes) + { + ret = ixEthAccQMgrQueueSetup(qInfoDes); + } + + return(ret); +} + +/** + * @fn ixEthAccQMgrRxQEntryGet(UINT32 *rxQueueEntries) + * + * @brief Add and return the total number of entries in all Rx queues + * + * @param UINT32 rxQueueEntries[in] number of entries in all queues + * + * @return void + * + * @note Rx queues configuration is driven by Qos Setup. There is a + * variable number of rx queues which are set at initialisation. + * + * @internal + */ +IX_ETH_ACC_PUBLIC +void ixEthAccQMgrRxQEntryGet(UINT32 *numRxQueueEntries) +{ + UINT32 rxQueueLevel; + IxEthAccQregInfo *qInfoDes;; + + *numRxQueueEntries = 0; + + /* iterate thru rx queues */ + for (qInfoDes = ixEthAccQmgrRxQueuesInfo; + qInfoDes->qCallback != (IxQMgrCallback)NULL; + ++qInfoDes) + { + /* retrieve the rx queue level */ + rxQueueLevel = 0; + ixQMgrQNumEntriesGet(qInfoDes->qId, &rxQueueLevel); + (*numRxQueueEntries) += rxQueueLevel; + } +} + +/** + * @fn ixEthAccQMgrRxCallbacksRegister(IxQMgrCallback ixQMgrCallback) + * + * @brief Change the callback registered to all rx queues. + * + * @param IxQMgrCallback ixQMgrCallback[in] QMgr callback to register + * + * @return IxEthAccStatus + * + * @note The user may decide to use different Rx mechanisms + * (e.g. receive many frames at the same time , or receive + * one frame at a time, depending on the overall application + * performances). A different QMgr callback is registered. This + * way, there is no excessive pointer checks in the datapath. + * + * @internal + */ +IX_ETH_ACC_PUBLIC +IxEthAccStatus ixEthAccQMgrRxCallbacksRegister(IxQMgrCallback ixQMgrCallback) +{ + IxEthAccQregInfo *qInfoDes; + IxEthAccStatus ret = IX_ETH_ACC_SUCCESS; + + /* parameter check */ + if (NULL == ixQMgrCallback) + { + ret = IX_ETH_ACC_FAIL; + } + + /* iterate thru rx queues */ + for (qInfoDes = ixEthAccQmgrRxQueuesInfo; + (qInfoDes->qCallback != (IxQMgrCallback) NULL ) + && (ret == IX_ETH_ACC_SUCCESS); + ++qInfoDes) + { + /* register the rx callback for all queues */ + if (ixQMgrNotificationCallbackSet(qInfoDes->qId, + ixQMgrCallback, + qInfoDes->callbackTag + ) != IX_SUCCESS) + { + ret = IX_ETH_ACC_FAIL; + } + } + return(ret); +} + +/** + * @fn ixEthAccSingleEthNpeCheck(IxEthAccPortId portId) + * + * @brief Check the npe exists for this port + * + * @param IxEthAccPortId portId[in] port + * + * @return IxEthAccStatus + * + * @internal + */ +IX_ETH_ACC_PUBLIC +IxEthAccStatus ixEthAccSingleEthNpeCheck(IxEthAccPortId 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 ((IX_ETH_PORT_1 == portId) && + (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH0) == + IX_FEATURE_CTRL_COMPONENT_ENABLED)) + { + return IX_ETH_ACC_SUCCESS; + } + + if ((IX_ETH_PORT_2 == portId) && + (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH1) == + IX_FEATURE_CTRL_COMPONENT_ENABLED)) + { + return IX_ETH_ACC_SUCCESS; + } + + if ((IX_ETH_PORT_3 == portId) && + (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEA_ETH) == + IX_FEATURE_CTRL_COMPONENT_ENABLED)) + { + return IX_ETH_ACC_SUCCESS; + } + + return IX_ETH_ACC_FAIL; + } + + return IX_ETH_ACC_SUCCESS; +} + +/** + * @fn ixEthAccStatsShow(void) + * + * @brief Displays all EthAcc stats + * + * @return void + * + */ +void ixEthAccStatsShow(IxEthAccPortId portId) +{ + ixEthAccMdioShow(); + + printf("\nPort %u\nUnicast MAC : ", portId); + ixEthAccPortUnicastAddressShow(portId); + ixEthAccPortMulticastAddressShow(portId); + printf("\n"); + + ixEthAccDataPlaneShow(); +} + + + diff --git a/cpu/ixp/npe/IxEthAccControlInterface.c b/cpu/ixp/npe/IxEthAccControlInterface.c new file mode 100644 index 0000000..4432847 --- /dev/null +++ b/cpu/ixp/npe/IxEthAccControlInterface.c @@ -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; +} diff --git a/cpu/ixp/npe/IxEthAccDataPlane.c b/cpu/ixp/npe/IxEthAccDataPlane.c new file mode 100644 index 0000000..e46fc9b --- /dev/null +++ b/cpu/ixp/npe/IxEthAccDataPlane.c @@ -0,0 +1,2483 @@ +/** + * @file IxEthDataPlane.c + * + * @author Intel Corporation + * @date 12-Feb-2002 + * + * @brief This file contains the implementation of the IXPxxx + * Ethernet Access Data plane 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 "IxNpeMh.h" +#include "IxEthAcc.h" +#include "IxEthDB.h" +#include "IxOsal.h" +#include "IxEthDBPortDefs.h" +#include "IxFeatureCtrl.h" +#include "IxEthAcc_p.h" +#include "IxEthAccQueueAssign_p.h" + +extern PUBLIC IxEthAccMacState ixEthAccMacState[]; +extern PUBLIC UINT32 ixEthAccNewSrcMask; + +/** + * private functions prototype + */ +PRIVATE IX_OSAL_MBUF * +ixEthAccEntryFromQConvert(UINT32 qEntry, UINT32 mask); + +PRIVATE UINT32 +ixEthAccMbufRxQPrepare(IX_OSAL_MBUF *mbuf); + +PRIVATE UINT32 +ixEthAccMbufTxQPrepare(IX_OSAL_MBUF *mbuf); + +PRIVATE IxEthAccStatus +ixEthAccTxSwQHighestPriorityGet(IxEthAccPortId portId, + IxEthAccTxPriority *priorityPtr); + +PRIVATE IxEthAccStatus +ixEthAccTxFromSwQ(IxEthAccPortId portId, + IxEthAccTxPriority priority); + +PRIVATE IxEthAccStatus +ixEthAccRxFreeFromSwQ(IxEthAccPortId portId); + +PRIVATE void +ixEthAccMbufFromTxQ(IX_OSAL_MBUF *mbuf); + +PRIVATE void +ixEthAccMbufFromRxQ(IX_OSAL_MBUF *mbuf); + +PRIVATE IX_STATUS +ixEthAccQmgrLockTxWrite(IxEthAccPortId portId, + UINT32 qBuffer); + +PRIVATE IX_STATUS +ixEthAccQmgrLockRxWrite(IxEthAccPortId portId, + UINT32 qBuffer); + +PRIVATE IX_STATUS +ixEthAccQmgrTxWrite(IxEthAccPortId portId, + UINT32 qBuffer, + UINT32 priority); + +/** + * @addtogroup IxEthAccPri + *@{ + */ + +/* increment a counter only when stats are enabled */ +#define TX_STATS_INC(port,field) \ + IX_ETH_ACC_STATS_INC(ixEthAccPortData[port].ixEthAccTxData.stats.field) +#define RX_STATS_INC(port,field) \ + IX_ETH_ACC_STATS_INC(ixEthAccPortData[port].ixEthAccRxData.stats.field) + +/* always increment the counter (mainly used for unexpected errors) */ +#define TX_INC(port,field) \ + ixEthAccPortData[port].ixEthAccTxData.stats.field++ +#define RX_INC(port,field) \ + ixEthAccPortData[port].ixEthAccRxData.stats.field++ + +PRIVATE IxEthAccDataPlaneStats ixEthAccDataStats; + +extern IxEthAccPortDataInfo ixEthAccPortData[]; +extern IxEthAccInfo ixEthAccDataInfo; + +PRIVATE IxOsalFastMutex txWriteMutex[IX_ETH_ACC_NUMBER_OF_PORTS]; +PRIVATE IxOsalFastMutex rxWriteMutex[IX_ETH_ACC_NUMBER_OF_PORTS]; + +/** + * + * @brief Mbuf header conversion macros : they implement the + * different conversions using a temporary value. They also double-check + * that the parameters can be converted to/from NPE format. + * + */ +#if defined(__wince) && !defined(IN_KERNEL) +#define PTR_VIRT2NPE(ptrSrc,dst) \ + do { UINT32 temp; \ + IX_OSAL_ENSURE(sizeof(ptrSrc) == sizeof(UINT32), "Wrong parameter type"); \ + IX_OSAL_ENSURE(sizeof(dst) == sizeof(UINT32), "Wrong parameter type"); \ + temp = (UINT32)IX_OSAL_MBUF_MBUF_VIRTUAL_TO_PHYSICAL_TRANSLATION((IX_OSAL_MBUF*)ptrSrc); \ + (dst) = IX_OSAL_SWAP_BE_SHARED_LONG(temp); } \ + while(0) + +#define PTR_NPE2VIRT(type,src,ptrDst) \ + do { void *temp; \ + IX_OSAL_ENSURE(sizeof(type) == sizeof(UINT32), "Wrong parameter type"); \ + IX_OSAL_ENSURE(sizeof(src) == sizeof(UINT32), "Wrong parameter type"); \ + IX_OSAL_ENSURE(sizeof(ptrDst) == sizeof(UINT32), "Wrong parameter type"); \ + temp = (void *)IX_OSAL_SWAP_BE_SHARED_LONG(src); \ + (ptrDst) = (type)IX_OSAL_MBUF_MBUF_PHYSICAL_TO_VIRTUAL_TRANSLATION(temp); } \ + while(0) +#else +#define PTR_VIRT2NPE(ptrSrc,dst) \ + do { UINT32 temp; \ + IX_OSAL_ENSURE(sizeof(ptrSrc) == sizeof(UINT32), "Wrong parameter type"); \ + IX_OSAL_ENSURE(sizeof(dst) == sizeof(UINT32), "Wrong parameter type"); \ + temp = (UINT32)IX_OSAL_MMU_VIRT_TO_PHYS(ptrSrc); \ + (dst) = IX_OSAL_SWAP_BE_SHARED_LONG(temp); } \ + while(0) + +#define PTR_NPE2VIRT(type,src,ptrDst) \ + do { void *temp; \ + IX_OSAL_ENSURE(sizeof(type) == sizeof(UINT32), "Wrong parameter type"); \ + IX_OSAL_ENSURE(sizeof(src) == sizeof(UINT32), "Wrong parameter type"); \ + IX_OSAL_ENSURE(sizeof(ptrDst) == sizeof(UINT32), "Wrong parameter type"); \ + temp = (void *)IX_OSAL_SWAP_BE_SHARED_LONG(src); \ + (ptrDst) = (type)IX_OSAL_MMU_PHYS_TO_VIRT(temp); } \ + while(0) +#endif + +/** + * + * @brief Mbuf payload pointer conversion macros : Wince has its own + * method to convert the buffer pointers + */ +#if defined(__wince) && !defined(IN_KERNEL) +#define DATAPTR_VIRT2NPE(ptrSrc,dst) \ + do { UINT32 temp; \ + temp = (UINT32)IX_OSAL_MBUF_DATA_VIRTUAL_TO_PHYSICAL_TRANSLATION(ptrSrc); \ + (dst) = IX_OSAL_SWAP_BE_SHARED_LONG(temp); } \ + while(0) + +#else +#define DATAPTR_VIRT2NPE(ptrSrc,dst) PTR_VIRT2NPE(IX_OSAL_MBUF_MDATA(ptrSrc),dst) +#endif + + +/* Flush the shared part of the mbuf header */ +#define IX_ETHACC_NE_CACHE_FLUSH(mbufPtr) \ + do { \ + IX_OSAL_CACHE_FLUSH(IX_ETHACC_NE_SHARED(mbufPtr), \ + sizeof(IxEthAccNe)); \ + } \ + while(0) + +/* Invalidate the shared part of the mbuf header */ +#define IX_ETHACC_NE_CACHE_INVALIDATE(mbufPtr) \ + do { \ + IX_OSAL_CACHE_INVALIDATE(IX_ETHACC_NE_SHARED(mbufPtr), \ + sizeof(IxEthAccNe)); \ + } \ + while(0) + +/* Preload one cache line (shared mbuf headers are aligned + * and their size is 1 cache line) + * + * IX_OSAL_CACHED is defined when the mbuf headers are + * allocated from cached memory. + * + * Other processor on emulation environment may not implement + * preload function + */ +#ifdef IX_OSAL_CACHED + #if (CPU!=SIMSPARCSOLARIS) && !defined (__wince) + #define IX_ACC_DATA_CACHE_PRELOAD(ptr) \ + do { /* preload a cache line (Xscale Processor) */ \ + __asm__ (" pld [%0]\n": : "r" (ptr)); \ + } \ + while(0) + #else + /* preload not implemented on different processor */ + #define IX_ACC_DATA_CACHE_PRELOAD(mbufPtr) \ + do { /* nothing */ } while (0) + #endif +#else + /* preload not needed if cache is not enabled */ + #define IX_ACC_DATA_CACHE_PRELOAD(mbufPtr) \ + do { /* nothing */ } while (0) +#endif + +/** + * + * @brief function to retrieve the correct pointer from + * a queue entry posted by the NPE + * + * @param qEntry : entry from qmgr queue + * mask : applicable mask for this queue + * (4 most significant bits are used for additional informations) + * + * @return IX_OSAL_MBUF * pointer to mbuf header + * + * @internal + */ +PRIVATE IX_OSAL_MBUF * +ixEthAccEntryFromQConvert(UINT32 qEntry, UINT32 mask) +{ + IX_OSAL_MBUF *mbufPtr; + + if (qEntry != 0) + { + /* mask NPE bits (e.g. priority, port ...) */ + qEntry &= mask; + +#if IX_ACC_DRAM_PHYS_OFFSET != 0 + /* restore the original address pointer (if PHYS_OFFSET is not 0) */ + qEntry |= (IX_ACC_DRAM_PHYS_OFFSET & ~IX_ETHNPE_QM_Q_RXENET_ADDR_MASK); +#endif + /* get the mbuf pointer address from the npe-shared address */ + qEntry -= offsetof(IX_OSAL_MBUF,ix_ne); + + /* phys2virt mbuf */ + mbufPtr = (IX_OSAL_MBUF *)IX_OSAL_MMU_PHYS_TO_VIRT(qEntry); + + /* preload the cacheline shared with NPE */ + IX_ACC_DATA_CACHE_PRELOAD(IX_ETHACC_NE_SHARED(mbufPtr)); + + /* preload the cacheline used by xscale */ + IX_ACC_DATA_CACHE_PRELOAD(mbufPtr); + } + else + { + mbufPtr = NULL; + } + + return mbufPtr; +} + +/* Convert the mbuf header for NPE transmission */ +PRIVATE UINT32 +ixEthAccMbufTxQPrepare(IX_OSAL_MBUF *mbuf) +{ + UINT32 qbuf; + UINT32 len; + + /* endianess swap for tci and flags + note: this is done only once, even for chained buffers */ + IX_ETHACC_NE_FLAGS(mbuf) = IX_OSAL_SWAP_BE_SHARED_SHORT(IX_ETHACC_NE_FLAGS(mbuf)); + IX_ETHACC_NE_VLANTCI(mbuf) = IX_OSAL_SWAP_BE_SHARED_SHORT(IX_ETHACC_NE_VLANTCI(mbuf)); + + /* test for unchained mbufs */ + if (IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mbuf) == NULL) + { + /* "best case" scenario : unchained mbufs */ + IX_ETH_ACC_STATS_INC(ixEthAccDataStats.unchainedTxMBufs); + + /* payload pointer conversion */ + DATAPTR_VIRT2NPE(mbuf, IX_ETHACC_NE_DATA(mbuf)); + + /* unchained mbufs : the frame length is the mbuf length + * and the 2 identical lengths are stored in the same + * word. + */ + len = IX_OSAL_MBUF_MLEN(mbuf); + + /* set the length in both length and pktLen 16-bits fields */ + len |= (len << IX_ETHNPE_ACC_LENGTH_OFFSET); + IX_ETHACC_NE_LEN(mbuf) = IX_OSAL_SWAP_BE_SHARED_LONG(len); + + /* unchained mbufs : next contains 0 */ + IX_ETHACC_NE_NEXT(mbuf) = 0; + + /* flush shared header after all address conversions */ + IX_ETHACC_NE_CACHE_FLUSH(mbuf); + } + else + { + /* chained mbufs */ + IX_OSAL_MBUF *ptr = mbuf; + IX_OSAL_MBUF *nextPtr; + UINT32 frmLen; + + /* get the frame length from the header of the first buffer */ + frmLen = IX_OSAL_MBUF_PKT_LEN(mbuf); + + do + { + IX_ETH_ACC_STATS_INC(ixEthAccDataStats.chainedTxMBufs); + + /* payload pointer */ + DATAPTR_VIRT2NPE(ptr,IX_ETHACC_NE_DATA(ptr)); + /* Buffer length and frame length are stored in the same word */ + len = IX_OSAL_MBUF_MLEN(ptr); + len = frmLen | (len << IX_ETHNPE_ACC_LENGTH_OFFSET); + IX_ETHACC_NE_LEN(ptr) = IX_OSAL_SWAP_BE_SHARED_LONG(len); + + /* get the virtual next chain pointer */ + nextPtr = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(ptr); + if (nextPtr != NULL) + { + /* shared pointer of the next buffer is chained */ + PTR_VIRT2NPE(IX_ETHACC_NE_SHARED(nextPtr), + IX_ETHACC_NE_NEXT(ptr)); + } + else + { + IX_ETHACC_NE_NEXT(ptr) = 0; + } + + /* flush shared header after all address conversions */ + IX_ETHACC_NE_CACHE_FLUSH(ptr); + + /* move to next buffer */ + ptr = nextPtr; + + /* the frame length field is set only in the first buffer + * and is zeroed in the next buffers + */ + frmLen = 0; + } + while(ptr != NULL); + + } + + /* virt2phys mbuf itself */ + qbuf = (UINT32)IX_OSAL_MMU_VIRT_TO_PHYS( + IX_ETHACC_NE_SHARED(mbuf)); + + /* Ensure the bits which are reserved to exchange information with + * the NPE are cleared + * + * If the mbuf address is not correctly aligned, or from an + * incompatible memory range, there is no point to continue + */ + IX_OSAL_ENSURE(((qbuf & ~IX_ETHNPE_QM_Q_TXENET_ADDR_MASK) == 0), + "Invalid address range"); + + return qbuf; +} + +/* Convert the mbuf header for NPE reception */ +PRIVATE UINT32 +ixEthAccMbufRxQPrepare(IX_OSAL_MBUF *mbuf) +{ + UINT32 len; + UINT32 qbuf; + + if (IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mbuf) == NULL) + { + /* "best case" scenario : unchained mbufs */ + IX_ETH_ACC_STATS_INC(ixEthAccDataStats.unchainedRxFreeMBufs); + + /* unchained mbufs : payload pointer */ + DATAPTR_VIRT2NPE(mbuf, IX_ETHACC_NE_DATA(mbuf)); + + /* unchained mbufs : set the buffer length + * and the frame length field is zeroed + */ + len = (IX_OSAL_MBUF_MLEN(mbuf) << IX_ETHNPE_ACC_LENGTH_OFFSET); + IX_ETHACC_NE_LEN(mbuf) = IX_OSAL_SWAP_BE_SHARED_LONG(len); + + /* unchained mbufs : next pointer is null */ + IX_ETHACC_NE_NEXT(mbuf) = 0; + + /* flush shared header after all address conversions */ + IX_ETHACC_NE_CACHE_FLUSH(mbuf); + + /* remove shared header cache line */ + IX_ETHACC_NE_CACHE_INVALIDATE(mbuf); + } + else + { + /* chained mbufs */ + IX_OSAL_MBUF *ptr = mbuf; + IX_OSAL_MBUF *nextPtr; + + do + { + /* chained mbufs */ + IX_ETH_ACC_STATS_INC(ixEthAccDataStats.chainedRxFreeMBufs); + + /* we must save virtual next chain pointer */ + nextPtr = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(ptr); + + if (nextPtr != NULL) + { + /* chaining pointer for NPE */ + PTR_VIRT2NPE(IX_ETHACC_NE_SHARED(nextPtr), + IX_ETHACC_NE_NEXT(ptr)); + } + else + { + IX_ETHACC_NE_NEXT(ptr) = 0; + } + + /* payload pointer */ + DATAPTR_VIRT2NPE(ptr,IX_ETHACC_NE_DATA(ptr)); + + /* buffer length */ + len = (IX_OSAL_MBUF_MLEN(ptr) << IX_ETHNPE_ACC_LENGTH_OFFSET); + IX_ETHACC_NE_LEN(ptr) = IX_OSAL_SWAP_BE_SHARED_LONG(len); + + /* flush shared header after all address conversions */ + IX_ETHACC_NE_CACHE_FLUSH(ptr); + + /* remove shared header cache line */ + IX_ETHACC_NE_CACHE_INVALIDATE(ptr); + + /* next mbuf in the chain */ + ptr = nextPtr; + } + while(ptr != NULL); + } + + /* virt2phys mbuf itself */ + qbuf = (UINT32)IX_OSAL_MMU_VIRT_TO_PHYS( + IX_ETHACC_NE_SHARED(mbuf)); + + /* Ensure the bits which are reserved to exchange information with + * the NPE are cleared + * + * If the mbuf address is not correctly aligned, or from an + * incompatible memory range, there is no point to continue + */ + IX_OSAL_ENSURE(((qbuf & ~IX_ETHNPE_QM_Q_RXENET_ADDR_MASK) == 0), + "Invalid address range"); + + return qbuf; +} + +/* Convert the mbuf header after NPE transmission + * Since there is nothing changed by the NPE, there is no need + * to process anything but the update of internal stats + * when they are enabled +*/ +PRIVATE void +ixEthAccMbufFromTxQ(IX_OSAL_MBUF *mbuf) +{ +#ifndef NDEBUG + /* test for unchained mbufs */ + if (IX_ETHACC_NE_NEXT(mbuf) == 0) + { + /* unchained mbufs : update the stats */ + IX_ETH_ACC_STATS_INC(ixEthAccDataStats.unchainedTxDoneMBufs); + } + else + { + /* chained mbufs : walk the chain and update the stats */ + IX_OSAL_MBUF *ptr = mbuf; + + do + { + IX_ETH_ACC_STATS_INC(ixEthAccDataStats.chainedTxDoneMBufs); + ptr = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(ptr); + } + while (ptr != NULL); + } +#endif +} + +/* Convert the mbuf header after NPE reception */ +PRIVATE void +ixEthAccMbufFromRxQ(IX_OSAL_MBUF *mbuf) +{ + UINT32 len; + + /* endianess swap for tci and flags + note: this is done only once, even for chained buffers */ + IX_ETHACC_NE_FLAGS(mbuf) = IX_OSAL_SWAP_BE_SHARED_SHORT(IX_ETHACC_NE_FLAGS(mbuf)); + IX_ETHACC_NE_VLANTCI(mbuf) = IX_OSAL_SWAP_BE_SHARED_SHORT(IX_ETHACC_NE_VLANTCI(mbuf)); + + /* test for unchained mbufs */ + if (IX_ETHACC_NE_NEXT(mbuf) == 0) + { + /* unchained mbufs */ + IX_ETH_ACC_STATS_INC(ixEthAccDataStats.unchainedRxMBufs); + + /* get the frame length. it is the same than the buffer length */ + len = IX_OSAL_SWAP_BE_SHARED_LONG(IX_ETHACC_NE_LEN(mbuf)); + len &= IX_ETHNPE_ACC_PKTLENGTH_MASK; + IX_OSAL_MBUF_PKT_LEN(mbuf) = IX_OSAL_MBUF_MLEN(mbuf) = len; + + /* clears the next packet field */ + IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mbuf) = NULL; + } + else + { + IX_OSAL_MBUF *ptr = mbuf; + IX_OSAL_MBUF *nextPtr; + UINT32 frmLen; + + /* convert the frame length */ + frmLen = IX_OSAL_SWAP_BE_SHARED_LONG(IX_ETHACC_NE_LEN(mbuf)); + IX_OSAL_MBUF_PKT_LEN(mbuf) = (frmLen & IX_ETHNPE_ACC_PKTLENGTH_MASK); + + /* chained mbufs */ + do + { + IX_ETH_ACC_STATS_INC(ixEthAccDataStats.chainedRxMBufs); + + /* convert the length */ + len = IX_OSAL_SWAP_BE_SHARED_LONG(IX_ETHACC_NE_LEN(ptr)); + IX_OSAL_MBUF_MLEN(ptr) = (len >> IX_ETHNPE_ACC_LENGTH_OFFSET); + + /* get the next pointer */ + PTR_NPE2VIRT(IX_OSAL_MBUF *,IX_ETHACC_NE_NEXT(ptr), nextPtr); + if (nextPtr != NULL) + { + nextPtr = (IX_OSAL_MBUF *)((UINT8 *)nextPtr - offsetof(IX_OSAL_MBUF,ix_ne)); + } + /* set the next pointer */ + IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(ptr) = nextPtr; + + /* move to the next buffer */ + ptr = nextPtr; + } + while (ptr != NULL); + } +} + +/* write to qmgr if possible and report an overflow if not possible + * Use a fast lock to protect the queue write. + * This way, the tx feature is reentrant. + */ +PRIVATE IX_STATUS +ixEthAccQmgrLockTxWrite(IxEthAccPortId portId, UINT32 qBuffer) +{ + IX_STATUS qStatus; + if (ixOsalFastMutexTryLock(&txWriteMutex[portId]) == IX_SUCCESS) + { + qStatus = ixQMgrQWrite( + IX_ETH_ACC_PORT_TO_TX_Q_ID(portId), + &qBuffer); +#ifndef NDEBUG + if (qStatus != IX_SUCCESS) + { + TX_STATS_INC(portId, txOverflow); + } +#endif + ixOsalFastMutexUnlock(&txWriteMutex[portId]); + } + else + { + TX_STATS_INC(portId, txLock); + qStatus = IX_QMGR_Q_OVERFLOW; + } + return qStatus; +} + +/* write to qmgr if possible and report an overflow if not possible + * Use a fast lock to protect the queue write. + * This way, the Rx feature is reentrant. + */ +PRIVATE IX_STATUS +ixEthAccQmgrLockRxWrite(IxEthAccPortId portId, UINT32 qBuffer) +{ + IX_STATUS qStatus; + if (ixOsalFastMutexTryLock(&rxWriteMutex[portId]) == IX_SUCCESS) + { + qStatus = ixQMgrQWrite( + IX_ETH_ACC_PORT_TO_RX_FREE_Q_ID(portId), + &qBuffer); +#ifndef NDEBUG + if (qStatus != IX_SUCCESS) + { + RX_STATS_INC(portId, rxFreeOverflow); + } +#endif + ixOsalFastMutexUnlock(&rxWriteMutex[portId]); + } + else + { + RX_STATS_INC(portId, rxFreeLock); + qStatus = IX_QMGR_Q_OVERFLOW; + } + return qStatus; +} + +/* + * Set the priority and write to a qmgr queue. + */ +PRIVATE IX_STATUS +ixEthAccQmgrTxWrite(IxEthAccPortId portId, UINT32 qBuffer, UINT32 priority) +{ + /* fill the priority field */ + qBuffer |= (priority << IX_ETHNPE_QM_Q_FIELD_PRIOR_R); + + return ixEthAccQmgrLockTxWrite(portId, qBuffer); +} + +/** + * + * @brief This function will discover the highest priority S/W Tx Q that + * has entries in it + * + * @param portId - (in) the id of the port whose S/W Tx queues are to be searched + * priorityPtr - (out) the priority of the highest priority occupied q will be written + * here + * + * @return IX_ETH_ACC_SUCCESS if an occupied Q is found + * IX_ETH_ACC_FAIL if no Q has entries + * + * @internal + */ +PRIVATE IxEthAccStatus +ixEthAccTxSwQHighestPriorityGet(IxEthAccPortId portId, + IxEthAccTxPriority *priorityPtr) +{ + if (ixEthAccPortData[portId].ixEthAccTxData.schDiscipline + == FIFO_NO_PRIORITY) + { + if(IX_ETH_ACC_DATAPLANE_IS_Q_EMPTY(ixEthAccPortData[portId]. + ixEthAccTxData.txQ[IX_ETH_ACC_TX_DEFAULT_PRIORITY])) + { + return IX_ETH_ACC_FAIL; + } + else + { + *priorityPtr = IX_ETH_ACC_TX_DEFAULT_PRIORITY; + TX_STATS_INC(portId,txPriority[*priorityPtr]); + return IX_ETH_ACC_SUCCESS; + } + } + else + { + IxEthAccTxPriority highestPriority = IX_ETH_ACC_TX_PRIORITY_7; + while(1) + { + if(!IX_ETH_ACC_DATAPLANE_IS_Q_EMPTY(ixEthAccPortData[portId]. + ixEthAccTxData.txQ[highestPriority])) + { + + *priorityPtr = highestPriority; + TX_STATS_INC(portId,txPriority[highestPriority]); + return IX_ETH_ACC_SUCCESS; + + } + if (highestPriority == IX_ETH_ACC_TX_PRIORITY_0) + { + return IX_ETH_ACC_FAIL; + } + highestPriority--; + } + } +} + +/** + * + * @brief This function will take a buffer from a TX S/W Q and attempt + * to add it to the relevant TX H/W Q + * + * @param portId - the port whose TX queue is to be written to + * priority - identifies the queue from which the entry is to be read + * + * @internal + */ +PRIVATE IxEthAccStatus +ixEthAccTxFromSwQ(IxEthAccPortId portId, + IxEthAccTxPriority priority) +{ + IX_OSAL_MBUF *mbuf; + IX_STATUS qStatus; + + IX_OSAL_ENSURE((UINT32)priority <= (UINT32)7, "Invalid priority"); + + IX_ETH_ACC_DATAPLANE_REMOVE_MBUF_FROM_Q_HEAD( + ixEthAccPortData[portId].ixEthAccTxData.txQ[priority], + mbuf); + + if (mbuf != NULL) + { + /* + * Add the Tx buffer to the H/W Tx Q + * We do not need to flush here as it is already done + * in TxFrameSubmit(). + */ + qStatus = ixEthAccQmgrTxWrite( + portId, + IX_OSAL_MMU_VIRT_TO_PHYS((UINT32)IX_ETHACC_NE_SHARED(mbuf)), + priority); + + if (qStatus == IX_SUCCESS) + { + TX_STATS_INC(portId,txFromSwQOK); + return IX_SUCCESS; + } + else if (qStatus == IX_QMGR_Q_OVERFLOW) + { + /* + * H/W Q overflow, need to save the buffer + * back on the s/w Q. + * we must put it back on the head of the q to avoid + * reordering packet tx + */ + TX_STATS_INC(portId,txFromSwQDelayed); + IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_HEAD( + ixEthAccPortData[portId].ixEthAccTxData.txQ[priority], + mbuf); + + /*enable Q notification*/ + qStatus = ixQMgrNotificationEnable( + IX_ETH_ACC_PORT_TO_TX_Q_ID(portId), + IX_ETH_ACC_PORT_TO_TX_Q_SOURCE(portId)); + + if (qStatus != IX_SUCCESS && qStatus != IX_QMGR_WARNING) + { + TX_INC(portId,txUnexpectedError); + IX_ETH_ACC_FATAL_LOG( + "ixEthAccTxFromSwQ:Unexpected Error: %u\n", + qStatus, 0, 0, 0, 0, 0); + } + } + else + { + TX_INC(portId,txUnexpectedError); + + /* recovery attempt */ + IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_HEAD( + ixEthAccPortData[portId].ixEthAccTxData.txQ[priority], + mbuf); + + IX_ETH_ACC_FATAL_LOG( + "ixEthAccTxFromSwQ:Error: unexpected QM status 0x%08X\n", + qStatus, 0, 0, 0, 0, 0); + } + } + else + { + /* sw queue is empty */ + } + return IX_ETH_ACC_FAIL; +} + +/** + * + * @brief This function will take a buffer from a RXfree S/W Q and attempt + * to add it to the relevant RxFree H/W Q + * + * @param portId - the port whose RXFree queue is to be written to + * + * @internal + */ +PRIVATE IxEthAccStatus +ixEthAccRxFreeFromSwQ(IxEthAccPortId portId) +{ + IX_OSAL_MBUF *mbuf; + IX_STATUS qStatus = IX_SUCCESS; + + IX_ETH_ACC_DATAPLANE_REMOVE_MBUF_FROM_Q_HEAD( + ixEthAccPortData[portId].ixEthAccRxData.freeBufferList, + mbuf); + if (mbuf != NULL) + { + /* + * Add The Rx Buffer to the H/W Free buffer Q if possible + */ + qStatus = ixEthAccQmgrLockRxWrite(portId, + IX_OSAL_MMU_VIRT_TO_PHYS( + (UINT32)IX_ETHACC_NE_SHARED(mbuf))); + + if (qStatus == IX_SUCCESS) + { + RX_STATS_INC(portId,rxFreeRepFromSwQOK); + /* + * Buffer added to h/w Q. + */ + return IX_SUCCESS; + } + else if (qStatus == IX_QMGR_Q_OVERFLOW) + { + /* + * H/W Q overflow, need to save the buffer back on the s/w Q. + */ + RX_STATS_INC(portId,rxFreeRepFromSwQDelayed); + + IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_HEAD( + ixEthAccPortData[portId].ixEthAccRxData.freeBufferList, + mbuf); + } + else + { + /* unexpected qmgr error */ + RX_INC(portId,rxUnexpectedError); + + IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_HEAD( + ixEthAccPortData[portId].ixEthAccRxData.freeBufferList, + mbuf); + + IX_ETH_ACC_FATAL_LOG("IxEthAccRxFreeFromSwQ:Error: unexpected QM status 0x%08X\n", + qStatus, 0, 0, 0, 0, 0); + } + } + else + { + /* sw queue is empty */ + } + return IX_ETH_ACC_FAIL; +} + + +IX_ETH_ACC_PUBLIC +IxEthAccStatus ixEthAccInitDataPlane() +{ + UINT32 portId; + + /* + * Initialize the service and register callback to other services. + */ + + IX_ETH_ACC_MEMSET(&ixEthAccDataStats, + 0, + sizeof(ixEthAccDataStats)); + + for(portId=0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++) + { + ixOsalFastMutexInit(&txWriteMutex[portId]); + ixOsalFastMutexInit(&rxWriteMutex[portId]); + + IX_ETH_ACC_MEMSET(&ixEthAccPortData[portId], + 0, + sizeof(ixEthAccPortData[portId])); + + ixEthAccPortData[portId].ixEthAccTxData.schDiscipline = FIFO_NO_PRIORITY; + } + + return (IX_ETH_ACC_SUCCESS); +} + + +IX_ETH_ACC_PUBLIC +IxEthAccStatus ixEthAccPortTxDoneCallbackRegister(IxEthAccPortId portId, + IxEthAccPortTxDoneCallback + txCallbackFn, + UINT32 callbackTag) +{ + if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) + { + return (IX_ETH_ACC_FAIL); + } + if (!IX_ETH_ACC_IS_PORT_VALID(portId)) + { + return (IX_ETH_ACC_INVALID_PORT); + } + +/* HACK: removing this code to enable NPE-A preliminary testing + * if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + * { + * IX_ETH_ACC_WARNING_LOG("ixEthAccPortTxDoneCallbackRegister: Unavailable Eth %d: Cannot register TxDone Callback.\n",(INT32)portId,0,0,0,0,0); + * return IX_ETH_ACC_SUCCESS ; + * } + */ + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + if (txCallbackFn == 0) + /* Check for null function pointer here. */ + { + return (IX_ETH_ACC_INVALID_ARG); + } + ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn = txCallbackFn; + ixEthAccPortData[portId].ixEthAccTxData.txCallbackTag = callbackTag; + return (IX_ETH_ACC_SUCCESS); +} + + +IX_ETH_ACC_PUBLIC +IxEthAccStatus ixEthAccPortRxCallbackRegister(IxEthAccPortId portId, + IxEthAccPortRxCallback + rxCallbackFn, + UINT32 callbackTag) +{ + IxEthAccPortId port; + + if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) + { + return (IX_ETH_ACC_FAIL); + } + 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("ixEthAccPortRxCallbackRegister: Unavailable Eth %d: Cannot register Rx Callback.\n",(INT32)portId,0,0,0,0,0); + return IX_ETH_ACC_SUCCESS ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + /* Check for null function pointer here. */ + if (rxCallbackFn == NULL) + { + return (IX_ETH_ACC_INVALID_ARG); + } + + /* Check the user is not changing the callback type + * when the port is enabled. + */ + if (ixEthAccMacState[portId].portDisableState == ACTIVE) + { + for (port = 0; port < IX_ETH_ACC_NUMBER_OF_PORTS; port++) + { + if ((ixEthAccMacState[port].portDisableState == ACTIVE) + && (ixEthAccPortData[port].ixEthAccRxData.rxMultiBufferCallbackInUse == TRUE)) + { + /* one of the active ports has a different rx callback type. + * Changing the callback type when the port is enabled + * is not safe + */ + return (IX_ETH_ACC_INVALID_ARG); + } + } + } + + /* update the callback pointer : this is done before + * registering the new qmgr callback + */ + ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn = rxCallbackFn; + ixEthAccPortData[portId].ixEthAccRxData.rxCallbackTag = callbackTag; + + /* update the qmgr callback for rx queues */ + if (ixEthAccQMgrRxCallbacksRegister(ixEthRxFrameQMCallback) + != IX_ETH_ACC_SUCCESS) + { + /* unexpected qmgr error */ + IX_ETH_ACC_FATAL_LOG("ixEthAccPortRxCallbackRegister: unexpected QMgr error, " \ + "could not register Rx single-buffer callback\n", 0, 0, 0, 0, 0, 0); + + RX_INC(portId,rxUnexpectedError); + return (IX_ETH_ACC_INVALID_ARG); + } + + ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackInUse = FALSE; + + return (IX_ETH_ACC_SUCCESS); +} + +IX_ETH_ACC_PUBLIC +IxEthAccStatus ixEthAccPortMultiBufferRxCallbackRegister( + IxEthAccPortId portId, + IxEthAccPortMultiBufferRxCallback + rxCallbackFn, + UINT32 callbackTag) +{ + IxEthAccPortId port; + + if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) + { + return (IX_ETH_ACC_FAIL); + } + 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("ixEthAccPortMultiBufferRxCallbackRegister: Unavailable Eth %d: Cannot register Rx Callback.\n",(INT32)portId,0,0,0,0,0); + return IX_ETH_ACC_SUCCESS ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + /* Check for null function pointer here. */ + if (rxCallbackFn == NULL) + { + return (IX_ETH_ACC_INVALID_ARG); + } + + /* Check the user is not changing the callback type + * when the port is enabled. + */ + if (ixEthAccMacState[portId].portDisableState == ACTIVE) + { + for (port = 0; port < IX_ETH_ACC_NUMBER_OF_PORTS; port++) + { + if ((ixEthAccMacState[port].portDisableState == ACTIVE) + && (ixEthAccPortData[port].ixEthAccRxData.rxMultiBufferCallbackInUse == FALSE)) + { + /* one of the active ports has a different rx callback type. + * Changing the callback type when the port is enabled + * is not safe + */ + return (IX_ETH_ACC_INVALID_ARG); + } + } + } + + /* update the callback pointer : this is done before + * registering the new qmgr callback + */ + ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackFn = rxCallbackFn; + ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackTag = callbackTag; + + /* update the qmgr callback for rx queues */ + if (ixEthAccQMgrRxCallbacksRegister(ixEthRxMultiBufferQMCallback) + != IX_ETH_ACC_SUCCESS) + { + /* unexpected qmgr error */ + RX_INC(portId,rxUnexpectedError); + + IX_ETH_ACC_FATAL_LOG("ixEthAccPortMultiBufferRxCallbackRegister: unexpected QMgr error, " \ + "could not register Rx multi-buffer callback\n", 0, 0, 0, 0, 0, 0); + + return (IX_ETH_ACC_INVALID_ARG); + } + + ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackInUse = TRUE; + + return (IX_ETH_ACC_SUCCESS); +} + +IX_ETH_ACC_PUBLIC +IxEthAccStatus ixEthAccPortTxFrameSubmit(IxEthAccPortId portId, + IX_OSAL_MBUF *buffer, + IxEthAccTxPriority priority) +{ + IX_STATUS qStatus = IX_SUCCESS; + UINT32 qBuffer; + IxEthAccTxPriority highestPriority; + IxQMgrQStatus txQStatus; + +#ifndef NDEBUG + if (buffer == NULL) + { + return (IX_ETH_ACC_FAIL); + } + if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) + { + return (IX_ETH_ACC_FAIL); + } + if (!IX_ETH_ACC_IS_PORT_VALID(portId)) + { + return (IX_ETH_ACC_INVALID_PORT); + } + + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + IX_ETH_ACC_FATAL_LOG("ixEthAccPortTxFrameSubmit: Unavailable Eth %d: Cannot submit Tx Frame.\n", + (INT32)portId,0,0,0,0,0); + return IX_ETH_ACC_PORT_UNINITIALIZED ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + if ((UINT32)priority > (UINT32)IX_ETH_ACC_TX_PRIORITY_7) + { + return (IX_ETH_ACC_INVALID_ARG); + } +#endif + + /* + * Need to Flush the MBUF and its contents (data) as it may be + * read from the NPE. Convert virtual addresses to physical addresses also. + */ + qBuffer = ixEthAccMbufTxQPrepare(buffer); + + /* + * If no fifo priority set on Xscale ... + */ + if (ixEthAccPortData[portId].ixEthAccTxData.schDiscipline == + FIFO_NO_PRIORITY) + { + /* + * Add The Tx Buffer to the H/W Tx Q if possible + * (the priority is passed to the NPE, because + * the NPE is able to reorder the frames + * before transmission to the underlying hardware) + */ + qStatus = ixEthAccQmgrTxWrite(portId, + qBuffer, + IX_ETH_ACC_TX_DEFAULT_PRIORITY); + + if (qStatus == IX_SUCCESS) + { + TX_STATS_INC(portId,txQOK); + + /* + * "best case" scenario : Buffer added to h/w Q. + */ + return (IX_SUCCESS); + } + else if (qStatus == IX_QMGR_Q_OVERFLOW) + { + /* + * We were unable to write the buffer to the + * appropriate H/W Q, Save it in the sw Q. + * (use the default priority queue regardless of + * input parameter) + */ + priority = IX_ETH_ACC_TX_DEFAULT_PRIORITY; + } + else + { + /* unexpected qmgr error */ + TX_INC(portId,txUnexpectedError); + IX_ETH_ACC_FATAL_LOG( + "ixEthAccPortTxFrameSubmit:Error: qStatus = %u\n", + (UINT32)qStatus, 0, 0, 0, 0, 0); + return (IX_ETH_ACC_FAIL); + } + } + else if (ixEthAccPortData[portId].ixEthAccTxData.schDiscipline == + FIFO_PRIORITY) + { + + /* + * For priority transmission, put the frame directly on the H/W queue + * if the H/W queue is empty, otherwise, put it in a S/W Q + */ + ixQMgrQStatusGet(IX_ETH_ACC_PORT_TO_TX_Q_ID(portId), &txQStatus); + if((txQStatus & IX_QMGR_Q_STATUS_E_BIT_MASK) != 0) + { + /*The tx queue is empty, check whether there are buffers on the s/w queues*/ + if(ixEthAccTxSwQHighestPriorityGet(portId, &highestPriority) + !=IX_ETH_ACC_FAIL) + { + /*there are buffers on the s/w queues, submit them*/ + ixEthAccTxFromSwQ(portId, highestPriority); + + /* the queue was empty, 1 buffer is already supplied + * but is likely to be immediately transmitted and the + * hw queue is likely to be empty again, so submit + * more from the sw queues + */ + if(ixEthAccTxSwQHighestPriorityGet(portId, &highestPriority) + !=IX_ETH_ACC_FAIL) + { + ixEthAccTxFromSwQ(portId, highestPriority); + /* + * and force the buffer supplied to be placed + * on a priority queue + */ + qStatus = IX_QMGR_Q_OVERFLOW; + } + else + { + /*there are no buffers in the s/w queues, submit directly*/ + qStatus = ixEthAccQmgrTxWrite(portId, qBuffer, priority); + } + } + else + { + /*there are no buffers in the s/w queues, submit directly*/ + qStatus = ixEthAccQmgrTxWrite(portId, qBuffer, priority); + } + } + else + { + qStatus = IX_QMGR_Q_OVERFLOW; + } + } + else + { + TX_INC(portId,txUnexpectedError); + IX_ETH_ACC_FATAL_LOG( + "ixEthAccPortTxFrameSubmit:Error: wrong schedule discipline setup\n", + 0, 0, 0, 0, 0, 0); + return (IX_ETH_ACC_FAIL); + } + + if(qStatus == IX_SUCCESS ) + { + TX_STATS_INC(portId,txQOK); + return IX_ETH_ACC_SUCCESS; + } + else if(qStatus == IX_QMGR_Q_OVERFLOW) + { + TX_STATS_INC(portId,txQDelayed); + /* + * We were unable to write the buffer to the + * appropriate H/W Q, Save it in a s/w Q. + */ + IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_TAIL( + ixEthAccPortData[portId]. + ixEthAccTxData.txQ[priority], + buffer); + + qStatus = ixQMgrNotificationEnable( + IX_ETH_ACC_PORT_TO_TX_Q_ID(portId), + IX_ETH_ACC_PORT_TO_TX_Q_SOURCE(portId)); + + if (qStatus != IX_SUCCESS) + { + if (qStatus == IX_QMGR_WARNING) + { + /* notification is enabled for a queue + * which is already empty (the condition is already met) + * and there will be no more queue event to drain the sw queue + */ + TX_STATS_INC(portId,txLateNotificationEnabled); + + /* pull a buffer from the sw queue */ + if(ixEthAccTxSwQHighestPriorityGet(portId, &highestPriority) + !=IX_ETH_ACC_FAIL) + { + /*there are buffers on the s/w queues, submit from them*/ + ixEthAccTxFromSwQ(portId, highestPriority); + } + } + else + { + TX_INC(portId,txUnexpectedError); + IX_ETH_ACC_FATAL_LOG( + "ixEthAccPortTxFrameSubmit: unexpected Error: %u\n", + qStatus, 0, 0, 0, 0, 0); + } + } + } + else + { + TX_INC(portId,txUnexpectedError); + IX_ETH_ACC_FATAL_LOG( + "ixEthAccPortTxFrameSubmit: unexpected Error: %u\n", + qStatus, 0, 0, 0, 0, 0); + return (IX_ETH_ACC_FAIL); + } + + return (IX_ETH_ACC_SUCCESS); +} + + +/** + * + * @brief replenish: convert a chain of mbufs to the format + * expected by the NPE + * + */ + +IX_ETH_ACC_PUBLIC +IxEthAccStatus ixEthAccPortRxFreeReplenish(IxEthAccPortId portId, + IX_OSAL_MBUF *buffer) +{ + IX_STATUS qStatus = IX_SUCCESS; + UINT32 qBuffer; + + /* + * Check buffer is valid. + */ + +#ifndef NDEBUG + /* check parameter value */ + if (buffer == 0) + { + return (IX_ETH_ACC_FAIL); + } + if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) + { + return (IX_ETH_ACC_FAIL); + } + if (!IX_ETH_ACC_IS_PORT_VALID(portId)) + { + return (IX_ETH_ACC_INVALID_PORT); + } + + /* check initialisation is done */ + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + IX_ETH_ACC_FATAL_LOG(" ixEthAccPortRxFreeReplenish: Unavailable Eth %d: Cannot replenish Rx Free Q.\n",(INT32)portId,0,0,0,0,0); + return IX_ETH_ACC_PORT_UNINITIALIZED ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + /* check boundaries and constraints */ + if (IX_OSAL_MBUF_MLEN(buffer) < IX_ETHNPE_ACC_RXFREE_BUFFER_LENGTH_MIN) + { + return (IX_ETH_ACC_FAIL); + } +#endif + + qBuffer = ixEthAccMbufRxQPrepare(buffer); + + /* + * Add The Rx Buffer to the H/W Free buffer Q if possible + */ + qStatus = ixEthAccQmgrLockRxWrite(portId, qBuffer); + + if (qStatus == IX_SUCCESS) + { + RX_STATS_INC(portId,rxFreeRepOK); + /* + * Buffer added to h/w Q. + */ + return (IX_SUCCESS); + } + else if (qStatus == IX_QMGR_Q_OVERFLOW) + { + RX_STATS_INC(portId,rxFreeRepDelayed); + /* + * We were unable to write the buffer to the approprate H/W Q, + * Save it in a s/w Q. + */ + IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_TAIL( + ixEthAccPortData[portId].ixEthAccRxData.freeBufferList, + buffer); + + qStatus = ixQMgrNotificationEnable( + IX_ETH_ACC_PORT_TO_RX_FREE_Q_ID(portId), + IX_ETH_ACC_PORT_TO_RX_FREE_Q_SOURCE(portId)); + + if (qStatus != IX_SUCCESS) + { + if (qStatus == IX_QMGR_WARNING) + { + /* notification is enabled for a queue + * which is already empty (the condition is already met) + * and there will be no more queue event to drain the sw queue + * move an entry from the sw queue to the hw queue */ + RX_STATS_INC(portId,rxFreeLateNotificationEnabled); + ixEthAccRxFreeFromSwQ(portId); + } + else + { + RX_INC(portId,rxUnexpectedError); + IX_ETH_ACC_FATAL_LOG( + "ixEthAccRxPortFreeReplenish:Error: %u\n", + qStatus, 0, 0, 0, 0, 0); + } + } + } + else + { + RX_INC(portId,rxUnexpectedError); + IX_ETH_ACC_FATAL_LOG( + "ixEthAccRxPortFreeReplenish:Error: qStatus = %u\n", + (UINT32)qStatus, 0, 0, 0, 0, 0); + return(IX_ETH_ACC_FAIL); + } + return (IX_ETH_ACC_SUCCESS); +} + + +IX_ETH_ACC_PUBLIC +IxEthAccStatus ixEthAccTxSchedulingDisciplineSetPriv(IxEthAccPortId portId, + IxEthAccSchedulerDiscipline + sched) +{ + 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("ixEthAccTxSchedulingDisciplineSet: Unavailable Eth %d: Cannot set Tx Scheduling Discipline.\n",(INT32)portId,0,0,0,0,0); + return IX_ETH_ACC_SUCCESS ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + if (sched != FIFO_PRIORITY && sched != FIFO_NO_PRIORITY) + { + return (IX_ETH_ACC_INVALID_ARG); + } + + ixEthAccPortData[portId].ixEthAccTxData.schDiscipline = sched; + return (IX_ETH_ACC_SUCCESS); +} + +IX_ETH_ACC_PUBLIC +IxEthAccStatus ixEthAccRxSchedulingDisciplineSetPriv(IxEthAccSchedulerDiscipline + sched) +{ + if (sched != FIFO_PRIORITY && sched != FIFO_NO_PRIORITY) + { + return (IX_ETH_ACC_INVALID_ARG); + } + + ixEthAccDataInfo.schDiscipline = sched; + + return (IX_ETH_ACC_SUCCESS); +} + + +/** + * @fn ixEthRxFrameProcess(IxEthAccPortId portId, IX_OSAL_MBUF *mbufPtr) + * + * @brief process incoming frame : + * + * @param @ref IxQMgrCallback IxQMgrMultiBufferCallback + * + * @return none + * + * @internal + * + */ +IX_ETH_ACC_PRIVATE BOOL +ixEthRxFrameProcess(IxEthAccPortId portId, IX_OSAL_MBUF *mbufPtr) +{ + UINT32 flags; + IxEthDBStatus result; + +#ifndef NDEBUG + /* Prudent to at least check the port is within range */ + if (portId >= IX_ETH_ACC_NUMBER_OF_PORTS) + { + ixEthAccDataStats.unexpectedError++; + IX_ETH_ACC_FATAL_LOG( + "ixEthRxFrameProcess: Illegal port: %u\n", + (UINT32)portId, 0, 0, 0, 0, 0); + return FALSE; + } +#endif + + /* convert fields from mbuf header */ + ixEthAccMbufFromRxQ(mbufPtr); + + /* check about any special processing for this frame */ + flags = IX_ETHACC_NE_FLAGS(mbufPtr); + if ((flags & (IX_ETHACC_NE_FILTERMASK | IX_ETHACC_NE_NEWSRCMASK)) == 0) + { + /* "best case" scenario : nothing special to do for this frame */ + return TRUE; + } + +#ifdef CONFIG_IXP425_COMPONENT_ETHDB + /* if a new source MAC address is detected by the NPE, + * update IxEthDB with the portId and the MAC address. + */ + if ((flags & IX_ETHACC_NE_NEWSRCMASK & ixEthAccNewSrcMask) != 0) + { + result = ixEthDBFilteringDynamicEntryProvision(portId, + (IxEthDBMacAddr *) IX_ETHACC_NE_SOURCEMAC(mbufPtr)); + + if (result != IX_ETH_DB_SUCCESS && result != IX_ETH_DB_FEATURE_UNAVAILABLE) + { + if ((ixEthAccMacState[portId].portDisableState == ACTIVE) && (result != IX_ETH_DB_BUSY)) + { + RX_STATS_INC(portId, rxUnexpectedError); + IX_ETH_ACC_FATAL_LOG("ixEthRxFrameProcess: Failed to add source MAC \ + to the Learning/Filtering database\n", 0, 0, 0, 0, 0, 0); + } + else + { + /* we expect this to fail during PortDisable, as EthDB is disabled for + * that port and will refuse to learn new addresses + */ + } + } + else + { + RX_STATS_INC(portId, rxUnlearnedMacAddress); + } + } +#endif + + /* check if this frame should have been filtered + * by the NPE and take the appropriate action + */ + if (((flags & IX_ETHACC_NE_FILTERMASK) != 0) + && (ixEthAccMacState[portId].portDisableState == ACTIVE)) + { + /* If the mbuf was allocated with a small data size, or the current data pointer is not + * within the allocated data area, then the buffer is non-standard and has to be + * replenished with the minimum size only + */ + if( (IX_OSAL_MBUF_ALLOCATED_BUFF_LEN(mbufPtr) < IX_ETHNPE_ACC_RXFREE_BUFFER_LENGTH_MIN) + || ((UINT8 *)IX_OSAL_MBUF_ALLOCATED_BUFF_DATA(mbufPtr) > IX_OSAL_MBUF_MDATA(mbufPtr)) + || ((UINT8 *)(IX_OSAL_MBUF_ALLOCATED_BUFF_DATA(mbufPtr) + + IX_OSAL_MBUF_ALLOCATED_BUFF_LEN(mbufPtr)) + < IX_OSAL_MBUF_MDATA(mbufPtr)) ) + { + /* set to minimum length */ + IX_OSAL_MBUF_MLEN(mbufPtr) = IX_OSAL_MBUF_PKT_LEN(mbufPtr) = + IX_ETHNPE_ACC_RXFREE_BUFFER_LENGTH_MIN; + } + else + { + /* restore original length */ + IX_OSAL_MBUF_MLEN(mbufPtr) = IX_OSAL_MBUF_PKT_LEN(mbufPtr) = + ( IX_OSAL_MBUF_ALLOCATED_BUFF_LEN(mbufPtr) - + (IX_OSAL_MBUF_MDATA(mbufPtr) - (UINT8 *)IX_OSAL_MBUF_ALLOCATED_BUFF_DATA(mbufPtr)) ); + } + + /* replenish from here */ + if (ixEthAccPortRxFreeReplenish(portId, mbufPtr) != IX_ETH_ACC_SUCCESS) + { + IX_ETH_ACC_FATAL_LOG("ixEthRxFrameProcess: Failed to replenish with filtered frame\ + on port %d\n", portId, 0, 0, 0, 0, 0); + } + + RX_STATS_INC(portId, rxFiltered); + + /* indicate that frame should not be subjected to further processing */ + return FALSE; + } + + return TRUE; +} + + +/** + * @fn ixEthRxFrameQMCallback + * + * @brief receive callback for Frame receive Q from NPE + * + * Frames are passed one-at-a-time to the user + * + * @param @ref IxQMgrCallback + * + * @return none + * + * @internal + * + * Design note : while processing the entry X, entry X+1 is preloaded + * into memory to reduce the number of stall cycles + * + */ +void ixEthRxFrameQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId) +{ + IX_OSAL_MBUF *mbufPtr; + IX_OSAL_MBUF *nextMbufPtr; + UINT32 qEntry; + UINT32 nextQEntry; + UINT32 *qEntryPtr; + UINT32 portId; + UINT32 destPortId; + UINT32 npeId; + UINT32 rxQReadStatus; + + /* + * Design note : entries are read in a buffer, This buffer contains + * an extra zeroed entry so the loop will + * always terminate on a null entry, whatever the result of Burst read is. + */ + UINT32 rxQEntry[IX_ETH_ACC_MAX_RX_FRAME_CONSUME_PER_CALLBACK + 1]; + + /* + * Indication of the number of times the callback is used. + */ + IX_ETH_ACC_STATS_INC(ixEthAccDataStats.rxCallbackCounter); + + do + { + /* + * Indication of the number of times the queue is drained + */ + IX_ETH_ACC_STATS_INC(ixEthAccDataStats.rxCallbackBurstRead); + + /* ensure the last entry of the array contains a zeroed value */ + qEntryPtr = rxQEntry; + qEntryPtr[IX_ETH_ACC_MAX_RX_FRAME_CONSUME_PER_CALLBACK] = 0; + + rxQReadStatus = ixQMgrQBurstRead(qId, + IX_ETH_ACC_MAX_RX_FRAME_CONSUME_PER_CALLBACK, + qEntryPtr); + +#ifndef NDEBUG + if ((rxQReadStatus != IX_QMGR_Q_UNDERFLOW) + && (rxQReadStatus != IX_SUCCESS)) + { + ixEthAccDataStats.unexpectedError++; + /*major error*/ + IX_ETH_ACC_FATAL_LOG( + "ixEthRxFrameQMCallback:Error: %u\n", + (UINT32)rxQReadStatus, 0, 0, 0, 0, 0); + return; + } +#endif + + /* convert and preload the next entry + * (the conversion function takes care about null pointers which + * are used to mark the end of the loop) + */ + nextQEntry = *qEntryPtr; + nextMbufPtr = ixEthAccEntryFromQConvert(nextQEntry, + IX_ETHNPE_QM_Q_RXENET_ADDR_MASK); + + while(nextQEntry != 0) + { + /* get the next entry */ + qEntry = nextQEntry; + mbufPtr = nextMbufPtr; + +#ifndef NDEBUG + if (mbufPtr == NULL) + { + ixEthAccDataStats.unexpectedError++; + IX_ETH_ACC_FATAL_LOG( + "ixEthRxFrameQMCallback: Null Mbuf Ptr\n", + 0, 0, 0, 0, 0, 0); + return; + } +#endif + + /* convert the next entry + * (the conversion function takes care about null pointers which + * are used to mark the end of the loop) + */ + nextQEntry = *(++qEntryPtr); + nextMbufPtr = ixEthAccEntryFromQConvert(nextQEntry, + IX_ETHNPE_QM_Q_RXENET_ADDR_MASK); + + /* + * Get Port and Npe ID from message. + */ + npeId = ((IX_ETHNPE_QM_Q_RXENET_NPEID_MASK & + qEntry) >> IX_ETHNPE_QM_Q_FIELD_NPEID_R); + portId = IX_ETH_ACC_NPE_TO_PORT_ID(npeId); + + /* process frame, check the return code and skip the remaining of + * the loop if the frame is to be filtered out + */ + if (ixEthRxFrameProcess(portId, mbufPtr)) + { + /* destination portId for this packet */ + destPortId = IX_ETHACC_NE_DESTPORTID(mbufPtr); + + if (destPortId != IX_ETH_DB_UNKNOWN_PORT) + { + destPortId = IX_ETH_DB_NPE_LOGICAL_ID_TO_PORT_ID(destPortId); + } + + /* test if QoS is enabled in ethAcc + */ + if (ixEthAccDataInfo.schDiscipline == FIFO_PRIORITY) + { + /* check if there is a higher priority queue + * which may require processing and then process it. + */ + if (ixEthAccDataInfo.higherPriorityQueue[qId] < IX_QMGR_MAX_NUM_QUEUES) + { + ixEthRxFrameQMCallback(ixEthAccDataInfo.higherPriorityQueue[qId], + callbackId); + } + } + + /* + * increment priority stats + */ + RX_STATS_INC(portId,rxPriority[IX_ETHACC_NE_QOS(mbufPtr)]); + + /* + * increment callback count stats + */ + RX_STATS_INC(portId,rxFrameClientCallback); + + /* + * Call user level callback. + */ + ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn( + ixEthAccPortData[portId].ixEthAccRxData.rxCallbackTag, + mbufPtr, + destPortId); + } + } + } while (rxQReadStatus == IX_SUCCESS); +} + +/** + * @fn ixEthRxMultiBufferQMCallback + * + * @brief receive callback for Frame receive Q from NPE + * + * Frames are passed as an array to the user + * + * @param @ref IxQMgrCallback + * + * @return none + * + * @internal + * + * Design note : while processing the entry X, entry X+1 is preloaded + * into memory to reduce the number of stall cycles + * + */ +void ixEthRxMultiBufferQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId) +{ + IX_OSAL_MBUF *mbufPtr; + IX_OSAL_MBUF *nextMbufPtr; + UINT32 qEntry; + UINT32 nextQEntry; + UINT32 *qEntryPtr; + UINT32 portId; + UINT32 npeId; + UINT32 rxQReadStatus; + /* + * Design note : entries are read in a static buffer, This buffer contains + * an extra zeroed entry so the loop will + * always terminate on a null entry, whatever the result of Burst read is. + */ + static UINT32 rxQEntry[IX_ETH_ACC_MAX_RX_FRAME_CONSUME_PER_CALLBACK + 1]; + static IX_OSAL_MBUF *rxMbufPortArray[IX_ETH_ACC_NUMBER_OF_PORTS][IX_ETH_ACC_MAX_RX_FRAME_CONSUME_PER_CALLBACK + 1]; + IX_OSAL_MBUF **rxMbufPtr[IX_ETH_ACC_NUMBER_OF_PORTS]; + + for (portId = 0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++) + { + rxMbufPtr[portId] = rxMbufPortArray[portId]; + } + + /* + * Indication of the number of times the callback is used. + */ + IX_ETH_ACC_STATS_INC(ixEthAccDataStats.rxCallbackCounter); + + do + { + /* + * Indication of the number of times the queue is drained + */ + IX_ETH_ACC_STATS_INC(ixEthAccDataStats.rxCallbackBurstRead); + + /* ensure the last entry of the array contains a zeroed value */ + qEntryPtr = rxQEntry; + qEntryPtr[IX_ETH_ACC_MAX_RX_FRAME_CONSUME_PER_CALLBACK] = 0; + + rxQReadStatus = ixQMgrQBurstRead(qId, + IX_ETH_ACC_MAX_RX_FRAME_CONSUME_PER_CALLBACK, + qEntryPtr); + +#ifndef NDEBUG + if ((rxQReadStatus != IX_QMGR_Q_UNDERFLOW) + && (rxQReadStatus != IX_SUCCESS)) + { + ixEthAccDataStats.unexpectedError++; + /*major error*/ + IX_ETH_ACC_FATAL_LOG( + "ixEthRxFrameMultiBufferQMCallback:Error: %u\n", + (UINT32)rxQReadStatus, 0, 0, 0, 0, 0); + return; + } +#endif + + /* convert and preload the next entry + * (the conversion function takes care about null pointers which + * are used to mark the end of the loop) + */ + nextQEntry = *qEntryPtr; + nextMbufPtr = ixEthAccEntryFromQConvert(nextQEntry, + IX_ETHNPE_QM_Q_RXENET_ADDR_MASK); + + while(nextQEntry != 0) + { + /* get the next entry */ + qEntry = nextQEntry; + mbufPtr = nextMbufPtr; + +#ifndef NDEBUG + if (mbufPtr == NULL) + { + ixEthAccDataStats.unexpectedError++; + IX_ETH_ACC_FATAL_LOG( + "ixEthRxFrameMultiBufferQMCallback:Error: Null Mbuf Ptr\n", + 0, 0, 0, 0, 0, 0); + return; + } +#endif + + /* convert the next entry + * (the conversion function takes care about null pointers which + * are used to mark the end of the loop) + */ + nextQEntry = *(++qEntryPtr); + nextMbufPtr = ixEthAccEntryFromQConvert(nextQEntry, + IX_ETHNPE_QM_Q_RXENET_ADDR_MASK); + + /* + * Get Port and Npe ID from message. + */ + npeId = ((IX_ETHNPE_QM_Q_RXENET_NPEID_MASK & + qEntry) >> + IX_ETHNPE_QM_Q_FIELD_NPEID_R); + portId = IX_ETH_ACC_NPE_TO_PORT_ID(npeId); + + /* skip the remaining of the loop if the frame is + * to be filtered out + */ + if (ixEthRxFrameProcess(portId, mbufPtr)) + { + /* store a mbuf pointer in an array */ + *rxMbufPtr[portId]++ = mbufPtr; + + /* + * increment priority stats + */ + RX_STATS_INC(portId,rxPriority[IX_ETHACC_NE_QOS(mbufPtr)]); + } + + /* test for QoS enabled in ethAcc */ + if (ixEthAccDataInfo.schDiscipline == FIFO_PRIORITY) + { + /* check if there is a higher priority queue + * which may require processing and then process it. + */ + if (ixEthAccDataInfo.higherPriorityQueue[qId] < IX_QMGR_MAX_NUM_QUEUES) + { + ixEthRxMultiBufferQMCallback(ixEthAccDataInfo.higherPriorityQueue[qId], + callbackId); + } + } + } + + /* check if any of the the arrays contains any entry */ + for (portId = 0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++) + { + if (rxMbufPtr[portId] != rxMbufPortArray[portId]) + { + /* add a last NULL pointer at the end of the + * array of mbuf pointers + */ + *rxMbufPtr[portId] = NULL; + + /* + * increment callback count stats + */ + RX_STATS_INC(portId,rxFrameClientCallback); + + /* + * Call user level callback with an array of + * buffers (NULL terminated) + */ + ixEthAccPortData[portId].ixEthAccRxData. + rxMultiBufferCallbackFn( + ixEthAccPortData[portId].ixEthAccRxData. + rxMultiBufferCallbackTag, + rxMbufPortArray[portId]); + + /* reset the buffer pointer to the beginning of + * the array + */ + rxMbufPtr[portId] = rxMbufPortArray[portId]; + } + } + + } while (rxQReadStatus == IX_SUCCESS); +} + + +/** + * @brief rxFree low event handler + * + */ +void ixEthRxFreeQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId) +{ + IxEthAccPortId portId = (IxEthAccPortId) callbackId; + int lockVal; + UINT32 maxQWritesToPerform = IX_ETH_ACC_MAX_RX_FREE_BUFFERS_LOAD; + IX_STATUS qStatus = IX_SUCCESS; + + /* + * We have reached a low threshold on one of the Rx Free Qs + */ + + /*note that due to the fact that we are working off an Empty threshold, this callback + need only write a single entry to the Rx Free queue in order to re-arm the notification + */ + + RX_STATS_INC(portId,rxFreeLowCallback); + + /* + * Get buffers from approprite S/W Rx freeBufferList Q. + */ + +#ifndef NDEBUG + if (!IX_ETH_ACC_IS_PORT_VALID(portId)) + { + ixEthAccDataStats.unexpectedError++; + IX_ETH_ACC_FATAL_LOG( + "ixEthRxFreeQMCallback:Error: Invalid Port 0x%08X\n", + portId, 0, 0, 0, 0, 0); + return; + } +#endif + IX_ETH_ACC_DATA_PLANE_LOCK(lockVal); + if (IX_ETH_ACC_DATAPLANE_IS_Q_EMPTY(ixEthAccPortData[portId]. + ixEthAccRxData.freeBufferList)) + { + /* + * Turn off Q callback notification for Q in Question. + */ + qStatus = ixQMgrNotificationDisable( + IX_ETH_ACC_PORT_TO_RX_FREE_Q_ID(portId)); + + + IX_ETH_ACC_DATA_PLANE_UNLOCK(lockVal); + + if (qStatus != IX_SUCCESS) + { + RX_INC(portId,rxUnexpectedError); + IX_ETH_ACC_FATAL_LOG( + "ixEthRxFreeQMCallback:Error: unexpected QM status 0x%08X\n", + qStatus, 0, 0, 0, 0, 0); + return; + } + } + else + { + IX_ETH_ACC_DATA_PLANE_UNLOCK(lockVal); + /* + * Load the H/W Q with buffers from the s/w Q. + */ + + do + { + /* + * Consume Q entries. - Note Q contains Physical addresss, + * and have already been flushed to memory, + * And endianess converted if required. + */ + if (ixEthAccRxFreeFromSwQ(portId) != IX_SUCCESS) + { + /* + * No more entries in s/w Q. + * Turn off Q callback indication + */ + + IX_ETH_ACC_DATA_PLANE_LOCK(lockVal); + if (IX_ETH_ACC_DATAPLANE_IS_Q_EMPTY(ixEthAccPortData[portId]. + ixEthAccRxData.freeBufferList)) + { + qStatus = ixQMgrNotificationDisable( + IX_ETH_ACC_PORT_TO_RX_FREE_Q_ID(portId)); + } + IX_ETH_ACC_DATA_PLANE_UNLOCK(lockVal); + break; + } + } + while (--maxQWritesToPerform); + } +} +/** + * @fn Tx queue low event handler + * + */ +void +ixEthTxFrameQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId) +{ + IxEthAccPortId portId = (IxEthAccPortId) callbackId; + int lockVal; + UINT32 maxQWritesToPerform = IX_ETH_ACC_MAX_TX_FRAME_TX_CONSUME_PER_CALLBACK; + IX_STATUS qStatus = IX_SUCCESS; + IxEthAccTxPriority highestPriority; + + + /* + * We have reached a low threshold on the Tx Q, and are being asked to + * supply a buffer for transmission from our S/W TX queues + */ + TX_STATS_INC(portId,txLowThreshCallback); + + /* + * Get buffers from approprite Q. + */ + +#ifndef NDEBUG + if (!IX_ETH_ACC_IS_PORT_VALID(portId)) + { + ixEthAccDataStats.unexpectedError++; + IX_ETH_ACC_FATAL_LOG( + "ixEthTxFrameQMCallback:Error: Invalid Port 0x%08X\n", + portId, 0, 0, 0, 0, 0); + return; + } +#endif + + do + { + /* + * Consume Q entries. - Note Q contains Physical addresss, + * and have already been flushed to memory, + * and endianess already sone if required. + */ + + IX_ETH_ACC_DATA_PLANE_LOCK(lockVal); + + if(ixEthAccTxSwQHighestPriorityGet(portId, &highestPriority) == + IX_ETH_ACC_FAIL) + { + /* + * No more entries in s/w Q. + * Turn off Q callback indication + */ + qStatus = ixQMgrNotificationDisable( + IX_ETH_ACC_PORT_TO_TX_Q_ID(portId)); + + IX_ETH_ACC_DATA_PLANE_UNLOCK(lockVal); + + if (qStatus != IX_SUCCESS) + { + ixEthAccDataStats.unexpectedError++; + IX_ETH_ACC_FATAL_LOG( + "ixEthTxFrameQMCallback:Error: unexpected QM status 0x%08X\n", + qStatus, 0, 0, 0, 0, 0); + } + + return; + } + else + { + IX_ETH_ACC_DATA_PLANE_UNLOCK(lockVal); + if (ixEthAccTxFromSwQ(portId,highestPriority)!=IX_SUCCESS) + { + /* nothing left in the sw queue or the hw queues are + * full. There is no point to continue to drain the + * sw queues + */ + return; + } + } + } + while (--maxQWritesToPerform); +} + +/** + * @brief TxDone event handler + * + * Design note : while processing the entry X, entry X+1 is preloaded + * into memory to reduce the number of stall cycles + * + */ + +void +ixEthTxFrameDoneQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId) +{ + IX_OSAL_MBUF *mbufPtr; + UINT32 qEntry; + UINT32 *qEntryPtr; + UINT32 txDoneQReadStatus; + UINT32 portId; + UINT32 npeId; + + /* + * Design note : entries are read in a static buffer, This buffer contains + * an extra entyry (which is zeroed by the compiler), so the loop will + * always terminate on a null entry, whatever the result of Burst read is. + */ + static UINT32 txDoneQEntry[IX_ETH_ACC_MAX_TX_FRAME_DONE_CONSUME_PER_CALLBACK + 1]; + + /* + * Indication that Tx frames have been transmitted from the NPE. + */ + + IX_ETH_ACC_STATS_INC(ixEthAccDataStats.txDoneCallbackCounter); + + do{ + qEntryPtr = txDoneQEntry; + txDoneQReadStatus = ixQMgrQBurstRead(IX_ETH_ACC_TX_FRAME_DONE_ETH_Q, + IX_ETH_ACC_MAX_TX_FRAME_DONE_CONSUME_PER_CALLBACK, + qEntryPtr); + +#ifndef NDEBUG + if (txDoneQReadStatus != IX_QMGR_Q_UNDERFLOW + && (txDoneQReadStatus != IX_SUCCESS)) + { + /*major error*/ + ixEthAccDataStats.unexpectedError++; + IX_ETH_ACC_FATAL_LOG( + "ixEthTxFrameDoneQMCallback:Error: %u\n", + (UINT32)txDoneQReadStatus, 0, 0, 0, 0, 0); + return; + } +#endif + + qEntry = *qEntryPtr; + + while(qEntry != 0) + { + mbufPtr = ixEthAccEntryFromQConvert(qEntry, + IX_ETHNPE_QM_Q_TXENET_ADDR_MASK); + +#ifndef NDEBUG + if (mbufPtr == NULL) + { + ixEthAccDataStats.unexpectedError++; + IX_ETH_ACC_FATAL_LOG( + "ixEthTxFrameDoneQMCallback:Error: Null Mbuf Ptr\n", + 0, 0, 0, 0, 0, 0); + return; + } +#endif + + /* endianness conversions and stats updates */ + ixEthAccMbufFromTxQ(mbufPtr); + + /* + * Get NPE id from message, then convert to portId. + */ + npeId = ((IX_ETHNPE_QM_Q_TXENETDONE_NPEID_MASK & + qEntry) >> + IX_ETHNPE_QM_Q_FIELD_NPEID_R); + portId = IX_ETH_ACC_NPE_TO_PORT_ID(npeId); + +#ifndef NDEBUG + /* Prudent to at least check the port is within range */ + if (portId >= IX_ETH_ACC_NUMBER_OF_PORTS) + { + ixEthAccDataStats.unexpectedError++; + IX_ETH_ACC_FATAL_LOG( + "ixEthTxFrameDoneQMCallback: Illegal port: %u\n", + (UINT32)portId, 0, 0, 0, 0, 0); + return; + } +#endif + + TX_STATS_INC(portId,txDoneClientCallback); + + /* + * Call user level callback. + */ + ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn( + ixEthAccPortData[portId].ixEthAccTxData.txCallbackTag, + mbufPtr); + + /* move to next queue entry */ + qEntry = *(++qEntryPtr); + + } + } while( txDoneQReadStatus == IX_SUCCESS ); +} + +IX_ETH_ACC_PUBLIC +void ixEthAccDataPlaneShow(void) +{ + UINT32 numTx0Entries; + UINT32 numTx1Entries; + UINT32 numTxDoneEntries; + UINT32 numRxEntries; + UINT32 numRxFree0Entries; + UINT32 numRxFree1Entries; + UINT32 portId; +#ifdef __ixp46X + UINT32 numTx2Entries; + UINT32 numRxFree2Entries; +#endif +#ifndef NDEBUG + UINT32 priority; + UINT32 numBuffersInRx=0; + UINT32 numBuffersInTx=0; + UINT32 numBuffersInSwQ=0; + UINT32 totalBuffers=0; + UINT32 rxFreeCallbackCounter = 0; + UINT32 txCallbackCounter = 0; +#endif + UINT32 key; + + /* snapshot of stats */ + IxEthAccTxDataStats tx[IX_ETH_ACC_NUMBER_OF_PORTS]; + IxEthAccRxDataStats rx[IX_ETH_ACC_NUMBER_OF_PORTS]; + IxEthAccDataPlaneStats stats; + + if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) + { + return; + } + + /* get a reliable snapshot */ + key = ixOsalIrqLock(); + + numTx0Entries = 0; + ixQMgrQNumEntriesGet(IX_ETH_ACC_TX_FRAME_ENET0_Q, &numTx0Entries); + numTx1Entries = 0; + ixQMgrQNumEntriesGet(IX_ETH_ACC_TX_FRAME_ENET1_Q, &numTx1Entries); + numTxDoneEntries = 0; + ixQMgrQNumEntriesGet( IX_ETH_ACC_TX_FRAME_DONE_ETH_Q, &numTxDoneEntries); + numRxEntries = 0; + ixEthAccQMgrRxQEntryGet(&numRxEntries); + numRxFree0Entries = 0; + ixQMgrQNumEntriesGet(IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q, &numRxFree0Entries); + numRxFree1Entries = 0; + ixQMgrQNumEntriesGet(IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q, &numRxFree1Entries); + +#ifdef __ixp46X + numTx2Entries = 0; + ixQMgrQNumEntriesGet(IX_ETH_ACC_TX_FRAME_ENET2_Q, &numTx2Entries); + numRxFree2Entries = 0; + ixQMgrQNumEntriesGet(IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q, &numRxFree2Entries); +#endif + + for(portId=IX_ETH_PORT_1; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++) + { + memcpy(&tx[portId], + &ixEthAccPortData[portId].ixEthAccTxData.stats, + sizeof(tx[portId])); + memcpy(&rx[portId], + &ixEthAccPortData[portId].ixEthAccRxData.stats, + sizeof(rx[portId])); + } + memcpy(&stats, &ixEthAccDataStats, sizeof(stats)); + + ixOsalIrqUnlock(key); + +#ifdef NDEBUG + printf("Detailed statistics collection not supported in this load\n"); +#endif + + /* print snapshot */ + for(portId=0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; 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 ((IX_ETH_PORT_1 == portId) && + (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH0) == + IX_FEATURE_CTRL_COMPONENT_DISABLED)) + { + continue ; + } + if ((IX_ETH_PORT_2 == portId) && + (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH1) == + IX_FEATURE_CTRL_COMPONENT_DISABLED)) + { + continue ; + } + if ((IX_ETH_PORT_3 == portId) && + (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEA_ETH) == + IX_FEATURE_CTRL_COMPONENT_DISABLED)) + { + continue ; + } + } + + printf("PORT %u --------------------------------\n", + portId); +#ifndef NDEBUG + printf("Tx Done Frames : %u\n", + tx[portId].txDoneClientCallback + + tx[portId].txDoneSwQDuringDisable + + tx[portId].txDoneDuringDisable); + printf("Tx Frames : %u\n", + tx[portId].txQOK + tx[portId].txQDelayed); + printf("Tx H/W Q Added OK : %u\n", + tx[portId].txQOK); + printf("Tx H/W Q Delayed : %u\n", + tx[portId].txQDelayed); + printf("Tx From S/W Q Added OK : %u\n", + tx[portId].txFromSwQOK); + printf("Tx From S/W Q Delayed : %u\n", + tx[portId].txFromSwQDelayed); + printf("Tx Overflow : %u\n", + tx[portId].txOverflow); + printf("Tx Mutual Lock : %u\n", + tx[portId].txLock); + printf("Tx Late Ntf Enabled : %u\n", + tx[portId].txLateNotificationEnabled); + printf("Tx Low Thresh CB : %u\n", + tx[portId].txLowThreshCallback); + printf("Tx Done from H/W Q (Disable) : %u\n", + tx[portId].txDoneDuringDisable); + printf("Tx Done from S/W Q (Disable) : %u\n", + tx[portId].txDoneSwQDuringDisable); + for (priority = IX_ETH_ACC_TX_PRIORITY_0; + priority <= IX_ETH_ACC_TX_PRIORITY_7; + priority++) + { + if (tx[portId].txPriority[priority]) + { + printf("Tx Priority %u : %u\n", + priority, + tx[portId].txPriority[priority]); + } + } +#endif + printf("Tx unexpected errors : %u (should be 0)\n", + tx[portId].txUnexpectedError); + +#ifndef NDEBUG + printf("Rx Frames : %u\n", + rx[portId].rxFrameClientCallback + + rx[portId].rxSwQDuringDisable+ + rx[portId].rxDuringDisable); + printf("Rx Free Replenish : %u\n", + rx[portId].rxFreeRepOK + rx[portId].rxFreeRepDelayed); + printf("Rx Free H/W Q Added OK : %u\n", + rx[portId].rxFreeRepOK); + printf("Rx Free H/W Q Delayed : %u\n", + rx[portId].rxFreeRepDelayed); + printf("Rx Free From S/W Q Added OK : %u\n", + rx[portId].rxFreeRepFromSwQOK); + printf("Rx Free From S/W Q Delayed : %u\n", + rx[portId].rxFreeRepFromSwQDelayed); + printf("Rx Free Overflow : %u\n", + rx[portId].rxFreeOverflow); + printf("Rx Free Mutual Lock : %u\n", + rx[portId].rxFreeLock); + printf("Rx Free Late Ntf Enabled : %u\n", + rx[portId].rxFreeLateNotificationEnabled); + printf("Rx Free Low CB : %u\n", + rx[portId].rxFreeLowCallback); + printf("Rx From H/W Q (Disable) : %u\n", + rx[portId].rxDuringDisable); + printf("Rx From S/W Q (Disable) : %u\n", + rx[portId].rxSwQDuringDisable); + printf("Rx unlearned Mac Address : %u\n", + rx[portId].rxUnlearnedMacAddress); + printf("Rx Filtered (Rx => RxFree) : %u\n", + rx[portId].rxFiltered); + + for (priority = IX_ETH_ACC_TX_PRIORITY_0; + priority <= IX_ETH_ACC_TX_PRIORITY_7; + priority++) + { + if (rx[portId].rxPriority[priority]) + { + printf("Rx Priority %u : %u\n", + priority, + rx[portId].rxPriority[priority]); + } + } +#endif + printf("Rx unexpected errors : %u (should be 0)\n", + rx[portId].rxUnexpectedError); + +#ifndef NDEBUG + numBuffersInTx = tx[portId].txQOK + + tx[portId].txQDelayed - + tx[portId].txDoneClientCallback - + tx[portId].txDoneSwQDuringDisable - + tx[portId].txDoneDuringDisable; + + printf("# Tx Buffers currently for transmission : %u\n", + numBuffersInTx); + + numBuffersInRx = rx[portId].rxFreeRepOK + + rx[portId].rxFreeRepDelayed - + rx[portId].rxFrameClientCallback - + rx[portId].rxSwQDuringDisable - + rx[portId].rxDuringDisable; + + printf("# Rx Buffers currently for reception : %u\n", + numBuffersInRx); + + totalBuffers += numBuffersInRx + numBuffersInTx; +#endif + } + + printf("---------------------------------------\n"); + +#ifndef NDEBUG + printf("\n"); + printf("Mbufs :\n"); + printf("Tx Unchained mbufs : %u\n", + stats.unchainedTxMBufs); + printf("Tx Chained bufs : %u\n", + stats.chainedTxMBufs); + printf("TxDone Unchained mbufs : %u\n", + stats.unchainedTxDoneMBufs); + printf("TxDone Chained bufs : %u\n", + stats.chainedTxDoneMBufs); + printf("RxFree Unchained mbufs : %u\n", + stats.unchainedRxFreeMBufs); + printf("RxFree Chained bufs : %u\n", + stats.chainedRxFreeMBufs); + printf("Rx Unchained mbufs : %u\n", + stats.unchainedRxMBufs); + printf("Rx Chained bufs : %u\n", + stats.chainedRxMBufs); + + printf("\n"); + printf("Software queue usage :\n"); + printf("Buffers added to S/W Q : %u\n", + stats.addToSwQ); + printf("Buffers removed from S/W Q : %u\n", + stats.removeFromSwQ); + + printf("\n"); + printf("Hardware queues callbacks :\n"); + + for(portId=0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++) + { + rxFreeCallbackCounter += rx[portId].rxFreeLowCallback; + txCallbackCounter += tx[portId].txLowThreshCallback; + } + printf("Tx Done QM Callback invoked : %u\n", + stats.txDoneCallbackCounter); + printf("Tx QM Callback invoked : %u\n", + txCallbackCounter); + printf("Rx QM Callback invoked : %u\n", + stats.rxCallbackCounter); + printf("Rx QM Callback burst read : %u\n", + stats.rxCallbackBurstRead); + printf("Rx Free QM Callback invoked : %u\n", + rxFreeCallbackCounter); +#endif + printf("Unexpected errors in CB : %u (should be 0)\n", + stats.unexpectedError); + printf("\n"); + + printf("Hardware queues levels :\n"); + printf("Transmit Port 1 Q : %u \n",numTx0Entries); + printf("Transmit Port 2 Q : %u \n",numTx1Entries); +#ifdef __ixp46X + printf("Transmit Port 3 Q : %u \n",numTx2Entries); +#endif + printf("Transmit Done Q : %u \n",numTxDoneEntries); + printf("Receive Q : %u \n",numRxEntries); + printf("Receive Free Port 1 Q : %u \n",numRxFree0Entries); + printf("Receive Free Port 2 Q : %u \n",numRxFree1Entries); +#ifdef __ixp46X + printf("Receive Free Port 3 Q : %u \n",numRxFree2Entries); +#endif + +#ifndef NDEBUG + printf("\n"); + printf("# Total Buffers accounted for : %u\n", + totalBuffers); + + numBuffersInSwQ = ixEthAccDataStats.addToSwQ - + ixEthAccDataStats.removeFromSwQ; + + printf(" Buffers in S/W Qs : %u\n", + numBuffersInSwQ); + printf(" Buffers in H/W Qs or NPEs : %u\n", + totalBuffers - numBuffersInSwQ); +#endif + + printf("Rx QoS Discipline : %s\n", + (ixEthAccDataInfo.schDiscipline == + FIFO_PRIORITY ) ? "Enabled" : "Disabled"); + + for(portId=0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++) + { + printf("Tx QoS Discipline port %u : %s\n", + portId, + (ixEthAccPortData[portId].ixEthAccTxData.schDiscipline == + FIFO_PRIORITY ) ? "Enabled" : "Disabled"); + } + printf("\n"); +} + + + + + diff --git a/cpu/ixp/npe/IxEthAccMac.c b/cpu/ixp/npe/IxEthAccMac.c new file mode 100644 index 0000000..d57e716 --- /dev/null +++ b/cpu/ixp/npe/IxEthAccMac.c @@ -0,0 +1,2641 @@ +/** + * @file IxEthAccMac.c + * + * @author Intel Corporation + * @date + * + * @brief MAC 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 "IxNpeMh.h" +#ifdef CONFIG_IXP425_COMPONENT_ETHDB +#include "IxEthDB.h" +#endif +#include "IxEthDBPortDefs.h" +#include "IxEthNpe.h" +#include "IxEthAcc.h" +#include "IxEthAccDataPlane_p.h" +#include "IxEthAcc_p.h" +#include "IxEthAccMac_p.h" + +/* Maximum number of retries during ixEthAccPortDisable, which + * is approximately 10 seconds +*/ +#define IX_ETH_ACC_MAX_RETRY 500 + +/* Maximum number of retries during ixEthAccPortDisable when expecting + * timeout + */ +#define IX_ETH_ACC_MAX_RETRY_TIMEOUT 5 + +#define IX_ETH_ACC_VALIDATE_PORT_ID(portId) \ + do \ + { \ + if(!IX_ETH_ACC_IS_PORT_VALID(portId)) \ + { \ + return IX_ETH_ACC_INVALID_PORT; \ + } \ + } while(0) + +PUBLIC IxEthAccMacState ixEthAccMacState[IX_ETH_ACC_NUMBER_OF_PORTS]; + +PRIVATE UINT32 ixEthAccMacBase[IX_ETH_ACC_NUMBER_OF_PORTS]; + +/*Forward function declarations*/ +PRIVATE void +ixEthAccPortDisableRx (IxEthAccPortId portId, + IX_OSAL_MBUF * mBufPtr, + BOOL useMultiBufferCallback); + +PRIVATE void +ixEthAccPortDisableRxAndReplenish (IxEthAccPortId portId, + IX_OSAL_MBUF * mBufPtr, + BOOL useMultiBufferCallback); + +PRIVATE void +ixEthAccPortDisableTxDone (UINT32 cbTag, + IX_OSAL_MBUF *mbuf); + +PRIVATE void +ixEthAccPortDisableTxDoneAndSubmit (UINT32 cbTag, + IX_OSAL_MBUF *mbuf); + +PRIVATE void +ixEthAccPortDisableRxCallback (UINT32 cbTag, + IX_OSAL_MBUF * mBufPtr, + UINT32 learnedPortId); + +PRIVATE void +ixEthAccPortDisableMultiBufferRxCallback (UINT32 cbTag, + IX_OSAL_MBUF **mBufPtr); + +PRIVATE IxEthAccStatus +ixEthAccPortDisableTryTransmit(UINT32 portId); + +PRIVATE IxEthAccStatus +ixEthAccPortDisableTryReplenish(UINT32 portId); + +PRIVATE IxEthAccStatus +ixEthAccPortMulticastMacAddressGet (IxEthAccPortId portId, + IxEthAccMacAddr *macAddr); + +PRIVATE IxEthAccStatus +ixEthAccPortMulticastMacFilterGet (IxEthAccPortId portId, + IxEthAccMacAddr *macAddr); + +PRIVATE void +ixEthAccMacNpeStatsMessageCallback (IxNpeMhNpeId npeId, + IxNpeMhMessage msg); + +PRIVATE void +ixEthAccMacNpeStatsResetMessageCallback (IxNpeMhNpeId npeId, + IxNpeMhMessage msg); + +PRIVATE void +ixEthAccNpeLoopbackMessageCallback (IxNpeMhNpeId npeId, + IxNpeMhMessage msg); + +PRIVATE void +ixEthAccMulticastAddressSet(IxEthAccPortId portId); + +PRIVATE BOOL +ixEthAccMacEqual(IxEthAccMacAddr *macAddr1, + IxEthAccMacAddr *macAddr2); + +PRIVATE void +ixEthAccMacPrint(IxEthAccMacAddr *m); + +PRIVATE void +ixEthAccMacStateUpdate(IxEthAccPortId portId); + +IxEthAccStatus +ixEthAccMacMemInit(void) +{ + ixEthAccMacBase[IX_ETH_PORT_1] = + (UINT32) IX_OSAL_MEM_MAP(IX_ETH_ACC_MAC_0_BASE, + IX_OSAL_IXP400_ETHA_MAP_SIZE); + ixEthAccMacBase[IX_ETH_PORT_2] = + (UINT32) IX_OSAL_MEM_MAP(IX_ETH_ACC_MAC_1_BASE, + IX_OSAL_IXP400_ETHB_MAP_SIZE); +#ifdef __ixp46X + ixEthAccMacBase[IX_ETH_PORT_3] = + (UINT32) IX_OSAL_MEM_MAP(IX_ETH_ACC_MAC_2_BASE, + IX_OSAL_IXP400_ETH_NPEA_MAP_SIZE); + if (ixEthAccMacBase[IX_ETH_PORT_3] == 0) + { + ixOsalLog(IX_OSAL_LOG_LVL_FATAL, + IX_OSAL_LOG_DEV_STDOUT, + "EthAcc: Could not map MAC I/O memory\n", + 0, 0, 0, 0, 0 ,0); + + return IX_ETH_ACC_FAIL; + } +#endif + + if (ixEthAccMacBase[IX_ETH_PORT_1] == 0 + || ixEthAccMacBase[IX_ETH_PORT_2] == 0) + { + ixOsalLog(IX_OSAL_LOG_LVL_FATAL, + IX_OSAL_LOG_DEV_STDOUT, + "EthAcc: Could not map MAC I/O memory\n", + 0, 0, 0, 0, 0 ,0); + + return IX_ETH_ACC_FAIL; + } + + return IX_ETH_ACC_SUCCESS; +} + +void +ixEthAccMacUnload(void) +{ + IX_OSAL_MEM_UNMAP(ixEthAccMacBase[IX_ETH_PORT_1]); + IX_OSAL_MEM_UNMAP(ixEthAccMacBase[IX_ETH_PORT_2]); +#ifdef __ixp46X + IX_OSAL_MEM_UNMAP(ixEthAccMacBase[IX_ETH_PORT_3]); + ixEthAccMacBase[IX_ETH_PORT_3] = 0; +#endif + ixEthAccMacBase[IX_ETH_PORT_2] = 0; + ixEthAccMacBase[IX_ETH_PORT_1] = 0; +} + +IxEthAccStatus +ixEthAccPortEnablePriv(IxEthAccPortId portId) +{ + IX_ETH_ACC_VALIDATE_PORT_ID(portId); + + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot enable port.\n",(INT32)portId,0,0,0,0,0); + return IX_ETH_ACC_SUCCESS ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + printf("EthAcc: (Mac) cannot enable port %d, port not initialized\n", portId); + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + if (ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn == NULL) + { + /* TxDone callback not registered */ + printf("EthAcc: (Mac) cannot enable port %d, TxDone callback not registered\n", portId); + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + if ((ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn == NULL) + && (ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackFn == NULL)) + { + /* Receive callback not registered */ + printf("EthAcc: (Mac) cannot enable port %d, Rx callback not registered\n", portId); + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + if(!ixEthAccMacState[portId].initDone) + { + printf("EthAcc: (Mac) cannot enable port %d, MAC address not set\n", portId); + return (IX_ETH_ACC_MAC_UNINITIALIZED); + } + + /* if the state is being set to what it is already at, do nothing*/ + if (ixEthAccMacState[portId].enabled) + { + return IX_ETH_ACC_SUCCESS; + } + +#ifdef CONFIG_IXP425_COMPONENT_ETHDB + /* enable ethernet database for this port */ + if (ixEthDBPortEnable(portId) != IX_ETH_DB_SUCCESS) + { + printf("EthAcc: (Mac) cannot enable port %d, EthDB failure\n", portId); + return IX_ETH_ACC_FAIL; + } +#endif + + /* set the MAC core registers */ + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_TX_CNTRL2, + IX_ETH_ACC_TX_CNTRL2_RETRIES_MASK); + + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_RANDOM_SEED, + IX_ETH_ACC_RANDOM_SEED_DEFAULT); + + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_THRESH_P_EMPTY, + IX_ETH_ACC_MAC_THRESH_P_EMPTY_DEFAULT); + + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_THRESH_P_FULL, + IX_ETH_ACC_MAC_THRESH_P_FULL_DEFAULT); + + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_TX_DEFER, + IX_ETH_ACC_MAC_TX_DEFER_DEFAULT); + + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_TX_TWO_DEFER_1, + IX_ETH_ACC_MAC_TX_TWO_DEFER_1_DEFAULT); + + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_TX_TWO_DEFER_2, + IX_ETH_ACC_MAC_TX_TWO_DEFER_2_DEFAULT); + + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_SLOT_TIME, + IX_ETH_ACC_MAC_SLOT_TIME_DEFAULT); + + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_INT_CLK_THRESH, + IX_ETH_ACC_MAC_INT_CLK_THRESH_DEFAULT); + + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_BUF_SIZE_TX, + IX_ETH_ACC_MAC_BUF_SIZE_TX_DEFAULT); + + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_TX_CNTRL1, + IX_ETH_ACC_TX_CNTRL1_DEFAULT); + + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_RX_CNTRL1, + IX_ETH_ACC_RX_CNTRL1_DEFAULT); + + /* set the global state */ + ixEthAccMacState[portId].portDisableState = ACTIVE; + ixEthAccMacState[portId].enabled = TRUE; + + /* rewrite the setup (including mac filtering) depending + * on current options + */ + ixEthAccMacStateUpdate(portId); + + return IX_ETH_ACC_SUCCESS; +} + +/* + * PortDisable local variables. They contain the intermediate steps + * while the port is being disabled and the buffers being drained out + * of the NPE. + */ +typedef void (*IxEthAccPortDisableRx)(IxEthAccPortId portId, + IX_OSAL_MBUF * mBufPtr, + BOOL useMultiBufferCallback); +static IxEthAccPortRxCallback +ixEthAccPortDisableFn[IX_ETH_ACC_NUMBER_OF_PORTS]; +static IxEthAccPortMultiBufferRxCallback +ixEthAccPortDisableMultiBufferFn[IX_ETH_ACC_NUMBER_OF_PORTS]; +static IxEthAccPortDisableRx +ixEthAccPortDisableRxTable[IX_ETH_ACC_NUMBER_OF_PORTS]; +static UINT32 +ixEthAccPortDisableCbTag[IX_ETH_ACC_NUMBER_OF_PORTS]; +static UINT32 +ixEthAccPortDisableMultiBufferCbTag[IX_ETH_ACC_NUMBER_OF_PORTS]; + +static IxEthAccPortTxDoneCallback +ixEthAccPortDisableTxDoneFn[IX_ETH_ACC_NUMBER_OF_PORTS]; +static UINT32 +ixEthAccPortDisableTxDoneCbTag[IX_ETH_ACC_NUMBER_OF_PORTS]; + +static UINT32 +ixEthAccPortDisableUserBufferCount[IX_ETH_ACC_NUMBER_OF_PORTS]; + +/* + * PortDisable private callbacks functions. They handle the user + * traffic, and the special buffers (one for tx, one for rx) used + * in portDisable. + */ +PRIVATE void +ixEthAccPortDisableTxDone(UINT32 cbTag, + IX_OSAL_MBUF *mbuf) +{ + IxEthAccPortId portId = (IxEthAccPortId)cbTag; + volatile IxEthAccPortDisableState *txState = &ixEthAccMacState[portId].txState; + + /* check for the special mbuf used in portDisable */ + if (mbuf == ixEthAccMacState[portId].portDisableTxMbufPtr) + { + *txState = TRANSMIT_DONE; + } + else + { + /* increment the count of user traffic during portDisable */ + ixEthAccPortDisableUserBufferCount[portId]++; + + /* call client TxDone function */ + ixEthAccPortDisableTxDoneFn[portId](ixEthAccPortDisableTxDoneCbTag[portId], mbuf); + } +} + +PRIVATE IxEthAccStatus +ixEthAccPortDisableTryTransmit(UINT32 portId) +{ + int key; + IxEthAccStatus status = IX_ETH_ACC_SUCCESS; + volatile IxEthAccPortDisableState *txState = &ixEthAccMacState[portId].txState; + /* transmit the special buffer again if it is transmitted + * and update the txState + * This section is protected because the portDisable context + * run an identical code, so the system keeps transmitting at the + * maximum rate. + */ + key = ixOsalIrqLock(); + if (*txState == TRANSMIT_DONE) + { + IX_OSAL_MBUF *mbufTxPtr = ixEthAccMacState[portId].portDisableTxMbufPtr; + *txState = TRANSMIT; + status = ixEthAccPortTxFrameSubmit(portId, + mbufTxPtr, + IX_ETH_ACC_TX_DEFAULT_PRIORITY); + } + ixOsalIrqUnlock(key); + + return status; +} + +PRIVATE void +ixEthAccPortDisableTxDoneAndSubmit(UINT32 cbTag, + IX_OSAL_MBUF *mbuf) +{ + IxEthAccPortId portId = (IxEthAccPortId)cbTag; + + /* call the callback which forwards the traffic to the client */ + ixEthAccPortDisableTxDone(cbTag, mbuf); + + /* try to transmit the buffer used in portDisable + * if seen in TxDone + */ + ixEthAccPortDisableTryTransmit(portId); +} + +PRIVATE void +ixEthAccPortDisableRx (IxEthAccPortId portId, + IX_OSAL_MBUF * mBufPtr, + BOOL useMultiBufferCallback) +{ + volatile IxEthAccPortDisableState *rxState = &ixEthAccMacState[portId].rxState; + IX_OSAL_MBUF *mNextPtr; + + while (mBufPtr) + { + mNextPtr = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mBufPtr); + IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mBufPtr) = NULL; + + /* check for the special mbuf used in portDisable */ + if (mBufPtr == ixEthAccMacState[portId].portDisableRxMbufPtr) + { + *rxState = RECEIVE; + } + else + { + /* increment the count of user traffic during portDisable */ + ixEthAccPortDisableUserBufferCount[portId]++; + + /* reset the received payload length during portDisable */ + IX_OSAL_MBUF_MLEN(mBufPtr) = 0; + IX_OSAL_MBUF_PKT_LEN(mBufPtr) = 0; + + if (useMultiBufferCallback) + { + /* call the user callback with one unchained + * buffer, without payload. A small array is built + * to be used as a parameter (the user callback expects + * to receive an array ended by a NULL pointer. + */ + IX_OSAL_MBUF *mBufPtrArray[2]; + + mBufPtrArray[0] = mBufPtr; + mBufPtrArray[1] = NULL; + ixEthAccPortDisableMultiBufferFn[portId]( + ixEthAccPortDisableMultiBufferCbTag[portId], + mBufPtrArray); + } + else + { + /* call the user callback with a unchained + * buffer, without payload and the destination port is + * unknown. + */ + ixEthAccPortDisableFn[portId]( + ixEthAccPortDisableCbTag[portId], + mBufPtr, + IX_ETH_DB_UNKNOWN_PORT /* port not found */); + } + } + + mBufPtr = mNextPtr; + } +} + +PRIVATE IxEthAccStatus +ixEthAccPortDisableTryReplenish(UINT32 portId) +{ + int key; + IxEthAccStatus status = IX_ETH_ACC_SUCCESS; + volatile IxEthAccPortDisableState *rxState = &ixEthAccMacState[portId].rxState; + /* replenish with the special buffer again if it is received + * and update the rxState + * This section is protected because the portDisable context + * run an identical code, so the system keeps replenishing at the + * maximum rate. + */ + key = ixOsalIrqLock(); + if (*rxState == RECEIVE) + { + IX_OSAL_MBUF *mbufRxPtr = ixEthAccMacState[portId].portDisableRxMbufPtr; + *rxState = REPLENISH; + IX_OSAL_MBUF_MLEN(mbufRxPtr) = IX_ETHACC_RX_MBUF_MIN_SIZE; + status = ixEthAccPortRxFreeReplenish(portId, mbufRxPtr); + } + ixOsalIrqUnlock(key); + + return status; +} + +PRIVATE void +ixEthAccPortDisableRxAndReplenish (IxEthAccPortId portId, + IX_OSAL_MBUF * mBufPtr, + BOOL useMultiBufferCallback) +{ + /* call the callback which forwards the traffic to the client */ + ixEthAccPortDisableRx(portId, mBufPtr, useMultiBufferCallback); + + /* try to replenish with the buffer used in portDisable + * if seen in Rx + */ + ixEthAccPortDisableTryReplenish(portId); +} + +PRIVATE void +ixEthAccPortDisableRxCallback (UINT32 cbTag, + IX_OSAL_MBUF * mBufPtr, + UINT32 learnedPortId) +{ + IxEthAccPortId portId = (IxEthAccPortId)cbTag; + + /* call the portDisable receive callback */ + (ixEthAccPortDisableRxTable[portId])(portId, mBufPtr, FALSE); +} + +PRIVATE void +ixEthAccPortDisableMultiBufferRxCallback (UINT32 cbTag, + IX_OSAL_MBUF **mBufPtr) +{ + IxEthAccPortId portId = (IxEthAccPortId)cbTag; + + while (*mBufPtr) + { + /* call the portDisable receive callback with one buffer at a time */ + (ixEthAccPortDisableRxTable[portId])(portId, *mBufPtr++, TRUE); + } +} + +IxEthAccStatus +ixEthAccPortDisablePriv(IxEthAccPortId portId) +{ + IxEthAccStatus status = IX_ETH_ACC_SUCCESS; + int key; + int retry, retryTimeout; + volatile IxEthAccPortDisableState *state = &ixEthAccMacState[portId].portDisableState; + volatile IxEthAccPortDisableState *rxState = &ixEthAccMacState[portId].rxState; + volatile IxEthAccPortDisableState *txState = &ixEthAccMacState[portId].txState; + + IX_ETH_ACC_VALIDATE_PORT_ID(portId); + + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot disable port.\n",(INT32)portId,0,0,0,0,0); + return IX_ETH_ACC_SUCCESS ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + /* if the state is being set to what it is already at, do nothing */ + if (!ixEthAccMacState[portId].enabled) + { + return IX_ETH_ACC_SUCCESS; + } + + *state = DISABLED; + + /* disable MAC receive first */ + ixEthAccPortRxDisablePriv(portId); + +#ifdef CONFIG_IXP425_COMPONENT_ETHDB + /* disable ethernet database for this port - It is done now to avoid + * issuing ELT maintenance after requesting 'port disable' in an NPE + */ + if (ixEthDBPortDisable(portId) != IX_ETH_DB_SUCCESS) + { + status = IX_ETH_ACC_FAIL; + IX_ETH_ACC_FATAL_LOG("ixEthAccPortDisable: failed to disable EthDB for this port\n", 0, 0, 0, 0, 0, 0); + } +#endif + + /* enter the critical section */ + key = ixOsalIrqLock(); + + /* swap the Rx and TxDone callbacks */ + ixEthAccPortDisableFn[portId] = ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn; + ixEthAccPortDisableMultiBufferFn[portId] = ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackFn; + ixEthAccPortDisableCbTag[portId] = ixEthAccPortData[portId].ixEthAccRxData.rxCallbackTag; + ixEthAccPortDisableMultiBufferCbTag[portId] = ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackTag; + ixEthAccPortDisableTxDoneFn[portId] = ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn; + ixEthAccPortDisableTxDoneCbTag[portId] = ixEthAccPortData[portId].ixEthAccTxData.txCallbackTag; + ixEthAccPortDisableRxTable[portId] = ixEthAccPortDisableRx; + + /* register temporary callbacks */ + ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn = ixEthAccPortDisableRxCallback; + ixEthAccPortData[portId].ixEthAccRxData.rxCallbackTag = portId; + + ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackFn = ixEthAccPortDisableMultiBufferRxCallback; + ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackTag = portId; + + ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn = ixEthAccPortDisableTxDone; + ixEthAccPortData[portId].ixEthAccTxData.txCallbackTag = portId; + + /* initialise the Rx state and Tx states */ + *txState = TRANSMIT_DONE; + *rxState = RECEIVE; + + /* exit the critical section */ + ixOsalIrqUnlock(key); + + /* enable a NPE loopback */ + if (ixEthAccNpeLoopbackEnablePriv(portId) != IX_ETH_ACC_SUCCESS) + { + status = IX_ETH_ACC_FAIL; + } + + if (status == IX_ETH_ACC_SUCCESS) + { + retry = 0; + + /* Step 1 : Drain Tx traffic and TxDone queues : + * + * Transmit and replenish at least once with the + * special buffers until both of them are seen + * in the callback hook + * + * (the receive callback keeps replenishing, so once we see + * the special Tx buffer, we can be sure that Tx drain is complete) + */ + ixEthAccPortDisableRxTable[portId] + = ixEthAccPortDisableRxAndReplenish; + ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn + = ixEthAccPortDisableTxDone; + + do + { + /* keep replenishing */ + status = ixEthAccPortDisableTryReplenish(portId); + if (status == IX_ETH_ACC_SUCCESS) + { + /* keep transmitting */ + status = ixEthAccPortDisableTryTransmit(portId); + } + if (status == IX_ETH_ACC_SUCCESS) + { + /* wait for some traffic being processed */ + ixOsalSleep(IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS); + } + } + while ((status == IX_ETH_ACC_SUCCESS) + && (retry++ < IX_ETH_ACC_MAX_RETRY) + && (*txState == TRANSMIT)); + + /* Step 2 : Drain Rx traffic, RxFree and Rx queues : + * + * Transmit and replenish at least once with the + * special buffers until both of them are seen + * in the callback hook + * (the transmit callback keeps transmitting, and when we see + * the special Rx buffer, we can be sure that rxFree drain + * is complete) + * + * The nested loop helps to retry if the user was keeping + * replenishing or transmitting during portDisable. + * + * The 2 nested loops ensure more retries if user traffic is + * seen during portDisable : the user should not replenish + * or transmit while portDisable is running. However, because of + * the queueing possibilities in ethAcc dataplane, it is possible + * that a lot of traffic is left in the queues (e.g. when + * transmitting over a low speed link) and therefore, more + * retries are allowed to help flushing the buffers out. + */ + ixEthAccPortDisableRxTable[portId] + = ixEthAccPortDisableRx; + ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn + = ixEthAccPortDisableTxDoneAndSubmit; + + do + { + do + { + ixEthAccPortDisableUserBufferCount[portId] = 0; + + /* keep replenishing */ + status = ixEthAccPortDisableTryReplenish(portId); + if (status == IX_ETH_ACC_SUCCESS) + { + /* keep transmitting */ + status = ixEthAccPortDisableTryTransmit(portId); + } + if (status == IX_ETH_ACC_SUCCESS) + { + /* wait for some traffic being processed */ + ixOsalSleep(IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS); + } + } + while ((status == IX_ETH_ACC_SUCCESS) + && (retry++ < IX_ETH_ACC_MAX_RETRY) + && ((ixEthAccPortDisableUserBufferCount[portId] != 0) + || (*rxState == REPLENISH))); + + /* After the first iteration, change the receive callbacks, + * to process only 1 buffer at a time + */ + ixEthAccPortDisableRxTable[portId] + = ixEthAccPortDisableRx; + ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn + = ixEthAccPortDisableTxDone; + + /* repeat the whole process while user traffic is seen in TxDone + * + * The conditions to stop the loop are + * - Xscale has both Rx and Tx special buffers + * (txState = transmit, rxState = receive) + * - any error in txSubmit or rxReplenish + * - no user traffic seen + * - an excessive amount of retries + */ + } + while ((status == IX_ETH_ACC_SUCCESS) + && (retry < IX_ETH_ACC_MAX_RETRY) + && (*txState == TRANSMIT)); + + /* check the loop exit conditions. The NPE should not hold + * the special buffers. + */ + if ((*rxState == REPLENISH) || (*txState == TRANSMIT)) + { + status = IX_ETH_ACC_FAIL; + } + + if (status == IX_ETH_ACC_SUCCESS) + { + /* Step 3 : Replenish without transmitting until a timeout + * occurs, in order to drain the internal NPE fifos + * + * we can expect a few frames srill held + * in the NPE. + * + * The 2 nested loops take care about the NPE dropping traffic + * (including loopback traffic) when the Rx queue is full. + * + * The timeout value is very conservative + * since the loopback used keeps replenishhing. + * + */ + do + { + ixEthAccPortDisableRxTable[portId] = ixEthAccPortDisableRxAndReplenish; + ixEthAccPortDisableUserBufferCount[portId] = 0; + retryTimeout = 0; + do + { + /* keep replenishing */ + status = ixEthAccPortDisableTryReplenish(portId); + if (status == IX_ETH_ACC_SUCCESS) + { + /* wait for some traffic being processed */ + ixOsalSleep(IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS); + } + } + while ((status == IX_ETH_ACC_SUCCESS) + && (retryTimeout++ < IX_ETH_ACC_MAX_RETRY_TIMEOUT)); + + /* Step 4 : Transmit once. Stop replenish + * + * After the Rx timeout, we are sure that the NPE does not + * hold any frame in its internal NPE fifos. + * + * At this point, the NPE still holds the last rxFree buffer. + * By transmitting a single frame, this should unblock the + * last rxFree buffer. This code just transmit once and + * wait for both frames seen in TxDone and in rxFree. + * + */ + ixEthAccPortDisableRxTable[portId] = ixEthAccPortDisableRx; + status = ixEthAccPortDisableTryTransmit(portId); + + /* the NPE should immediatelyt release + * the last Rx buffer and the last transmitted buffer + * unless the last Tx frame was dropped (rx queue full) + */ + if (status == IX_ETH_ACC_SUCCESS) + { + retryTimeout = 0; + do + { + ixOsalSleep(IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS); + } + while ((*rxState == REPLENISH) + && (retryTimeout++ < IX_ETH_ACC_MAX_RETRY_TIMEOUT)); + } + + /* the NPE may have dropped the traffic because of Rx + * queue being full. This code ensures that the last + * Tx and Rx frames are both received. + */ + } + while ((status == IX_ETH_ACC_SUCCESS) + && (retry++ < IX_ETH_ACC_MAX_RETRY) + && ((*txState == TRANSMIT) + || (*rxState == REPLENISH) + || (ixEthAccPortDisableUserBufferCount[portId] != 0))); + + /* Step 5 : check the final states : the NPE has + * no buffer left, nor in Tx , nor in Rx directions. + */ + if ((*rxState == REPLENISH) || (*txState == TRANSMIT)) + { + status = IX_ETH_ACC_FAIL; + } + } + + /* now all the buffers are drained, disable NPE loopback + * This is done regardless of the logic to drain the queues and + * the internal buffers held by the NPE. + */ + if (ixEthAccNpeLoopbackDisablePriv(portId) != IX_ETH_ACC_SUCCESS) + { + status = IX_ETH_ACC_FAIL; + } + } + + /* disable MAC Tx and Rx services */ + ixEthAccMacState[portId].enabled = FALSE; + ixEthAccMacStateUpdate(portId); + + /* restore the Rx and TxDone callbacks (within a critical section) */ + key = ixOsalIrqLock(); + + ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn = ixEthAccPortDisableFn[portId]; + ixEthAccPortData[portId].ixEthAccRxData.rxCallbackTag = ixEthAccPortDisableCbTag[portId]; + ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackFn = ixEthAccPortDisableMultiBufferFn[portId]; + ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackTag = ixEthAccPortDisableMultiBufferCbTag[portId]; + ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn = ixEthAccPortDisableTxDoneFn[portId]; + ixEthAccPortData[portId].ixEthAccTxData.txCallbackTag = ixEthAccPortDisableTxDoneCbTag[portId]; + + ixOsalIrqUnlock(key); + + /* the MAC core rx/tx disable may left the MAC hardware in an + * unpredictable state. A hw reset is executed before resetting + * all the MAC parameters to a known value. + */ + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_CORE_CNTRL, + IX_ETH_ACC_CORE_RESET); + + ixOsalSleep(IX_ETH_ACC_MAC_RESET_DELAY); + + /* rewrite all parameters to their current value */ + ixEthAccMacStateUpdate(portId); + + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_INT_CLK_THRESH, + IX_ETH_ACC_MAC_INT_CLK_THRESH_DEFAULT); + + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_CORE_CNTRL, + IX_ETH_ACC_CORE_MDC_EN); + + return status; +} + +IxEthAccStatus +ixEthAccPortEnabledQueryPriv(IxEthAccPortId portId, BOOL *enabled) +{ + IX_ETH_ACC_VALIDATE_PORT_ID(portId); + + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot enable port.\n",(INT32)portId,0,0,0,0,0); + + /* Since Eth NPE is not available, port must be disabled */ + *enabled = FALSE ; + return IX_ETH_ACC_SUCCESS ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + /* Since Eth NPE is not available, port must be disabled */ + *enabled = FALSE ; + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + *enabled = ixEthAccMacState[portId].enabled; + + return IX_ETH_ACC_SUCCESS; +} + +IxEthAccStatus +ixEthAccPortMacResetPriv(IxEthAccPortId portId) +{ + IX_ETH_ACC_VALIDATE_PORT_ID(portId); + + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot reset Ethernet coprocessor.\n",(INT32)portId,0,0,0,0,0); + return IX_ETH_ACC_SUCCESS ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_CORE_CNTRL, + IX_ETH_ACC_CORE_RESET); + + ixOsalSleep(IX_ETH_ACC_MAC_RESET_DELAY); + + /* rewrite all parameters to their current value */ + ixEthAccMacStateUpdate(portId); + + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_INT_CLK_THRESH, + IX_ETH_ACC_MAC_INT_CLK_THRESH_DEFAULT); + + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_CORE_CNTRL, + IX_ETH_ACC_CORE_MDC_EN); + + return IX_ETH_ACC_SUCCESS; +} + +IxEthAccStatus +ixEthAccPortLoopbackEnable(IxEthAccPortId portId) +{ + UINT32 regval; + + /* Turn off promiscuous mode */ + IX_ETH_ACC_VALIDATE_PORT_ID(portId); + + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot enable loopback.\n",(INT32)portId,0,0,0,0,0); + return IX_ETH_ACC_SUCCESS ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + /* read register */ + REG_READ(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_RX_CNTRL1, + regval); + + /* update register */ + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_RX_CNTRL1, + regval | IX_ETH_ACC_RX_CNTRL1_LOOP_EN); + + return IX_ETH_ACC_SUCCESS; +} + +PRIVATE void +ixEthAccNpeLoopbackMessageCallback (IxNpeMhNpeId npeId, + IxNpeMhMessage msg) +{ + IxEthAccPortId portId = IX_ETH_ACC_NPE_TO_PORT_ID(npeId); + +#ifndef NDEBUG + /* Prudent to at least check the port is within range */ + if (portId >= IX_ETH_ACC_NUMBER_OF_PORTS) + { + IX_ETH_ACC_FATAL_LOG("IXETHACC:ixEthAccPortDisableMessageCallback: Illegal port: %u\n", + (UINT32) portId, 0, 0, 0, 0, 0); + + return; + } +#endif + + /* unlock message reception mutex */ + ixOsalMutexUnlock(&ixEthAccMacState[portId].npeLoopbackMessageLock); +} + +IxEthAccStatus +ixEthAccNpeLoopbackEnablePriv(IxEthAccPortId portId) +{ + IX_STATUS npeMhStatus; + IxNpeMhMessage message; + IxEthAccStatus status = IX_ETH_ACC_SUCCESS; + + /* Turn off promiscuous mode */ + IX_ETH_ACC_VALIDATE_PORT_ID(portId); + + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot enable NPE loopback.\n",(INT32)portId,0,0,0,0,0); + return IX_ETH_ACC_SUCCESS ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + /* enable NPE loopback (lsb of the message contains the value 1) */ + message.data[0] = (IX_ETHNPE_SETLOOPBACK_MODE << IX_ETH_ACC_MAC_MSGID_SHL) + | 0x01; + message.data[1] = 0; + + npeMhStatus = ixNpeMhMessageWithResponseSend(IX_ETH_ACC_PORT_TO_NPE_ID(portId), + message, + IX_ETHNPE_SETLOOPBACK_MODE_ACK, + ixEthAccNpeLoopbackMessageCallback, + IX_NPEMH_SEND_RETRIES_DEFAULT); + + if (npeMhStatus != IX_SUCCESS) + { + status = IX_ETH_ACC_FAIL; + } + else + { + /* wait for NPE loopbackEnable response */ + if (ixOsalMutexLock(&ixEthAccMacState[portId]. npeLoopbackMessageLock, + IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS) + != IX_SUCCESS) + { + status = IX_ETH_ACC_FAIL; + } + } + + return status; +} + +IxEthAccStatus +ixEthAccPortTxEnablePriv(IxEthAccPortId portId) +{ + UINT32 regval; + + /* Turn off promiscuous mode */ + IX_ETH_ACC_VALIDATE_PORT_ID(portId); + + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot enable TX.\n",(INT32)portId,0,0,0,0,0); + return IX_ETH_ACC_SUCCESS ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + /* read register */ + REG_READ(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_TX_CNTRL1, + regval); + + /* update register */ + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_TX_CNTRL1, + regval | IX_ETH_ACC_TX_CNTRL1_TX_EN); + + return IX_ETH_ACC_SUCCESS; +} + +IxEthAccStatus +ixEthAccPortRxEnablePriv(IxEthAccPortId portId) +{ + UINT32 regval; + + /* Turn off promiscuous mode */ + IX_ETH_ACC_VALIDATE_PORT_ID(portId); + + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot enable RX.\n",(INT32)portId,0,0,0,0,0); + return IX_ETH_ACC_SUCCESS ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + /* read register */ + REG_READ(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_RX_CNTRL1, + regval); + + /* update register */ + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_RX_CNTRL1, + regval | IX_ETH_ACC_RX_CNTRL1_RX_EN); + + return IX_ETH_ACC_SUCCESS; +} + +IxEthAccStatus +ixEthAccPortLoopbackDisable(IxEthAccPortId portId) +{ + UINT32 regval; + + IX_ETH_ACC_VALIDATE_PORT_ID(portId); + + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot disable loopback.\n",(INT32)portId,0,0,0,0,0); + return IX_ETH_ACC_SUCCESS ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + /*disable MAC loopabck */ + REG_READ(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_RX_CNTRL1, + regval); + + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_RX_CNTRL1, + (regval & ~IX_ETH_ACC_RX_CNTRL1_LOOP_EN)); + + return IX_ETH_ACC_SUCCESS; +} + +IxEthAccStatus +ixEthAccNpeLoopbackDisablePriv(IxEthAccPortId portId) +{ + IX_STATUS npeMhStatus; + IxNpeMhMessage message; + IxEthAccStatus status = IX_ETH_ACC_SUCCESS; + + /* Turn off promiscuous mode */ + IX_ETH_ACC_VALIDATE_PORT_ID(portId); + + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot enable NPE loopback.\n",(INT32)portId,0,0,0,0,0); + return IX_ETH_ACC_SUCCESS ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + /* disable NPE loopback (lsb of the message contains the value 0) */ + message.data[0] = (IX_ETHNPE_SETLOOPBACK_MODE << IX_ETH_ACC_MAC_MSGID_SHL); + message.data[1] = 0; + + npeMhStatus = ixNpeMhMessageWithResponseSend(IX_ETH_ACC_PORT_TO_NPE_ID(portId), + message, + IX_ETHNPE_SETLOOPBACK_MODE_ACK, + ixEthAccNpeLoopbackMessageCallback, + IX_NPEMH_SEND_RETRIES_DEFAULT); + + if (npeMhStatus != IX_SUCCESS) + { + status = IX_ETH_ACC_FAIL; + } + else + { + /* wait for NPE loopbackEnable response */ + if (ixOsalMutexLock(&ixEthAccMacState[portId].npeLoopbackMessageLock, + IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS) + != IX_SUCCESS) + { + status = IX_ETH_ACC_FAIL; + } + } + + return status; +} + +IxEthAccStatus +ixEthAccPortTxDisablePriv(IxEthAccPortId portId) +{ + UINT32 regval; + + /* Turn off promiscuous mode */ + IX_ETH_ACC_VALIDATE_PORT_ID(portId); + + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot disable TX.\n", (INT32)portId,0,0,0,0,0); + return IX_ETH_ACC_SUCCESS ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + /* read register */ + REG_READ(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_TX_CNTRL1, + regval); + + /* update register */ + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_TX_CNTRL1, + (regval & ~IX_ETH_ACC_TX_CNTRL1_TX_EN)); + + return IX_ETH_ACC_SUCCESS; +} + +IxEthAccStatus +ixEthAccPortRxDisablePriv(IxEthAccPortId portId) +{ + UINT32 regval; + + /* Turn off promiscuous mode */ + IX_ETH_ACC_VALIDATE_PORT_ID(portId); + + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot disable RX.\n", (INT32)portId,0,0,0,0,0); + return IX_ETH_ACC_SUCCESS ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + /* read register */ + REG_READ(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_RX_CNTRL1, + regval); + + /* update register */ + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_RX_CNTRL1, + (regval & ~IX_ETH_ACC_RX_CNTRL1_RX_EN)); + + return IX_ETH_ACC_SUCCESS; +} + +IxEthAccStatus +ixEthAccPortPromiscuousModeClearPriv(IxEthAccPortId portId) +{ + UINT32 regval; + + /* Turn off promiscuous mode */ + IX_ETH_ACC_VALIDATE_PORT_ID(portId); + + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot clear promiscuous mode.\n",(INT32)portId,0,0,0,0,0); + return IX_ETH_ACC_SUCCESS ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + /*set bit 5 of Rx control 1 - enable address filtering*/ + REG_READ(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_RX_CNTRL1, + regval); + + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_RX_CNTRL1, + regval | IX_ETH_ACC_RX_CNTRL1_ADDR_FLTR_EN); + + ixEthAccMacState[portId].promiscuous = FALSE; + + ixEthAccMulticastAddressSet(portId); + + return IX_ETH_ACC_SUCCESS; +} + +IxEthAccStatus +ixEthAccPortPromiscuousModeSetPriv(IxEthAccPortId portId) +{ + UINT32 regval; + + IX_ETH_ACC_VALIDATE_PORT_ID(portId); + + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot set promiscuous mode.\n",(INT32)portId,0,0,0,0,0); + return IX_ETH_ACC_SUCCESS ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + /* + * Set bit 5 of Rx control 1 - We enable address filtering even in + * promiscuous mode because we want the MAC to set the appropriate + * bits in m_flags which doesn't happen if we turn off filtering. + */ + REG_READ(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_RX_CNTRL1, + regval); + + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_RX_CNTRL1, + regval | IX_ETH_ACC_RX_CNTRL1_ADDR_FLTR_EN); + + ixEthAccMacState[portId].promiscuous = TRUE; + + ixEthAccMulticastAddressSet(portId); + + return IX_ETH_ACC_SUCCESS; +} + +IxEthAccStatus +ixEthAccPortUnicastMacAddressSetPriv (IxEthAccPortId portId, + IxEthAccMacAddr *macAddr) +{ + UINT32 i; + + IX_ETH_ACC_VALIDATE_PORT_ID(portId); + + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot set Unicast Mac Address.\n",(INT32)portId,0,0,0,0,0); + return IX_ETH_ACC_SUCCESS ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + + if (macAddr == NULL) + { + return IX_ETH_ACC_FAIL; + } + + if ( macAddr->macAddress[0] & IX_ETH_ACC_ETH_MAC_BCAST_MCAST_BIT ) + { + /* This is a multicast/broadcast address cant set it ! */ + return IX_ETH_ACC_FAIL; + } + + if ( macAddr->macAddress[0] == 0 && + macAddr->macAddress[1] == 0 && + macAddr->macAddress[2] == 0 && + macAddr->macAddress[3] == 0 && + macAddr->macAddress[4] == 0 && + macAddr->macAddress[5] == 0 ) + { + /* This is an invalid mac address cant set it ! */ + return IX_ETH_ACC_FAIL; + } + +#ifdef CONFIG_IXP425_COMPONENT_ETHDB + /* update the MAC address in the ethernet database */ + if (ixEthDBPortAddressSet(portId, (IxEthDBMacAddr *) macAddr) != IX_ETH_DB_SUCCESS) + { + return IX_ETH_ACC_FAIL; + } +#endif + + /*Set the Unicast MAC to the specified value*/ + for(i=0;imacAddress[i]); + } + ixEthAccMacState[portId].initDone = TRUE; + + return IX_ETH_ACC_SUCCESS; +} + +IxEthAccStatus +ixEthAccPortUnicastMacAddressGetPriv (IxEthAccPortId portId, + IxEthAccMacAddr *macAddr) +{ + /*Return the current value of the Unicast MAC from h/w + for the specified port*/ + UINT32 i; + + IX_ETH_ACC_VALIDATE_PORT_ID(portId); + + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot get Unicast Mac Address.\n",(INT32)portId,0,0,0,0,0); + /* Since Eth Npe is unavailable, return invalid MAC Address = 00:00:00:00:00:00 */ + for(i=0;imacAddress[i] = 0; + } + return IX_ETH_ACC_SUCCESS ; + } + + if(!ixEthAccMacState[portId].initDone) + { + return (IX_ETH_ACC_MAC_UNINITIALIZED); + } + + if (macAddr == NULL) + { + return IX_ETH_ACC_FAIL; + } + + + for(i=0;imacAddress[i]); + } + return IX_ETH_ACC_SUCCESS; +} + +PRIVATE IxEthAccStatus +ixEthAccPortMulticastMacAddressGet (IxEthAccPortId portId, + IxEthAccMacAddr *macAddr) +{ + /*Return the current value of the Multicast MAC from h/w + for the specified port*/ + UINT32 i; + + for(i=0;imacAddress[i]); + } + + return IX_ETH_ACC_SUCCESS; +} + +PRIVATE IxEthAccStatus +ixEthAccPortMulticastMacFilterGet (IxEthAccPortId portId, + IxEthAccMacAddr *macAddr) +{ + /*Return the current value of the Multicast MAC from h/w + for the specified port*/ + UINT32 i; + + for(i=0;imacAddress[i]); + } + return IX_ETH_ACC_SUCCESS; +} + +IxEthAccStatus +ixEthAccPortMulticastAddressJoinPriv (IxEthAccPortId portId, + IxEthAccMacAddr *macAddr) +{ + UINT32 i; + IxEthAccMacAddr broadcastAddr = {{0xff,0xff,0xff,0xff,0xff,0xff}}; + + /*Check that the port parameter is valid*/ + IX_ETH_ACC_VALIDATE_PORT_ID(portId); + + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot join Multicast Mac Address.\n",(INT32)portId,0,0,0,0,0); + return IX_ETH_ACC_SUCCESS ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + /*Check that the mac address is valid*/ + if(macAddr == NULL) + { + return IX_ETH_ACC_FAIL; + } + + /* Check that this is a multicast address */ + if (!(macAddr->macAddress[0] & IX_ETH_ACC_ETH_MAC_BCAST_MCAST_BIT)) + { + return IX_ETH_ACC_FAIL; + } + + /* We don't add the Broadcast address */ + if(ixEthAccMacEqual(&broadcastAddr, macAddr)) + { + return IX_ETH_ACC_FAIL; + } + + for (i = 0; + i= IX_ETH_ACC_MAX_MULTICAST_ADDRESSES) + { + return IX_ETH_ACC_FAIL; + } + + /*First add the address to the multicast table for the + specified port*/ + i=ixEthAccMacState[portId].mcastAddrIndex; + + memcpy(&ixEthAccMacState[portId].mcastAddrsTable[i], + &macAddr->macAddress, + IX_IEEE803_MAC_ADDRESS_SIZE); + + /*Increment the index into the table, this must be done here + as MulticastAddressSet below needs to know about the latest + entry. + */ + ixEthAccMacState[portId].mcastAddrIndex++; + + /*Then calculate the new value to be written to the address and + address mask registers*/ + ixEthAccMulticastAddressSet(portId); + + return IX_ETH_ACC_SUCCESS; +} + + +IxEthAccStatus +ixEthAccPortMulticastAddressJoinAllPriv (IxEthAccPortId portId) +{ + IxEthAccMacAddr mcastMacAddr = {{0x1,0x0,0x0,0x0,0x0,0x0}}; + + /*Check that the port parameter is valid*/ + IX_ETH_ACC_VALIDATE_PORT_ID(portId); + + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot join all Multicast Address.\n",(INT32)portId,0,0,0,0,0); + return IX_ETH_ACC_SUCCESS ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + /* remove all entries from the database and + * insert a multicast entry + */ + memcpy(&ixEthAccMacState[portId].mcastAddrsTable[0], + &mcastMacAddr.macAddress, + IX_IEEE803_MAC_ADDRESS_SIZE); + + ixEthAccMacState[portId].mcastAddrIndex = 1; + ixEthAccMacState[portId].joinAll = TRUE; + + ixEthAccMulticastAddressSet(portId); + + return IX_ETH_ACC_SUCCESS; +} + +IxEthAccStatus +ixEthAccPortMulticastAddressLeavePriv (IxEthAccPortId portId, + IxEthAccMacAddr *macAddr) +{ + UINT32 i; + IxEthAccMacAddr mcastMacAddr = {{0x1,0x0,0x0,0x0,0x0,0x0}}; + + /*Check that the port parameter is valid*/ + IX_ETH_ACC_VALIDATE_PORT_ID(portId); + + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot leave Multicast Address.\n",(INT32)portId,0,0,0,0,0); + return IX_ETH_ACC_SUCCESS ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + /*Check that the mac address is valid*/ + if(macAddr == NULL) + { + return IX_ETH_ACC_FAIL; + } + /* Remove this mac address from the mask for the specified port + * we copy down all entries above the blanked entry, and + * decrement the index + */ + i=0; + + while(i= IX_ETH_ACC_NUMBER_OF_PORTS) + { + IX_ETH_ACC_FATAL_LOG( + "IXETHACC:ixEthAccMacNpeStatsMessageCallback: Illegal port: %u\n", + (UINT32)portId, 0, 0, 0, 0, 0); + return; + } +#endif + + /*Unblock Stats Get call*/ + ixOsalMutexUnlock(&ixEthAccMacState[portId].ackMIBStatsLock); + +} + +PRIVATE void +ixEthAccMibIIStatsEndianConvert (IxEthEthObjStats *retStats) +{ + /* endianness conversion */ + + /* Rx stats */ + retStats->dot3StatsAlignmentErrors = + IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsAlignmentErrors); + retStats->dot3StatsFCSErrors = + IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsFCSErrors); + retStats->dot3StatsInternalMacReceiveErrors = + IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsInternalMacReceiveErrors); + retStats->RxOverrunDiscards = + IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxOverrunDiscards); + retStats->RxLearnedEntryDiscards = + IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxLearnedEntryDiscards); + retStats->RxLargeFramesDiscards = + IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxLargeFramesDiscards); + retStats->RxSTPBlockedDiscards = + IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxSTPBlockedDiscards); + retStats->RxVLANTypeFilterDiscards = + IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxVLANTypeFilterDiscards); + retStats->RxVLANIdFilterDiscards = + IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxVLANIdFilterDiscards); + retStats->RxInvalidSourceDiscards = + IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxInvalidSourceDiscards); + retStats->RxBlackListDiscards = + IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxBlackListDiscards); + retStats->RxWhiteListDiscards = + IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxWhiteListDiscards); + retStats->RxUnderflowEntryDiscards = + IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxUnderflowEntryDiscards); + + /* Tx stats */ + retStats->dot3StatsSingleCollisionFrames = + IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsSingleCollisionFrames); + retStats->dot3StatsMultipleCollisionFrames = + IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsMultipleCollisionFrames); + retStats->dot3StatsDeferredTransmissions = + IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsDeferredTransmissions); + retStats->dot3StatsLateCollisions = + IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsLateCollisions); + retStats->dot3StatsExcessiveCollsions = + IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsExcessiveCollsions); + retStats->dot3StatsInternalMacTransmitErrors = + IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsInternalMacTransmitErrors); + retStats->dot3StatsCarrierSenseErrors = + IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsCarrierSenseErrors); + retStats->TxLargeFrameDiscards = + IX_OSAL_SWAP_BE_SHARED_LONG(retStats->TxLargeFrameDiscards); + retStats->TxVLANIdFilterDiscards = + IX_OSAL_SWAP_BE_SHARED_LONG(retStats->TxVLANIdFilterDiscards); +} + +IxEthAccStatus +ixEthAccMibIIStatsGet (IxEthAccPortId portId, + IxEthEthObjStats *retStats ) +{ + IxNpeMhMessage message; + + if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) + { + printf("EthAcc: ixEthAccMibIIStatsGet (Mac) EthAcc service is not initialized\n"); + return (IX_ETH_ACC_FAIL); + } + + IX_ETH_ACC_VALIDATE_PORT_ID(portId); + + if (retStats == NULL) + { + printf("EthAcc: ixEthAccMibIIStatsGet (Mac) NULL argument\n"); + return (IX_ETH_ACC_FAIL); + } + + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + printf("EthAcc: ixEthAccMibIIStatsGet (Mac) NPE for port %d is not available\n", portId); + + IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot get MIB II Stats.\n",(INT32)portId,0,0,0,0,0); + + /* Return all zero stats */ + IX_ETH_ACC_MEMSET(retStats, 0, sizeof(IxEthEthObjStats)); + + return IX_ETH_ACC_SUCCESS ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + printf("EthAcc: ixEthAccMibIIStatsGet (Mac) port %d is not initialized\n", portId); + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + IX_OSAL_CACHE_INVALIDATE(retStats, sizeof(IxEthEthObjStats)); + + message.data[0] = IX_ETHNPE_GETSTATS << IX_ETH_ACC_MAC_MSGID_SHL; + message.data[1] = (UINT32) IX_OSAL_MMU_VIRT_TO_PHYS(retStats); + + /* Permit only one task to request MIB statistics Get operation + at a time */ + ixOsalMutexLock(&ixEthAccMacState[portId].MIBStatsGetAccessLock, IX_OSAL_WAIT_FOREVER); + + if(ixNpeMhMessageWithResponseSend(IX_ETH_ACC_PORT_TO_NPE_ID(portId), + message, + IX_ETHNPE_GETSTATS, + ixEthAccMacNpeStatsMessageCallback, + IX_NPEMH_SEND_RETRIES_DEFAULT) + != IX_SUCCESS) + { + ixOsalMutexUnlock(&ixEthAccMacState[portId].MIBStatsGetAccessLock); + + printf("EthAcc: (Mac) StatsGet failed to send NPE message\n"); + + return IX_ETH_ACC_FAIL; + } + + /* Wait for callback invocation indicating response to + this request - we need this mutex in order to ensure + that the return from this function is synchronous */ + ixOsalMutexLock(&ixEthAccMacState[portId].ackMIBStatsLock, IX_ETH_ACC_MIB_STATS_DELAY_MSECS); + + /* Permit other tasks to perform MIB statistics Get operation */ + ixOsalMutexUnlock(&ixEthAccMacState[portId].MIBStatsGetAccessLock); + + ixEthAccMibIIStatsEndianConvert (retStats); + + return IX_ETH_ACC_SUCCESS; +} + + +PRIVATE void +ixEthAccMacNpeStatsResetMessageCallback (IxNpeMhNpeId npeId, + IxNpeMhMessage msg) +{ + IxEthAccPortId portId = IX_ETH_ACC_NPE_TO_PORT_ID(npeId); + +#ifndef NDEBUG + /* Prudent to at least check the port is within range */ + if (portId >= IX_ETH_ACC_NUMBER_OF_PORTS) + { + IX_ETH_ACC_FATAL_LOG( + "IXETHACC:ixEthAccMacNpeStatsResetMessageCallback: Illegal port: %u\n", + (UINT32)portId, 0, 0, 0, 0, 0); + return; + } +#endif + + /*Unblock Stats Get & reset call*/ + ixOsalMutexUnlock(&ixEthAccMacState[portId].ackMIBStatsResetLock); + +} + + + +IxEthAccStatus +ixEthAccMibIIStatsGetClear (IxEthAccPortId portId, + IxEthEthObjStats *retStats) +{ + IxNpeMhMessage message; + + if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) + { + printf("EthAcc: ixEthAccMibIIStatsGetClear (Mac) EthAcc service is not initialized\n"); + return (IX_ETH_ACC_FAIL); + } + + IX_ETH_ACC_VALIDATE_PORT_ID(portId); + + if (retStats == NULL) + { + printf("EthAcc: ixEthAccMibIIStatsGetClear (Mac) NULL argument\n"); + return (IX_ETH_ACC_FAIL); + } + + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + printf("EthAcc: ixEthAccMibIIStatsGetClear (Mac) NPE for port %d is not available\n", portId); + + IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot get and clear MIB II Stats.\n", (INT32)portId, 0, 0, 0, 0, 0); + + /* Return all zero stats */ + IX_ETH_ACC_MEMSET(retStats, 0, sizeof(IxEthEthObjStats)); + + return IX_ETH_ACC_SUCCESS ; + } + + if (!IX_ETH_IS_PORT_INITIALIZED(portId)) + { + printf("EthAcc: ixEthAccMibIIStatsGetClear (Mac) port %d is not initialized\n", portId); + return (IX_ETH_ACC_PORT_UNINITIALIZED); + } + + IX_OSAL_CACHE_INVALIDATE(retStats, sizeof(IxEthEthObjStats)); + + message.data[0] = IX_ETHNPE_RESETSTATS << IX_ETH_ACC_MAC_MSGID_SHL; + message.data[1] = (UINT32) IX_OSAL_MMU_VIRT_TO_PHYS(retStats); + + /* Permit only one task to request MIB statistics Get-Reset operation at a time */ + ixOsalMutexLock(&ixEthAccMacState[portId].MIBStatsGetResetAccessLock, IX_OSAL_WAIT_FOREVER); + + if(ixNpeMhMessageWithResponseSend(IX_ETH_ACC_PORT_TO_NPE_ID(portId), + message, + IX_ETHNPE_RESETSTATS, + ixEthAccMacNpeStatsResetMessageCallback, + IX_NPEMH_SEND_RETRIES_DEFAULT) + != IX_SUCCESS) + { + ixOsalMutexUnlock(&ixEthAccMacState[portId].MIBStatsGetResetAccessLock); + + printf("EthAcc: (Mac) ixEthAccMibIIStatsGetClear failed to send NPE message\n"); + + return IX_ETH_ACC_FAIL; + } + + /* Wait for callback invocation indicating response to this request */ + ixOsalMutexLock(&ixEthAccMacState[portId].ackMIBStatsResetLock, IX_ETH_ACC_MIB_STATS_DELAY_MSECS); + + /* permit other tasks to get and reset MIB stats*/ + ixOsalMutexUnlock(&ixEthAccMacState[portId].MIBStatsGetResetAccessLock); + + ixEthAccMibIIStatsEndianConvert(retStats); + + return IX_ETH_ACC_SUCCESS; +} + +IxEthAccStatus +ixEthAccMibIIStatsClear (IxEthAccPortId portId) +{ + static IxEthEthObjStats retStats; + IxEthAccStatus status; + + if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) + { + return (IX_ETH_ACC_FAIL); + } + + IX_ETH_ACC_VALIDATE_PORT_ID(portId); + + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot clear MIB II Stats.\n",(INT32)portId,0,0,0,0,0); + return IX_ETH_ACC_SUCCESS ; + } + + /* there is no reset operation without a corresponding Get */ + status = ixEthAccMibIIStatsGetClear(portId, &retStats); + + return status; +} + +/* Initialize the ethernet MAC settings */ +IxEthAccStatus +ixEthAccMacInit(IxEthAccPortId portId) +{ + IX_OSAL_MBUF_POOL* portDisablePool; + UINT8 *data; + + IX_ETH_ACC_VALIDATE_PORT_ID(portId); + + if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) + { + IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot initialize Mac.\n",(INT32)portId,0,0,0,0,0); + return IX_ETH_ACC_SUCCESS ; + } + + if(ixEthAccMacState[portId].macInitialised == FALSE) + { + ixEthAccMacState[portId].fullDuplex = TRUE; + ixEthAccMacState[portId].rxFCSAppend = TRUE; + ixEthAccMacState[portId].txFCSAppend = TRUE; + ixEthAccMacState[portId].txPADAppend = TRUE; + ixEthAccMacState[portId].enabled = FALSE; + ixEthAccMacState[portId].promiscuous = TRUE; + ixEthAccMacState[portId].joinAll = FALSE; + ixEthAccMacState[portId].initDone = FALSE; + ixEthAccMacState[portId].macInitialised = TRUE; + + /* initialize MIB stats mutexes */ + ixOsalMutexInit(&ixEthAccMacState[portId].ackMIBStatsLock); + ixOsalMutexLock(&ixEthAccMacState[portId].ackMIBStatsLock, IX_OSAL_WAIT_FOREVER); + + ixOsalMutexInit(&ixEthAccMacState[portId].ackMIBStatsResetLock); + ixOsalMutexLock(&ixEthAccMacState[portId].ackMIBStatsResetLock, IX_OSAL_WAIT_FOREVER); + + ixOsalMutexInit(&ixEthAccMacState[portId].MIBStatsGetAccessLock); + + ixOsalMutexInit(&ixEthAccMacState[portId].MIBStatsGetResetAccessLock); + + ixOsalMutexInit(&ixEthAccMacState[portId].npeLoopbackMessageLock); + + ixEthAccMacState[portId].portDisableRxMbufPtr = NULL; + ixEthAccMacState[portId].portDisableTxMbufPtr = NULL; + + portDisablePool = IX_OSAL_MBUF_POOL_INIT(2, + IX_ETHACC_RX_MBUF_MIN_SIZE, + "portDisable Pool"); + + IX_OSAL_ENSURE(portDisablePool != NULL, "Failed to initialize PortDisable pool"); + + ixEthAccMacState[portId].portDisableRxMbufPtr = IX_OSAL_MBUF_POOL_GET(portDisablePool); + ixEthAccMacState[portId].portDisableTxMbufPtr = IX_OSAL_MBUF_POOL_GET(portDisablePool); + + IX_OSAL_ENSURE(ixEthAccMacState[portId].portDisableRxMbufPtr != NULL, + "Pool allocation failed"); + IX_OSAL_ENSURE(ixEthAccMacState[portId].portDisableTxMbufPtr != NULL, + "Pool allocation failed"); + /* fill the payload of the Rx mbuf used in portDisable */ + IX_OSAL_MBUF_MLEN(ixEthAccMacState[portId].portDisableRxMbufPtr) = IX_ETHACC_RX_MBUF_MIN_SIZE; + + memset(IX_OSAL_MBUF_MDATA(ixEthAccMacState[portId].portDisableRxMbufPtr), + 0xAA, + IX_ETHACC_RX_MBUF_MIN_SIZE); + + /* fill the payload of the Tx mbuf used in portDisable (64 bytes) */ + IX_OSAL_MBUF_MLEN(ixEthAccMacState[portId].portDisableTxMbufPtr) = 64; + IX_OSAL_MBUF_PKT_LEN(ixEthAccMacState[portId].portDisableTxMbufPtr) = 64; + + data = (UINT8 *) IX_OSAL_MBUF_MDATA(ixEthAccMacState[portId].portDisableTxMbufPtr); + memset(data, 0xBB, 64); + data[0] = 0x00; /* unicast destination MAC address */ + data[6] = 0x00; /* unicast source MAC address */ + data[12] = 0x08; /* typelength : IP frame */ + data[13] = 0x00; /* typelength : IP frame */ + + IX_OSAL_CACHE_FLUSH(data, 64); + } + + IX_OSAL_ASSERT (ixEthAccMacBase[portId] != 0); + + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_CORE_CNTRL, + IX_ETH_ACC_CORE_RESET); + + ixOsalSleep(IX_ETH_ACC_MAC_RESET_DELAY); + + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_CORE_CNTRL, + IX_ETH_ACC_CORE_MDC_EN); + + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_INT_CLK_THRESH, + IX_ETH_ACC_MAC_INT_CLK_THRESH_DEFAULT); + + ixEthAccMacStateUpdate(portId); + + return IX_ETH_ACC_SUCCESS; +} + +/* PRIVATE Functions*/ + +PRIVATE void +ixEthAccMacStateUpdate(IxEthAccPortId portId) +{ + UINT32 regval; + + if ( ixEthAccMacState[portId].enabled == FALSE ) + { + /* Just disable both the transmitter and reciver in the MAC. */ + REG_READ(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_RX_CNTRL1, + regval); + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_RX_CNTRL1, + regval & ~IX_ETH_ACC_RX_CNTRL1_RX_EN); + + REG_READ(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_TX_CNTRL1, + regval); + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_TX_CNTRL1, + regval & ~IX_ETH_ACC_TX_CNTRL1_TX_EN); + } + + if(ixEthAccMacState[portId].fullDuplex) + { + ixEthAccPortDuplexModeSetPriv (portId, IX_ETH_ACC_FULL_DUPLEX); + } + else + { + ixEthAccPortDuplexModeSetPriv (portId, IX_ETH_ACC_HALF_DUPLEX); + } + + if(ixEthAccMacState[portId].rxFCSAppend) + { + ixEthAccPortRxFrameAppendFCSEnablePriv (portId); + } + else + { + ixEthAccPortRxFrameAppendFCSDisablePriv (portId); + } + + if(ixEthAccMacState[portId].txFCSAppend) + { + ixEthAccPortTxFrameAppendFCSEnablePriv (portId); + } + else + { + ixEthAccPortTxFrameAppendFCSDisablePriv (portId); + } + + if(ixEthAccMacState[portId].txPADAppend) + { + ixEthAccPortTxFrameAppendPaddingEnablePriv (portId); + } + else + { + ixEthAccPortTxFrameAppendPaddingDisablePriv (portId); + } + + if(ixEthAccMacState[portId].promiscuous) + { + ixEthAccPortPromiscuousModeSetPriv(portId); + } + else + { + ixEthAccPortPromiscuousModeClearPriv(portId); + } + + if ( ixEthAccMacState[portId].enabled == TRUE ) + { + /* Enable both the transmitter and reciver in the MAC. */ + REG_READ(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_RX_CNTRL1, + regval); + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_RX_CNTRL1, + regval | IX_ETH_ACC_RX_CNTRL1_RX_EN); + + REG_READ(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_TX_CNTRL1, + regval); + REG_WRITE(ixEthAccMacBase[portId], + IX_ETH_ACC_MAC_TX_CNTRL1, + regval | IX_ETH_ACC_TX_CNTRL1_TX_EN); + } +} + + +PRIVATE BOOL +ixEthAccMacEqual(IxEthAccMacAddr *macAddr1, + IxEthAccMacAddr *macAddr2) +{ + UINT32 i; + for(i=0;imacAddress[i] != macAddr2->macAddress[i]) + { + return FALSE; + } + } + return TRUE; +} + +PRIVATE void +ixEthAccMacPrint(IxEthAccMacAddr *m) +{ + printf("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", + m->macAddress[0], m->macAddress[1], + m->macAddress[2], m->macAddress[3], + m->macAddress[4], m->macAddress[5]); +} + +/* Set the multicast address and address mask registers + * + * A bit in the address mask register must be set if + * all multicast addresses always have that bit set, or if + * all multicast addresses always have that bit cleared. + * + * A bit in the address register must be set if all multicast + * addresses have that bit set, otherwise, it should be cleared + */ + +PRIVATE void +ixEthAccMulticastAddressSet(IxEthAccPortId portId) +{ + UINT32 i; + UINT32 j; + IxEthAccMacAddr addressMask; + IxEthAccMacAddr address; + IxEthAccMacAddr alwaysClearBits; + IxEthAccMacAddr alwaysSetBits; + + /* calculate alwaysClearBits and alwaysSetBits: + * alwaysClearBits is calculated by ORing all + * multicast addresses, those bits that are always + * clear are clear in the result + * + * alwaysSetBits is calculated by ANDing all + * multicast addresses, those bits that are always set + * are set in the result + */ + + if (ixEthAccMacState[portId].promiscuous == TRUE) + { + /* Promiscuous Mode is set, and filtering + * allow all packets, and enable the mcast and + * bcast detection. + */ + memset(&addressMask.macAddress, + 0, + IX_IEEE803_MAC_ADDRESS_SIZE); + memset(&address.macAddress, + 0, + IX_IEEE803_MAC_ADDRESS_SIZE); + } + else + { + if(ixEthAccMacState[portId].joinAll == TRUE) + { + /* Join all is set. The mask and address are + * the multicast settings. + */ + IxEthAccMacAddr macAddr = {{0x1,0x0,0x0,0x0,0x0,0x0}}; + + memcpy(addressMask.macAddress, + macAddr.macAddress, + IX_IEEE803_MAC_ADDRESS_SIZE); + memcpy(address.macAddress, + macAddr.macAddress, + IX_IEEE803_MAC_ADDRESS_SIZE); + } + else if(ixEthAccMacState[portId].mcastAddrIndex == 0) + { + /* No entry in the filtering database, + * Promiscuous Mode is cleared, Broadcast filtering + * is configured. + */ + memset(addressMask.macAddress, + IX_ETH_ACC_MAC_ALL_BITS_SET, + IX_IEEE803_MAC_ADDRESS_SIZE); + memset(address.macAddress, + IX_ETH_ACC_MAC_ALL_BITS_SET, + IX_IEEE803_MAC_ADDRESS_SIZE); + } + else + { + /* build a mask and an address which mix all entreis + * from the list of multicast addresses + */ + memset(alwaysClearBits.macAddress, + 0, + IX_IEEE803_MAC_ADDRESS_SIZE); + memset(alwaysSetBits.macAddress, + IX_ETH_ACC_MAC_ALL_BITS_SET, + IX_IEEE803_MAC_ADDRESS_SIZE); + + for(i=0;i> 8) & 0xff); + + REG_WRITE(miiBaseAddressVirt, + IX_ETH_ACC_MAC_MDIO_CMD_3, + (mdioCommand >> 16) & 0xff); + + REG_WRITE(miiBaseAddressVirt, + IX_ETH_ACC_MAC_MDIO_CMD_4, + (mdioCommand >> 24) & 0xff); +} + +PRIVATE void +ixEthAccMdioCmdRead(UINT32 *data) +{ + UINT32 regval; + + REG_READ(miiBaseAddressVirt, + IX_ETH_ACC_MAC_MDIO_CMD_1, + regval); + + *data = regval & 0xff; + + REG_READ(miiBaseAddressVirt, + IX_ETH_ACC_MAC_MDIO_CMD_2, + regval); + + *data |= (regval & 0xff) << 8; + + REG_READ(miiBaseAddressVirt, + IX_ETH_ACC_MAC_MDIO_CMD_3, + regval); + + *data |= (regval & 0xff) << 16; + + REG_READ(miiBaseAddressVirt, + IX_ETH_ACC_MAC_MDIO_CMD_4, + regval); + + *data |= (regval & 0xff) << 24; + +} + +PRIVATE void +ixEthAccMdioStatusRead(UINT32 *data) +{ + UINT32 regval; + + REG_READ(miiBaseAddressVirt, + IX_ETH_ACC_MAC_MDIO_STS_1, + regval); + + *data = regval & 0xff; + + REG_READ(miiBaseAddressVirt, + IX_ETH_ACC_MAC_MDIO_STS_2, + regval); + + *data |= (regval & 0xff) << 8; + + REG_READ(miiBaseAddressVirt, + IX_ETH_ACC_MAC_MDIO_STS_3, + regval); + + *data |= (regval & 0xff) << 16; + + REG_READ(miiBaseAddressVirt, + IX_ETH_ACC_MAC_MDIO_STS_4, + regval); + + *data |= (regval & 0xff) << 24; + +} + + +/******************************************************************** + * ixEthAccMiiInit + */ +IxEthAccStatus +ixEthAccMiiInit() +{ + if(ixOsalMutexInit(&miiAccessLock)!= IX_SUCCESS) + { + return IX_ETH_ACC_FAIL; + } + + miiBaseAddressVirt = (UINT32) IX_OSAL_MEM_MAP(IX_ETH_ACC_MAC_0_BASE, IX_OSAL_IXP400_ETHA_MAP_SIZE); + + if (miiBaseAddressVirt == 0) + { + ixOsalLog(IX_OSAL_LOG_LVL_FATAL, + IX_OSAL_LOG_DEV_STDOUT, + "EthAcc: Could not map MII I/O mapped memory\n", + 0, 0, 0, 0, 0, 0); + + return IX_ETH_ACC_FAIL; + } + + return IX_ETH_ACC_SUCCESS; +} + +void +ixEthAccMiiUnload(void) +{ + IX_OSAL_MEM_UNMAP(miiBaseAddressVirt); + + miiBaseAddressVirt = 0; +} + +PUBLIC IxEthAccStatus +ixEthAccMiiAccessTimeoutSet(UINT32 timeout, UINT32 retryCount) +{ + if (retryCount < 1) return IX_ETH_ACC_FAIL; + + ixEthAccMiiRetryCount = retryCount; + ixEthAccMiiAccessTimeout = timeout; + + return IX_ETH_ACC_SUCCESS; +} + +/********************************************************************* + * ixEthAccMiiReadRtn - read a 16 bit value from a PHY + */ +IxEthAccStatus +ixEthAccMiiReadRtn (UINT8 phyAddr, + UINT8 phyReg, + UINT16 *value) +{ + UINT32 mdioCommand; + UINT32 regval; + UINT32 miiTimeout; + + if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) + { + return (IX_ETH_ACC_FAIL); + } + + if ((phyAddr >= IXP425_ETH_ACC_MII_MAX_ADDR) + || (phyReg >= IXP425_ETH_ACC_MII_MAX_REG)) + { + return (IX_ETH_ACC_FAIL); + } + + if (value == NULL) + { + return (IX_ETH_ACC_FAIL); + } + + ixOsalMutexLock(&miiAccessLock, IX_OSAL_WAIT_FOREVER); + mdioCommand = phyReg << IX_ETH_ACC_MII_REG_SHL + | phyAddr << IX_ETH_ACC_MII_ADDR_SHL; + mdioCommand |= IX_ETH_ACC_MII_GO; + + ixEthAccMdioCmdWrite(mdioCommand); + + miiTimeout = ixEthAccMiiRetryCount; + + while(miiTimeout) + { + + ixEthAccMdioCmdRead(®val); + + if((regval & IX_ETH_ACC_MII_GO) == 0x0) + { + break; + } + /* Sleep for a while */ + ixOsalSleep(ixEthAccMiiAccessTimeout); + miiTimeout--; + } + + + + if(miiTimeout == 0) + { + ixOsalMutexUnlock(&miiAccessLock); + *value = 0xffff; + return IX_ETH_ACC_FAIL; + } + + + ixEthAccMdioStatusRead(®val); + if(regval & IX_ETH_ACC_MII_READ_FAIL) + { + ixOsalMutexUnlock(&miiAccessLock); + *value = 0xffff; + return IX_ETH_ACC_FAIL; + } + + *value = regval & 0xffff; + ixOsalMutexUnlock(&miiAccessLock); + return IX_ETH_ACC_SUCCESS; + +} + + +/********************************************************************* + * ixEthAccMiiWriteRtn - write a 16 bit value to a PHY + */ +IxEthAccStatus +ixEthAccMiiWriteRtn (UINT8 phyAddr, + UINT8 phyReg, + UINT16 value) +{ + UINT32 mdioCommand; + UINT32 regval; + UINT16 readVal; + UINT32 miiTimeout; + + if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) + { + return (IX_ETH_ACC_FAIL); + } + + if ((phyAddr >= IXP425_ETH_ACC_MII_MAX_ADDR) + || (phyReg >= IXP425_ETH_ACC_MII_MAX_REG)) + { + return (IX_ETH_ACC_FAIL); + } + + /* ensure that a PHY is present at this address */ + if(ixEthAccMiiReadRtn(phyAddr, + IX_ETH_ACC_MII_CTRL_REG, + &readVal) != IX_ETH_ACC_SUCCESS) + { + return (IX_ETH_ACC_FAIL); + } + + ixOsalMutexLock(&miiAccessLock, IX_OSAL_WAIT_FOREVER); + mdioCommand = phyReg << IX_ETH_ACC_MII_REG_SHL + | phyAddr << IX_ETH_ACC_MII_ADDR_SHL ; + mdioCommand |= IX_ETH_ACC_MII_GO | IX_ETH_ACC_MII_WRITE | value; + + ixEthAccMdioCmdWrite(mdioCommand); + + miiTimeout = ixEthAccMiiRetryCount; + + while(miiTimeout) + { + + ixEthAccMdioCmdRead(®val); + + /*The "GO" bit is reset to 0 when the write completes*/ + if((regval & IX_ETH_ACC_MII_GO) == 0x0) + { + break; + } + /* Sleep for a while */ + ixOsalSleep(ixEthAccMiiAccessTimeout); + miiTimeout--; + } + + ixOsalMutexUnlock(&miiAccessLock); + if(miiTimeout == 0) + { + return IX_ETH_ACC_FAIL; + } + return IX_ETH_ACC_SUCCESS; +} + + +/***************************************************************** + * + * Phy query functions + * + */ +IxEthAccStatus +ixEthAccMiiStatsShow (UINT32 phyAddr) +{ + UINT16 regval; + printf("Regisers on PHY at address 0x%x\n", phyAddr); + ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_CTRL_REG, ®val); + printf(" Control Register : 0x%4.4x\n", regval); + ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_STAT_REG, ®val); + printf(" Status Register : 0x%4.4x\n", regval); + ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_PHY_ID1_REG, ®val); + printf(" PHY ID1 Register : 0x%4.4x\n", regval); + ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_PHY_ID2_REG, ®val); + printf(" PHY ID2 Register : 0x%4.4x\n", regval); + ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_AN_ADS_REG, ®val); + printf(" Auto Neg ADS Register : 0x%4.4x\n", regval); + ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_AN_PRTN_REG, ®val); + printf(" Auto Neg Partner Ability Register : 0x%4.4x\n", regval); + ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_AN_EXP_REG, ®val); + printf(" Auto Neg Expansion Register : 0x%4.4x\n", regval); + ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_AN_NEXT_REG, ®val); + printf(" Auto Neg Next Register : 0x%4.4x\n", regval); + + return IX_ETH_ACC_SUCCESS; +} + + +/***************************************************************** + * + * Interface query functions + * + */ +IxEthAccStatus +ixEthAccMdioShow (void) +{ + UINT32 regval; + + if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) + { + return (IX_ETH_ACC_FAIL); + } + + ixOsalMutexLock(&miiAccessLock, IX_OSAL_WAIT_FOREVER); + ixEthAccMdioCmdRead(®val); + ixOsalMutexUnlock(&miiAccessLock); + + printf("MDIO command register\n"); + printf(" Go bit : 0x%x\n", (regval & BIT(31)) >> 31); + printf(" MDIO Write : 0x%x\n", (regval & BIT(26)) >> 26); + printf(" PHY address : 0x%x\n", (regval >> 21) & 0x1f); + printf(" Reg address : 0x%x\n", (regval >> 16) & 0x1f); + + ixOsalMutexLock(&miiAccessLock, IX_OSAL_WAIT_FOREVER); + ixEthAccMdioStatusRead(®val); + ixOsalMutexUnlock(&miiAccessLock); + + printf("MDIO status register\n"); + printf(" Read OK : 0x%x\n", (regval & BIT(31)) >> 31); + printf(" Read Data : 0x%x\n", (regval >> 16) & 0xff); + + return IX_ETH_ACC_SUCCESS; +} + diff --git a/cpu/ixp/npe/IxEthDBAPI.c b/cpu/ixp/npe/IxEthDBAPI.c new file mode 100644 index 0000000..b2bfb72 --- /dev/null +++ b/cpu/ixp/npe/IxEthDBAPI.c @@ -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; +} diff --git a/cpu/ixp/npe/IxEthDBAPISupport.c b/cpu/ixp/npe/IxEthDBAPISupport.c new file mode 100644 index 0000000..25633a3 --- /dev/null +++ b/cpu/ixp/npe/IxEthDBAPISupport.c @@ -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 +#include +#include + +#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; +} diff --git a/cpu/ixp/npe/IxEthDBCore.c b/cpu/ixp/npe/IxEthDBCore.c new file mode 100644 index 0000000..25b7cbb --- /dev/null +++ b/cpu/ixp/npe/IxEthDBCore.c @@ -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; +} diff --git a/cpu/ixp/npe/IxEthDBEvents.c b/cpu/ixp/npe/IxEthDBEvents.c new file mode 100644 index 0000000..4d44e03 --- /dev/null +++ b/cpu/ixp/npe/IxEthDBEvents.c @@ -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 +#include + +#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); +} + diff --git a/cpu/ixp/npe/IxEthDBFeatures.c b/cpu/ixp/npe/IxEthDBFeatures.c new file mode 100644 index 0000000..7a58d26 --- /dev/null +++ b/cpu/ixp/npe/IxEthDBFeatures.c @@ -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; +} diff --git a/cpu/ixp/npe/IxEthDBFirewall.c b/cpu/ixp/npe/IxEthDBFirewall.c new file mode 100644 index 0000000..eb46174 --- /dev/null +++ b/cpu/ixp/npe/IxEthDBFirewall.c @@ -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; +} diff --git a/cpu/ixp/npe/IxEthDBHashtable.c b/cpu/ixp/npe/IxEthDBHashtable.c new file mode 100644 index 0000000..f1b18e6 --- /dev/null +++ b/cpu/ixp/npe/IxEthDBHashtable.c @@ -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 entry 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 reference and places the + * pointer to the resulting node in searchResult. + * 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 IX_ETH_DB_SUCCESS 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 reference. + * 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; +} + +/** + * @} + */ diff --git a/cpu/ixp/npe/IxEthDBLearning.c b/cpu/ixp/npe/IxEthDBLearning.c new file mode 100644 index 0000000..2287dbe --- /dev/null +++ b/cpu/ixp/npe/IxEthDBLearning.c @@ -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; +} + diff --git a/cpu/ixp/npe/IxEthDBMem.c b/cpu/ixp/npe/IxEthDBMem.c new file mode 100644 index 0000000..133cbef --- /dev/null +++ b/cpu/ixp/npe/IxEthDBMem.c @@ -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, its associated descriptor + * and recursively of all its child nodes. + * + * @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 + */ diff --git a/cpu/ixp/npe/IxEthDBNPEAdaptor.c b/cpu/ixp/npe/IxEthDBNPEAdaptor.c new file mode 100644 index 0000000..112a46c --- /dev/null +++ b/cpu/ixp/npe/IxEthDBNPEAdaptor.c @@ -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 diff --git a/cpu/ixp/npe/IxEthDBPortUpdate.c b/cpu/ixp/npe/IxEthDBPortUpdate.c new file mode 100644 index 0000000..cdf114b --- /dev/null +++ b/cpu/ixp/npe/IxEthDBPortUpdate.c @@ -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 route balanced + * not perfectly balanced. 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; +} + diff --git a/cpu/ixp/npe/IxEthDBReports.c b/cpu/ixp/npe/IxEthDBReports.c new file mode 100644 index 0000000..9c7ae1c --- /dev/null +++ b/cpu/ixp/npe/IxEthDBReports.c @@ -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; +} + diff --git a/cpu/ixp/npe/IxEthDBSearch.c b/cpu/ixp/npe/IxEthDBSearch.c new file mode 100644 index 0000000..4a10878 --- /dev/null +++ b/cpu/ixp/npe/IxEthDBSearch.c @@ -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; +} diff --git a/cpu/ixp/npe/IxEthDBSpanningTree.c b/cpu/ixp/npe/IxEthDBSpanningTree.c new file mode 100644 index 0000000..6d9fd6e --- /dev/null +++ b/cpu/ixp/npe/IxEthDBSpanningTree.c @@ -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; +} diff --git a/cpu/ixp/npe/IxEthDBUtil.c b/cpu/ixp/npe/IxEthDBUtil.c new file mode 100644 index 0000000..e708bf1 --- /dev/null +++ b/cpu/ixp/npe/IxEthDBUtil.c @@ -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; +} diff --git a/cpu/ixp/npe/IxEthDBVlan.c b/cpu/ixp/npe/IxEthDBVlan.c new file mode 100644 index 0000000..e2efb9b --- /dev/null +++ b/cpu/ixp/npe/IxEthDBVlan.c @@ -0,0 +1,1179 @@ +/** + * @file IxEthDBVlan.c + * + * @brief Implementation of the VLAN 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.h" +#include "IxEthDB_p.h" + +/* forward prototypes */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBUpdateTrafficClass(IxEthDBPortId portID, UINT32 classIndex); +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBVlanTableGet(IxEthDBPortId portID, IxEthDBVlanSet portVlanTable, IxEthDBVlanSet vlanSet); + +/* contants used by various functions as "action" parameter */ +#define ADD_VLAN (0x1) +#define REMOVE_VLAN (0x2) + +/** + * @brief adds or removes a VLAN from a VLAN set + * + * @param vlanID VLAN ID to add or remove + * @param table VLAN set to add into or remove from + * @param action ADD_VLAN or REMOVE_VLAN + * + * @internal + */ +IX_ETH_DB_PRIVATE +void ixEthDBLocalVlanMembershipChange(UINT32 vlanID, IxEthDBVlanSet table, UINT32 action) +{ + UINT32 setOffset; + + /* add/remove VID to membership table */ + setOffset = VLAN_SET_OFFSET(vlanID); /* we need 9 bits to index the 512 byte membership array */ + + if (action == ADD_VLAN) + { + table[setOffset] |= 1 << VLAN_SET_MASK(vlanID); + } + else if (action == REMOVE_VLAN) + { + table[setOffset] &= ~(1 << VLAN_SET_MASK(vlanID)); + } +} + +/** + * @brief updates a set of 8 VLANs in an NPE + * + * @param portID ID of the port + * @param setOffset offset of the 8 VLANs + * + * This function updates the VLAN membership table + * and Transmit Tagging Info table for 8 consecutive + * VLAN IDs indexed by setOffset. + * + * For example, a setOffset of 0 indexes VLAN IDs 0 + * through 7, 1 indexes VLAN IDs 8 through 9 etc. + * + * @return IX_ETH_DB_SUCCESS if the operation completed + * successfully or an appropriate error message otherwise + * + * @internal + */ +IX_ETH_DB_PRIVATE +IxEthDBStatus ixEthDBVlanTableEntryUpdate(IxEthDBPortId portID, UINT32 setOffset) +{ + PortInfo *portInfo = &ixEthDBPortInfo[portID]; + IxNpeMhMessage message; + IX_STATUS result; + + FILL_SETPORTVLANTABLEENTRY_MSG(message, IX_ETH_DB_PORT_ID_TO_NPE_LOGICAL_ID(portID), + 2 * setOffset, + portInfo->vlanMembership[setOffset], + portInfo->transmitTaggingInfo[setOffset]); + + IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result); + + return result; +} + +/** + * @brief updates a VLAN range in an NPE + * + * @param portID ID of the port + * + * This function is similar to @ref ixEthDBVlanTableEntryUpdate + * except that it can update more than one VLAN set (up to + * the entire VLAN membership and TTI tables if the offset is 0 + * and length is sizeof (IxEthDBVlanSet) (512 bytes). + * + * Updating the NPE via this method is slower as it requires + * a memory copy from SDRAM, hence it is recommended that the + * ixEthDBVlanTableEntryUpdate function is used where possible. + * + * @return IX_ETH_DB_SUCCESS if the operation completed + * successfully or an appropriate error message otherwise + * + * @internal + */ +IX_ETH_DB_PRIVATE +IxEthDBStatus ixEthDBVlanTableRangeUpdate(IxEthDBPortId portID) +{ + PortInfo *portInfo = &ixEthDBPortInfo[portID]; + UINT8 *vlanUpdateZone = (UINT8 *) portInfo->updateMethod.vlanUpdateZone; + IxNpeMhMessage message; + UINT32 setIndex; + IX_STATUS result; + + /* copy membership info and transmit tagging into into exchange area */ + for (setIndex = 0 ; setIndex < sizeof (portInfo->vlanMembership) ; setIndex++) + { + /* membership and TTI data are interleaved */ + vlanUpdateZone[setIndex * 2] = portInfo->vlanMembership[setIndex]; + vlanUpdateZone[setIndex * 2 + 1] = portInfo->transmitTaggingInfo[setIndex]; + } + + IX_OSAL_CACHE_FLUSH(vlanUpdateZone, FULL_VLAN_BYTE_SIZE); + + /* build NPE message */ + FILL_SETPORTVLANTABLERANGE_MSG(message, IX_ETH_DB_PORT_ID_TO_NPE_LOGICAL_ID(portID), 0, 0, + IX_OSAL_MMU_VIRT_TO_PHYS(vlanUpdateZone)); + + /* send message */ + IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result); + + return result; +} + +/** + * @brief adds or removes a VLAN from a port's VLAN membership table + * or Transmit Tagging Information table + * + * @param portID ID of the port + * @param vlanID VLAN ID to add or remove + * @param table to add or remove from + * @param action ADD_VLAN or REMOVE_VLAN + * + * @return IX_ETH_DB_SUCCESS if the operation completed + * successfully or an appropriate error message otherwise + * + * @internal + */ +IX_ETH_DB_PRIVATE +IxEthDBStatus ixEthDBPortVlanMembershipChange(IxEthDBPortId portID, IxEthDBVlanId vlanID, IxEthDBVlanSet table, UINT32 action) +{ + /* change VLAN in local membership table */ + ixEthDBLocalVlanMembershipChange(vlanID, table, action); + + /* send updated entry to NPE */ + return ixEthDBVlanTableEntryUpdate(portID, VLAN_SET_OFFSET(vlanID)); +} + +/** + * @brief sets the default port VLAN tag (the lower 3 bytes are the PVID) + * + * @param portID ID of the port + * @param vlanTag port VLAN tag (802.1Q tag) + * + * 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 ixEthDBPortVlanTagSet(IxEthDBPortId portID, IxEthDBVlanTag vlanTag) +{ + IxNpeMhMessage message; + IX_STATUS result; + + IX_ETH_DB_CHECK_PORT(portID); + + IX_ETH_DB_CHECK_SINGLE_NPE(portID); + + IX_ETH_DB_CHECK_VLAN_TAG(vlanTag); + + IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_VLAN_QOS); + + /* add VLAN ID to local membership table */ + ixEthDBPortVlanMembershipChange(portID, + vlanTag & IX_ETH_DB_802_1Q_VLAN_MASK, + ixEthDBPortInfo[portID].vlanMembership, + ADD_VLAN); + + /* set tag in portInfo */ + ixEthDBPortInfo[portID].vlanTag = vlanTag; + + /* build VLAN_SetDefaultRxVID message */ + FILL_SETDEFAULTRXVID_MSG(message, + IX_ETH_DB_PORT_ID_TO_NPE_LOGICAL_ID(portID), + IX_IEEE802_1Q_VLAN_TPID, + vlanTag); + + IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result); + + return result; +} + +/** + * @brief retrieves the default port VLAN tag (the lower 3 bytes are the PVID) + * + * @param portID ID of the port + * @param vlanTag address to write the port VLAN tag (802.1Q tag) 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 ixEthDBPortVlanTagGet(IxEthDBPortId portID, IxEthDBVlanTag *vlanTag) +{ + IX_ETH_DB_CHECK_PORT(portID); + + IX_ETH_DB_CHECK_SINGLE_NPE(portID); + + IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_VLAN_QOS); + + IX_ETH_DB_CHECK_REFERENCE(vlanTag); + + *vlanTag = ixEthDBPortInfo[portID].vlanTag; + + return IX_ETH_DB_SUCCESS; +} + +/** + * @brief sets the VLAN tag (the lower 3 bytes are the PVID) of a + * database filtering record + * + * @param portID ID of the port + * @param vlanTag VLAN tag (802.1Q tag) + * + * Important: filtering records are automatically converted to + * IX_ETH_DB_FILTERING_VLAN record when added a VLAN tag. + * + * 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 ixEthDBVlanTagSet(IxEthDBMacAddr *macAddr, IxEthDBVlanTag vlanTag) +{ + HashNode *searchResult; + MacDescriptor *descriptor; + + IX_ETH_DB_CHECK_REFERENCE(macAddr); + + IX_ETH_DB_CHECK_VLAN_TAG(vlanTag); + + searchResult = ixEthDBSearch(macAddr, IX_ETH_DB_ALL_FILTERING_RECORDS); + + if (searchResult == NULL) + { + return IX_ETH_DB_NO_SUCH_ADDR; + } + + descriptor = (MacDescriptor *) searchResult->data; + + /* set record type to VLAN if not already set */ + descriptor->type = IX_ETH_DB_FILTERING_VLAN_RECORD; + + /* add vlan tag */ + descriptor->recordData.filteringVlanData.ieee802_1qTag = vlanTag; + + /* transaction completed */ + ixEthDBReleaseHashNode(searchResult); + + return IX_ETH_DB_SUCCESS; +} + +/** + * @brief retrieves the VLAN tag (the lower 3 bytes are the PVID) from a + * database VLAN filtering record + * + * @param portID ID of the port + * @param vlanTag address to write the VLAN tag (802.1Q tag) 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 ixEthDBVlanTagGet(IxEthDBMacAddr *macAddr, IxEthDBVlanTag *vlanTag) +{ + HashNode *searchResult; + MacDescriptor *descriptor; + + IX_ETH_DB_CHECK_REFERENCE(macAddr); + + IX_ETH_DB_CHECK_REFERENCE(vlanTag); + + searchResult = ixEthDBSearch(macAddr, IX_ETH_DB_FILTERING_VLAN_RECORD); + + if (searchResult == NULL) + { + return IX_ETH_DB_NO_SUCH_ADDR; + } + + descriptor = (MacDescriptor *) searchResult->data; + + /* get vlan tag */ + *vlanTag = descriptor->recordData.filteringVlanData.ieee802_1qTag; + + /* transaction completed */ + ixEthDBReleaseHashNode(searchResult); + + return IX_ETH_DB_SUCCESS; +} + +/** + * @brief adds a VLAN to a port's VLAN membership table + * + * @param portID ID of the port + * @param vlanID VLAN ID to add + * + * 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 ixEthDBPortVlanMembershipAdd(IxEthDBPortId portID, IxEthDBVlanId vlanID) +{ + IX_ETH_DB_CHECK_PORT(portID); + + IX_ETH_DB_CHECK_SINGLE_NPE(portID); + + IX_ETH_DB_CHECK_VLAN_ID(vlanID); + + IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_VLAN_QOS); + + return ixEthDBPortVlanMembershipChange(portID, vlanID, ixEthDBPortInfo[portID].vlanMembership, ADD_VLAN); +} + +/** + * @brief removes a VLAN from a port's VLAN membership table + * + * @param portID ID of the port + * @param vlanID VLAN ID 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 ixEthDBPortVlanMembershipRemove(IxEthDBPortId portID, IxEthDBVlanId vlanID) +{ + IX_ETH_DB_CHECK_PORT(portID); + + IX_ETH_DB_CHECK_SINGLE_NPE(portID); + + IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_VLAN_QOS); + + IX_ETH_DB_CHECK_VLAN_ID(vlanID); + + /* for safety isolate only the VLAN ID in the tag (the lower 12 bits) */ + vlanID = vlanID & IX_ETH_DB_802_1Q_VLAN_MASK; + + /* check we're not asked to remove the default port VID */ + if (vlanID == IX_ETH_DB_GET_VLAN_ID(ixEthDBPortInfo[portID].vlanTag)) + { + return IX_ETH_DB_NO_PERMISSION; + } + + return ixEthDBPortVlanMembershipChange(portID, vlanID, ixEthDBPortInfo[portID].vlanMembership, REMOVE_VLAN); +} + +/** + * @brief adds or removes a VLAN range from a port's + * VLAN membership table or TTI table + * + * @param portID ID of the port + * @param vlanIDMin start of the VLAN range + * @param vlanIDMax end of the VLAN range + * @param table VLAN set to add or remove from + * @param action ADD_VLAN or REMOVE_VLAN + * + * @return IX_ETH_DB_SUCCESS if the operation completed successfully + * or an appropriate error message otherwise + * + * @internal + */ +IX_ETH_DB_PRIVATE +IxEthDBStatus ixEthDBPortVlanMembershipRangeChange(IxEthDBPortId portID, IxEthDBVlanId vlanIDMin, IxEthDBVlanId vlanIDMax, IxEthDBVlanSet table, UINT32 action) +{ + UINT32 setOffsetMin, setOffsetMax; + + IX_ETH_DB_CHECK_PORT(portID); + + IX_ETH_DB_CHECK_SINGLE_NPE(portID); + + IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_VLAN_QOS); + + IX_ETH_DB_CHECK_VLAN_ID(vlanIDMin); + + IX_ETH_DB_CHECK_VLAN_ID(vlanIDMax); + + /* for safety isolate only the VLAN ID in the tags (the lower 12 bits) */ + vlanIDMin = vlanIDMin & IX_ETH_DB_802_1Q_VLAN_MASK; + vlanIDMax = vlanIDMax & IX_ETH_DB_802_1Q_VLAN_MASK; + + /* is this a range? */ + if (vlanIDMax < vlanIDMin) + { + return IX_ETH_DB_INVALID_VLAN; + } + + /* check that we're not specifically asked to remove the default port VID */ + if (action == REMOVE_VLAN && vlanIDMax == vlanIDMin && IX_ETH_DB_GET_VLAN_ID(ixEthDBPortInfo[portID].vlanTag) == vlanIDMin) + { + return IX_ETH_DB_NO_PERMISSION; + } + + /* compute set offsets */ + setOffsetMin = VLAN_SET_OFFSET(vlanIDMin); + setOffsetMax = VLAN_SET_OFFSET(vlanIDMax); + + /* change VLAN range */ + for (; vlanIDMin <= vlanIDMax ; vlanIDMin++) + { + /* change vlan in local membership table */ + ixEthDBLocalVlanMembershipChange(vlanIDMin, table, action); + } + + /* if the range is within one set (max 8 VLANs in one table byte) we can just update that entry in the NPE */ + if (setOffsetMin == setOffsetMax) + { + /* send updated entry to NPE */ + return ixEthDBVlanTableEntryUpdate(portID, setOffsetMin); + } + else + { + /* update a zone of the membership/transmit tag info table */ + return ixEthDBVlanTableRangeUpdate(portID); + } +} + +/** + * @brief adds a VLAN range to a port's VLAN membership table + * + * @param portID ID of the port + * @param vlanIDMin start of the VLAN range + * @param vlanIDMax end of the VLAN range + * + * 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 ixEthDBPortVlanMembershipRangeAdd(IxEthDBPortId portID, IxEthDBVlanId vlanIDMin, IxEthDBVlanId vlanIDMax) +{ + IX_ETH_DB_CHECK_PORT(portID); + + IX_ETH_DB_CHECK_SINGLE_NPE(portID); + + return ixEthDBPortVlanMembershipRangeChange(portID, vlanIDMin, vlanIDMax, ixEthDBPortInfo[portID].vlanMembership, ADD_VLAN); +} + +/** + * @brief removes a VLAN range from a port's VLAN membership table + * + * @param portID ID of the port + * @param vlanIDMin start of the VLAN range + * @param vlanIDMax end of the VLAN range + * + * 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 ixEthDBPortVlanMembershipRangeRemove(IxEthDBPortId portID, IxEthDBVlanId vlanIDMin, IxEthDBVlanId vlanIDMax) +{ + IX_ETH_DB_CHECK_PORT(portID); + + IX_ETH_DB_CHECK_SINGLE_NPE(portID); + + return ixEthDBPortVlanMembershipRangeChange(portID, vlanIDMin, vlanIDMax, ixEthDBPortInfo[portID].vlanMembership, REMOVE_VLAN); +} + +/** + * @brief sets a port's VLAN membership table or TTI table and + * updates the NPE VLAN configuration + * + * @param portID ID of the port + * @param portVlanTable port VLAN table to set + * @param vlanSet new set contents + * + * @return IX_ETH_DB_SUCCESS if the operation completed successfully + * or an appropriate error message otherwise + * + * @internal + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBPortVlanTableSet(IxEthDBPortId portID, IxEthDBVlanSet portVlanTable, IxEthDBVlanSet vlanSet) +{ + IX_ETH_DB_CHECK_PORT(portID); + + IX_ETH_DB_CHECK_SINGLE_NPE(portID); + + IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_VLAN_QOS); + + IX_ETH_DB_CHECK_REFERENCE(vlanSet); + + memcpy(portVlanTable, vlanSet, sizeof (IxEthDBVlanSet)); + + return ixEthDBVlanTableRangeUpdate(portID); +} + +/** + * @brief retireves a port's VLAN membership table or TTI table + * + * @param portID ID of the port + * @param portVlanTable port VLAN table to retrieve + * @param vlanSet address to + * + * @return IX_ETH_DB_SUCCESS if the operation completed successfully + * or an appropriate error message otherwise + * + * @internal + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBVlanTableGet(IxEthDBPortId portID, IxEthDBVlanSet portVlanTable, IxEthDBVlanSet vlanSet) +{ + IX_ETH_DB_CHECK_PORT(portID); + + IX_ETH_DB_CHECK_SINGLE_NPE(portID); + + IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_VLAN_QOS); + + IX_ETH_DB_CHECK_REFERENCE(vlanSet); + + memcpy(vlanSet, portVlanTable, sizeof (IxEthDBVlanSet)); + + return IX_ETH_DB_SUCCESS; +} + +/** + * @brief sets a port's VLAN membership table + * + * @param portID ID of the port + * @param vlanSet new VLAN membership table + * + * 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 ixEthDBPortVlanMembershipSet(IxEthDBPortId portID, IxEthDBVlanSet vlanSet) +{ + IxEthDBVlanId vlanID; + + IX_ETH_DB_CHECK_PORT(portID); + + IX_ETH_DB_CHECK_SINGLE_NPE(portID); + + IX_ETH_DB_CHECK_REFERENCE(vlanSet); + + /* set the bit corresponding to the PVID just in case */ + vlanID = IX_ETH_DB_GET_VLAN_ID(ixEthDBPortInfo[portID].vlanTag); + vlanSet[VLAN_SET_OFFSET(vlanID)] |= 1 << VLAN_SET_MASK(vlanID); + + return ixEthDBPortVlanTableSet(portID, ixEthDBPortInfo[portID].vlanMembership, vlanSet); +} + +/** + * @brief retrieves a port's VLAN membership table + * + * @param portID ID of the port + * @param vlanSet location to store the port's VLAN membership table + * + * 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 ixEthDBPortVlanMembershipGet(IxEthDBPortId portID, IxEthDBVlanSet vlanSet) +{ + IX_ETH_DB_CHECK_PORT(portID); + + IX_ETH_DB_CHECK_SINGLE_NPE(portID); + + return ixEthDBVlanTableGet(portID, ixEthDBPortInfo[portID].vlanMembership, vlanSet); +} + +/** + * @brief enables or disables Egress tagging for one VLAN ID + * + * @param portID ID of the port + * @param vlanID VLAN ID to enable or disable Egress tagging on + * @param enabled TRUE to enable and FALSE to disable tagging + * + * 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 ixEthDBEgressVlanEntryTaggingEnabledSet(IxEthDBPortId portID, IxEthDBVlanId vlanID, BOOL enabled) +{ + IX_ETH_DB_CHECK_PORT(portID); + + IX_ETH_DB_CHECK_SINGLE_NPE(portID); + + IX_ETH_DB_CHECK_VLAN_ID(vlanID); + + IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_VLAN_QOS); + + return ixEthDBPortVlanMembershipChange(portID, vlanID, ixEthDBPortInfo[portID].transmitTaggingInfo, enabled? ADD_VLAN : REMOVE_VLAN); +} + +/** + * @brief retrieves the Egress tagging status for one VLAN ID + * + * @param portID ID of the port + * @param vlanID VLAN ID to retrieve the tagging status for + * @param enabled location to store the tagging status + * (TRUE - tagging enabled, FALSE - tagging disabled) + * + * 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 ixEthDBEgressVlanEntryTaggingEnabledGet(IxEthDBPortId portID, IxEthDBVlanId vlanID, BOOL *enabled) +{ + IX_ETH_DB_CHECK_PORT(portID); + + IX_ETH_DB_CHECK_SINGLE_NPE(portID); + + IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_VLAN_QOS); + + IX_ETH_DB_CHECK_REFERENCE(enabled); + + IX_ETH_DB_CHECK_VLAN_ID(vlanID); + + *enabled = ((ixEthDBPortInfo[portID].transmitTaggingInfo[VLAN_SET_OFFSET(vlanID)] & (1 << VLAN_SET_MASK(vlanID))) != 0); + + return IX_ETH_DB_SUCCESS; +} + +/** + * @brief enables or disables Egress VLAN tagging for a VLAN range + * + * @param portID ID of the port + * @param vlanIDMin start of VLAN range + * @param vlanIDMax end of VLAN range + * @param enabled TRUE to enable or FALSE to disable VLAN tagging + * + * 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 ixEthDBEgressVlanRangeTaggingEnabledSet(IxEthDBPortId portID, IxEthDBVlanId vlanIDMin, IxEthDBVlanId vlanIDMax, BOOL enabled) +{ + IX_ETH_DB_CHECK_PORT(portID); + + IX_ETH_DB_CHECK_SINGLE_NPE(portID); + + return ixEthDBPortVlanMembershipRangeChange(portID, vlanIDMin, vlanIDMax, ixEthDBPortInfo[portID].transmitTaggingInfo, enabled? ADD_VLAN : REMOVE_VLAN); +} + +/** + * @brief sets the Egress VLAN tagging table (the Transmit Tagging + * Information table) + * + * @param portID ID of the port + * @param vlanSet new TTI table + * + * 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 ixEthDBEgressVlanTaggingEnabledSet(IxEthDBPortId portID, IxEthDBVlanSet vlanSet) +{ + IxEthDBVlanId vlanID; + + IX_ETH_DB_CHECK_PORT(portID); + + IX_ETH_DB_CHECK_SINGLE_NPE(portID); + + IX_ETH_DB_CHECK_REFERENCE(vlanSet); + + /* set the PVID bit just in case */ + vlanID = IX_ETH_DB_GET_VLAN_ID(ixEthDBPortInfo[portID].vlanTag); + vlanSet[VLAN_SET_OFFSET(vlanID)] |= 1 << VLAN_SET_MASK(vlanID); + + return ixEthDBPortVlanTableSet(portID, ixEthDBPortInfo[portID].transmitTaggingInfo, vlanSet); +} + +/** + * @brief retrieves the Egress VLAN tagging table (the Transmit + * Tagging Information table) + * + * @param portID ID of the port + * @param vlanSet location to store the port's TTI table + * + * 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 ixEthDBEgressVlanTaggingEnabledGet(IxEthDBPortId portID, IxEthDBVlanSet vlanSet) +{ + IX_ETH_DB_CHECK_PORT(portID); + + IX_ETH_DB_CHECK_SINGLE_NPE(portID); + + return ixEthDBVlanTableGet(portID, ixEthDBPortInfo[portID].transmitTaggingInfo, vlanSet); +} + +/** + * @brief sends the NPE the updated frame filter and default + * Ingress tagging + * + * @param portID ID of the port + * + * @return IX_ETH_DB_SUCCESS if the operation completed successfully + * or an appropriate error message otherwise + * + * @internal + */ +IX_ETH_DB_PRIVATE +IxEthDBStatus ixEthDBIngressVlanModeUpdate(IxEthDBPortId portID) +{ + PortInfo *portInfo = &ixEthDBPortInfo[portID]; + IxNpeMhMessage message; + IX_STATUS result; + + FILL_SETRXTAGMODE_MSG(message, portID, portInfo->npeFrameFilter, portInfo->npeTaggingAction); + IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result); + + return result; +} + +/** + * @brief sets the default Ingress tagging behavior + * + * @param portID ID of the port + * @param taggingAction default tagging behavior + * + * 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 ixEthDBIngressVlanTaggingEnabledSet(IxEthDBPortId portID, IxEthDBTaggingAction taggingAction) +{ + PortInfo *portInfo; + + IX_ETH_DB_CHECK_PORT(portID); + + IX_ETH_DB_CHECK_SINGLE_NPE(portID); + + IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_VLAN_QOS); + + portInfo = &ixEthDBPortInfo[portID]; + + if (taggingAction == IX_ETH_DB_PASS_THROUGH) + { + portInfo->npeTaggingAction = 0x00; + } + else if (taggingAction == IX_ETH_DB_ADD_TAG) + { + portInfo->npeTaggingAction = 0x02; + } + else if (taggingAction == IX_ETH_DB_REMOVE_TAG) + { + portInfo->npeTaggingAction = 0x01; + } + else + { + return IX_ETH_DB_INVALID_ARG; + } + + portInfo->taggingAction = taggingAction; + + return ixEthDBIngressVlanModeUpdate(portID); +} + +/** + * @brief retrieves the default Ingress tagging behavior of a port + * + * @param portID ID of the port + * @param taggingAction location to save the default tagging behavior + * + * 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 ixEthDBIngressVlanTaggingEnabledGet(IxEthDBPortId portID, IxEthDBTaggingAction *taggingAction) +{ + IX_ETH_DB_CHECK_PORT(portID); + + IX_ETH_DB_CHECK_SINGLE_NPE(portID); + + IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_VLAN_QOS); + + IX_ETH_DB_CHECK_REFERENCE(taggingAction); + + *taggingAction = ixEthDBPortInfo[portID].taggingAction; + + return IX_ETH_DB_SUCCESS; +} + +/** + * @brief sets the Ingress acceptable frame type filter + * + * @param portID ID of the port + * @param frameFilter acceptable frame type filter + * + * 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 ixEthDBAcceptableFrameTypeSet(IxEthDBPortId portID, IxEthDBFrameFilter frameFilter) +{ + PortInfo *portInfo; + IxEthDBStatus result = IX_ETH_DB_SUCCESS; + + IX_ETH_DB_CHECK_PORT(portID); + + IX_ETH_DB_CHECK_SINGLE_NPE(portID); + + IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_VLAN_QOS); + + /* check parameter range + the ORed value of the valid values is 0x7 + a value having extra bits is invalid */ + if ((frameFilter | 0x7) != 0x7 || frameFilter == 0) + { + return IX_ETH_DB_INVALID_ARG; + } + + portInfo = &ixEthDBPortInfo[portID]; + + portInfo->frameFilter = frameFilter; + portInfo->npeFrameFilter = 0; /* allow all by default */ + + /* if accepting priority tagged but not all VLAN tagged + set the membership table to contain only VLAN ID 0 + hence remove vlans 1-4094 and add VLAN ID 0 */ + if (((frameFilter & IX_ETH_DB_PRIORITY_TAGGED_FRAMES) != 0) + && ((frameFilter & IX_ETH_DB_VLAN_TAGGED_FRAMES) == 0)) + { + result = ixEthDBPortVlanMembershipRangeChange(portID, + 1, IX_ETH_DB_802_1Q_MAX_VLAN_ID, portInfo->vlanMembership, REMOVE_VLAN); + + if (result == IX_ETH_DB_SUCCESS) + { + ixEthDBLocalVlanMembershipChange(0, portInfo->vlanMembership, ADD_VLAN); + result = ixEthDBVlanTableRangeUpdate(portID); + } + } + + /* untagged only? */ + if (frameFilter == IX_ETH_DB_UNTAGGED_FRAMES) + { + portInfo->npeFrameFilter = 0x01; + } + + /* tagged only? */ + if ((frameFilter & IX_ETH_DB_UNTAGGED_FRAMES) == 0) + { + portInfo->npeFrameFilter = 0x02; + } + + if (result == IX_ETH_DB_SUCCESS) + { + result = ixEthDBIngressVlanModeUpdate(portID); + } + + return result; +} + +/** + * @brief retrieves the acceptable frame type filter for a port + * + * @param portID ID of the port + * @param frameFilter location to store the frame filter + * + * 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 ixEthDBAcceptableFrameTypeGet(IxEthDBPortId portID, IxEthDBFrameFilter *frameFilter) +{ + IX_ETH_DB_CHECK_PORT(portID); + + IX_ETH_DB_CHECK_SINGLE_NPE(portID); + + IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_VLAN_QOS); + + IX_ETH_DB_CHECK_REFERENCE(frameFilter); + + *frameFilter = ixEthDBPortInfo[portID].frameFilter; + + return IX_ETH_DB_SUCCESS; +} + +/** + * @brief sends an NPE the updated configuration related + * to one QoS priority (associated traffic class and AQM mapping) + * + * @param portID ID of the port + * @param classIndex QoS priority (traffic class index) + * + * @return IX_ETH_DB_SUCCESS if the operation completed successfully + * or an appropriate error message otherwise + * + * @internal + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBUpdateTrafficClass(IxEthDBPortId portID, UINT32 classIndex) +{ + IxNpeMhMessage message; + IX_STATUS result; + + UINT32 trafficClass = ixEthDBPortInfo[portID].priorityTable[classIndex]; + UINT32 aqmQueue = ixEthDBPortInfo[portID].ixEthDBTrafficClassAQMAssignments[trafficClass]; + + FILL_SETRXQOSENTRY(message, IX_ETH_DB_PORT_ID_TO_NPE_LOGICAL_ID(portID), classIndex, trafficClass, aqmQueue); + + IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result); + + return result; +} + +/** + * @brief sets the priority mapping table + * + * @param portID ID of the port + * @param priorityTable new priority mapping table + * + * 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 ixEthDBPriorityMappingTableSet(IxEthDBPortId portID, IxEthDBPriorityTable priorityTable) +{ + UINT32 classIndex; + + IX_ETH_DB_CHECK_PORT(portID); + + IX_ETH_DB_CHECK_SINGLE_NPE(portID); + + IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_VLAN_QOS); + + IX_ETH_DB_CHECK_REFERENCE(priorityTable); + + for (classIndex = 0 ; classIndex < IX_IEEE802_1Q_QOS_PRIORITY_COUNT ; classIndex++) + { + /* check range */ + if (priorityTable[classIndex] >= ixEthDBPortInfo[portID].ixEthDBTrafficClassCount) + { + return IX_ETH_DB_INVALID_PRIORITY; + } + } + + /* set new traffic classes */ + for (classIndex = 0 ; classIndex < IX_IEEE802_1Q_QOS_PRIORITY_COUNT ; classIndex++) + { + ixEthDBPortInfo[portID].priorityTable[classIndex] = priorityTable[classIndex]; + + if (ixEthDBUpdateTrafficClass(portID, classIndex) != IX_ETH_DB_SUCCESS) + { + return IX_ETH_DB_FAIL; + } + } + + return IX_ETH_DB_SUCCESS; + } + +/** + * @brief retrieves a port's priority mapping table + * + * @param portID ID of the port + * @param priorityTable location to store the priority table + * + * 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 ixEthDBPriorityMappingTableGet(IxEthDBPortId portID, IxEthDBPriorityTable priorityTable) +{ + IX_ETH_DB_CHECK_PORT(portID); + + IX_ETH_DB_CHECK_SINGLE_NPE(portID); + + IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_VLAN_QOS); + + IX_ETH_DB_CHECK_REFERENCE(priorityTable); + + memcpy(priorityTable, ixEthDBPortInfo[portID].priorityTable, sizeof (IxEthDBPriorityTable)); + + return IX_ETH_DB_SUCCESS; +} + +/** + * @brief sets one QoS priority => traffic class mapping + * + * @param portID ID of the port + * @param userPriority QoS (user) priority + * @param trafficClass associated traffic class + * + * 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 ixEthDBPriorityMappingClassSet(IxEthDBPortId portID, IxEthDBPriority userPriority, IxEthDBPriority trafficClass) +{ + IX_ETH_DB_CHECK_PORT(portID); + + IX_ETH_DB_CHECK_SINGLE_NPE(portID); + + IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_VLAN_QOS); + + /* check ranges for userPriority and trafficClass */ + if (userPriority >= IX_IEEE802_1Q_QOS_PRIORITY_COUNT || trafficClass >= ixEthDBPortInfo[portID].ixEthDBTrafficClassCount) + { + return IX_ETH_DB_INVALID_PRIORITY; + } + + ixEthDBPortInfo[portID].priorityTable[userPriority] = trafficClass; + + return ixEthDBUpdateTrafficClass(portID, userPriority); +} + +/** + * @brief retrieves one QoS priority => traffic class mapping + * + * @param portID ID of the port + * @param userPriority QoS (user) priority + * @param trafficClass location to store the associated traffic class + * + * 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 ixEthDBPriorityMappingClassGet(IxEthDBPortId portID, IxEthDBPriority userPriority, IxEthDBPriority *trafficClass) +{ + IX_ETH_DB_CHECK_PORT(portID); + + IX_ETH_DB_CHECK_SINGLE_NPE(portID); + + IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_VLAN_QOS); + + IX_ETH_DB_CHECK_REFERENCE(trafficClass); + + /* check userPriority range */ + if (userPriority >= IX_IEEE802_1Q_QOS_PRIORITY_COUNT) + { + return IX_ETH_DB_INVALID_PRIORITY; + } + + *trafficClass = ixEthDBPortInfo[portID].priorityTable[userPriority]; + + return IX_ETH_DB_SUCCESS; +} + +/** + * @brief enables or disables the source port extraction + * from the VLAN TPID field + * + * @param portID ID of the port + * @param enable TRUE to enable or FALSE to disable + * + * 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 ixEthDBVlanPortExtractionEnable(IxEthDBPortId portID, BOOL enable) +{ + 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_VLAN_QOS); + + FILL_SETPORTIDEXTRACTIONMODE(message, portID, enable); + + IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result); + + return result; +} diff --git a/cpu/ixp/npe/IxEthDBWiFi.c b/cpu/ixp/npe/IxEthDBWiFi.c new file mode 100644 index 0000000..0a6043f --- /dev/null +++ b/cpu/ixp/npe/IxEthDBWiFi.c @@ -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; +} diff --git a/cpu/ixp/npe/IxEthMii.c b/cpu/ixp/npe/IxEthMii.c new file mode 100644 index 0000000..4d92f17 --- /dev/null +++ b/cpu/ixp/npe/IxEthMii.c @@ -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 0 && i= IX_ETH_MII_RESET_DELAY_MS) + { + ixEthAccMiiWriteRtn(phyAddr, IX_ETH_MII_CTRL_REG, + IX_ETH_MII_CR_NORM_EN); + return IX_FAIL; + } + + return IX_SUCCESS; + } /* end of if(ixEthMiiPhyId) */ + else if (ixEthMiiPhyId[phyAddr] == IX_ETH_MII_KS8995_PHY_ID) + { + /* reset bit is reserved, just reset the control register */ + ixEthAccMiiWriteRtn(phyAddr, IX_ETH_MII_CTRL_REG, + IX_ETH_MII_CR_NORM_EN); + return IX_SUCCESS; + } + else + { + /* unknown PHY, set the control register reset bit, + * wait 2 s. and clear the control register. + */ + ixEthAccMiiWriteRtn(phyAddr, IX_ETH_MII_CTRL_REG, + IX_ETH_MII_CR_RESET); + + ixOsalSleep (IX_ETH_MII_RESET_DELAY_MS); + + ixEthAccMiiWriteRtn(phyAddr, IX_ETH_MII_CTRL_REG, + IX_ETH_MII_CR_NORM_EN); + return IX_SUCCESS; + } /* end of if-else(ixEthMiiPhyId) */ + } /* end of if(phyAddr) */ + return IX_FAIL; +} + +/***************************************************************** + * + * Link state query functions + */ + +PUBLIC IX_STATUS +ixEthMiiLinkStatus(UINT32 phyAddr, + BOOL *linkUp, + BOOL *speed100, + BOOL *fullDuplex, + BOOL *autoneg) +{ + UINT16 ctrlRegval, statRegval, regval, regval4, regval5; + + /* check the parameters */ + if ((linkUp == NULL) || + (speed100 == NULL) || + (fullDuplex == NULL) || + (autoneg == NULL)) + { + return IX_FAIL; + } + + *linkUp = FALSE; + *speed100 = FALSE; + *fullDuplex = FALSE; + *autoneg = FALSE; + + if ((phyAddr < IXP425_ETH_ACC_MII_MAX_ADDR) && + (ixEthMiiPhyId[phyAddr] != IX_ETH_MII_INVALID_PHY_ID)) + { + if ((ixEthMiiPhyId[phyAddr] == IX_ETH_MII_LXT971_PHY_ID) || + (ixEthMiiPhyId[phyAddr] == IX_ETH_MII_LXT972_PHY_ID) || + (ixEthMiiPhyId[phyAddr] == IX_ETH_MII_LXT9785_PHY_ID) + ) + { + /* --------------------------------------------------*/ + /* Retrieve information from PHY specific register */ + /* --------------------------------------------------*/ + if (ixEthAccMiiReadRtn(phyAddr, + IX_ETH_MII_STAT2_REG, + ®val) != IX_ETH_ACC_SUCCESS) + { + return IX_FAIL; + } + *linkUp = ((regval & IX_ETH_MII_SR2_LINK) != 0); + *speed100 = ((regval & IX_ETH_MII_SR2_100) != 0); + *fullDuplex = ((regval & IX_ETH_MII_SR2_FD) != 0); + *autoneg = ((regval & IX_ETH_MII_SR2_AUTO) != 0); + return IX_SUCCESS; + } /* end of if(ixEthMiiPhyId) */ + else + { + /* ----------------------------------------------------*/ + /* Retrieve information from status and ctrl registers */ + /* ----------------------------------------------------*/ + if (ixEthAccMiiReadRtn(phyAddr, + IX_ETH_MII_CTRL_REG, + &ctrlRegval) != IX_ETH_ACC_SUCCESS) + { + return IX_FAIL; + } + ixEthAccMiiReadRtn(phyAddr, IX_ETH_MII_STAT_REG, &statRegval); + + *linkUp = ((statRegval & IX_ETH_MII_SR_LINK_STATUS) != 0); + if (*linkUp) + { + *autoneg = ((ctrlRegval & IX_ETH_MII_CR_AUTO_EN) != 0) && + ((statRegval & IX_ETH_MII_SR_AUTO_SEL) != 0) && + ((statRegval & IX_ETH_MII_SR_AUTO_NEG) != 0); + + if (*autoneg) + { + /* mask the current stat values with the capabilities */ + ixEthAccMiiReadRtn(phyAddr, IX_ETH_MII_AN_ADS_REG, ®val4); + ixEthAccMiiReadRtn(phyAddr, IX_ETH_MII_AN_PRTN_REG, ®val5); + /* merge the flags from the 3 registers */ + regval = (statRegval & ((regval4 & regval5) << 6)); + /* initialise from status register values */ + if ((regval & IX_ETH_MII_SR_TX_FULL_DPX) != 0) + { + /* 100 Base X full dplx */ + *speed100 = TRUE; + *fullDuplex = TRUE; + return IX_SUCCESS; + } + if ((regval & IX_ETH_MII_SR_TX_HALF_DPX) != 0) + { + /* 100 Base X half dplx */ + *speed100 = TRUE; + return IX_SUCCESS; + } + if ((regval & IX_ETH_MII_SR_10T_FULL_DPX) != 0) + { + /* 10 mb full dplx */ + *fullDuplex = TRUE; + return IX_SUCCESS; + } + if ((regval & IX_ETH_MII_SR_10T_HALF_DPX) != 0) + { + /* 10 mb half dplx */ + return IX_SUCCESS; + } + } /* end of if(autoneg) */ + else + { + /* autonegotiate not complete, return setup parameters */ + *speed100 = ((ctrlRegval & IX_ETH_MII_CR_100) != 0); + *fullDuplex = ((ctrlRegval & IX_ETH_MII_CR_FDX) != 0); + } + } /* end of if(linkUp) */ + } /* end of if-else(ixEthMiiPhyId) */ + } /* end of if(phyAddr) */ + else + { + return IX_FAIL; + } /* end of if-else(phyAddr) */ + return IX_SUCCESS; +} + +/***************************************************************** + * + * Link state display functions + */ + +PUBLIC IX_STATUS +ixEthMiiPhyShow (UINT32 phyAddr) +{ + BOOL linkUp, speed100, fullDuplex, autoneg; + UINT16 cregval; + UINT16 sregval; + + + ixEthAccMiiReadRtn(phyAddr, IX_ETH_MII_STAT_REG, &sregval); + ixEthAccMiiReadRtn(phyAddr, IX_ETH_MII_CTRL_REG, &cregval); + + /* get link information */ + if (ixEthMiiLinkStatus(phyAddr, + &linkUp, + &speed100, + &fullDuplex, + &autoneg) != IX_ETH_ACC_SUCCESS) + { + printf("PHY Status unknown\n"); + return IX_FAIL; + } + + printf("PHY ID [phyAddr]: %8.8x\n",ixEthMiiPhyId[phyAddr]); + printf( " Status reg: %4.4x\n",sregval); + printf( " control reg: %4.4x\n",cregval); + /* display link information */ + printf("PHY Status:\n"); + printf(" Link is %s\n", + (linkUp ? "Up" : "Down")); + if((sregval & IX_ETH_MII_SR_REMOTE_FAULT) != 0) + { + printf(" Remote fault detected\n"); + } + printf(" Auto Negotiation %s\n", + (autoneg ? "Completed" : "Not Completed")); + + printf("PHY Configuration:\n"); + printf(" Speed %sMb/s\n", + (speed100 ? "100" : "10")); + printf(" %s Duplex\n", + (fullDuplex ? "Full" : "Half")); + printf(" Auto Negotiation %s\n", + (autoneg ? "Enabled" : "Disabled")); + return IX_SUCCESS; +} + diff --git a/cpu/ixp/npe/IxFeatureCtrl.c b/cpu/ixp/npe/IxFeatureCtrl.c new file mode 100644 index 0000000..e02aabf --- /dev/null +++ b/cpu/ixp/npe/IxFeatureCtrl.c @@ -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_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 +} diff --git a/cpu/ixp/npe/IxNpeDl.c b/cpu/ixp/npe/IxNpeDl.c new file mode 100644 index 0000000..ffe355c --- /dev/null +++ b/cpu/ixp/npe/IxNpeDl.c @@ -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; + } +} diff --git a/cpu/ixp/npe/IxNpeDlImageMgr.c b/cpu/ixp/npe/IxNpeDlImageMgr.c new file mode 100644 index 0000000..e05c228 --- /dev/null +++ b/cpu/ixp/npe/IxNpeDlImageMgr.c @@ -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; +} + diff --git a/cpu/ixp/npe/IxNpeDlNpeMgr.c b/cpu/ixp/npe/IxNpeDlNpeMgr.c new file mode 100644 index 0000000..f5a4c5f --- /dev/null +++ b/cpu/ixp/npe/IxNpeDlNpeMgr.c @@ -0,0 +1,936 @@ +/** + * @file IxNpeDlNpeMgr.c + * + * @author Intel Corporation + * @date 09 January 2002 + * + * @brief This file contains the implementation of the private API for the + * IXP425 NPE Downloader NpeMgr module + * + * + * @par + * IXP400 SW Release version 2.0 + * + * -- Copyright Notice -- + * + * @par + * Copyright 2001-2005, Intel Corporation. + * All rights reserved. + * + * @par + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * @par + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @par + * -- End of Copyright Notice -- +*/ + + +/* + * Put the user defined include files required. + */ + + +/* + * Put the user defined include files required. + */ +#include "IxOsal.h" +#include "IxNpeDl.h" +#include "IxNpeDlNpeMgr_p.h" +#include "IxNpeDlNpeMgrUtils_p.h" +#include "IxNpeDlNpeMgrEcRegisters_p.h" +#include "IxNpeDlMacros_p.h" +#include "IxFeatureCtrl.h" + +/* + * #defines and macros used in this file. + */ +#define IX_NPEDL_BYTES_PER_WORD 4 + +/* used to read download map from version in microcode image */ +#define IX_NPEDL_BLOCK_TYPE_INSTRUCTION 0x00000000 +#define IX_NPEDL_BLOCK_TYPE_DATA 0x00000001 +#define IX_NPEDL_BLOCK_TYPE_STATE 0x00000002 +#define IX_NPEDL_END_OF_DOWNLOAD_MAP 0x0000000F + +/* + * masks used to extract address info from State information context + * register addresses as read from microcode image + */ +#define IX_NPEDL_MASK_STATE_ADDR_CTXT_REG 0x0000000F +#define IX_NPEDL_MASK_STATE_ADDR_CTXT_NUM 0x000000F0 + +/* LSB offset of Context Number field in State-Info Context Address */ +#define IX_NPEDL_OFFSET_STATE_ADDR_CTXT_NUM 4 + +/* size (in words) of single State Information entry (ctxt reg address|data) */ +#define IX_NPEDL_STATE_INFO_ENTRY_SIZE 2 + + + #define IX_NPEDL_RESET_NPE_PARITY 0x0800 + #define IX_NPEDL_PARITY_BIT_MASK 0x3F00FFFF + #define IX_NPEDL_CONFIG_CTRL_REG_MASK 0x3F3FFFFF + + +/* + * Typedefs whose scope is limited to this file. + */ + +typedef struct +{ + UINT32 type; + UINT32 offset; +} IxNpeDlNpeMgrDownloadMapBlockEntry; + +typedef union +{ + IxNpeDlNpeMgrDownloadMapBlockEntry block; + UINT32 eodmMarker; +} IxNpeDlNpeMgrDownloadMapEntry; + +typedef struct +{ + /* 1st entry in the download map (there may be more than one) */ + IxNpeDlNpeMgrDownloadMapEntry entry[1]; +} IxNpeDlNpeMgrDownloadMap; + + +/* used to access an instruction or data block in a microcode image */ +typedef struct +{ + UINT32 npeMemAddress; + UINT32 size; + UINT32 data[1]; +} IxNpeDlNpeMgrCodeBlock; + +/* used to access each Context Reg entry state-information block */ +typedef struct +{ + UINT32 addressInfo; + UINT32 value; +} IxNpeDlNpeMgrStateInfoCtxtRegEntry; + +/* used to access a state-information block in a microcode image */ +typedef struct +{ + UINT32 size; + IxNpeDlNpeMgrStateInfoCtxtRegEntry ctxtRegEntry[1]; +} IxNpeDlNpeMgrStateInfoBlock; + +/* used to store some useful NPE information for easy access */ +typedef struct +{ + UINT32 baseAddress; + UINT32 insMemSize; + UINT32 dataMemSize; +} IxNpeDlNpeInfo; + +/* used to distinguish instruction and data memory operations */ +typedef enum +{ + IX_NPEDL_MEM_TYPE_INSTRUCTION = 0, + IX_NPEDL_MEM_TYPE_DATA +} IxNpeDlNpeMemType; + +/* used to hold a reset value for a particular ECS register */ +typedef struct +{ + UINT32 regAddr; + UINT32 regResetVal; +} IxNpeDlEcsRegResetValue; + +/* prototype of function to write either Instruction or Data memory */ +typedef IX_STATUS (*IxNpeDlNpeMgrMemWrite) (UINT32 npeBaseAddress, + UINT32 npeMemAddress, + UINT32 npeMemData, + BOOL verify); + +/* module statistics counters */ +typedef struct +{ + UINT32 instructionBlocksLoaded; + UINT32 dataBlocksLoaded; + UINT32 stateInfoBlocksLoaded; + UINT32 criticalNpeErrors; + UINT32 criticalMicrocodeErrors; + UINT32 npeStarts; + UINT32 npeStops; + UINT32 npeResets; +} IxNpeDlNpeMgrStats; + + +/* + * Variable declarations global to this file only. Externs are followed by + * static variables. + */ +static IxNpeDlNpeInfo ixNpeDlNpeInfo[] = +{ + { + 0, + IX_NPEDL_INS_MEMSIZE_WORDS_NPEA, + IX_NPEDL_DATA_MEMSIZE_WORDS_NPEA + }, + { + 0, + IX_NPEDL_INS_MEMSIZE_WORDS_NPEB, + IX_NPEDL_DATA_MEMSIZE_WORDS_NPEB + }, + { + 0, + IX_NPEDL_INS_MEMSIZE_WORDS_NPEC, + IX_NPEDL_DATA_MEMSIZE_WORDS_NPEC + } +}; + +/* contains Reset values for Context Store Registers */ +static UINT32 ixNpeDlCtxtRegResetValues[] = +{ + IX_NPEDL_CTXT_REG_RESET_STEVT, + IX_NPEDL_CTXT_REG_RESET_STARTPC, + IX_NPEDL_CTXT_REG_RESET_REGMAP, + IX_NPEDL_CTXT_REG_RESET_CINDEX, +}; + +/* contains Reset values for Context Store Registers */ +static IxNpeDlEcsRegResetValue ixNpeDlEcsRegResetValues[] = +{ + {IX_NPEDL_ECS_BG_CTXT_REG_0, IX_NPEDL_ECS_BG_CTXT_REG_0_RESET}, + {IX_NPEDL_ECS_BG_CTXT_REG_1, IX_NPEDL_ECS_BG_CTXT_REG_1_RESET}, + {IX_NPEDL_ECS_BG_CTXT_REG_2, IX_NPEDL_ECS_BG_CTXT_REG_2_RESET}, + {IX_NPEDL_ECS_PRI_1_CTXT_REG_0, IX_NPEDL_ECS_PRI_1_CTXT_REG_0_RESET}, + {IX_NPEDL_ECS_PRI_1_CTXT_REG_1, IX_NPEDL_ECS_PRI_1_CTXT_REG_1_RESET}, + {IX_NPEDL_ECS_PRI_1_CTXT_REG_2, IX_NPEDL_ECS_PRI_1_CTXT_REG_2_RESET}, + {IX_NPEDL_ECS_PRI_2_CTXT_REG_0, IX_NPEDL_ECS_PRI_2_CTXT_REG_0_RESET}, + {IX_NPEDL_ECS_PRI_2_CTXT_REG_1, IX_NPEDL_ECS_PRI_2_CTXT_REG_1_RESET}, + {IX_NPEDL_ECS_PRI_2_CTXT_REG_2, IX_NPEDL_ECS_PRI_2_CTXT_REG_2_RESET}, + {IX_NPEDL_ECS_DBG_CTXT_REG_0, IX_NPEDL_ECS_DBG_CTXT_REG_0_RESET}, + {IX_NPEDL_ECS_DBG_CTXT_REG_1, IX_NPEDL_ECS_DBG_CTXT_REG_1_RESET}, + {IX_NPEDL_ECS_DBG_CTXT_REG_2, IX_NPEDL_ECS_DBG_CTXT_REG_2_RESET}, + {IX_NPEDL_ECS_INSTRUCT_REG, IX_NPEDL_ECS_INSTRUCT_REG_RESET} +}; + +static IxNpeDlNpeMgrStats ixNpeDlNpeMgrStats; + +/* Set when NPE register memory has been mapped */ +static BOOL ixNpeDlMemInitialised = FALSE; + + +/* + * static function prototypes. + */ +PRIVATE IX_STATUS +ixNpeDlNpeMgrMemLoad (IxNpeDlNpeId npeId, UINT32 npeBaseAddress, + IxNpeDlNpeMgrCodeBlock *codeBlockPtr, + BOOL verify, IxNpeDlNpeMemType npeMemType); +PRIVATE IX_STATUS +ixNpeDlNpeMgrStateInfoLoad (UINT32 npeBaseAddress, + IxNpeDlNpeMgrStateInfoBlock *codeBlockPtr, + BOOL verify); +PRIVATE BOOL +ixNpeDlNpeMgrBitsSetCheck (UINT32 npeBaseAddress, UINT32 regOffset, + UINT32 expectedBitsSet); + +PRIVATE UINT32 +ixNpeDlNpeMgrBaseAddressGet (IxNpeDlNpeId npeId); + +/* + * Function definition: ixNpeDlNpeMgrBaseAddressGet + */ +PRIVATE UINT32 +ixNpeDlNpeMgrBaseAddressGet (IxNpeDlNpeId npeId) +{ + IX_OSAL_ASSERT (ixNpeDlMemInitialised); + return ixNpeDlNpeInfo[npeId].baseAddress; +} + + +/* + * Function definition: ixNpeDlNpeMgrInit + */ +void +ixNpeDlNpeMgrInit (void) +{ + /* Only map the memory once */ + if (!ixNpeDlMemInitialised) + { + UINT32 virtAddr; + + /* map the register memory for NPE-A */ + virtAddr = (UINT32) IX_OSAL_MEM_MAP (IX_NPEDL_NPEBASEADDRESS_NPEA, + IX_OSAL_IXP400_NPEA_MAP_SIZE); + IX_OSAL_ASSERT(virtAddr); + ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEA].baseAddress = virtAddr; + + /* map the register memory for NPE-B */ + virtAddr = (UINT32) IX_OSAL_MEM_MAP (IX_NPEDL_NPEBASEADDRESS_NPEB, + IX_OSAL_IXP400_NPEB_MAP_SIZE); + IX_OSAL_ASSERT(virtAddr); + ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEB].baseAddress = virtAddr; + + /* map the register memory for NPE-C */ + virtAddr = (UINT32) IX_OSAL_MEM_MAP (IX_NPEDL_NPEBASEADDRESS_NPEC, + IX_OSAL_IXP400_NPEC_MAP_SIZE); + IX_OSAL_ASSERT(virtAddr); + ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEC].baseAddress = virtAddr; + + ixNpeDlMemInitialised = TRUE; + } +} + + +/* + * Function definition: ixNpeDlNpeMgrUninit + */ +IX_STATUS +ixNpeDlNpeMgrUninit (void) +{ + if (!ixNpeDlMemInitialised) + { + return IX_FAIL; + } + + IX_OSAL_MEM_UNMAP (ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEA].baseAddress); + IX_OSAL_MEM_UNMAP (ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEB].baseAddress); + IX_OSAL_MEM_UNMAP (ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEC].baseAddress); + + ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEA].baseAddress = 0; + ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEB].baseAddress = 0; + ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEC].baseAddress = 0; + + ixNpeDlMemInitialised = FALSE; + + return IX_SUCCESS; +} + +/* + * Function definition: ixNpeDlNpeMgrImageLoad + */ +IX_STATUS +ixNpeDlNpeMgrImageLoad ( + IxNpeDlNpeId npeId, + UINT32 *imageCodePtr, + BOOL verify) +{ + UINT32 npeBaseAddress; + IxNpeDlNpeMgrDownloadMap *downloadMap; + UINT32 *blockPtr; + UINT32 mapIndex = 0; + IX_STATUS status = IX_SUCCESS; + + IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT, + "Entering ixNpeDlNpeMgrImageLoad\n"); + + /* get base memory address of NPE from npeId */ + npeBaseAddress = ixNpeDlNpeMgrBaseAddressGet (npeId); + + /* check execution status of NPE to verify NPE Stop was successful */ + if (!ixNpeDlNpeMgrBitsSetCheck (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXCTL, + IX_NPEDL_EXCTL_STATUS_STOP)) + { + IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrImageDownload - " + "NPE was not stopped before download\n"); + status = IX_FAIL; + } + else + { + /* + * Read Download Map, checking each block type and calling + * appropriate function to perform download + */ + downloadMap = (IxNpeDlNpeMgrDownloadMap *) imageCodePtr; + while ((downloadMap->entry[mapIndex].eodmMarker != + IX_NPEDL_END_OF_DOWNLOAD_MAP) + && (status == IX_SUCCESS)) + { + /* calculate pointer to block to be downloaded */ + blockPtr = imageCodePtr + + downloadMap->entry[mapIndex].block.offset; + + switch (downloadMap->entry[mapIndex].block.type) + { + case IX_NPEDL_BLOCK_TYPE_INSTRUCTION: + status = ixNpeDlNpeMgrMemLoad (npeId, npeBaseAddress, + (IxNpeDlNpeMgrCodeBlock *)blockPtr, + verify, + IX_NPEDL_MEM_TYPE_INSTRUCTION); + break; + case IX_NPEDL_BLOCK_TYPE_DATA: + status = ixNpeDlNpeMgrMemLoad (npeId, npeBaseAddress, + (IxNpeDlNpeMgrCodeBlock *)blockPtr, + verify, IX_NPEDL_MEM_TYPE_DATA); + break; + case IX_NPEDL_BLOCK_TYPE_STATE: + status = ixNpeDlNpeMgrStateInfoLoad (npeBaseAddress, + (IxNpeDlNpeMgrStateInfoBlock *) blockPtr, + verify); + break; + default: + IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrImageLoad: " + "unknown block type in download map\n"); + status = IX_NPEDL_CRITICAL_MICROCODE_ERR; + ixNpeDlNpeMgrStats.criticalMicrocodeErrors++; + break; + } + mapIndex++; + }/* loop: for each entry in download map, while status == SUCCESS */ + }/* condition: NPE stopped before attempting download */ + + IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT, + "Exiting ixNpeDlNpeMgrImageLoad : status = %d\n", + status); + return status; +} + + +/* + * Function definition: ixNpeDlNpeMgrMemLoad + */ +PRIVATE IX_STATUS +ixNpeDlNpeMgrMemLoad ( + IxNpeDlNpeId npeId, + UINT32 npeBaseAddress, + IxNpeDlNpeMgrCodeBlock *blockPtr, + BOOL verify, + IxNpeDlNpeMemType npeMemType) +{ + UINT32 npeMemAddress; + UINT32 blockSize; + UINT32 memSize = 0; + IxNpeDlNpeMgrMemWrite memWriteFunc = NULL; + UINT32 localIndex = 0; + IX_STATUS status = IX_SUCCESS; + + IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT, + "Entering ixNpeDlNpeMgrMemLoad\n"); + + /* + * select NPE EXCTL reg read/write commands depending on memory + * type (instruction/data) to be accessed + */ + if (npeMemType == IX_NPEDL_MEM_TYPE_INSTRUCTION) + { + memSize = ixNpeDlNpeInfo[npeId].insMemSize; + memWriteFunc = (IxNpeDlNpeMgrMemWrite) ixNpeDlNpeMgrInsMemWrite; + } + else if (npeMemType == IX_NPEDL_MEM_TYPE_DATA) + { + memSize = ixNpeDlNpeInfo[npeId].dataMemSize; + memWriteFunc = (IxNpeDlNpeMgrMemWrite) ixNpeDlNpeMgrDataMemWrite; + } + + /* + * NPE memory is loaded contiguously from each block, so only address + * of 1st word in block is needed + */ + npeMemAddress = blockPtr->npeMemAddress; + /* number of words of instruction/data microcode in block to download */ + blockSize = blockPtr->size; + if ((npeMemAddress + blockSize) > memSize) + { + IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrMemLoad: " + "Block size too big for NPE memory\n"); + status = IX_NPEDL_CRITICAL_MICROCODE_ERR; + ixNpeDlNpeMgrStats.criticalMicrocodeErrors++; + } + else + { + for (localIndex = 0; localIndex < blockSize; localIndex++) + { + status = memWriteFunc (npeBaseAddress, npeMemAddress, + blockPtr->data[localIndex], verify); + + if (status != IX_SUCCESS) + { + IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrMemLoad: " + "write to NPE memory failed\n"); + status = IX_NPEDL_CRITICAL_NPE_ERR; + ixNpeDlNpeMgrStats.criticalNpeErrors++; + break; /* abort download */ + } + /* increment target (word)address in NPE memory */ + npeMemAddress++; + } + }/* condition: block size will fit in NPE memory */ + + if (status == IX_SUCCESS) + { + if (npeMemType == IX_NPEDL_MEM_TYPE_INSTRUCTION) + { + ixNpeDlNpeMgrStats.instructionBlocksLoaded++; + } + else if (npeMemType == IX_NPEDL_MEM_TYPE_DATA) + { + ixNpeDlNpeMgrStats.dataBlocksLoaded++; + } + } + + IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT, + "Exiting ixNpeDlNpeMgrMemLoad : status = %d\n", status); + return status; +} + + +/* + * Function definition: ixNpeDlNpeMgrStateInfoLoad + */ +PRIVATE IX_STATUS +ixNpeDlNpeMgrStateInfoLoad ( + UINT32 npeBaseAddress, + IxNpeDlNpeMgrStateInfoBlock *blockPtr, + BOOL verify) +{ + UINT32 blockSize; + UINT32 ctxtRegAddrInfo; + UINT32 ctxtRegVal; + IxNpeDlCtxtRegNum ctxtReg; /* identifies Context Store reg (0-3) */ + UINT32 ctxtNum; /* identifies Context number (0-16) */ + UINT32 i; + IX_STATUS status = IX_SUCCESS; + + IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT, + "Entering ixNpeDlNpeMgrStateInfoLoad\n"); + + /* block size contains number of words of state-info in block */ + blockSize = blockPtr->size; + + ixNpeDlNpeMgrDebugInstructionPreExec (npeBaseAddress); + + /* for each state-info context register entry in block */ + for (i = 0; i < (blockSize/IX_NPEDL_STATE_INFO_ENTRY_SIZE); i++) + { + /* each state-info entry is 2 words (address, value) in length */ + ctxtRegAddrInfo = (blockPtr->ctxtRegEntry[i]).addressInfo; + ctxtRegVal = (blockPtr->ctxtRegEntry[i]).value; + + ctxtReg = (ctxtRegAddrInfo & IX_NPEDL_MASK_STATE_ADDR_CTXT_REG); + ctxtNum = (ctxtRegAddrInfo & IX_NPEDL_MASK_STATE_ADDR_CTXT_NUM) >> + IX_NPEDL_OFFSET_STATE_ADDR_CTXT_NUM; + + /* error-check Context Register No. and Context Number values */ + /* NOTE that there is no STEVT register for Context 0 */ + if ((ctxtReg < 0) || + (ctxtReg >= IX_NPEDL_CTXT_REG_MAX) || + (ctxtNum > IX_NPEDL_CTXT_NUM_MAX) || + ((ctxtNum == 0) && (ctxtReg == IX_NPEDL_CTXT_REG_STEVT))) + { + IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrStateInfoLoad: " + "invalid Context Register Address\n"); + status = IX_NPEDL_CRITICAL_MICROCODE_ERR; + ixNpeDlNpeMgrStats.criticalMicrocodeErrors++; + break; /* abort download */ + } + + status = ixNpeDlNpeMgrCtxtRegWrite (npeBaseAddress, ctxtNum, ctxtReg, + ctxtRegVal, verify); + if (status != IX_SUCCESS) + { + IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrStateInfoLoad: " + "write of state-info to NPE failed\n"); + status = IX_NPEDL_CRITICAL_NPE_ERR; + ixNpeDlNpeMgrStats.criticalNpeErrors++; + break; /* abort download */ + } + }/* loop: for each context reg entry in State Info block */ + + ixNpeDlNpeMgrDebugInstructionPostExec (npeBaseAddress); + + if (status == IX_SUCCESS) + { + ixNpeDlNpeMgrStats.stateInfoBlocksLoaded++; + } + + IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT, + "Exiting ixNpeDlNpeMgrStateInfoLoad : status = %d\n", + status); + return status; +} + + +/* + * Function definition: ixNpeDlNpeMgrNpeReset + */ +IX_STATUS +ixNpeDlNpeMgrNpeReset ( + IxNpeDlNpeId npeId) +{ + UINT32 npeBaseAddress; + IxNpeDlCtxtRegNum ctxtReg; /* identifies Context Store reg (0-3) */ + UINT32 ctxtNum; /* identifies Context number (0-16) */ + UINT32 regAddr; + UINT32 regVal; + UINT32 localIndex; + UINT32 indexMax; + IX_STATUS status = IX_SUCCESS; + IxFeatureCtrlReg unitFuseReg; + UINT32 ixNpeConfigCtrlRegVal; + + IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT, + "Entering ixNpeDlNpeMgrNpeReset\n"); + + /* get base memory address of NPE from npeId */ + npeBaseAddress = ixNpeDlNpeMgrBaseAddressGet (npeId); + + /* pre-store the NPE Config Control Register Value */ + IX_NPEDL_REG_READ (npeBaseAddress, IX_NPEDL_REG_OFFSET_CTL, &ixNpeConfigCtrlRegVal); + + ixNpeConfigCtrlRegVal |= 0x3F000000; + + /* disable the parity interrupt */ + IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_CTL, (ixNpeConfigCtrlRegVal & IX_NPEDL_PARITY_BIT_MASK)); + + ixNpeDlNpeMgrDebugInstructionPreExec (npeBaseAddress); + + /* + * clear the FIFOs + */ + while (ixNpeDlNpeMgrBitsSetCheck (npeBaseAddress, + IX_NPEDL_REG_OFFSET_WFIFO, + IX_NPEDL_MASK_WFIFO_VALID)) + { + /* read from the Watch-point FIFO until empty */ + IX_NPEDL_REG_READ (npeBaseAddress, IX_NPEDL_REG_OFFSET_WFIFO, + ®Val); + } + + while (ixNpeDlNpeMgrBitsSetCheck (npeBaseAddress, + IX_NPEDL_REG_OFFSET_STAT, + IX_NPEDL_MASK_STAT_OFNE)) + { + /* read from the outFIFO until empty */ + IX_NPEDL_REG_READ (npeBaseAddress, IX_NPEDL_REG_OFFSET_FIFO, + ®Val); + } + + while (ixNpeDlNpeMgrBitsSetCheck (npeBaseAddress, + IX_NPEDL_REG_OFFSET_STAT, + IX_NPEDL_MASK_STAT_IFNE)) + { + /* + * step execution of the NPE intruction to read inFIFO using + * the Debug Executing Context stack + */ + status = ixNpeDlNpeMgrDebugInstructionExec (npeBaseAddress, + IX_NPEDL_INSTR_RD_FIFO, 0, 0); + + if (IX_SUCCESS != status) + { + return status; + } + + } + + /* + * Reset the mailbox reg + */ + /* ...from XScale side */ + IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_MBST, + IX_NPEDL_REG_RESET_MBST); + /* ...from NPE side */ + status = ixNpeDlNpeMgrDebugInstructionExec (npeBaseAddress, + IX_NPEDL_INSTR_RESET_MBOX, 0, 0); + + if (IX_SUCCESS != status) + { + return status; + } + + /* + * Reset the physical registers in the NPE register file: + * Note: no need to save/restore REGMAP for Context 0 here + * since all Context Store regs are reset in subsequent code + */ + for (regAddr = 0; + (regAddr < IX_NPEDL_TOTAL_NUM_PHYS_REG) && (status != IX_FAIL); + regAddr++) + { + /* for each physical register in the NPE reg file, write 0 : */ + status = ixNpeDlNpeMgrPhysicalRegWrite (npeBaseAddress, regAddr, + 0, TRUE); + if (status != IX_SUCCESS) + { + return status; /* abort reset */ + } + } + + + /* + * Reset the context store: + */ + for (ctxtNum = IX_NPEDL_CTXT_NUM_MIN; + ctxtNum <= IX_NPEDL_CTXT_NUM_MAX; ctxtNum++) + { + /* set each context's Context Store registers to reset values: */ + for (ctxtReg = 0; ctxtReg < IX_NPEDL_CTXT_REG_MAX; ctxtReg++) + { + /* NOTE that there is no STEVT register for Context 0 */ + if (!((ctxtNum == 0) && (ctxtReg == IX_NPEDL_CTXT_REG_STEVT))) + { + regVal = ixNpeDlCtxtRegResetValues[ctxtReg]; + status = ixNpeDlNpeMgrCtxtRegWrite (npeBaseAddress, ctxtNum, + ctxtReg, regVal, TRUE); + if (status != IX_SUCCESS) + { + return status; /* abort reset */ + } + } + } + } + + ixNpeDlNpeMgrDebugInstructionPostExec (npeBaseAddress); + + /* write Reset values to Execution Context Stack registers */ + indexMax = sizeof (ixNpeDlEcsRegResetValues) / + sizeof (IxNpeDlEcsRegResetValue); + for (localIndex = 0; localIndex < indexMax; localIndex++) + { + regAddr = ixNpeDlEcsRegResetValues[localIndex].regAddr; + regVal = ixNpeDlEcsRegResetValues[localIndex].regResetVal; + ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, regAddr, regVal); + } + + /* clear the profile counter */ + ixNpeDlNpeMgrCommandIssue (npeBaseAddress, + IX_NPEDL_EXCTL_CMD_CLR_PROFILE_CNT); + + /* clear registers EXCT, AP0, AP1, AP2 and AP3 */ + for (regAddr = IX_NPEDL_REG_OFFSET_EXCT; + regAddr <= IX_NPEDL_REG_OFFSET_AP3; + regAddr += IX_NPEDL_BYTES_PER_WORD) + { + IX_NPEDL_REG_WRITE (npeBaseAddress, regAddr, 0); + } + + /* Reset the Watch-count register */ + IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_WC, 0); + + /* + * WR IXA00055043 - Remove IMEM Parity Introduced by NPE Reset Operation + */ + + /* + * Call the feature control API to fused out and reset the NPE and its + * coprocessor - to reset internal states and remove parity error + */ + unitFuseReg = ixFeatureCtrlRead (); + unitFuseReg |= (IX_NPEDL_RESET_NPE_PARITY << npeId); + ixFeatureCtrlWrite (unitFuseReg); + + /* call the feature control API to un-fused and un-reset the NPE & COP */ + unitFuseReg &= (~(IX_NPEDL_RESET_NPE_PARITY << npeId)); + ixFeatureCtrlWrite (unitFuseReg); + + /* + * Call NpeMgr function to stop the NPE again after the Feature Control + * has unfused and Un-Reset the NPE and its associated Coprocessors + */ + status = ixNpeDlNpeMgrNpeStop (npeId); + + /* restore NPE configuration bus Control Register - Parity Settings */ + IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_CTL, + (ixNpeConfigCtrlRegVal & IX_NPEDL_CONFIG_CTRL_REG_MASK)); + + ixNpeDlNpeMgrStats.npeResets++; + + IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT, + "Exiting ixNpeDlNpeMgrNpeReset : status = %d\n", status); + return status; +} + + +/* + * Function definition: ixNpeDlNpeMgrNpeStart + */ +IX_STATUS +ixNpeDlNpeMgrNpeStart ( + IxNpeDlNpeId npeId) +{ + UINT32 npeBaseAddress; + UINT32 ecsRegVal; + BOOL npeRunning; + IX_STATUS status = IX_SUCCESS; + + IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT, + "Entering ixNpeDlNpeMgrNpeStart\n"); + + /* get base memory address of NPE from npeId */ + npeBaseAddress = ixNpeDlNpeMgrBaseAddressGet (npeId); + + /* + * ensure only Background Context Stack Level is Active by turning off + * the Active bit in each of the other Executing Context Stack levels + */ + ecsRegVal = ixNpeDlNpeMgrExecAccRegRead (npeBaseAddress, + IX_NPEDL_ECS_PRI_1_CTXT_REG_0); + ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE; + ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, IX_NPEDL_ECS_PRI_1_CTXT_REG_0, + ecsRegVal); + + ecsRegVal = ixNpeDlNpeMgrExecAccRegRead (npeBaseAddress, + IX_NPEDL_ECS_PRI_2_CTXT_REG_0); + ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE; + ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, IX_NPEDL_ECS_PRI_2_CTXT_REG_0, + ecsRegVal); + + ecsRegVal = ixNpeDlNpeMgrExecAccRegRead (npeBaseAddress, + IX_NPEDL_ECS_DBG_CTXT_REG_0); + ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE; + ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, IX_NPEDL_ECS_DBG_CTXT_REG_0, + ecsRegVal); + + /* clear the pipeline */ + ixNpeDlNpeMgrCommandIssue (npeBaseAddress, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE); + + /* start NPE execution by issuing command through EXCTL register on NPE */ + ixNpeDlNpeMgrCommandIssue (npeBaseAddress, IX_NPEDL_EXCTL_CMD_NPE_START); + + /* + * check execution status of NPE to verify NPE Start operation was + * successful + */ + npeRunning = ixNpeDlNpeMgrBitsSetCheck (npeBaseAddress, + IX_NPEDL_REG_OFFSET_EXCTL, + IX_NPEDL_EXCTL_STATUS_RUN); + if (npeRunning) + { + ixNpeDlNpeMgrStats.npeStarts++; + } + else + { + IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrNpeStart: " + "failed to start NPE execution\n"); + status = IX_FAIL; + } + + + IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT, + "Exiting ixNpeDlNpeMgrNpeStart : status = %d\n", status); + return status; +} + + +/* + * Function definition: ixNpeDlNpeMgrNpeStop + */ +IX_STATUS +ixNpeDlNpeMgrNpeStop ( + IxNpeDlNpeId npeId) +{ + UINT32 npeBaseAddress; + IX_STATUS status = IX_SUCCESS; + + IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT, + "Entering ixNpeDlNpeMgrNpeStop\n"); + + /* get base memory address of NPE from npeId */ + npeBaseAddress = ixNpeDlNpeMgrBaseAddressGet (npeId); + + /* stop NPE execution by issuing command through EXCTL register on NPE */ + ixNpeDlNpeMgrCommandIssue (npeBaseAddress, IX_NPEDL_EXCTL_CMD_NPE_STOP); + + /* verify that NPE Stop was successful */ + if (! ixNpeDlNpeMgrBitsSetCheck (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXCTL, + IX_NPEDL_EXCTL_STATUS_STOP)) + { + IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrNpeStop: " + "failed to stop NPE execution\n"); + status = IX_FAIL; + } + + ixNpeDlNpeMgrStats.npeStops++; + + IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT, + "Exiting ixNpeDlNpeMgrNpeStop : status = %d\n", status); + return status; +} + + +/* + * Function definition: ixNpeDlNpeMgrBitsSetCheck + */ +PRIVATE BOOL +ixNpeDlNpeMgrBitsSetCheck ( + UINT32 npeBaseAddress, + UINT32 regOffset, + UINT32 expectedBitsSet) +{ + UINT32 regVal; + IX_NPEDL_REG_READ (npeBaseAddress, regOffset, ®Val); + + return expectedBitsSet == (expectedBitsSet & regVal); +} + + +/* + * Function definition: ixNpeDlNpeMgrStatsShow + */ +void +ixNpeDlNpeMgrStatsShow (void) +{ + ixOsalLog (IX_OSAL_LOG_LVL_USER, + IX_OSAL_LOG_DEV_STDOUT, + "\nixNpeDlNpeMgrStatsShow:\n" + "\tInstruction Blocks loaded: %u\n" + "\tData Blocks loaded: %u\n" + "\tState Information Blocks loaded: %u\n" + "\tCritical NPE errors: %u\n" + "\tCritical Microcode errors: %u\n", + ixNpeDlNpeMgrStats.instructionBlocksLoaded, + ixNpeDlNpeMgrStats.dataBlocksLoaded, + ixNpeDlNpeMgrStats.stateInfoBlocksLoaded, + ixNpeDlNpeMgrStats.criticalNpeErrors, + ixNpeDlNpeMgrStats.criticalMicrocodeErrors, + 0); + + ixOsalLog (IX_OSAL_LOG_LVL_USER, + IX_OSAL_LOG_DEV_STDOUT, + "\tSuccessful NPE Starts: %u\n" + "\tSuccessful NPE Stops: %u\n" + "\tSuccessful NPE Resets: %u\n\n", + ixNpeDlNpeMgrStats.npeStarts, + ixNpeDlNpeMgrStats.npeStops, + ixNpeDlNpeMgrStats.npeResets, + 0,0,0); + + ixNpeDlNpeMgrUtilsStatsShow (); +} + + +/* + * Function definition: ixNpeDlNpeMgrStatsReset + */ +void +ixNpeDlNpeMgrStatsReset (void) +{ + ixNpeDlNpeMgrStats.instructionBlocksLoaded = 0; + ixNpeDlNpeMgrStats.dataBlocksLoaded = 0; + ixNpeDlNpeMgrStats.stateInfoBlocksLoaded = 0; + ixNpeDlNpeMgrStats.criticalNpeErrors = 0; + ixNpeDlNpeMgrStats.criticalMicrocodeErrors = 0; + ixNpeDlNpeMgrStats.npeStarts = 0; + ixNpeDlNpeMgrStats.npeStops = 0; + ixNpeDlNpeMgrStats.npeResets = 0; + + ixNpeDlNpeMgrUtilsStatsReset (); +} diff --git a/cpu/ixp/npe/IxNpeDlNpeMgrUtils.c b/cpu/ixp/npe/IxNpeDlNpeMgrUtils.c new file mode 100644 index 0000000..9dcf3c1 --- /dev/null +++ b/cpu/ixp/npe/IxNpeDlNpeMgrUtils.c @@ -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; +} diff --git a/cpu/ixp/npe/IxNpeMh.c b/cpu/ixp/npe/IxNpeMh.c new file mode 100644 index 0000000..8703def --- /dev/null +++ b/cpu/ixp/npe/IxNpeMh.c @@ -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; +} diff --git a/cpu/ixp/npe/IxNpeMhConfig.c b/cpu/ixp/npe/IxNpeMhConfig.c new file mode 100644 index 0000000..50c8f21 --- /dev/null +++ b/cpu/ixp/npe/IxNpeMhConfig.c @@ -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; +} + + diff --git a/cpu/ixp/npe/IxNpeMhReceive.c b/cpu/ixp/npe/IxNpeMhReceive.c new file mode 100644 index 0000000..57c8be3 --- /dev/null +++ b/cpu/ixp/npe/IxNpeMhReceive.c @@ -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; +} diff --git a/cpu/ixp/npe/IxNpeMhSend.c b/cpu/ixp/npe/IxNpeMhSend.c new file mode 100644 index 0000000..318913a --- /dev/null +++ b/cpu/ixp/npe/IxNpeMhSend.c @@ -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; +} diff --git a/cpu/ixp/npe/IxNpeMhSolicitedCbMgr.c b/cpu/ixp/npe/IxNpeMhSolicitedCbMgr.c new file mode 100644 index 0000000..8e083a6 --- /dev/null +++ b/cpu/ixp/npe/IxNpeMhSolicitedCbMgr.c @@ -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; +} diff --git a/cpu/ixp/npe/IxNpeMhUnsolicitedCbMgr.c b/cpu/ixp/npe/IxNpeMhUnsolicitedCbMgr.c new file mode 100644 index 0000000..d37f9f9 --- /dev/null +++ b/cpu/ixp/npe/IxNpeMhUnsolicitedCbMgr.c @@ -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; +} diff --git a/cpu/ixp/npe/IxOsalBufferMgt.c b/cpu/ixp/npe/IxOsalBufferMgt.c new file mode 100644 index 0000000..fa8db47 --- /dev/null +++ b/cpu/ixp/npe/IxOsalBufferMgt.c @@ -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 */ diff --git a/cpu/ixp/npe/IxOsalIoMem.c b/cpu/ixp/npe/IxOsalIoMem.c new file mode 100644 index 0000000..9e540c1 --- /dev/null +++ b/cpu/ixp/npe/IxOsalIoMem.c @@ -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); + } +} diff --git a/cpu/ixp/npe/IxOsalOsCacheMMU.c b/cpu/ixp/npe/IxOsalOsCacheMMU.c new file mode 100644 index 0000000..3db1a70 --- /dev/null +++ b/cpu/ixp/npe/IxOsalOsCacheMMU.c @@ -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 + +/* + * 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); +} diff --git a/cpu/ixp/npe/IxOsalOsMsgQ.c b/cpu/ixp/npe/IxOsalOsMsgQ.c new file mode 100644 index 0000000..45a5c68 --- /dev/null +++ b/cpu/ixp/npe/IxOsalOsMsgQ.c @@ -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; +} + diff --git a/cpu/ixp/npe/IxOsalOsSemaphore.c b/cpu/ixp/npe/IxOsalOsSemaphore.c new file mode 100644 index 0000000..443aefd --- /dev/null +++ b/cpu/ixp/npe/IxOsalOsSemaphore.c @@ -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); +} diff --git a/cpu/ixp/npe/IxOsalOsServices.c b/cpu/ixp/npe/IxOsalOsServices.c new file mode 100644 index 0000000..e18c6c4 --- /dev/null +++ b/cpu/ixp/npe/IxOsalOsServices.c @@ -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 +#include +#include "IxOsal.h" +#include +#include +#include +#include +#include + +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)); +} diff --git a/cpu/ixp/npe/IxOsalOsThread.c b/cpu/ixp/npe/IxOsalOsThread.c new file mode 100644 index 0000000..e6a4967 --- /dev/null +++ b/cpu/ixp/npe/IxOsalOsThread.c @@ -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; +} diff --git a/cpu/ixp/npe/IxQMgrAqmIf.c b/cpu/ixp/npe/IxQMgrAqmIf.c new file mode 100644 index 0000000..b27b3a2 --- /dev/null +++ b/cpu/ixp/npe/IxQMgrAqmIf.c @@ -0,0 +1,963 @@ +/* + * @file: IxQMgrAqmIf.c + * + * @author Intel Corporation + * @date 30-Oct-2001 + * + * @brief This component provides a set of functions for + * perfoming I/O on the AQM hardware. + * + * Design Notes: + * These functions are intended to be as fast as possible + * and as a result perform NO PARAMETER CHECKING. + * + * + * @par + * IXP400 SW Release version 2.0 + * + * -- Copyright Notice -- + * + * @par + * Copyright 2001-2005, Intel Corporation. + * All rights reserved. + * + * @par + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * @par + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @par + * -- End of Copyright Notice -- +*/ + +/* + * Inlines are compiled as function when this is defined. + * N.B. Must be placed before #include of "IxQMgrAqmIf_p.h + */ +#ifndef IXQMGRAQMIF_P_H +# define IXQMGRAQMIF_C +#else +# error +#endif + +/* + * User defined include files. + */ +#include "IxOsal.h" +#include "IxQMgr.h" +#include "IxQMgrAqmIf_p.h" +#include "IxQMgrLog_p.h" + + +/* + * #defines and macros used in this file. + */ + +/* These defines are the bit offsets of the various fields of + * the queue configuration register + */ +#define IX_QMGR_Q_CONFIG_WRPTR_OFFSET 0x00 +#define IX_QMGR_Q_CONFIG_RDPTR_OFFSET 0x07 +#define IX_QMGR_Q_CONFIG_BADDR_OFFSET 0x0E +#define IX_QMGR_Q_CONFIG_ESIZE_OFFSET 0x16 +#define IX_QMGR_Q_CONFIG_BSIZE_OFFSET 0x18 +#define IX_QMGR_Q_CONFIG_NE_OFFSET 0x1A +#define IX_QMGR_Q_CONFIG_NF_OFFSET 0x1D + +#define IX_QMGR_BASE_ADDR_16_WORD_ALIGN 0x40 +#define IX_QMGR_BASE_ADDR_16_WORD_SHIFT 0x6 + +#define IX_QMGR_NE_NF_CLEAR_MASK 0x03FFFFFF +#define IX_QMGR_NE_MASK 0x7 +#define IX_QMGR_NF_MASK 0x7 +#define IX_QMGR_SIZE_MASK 0x3 +#define IX_QMGR_ENTRY_SIZE_MASK 0x3 +#define IX_QMGR_BADDR_MASK 0x003FC000 +#define IX_QMGR_RDPTR_MASK 0x7F +#define IX_QMGR_WRPTR_MASK 0x7F +#define IX_QMGR_RDWRPTR_MASK 0x00003FFF + +#define IX_QMGR_AQM_ADDRESS_SPACE_SIZE_IN_WORDS 0x1000 + +/* Base address of AQM SRAM */ +#define IX_QMGR_AQM_SRAM_BASE_ADDRESS_OFFSET \ +((IX_QMGR_QUECONFIG_BASE_OFFSET) + (IX_QMGR_QUECONFIG_SIZE)) + +/* Min buffer size used for generating buffer size in QUECONFIG */ +#define IX_QMGR_MIN_BUFFER_SIZE 16 + +/* Reset values of QMgr hardware registers */ +#define IX_QMGR_QUELOWSTAT_RESET_VALUE 0x33333333 +#define IX_QMGR_QUEUOSTAT_RESET_VALUE 0x00000000 +#define IX_QMGR_QUEUPPSTAT0_RESET_VALUE 0xFFFFFFFF +#define IX_QMGR_QUEUPPSTAT1_RESET_VALUE 0x00000000 +#define IX_QMGR_INT0SRCSELREG_RESET_VALUE 0x00000000 +#define IX_QMGR_QUEIEREG_RESET_VALUE 0x00000000 +#define IX_QMGR_QINTREG_RESET_VALUE 0xFFFFFFFF +#define IX_QMGR_QUECONFIG_RESET_VALUE 0x00000000 + +#define IX_QMGR_PHYSICAL_AQM_BASE_ADDRESS IX_OSAL_IXP400_QMGR_PHYS_BASE + +#define IX_QMGR_QUELOWSTAT_BITS_PER_Q (BITS_PER_WORD/IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD) + +#define IX_QMGR_QUELOWSTAT_QID_MASK 0x7 +#define IX_QMGR_Q_CONFIG_ADDR_GET(qId)\ + (((qId) * IX_QMGR_NUM_BYTES_PER_WORD) +\ + IX_QMGR_QUECONFIG_BASE_OFFSET) + +#define IX_QMGR_ENTRY1_OFFSET 0 +#define IX_QMGR_ENTRY2_OFFSET 1 +#define IX_QMGR_ENTRY4_OFFSET 3 + +/* + * Variable declarations global to this file. Externs are followed by + * statics. + */ +UINT32 aqmBaseAddress = 0; +/* Store addresses and bit-masks for certain queue access and status registers. + * This is to facilitate inlining of QRead, QWrite and QStatusGet functions + * in IxQMgr,h + */ +extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[]; +UINT32 * ixQMgrAqmIfQueAccRegAddr[IX_QMGR_MAX_NUM_QUEUES]; +UINT32 ixQMgrAqmIfQueLowStatRegAddr[IX_QMGR_MIN_QUEUPP_QID]; +UINT32 ixQMgrAqmIfQueLowStatBitsOffset[IX_QMGR_MIN_QUEUPP_QID]; +UINT32 ixQMgrAqmIfQueLowStatBitsMask; +UINT32 ixQMgrAqmIfQueUppStat0RegAddr; +UINT32 ixQMgrAqmIfQueUppStat1RegAddr; +UINT32 ixQMgrAqmIfQueUppStat0BitMask[IX_QMGR_MIN_QUEUPP_QID]; +UINT32 ixQMgrAqmIfQueUppStat1BitMask[IX_QMGR_MIN_QUEUPP_QID]; + +/* + * Fast mutexes, one for each queue, used to protect peek & poke functions + */ +IxOsalFastMutex ixQMgrAqmIfPeekPokeFastMutex[IX_QMGR_MAX_NUM_QUEUES]; + +/* + * Function prototypes + */ +PRIVATE unsigned +watermarkToAqmWatermark (IxQMgrWMLevel watermark ); + +PRIVATE unsigned +entrySizeToAqmEntrySize (IxQMgrQEntrySizeInWords entrySize); + +PRIVATE unsigned +bufferSizeToAqmBufferSize (unsigned bufferSizeInWords); + +PRIVATE void +ixQMgrAqmIfRegistersReset (void); + +PRIVATE void +ixQMgrAqmIfEntryAddressGet (unsigned int entryIndex, + UINT32 configRegWord, + unsigned int qEntrySizeInwords, + unsigned int qSizeInWords, + UINT32 **address); +/* + * Function definitions + */ +void +ixQMgrAqmIfInit (void) +{ + UINT32 aqmVirtualAddr; + int i; + + /* The value of aqmBaseAddress depends on the logical address + * assigned by the MMU. + */ + aqmVirtualAddr = + (UINT32) IX_OSAL_MEM_MAP(IX_QMGR_PHYSICAL_AQM_BASE_ADDRESS, + IX_OSAL_IXP400_QMGR_MAP_SIZE); + IX_OSAL_ASSERT (aqmVirtualAddr); + + ixQMgrAqmIfBaseAddressSet (aqmVirtualAddr); + + ixQMgrAqmIfRegistersReset (); + + for (i = 0; i< IX_QMGR_MAX_NUM_QUEUES; i++) + { + ixOsalFastMutexInit(&ixQMgrAqmIfPeekPokeFastMutex[i]); + + /******************************************************************** + * Register addresses and bit masks are calculated and stored here to + * facilitate inlining of QRead, QWrite and QStatusGet functions in + * IxQMgr.h. + * These calculations are normally performed dynamically in inlined + * functions in IxQMgrAqmIf_p.h, and their semantics are reused here. + */ + + /* AQM Queue access reg addresses, per queue */ + ixQMgrAqmIfQueAccRegAddr[i] = + (UINT32 *)(aqmBaseAddress + IX_QMGR_Q_ACCESS_ADDR_GET(i)); + ixQMgrQInlinedReadWriteInfo[i].qAccRegAddr = + (volatile UINT32 *)(aqmBaseAddress + IX_QMGR_Q_ACCESS_ADDR_GET(i)); + + + ixQMgrQInlinedReadWriteInfo[i].qConfigRegAddr = + (volatile UINT32 *)(aqmBaseAddress + IX_QMGR_Q_CONFIG_ADDR_GET(i)); + + /* AQM Queue lower-group (0-31), only */ + if (i < IX_QMGR_MIN_QUEUPP_QID) + { + /* AQM Q underflow/overflow status register addresses, per queue */ + ixQMgrQInlinedReadWriteInfo[i].qUOStatRegAddr = + (volatile UINT32 *)(aqmBaseAddress + + IX_QMGR_QUEUOSTAT0_OFFSET + + ((i / IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD) * + IX_QMGR_NUM_BYTES_PER_WORD)); + + /* AQM Q underflow status bit masks for status register per queue */ + ixQMgrQInlinedReadWriteInfo[i].qUflowStatBitMask = + (IX_QMGR_UNDERFLOW_BIT_OFFSET + 1) << + ((i & (IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD - 1)) * + (BITS_PER_WORD / IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD)); + + /* AQM Q overflow status bit masks for status register, per queue */ + ixQMgrQInlinedReadWriteInfo[i].qOflowStatBitMask = + (IX_QMGR_OVERFLOW_BIT_OFFSET + 1) << + ((i & (IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD - 1)) * + (BITS_PER_WORD / IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD)); + + /* AQM Q lower-group (0-31) status register addresses, per queue */ + ixQMgrAqmIfQueLowStatRegAddr[i] = aqmBaseAddress + + IX_QMGR_QUELOWSTAT0_OFFSET + + ((i / IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD) * + IX_QMGR_NUM_BYTES_PER_WORD); + + /* AQM Q lower-group (0-31) status register bit offset */ + ixQMgrAqmIfQueLowStatBitsOffset[i] = + (i & (IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD - 1)) * + (BITS_PER_WORD / IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD); + } + else /* AQM Q upper-group (32-63), only */ + { + /* AQM Q upper-group (32-63) Nearly Empty status reg bit masks */ + ixQMgrAqmIfQueUppStat0BitMask[i - IX_QMGR_MIN_QUEUPP_QID] = + (1 << (i - IX_QMGR_MIN_QUEUPP_QID)); + + /* AQM Q upper-group (32-63) Full status register bit masks */ + ixQMgrAqmIfQueUppStat1BitMask[i - IX_QMGR_MIN_QUEUPP_QID] = + (1 << (i - IX_QMGR_MIN_QUEUPP_QID)); + } + } + + /* AQM Q lower-group (0-31) status register bit mask */ + ixQMgrAqmIfQueLowStatBitsMask = (1 << + (BITS_PER_WORD / + IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD)) - 1; + + /* AQM Q upper-group (32-63) Nearly Empty status register address */ + ixQMgrAqmIfQueUppStat0RegAddr = aqmBaseAddress + IX_QMGR_QUEUPPSTAT0_OFFSET; + + /* AQM Q upper-group (32-63) Full status register address */ + ixQMgrAqmIfQueUppStat1RegAddr = aqmBaseAddress + IX_QMGR_QUEUPPSTAT1_OFFSET; +} + +/* + * Uninitialise the AqmIf module by unmapping memory, etc + */ +void +ixQMgrAqmIfUninit (void) +{ + UINT32 virtAddr; + + ixQMgrAqmIfBaseAddressGet (&virtAddr); + IX_OSAL_MEM_UNMAP (virtAddr); + ixQMgrAqmIfBaseAddressSet (0); +} + +/* + * Set the the logical base address of AQM + */ +void +ixQMgrAqmIfBaseAddressSet (UINT32 address) +{ + aqmBaseAddress = address; +} + +/* + * Get the logical base address of AQM + */ +void +ixQMgrAqmIfBaseAddressGet (UINT32 *address) +{ + *address = aqmBaseAddress; +} + +/* + * Get the logical base address of AQM SRAM + */ +void +ixQMgrAqmIfSramBaseAddressGet (UINT32 *address) +{ + *address = aqmBaseAddress + + IX_QMGR_AQM_SRAM_BASE_ADDRESS_OFFSET; +} + +/* + * This function will write the status bits of a queue + * specified by qId. + */ +void +ixQMgrAqmIfQRegisterBitsWrite (IxQMgrQId qId, + UINT32 registerBaseAddrOffset, + unsigned queuesPerRegWord, + UINT32 value) +{ + volatile UINT32 *registerAddress; + UINT32 registerWord; + UINT32 statusBitsMask; + UINT32 bitsPerQueue; + + bitsPerQueue = BITS_PER_WORD / queuesPerRegWord; + + /* + * Calculate the registerAddress + * multiple queues split accross registers + */ + registerAddress = (UINT32*)(aqmBaseAddress + + registerBaseAddrOffset + + ((qId / queuesPerRegWord) * + IX_QMGR_NUM_BYTES_PER_WORD)); + + /* Read the current data */ + ixQMgrAqmIfWordRead (registerAddress, ®isterWord); + + + if( (registerBaseAddrOffset == IX_QMGR_INT0SRCSELREG0_OFFSET) && + (qId == IX_QMGR_QUEUE_0) ) + { + statusBitsMask = 0x7 ; + + /* Queue 0 at INT0SRCSELREG should not corrupt the value bit-3 */ + value &= 0x7 ; + } + else + { + /* Calculate the mask for the status bits for this queue. */ + statusBitsMask = ((1 << bitsPerQueue) - 1); + statusBitsMask <<= ((qId & (queuesPerRegWord - 1)) * bitsPerQueue); + + /* Mask out bits in value that would overwrite other q data */ + value <<= ((qId & (queuesPerRegWord - 1)) * bitsPerQueue); + value &= statusBitsMask; + } + + /* Mask out bits to write to */ + registerWord &= ~statusBitsMask; + + + /* Set the write bits */ + registerWord |= value; + + /* + * Write the data + */ + ixQMgrAqmIfWordWrite (registerAddress, registerWord); +} + +/* + * This function generates the parameters that can be used to + * check if a Qs status matches the specified source select. + * It calculates which status word to check (statusWordOffset), + * the value to check the status against (checkValue) and the + * mask (mask) to mask out all but the bits to check in the status word. + */ +void +ixQMgrAqmIfQStatusCheckValsCalc (IxQMgrQId qId, + IxQMgrSourceId srcSel, + unsigned int *statusWordOffset, + UINT32 *checkValue, + UINT32 *mask) +{ + UINT32 shiftVal; + + if (qId < IX_QMGR_MIN_QUEUPP_QID) + { + switch (srcSel) + { + case IX_QMGR_Q_SOURCE_ID_E: + *checkValue = IX_QMGR_Q_STATUS_E_BIT_MASK; + *mask = IX_QMGR_Q_STATUS_E_BIT_MASK; + break; + case IX_QMGR_Q_SOURCE_ID_NE: + *checkValue = IX_QMGR_Q_STATUS_NE_BIT_MASK; + *mask = IX_QMGR_Q_STATUS_NE_BIT_MASK; + break; + case IX_QMGR_Q_SOURCE_ID_NF: + *checkValue = IX_QMGR_Q_STATUS_NF_BIT_MASK; + *mask = IX_QMGR_Q_STATUS_NF_BIT_MASK; + break; + case IX_QMGR_Q_SOURCE_ID_F: + *checkValue = IX_QMGR_Q_STATUS_F_BIT_MASK; + *mask = IX_QMGR_Q_STATUS_F_BIT_MASK; + break; + case IX_QMGR_Q_SOURCE_ID_NOT_E: + *checkValue = 0; + *mask = IX_QMGR_Q_STATUS_E_BIT_MASK; + break; + case IX_QMGR_Q_SOURCE_ID_NOT_NE: + *checkValue = 0; + *mask = IX_QMGR_Q_STATUS_NE_BIT_MASK; + break; + case IX_QMGR_Q_SOURCE_ID_NOT_NF: + *checkValue = 0; + *mask = IX_QMGR_Q_STATUS_NF_BIT_MASK; + break; + case IX_QMGR_Q_SOURCE_ID_NOT_F: + *checkValue = 0; + *mask = IX_QMGR_Q_STATUS_F_BIT_MASK; + break; + default: + /* Should never hit */ + IX_OSAL_ASSERT(0); + break; + } + + /* One nibble of status per queue so need to shift the + * check value and mask out to the correct position. + */ + shiftVal = (qId % IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD) * + IX_QMGR_QUELOWSTAT_BITS_PER_Q; + + /* Calculate the which status word to check from the qId, + * 8 Qs status per word + */ + *statusWordOffset = qId / IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD; + + *checkValue <<= shiftVal; + *mask <<= shiftVal; + } + else + { + /* One status word */ + *statusWordOffset = 0; + /* Single bits per queue and int source bit hardwired NE, + * Qs start at 32. + */ + *mask = 1 << (qId - IX_QMGR_MIN_QUEUPP_QID); + *checkValue = *mask; + } +} + +void +ixQMgrAqmIfQInterruptEnable (IxQMgrQId qId) +{ + volatile UINT32 *registerAddress; + UINT32 registerWord; + UINT32 actualBitOffset; + + if (qId < IX_QMGR_MIN_QUEUPP_QID) + { + registerAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_QUEIEREG0_OFFSET); + } + else + { + registerAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_QUEIEREG1_OFFSET); + } + + actualBitOffset = 1 << (qId % IX_QMGR_MIN_QUEUPP_QID); + + ixQMgrAqmIfWordRead (registerAddress, ®isterWord); + ixQMgrAqmIfWordWrite (registerAddress, (registerWord | actualBitOffset)); +} + +void +ixQMgrAqmIfQInterruptDisable (IxQMgrQId qId) +{ + volatile UINT32 *registerAddress; + UINT32 registerWord; + UINT32 actualBitOffset; + + if (qId < IX_QMGR_MIN_QUEUPP_QID) + { + registerAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_QUEIEREG0_OFFSET); + } + else + { + registerAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_QUEIEREG1_OFFSET); + } + + actualBitOffset = 1 << (qId % IX_QMGR_MIN_QUEUPP_QID); + + ixQMgrAqmIfWordRead (registerAddress, ®isterWord); + ixQMgrAqmIfWordWrite (registerAddress, registerWord & (~actualBitOffset)); +} + +void +ixQMgrAqmIfQueCfgWrite (IxQMgrQId qId, + IxQMgrQSizeInWords qSizeInWords, + IxQMgrQEntrySizeInWords entrySizeInWords, + UINT32 freeSRAMAddress) +{ + volatile UINT32 *cfgAddress = NULL; + UINT32 qCfg = 0; + UINT32 baseAddress = 0; + unsigned aqmEntrySize = 0; + unsigned aqmBufferSize = 0; + + /* Build config register */ + aqmEntrySize = entrySizeToAqmEntrySize (entrySizeInWords); + qCfg |= (aqmEntrySize&IX_QMGR_ENTRY_SIZE_MASK) << + IX_QMGR_Q_CONFIG_ESIZE_OFFSET; + + aqmBufferSize = bufferSizeToAqmBufferSize (qSizeInWords); + qCfg |= (aqmBufferSize&IX_QMGR_SIZE_MASK) << IX_QMGR_Q_CONFIG_BSIZE_OFFSET; + + /* baseAddress, calculated relative to aqmBaseAddress and start address */ + baseAddress = freeSRAMAddress - + (aqmBaseAddress + IX_QMGR_QUECONFIG_BASE_OFFSET); + + /* Verify base address aligned to a 16 word boundary */ + if ((baseAddress % IX_QMGR_BASE_ADDR_16_WORD_ALIGN) != 0) + { + IX_QMGR_LOG_ERROR0("ixQMgrAqmIfQueCfgWrite () address is not on 16 word boundary\n"); + } + /* Now convert it to a 16 word pointer as required by QUECONFIG register */ + baseAddress >>= IX_QMGR_BASE_ADDR_16_WORD_SHIFT; + + + qCfg |= (baseAddress << IX_QMGR_Q_CONFIG_BADDR_OFFSET); + + + cfgAddress = (UINT32*)(aqmBaseAddress + + IX_QMGR_Q_CONFIG_ADDR_GET(qId)); + + + /* NOTE: High and Low watermarks are set to zero */ + ixQMgrAqmIfWordWrite (cfgAddress, qCfg); +} + +void +ixQMgrAqmIfQueCfgRead (IxQMgrQId qId, + unsigned int numEntries, + UINT32 *baseAddress, + unsigned int *ne, + unsigned int *nf, + UINT32 *readPtr, + UINT32 *writePtr) +{ + UINT32 qcfg; + UINT32 *cfgAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_Q_CONFIG_ADDR_GET(qId)); + unsigned int qEntrySizeInwords; + unsigned int qSizeInWords; + UINT32 *readPtr_ = NULL; + + /* Read the queue configuration register */ + ixQMgrAqmIfWordRead (cfgAddress, &qcfg); + + /* Extract the base address */ + *baseAddress = (UINT32)((qcfg & IX_QMGR_BADDR_MASK) >> + (IX_QMGR_Q_CONFIG_BADDR_OFFSET)); + + /* Base address is a 16 word pointer from the start of AQM SRAM. + * Convert to absolute word address. + */ + *baseAddress <<= IX_QMGR_BASE_ADDR_16_WORD_SHIFT; + *baseAddress += (UINT32)IX_QMGR_QUECONFIG_BASE_OFFSET; + + /* + * Extract the watermarks. 0->0 entries, 1->1 entries, 2->2 entries, 3->4 entries...... + * If ne > 0 ==> neInEntries = 2^(ne - 1) + * If ne == 0 ==> neInEntries = 0 + * The same applies. + */ + *ne = ((qcfg) >> (IX_QMGR_Q_CONFIG_NE_OFFSET)) & IX_QMGR_NE_MASK; + *nf = ((qcfg) >> (IX_QMGR_Q_CONFIG_NF_OFFSET)) & IX_QMGR_NF_MASK; + + if (0 != *ne) + { + *ne = 1 << (*ne - 1); + } + if (0 != *nf) + { + *nf = 1 << (*nf - 1); + } + + /* Get the queue entry size in words */ + qEntrySizeInwords = ixQMgrQEntrySizeInWordsGet (qId); + + /* Get the queue size in words */ + qSizeInWords = ixQMgrQSizeInWordsGet (qId); + + ixQMgrAqmIfEntryAddressGet (0/* Entry 0. i.e the readPtr*/, + qcfg, + qEntrySizeInwords, + qSizeInWords, + &readPtr_); + *readPtr = (UINT32)readPtr_; + *readPtr -= (UINT32)aqmBaseAddress;/* Offset, not absolute address */ + + *writePtr = (qcfg >> IX_QMGR_Q_CONFIG_WRPTR_OFFSET) & IX_QMGR_WRPTR_MASK; + *writePtr = *baseAddress + (*writePtr * (IX_QMGR_NUM_BYTES_PER_WORD)); + return; +} + +unsigned +ixQMgrAqmIfLog2 (unsigned number) +{ + unsigned count = 0; + + /* + * N.B. this function will return 0 + * for ixQMgrAqmIfLog2 (0) + */ + while (number/2) + { + number /=2; + count++; + } + + return count; +} + +void ixQMgrAqmIfIntSrcSelReg0Bit3Set (void) +{ + + volatile UINT32 *registerAddress; + UINT32 registerWord; + + /* + * Calculate the registerAddress + * multiple queues split accross registers + */ + registerAddress = (UINT32*)(aqmBaseAddress + + IX_QMGR_INT0SRCSELREG0_OFFSET); + + /* Read the current data */ + ixQMgrAqmIfWordRead (registerAddress, ®isterWord); + + /* Set the write bits */ + registerWord |= (1<> + (IX_QMGR_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++; + } +} + diff --git a/cpu/ixp/npe/IxQMgrDispatcher.c b/cpu/ixp/npe/IxQMgrDispatcher.c new file mode 100644 index 0000000..09f69ce --- /dev/null +++ b/cpu/ixp/npe/IxQMgrDispatcher.c @@ -0,0 +1,1347 @@ +/** + * @file IxQMgrDispatcher.c + * + * @author Intel Corporation + * @date 20-Dec-2001 + * + * @brief This file contains the implementation of the Dispatcher sub 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 -- +*/ + +/* + * User defined include files. + */ +#include "IxQMgr.h" +#include "IxQMgrAqmIf_p.h" +#include "IxQMgrQCfg_p.h" +#include "IxQMgrDispatcher_p.h" +#include "IxQMgrLog_p.h" +#include "IxQMgrDefines_p.h" +#include "IxFeatureCtrl.h" +#include "IxOsal.h" + + + +/* + * #defines and macros used in this file. + */ + + +/* + * This constant is used to indicate the number of priority levels supported + */ +#define IX_QMGR_NUM_PRIORITY_LEVELS 3 + +/* + * This constant is used to set the size of the array of status words + */ +#define MAX_Q_STATUS_WORDS 4 + +/* + * This macro is used to check if a given priority is valid + */ +#define IX_QMGR_DISPATCHER_PRIORITY_CHECK(priority) \ +(((priority) >= IX_QMGR_Q_PRIORITY_0) && ((priority) <= IX_QMGR_Q_PRIORITY_2)) + +/* + * This macto is used to check that a given interrupt source is valid + */ +#define IX_QMGR_DISPATCHER_SOURCE_ID_CHECK(srcSel) \ +(((srcSel) >= IX_QMGR_Q_SOURCE_ID_E) && ((srcSel) <= IX_QMGR_Q_SOURCE_ID_NOT_F)) + +/* + * Number of times a dummy callback is called before logging a trace + * message + */ +#define LOG_THROTTLE_COUNT 1000000 + +/* Priority tables limits */ +#define IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX (0) +#define IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX (16) +#define IX_QMGR_MAX_LOW_QUE_PRIORITY_TABLE_INDEX (31) +#define IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX (32) +#define IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX (48) +#define IX_QMGR_MAX_UPP_QUE_PRIORITY_TABLE_INDEX (63) + +/* + * This macro is used to check if a given callback type is valid + */ +#define IX_QMGR_DISPATCHER_CALLBACK_TYPE_CHECK(type) \ + (((type) >= IX_QMGR_TYPE_REALTIME_OTHER) && \ + ((type) <= IX_QMGR_TYPE_REALTIME_SPORADIC)) + +/* + * define max index in lower queue to use in loops + */ +#define IX_QMGR_MAX_LOW_QUE_TABLE_INDEX (31) + +/* + * Typedefs whose scope is limited to this file. + */ + +/* + * Information on a queue needed by the Dispatcher + */ +typedef struct +{ + IxQMgrCallback callback; /* Notification callback */ + IxQMgrCallbackId callbackId; /* Notification callback identifier */ + unsigned dummyCallbackCount; /* Number of times runs of dummy callback */ + IxQMgrPriority priority; /* Dispatch priority */ + unsigned int statusWordOffset; /* Offset to the status word to check */ + UINT32 statusMask; /* Status mask */ + UINT32 statusCheckValue; /* Status check value */ + UINT32 intRegCheckMask; /* Interrupt register check mask */ +} IxQMgrQInfo; + +/* + * Variable declarations global to this file. Externs are followed by + * statics. + */ + +/* + * Flag to keep record of what dispatcher set in featureCtrl when ixQMgrInit() + * is called. This is needed because it is possible that a client might + * change whether the live lock prevention dispatcher is used between + * calls to ixQMgrInit() and ixQMgrDispatcherLoopGet(). + */ +PRIVATE IX_STATUS ixQMgrOrigB0Dispatcher = IX_FEATURE_CTRL_COMPONENT_ENABLED; + +/* + * keep record of Q types - not in IxQMgrQInfo for performance as + * it is only used with ixQMgrDispatcherLoopRunB0LLP() + */ +PRIVATE IxQMgrType ixQMgrQTypes[IX_QMGR_MAX_NUM_QUEUES]; + +/* + * This array contains a list of queue identifiers ordered by priority. The table + * is split logically between queue identifiers 0-31 and 32-63. + */ +static IxQMgrQId priorityTable[IX_QMGR_MAX_NUM_QUEUES]; + +/* + * This flag indicates to the dispatcher that the priority table needs to be rebuilt. + */ +static BOOL rebuildTable = FALSE; + +/* Dispatcher statistics */ +static IxQMgrDispatcherStats dispatcherStats; + +/* Table of queue information */ +static IxQMgrQInfo dispatchQInfo[IX_QMGR_MAX_NUM_QUEUES]; + +/* Masks use to identify the first queues in the priority tables +* when comparing with the interrupt register +*/ +static unsigned int lowPriorityTableFirstHalfMask; +static unsigned int uppPriorityTableFirstHalfMask; + +/* + * Static function prototypes + */ + +/* + * This function is the default callback for all queues + */ +PRIVATE void +dummyCallback (IxQMgrQId qId, + IxQMgrCallbackId cbId); + +PRIVATE void +ixQMgrDispatcherReBuildPriorityTable (void); + +/* + * Function definitions. + */ +void +ixQMgrDispatcherInit (void) +{ + int i; + IxFeatureCtrlProductId productId = 0; + IxFeatureCtrlDeviceId deviceId = 0; + BOOL stickyIntSilicon = TRUE; + + /* Set default priorities */ + for (i=0; i< IX_QMGR_MAX_NUM_QUEUES; i++) + { + dispatchQInfo[i].callback = dummyCallback; + dispatchQInfo[i].callbackId = 0; + dispatchQInfo[i].dummyCallbackCount = 0; + dispatchQInfo[i].priority = IX_QMGR_Q_PRIORITY_2; + dispatchQInfo[i].statusWordOffset = 0; + dispatchQInfo[i].statusCheckValue = 0; + dispatchQInfo[i].statusMask = 0; + /* + * There are two interrupt registers, 32 bits each. One for the lower + * queues(0-31) and one for the upper queues(32-63). Therefore need to + * mod by 32 i.e the min upper queue identifier. + */ + dispatchQInfo[i].intRegCheckMask = (1<<(i%(IX_QMGR_MIN_QUEUPP_QID))); + + /* + * Set the Q types - will only be used with livelock + */ + ixQMgrQTypes[i] = IX_QMGR_TYPE_REALTIME_OTHER; + + /* Reset queue statistics */ + dispatcherStats.queueStats[i].callbackCnt = 0; + dispatcherStats.queueStats[i].priorityChangeCnt = 0; + dispatcherStats.queueStats[i].intNoCallbackCnt = 0; + dispatcherStats.queueStats[i].intLostCallbackCnt = 0; + dispatcherStats.queueStats[i].notificationEnabled = FALSE; + dispatcherStats.queueStats[i].srcSel = 0; + + } + + /* Priority table. Order the table from queue 0 to 63 */ + ixQMgrDispatcherReBuildPriorityTable(); + + /* Reset statistics */ + dispatcherStats.loopRunCnt = 0; + + /* Get the device ID for the underlying silicon */ + deviceId = ixFeatureCtrlDeviceRead(); + + /* Get the product ID for the underlying silicon */ + productId = ixFeatureCtrlProductIdRead(); + + /* + * Check featureCtrl to see if Livelock prevention is required + */ + ixQMgrOrigB0Dispatcher = ixFeatureCtrlSwConfigurationCheck( + IX_FEATURECTRL_ORIGB0_DISPATCHER); + + /* + * Check if the silicon supports the sticky interrupt feature. + * IF (IXP42X AND A0) -> No sticky interrupt feature supported + */ + if ((IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X == + (IX_FEATURE_CTRL_DEVICE_TYPE_MASK & deviceId)) && + (IX_FEATURE_CTRL_SILICON_TYPE_A0 == + (IX_FEATURE_CTRL_SILICON_STEPPING_MASK & productId))) + { + stickyIntSilicon = FALSE; + } + + /* + * IF user wants livelock prev option AND silicon supports sticky interrupt + * feature -> enable the sticky interrupt bit + */ + if ((IX_FEATURE_CTRL_SWCONFIG_DISABLED == ixQMgrOrigB0Dispatcher) && + stickyIntSilicon) + { + ixQMgrStickyInterruptRegEnable(); + } +} + +IX_STATUS +ixQMgrDispatcherPrioritySet (IxQMgrQId qId, + IxQMgrPriority priority) +{ + int ixQMgrLockKey; + + if (!ixQMgrQIsConfigured(qId)) + { + return IX_QMGR_Q_NOT_CONFIGURED; + } + + if (!IX_QMGR_DISPATCHER_PRIORITY_CHECK(priority)) + { + return IX_QMGR_Q_INVALID_PRIORITY; + } + + ixQMgrLockKey = ixOsalIrqLock(); + + /* Change priority */ + dispatchQInfo[qId].priority = priority; + /* Set flag */ + rebuildTable = TRUE; + + ixOsalIrqUnlock(ixQMgrLockKey); + +#ifndef NDEBUG + /* Update statistics */ + dispatcherStats.queueStats[qId].priorityChangeCnt++; +#endif + + return IX_SUCCESS; +} + +IX_STATUS +ixQMgrNotificationCallbackSet (IxQMgrQId qId, + IxQMgrCallback callback, + IxQMgrCallbackId callbackId) +{ + if (!ixQMgrQIsConfigured(qId)) + { + return IX_QMGR_Q_NOT_CONFIGURED; + } + + if (NULL == callback) + { + /* Reset to dummy callback */ + dispatchQInfo[qId].callback = dummyCallback; + dispatchQInfo[qId].dummyCallbackCount = 0; + dispatchQInfo[qId].callbackId = 0; + } + else + { + dispatchQInfo[qId].callback = callback; + dispatchQInfo[qId].callbackId = callbackId; + } + + return IX_SUCCESS; +} + +IX_STATUS +ixQMgrNotificationEnable (IxQMgrQId qId, + IxQMgrSourceId srcSel) +{ + IxQMgrQStatus qStatusOnEntry;/* The queue status on entry/exit */ + IxQMgrQStatus qStatusOnExit; /* to this function */ + int ixQMgrLockKey; + +#ifndef NDEBUG + if (!ixQMgrQIsConfigured (qId)) + { + return IX_QMGR_Q_NOT_CONFIGURED; + } + + if ((qId < IX_QMGR_MIN_QUEUPP_QID) && + !IX_QMGR_DISPATCHER_SOURCE_ID_CHECK(srcSel)) + { + /* QId 0-31 source id invalid */ + return IX_QMGR_INVALID_INT_SOURCE_ID; + } + + if ((IX_QMGR_Q_SOURCE_ID_NE != srcSel) && + (qId >= IX_QMGR_MIN_QUEUPP_QID)) + { + /* + * For queues 32-63 the interrupt source is fixed to the Nearly + * Empty status flag and therefore should have a srcSel of NE. + */ + return IX_QMGR_INVALID_INT_SOURCE_ID; + } +#endif + +#ifndef NDEBUG + dispatcherStats.queueStats[qId].notificationEnabled = TRUE; + dispatcherStats.queueStats[qId].srcSel = srcSel; +#endif + + /* Get the current queue status */ + ixQMgrAqmIfQueStatRead (qId, &qStatusOnEntry); + + /* + * Enabling interrupts results in Read-Modify-Write + * so need critical section + */ + + ixQMgrLockKey = ixOsalIrqLock(); + + /* Calculate the checkMask and checkValue for this q */ + ixQMgrAqmIfQStatusCheckValsCalc (qId, + srcSel, + &dispatchQInfo[qId].statusWordOffset, + &dispatchQInfo[qId].statusCheckValue, + &dispatchQInfo[qId].statusMask); + + + /* Set the interupt source is this queue is in the range 0-31 */ + if (qId < IX_QMGR_MIN_QUEUPP_QID) + { + ixQMgrAqmIfIntSrcSelWrite (qId, srcSel); + } + + /* Enable the interrupt */ + ixQMgrAqmIfQInterruptEnable (qId); + + ixOsalIrqUnlock(ixQMgrLockKey); + + /* 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 +ixQMgrNotificationDisable (IxQMgrQId qId) +{ + int ixQMgrLockKey; + +#ifndef NDEBUG + /* Validate parameters */ + if (!ixQMgrQIsConfigured (qId)) + { + return IX_QMGR_Q_NOT_CONFIGURED; + } +#endif + + /* + * Enabling interrupts results in Read-Modify-Write + * so need critical section + */ +#ifndef NDEBUG + dispatcherStats.queueStats[qId].notificationEnabled = FALSE; +#endif + + ixQMgrLockKey = ixOsalIrqLock(); + + ixQMgrAqmIfQInterruptDisable (qId); + + ixOsalIrqUnlock(ixQMgrLockKey); + + return IX_SUCCESS; +} + +void +ixQMgrStickyInterruptRegEnable(void) +{ + /* Use Aqm If function to set Interrupt Register0 Bit-3 */ + ixQMgrAqmIfIntSrcSelReg0Bit3Set (); +} + +#if !defined __XSCALE__ || defined __linux + +/* Count the number of leading zero bits in a word, + * and return the same value than the CLZ instruction. + * + * word (in) return value (out) + * 0x80000000 0 + * 0x40000000 1 + * ,,, ,,, + * 0x00000002 30 + * 0x00000001 31 + * 0x00000000 32 + * + * The C version of this function is used as a replacement + * for system not providing the equivalent of the CLZ + * assembly language instruction. + * + * Note that this version is big-endian + */ +unsigned int +ixQMgrCountLeadingZeros(UINT32 word) +{ + unsigned int leadingZerosCount = 0; + + if (word == 0) + { + return 32; + } + /* search the first bit set by testing the MSB and shifting the input word */ + while ((word & 0x80000000) == 0) + { + word <<= 1; + leadingZerosCount++; + } + return leadingZerosCount; +} +#endif /* not __XSCALE__ or __linux */ + +void +ixQMgrDispatcherLoopGet (IxQMgrDispatcherFuncPtr *qDispatcherFuncPtr) +{ + IxFeatureCtrlProductId productId = 0; + IxFeatureCtrlDeviceId deviceId = 0; + + /* Get the device ID for the underlying silicon */ + deviceId = ixFeatureCtrlDeviceRead(); + + /* Get the product ID for the underlying silicon */ + productId = ixFeatureCtrlProductIdRead (); + + /* IF (IXP42X AND A0 silicon) -> use ixQMgrDispatcherLoopRunA0 */ + if ((IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X == + (IX_FEATURE_CTRL_DEVICE_TYPE_MASK & deviceId)) && + (IX_FEATURE_CTRL_SILICON_TYPE_A0 == + (IX_FEATURE_CTRL_SILICON_STEPPING_MASK & productId))) + { + /*For IXP42X A0 silicon */ + *qDispatcherFuncPtr = &ixQMgrDispatcherLoopRunA0 ; + } + else /*For IXP42X B0 or IXP46X silicon*/ + { + if (IX_FEATURE_CTRL_SWCONFIG_ENABLED == ixQMgrOrigB0Dispatcher) + { + /* Default for IXP42X B0 and IXP46X silicon */ + *qDispatcherFuncPtr = &ixQMgrDispatcherLoopRunB0; + } + else + { + /* FeatureCtrl indicated that livelock dispatcher be used */ + *qDispatcherFuncPtr = &ixQMgrDispatcherLoopRunB0LLP; + } + } +} + +void +ixQMgrDispatcherLoopRunA0 (IxQMgrDispatchGroup group) +{ + UINT32 intRegVal; /* Interrupt reg val */ + UINT32 intRegValAfterWrite; /* Interrupt reg val after writing back */ + UINT32 intRegCheckMask; /* Mask for checking interrupt bits */ + UINT32 qStatusWordsB4Write[MAX_Q_STATUS_WORDS]; /* Status b4 interrupt write */ + UINT32 qStatusWordsAfterWrite[MAX_Q_STATUS_WORDS]; /* Status after interrupt write */ + IxQMgrQInfo *currDispatchQInfo; + BOOL statusChangeFlag; + + int priorityTableIndex;/* Priority table index */ + int qIndex; /* Current queue being processed */ + int endIndex; /* Index of last queue to process */ + +#ifndef NDEBUG + IX_OSAL_ASSERT((group == IX_QMGR_QUEUPP_GROUP) || + (group == IX_QMGR_QUELOW_GROUP)); +#endif + + /* Read Q status registers before interrupt status read/write */ + ixQMgrAqmIfQStatusRegsRead (group, qStatusWordsB4Write); + + /* Read the interrupt register */ + ixQMgrAqmIfQInterruptRegRead (group, &intRegVal); + + /* No bit set : nothing to process (the reaminder of the algorithm is + * based on the fact that the interrupt register value contains at + * least one bit set + */ + if (intRegVal == 0) + { +#ifndef NDEBUG + /* Update statistics */ + dispatcherStats.loopRunCnt++; +#endif + + /* Rebuild the priority table if needed */ + if (rebuildTable) + { + ixQMgrDispatcherReBuildPriorityTable (); + } + + return; + } + + /* Write it back to clear the interrupt */ + ixQMgrAqmIfQInterruptRegWrite (group, intRegVal); + + /* Read Q status registers after interrupt status read/write */ + ixQMgrAqmIfQStatusRegsRead (group, qStatusWordsAfterWrite); + + /* get the first queue Id from the interrupt register value */ + qIndex = (BITS_PER_WORD - 1) - ixQMgrCountLeadingZeros(intRegVal); + + /* check if any change occured during hw register modifications */ + if (IX_QMGR_QUELOW_GROUP == group) + { + statusChangeFlag = + (qStatusWordsB4Write[0] != qStatusWordsAfterWrite[0]) || + (qStatusWordsB4Write[1] != qStatusWordsAfterWrite[1]) || + (qStatusWordsB4Write[2] != qStatusWordsAfterWrite[2]) || + (qStatusWordsB4Write[3] != qStatusWordsAfterWrite[3]); + } + else + { + statusChangeFlag = + (qStatusWordsB4Write[0] != qStatusWordsAfterWrite[0]); + /* Set the queue range based on the queue group to proccess */ + qIndex += IX_QMGR_MIN_QUEUPP_QID; + } + + if (statusChangeFlag == FALSE) + { + /* check if the interrupt register contains + * only 1 bit set (happy day scenario) + */ + currDispatchQInfo = &dispatchQInfo[qIndex]; + if (intRegVal == currDispatchQInfo->intRegCheckMask) + { + /* only 1 queue event triggered a notification * + * Call the callback function for this queue + */ + currDispatchQInfo->callback (qIndex, + currDispatchQInfo->callbackId); +#ifndef NDEBUG + /* Update statistics */ + dispatcherStats.queueStats[qIndex].callbackCnt++; +#endif + } + else + { + /* the event is triggered by more than 1 queue, + * the queue search will be starting from the beginning + * or the middle of the priority table + * + * the serach will end when all the bits of the interrupt + * register are cleared. There is no need to maintain + * a seperate value and test it at each iteration. + */ + if (IX_QMGR_QUELOW_GROUP == group) + { + /* check if any bit related to queues in the first + * half of the priority table is set + */ + if (intRegVal & lowPriorityTableFirstHalfMask) + { + priorityTableIndex = IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX; + } + else + { + priorityTableIndex = IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX; + } + } + else + { + /* check if any bit related to queues in the first + * half of the priority table is set + */ + if (intRegVal & uppPriorityTableFirstHalfMask) + { + priorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX; + } + else + { + priorityTableIndex = IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX; + } + } + + /* iterate following the priority table until all the bits + * of the interrupt register are cleared. + */ + do + { + qIndex = priorityTable[priorityTableIndex++]; + currDispatchQInfo = &dispatchQInfo[qIndex]; + intRegCheckMask = currDispatchQInfo->intRegCheckMask; + + /* If this queue caused this interrupt to be raised */ + if (intRegVal & intRegCheckMask) + { + /* Call the callback function for this queue */ + currDispatchQInfo->callback (qIndex, + currDispatchQInfo->callbackId); +#ifndef NDEBUG + /* Update statistics */ + dispatcherStats.queueStats[qIndex].callbackCnt++; +#endif + + /* Clear the interrupt register bit */ + intRegVal &= ~intRegCheckMask; + } + } + while(intRegVal); + } + } + else + { + /* A change in queue status occured during the hw interrupt + * register update. To maintain the interrupt consistency, it + * is necessary to iterate through all queues of the queue group. + */ + + /* Read interrupt status again */ + ixQMgrAqmIfQInterruptRegRead (group, &intRegValAfterWrite); + + if (IX_QMGR_QUELOW_GROUP == group) + { + priorityTableIndex = IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX; + endIndex = IX_QMGR_MAX_LOW_QUE_PRIORITY_TABLE_INDEX; + } + else + { + priorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX; + endIndex = IX_QMGR_MAX_UPP_QUE_PRIORITY_TABLE_INDEX; + } + + for ( ; priorityTableIndex<=endIndex; priorityTableIndex++) + { + qIndex = priorityTable[priorityTableIndex]; + currDispatchQInfo = &dispatchQInfo[qIndex]; + intRegCheckMask = currDispatchQInfo->intRegCheckMask; + + /* If this queue caused this interrupt to be raised */ + if (intRegVal & intRegCheckMask) + { + /* Call the callback function for this queue */ + currDispatchQInfo->callback (qIndex, + currDispatchQInfo->callbackId); +#ifndef NDEBUG + /* Update statistics */ + dispatcherStats.queueStats[qIndex].callbackCnt++; +#endif + + } /* if (intRegVal .. */ + + /* + * If interrupt bit is set in intRegValAfterWrite don't + * proceed as this will be caught in next interrupt + */ + else if ((intRegValAfterWrite & intRegCheckMask) == 0) + { + /* Check if an interrupt was lost for this Q */ + if (ixQMgrAqmIfQStatusCheck(qStatusWordsB4Write, + qStatusWordsAfterWrite, + currDispatchQInfo->statusWordOffset, + currDispatchQInfo->statusCheckValue, + currDispatchQInfo->statusMask)) + { + /* Call the callback function for this queue */ + currDispatchQInfo->callback (qIndex, + dispatchQInfo[qIndex].callbackId); +#ifndef NDEBUG + /* Update statistics */ + dispatcherStats.queueStats[qIndex].callbackCnt++; + dispatcherStats.queueStats[qIndex].intLostCallbackCnt++; +#endif + } /* if ixQMgrAqmIfQStatusCheck(.. */ + } /* else if ((intRegValAfterWrite ... */ + } /* for (priorityTableIndex=0 ... */ + } + + /* Rebuild the priority table if needed */ + if (rebuildTable) + { + ixQMgrDispatcherReBuildPriorityTable (); + } + +#ifndef NDEBUG + /* Update statistics */ + dispatcherStats.loopRunCnt++; +#endif +} + + + +void +ixQMgrDispatcherLoopRunB0 (IxQMgrDispatchGroup group) +{ + UINT32 intRegVal; /* Interrupt reg val */ + UINT32 intRegCheckMask; /* Mask for checking interrupt bits */ + IxQMgrQInfo *currDispatchQInfo; + + + int priorityTableIndex; /* Priority table index */ + int qIndex; /* Current queue being processed */ + +#ifndef NDEBUG + IX_OSAL_ASSERT((group == IX_QMGR_QUEUPP_GROUP) || + (group == IX_QMGR_QUELOW_GROUP)); + IX_OSAL_ASSERT((group == IX_QMGR_QUEUPP_GROUP) || + (group == IX_QMGR_QUELOW_GROUP)); +#endif + + /* Read the interrupt register */ + ixQMgrAqmIfQInterruptRegRead (group, &intRegVal); + + + /* No queue has interrupt register set */ + if (intRegVal != 0) + { + + /* Write it back to clear the interrupt */ + ixQMgrAqmIfQInterruptRegWrite (group, intRegVal); + + /* get the first queue Id from the interrupt register value */ + qIndex = (BITS_PER_WORD - 1) - ixQMgrCountLeadingZeros(intRegVal); + + if (IX_QMGR_QUEUPP_GROUP == group) + { + /* Set the queue range based on the queue group to proccess */ + qIndex += IX_QMGR_MIN_QUEUPP_QID; + } + + /* check if the interrupt register contains + * only 1 bit set + * For example: + * intRegVal = 0x0010 + * currDispatchQInfo->intRegCheckMask = 0x0010 + * intRegVal == currDispatchQInfo->intRegCheckMask is TRUE. + */ + currDispatchQInfo = &dispatchQInfo[qIndex]; + if (intRegVal == currDispatchQInfo->intRegCheckMask) + { + /* only 1 queue event triggered a notification * + * Call the callback function for this queue + */ + currDispatchQInfo->callback (qIndex, + currDispatchQInfo->callbackId); +#ifndef NDEBUG + /* Update statistics */ + dispatcherStats.queueStats[qIndex].callbackCnt++; +#endif + } + else + { + /* the event is triggered by more than 1 queue, + * the queue search will be starting from the beginning + * or the middle of the priority table + * + * the serach will end when all the bits of the interrupt + * register are cleared. There is no need to maintain + * a seperate value and test it at each iteration. + */ + if (IX_QMGR_QUELOW_GROUP == group) + { + /* check if any bit related to queues in the first + * half of the priority table is set + */ + if (intRegVal & lowPriorityTableFirstHalfMask) + { + priorityTableIndex = IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX; + } + else + { + priorityTableIndex = IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX; + } + } + else + { + /* check if any bit related to queues in the first + * half of the priority table is set + */ + if (intRegVal & uppPriorityTableFirstHalfMask) + { + priorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX; + } + else + { + priorityTableIndex = IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX; + } + } + + /* iterate following the priority table until all the bits + * of the interrupt register are cleared. + */ + do + { + qIndex = priorityTable[priorityTableIndex++]; + currDispatchQInfo = &dispatchQInfo[qIndex]; + intRegCheckMask = currDispatchQInfo->intRegCheckMask; + + /* If this queue caused this interrupt to be raised */ + if (intRegVal & intRegCheckMask) + { + /* Call the callback function for this queue */ + currDispatchQInfo->callback (qIndex, + currDispatchQInfo->callbackId); +#ifndef NDEBUG + /* Update statistics */ + dispatcherStats.queueStats[qIndex].callbackCnt++; +#endif + + /* Clear the interrupt register bit */ + intRegVal &= ~intRegCheckMask; + } + } + while(intRegVal); + } /*End of intRegVal == currDispatchQInfo->intRegCheckMask */ + } /* End of intRegVal != 0 */ + +#ifndef NDEBUG + /* Update statistics */ + dispatcherStats.loopRunCnt++; +#endif + + /* Rebuild the priority table if needed */ + if (rebuildTable) + { + ixQMgrDispatcherReBuildPriorityTable (); + } +} + +void +ixQMgrDispatcherLoopRunB0LLP (IxQMgrDispatchGroup group) +{ + UINT32 intRegVal =0; /* Interrupt reg val */ + UINT32 intRegCheckMask; /* Mask for checking interrupt bits */ + IxQMgrQInfo *currDispatchQInfo; + + int priorityTableIndex; /* Priority table index */ + int qIndex; /* Current queue being processed */ + + UINT32 intRegValCopy = 0; + UINT32 intEnableRegVal = 0; + UINT8 i = 0; + +#ifndef NDEBUG + IX_OSAL_ASSERT((group == IX_QMGR_QUEUPP_GROUP) || + (group == IX_QMGR_QUELOW_GROUP)); +#endif + + /* Read the interrupt register */ + ixQMgrAqmIfQInterruptRegRead (group, &intRegVal); + + /* + * mask any interrupts that are not enabled + */ + ixQMgrAqmIfQInterruptEnableRegRead (group, &intEnableRegVal); + intRegVal &= intEnableRegVal; + + /* No queue has interrupt register set */ + if (intRegVal != 0) + { + if (IX_QMGR_QUELOW_GROUP == group) + { + /* + * As the sticky bit is set, the interrupt register will + * not clear if write back at this point because the condition + * has not been cleared. Take a copy and write back later after + * the condition has been cleared + */ + intRegValCopy = intRegVal; + } + else + { + /* no sticky for upper Q's, so write back now */ + ixQMgrAqmIfQInterruptRegWrite (group, intRegVal); + } + + /* get the first queue Id from the interrupt register value */ + qIndex = (BITS_PER_WORD - 1) - ixQMgrCountLeadingZeros(intRegVal); + + if (IX_QMGR_QUEUPP_GROUP == group) + { + /* Set the queue range based on the queue group to proccess */ + qIndex += IX_QMGR_MIN_QUEUPP_QID; + } + + /* check if the interrupt register contains + * only 1 bit set + * For example: + * intRegVal = 0x0010 + * currDispatchQInfo->intRegCheckMask = 0x0010 + * intRegVal == currDispatchQInfo->intRegCheckMask is TRUE. + */ + currDispatchQInfo = &dispatchQInfo[qIndex]; + if (intRegVal == currDispatchQInfo->intRegCheckMask) + { + + /* + * check if Q type periodic - only lower queues can + * have there type set to periodic + */ + if (IX_QMGR_TYPE_REALTIME_PERIODIC == ixQMgrQTypes[qIndex]) + { + /* + * Disable the notifications on any sporadics + */ + for (i=0; i <= IX_QMGR_MAX_LOW_QUE_TABLE_INDEX; i++) + { + if (IX_QMGR_TYPE_REALTIME_SPORADIC == ixQMgrQTypes[i]) + { + ixQMgrNotificationDisable(i); +#ifndef NDEBUG + /* Update statistics */ + dispatcherStats.queueStats[i].disableCount++; +#endif + } + } + } + + currDispatchQInfo->callback (qIndex, + currDispatchQInfo->callbackId); +#ifndef NDEBUG + /* Update statistics */ + dispatcherStats.queueStats[qIndex].callbackCnt++; +#endif + } + else + { + /* the event is triggered by more than 1 queue, + * the queue search will be starting from the beginning + * or the middle of the priority table + * + * the serach will end when all the bits of the interrupt + * register are cleared. There is no need to maintain + * a seperate value and test it at each iteration. + */ + if (IX_QMGR_QUELOW_GROUP == group) + { + /* check if any bit related to queues in the first + * half of the priority table is set + */ + if (intRegVal & lowPriorityTableFirstHalfMask) + { + priorityTableIndex = + IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX; + } + else + { + priorityTableIndex = + IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX; + } + } + else + { + /* check if any bit related to queues in the first + * half of the priority table is set + */ + if (intRegVal & uppPriorityTableFirstHalfMask) + { + priorityTableIndex = + IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX; + } + else + { + priorityTableIndex = + IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX; + } + } + + /* iterate following the priority table until all the bits + * of the interrupt register are cleared. + */ + do + { + qIndex = priorityTable[priorityTableIndex++]; + currDispatchQInfo = &dispatchQInfo[qIndex]; + intRegCheckMask = currDispatchQInfo->intRegCheckMask; + + /* If this queue caused this interrupt to be raised */ + if (intRegVal & intRegCheckMask) + { + /* + * check if Q type periodic - only lower queues can + * have there type set to periodic. There can only be one + * periodic queue, so the sporadics are only disabled once. + */ + if (IX_QMGR_TYPE_REALTIME_PERIODIC == ixQMgrQTypes[qIndex]) + { + /* + * Disable the notifications on any sporadics + */ + for (i=0; i <= IX_QMGR_MAX_LOW_QUE_TABLE_INDEX; i++) + { + if (IX_QMGR_TYPE_REALTIME_SPORADIC == + ixQMgrQTypes[i]) + { + ixQMgrNotificationDisable(i); + /* + * remove from intRegVal as we don't want + * to service any sporadics now + */ + intRegVal &= ~dispatchQInfo[i].intRegCheckMask; +#ifndef NDEBUG + /* Update statistics */ + dispatcherStats.queueStats[i].disableCount++; +#endif + } + } + } + + currDispatchQInfo->callback (qIndex, + currDispatchQInfo->callbackId); +#ifndef NDEBUG + /* Update statistics */ + dispatcherStats.queueStats[qIndex].callbackCnt++; +#endif + /* Clear the interrupt register bit */ + intRegVal &= ~intRegCheckMask; + } + } + while(intRegVal); + } /*End of intRegVal == currDispatchQInfo->intRegCheckMask */ + } /* End of intRegVal != 0 */ + +#ifndef NDEBUG + /* Update statistics */ + dispatcherStats.loopRunCnt++; +#endif + + if ((intRegValCopy != 0) && (IX_QMGR_QUELOW_GROUP == group)) + { + /* + * lower groups (therefore sticky) AND at least one enabled interrupt + * Write back to clear the interrupt + */ + ixQMgrAqmIfQInterruptRegWrite (IX_QMGR_QUELOW_GROUP, intRegValCopy); + } + + /* Rebuild the priority table if needed */ + if (rebuildTable) + { + ixQMgrDispatcherReBuildPriorityTable (); + } +} + +PRIVATE void +ixQMgrDispatcherReBuildPriorityTable (void) +{ + UINT32 qIndex; + UINT32 priority; + int lowQuePriorityTableIndex = IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX; + int uppQuePriorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX; + + /* Reset the rebuild flag */ + rebuildTable = FALSE; + + /* initialize the mak used to identify the queues in the first half + * of the priority table + */ + lowPriorityTableFirstHalfMask = 0; + uppPriorityTableFirstHalfMask = 0; + + /* For each priority level */ + for(priority=0; priority dummyCallback: qId (%d), callbackId (%d)\n",qId,cbId); + } + dispatchQInfo[qId].dummyCallbackCount++; + +#ifndef NDEBUG + /* Update statistcs */ + dispatcherStats.queueStats[qId].intNoCallbackCnt++; +#endif +} +void +ixQMgrLLPShow (int resetStats) +{ +#ifndef NDEBUG + UINT8 i = 0; + IxQMgrQInfo *q; + UINT32 intEnableRegVal = 0; + + printf ("Livelock statistics are printed on the fly.\n"); + printf ("qId Type EnableCnt DisableCnt IntEnableState Callbacks\n"); + printf ("=== ======== ========= ========== ============== =========\n"); + + for (i=0; i<= IX_QMGR_MAX_LOW_QUE_TABLE_INDEX; i++) + { + q = &dispatchQInfo[i]; + + if (ixQMgrQTypes[i] != IX_QMGR_TYPE_REALTIME_OTHER) + { + printf (" %2d ", i); + + if (ixQMgrQTypes[i] == IX_QMGR_TYPE_REALTIME_SPORADIC) + { + printf ("Sporadic"); + } + else + { + printf ("Periodic"); + } + + + ixQMgrAqmIfQInterruptEnableRegRead (IX_QMGR_QUELOW_GROUP, + &intEnableRegVal); + + + intEnableRegVal &= dispatchQInfo[i].intRegCheckMask; + intEnableRegVal = intEnableRegVal >> i; + + printf (" %10d %10d %10d %10d\n", + dispatcherStats.queueStats[i].enableCount, + dispatcherStats.queueStats[i].disableCount, + intEnableRegVal, + dispatcherStats.queueStats[i].callbackCnt); + + if (resetStats) + { + dispatcherStats.queueStats[i].enableCount = + dispatcherStats.queueStats[i].disableCount = + dispatcherStats.queueStats[i].callbackCnt = 0; + } + } + } +#else + IX_QMGR_LOG0("Livelock Prevention statistics are only collected in debug mode\n"); +#endif +} + +void +ixQMgrPeriodicDone (void) +{ + UINT32 i = 0; + UINT32 ixQMgrLockKey = 0; + + /* + * for the lower queues + */ + for (i=0; i <= IX_QMGR_MAX_LOW_QUE_TABLE_INDEX; i++) + { + /* + * check for sporadics + */ + if (IX_QMGR_TYPE_REALTIME_SPORADIC == ixQMgrQTypes[i]) + { + /* + * enable any sporadics + */ + ixQMgrLockKey = ixOsalIrqLock(); + ixQMgrAqmIfQInterruptEnable(i); + ixOsalIrqUnlock(ixQMgrLockKey); +#ifndef NDEBUG + /* + * Update statistics + */ + dispatcherStats.queueStats[i].enableCount++; + dispatcherStats.queueStats[i].notificationEnabled = TRUE; +#endif + } + } +} +IX_STATUS +ixQMgrCallbackTypeSet (IxQMgrQId qId, + IxQMgrType type) +{ + UINT32 ixQMgrLockKey = 0; + IxQMgrType ixQMgrOldType =0; + +#ifndef NDEBUG + if (!ixQMgrQIsConfigured(qId)) + { + return IX_QMGR_Q_NOT_CONFIGURED; + } + if (qId >= IX_QMGR_MIN_QUEUPP_QID) + { + return IX_QMGR_PARAMETER_ERROR; + } + if(!IX_QMGR_DISPATCHER_CALLBACK_TYPE_CHECK(type)) + { + return IX_QMGR_PARAMETER_ERROR; + } +#endif + + ixQMgrOldType = ixQMgrQTypes[qId]; + ixQMgrQTypes[qId] = type; + + /* + * check if Q has been changed from type SPORADIC + */ + if (IX_QMGR_TYPE_REALTIME_SPORADIC == ixQMgrOldType) + { + /* + * previously Q was a SPORADIC, this means that LLP + * might have had it disabled. enable it now. + */ + ixQMgrLockKey = ixOsalIrqLock(); + ixQMgrAqmIfQInterruptEnable(qId); + ixOsalIrqUnlock(ixQMgrLockKey); + +#ifndef NDEBUG + /* + * Update statistics + */ + dispatcherStats.queueStats[qId].enableCount++; +#endif + } + + return IX_SUCCESS; +} + +IX_STATUS +ixQMgrCallbackTypeGet (IxQMgrQId qId, + IxQMgrType *type) +{ +#ifndef NDEBUG + if (!ixQMgrQIsConfigured(qId)) + { + return IX_QMGR_Q_NOT_CONFIGURED; + } + if (qId >= IX_QMGR_MIN_QUEUPP_QID) + { + return IX_QMGR_PARAMETER_ERROR; + } + if(type == NULL) + { + return IX_QMGR_PARAMETER_ERROR; + } +#endif + + *type = ixQMgrQTypes[qId]; + return IX_SUCCESS; +} diff --git a/cpu/ixp/npe/IxQMgrInit.c b/cpu/ixp/npe/IxQMgrInit.c new file mode 100644 index 0000000..b00c22d --- /dev/null +++ b/cpu/ixp/npe/IxQMgrInit.c @@ -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; iqStats[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; +} + + + + diff --git a/cpu/ixp/npe/IxQMgrQAccess.c b/cpu/ixp/npe/IxQMgrQAccess.c new file mode 100644 index 0000000..2c3e302 --- /dev/null +++ b/cpu/ixp/npe/IxQMgrQAccess.c @@ -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 */ diff --git a/cpu/ixp/npe/IxQMgrQCfg.c b/cpu/ixp/npe/IxQMgrQCfg.c new file mode 100644 index 0000000..ec7d837 --- /dev/null +++ b/cpu/ixp/npe/IxQMgrQCfg.c @@ -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; +} diff --git a/cpu/ixp/npe/Makefile b/cpu/ixp/npe/Makefile new file mode 100644 index 0000000..937de9d --- /dev/null +++ b/cpu/ixp/npe/Makefile @@ -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 diff --git a/cpu/ixp/npe/include/IxAssert.h b/cpu/ixp/npe/include/IxAssert.h new file mode 100644 index 0000000..eae8b3f --- /dev/null +++ b/cpu/ixp/npe/include/IxAssert.h @@ -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 + */ + + + diff --git a/cpu/ixp/npe/include/IxAtmSch.h b/cpu/ixp/npe/include/IxAtmSch.h new file mode 100644 index 0000000..73c3be2 --- /dev/null +++ b/cpu/ixp/npe/include/IxAtmSch.h @@ -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 + * - IX_SUCCESS : indicates that + * -# The ATM scheduler component has been successfully initialized. + * -# The scheduler is ready to accept Port modelling requests. + * - IX_FAIL : 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 + * - IX_SUCCESS : 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. + * - IX_FAIL : 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 + * - IX_SUCCESS : The port rate has been successfully modified.
+ * - IX_FAIL : 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 + * - IX_SUCCESS : The VC has been successfully established on + * this port. The client may begin to submit demand on this VC. + * - IX_ATMSCH_RET_NOT_ADMITTED : The VC cannot be established + * on this port because there is insufficient upstream capacity + * available to support the requested traffic contract descriptor + * - IX_FAIL :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 + * - IX_SUCCESS : The id has successfully been set. + * - IX_FAIL :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 + * - IX_SUCCESS : The VC has been successfully removed from + * this port. It is no longer modelled on this port. + * - IX_FAIL :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 + * - IX_SUCCESS : The VC queue has been successfully updated. + * - IX_ATMSCH_RET_QUEUE_FULL : 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. + * - IX_FAIL : 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 + * - IX_SUCCESS : The VC queue has been successfully cleared. + * - IX_FAIL : 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 + * - IX_SUCCESS : The schedule table has been published. + * Currently there is at least one VC queue that is nonempty. + * - IX_ATMSCH_RET_QUEUE_EMPTY : 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. + * - IX_FAIL : 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 */ + +/** @} */ diff --git a/cpu/ixp/npe/include/IxAtmTypes.h b/cpu/ixp/npe/include/IxAtmTypes.h new file mode 100644 index 0000000..8624c33 --- /dev/null +++ b/cpu/ixp/npe/include/IxAtmTypes.h @@ -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 + */ + + diff --git a/cpu/ixp/npe/include/IxAtmdAcc.h b/cpu/ixp/npe/include/IxAtmdAcc.h new file mode 100644 index 0000000..ae7b243 --- /dev/null +++ b/cpu/ixp/npe/include/IxAtmdAcc.h @@ -0,0 +1,1194 @@ + +/** + * @file IxAtmdAcc.h + * + * @date 07-Nov-2001 + * + * @brief IxAtmdAcc Public API + * + * This file contains the public API of IxAtmdAcc, related to the + * data functions of the 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 -- + */ + +/* ------------------------------------------------------ + Doxygen group definitions + ------------------------------------------------------ */ + +/** + * + * @defgroup IxAtmdAccAPI IXP400 ATM Driver Access (IxAtmdAcc) API + * + * @brief The public API for the IXP400 Atm Driver Data component + * + * IxAtmdAcc is the low level interface by which AAL0/AAL5 and + * OAM data gets transmitted to,and received from the Utopia bus. + * + * For AAL0/AAL5 services transmit and receive connections may + * be established independantly for unique combinations of + * port,VPI,and VCI. + * + * Two AAL0 services supporting 48 or 52 byte cell data are provided. + * Submitted AAL0 PDUs must be a multiple of the cell data size (48/52). + * AAL0_52 is a raw cell service the client must format + * the PDU with an ATM cell header (excluding HEC) at the start of + * each cell, note that AtmdAcc does not validate the cell headers in + * a submitted PDU. + * + * OAM cells cannot be received over the AAL0 service but instead + * are received over a dedicated OAM service. + * + * For the OAM service an "OAM Tx channel" may be enabled for a port + * by establishing a single dedicated OAM Tx connection on that port. + * A single "OAM Rx channel" for all ports may be enabled by + * establishing a dedicated OAM Rx connection. + * + * The OAM service allows buffers containing 52 byte OAM F4/F5 cells + * to be transmitted and received over the dedicated OAM channels. + * HEC is appended/removed, and CRC-10 performed by the NPE. The OAM + * service offered by AtmdAcc is a raw cell transport service. + * It is assumed that ITU I.610 procedures that make use of this + * service are implemented above AtmdAcc. + * + * Note that the dedicated OAM connections are established on + * reserved VPI,VCI, and (in the case of Rx) port values defined below. + * These values are used purely to descriminate the dedicated OAM channels + * and do not identify a particular OAM F4/F5 flow. F4/F5 flows may be + * realised for particluar VPI/VCIs by manipulating the VPI,VCI + * fields of the ATM cell headers of cells in the buffers passed + * to AtmdAcc. Note that AtmdAcc does not validate the cell headers + * in a submitted OAM PDU. + * + * + * + * This part is related to the User datapath processing + * + * @{ + */ + +#ifndef IXATMDACC_H +#define IXATMDACC_H + +#include "IxAtmTypes.h" + +/* ------------------------------------------------------ + AtmdAcc Data Types definition + ------------------------------------------------------ */ + +/** + * + * @ingroup IxAtmdAccAPI + * + * @def IX_ATMDACC_WARNING + * + * @brief Warning return code + * + * This constant is used to tell IxAtmDAcc user about a special case. + * + */ +#define IX_ATMDACC_WARNING 2 + +/** + * + * @ingroup IxAtmdAccAPI + * + * @def IX_ATMDACC_BUSY + * + * @brief Busy return code + * + * This constant is used to tell IxAtmDAcc user that the request + * is correct, but cannot be processed because the IxAtmAcc resources + * are already used. The user has to retry its request later + * + */ +#define IX_ATMDACC_BUSY 3 + +/** + * + * @ingroup IxAtmdAccAPI + * + * @def IX_ATMDACC_RESOURCES_STILL_ALLOCATED + * + * @brief Disconnect return code + * + * This constant is used to tell IxAtmDAcc user that the disconnect + * functions are not complete because the resources used by the driver + * are not yet released. The user has to retry the disconnect call + * later. + * + */ +#define IX_ATMDACC_RESOURCES_STILL_ALLOCATED 4 + +/** + * + * @ingroup IxAtmdAccAPI + * + * @def IX_ATMDACC_DEFAULT_REPLENISH_COUNT + * + * @brief Default resources usage for RxVcFree replenish mechanism + * + * This constant is used to tell IxAtmDAcc to allocate and use + * the minimum of resources for rx free replenish. + * + * @sa ixAtmdAccRxVcConnect + */ +#define IX_ATMDACC_DEFAULT_REPLENISH_COUNT 0 + + +/** + * @ingroup IxAtmdAccAPI + * + * @def IX_ATMDACC_OAM_TX_VPI + * + * @brief The reserved value used for the dedicated OAM + * Tx connection. This "well known" value is used by atmdAcc and + * its clients to dsicriminate the OAM channel, and should be chosen so + * that it does not coencide with the VPI value used in an AAL0/AAL5 connection. + * Any attempt to connect a service type other than OAM on this VPI will fail. + * + * + */ +#define IX_ATMDACC_OAM_TX_VPI 0 + +/** + * @ingroup IxAtmdAccAPI + * + * @def IX_ATMDACC_OAM_TX_VCI + * + * @brief The reserved value used for the dedicated OAM + * Tx connection. This "well known" value is used by atmdAcc and + * its clients to dsicriminate the OAM channel, and should be chosen so + * that it does not coencide with the VCI value used in an AAL0/AAL5 connection. + * Any attempt to connect a service type other than OAM on this VCI will fail. + */ +#define IX_ATMDACC_OAM_TX_VCI 0 + + + /** + * @ingroup IxAtmdAccAPI + * + * @def IX_ATMDACC_OAM_RX_PORT + * + * @brief The reserved dummy PORT used for all dedicated OAM + * Rx connections. Note that this is not a real port but must + * have a value that lies within the valid range of port values. + */ +#define IX_ATMDACC_OAM_RX_PORT IX_UTOPIA_PORT_0 + + /** + * @ingroup IxAtmdAccAPI + * + * @def IX_ATMDACC_OAM_RX_VPI + * + * @brief The reserved value value used for the dedicated OAM + * Rx connection. This value should be chosen so that it does not + * coencide with the VPI value used in an AAL0/AAL5 connection. + * Any attempt to connect a service type other than OAM on this VPI will fail. + */ +#define IX_ATMDACC_OAM_RX_VPI 0 + +/** + * @ingroup IxAtmdAccAPI + * + * @def IX_ATMDACC_OAM_RX_VCI + * + * @brief The reserved value value used for the dedicated OAM + * Rx connection. This value should be chosen so that it does not + * coencide with the VCI value used in an AAL0/AAL5 connection. + * Any attempt to connect a service type other than OAM on this VCI will fail. + */ +#define IX_ATMDACC_OAM_RX_VCI 0 + + +/** + * @enum IxAtmdAccPduStatus + * + * @ingroup IxAtmdAccAPI + * + * @brief IxAtmdAcc Pdu status : + * + * IxAtmdAccPduStatus is used during a RX operation to indicate + * the status of the received PDU + * + */ + +typedef enum +{ + IX_ATMDACC_AAL0_VALID = 0, /**< aal0 pdu */ + IX_ATMDACC_OAM_VALID, /**< OAM pdu */ + IX_ATMDACC_AAL2_VALID, /**< aal2 pdu @b reserved for future use */ + IX_ATMDACC_AAL5_VALID, /**< aal5 pdu complete and trailer is valid */ + IX_ATMDACC_AAL5_PARTIAL, /**< aal5 pdu not complete, trailer is missing */ + IX_ATMDACC_AAL5_CRC_ERROR, /**< aal5 pdu not complete, crc error/length error */ + IX_ATMDACC_MBUF_RETURN /**< empty buffer returned to the user */ +} IxAtmdAccPduStatus; + + +/** + * + * @enum IxAtmdAccAalType + * + * @ingroup IxAtmdAccAPI + * + * @brief IxAtmdAcc AAL Service Type : + * + * IxAtmdAccAalType defines the type of traffic to run on this VC + * + */ +typedef enum +{ + IX_ATMDACC_AAL5, /**< ITU-T AAL5 */ + IX_ATMDACC_AAL2, /**< ITU-T AAL2 @b reserved for future use */ + IX_ATMDACC_AAL0_48, /**< AAL0 48 byte payloads (cell header is added by NPE)*/ + IX_ATMDACC_AAL0_52, /**< AAL0 52 byte cell data (HEC is added by NPE) */ + IX_ATMDACC_OAM, /**< OAM cell transport service (HEC is added by NPE)*/ + IX_ATMDACC_MAX_SERVICE_TYPE /**< not a service, used for parameter validation */ +} IxAtmdAccAalType; + +/** + * + * @enum IxAtmdAccClpStatus + * + * @ingroup IxAtmdAccAPI + * + * @brief IxAtmdAcc CLP indication + * + * IxAtmdAccClpStatus defines the CLP status of the current PDU + * + */ +typedef enum +{ + IX_ATMDACC_CLP_NOT_SET = 0, /**< CLP indication is not set */ + IX_ATMDACC_CLP_SET = 1 /**< CLP indication is set */ +} IxAtmdAccClpStatus; + +/** + * @typedef IxAtmdAccUserId + * + * @ingroup IxAtmdAccAPI + * + * @brief User-supplied Id + * + * IxAtmdAccUserId is passed through callbacks and allows the + * IxAtmdAcc user to identify the source of a call back. The range of + * this user-owned Id is [0...2^32-1)]. + * + * The user provides this own Ids on a per-channel basis as a parameter + * in a call to @a ixAtmdAccRxVcConnect() or @a ixAtmdAccRxVcConnect() + * + * @sa ixAtmdAccRxVcConnect + * @sa ixAtmdAccTxVcConnect + * + */ +typedef unsigned int IxAtmdAccUserId; + +/* ------------------------------------------------------ + Part of the IxAtmdAcc interface related to RX traffic + ------------------------------------------------------ */ + +/** + * + * @ingroup IxAtmdAccAPI + * + * @brief Rx callback prototype + * + * IxAtmdAccRxVcRxCallback is the prototype of the Rx callback user + * function called once per PDU to pass a receive Pdu to a user on a + * partilcular connection. The callback is likely to push the mbufs + * to a protocol layer, and recycle the mbufs for a further use. + * + * @note -This function is called ONLY in the context of + * the @a ixAtmdAccRxDispatch() function + * + * @sa ixAtmdAccRxDispatch + * @sa ixAtmdAccRxVcConnect + * + * @param port @ref IxAtmLogicalPort [in] - the port on which this PDU was received + * a logical PHY port [@a IX_UTOPIA_PORT_0 .. @a IX_UTOPIA_MAX_PORTS - 1] + * @param userId @ref IxAtmdAccUserId [in] - user Id provided in the call + * to @a ixAtmdAccRxVcConnect() + * @param status @ref IxAtmdAccPduStatus [in] - an indication about the PDU validity. + * In the case of AAL0 the only possibile value is + * AAL0_VALID, in this case the client may optionally determine + * that an rx timeout occured by checking if the mbuf is + * compleletly or only partially filled, the later case + * indicating a timeout. + * In the case of OAM the only possible value is OAM valid. + * The status is set to @a IX_ATMDACC_MBUF_RETURN when + * the mbuf is released during a disconnect process. + * @param clp @ref IxAtmdAccClpStatus [in] - clp indication for this PDU. + * For AAL5/AAL0_48 this information + * is set if the clp bit of any rx cell is set + * For AAL0-52/OAM the client may inspect the CLP in individual + * cell headers in the PDU, and this parameter is set to 0. + * @param *mbufPtr @ref IX_OSAL_MBUF [in] - depending on the servive type a pointer to + * an mbuf (AAL5/AAL0/OAM) or mbuf chain (AAL5 only), + * that comprises the complete PDU data. + * + * This parameter is guaranteed not to be a null pointer. + * + */ +typedef void (*IxAtmdAccRxVcRxCallback) (IxAtmLogicalPort port, + IxAtmdAccUserId userId, + IxAtmdAccPduStatus status, + IxAtmdAccClpStatus clp, + IX_OSAL_MBUF * mbufPtr); + +/** + * + * @ingroup IxAtmdAccAPI + * + * @brief Callback prototype for free buffer level is low. + * + * IxAtmdAccRxVcFreeLowCallback is the prototype of the user function + * which get called on a per-VC basis, when more mbufs are needed to + * continue the ATM data reception. This function is likely to supply + * more available mbufs by one or many calls to the replenish function + * @a ixAtmdAccRxVcFreeReplenish() + * + * This function is called when the number of available buffers for + * reception is going under the threshold level as defined + * in @a ixAtmdAccRxVcFreeLowCallbackRegister() + * + * This function is called inside an Qmgr dispatch context. No system + * resource or interrupt-unsafe feature should be used inside this + * callback. + * + * @sa ixAtmdAccRxVcFreeLowCallbackRegister + * @sa IxAtmdAccRxVcFreeLowCallback + * @sa ixAtmdAccRxVcFreeReplenish + * @sa ixAtmdAccRxVcFreeEntriesQuery + * @sa ixAtmdAccRxVcConnect + * + * @param userId @ref IxAtmdAccUserId [in] - user Id provided in the call + * to @a ixAtmdAccRxVcConnect() + * + * @return None + * + */ +typedef void (*IxAtmdAccRxVcFreeLowCallback) (IxAtmdAccUserId userId); + +/* ------------------------------------------------------ + Part of the IxAtmdAcc interface related to TX traffic + ------------------------------------------------------ */ + +/** + * + * @ingroup IxAtmdAccAPI + * + * @brief Buffer callback prototype. + * + * This function is called to relinguish ownership of a transmitted + * buffer chain to the user. + * + * @note -In the case of a chained mbuf the AmtdAcc component can + * chain many user buffers together and pass ownership to the user in + * one function call. + * + * @param userId @ref IxAtmdAccUserId [in] - user If provided at registration of this + * callback. + * @param mbufPtr @ref IX_OSAL_MBUF [in] - a pointer to mbufs or chain of mbufs and is + * guaranteed not to be a null pointer. + * + */ +typedef void (*IxAtmdAccTxVcBufferReturnCallback) (IxAtmdAccUserId userId, + IX_OSAL_MBUF * mbufPtr); + +/* ------------------------------------------------------ + Part of the IxAtmdAcc interface related to Initialisation + ------------------------------------------------------ */ + +/** + * + * @ingroup IxAtmdAccAPI + * + * @fn ixAtmdAccInit (void) + * + * @brief Initialise the IxAtmdAcc Component + * + * This function initialise the IxAtmdAcc component. This function shall + * be called before any other function of the API. Its role is to + * initialise all internal resources of the IxAtmdAcc component. + * + * The ixQmgr component needs to be initialized prior the use of + * @a ixAtmdAccInit() + * + * @param none + * + * Failing to initilialize the IxAtmdAcc API before any use of it will + * result in a failed status. + * If the specified component is not present, a success status will still be + * returned, however, a warning indicating the NPE to download to is not + * present will be issued. + * + * @return @li IX_SUCCESS initialisation is complete (in case of component not + * being present, a warning is clearly indicated) + * @return @li IX_FAIL unable to process this request either + * because this IxAtmdAcc is already initialised + * or some unspecified error has occrred. + */ +PUBLIC IX_STATUS ixAtmdAccInit (void); + +/** + * + * @ingroup IxAtmdAccAPI + * + * @fn ixAtmdAccShow (void) + * + * @brief Show IxAtmdAcc configuration on a per port basis + * + * @param none + * + * @return none + * + * @note - Display use printf() and are redirected to stdout + */ +PUBLIC void +ixAtmdAccShow (void); + +/** + * + * @ingroup IxAtmdAccAPI + * + * @fn ixAtmdAccStatsShow (void) + * + * @brief Show all IxAtmdAcc stats + * + * @param none + * + * @return none + * + * @note - Stats display use printf() and are redirected to stdout + */ +PUBLIC void +ixAtmdAccStatsShow (void); + +/** + * + * @ingroup IxAtmdAccAPI + * + * @fn ixAtmdAccStatsReset (void) + * + * @brief Reset all IxAtmdAcc stats + * + * @param none + * + * @return none + * + */ +PUBLIC void +ixAtmdAccStatsReset (void); + +/* ------------------------------------------------------ + Part of the IxAtmdAcc interface related to RX traffic + ------------------------------------------------------ */ + +/** + * + * @ingroup IxAtmdAccAPI + * + * @fn ixAtmdAccRxVcConnect (IxAtmLogicalPort port, + unsigned int vpi, + unsigned int vci, + IxAtmdAccAalType aalServiceType, + IxAtmRxQueueId rxQueueId, + IxAtmdAccUserId userCallbackId, + IxAtmdAccRxVcRxCallback rxCallback, + unsigned int minimumReplenishCount, + IxAtmConnId * connIdPtr, + IxAtmNpeRxVcId * npeVcIdPtr ) + * + * @brief Connect to a Aal Pdu receive service for a particular + * port/vpi/vci, and service type. + * + * This function allows a user to connect to an Aal5/Aal0/OAM Pdu receive service + * for a particular port/vpi/vci. It registers the callback and allocates + * internal resources and a Connection Id to be used in further API calls + * related to this VCC. + * + * The function will setup VC receive service on the specified rx queue. + * + * This function is blocking and makes use internal locks, and hence + * should not be called from an interrupt context. + * + * On return from @a ixAtmdAccRxVcConnect() with a failure status, the + * connection Id parameter is unspecified. Its value cannot be used. + * A connId is the reference by which IxAtmdAcc refers to a + * connected VC. This identifier is the result of a succesful call + * to a connect function. This identifier is invalid after a + * sucessful call to a disconnect function. + * + * Calling this function for the same combination of Vpi, Vci and more + * than once without calling @a ixAtmdAccRxVcTryDisconnect() will result in a + * failure status. + * + * If this function returns success the user should supply receive + * buffers by calling @a ixAtmdAccRxVcFreeReplenish() and then call + * @a ixAtmdAccRxVcEnable() to begin receiving pdus. + * + * There is a choice of two receive Qs on which the VC pdus could be + * receive. The user must associate the VC with one of these. Essentially + * having two qs allows more flexible system configuration such as have + * high prioriy traffic on one q (e.g. voice) and low priority traffic on + * the other (e.g. data). The high priority Q could be serviced in + * preference to the low priority Q. One queue may be configured to be + * serviced as soon as there is traffic, the other queue may be configured + * to be serviced by a polling mechanism running at idle time. + * + * Two AAL0 services supporting 48 or 52 byte cell data are provided. + * Received AAL0 PDUs will be be a multiple of the cell data size (48/52). + * AAL0_52 is a raw cell service and includes an ATM cell header + * (excluding HEC) at the start of each cell. + * + * A single "OAM Rx channel" for all ports may be enabled by + * establishing a dedicated OAM Rx connection. + * + * The OAM service allows buffers containing 52 byte OAM F4/F5 cells + * to be transmitted and received over the dedicated OAM channels. + * HEC is appended/removed, and CRC-10 performed by the NPE. The OAM + * service offered by AtmdAcc is a raw cell transport service. + * It is assumed that ITU I.610 procedures that make use of this + * service are implemented above AtmdAcc. + * + * Note that the dedicated OAM connections are established on + * reserved VPI,VCI, and (in the case of Rx) port values. + * These values are used purely to descriminate the dedicated OAM channels + * and do not identify a particular OAM F4/F5 flow. F4/F5 flows may be + * realised for particluar VPI/VCIs by manipulating the VPI,VCI + * fields of the ATM cell headers of cells in the buffers passed + * to AtmdAcc. + * + * Calling this function prior to enable the port will fail. + * + * @sa ixAtmdAccRxDispatch + * @sa ixAtmdAccRxVcEnable + * @sa ixAtmdAccRxVcDisable + * @sa ixAtmdAccRxVcTryDisconnect + * @sa ixAtmdAccPortEnable + * + * @param port @ref IxAtmLogicalPort [in] - VC identification : logical PHY port + * [@a IX_UTOPIA_PORT_0 .. @a IX_UTOPIA_MAX_PORTS - 1] + * @param vpi unsigned int [in] - VC identification : ATM Vpi [0..255] or IX_ATMDACC_OAM_VPI + * @param vci unsigned int [in] - VC identification : ATM Vci [0..65535] or IX_ATMDACC_OAM_VCI + * @param aalServiceType @ref IxAtmdAccAalType [in] - type of service: AAL5, AAL0_48, AAL0_52, or OAM + * @param rxQueueId @ref IxAtmRxQueueId [in] - this identifieds which of two Qs the VC + * should use.when icoming traffic is processed + * @param userCallbackId @ref IxAtmdAccUserId [in] - user Id used later as a parameter to + * the supplied rxCallback. + * @param rxCallback [in] @ref IxAtmdAccRxVxRxCallback - function called when mbufs are received. + * This parameter cannot be a null pointer. + * @param bufferFreeCallback [in] - function to be called to return + * ownership of buffers to IxAtmdAcc user. + * @param minimumReplenishCount unsigned int [in] - For AAL5/AAL0 the number of free mbufs + * to be used with this channel. Use a high number when the expected traffic + * rate on this channel is high, or when the user's mbufs are small, or when + * the RxVcFreeLow Notification has to be invoked less often. When this + * value is IX_ATMDACC_DEFAULT_REPLENISH_COUNT, the minimum of + * resources will be used. Depending on traffic rate, pdu + * size and mbuf size, rxfree queue size, polling/interrupt rate, this value may + * require to be replaced by a different value in the range 1-128 + * For OAM the rxFree queue size is fixed by atmdAcc and this parameter is ignored. + * @param connIdPtr @ref IxAtmConnId [out] - pointer to a connection Id + * This parameter cannot be a null pointer. + * @param npeVcIdPtr @ref IxAtmNpeRxVcId [out] - pointer to an npe Vc Id + * This parameter cannot be a null pointer. + * + * @return @li IX_SUCCESS successful call to IxAtmdAccRxVcConnect + * @return @li IX_ATMDACC_BUSY cannot process this request : + * no VC is available + * @return @li IX_FAIL + * parameter error, + * VC already in use, + * attempt to connect AAL service on reserved OAM VPI/VCI, + * attempt to connect OAM service on VPI/VCI other than the reserved OAM VPI/VCI, + * port is not initialised, + * or some other error occurs during processing. + * + */ +PUBLIC IX_STATUS ixAtmdAccRxVcConnect (IxAtmLogicalPort port, + unsigned int vpi, + unsigned int vci, + IxAtmdAccAalType aalServiceType, + IxAtmRxQueueId rxQueueId, + IxAtmdAccUserId userCallbackId, + IxAtmdAccRxVcRxCallback rxCallback, + unsigned int minimumReplenishCount, + IxAtmConnId * connIdPtr, + IxAtmNpeRxVcId * npeVcIdPtr ); + +/** + * + * @ingroup IxAtmdAccAPI + * + * @fn ixAtmdAccRxVcFreeReplenish (IxAtmConnId connId, + IX_OSAL_MBUF * mbufPtr) + * + * @brief Provide free mbufs for data reception on a connection. + * + * This function provides mbufs for data reception by the hardware. This + * function needs to be called by the user on a regular basis to ensure + * no packet loss. Providing free buffers is a connection-based feature; + * each connection can have different requirements in terms of buffer size + * number of buffers, recycling rate. This function could be invoked from + * within the context of a @a IxAtmdAccRxVcFreeLowCallback() callback + * for a particular VC + * + * Mbufs provided through this function call can be chained. They will be + * unchained internally. A call to this function with chained mbufs or + * multiple calls with unchained mbufs are equivalent, but calls with + * unchained mbufs are more efficients. + * + * Mbufs provided to this interface need to be able to hold at least one + * full cell payload (48/52 bytes, depending on service type). + * Chained buffers with a size less than the size supported by the hardware + * will be returned through the rx callback provided during the connect step. + * + * Failing to invoke this function prior to enabling the RX traffic + * can result in packet loss. + * + * This function is not reentrant for the same connId. + * + * This function does not use system resources and can be + * invoked from an interrupt context. + * + * @note - Over replenish is detected, and extra mbufs are returned through + * the rx callback provided during the connect step. + * + * @note - Mbuf provided to the replenish function should have a length greater or + * equal to 48/52 bytes according to service type. + * + * @note - The memory cache of mMbuf payload should be invalidated prior to Mbuf + * submission. Flushing the Mbuf headers is handled by IxAtmdAcc. + * + * @note - When a chained mbuf is provided, this function process the mbufs + * up to the hardware limit and invokes the user-supplied callback + * to release extra buffers. + * + * @sa ixAtmdAccRxVcFreeLowCallbackRegister + * @sa IxAtmdAccRxVcFreeLowCallback + * @sa ixAtmdAccRxVcConnect + * + * @param connId @ref IxAtmConnId [in] - connection Id as returned from a succesfull call to + * @a IxAtmdAccRxVcConnect() + * @param mbufPtr @ref IX_OSAL_MBUF [in] - pointer to a mbuf structure to be used for data + * reception. The mbuf pointed to by this parameter can be chained + * to an other mbuf. + * + * @return @li IX_SUCCESS successful call to @a ixAtmdAccRxVcFreeReplenish() + * and the mbuf is now ready to use for incoming traffic. + * @return @li IX_ATMDACC_BUSY cannot process this request because + * the max number of outstanding free buffers has been reached + * or the internal resources have exhausted for this VC. + * The user is responsible for retrying this request later. + * @return @li IX_FAIL cannot process this request because of parameter + * errors or some unspecified internal error has occurred. + * + * @note - It is not always guaranteed the replenish step to be as fast as the + * hardware is consuming Rx Free mbufs. There is nothing in IxAtmdAcc to + * guarantee that replenish reaches the rxFree threshold level. If the + * threshold level is not reached, the next rxFree low notification for + * this channel will not be triggered. + * The preferred ways to replenish can be as follows (depending on + * applications and implementations) : + * @li Replenish in a rxFree low notification until the function + * ixAtmdAccRxVcFreeReplenish() returns IX_ATMDACC_BUSY + * @li Query the queue level using @sa ixAtmdAccRxVcFreeEntriesQuery, then + * , replenish using @a ixAtmdAccRxVcFreeReplenish(), then query the queue + * level again, and replenish if the threshold is still not reached. + * @li Trigger replenish from an other event source and use rxFree starvation + * to throttle the Rx traffic. + * + */ +PUBLIC IX_STATUS ixAtmdAccRxVcFreeReplenish (IxAtmConnId connId, + IX_OSAL_MBUF * mbufPtr); + +/** + * + * @ingroup IxAtmdAccAPI + * + * @fn ixAtmdAccRxVcFreeLowCallbackRegister (IxAtmConnId connId, + unsigned int numberOfMbufs, + IxAtmdAccRxVcFreeLowCallback callback) + * + * @brief Configure the RX Free threshold value and register a callback + * to handle threshold notifications. + * + * The function ixAtmdAccRxVcFreeLowCallbackRegister sets the threshold value for + * a particular RX VC. When the number of buffers reaches this threshold + * the callback is invoked. + * + * This function should be called once per VC before RX traffic is + * enabled.This function will fail if the curent level of the free buffers + * is equal or less than the threshold value. + * + * @sa ixAtmdAccRxVcFreeLowCallbackRegister + * @sa IxAtmdAccRxVcFreeLowCallback + * @sa ixAtmdAccRxVcFreeReplenish + * @sa ixAtmdAccRxVcFreeEntriesQuery + * @sa ixAtmdAccRxVcConnect + * + * @param connId @ref IxAtmConnId [in] - connection Id as resulted from a succesfull call + * to @a IxAtmdAccRxVcConnect() + * @param numberOfMbufs unsigned int [in] - threshold number of buffers. This number + * has to be a power of 2, one of the values 0,1,2,4,8,16,32.... + * The maximum value cannot be more than half of the rxFree queue + * size (which can be retrieved using @a ixAtmdAccRxVcFreeEntriesQuery() + * before any use of the @a ixAtmdAccRxVcFreeReplenish() function) + * @param callback @ref IxAtmdAccRxVcFreeLowCallback [in] - function telling the user that the number of + * free buffers has reduced to the threshold value. + * + * @return @li IX_SUCCESS Threshold set successfully. + * @return @li IX_FAIL parameter error or the current number of free buffers + * is less than or equal to the threshold supplied or some + * unspecified error has occrred. + * + * @note - the callback will be called when the threshold level will drop from + * exactly (numberOfMbufs + 1) to (numberOfMbufs). + * + */ +PUBLIC IX_STATUS ixAtmdAccRxVcFreeLowCallbackRegister (IxAtmConnId connId, + unsigned int numberOfMbufs, + IxAtmdAccRxVcFreeLowCallback callback); + +/** + * + * @ingroup IxAtmdAccAPI + * + * @fn ixAtmdAccRxVcFreeEntriesQuery (IxAtmConnId connId, + unsigned int *numberOfMbufsPtr) + * + * @brief Get the number of rx mbufs the system can accept to replenish the + * the rx reception mechanism on a particular channel + * + * The ixAtmdAccRxVcFreeEntriesQuery function is used to retrieve the current + * number of available mbuf entries for reception, on a per-VC basis. This + * function can be used to know the number of mbufs which can be provided + * using @a ixAtmdAccRxVcFreeReplenish(). + * + * This function can be used from a timer context, or can be associated + * with a threshold event, or can be used inside an active polling + * mechanism which is under user control. + * + * This function is reentrant and does not use system resources and can + * be invoked from an interrupt context. + * + * @param connId @ref IxAtmConnId [in] - connection Id as resulted from a succesfull call + * to @a IxAtmdAccRxVcConnect() + * @param numberOfMbufsPtr unsigned int [out] - Pointer to the number of available entries. + * . This parameter cannot be a null pointer. + * + * @return @li IX_SUCCESS the current number of mbufs not yet used for incoming traffic + * @return @li IX_FAIL invalid parameter + * + * @sa ixAtmdAccRxVcFreeReplenish + * + */ +PUBLIC IX_STATUS ixAtmdAccRxVcFreeEntriesQuery (IxAtmConnId connId, + unsigned int *numberOfMbufsPtr); + +/** + * + * @ingroup IxAtmdAccAPI + * + * @fn ixAtmdAccRxVcEnable (IxAtmConnId connId) + * + * @brief Start the RX service on a VC. + * + * This functions kicks-off the traffic reception for a particular VC. + * Once invoked, incoming PDUs will be made available by the hardware + * and are eventually directed to the @a IxAtmdAccRxVcRxCallback() callback + * registered for the connection. + * + * If the traffic is already running, this function returns IX_SUCCESS. + * This function can be invoked many times. + * + * IxAtmdAccRxVcFreeLowCallback event will occur only after + * @a ixAtmdAccRxVcEnable() function is invoked. + * + * Before using this function, the @a ixAtmdAccRxVcFreeReplenish() function + * has to be used to replenish the RX Free queue. If not, incoming traffic + * may be discarded.and in the case of interrupt driven reception the + * @a IxAtmdAccRxVcFreeLowCallback() callback may be invoked as a side effect + * during a replenish action. + * + * This function is not reentrant and should not be used inside an + * interrupt context. + * + * For an VC connection this function can be called after a call to + * @a ixAtmdAccRxVcDisable() and should not be called after + * @a ixAtmdAccRxVcTryDisconnect() + * + * @sa ixAtmdAccRxVcDisable + * @sa ixAtmdAccRxVcConnect + * @sa ixAtmdAccRxVcFreeReplenish + * + * @param connId @ref IxAtmConnId [in] - connection Id as resulted from a succesfull call + * to @a IxAtmdAccRxVcConnect() + * + * @return @li IX_SUCCESS successful call to ixAtmdAccRxVcEnable + * @return @li IX_ATMDACC_WARNING the channel is already enabled + * @return @li IX_FAIL invalid parameters or some unspecified internal + * error occured. + * + */ +PUBLIC IX_STATUS ixAtmdAccRxVcEnable (IxAtmConnId connId); + +/** + * + * @ingroup IxAtmdAccAPI + * + * @fn ixAtmdAccRxVcDisable (IxAtmConnId connId) + * + * @brief Stop the RX service on a VC. + * + * This functions stops the traffic reception for a particular VC connection. + * + * Once invoked, incoming Pdus are discarded by the hardware. Any Pdus + * pending will be freed to the user + * + * Hence once this function returns no more receive callbacks will be + * called for that VC. However, buffer free callbacks will be invoked + * until such time as all buffers supplied by the user have been freed + * back to the user + * + * Calling this function doe not invalidate the connId. + * @a ixAtmdAccRxVcEnable() can be invoked to enable Pdu reception again. + * + * If the traffic is already stopped, this function returns IX_SUCCESS. + * + * This function is not reentrant and should not be used inside an + * interrupt context. + * + * @sa ixAtmdAccRxVcConnect + * @sa ixAtmdAccRxVcEnable + * @sa ixAtmdAccRxVcDisable + * + * @param connId @ref IxAtmConnId [in] - connection Id as resulted from a succesfull call to @a + * IxAtmdAccRxVcConnect() + * + * @return @li IX_SUCCESS successful call to @a ixAtmdAccRxVcDisable(). + * @return @li IX_ATMDACC_WARNING the channel is already disabled + * @return @li IX_FAIL invalid parameters or some unspecified internal error occured + * + */ +PUBLIC IX_STATUS ixAtmdAccRxVcDisable (IxAtmConnId connId); + +/** + * + * @ingroup IxAtmdAccAPI + * + * @fn ixAtmdAccRxVcTryDisconnect (IxAtmConnId connId) + * + * @brief Disconnect a VC from the RX service. + * + * This function deregisters the VC and guarantees that all resources + * associated with this VC are free. After its execution, the connection + * Id is not available. + * + * This function will fail until such time as all resources allocated to + * the VC connection have been freed. The user is responsible to delay and + * call again this function many times until a success status is returned. + * + * This function needs internal locks and should not be called from an + * interrupt context + * + * @param connId @ref IxAtmConnId [in] - connection Id as resulted from a succesfull call to + * @a IxAtmdAccRxVcConnect() + * + * @return @li IX_SUCCESS successful call to ixAtmdAccRxVcDisable + * @return @li IX_ATMDACC_RESOURCES_STILL_ALLOCATED not all resources + * associated with the connection have been freed. + * @return @li IX_FAIL cannot process this request because of a parameter + * error + * + */ +PUBLIC IX_STATUS ixAtmdAccRxVcTryDisconnect (IxAtmConnId connId); + +/* ------------------------------------------------------ + Part of the IxAtmdAcc interface related to TX traffic + ------------------------------------------------------ */ + +/** + * + * @ingroup IxAtmdAccAPI + * + * @fn ixAtmdAccTxVcConnect (IxAtmLogicalPort port, + unsigned int vpi, + unsigned int vci, + IxAtmdAccAalType aalServiceType, + IxAtmdAccUserId userId, + IxAtmdAccTxVcBufferReturnCallback bufferFreeCallback, + IxAtmConnId * connIdPtr) + * + * @brief Connect to a Aal Pdu transmit service for a particular + * port/vpi/vci and service type. + * + * This function allows a user to connect to an Aal5/Aal0/OAM Pdu transmit service + * for a particular port/vpi/vci. It registers the callback and allocates + * internal resources and a Connection Id to be used in further API calls + * related to this VC. + * + * The function will setup VC transmit service on the specified on the + * specified port. A connId is the reference by which IxAtmdAcc refers to a + * connected VC. This identifier is the result of a succesful call + * to a connect function. This identifier is invalid after a + * sucessful call to a disconnect function. + * + * This function needs internal locks, and hence should not be called + * from an interrupt context. + * + * On return from @a ixAtmdAccTxVcConnect() with a failure status, the + * connection Id parameter is unspecified. Its value cannot be used. + * + * Calling this function for the same combination of port, Vpi, Vci and + * more than once without calling @a ixAtmdAccTxVcTryDisconnect() will result + * in a failure status. + * + * Two AAL0 services supporting 48 or 52 byte cell data are provided. + * Submitted AAL0 PDUs must be a multiple of the cell data size (48/52). + * AAL0_52 is a raw cell service the client must format + * the PDU with an ATM cell header (excluding HEC) at the start of + * each cell, note that AtmdAcc does not validate the cell headers in + * a submitted PDU. + * + * For the OAM service an "OAM Tx channel" may be enabled for a port + * by establishing a single dedicated OAM Tx connection on that port. + * + * The OAM service allows buffers containing 52 byte OAM F4/F5 cells + * to be transmitted and received over the dedicated OAM channels. + * HEC is appended/removed, and CRC-10 performed by the NPE. The OAM + * service offered by AtmdAcc is a raw cell transport service. + * It is assumed that ITU I.610 procedures that make use of this + * service are implemented above AtmdAcc. + * + * Note that the dedicated OAM connections are established on + * reserved VPI,VCI, and (in the case of Rx) port values. + * These values are used purely to descriminate the dedicated OAM channels + * and do not identify a particular OAM F4/F5 flow. F4/F5 flows may be + * realised for particluar VPI/VCIs by manipulating the VPI,VCI + * fields of the ATM cell headers of cells in the buffers passed + * to AtmdAcc. + * + * Calling this function before enabling the port will fail. + * + * @sa ixAtmdAccTxVcTryDisconnect + * @sa ixAtmdAccPortTxScheduledModeEnable + * @sa ixAtmdAccPortEnable + * + * @param port @ref IxAtmLogicalPort [in] - VC identification : logical PHY port + * [@a IX_UTOPIA_PORT_0 .. @a IX_UTOPIA_MAX_PORTS - 1] + * @param vpi unsigned int [in] - VC identification : ATM Vpi [0..255] or IX_ATMDACC_OAM_VPI + * @param vci unsigned int [in] - VC identification : ATM Vci [0..65535] or IX_ATMDACC_OAM_VCI + * @param aalServiceType @ref IxAtmdAccAalType [in] - type of service AAL5, AAL0_48, AAL0_52, or OAM + * @param userId @ref IxAtmdAccUserId [in] - user id to be used later during callbacks related + * to this channel + * @param bufferFreeCallback @ref IxAtmdAccTxVcBufferReturnCallback [in] - function called when mbufs + * transmission is complete. This parameter cannot be a null + * pointer. + * @param connIdPtr @ref IxAtmConnId [out] - Pointer to a connection Id. + * This parameter cannot be a null pointer. + * + * @return @li IX_SUCCESS successful call to @a IxAtmdAccRxVcConnect(). + * @return @li IX_ATMDACC_BUSY cannot process this request + * because no VC is available + * @return @li IX_FAIL + * parameter error, + * VC already in use, + * attempt to connect AAL service on reserved OAM VPI/VCI, + * attempt to connect OAM service on VPI/VCI other than the reserved OAM VPI/VCI, + * port is not initialised, + * or some other error occurs during processing. + * + * @note - Unscheduled mode is not supported in ixp425 1.0. Therefore, the + * function @a ixAtmdAccPortTxScheduledModeEnable() need to be called + * for this port before any establishing a Tx Connection + */ +PUBLIC IX_STATUS ixAtmdAccTxVcConnect (IxAtmLogicalPort port, + unsigned int vpi, + unsigned int vci, + IxAtmdAccAalType aalServiceType, + IxAtmdAccUserId userId, + IxAtmdAccTxVcBufferReturnCallback bufferFreeCallback, + IxAtmConnId * connIdPtr); + +/** + * + * @ingroup IxAtmdAccAPI + * + * @fn ixAtmdAccTxVcPduSubmit (IxAtmConnId connId, + IX_OSAL_MBUF * mbufPtr, + IxAtmdAccClpStatus clp, + unsigned int numberOfCells) + * + * @brief Submit a Pdu for transmission on connection. + * + * A data user calls this function to submit an mbufs containing a Pdu + * to be transmitted. The buffer supplied can be chained and the Pdu it + * contains must be complete. + * + * The transmission behavior of this call depends on the operational mode + * of the port on which the connection is made. + * + * In unscheduled mode the mbuf will be submitted to the hardware + * immediately if sufficent resource is available. Otherwise the function + * will return failure. + * + * In scheduled mode the buffer is queued internally in IxAtmdAcc. The cell + * demand is made known to the traffic shaping entity. Cells from the + * buffers are MUXed onto the port some time later as dictated by the + * traffic shaping entity. The traffic shaping entity does this by sending + * transmit schedules to IxAtmdAcc via @a ixAtmdAccPortTxProcess() function call. + * + * Note that the dedicated OAM channel is scheduled just like any + * other channel. This means that any OAM traffic relating to an + * active AAL0/AAL5 connection will be scheduled independantly of the + * AAL0/AAL5 traffic for that connection. + * + * When transmission is complete, the TX Done mechanism will give the + * owmnership of these buffers back to the customer. The tx done mechanism + * must be in operation before transmission is attempted. + * + * For AAL0/OAM submitted AAL0 PDUs must be a multiple of the cell data + * size (48/52). AAL0_52 and OAM are raw cell services, and the client + * must format the PDU with an ATM cell header (excluding HEC) at the + * start of each cell, note that AtmdAcc does not validate the cell headers in + * a submitted PDU. + * + * + * @sa IxAtmdAccTxVcBufferReturnCallback + * @sa ixAtmdAccTxDoneDispatch + * + * @param connId @ref IxAtmConnId [in] - connection Id as resulted from a succesfull call to + * @a ixAtmdAccTxVcConnect() + * @param mbufPtr @ref IX_OSAL_MBUF [in] - pointer to a chained structure of mbufs to transmit. + * This parameter cannot be a null pointer. + * @param clp @ref IxAtmdAccClpStatus [in] - clp indication for this PDU. All cells of this pdu + * will be sent with the clp bit set + * @param numberOfCells unsigned int [in] - number of cells in the PDU. + * + * @return @li IX_SUCCESS successful call to @a ixAtmdAccTxVcPduSubmit() + * The pdu pointed by the mbufPtr parameter will be + * transmitted + * @return @li IX_ATMDACC_BUSY unable to process this request because + * internal resources are all used. The caller is responsible + * for retrying this request later. + * @return @li IX_FAIL unable to process this request because of error + * in the parameters (wrong connId supplied, + * or wrong mbuf pointer supplied), the total length of all buffers + * in the chain should be a multiple of the cell size + * ( 48/52 depending on the service type ), + * or unspecified error during processing + * + * @note - This function in not re-entrant for the same VC (e.g. : two + * thread cannot send PDUs for the same VC). But two threads can + * safely call this function with a different connection Id + * + * @note - In unscheduled mode, this function is not re-entrant on a per + * port basis. The size of pdus is limited to 8Kb. + * + * @note - 0-length mbufs should be removed from the chain before submission. + * The total length of the pdu (sdu + padding +trailer) has to be + * updated in the header of the first mbuf of a chain of mbufs. + * + * @note - Aal5 trailer information (UUI, CPI, SDU length) has to be supplied + * before submission. + * + * @note - The payload memory cache should be flushed, if needed, prior to + * transmission. Mbuf headers are flushed by IxAtmdAcc + * + * @note - This function does not use system resources and can be used + * inside an interrupt context + */ +PUBLIC IX_STATUS ixAtmdAccTxVcPduSubmit (IxAtmConnId connId, + IX_OSAL_MBUF * mbufPtr, + IxAtmdAccClpStatus clp, + unsigned int numberOfCells); + +/** + * + * @ingroup IxAtmdAccAPI + * + * @fn ixAtmdAccTxVcTryDisconnect (IxAtmConnId connId) + * + * @brief Disconnect from a Aal Pdu transmit service for a particular + * port/vpi/vci. + * + * This function deregisters the VC and guarantees that all resources + * associated with this VC are free. After its execution, the connection + * Id is not available. + * + * This function will fail until such time as all resources allocated to + * the VC connection have been freed. The user is responsible to delay + * and call again this function many times until a success status is + * returned. + * + * After its execution, the connection Id is not available. + * + * @param connId @ref IxAtmConnId [in] - connection Id as resulted from a succesfull call to + * @a ixAtmdAccTxVcConnect() + * + * @return @li IX_SUCCESS successful call to @a ixAtmdAccTxVcTryDisconnect() + * @return @li IX_ATMDACC_RESOURCES_STILL_ALLOCATED not all resources + * associated with the connection have been freed. This condition will + * disappear after Tx and TxDone is complete for this channel. + * @return @li IX_FAIL unable to process this request because of errors + * in the parameters (wrong connId supplied) + * + * @note - This function needs internal locks and should not be called + * from an interrupt context + * + * @note - If the @a IX_ATMDACC_RESOURCES_STILL_ALLOCATED error does not + * clear after a while, this may be linked to a previous problem + * of cell overscheduling. Diabling the port and retry a disconnect + * will free the resources associated with this channel. + * + * @sa ixAtmdAccPortTxProcess + * + */ +PUBLIC IX_STATUS ixAtmdAccTxVcTryDisconnect (IxAtmConnId connId); + +#endif /* IXATMDACC_H */ + +/** + * @} defgroup IxAtmdAccAPI + */ + + diff --git a/cpu/ixp/npe/include/IxAtmdAccCtrl.h b/cpu/ixp/npe/include/IxAtmdAccCtrl.h new file mode 100644 index 0000000..e223049 --- /dev/null +++ b/cpu/ixp/npe/include/IxAtmdAccCtrl.h @@ -0,0 +1,1958 @@ + +/** + * @file IxAtmdAccCtrl.h + * + * @date 20-Mar-2002 + * + * @brief IxAtmdAcc Public API + * + * This file contains the public API of IxAtmdAcc, related to the + * control functions of the 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 -- + */ + +/* ------------------------------------------------------ + Doxygen group definitions + ------------------------------------------------------ */ + +/** + * + * @defgroup IxAtmdAccCtrlAPI IXP400 ATM Driver Access (IxAtmdAcc) Control API + * + * @brief The public API for the IXP400 Atm Driver Control component + * + * IxAtmdAcc is the low level interface by which AAL PDU get transmitted + * to,and received from the Utopia bus + * + * This part is related to the Control configuration + * + * @{ + */ + +#ifndef IXATMDACCCTRL_H +#define IXATMDACCCTRL_H + +#include "IxAtmdAcc.h" + +/* ------------------------------------------------------ + AtmdAccCtrl Data Types definition + ------------------------------------------------------ */ + +/** +* +* @ingroup IxAtmdAccCtrlAPI +* +* @def IX_ATMDACC_PORT_DISABLE_IN_PROGRESS +* +* @brief Port enable return code +* +* This constant is used to tell IxAtmDAcc user that the port disable +* functions are not complete. The user can call ixAtmdAccPortDisableComplete() +* to find out when the disable has finished. The port enable can then proceed. +* +*/ +#define IX_ATMDACC_PORT_DISABLE_IN_PROGRESS 5 + +/** +* +* @ingroup IxAtmdAccCtrlAPI +* +* @def IX_ATMDACC_ALLPDUS +* +* @brief All PDUs +* +* This constant is used to tell IxAtmDAcc to process all PDUs from +* the RX queue or the TX Done +* +* @sa IxAtmdAccRxDispatcher +* @sa IxAtmdAccTxDoneDispatcher +* +*/ +#define IX_ATMDACC_ALLPDUS 0xffffffff + +/* ------------------------------------------------------ + Part of the IxAtmdAcc interface related to RX traffic + ------------------------------------------------------ */ + +/** + * + * @ingroup IxAtmdAccCtrlAPI + * + * @brief Callback prototype for notification of available PDUs for + * an Rx Q. + * + * This a protoype for a function which is called when there is at + * least one Pdu available for processing on a particular Rx Q. + * + * This function should call @a ixAtmdAccRxDispatch() with + * the aprropriate number of parameters to read and process the Rx Q. + * + * @sa ixAtmdAccRxDispatch + * @sa ixAtmdAccRxVcConnect + * @sa ixAtmdAccRxDispatcherRegister + * + * @param rxQueueId @ref IxAtmRxQueueId [in] indicates which RX queue to has Pdus to process. + * @param numberOfPdusToProcess unsigned int [in] indicates the minimum number of + * PDUs available to process all PDUs from the queue. + * @param reservedPtr unsigned int* [out] pointer to a int location which can + * be written to, but does not retain written values. This is + * provided to make this prototype compatible + * with @a ixAtmdAccRxDispatch() + * + * @return @li int - ignored. + * + */ +typedef IX_STATUS (*IxAtmdAccRxDispatcher) (IxAtmRxQueueId rxQueueId, + unsigned int numberOfPdusToProcess, + unsigned int *reservedPtr); + +/* ------------------------------------------------------ + Part of the IxAtmdAcc interface related to TX traffic + ------------------------------------------------------ */ + +/** + * + * @ingroup IxAtmdAccCtrlAPI + * + * @brief Callback prototype for transmitted mbuf when threshold level is + * crossed. + * + * IxAtmdAccTxDoneDispatcher is the prototype of the user function + * which get called when pdus are completely transmitted. This function + * is likely to call the @a ixAtmdAccTxDoneDispatch() function. + * + * This function is called when the number of available pdus for + * reception is crossing the threshold level as defined + * in @a ixAtmdAccTxDoneDispatcherRegister() + * + * This function is called inside an Qmgr dispatch context. No system + * resource or interrupt-unsafe feature should be used inside this + * callback. + * + * Transmitted buffers recycling implementation is a sytem-wide mechanism + * and needs to be set before any traffic is started. If this threshold + * mechanism is not used, the user is responsible for polling the + * transmitted buffers with @a ixAtmdAccTxDoneDispatch() + * and @a ixAtmdAccTxDoneLevelQuery() functions. + * + * @sa ixAtmdAccTxDoneDispatcherRegister + * @sa ixAtmdAccTxDoneDispatch + * @sa ixAtmdAccTxDoneLevelQuery + * + * @param numberOfPdusToProcess unsigned int [in] - The current number of pdus currently + * available for recycling + * @param *reservedPtr unsigned int [out] - pointer to a int location which can be + * written to but does not retain written values. This is provided + * to make this prototype compatible + * with @a ixAtmdAccTxDoneDispatch() + * + * @return @li IX_SUCCESS This is provided to make + * this prototype compatible with @a ixAtmdAccTxDoneDispatch() + * @return @li IX_FAIL invalid parameters or some unspecified internal + * error occured. This is provided to make + * this prototype compatible with @a ixAtmdAccTxDoneDispatch() + * + */ +typedef IX_STATUS (*IxAtmdAccTxDoneDispatcher) (unsigned int numberOfPdusToProcess, + unsigned int *reservedPtr); + +/** +* +* @ingroup IxAtmdAccCtrlAPI +* +* @brief Notification that the threshold number of scheduled cells +* remains in a port's transmit Q. +* +* The is the prototype for of the user notification function which +* gets called on a per-port basis, when the number of remaining +* scheduled cells to be transmitted decreases to the threshold level. +* The number of cells passed as a parameter can be used for scheduling +* purposes as the maximum number of cells that can be passed in a +* schedule table to the @a ixAtmdAccPortTxProcess() function. +* +* @sa ixAtmdAccPortTxCallbackRegister +* @sa ixAtmdAccPortTxProcess +* @sa ixAtmdAccPortTxFreeEntriesQuery +* +* @param port @ref IxAtmLogicalPort [in] - logical PHY port [@a IX_UTOPIA_PORT_0 .. @a IX_UTOPIA_MAX_PORTS - 1] +* @param numberOfAvailableCells unsigned int [in] - number of available +* cell entries.for the port +* +* @note - This functions shall not use system resources when used +* inside an interrupt context. +* +*/ +typedef void (*IxAtmdAccPortTxLowCallback) (IxAtmLogicalPort port, + unsigned int numberOfAvailableCells); + +/** +* +* @ingroup IxAtmdAccCtrlAPI +* +* @brief Prototype to submit cells for transmission +* +* IxAtmdAccTxVcDemandUpdateCallback is the prototype of the callback +* function used by AtmD to notify an ATM Scheduler that the user of +* a VC has submitted cells for transmission. +* +* @sa IxAtmdAccTxVcDemandUpdateCallback +* @sa IxAtmdAccTxVcDemandClearCallback +* @sa IxAtmdAccTxSchVcIdGetCallback +* @sa ixAtmdAccPortTxScheduledModeEnable +* +* @param port @ref IxAtmLogicalPort [in] - Specifies the ATM port on which the VC to be updated +* is established +* @param vcId int [in] - Identifies the VC to be updated. This is the value +* returned by the @a IxAtmdAccTxSchVcIdGetCallback() call . +* @param numberOfCells unsigned int [in] - Indicates how many ATM cells should be added +* to the queue for this VC. +* +* @return @li IX_SUCCESS the function is registering the cell demand for +* this VC. +* @return @li IX_FAIL the function cannot register cell for this VC : the +* scheduler maybe overloaded or misconfigured +* +*/ +typedef IX_STATUS (*IxAtmdAccTxVcDemandUpdateCallback) (IxAtmLogicalPort port, + int vcId, + unsigned int numberOfCells); + +/** +* +* @ingroup IxAtmdAccCtrlAPI +* +* @brief prototype to remove all currently queued cells from a +* registered VC +* +* IxAtmdAccTxVcDemandClearCallback is the prototype of the function +* to remove all currently queued cells from a registered VC. The +* pending cell count for the specified VC is reset to zero. After the +* use of this callback, the scheduler shall not schedule more cells +* for this VC. +* +* This callback function is called during a VC disconnection +* @a ixAtmdAccTxVcTryDisconnect() +* +* @sa IxAtmdAccTxVcDemandUpdateCallback +* @sa IxAtmdAccTxVcDemandClearCallback +* @sa IxAtmdAccTxSchVcIdGetCallback +* @sa ixAtmdAccPortTxScheduledModeEnable +* @sa ixAtmdAccTxVcTryDisconnect +* +* @param port @ref IxAtmLogicalPort [in] - Specifies the ATM port on which the VC to be cleared +* is established +* @param vcId int [in] - Identifies the VC to be cleared. This is the value +* returned by the @a IxAtmdAccTxSchVcIdGetCallback() call . +* +* @return none +* +*/ +typedef void (*IxAtmdAccTxVcDemandClearCallback) (IxAtmLogicalPort port, + int vcId); + +/** +* +* @ingroup IxAtmdAccCtrlAPI +* +* @brief prototype to get a scheduler vc id +* +* IxAtmdAccTxSchVcIdGetCallback is the prototype of the function to get +* a scheduler vcId +* +* @sa IxAtmdAccTxVcDemandUpdateCallback +* @sa IxAtmdAccTxVcDemandClearCallback +* @sa IxAtmdAccTxSchVcIdGetCallback +* @sa ixAtmdAccPortTxScheduledModeEnable +* +* @param port @ref IxAtmLogicalPort [in] - Specifies the ATM logical port on which the VC is +* established +* @param vpi unsigned int [in] - For AAL0/AAL5 specifies the ATM vpi on which the +* VC is established. +* For OAM specifies the dedicated "OAM Tx channel" VPI. +* @param vci unsigned int [in] - For AAL0/AAL5 specifies the ATM vci on which the +* VC is established. +* For OAM specifies the dedicated "OAM Tx channel" VCI. +* @param connId @ref IxAtmConnId [in] - specifies the IxAtmdAcc connection Id already +* associated with this VC +* @param vcId int* [out] - pointer to a vcId +* +* @return @li IX_SUCCESS the function is returning a Scheduler vcId for this +* VC +* @return @li IX_FAIL the function cannot process scheduling for this VC. +* the contents of vcId is unspecified +* +*/ +typedef IX_STATUS (*IxAtmdAccTxSchVcIdGetCallback) (IxAtmLogicalPort port, + unsigned int vpi, + unsigned int vci, + IxAtmConnId connId, + int *vcId); + +/* ------------------------------------------------------ + Part of the IxAtmdAcc interface related to RX traffic + ------------------------------------------------------ */ + +/** + * + * @ingroup IxAtmdAccCtrlAPI + * + * @fn ixAtmdAccRxDispatcherRegister ( + IxAtmRxQueueId queueId, + IxAtmdAccRxDispatcher callback) + * + * @brief Register a notification callback to be invoked when there is + * at least one entry on a particular Rx queue. + * + * This function registers a callback to be invoked when there is at + * least one entry in a particular queue. The registered callback is + * called every time when the hardware adds one or more pdus to the + * specified Rx queue. + * + * This function cannot be used when a Rx Vc using this queue is + * already existing. + * + * @note -The callback function can be the API function + * @a ixAtmdAccRxDispatch() : every time the threhold level + * of the queue is reached, the ixAtmdAccRxDispatch() is + * invoked to remove all entries from the queue. + * + * @sa ixAtmdAccRxDispatch + * @sa IxAtmdAccRxDispatcher + * + * @param queueId @ref IxAtmRxQueueId [in] RX queue identification + * @param callback @ref IxAtmdAccRxDispatcher [in] function triggering the delivery of incoming + * traffic. This parameter cannot be a null pointer. + * + * @return @li IX_SUCCESS Successful call to @a ixAtmdAccRxDispatcherRegister() + * @return @li IX_FAIL error in the parameters, or there is an + * already active RX VC for this queue or some unspecified + * internal error occurred. + * + */ +PUBLIC IX_STATUS ixAtmdAccRxDispatcherRegister ( + IxAtmRxQueueId queueId, + IxAtmdAccRxDispatcher callback); + +/** + * + * @ingroup IxAtmdAccCtrlAPI + * + * @fn ixAtmdAccRxDispatch (IxAtmRxQueueId rxQueueId, + unsigned int numberOfPdusToProcess, + unsigned int *numberOfPdusProcessedPtr) + * + * + * @brief Control function which executes Rx processing for a particular + * Rx stream. + * + * The @a IxAtmdAccRxDispatch() function is used to process received Pdus + * available from one of the two incoming RX streams. When this function + * is invoked, the incoming traffic (up to the number of PDUs passed as + * a parameter) will be transferred to the IxAtmdAcc users through the + * callback @a IxAtmdAccRxVcRxCallback(), as registered during the + * @a ixAtmdAccRxVcConnect() call. + * + * The user receive callbacks will be executed in the context of this + * function. + * + * Failing to use this function on a regular basis when there is traffic + * will block incoming traffic and can result in Pdus being dropped by + * the hardware. + * + * This should be used to control when received pdus are handed off from + * the hardware to Aal users from a particluar stream. The function can + * be used from a timer context, or can be registered as a callback in + * response to an rx stream threshold event, or can be used inside an + * active polling mechanism which is under user control. + * + * @note - The signature of this function is directly compatible with the + * callback prototype which can be register with @a ixAtmdAccRxDispatcherRegister(). + * + * @sa ixAtmdAccRxDispatcherRegister + * @sa IxAtmdAccRxVcRxCallback + * @sa ixAtmdAccRxVcFreeEntriesQuery + * + * @param rxQueueId @ref IxAtmRxQueueId [in] - indicates which RX queue to process. + * @param numberOfPdusToProcess unsigned int [in] - indicates the maxiumum number of PDU to + * remove from the RX queue. A value of IX_ATMDACC_ALLPDUS indicates + * to process all PDUs from the queue. This includes at least the PDUs + * in the queue when the fuction is invoked. Because of real-time + * constraints, there is no guarantee thatthe queue will be empty + * when the function exits. If this parameter is greater than the + * number of entries of the queues, the function will succeed + * and the parameter numberOfPdusProcessedPtr will reflect the exact + * number of PDUs processed. + * @param *numberOfPdusProcessedPtr unsigned int [out] - indicates the actual number of PDU + * processed during this call. This parameter cannot be a null + * pointer. + * + * @return @li IX_SUCCESS the number of PDUs as indicated in + * numberOfPdusProcessedPtr are removed from the RX queue and the VC callback + * are called. + * @return @li IX_FAIL invalid parameters or some unspecified internal + * error occured. + * + */ +PUBLIC IX_STATUS ixAtmdAccRxDispatch (IxAtmRxQueueId rxQueueId, + unsigned int numberOfPdusToProcess, + unsigned int *numberOfPdusProcessedPtr); + +/** + * + * @ingroup IxAtmdAccCtrlAPI + * + * @fn ixAtmdAccRxLevelQuery (IxAtmRxQueueId rxQueueId, + unsigned int *numberOfPdusPtr) + * + * @brief Query the number of entries in a particular RX queue. + * + * This function is used to retrieve the number of pdus received by + * the hardware and ready for distribution to users. + * + * @param rxQueueId @ref IxAtmRxQueueId [in] - indicates which of two RX queues to query. + * @param numberOfPdusPtr unsigned int* [out] - Pointer to store the number of available + * PDUs in the RX queue. This parameter cannot be a null pointer. + * + * @return @li IX_SUCCESS the value in numberOfPdusPtr specifies the + * number of incoming pdus waiting in this queue + * @return @li IX_FAIL an error occurs during processing. + * The value in numberOfPdusPtr is unspecified. + * + * @note - This function is reentrant, doesn't use system resources + * and can be used from an interrupt context. + * + */ +PUBLIC IX_STATUS ixAtmdAccRxLevelQuery (IxAtmRxQueueId rxQueueId, + unsigned int *numberOfPdusPtr); + +/** + * + * @ingroup IxAtmdAccCtrlAPI + * + * @fn ixAtmdAccRxQueueSizeQuery (IxAtmRxQueueId rxQueueId, + unsigned int *numberOfPdusPtr) + * + * @brief Query the size of a particular RX queue. + * + * This function is used to retrieve the number of pdus the system is + * able to queue when reception is complete. + * + * @param rxQueueId @ref IxAtmRxQueueId [in] - indicates which of two RX queues to query. + * @param numberOfPdusPtr unsigned int* [out] - Pointer to store the number of pdus + * the system is able to queue in the RX queue. This parameter + * cannot be a null pointer. + * + * @return @li IX_SUCCESS the value in numberOfPdusPtr specifies the + * number of pdus the system is able to queue. + * @return @li IX_FAIL an error occurs during processing. + * The value in numberOfPdusPtr is unspecified. + * + * @note - This function is reentrant, doesn't use system resources + * and can be used from an interrupt context. + * + */ +PUBLIC IX_STATUS ixAtmdAccRxQueueSizeQuery (IxAtmRxQueueId rxQueueId, + unsigned int *numberOfPdusPtr); + +/* ------------------------------------------------------ + Part of the IxAtmdAcc interface related to TX traffic + ------------------------------------------------------ */ + +/** + * + * @ingroup IxAtmdAccCtrlAPI + * + * @fn ixAtmdAccPortTxFreeEntriesQuery (IxAtmLogicalPort port, + unsigned int *numberOfCellsPtr) + * + * @brief Get the number of available cells the system can accept for + * transmission. + * + * The function is used to retrieve the number of cells that can be + * queued for transmission to the hardware. + * + * This number is based on the worst schedule table where one cell + * is stored in one schedule table entry, depending on the pdus size + * and mbuf size and fragmentation. + * + * This function doesn't use system resources and can be used from a + * timer context, or can be associated with a threshold event, or can + * be used inside an active polling mechanism + * + * @param port @ref IxAtmLogicalPort [in] - logical PHY port [@a IX_UTOPIA_PORT_0 .. @a IX_UTOPIA_MAX_PORTS - 1] + * @param numberOfCellsPtr unsigned int* [out] - number of available cells. + * This parameter cannot be a null pointer. + * + * @sa ixAtmdAccPortTxProcess + * + * @return @li IX_SUCCESS numberOfCellsPtr contains the number of cells that can be scheduled + * for this port. + * @return @li IX_FAIL error in the parameters, or some processing error + * occured. + * + */ +PUBLIC IX_STATUS ixAtmdAccPortTxFreeEntriesQuery (IxAtmLogicalPort port, + unsigned int *numberOfCellsPtr); + +/** + * + * @ingroup IxAtmdAccCtrlAPI + * + * @fn ixAtmdAccPortTxCallbackRegister (IxAtmLogicalPort port, + unsigned int numberOfCells, + IxAtmdAccPortTxLowCallback callback) + * + * @brief Configure the Tx port threshold value and register a callback to handle + * threshold notifications. + * + * This function sets the threshold in cells + * + * @sa ixAtmdAccPortTxCallbackRegister + * @sa ixAtmdAccPortTxProcess + * @sa ixAtmdAccPortTxFreeEntriesQuery + * + * @param port @ref IxAtmLogicalPort [in] - logical PHY port [@a IX_UTOPIA_PORT_0 .. @a IX_UTOPIA_MAX_PORTS - 1] + * @param numberOfCells unsigned int [in] - threshold value which triggers the callback + * invocation, This number has to be one of the + * values 0,1,2,4,8,16,32 .... + * The maximum value cannot be more than half of the txVc queue + * size (which can be retrieved using @a ixAtmdAccPortTxFreeEntriesQuery() + * before any Tx traffic is sent for this port) + * @param callback @ref IxAtmdAccPortTxLowCallback [in] - callback function to invoke when the threshold + * level is reached. + * This parameter cannot be a null pointer. + * + * @return @li IX_SUCCESS Successful call to @a ixAtmdAccPortTxCallbackRegister() + * @return @li IX_FAIL error in the parameters, Tx channel already set for this port + * threshold level is not correct or within the range regarding the + * queue size:or unspecified error during processing: + * + * @note - This callback function get called when the threshold level drops from + * (numberOfCells+1) cells to (numberOfCells) cells + * + * @note - This function should be called during system initialisation, + * outside an interrupt context + * + */ +PUBLIC IX_STATUS ixAtmdAccPortTxCallbackRegister (IxAtmLogicalPort port, + unsigned int numberOfCells, + IxAtmdAccPortTxLowCallback callback); + +/** + * + * @ingroup IxAtmdAccCtrlAPI + * + * @fn ixAtmdAccPortTxScheduledModeEnable (IxAtmLogicalPort port, + IxAtmdAccTxVcDemandUpdateCallback vcDemandUpdateCallback, + IxAtmdAccTxVcDemandClearCallback vcDemandClearCallback, + IxAtmdAccTxSchVcIdGetCallback vcIdGetCallback) + * + * @brief Put the port into Scheduled Mode + * + * This function puts the specified port into scheduled mode of + * transmission which means an external s/w entity controls the + * transmission of cells on this port. This faciltates traffic shaping on + * the port. + * + * Any buffers submitted on a VC for this port will be queued in IxAtmdAcc. + * The transmission of these buffers to and by the hardware will be driven + * by a transmit schedule submitted regulary in calls to + * @a ixAtmdAccPortTxProcess() by traffic shaping entity. + * + * The transmit schedule is expected to be dynamic in nature based on + * the demand in cells for each VC on the port. Hence the callback + * parameters provided to this function allow IxAtmdAcc to inform the + * shaping entity of demand changes for each VC on the port. + * + * By default a port is in Unscheduled Mode so if this function is not + * called, transmission of data is done without sheduling rules, on a + * first-come, first-out basis. + * + * Once a port is put in scheduled mode it cannot be reverted to + * un-scheduled mode. Note that unscheduled mode is not supported + * in ixp425 1.0 + * + * @note - This function should be called before any VCs have be + * connected on a port. Otherwise this function call will return failure. + * + * @note - This function uses internal locks and should not be called from + * an interrupt context + * + * @sa IxAtmdAccTxVcDemandUpdateCallback + * @sa IxAtmdAccTxVcDemandClearCallback + * @sa IxAtmdAccTxSchVcIdGetCallback + * @sa ixAtmdAccPortTxProcess + * + * @param port @ref IxAtmLogicalPort [in] - logical PHY port [@a IX_UTOPIA_PORT_0 .. @a IX_UTOPIA_MAX_PORTS - 1] + * @param vcDemandUpdateCallback @ref IxAtmdAccTxVcDemandUpdateCallback [in] - callback function used to update + * the number of outstanding cells for transmission. This parameter + * cannot be a null pointer. + * @param vcDemandClearCallback @ref IxAtmdAccTxVcDemandClearCallback [in] - callback function used to remove all + * clear the number of outstanding cells for a VC. This parameter + * cannot be a null pointer. + * @param vcIdGetCallback @ref IxAtmdAccTxSchVcIdGetCallback [in] - callback function used to exchange vc + * Identifiers between IxAtmdAcc and the entity supplying the + * transmit schedule. This parameter cannot be a null pointer. + * + * @return @li IX_SUCCESS scheduler registration is complete and the port + * is now in scheduled mode. + * @return @li IX_FAIL failed (wrong parameters, or traffic is already + * enabled on this port, possibly without ATM shaping) + * + */ +PUBLIC IX_STATUS ixAtmdAccPortTxScheduledModeEnable (IxAtmLogicalPort port, + IxAtmdAccTxVcDemandUpdateCallback vcDemandUpdateCallback, + IxAtmdAccTxVcDemandClearCallback vcDemandClearCallback, + IxAtmdAccTxSchVcIdGetCallback vcIdGetCallback); + +/** + * + * @ingroup IxAtmdAccCtrlAPI + * + * @fn ixAtmdAccPortTxProcess (IxAtmLogicalPort port, + IxAtmScheduleTable* scheduleTablePtr) + * + * @brief Transmit queue cells to the H/W based on the supplied schedule + * table. + * + * This function @a ixAtmdAccPortTxProcess() process the schedule + * table provided as a parameter to the function. As a result cells are + * sent to the underlaying hardware for transmission. + * + * The schedule table is executed in its entirety or not at all. So the + * onus is on the caller not to submit a table containing more cells than + * can be transmitted at that point. The maximum numbers that can be + * transmitted is guaranteed to be the number of cells as returned by the + * function @a ixAtmdAccPortTxFreeEntriesQuery(). + * + * When the scheduler is invoked on a threshold level, IxAtmdAcc gives the + * minimum number of cells (to ensure the callback will fire again later) + * and the maximum number of cells that @a ixAtmdAccPortTxProcess() + * will be able to process (assuming the ATM scheduler is able + * to produce the worst-case schedule table, i.e. one entry per cell). + * + * When invoked ouside a threshold level, the overall number of cells of + * the schedule table should be less than the number of cells returned + * by the @a ixAtmdAccPortTxFreeEntriesQuery() function. + * + * After invoking the @a ixAtmdAccPortTxProcess() function, it is the + * user choice to query again the queue level with the function + * @a ixAtmdAccPortTxFreeEntriesQuery() and, depending on a new cell + * number, submit an other schedule table. + * + * IxAtmdAcc will check that the number of cells in the schedule table + * is compatible with the current transmit level. If the + * + * Obsolete or invalid connection Id will be silently discarded. + * + * This function is not reentrant for the same port. + * + * This functions doesn't use system resources and can be used inside an + * interrupt context. + * + * This function is used as a response to the hardware requesting more + * cells to transmit. + * + * @sa ixAtmdAccPortTxScheduledModeEnable + * @sa ixAtmdAccPortTxFreeEntriesQuery + * @sa ixAtmdAccPortTxCallbackRegister + * @sa ixAtmdAccPortEnable + * + * @param port @ref IxAtmLogicalPort [in] - logical PHY port [@a IX_UTOPIA_PORT_0 .. @a IX_UTOPIA_MAX_PORTS - 1] + * @param scheduleTablePtr @ref IxAtmScheduleTable* [in] - pointer to a scheduler update table. The + * content of this table is not modified by this function. This + * parameter cannot be a null pointer. + * + * @return @li IX_SUCCESS the schedule table process is complete + * and cells are transmitted to the hardware + * @return @li IX_ATMDACC_WARNING : Traffic will be dropped: the schedule table exceed + * the hardware capacity If this error is ignored, further traffic + * and schedule will work correctly. + * Overscheduling does not occur when the schedule table does + * not contain more entries that the number of free entries returned + * by @a ixAtmdAccPortTxFreeEntriesQuery(). + * However, Disconnect attempts just after this error will fail permanently + * with the error code @a IX_ATMDACC_RESOURCES_STILL_ALLOCATED, and it is + * necessary to disable the port to make @a ixAtmdAccTxVcTryDisconnect() + * successful. + * @return @li IX_FAIL a wrong parameter is supplied, or the format of + * the schedule table is invalid, or the port is not Enabled, or + * an internal severe error occured. No cells is transmitted to the hardware + * + * @note - If the failure is linked to an overschedule of data cells + * the result is an inconsistency in the output traffic (one or many + * cells may be missing and the traffic contract is not respected). + * + */ +PUBLIC IX_STATUS ixAtmdAccPortTxProcess (IxAtmLogicalPort port, + IxAtmScheduleTable* scheduleTablePtr); + +/** + * + * @ingroup IxAtmdAccCtrlAPI + * + * @fn ixAtmdAccTxDoneDispatch (unsigned int numberOfPdusToProcess, + unsigned int *numberOfPdusProcessedPtr) + * + * @brief Process a number of pending transmit done pdus from the hardware. + * + * As a by-product of Atm transmit operation buffers which transmission + * is complete need to be recycled to users. This function is invoked + * to service the oustanding list of transmitted buffers and pass them + * to VC users. + * + * Users are handed back pdus by invoking the free callback registered + * during the @a ixAtmdAccTxVcConnect() call. + * + * There is a single Tx done stream servicing all active Atm Tx ports + * which can contain a maximum of 64 entries. If this stream fills port + * transmission will stop so this function must be call sufficently + * frequently to ensure no disruption to the transmit operation. + * + * This function can be used from a timer context, or can be associated + * with a TxDone level threshold event (see @a ixAtmdAccTxDoneDispatcherRegister() ), + * or can be used inside an active polling mechanism under user control. + * + * For ease of use the signature of this function is compatible with the + * TxDone threshold event callback prototype. + * + * This functions can be used inside an interrupt context. + * + * @sa ixAtmdAccTxDoneDispatcherRegister + * @sa IxAtmdAccTxVcBufferReturnCallback + * @sa ixAtmdAccTxDoneLevelQuery + * + * @param numberOfPdusToProcess unsigned int [in] - maxiumum number of pdus to remove + * from the TX Done queue + * @param *numberOfPdusProcessedPtr unsigned int [out] - number of pdus removed from + * the TX Done queue. This parameter cannot be a null pointer. + * + * @return @li IX_SUCCESS the number of pdus as indicated in + * numberOfPdusToProcess are removed from the TX Done hardware + * and passed to the user through the Tx Done callback registered + * during a call to @a ixAtmdAccTxVcConnect() + * @return @li IX_FAIL invalid parameters or numberOfPdusProcessedPtr is + * a null pointer or some unspecified internal error occured. + * + */ +PUBLIC IX_STATUS +ixAtmdAccTxDoneDispatch (unsigned int numberOfPdusToProcess, + unsigned int *numberOfPdusProcessedPtr); + +/** + * + * @ingroup IxAtmdAccCtrlAPI + * + * @fn ixAtmdAccTxDoneLevelQuery (unsigned int *numberOfPdusPtr) + * + * @brief Query the current number of transmit pdus ready for + * recycling. + * + * This function is used to get the number of transmitted pdus which + * the hardware is ready to hand back to user. + * + * This function can be used from a timer context, or can be associated + * with a threshold event, on can be used inside an active polling + * mechanism + * + * @sa ixAtmdAccTxDoneDispatch + * + * @param *numberOfPdusPtr unsigned int [out] - Pointer to the number of pdus transmitted + * at the time of this function call, and ready for recycling + * This parameter cannot be a null pointer. + * + * @return @li IX_SUCCESS numberOfPdusPtr contains the number of pdus + * ready for recycling at the time of this function call + * + * @return @li IX_FAIL wrong parameter (null pointer as parameter).or + * unspecified rocessing error occurs..The value in numberOfPdusPtr + * is unspecified. + * + */ +PUBLIC IX_STATUS +ixAtmdAccTxDoneLevelQuery (unsigned int *numberOfPdusPtr); + +/** + * + * @ingroup IxAtmdAccCtrlAPI + * + * @fn ixAtmdAccTxDoneQueueSizeQuery (unsigned int *numberOfPdusPtr) + * + * @brief Query the TxDone queue size. + * + * This function is used to get the number of pdus which + * the hardware is able to store after transmission is complete + * + * The returned value can be used to set a threshold and enable + * a callback to be notified when the number of pdus is going over + * the threshold. + * + * @sa ixAtmdAccTxDoneDispatcherRegister + * + * @param *numberOfPdusPtr unsigned int [out] - Pointer to the number of pdus the system + * is able to queue after transmission + * + * @return @li IX_SUCCESS numberOfPdusPtr contains the the number of + * pdus the system is able to queue after transmission + * @return @li IX_FAIL wrong parameter (null pointer as parameter).or + * unspecified rocessing error occurs..The value in numberOfPdusPtr + * is unspecified. + * + * @note - This function is reentrant, doesn't use system resources + * and can be used from an interrupt context. + */ +PUBLIC IX_STATUS +ixAtmdAccTxDoneQueueSizeQuery (unsigned int *numberOfPdusPtr); + +/** + * + * @ingroup IxAtmdAccCtrlAPI + * + * @fn ixAtmdAccTxDoneDispatcherRegister (unsigned int numberOfPdus, + IxAtmdAccTxDoneDispatcher notificationCallback) + * + * @brief Configure the Tx Done stream threshold value and register a + * callback to handle threshold notifications. + * + * This function sets the threshold level in term of number of pdus at + * which the supplied notification function should be called. + * + * The higher the threshold value is, the less events will be necessary + * to process transmitted buffers. + * + * Transmitted buffers recycling implementation is a sytem-wide mechanism + * and needs to be set prior any traffic is started. If this threshold + * mechanism is not used, the user is responsible for polling the + * transmitted buffers thanks to @a ixAtmdAccTxDoneDispatch() and + * @a ixAtmdAccTxDoneLevelQuery() functions. + * + * This function should be called during system initialisation outside + * an interrupt context + * + * @sa ixAtmdAccTxDoneDispatcherRegister + * @sa ixAtmdAccTxDoneDispatch + * @sa ixAtmdAccTxDoneLevelQuery + * + * @param numberOfPdus unsigned int [in] - The number of TxDone pdus which triggers the + * callback invocation This number has to be a power of 2, one of the + * values 0,1,2,4,8,16,32 ... + * The maximum value cannot be more than half of the txDone queue + * size (which can be retrieved using @a ixAtmdAccTxDoneQueueSizeQuery()) + * @param notificationCallback @ref IxAtmdAccTxDoneDispatcher [in] - The function to invoke. (This + * parameter can be @a ixAtmdAccTxDoneDispatch()).This + * parameter ust not be a null pointer. + * + * @return @li IX_SUCCESS Successful call to ixAtmdAccTxDoneDispatcherRegister + * @return @li IX_FAIL error in the parameters: + * + * @note - The notificationCallback will be called exactly when the threshold level + * will increase from (numberOfPdus) to (numberOfPdus+1) + * + * @note - If there is no Tx traffic, there is no guarantee that TxDone Pdus will + * be released to the user (when txDone level is permanently under the threshold + * level. One of the preffered way to return resources to the user is to use + * a mix of txDone notifications, used together with a slow + * rate timer and an exclusion mechanism protecting from re-entrancy + * + * @note - The TxDone threshold will only hand back buffers when the threshold level is + * crossed. Setting this threshold to a great number reduce the interrupt rate + * and the cpu load, but also increase the number of outstanding mbufs and has + * a system wide impact when these mbufs are needed by other components. + * + */ +PUBLIC IX_STATUS ixAtmdAccTxDoneDispatcherRegister (unsigned int numberOfPdus, + IxAtmdAccTxDoneDispatcher notificationCallback); + +/* ------------------------------------------------------ + Part of the IxAtmdAcc interface related to Utopia config + ------------------------------------------------------ */ + +/** + * + * @ingroup IxAtmdAccCtrlAPI + * + * @defgroup IxAtmdAccUtopiaCtrlAPI IXP400 ATM Driver Access (IxAtmdAcc) Utopia Control API + * + * @brief The public API for the IXP400 Atm Driver Control component + * + * IxAtmdAcc is the low level interface by which AAL PDU get + * transmitted to,and received from the Utopia bus + * + * This part is related to the UTOPIA configuration. + * + * @{ + */ + +/** + * + * @brief Utopia configuration + * + * This structure is used to set the Utopia parameters + * @li contains the values of Utopia registers, to be set during initialisation + * @li contains debug commands for NPE, to be used during development steps + * + * @note - the exact description of all parameters is done in the Utopia reference + * documents. + * + */ +typedef struct +{ + /** + * @ingroup IxAtmdAccUtopiaCtrlAPI + * @struct UtTxConfig_ + * @brief Utopia Tx Config Register + */ + struct UtTxConfig_ + { + + unsigned int reserved_1:1; /**< [31] These bits are always 0.*/ + unsigned int txInterface:1; /**< [30] Utopia Transmit Interface. The following encoding + * is used to set the Utopia Transmit interface as ATM master + * or PHY slave: + * @li 1 - PHY + * @li 0 - ATM + */ + unsigned int txMode:1; /**< [29] Utopia Transmit Mode. The following encoding is used + * to set the Utopia Transmit mode to SPHY or MPHY: + * @li 1 - SPHY + * @li 0 - MPHY + */ + unsigned int txOctet:1; /**< [28] Utopia Transmit cell transfer protocol. Used to set + * the Utopia cell transfer protocol to Octet-level handshaking. + * Note this is only applicable in SPHY mode. + * @li 1 - Octet-handshaking enabled + * @li 0 - Cell-handshaking enabled + */ + unsigned int txParity:1; /**< [27] Utopia Transmit parity enabled when set. TxEvenParity + * defines the parity format odd/even. + * @li 1 - Enable Parity generation. + * @li 0 - ut_op_prty held low. + */ + unsigned int txEvenParity:1; /**< [26] Utopia Transmit Parity Mode + * @li 1 - Even Parity Generated. + * @li 0 - Odd Parity Generated. + */ + unsigned int txHEC:1; /**< [25] Header Error Check Insertion Mode. Specifies if the transmit + * cell header check byte is calculated and inserted when set. + * @li 1 - Generate HEC. + * @li 0 - Disable HEC generation. + */ + unsigned int txCOSET:1; /**< [24] If enabled the HEC is Exclusive-ORÆed with the value 0x55 before + * being presented on the Utopia bus. + * @li 1 - Enable HEC ExOR with value 0x55 + * @li 0 - Use generated HEC value. + */ + + unsigned int reserved_2:1; /**< [23] These bits are always 0 + */ + unsigned int txCellSize:7; /**< [22:16] Transmit expected cell size. Configures the cell size + * for the transmit module: Values between 52-64 are valid. + */ + unsigned int reserved_3:3; /**< [15:13] These bits are always 0 */ + unsigned int txAddrRange:5; /**< [12:8] When configured as an ATM master in MPHY mode this + * register specifies the upper limit of the PHY polling logical + * range. The number of active PHYs are TxAddrRange + 1. + */ + unsigned int reserved_4:3; /**< [7:5] These bits are always 0 */ + unsigned int txPHYAddr:5; /**< [4:0] When configured as a slave in an MPHY system this register + * specifies the physical address of the PHY. + */ + } + + utTxConfig; /**< Tx config Utopia register */ + + /** + * @ingroup IxAtmdAccUtopiaCtrlAPI + * @struct UtTxStatsConfig_ + * @brief Utopia Tx stats Register + */ + struct UtTxStatsConfig_ + { + + unsigned int vpi:12; /**< [31:20] ATM VPI [11:0] OR GFC [3:0] and VPI [7:0] + @li Note: if VCStatsTxGFC is set to 0 the GFC field is ignored in test. */ + + unsigned int vci:16; /**< [19:4] ATM VCI [15:0] or PHY Address[4] */ + + unsigned int pti:3; /**< [3:1] ATM PTI [2:0] or PHY Address[3:1] + @li Note: if VCStatsTxPTI is set to 0 the PTI field is ignored in test. + @li Note: if VCStatsTxEnb is set to 0 only the transmit PHY port + address as defined by this register is used for ATM statistics [4:0]. */ + + unsigned int clp:1; /**< [0] ATM CLP or PHY Address [0] + @li Note: if VCStatsTxCLP is set to 0 the CLP field is ignored in test. + @li Note: if VCStatsTxEnb is set to 0 only the transmit PHY port + address as defined by this register is used for ATM statistics [4:0]. */ + } + + utTxStatsConfig; /**< Tx stats config Utopia register */ + + /** + * @ingroup IxAtmdAccUtopiaCtrlAPI + * @struct UtTxDefineIdle_ + * @brief Utopia Tx idle cells Register + */ + struct UtTxDefineIdle_ + { + + unsigned int vpi:12; /**< [31:20] ATM VPI [11:0] OR GFC [3:0] and VPI [7:0] + @li Note: if VCIdleTxGFC is set to 0 the GFC field is ignored in test. */ + + unsigned int vci:16; /**< [19:4] ATM VCI [15:0] */ + + unsigned int pti:3; /**< [3:1] ATM PTI PTI [2:0] + @li Note: if VCIdleTxPTI is set to 0 the PTI field is ignored in test.*/ + + unsigned int clp:1; /**< [0] ATM CLP [0] + @li Note: if VCIdleTxCLP is set to 0 the CLP field is ignored in test.*/ + } + + utTxDefineIdle; /**< Tx idle cell config Utopia register */ + + /** + * @ingroup IxAtmdAccUtopiaCtrlAPI + * @struct UtTxEnableFields_ + * @brief Utopia Tx ienable fields Register + */ + struct UtTxEnableFields_ + { + + unsigned int defineTxIdleGFC:1; /**< [31] This register is used to include or exclude the GFC + field of the ATM header when testing for Idle cells. + @li 1 - GFC field is valid. + @li 0 - GFC field ignored.*/ + + unsigned int defineTxIdlePTI:1; /**< [30] This register is used to include or exclude the PTI + field of the ATM header when testing for Idle cells. + @li 1 - PTI field is valid + @li 0 - PTI field ignored.*/ + + unsigned int defineTxIdleCLP:1; /**< [29] This register is used to include or + exclude the CLP field of the ATM header when testing for Idle cells. + @li 1 - CLP field is valid. + @li 0 - CLP field ignored. */ + + unsigned int phyStatsTxEnb:1; /**< [28] This register is used to enable or disable ATM + statistics gathering based on the specified PHY address as defined + in TxStatsConfig register. + @li 1 - Enable statistics for specified transmit PHY address. + @li 0 - Disable statistics for specified transmit PHY address. */ + + unsigned int vcStatsTxEnb:1; /**< [27] This register is used to change the ATM + statistics-gathering mode from the specified logical PHY address + to a specific VPI/VCI address. + @li 1 - Enable statistics for specified VPI/VCI address. + @li 0 - Disable statistics for specified VPI/VCI address */ + + unsigned int vcStatsTxGFC:1; /**< [26] This register is used to include or exclude the GFC + field of the ATM header when ATM VPI/VCI statistics are enabled. + GFC is only available at the UNI and uses the first 4-bits of + the VPI field. + @li 1 - GFC field is valid + @li 0 - GFC field ignored.*/ + + unsigned int vcStatsTxPTI:1; /**< [25] This register is used to include or exclude the PTI + field of the ATM header when ATM VPI/VCI statistics are enabled. + @li 1 - PTI field is valid + @li 0 - PTI field ignored.*/ + + unsigned int vcStatsTxCLP:1; /**< [24] This register is used to include or exclude the CLP + field of the ATM header when ATM VPI/VCI statistics are enabled. + @li 1 - CLP field is valid + @li 0 - CLP field ignored. */ + + unsigned int reserved_1:3; /**< [23-21] These bits are always 0 */ + + unsigned int txPollStsInt:1; /**< [20] Enable the assertion of the ucp_tx_poll_sts condition + where there is a change in polling status. + @li 1 - ucp_tx_poll_sts asserted whenever there is a change in status + @li 0 - ucp_tx_poll_sts asserted if ANY transmit PHY is available + */ + unsigned int txCellOvrInt:1; /**< [19] Enable TxCellCount overflow CBI Transmit Status condition + assertion. + @li 1 - If TxCellCountOvr is set assert the Transmit Status Condition. + @li 0 - No CBI Transmit Status condition assertion */ + + unsigned int txIdleCellOvrInt:1; /**< [18] Enable TxIdleCellCount overflow Transmit Status Condition + @li 1 - If TxIdleCellCountOvr is set assert the Transmit Status Condition + @li 0 - No CBI Transmit Status condition assertion..*/ + + unsigned int enbIdleCellCnt:1; /**< [17] Enable Transmit Idle Cell Count. + @li 1 - Enable count of Idle cells transmitted. + @li 0 - No count is maintained. */ + + unsigned int enbTxCellCnt:1; /**< [16] Enable Transmit Valid Cell Count of non-idle/non-error cells + @li 1 - Enable count of valid cells transmitted- non-idle/non-error + @li 0 - No count is maintained.*/ + + unsigned int reserved_2:16; /**< [15:0] These bits are always 0 */ + } utTxEnableFields; /**< Tx enable Utopia register */ + + /** + * @ingroup IxAtmdAccUtopiaCtrlAPI + * @struct UtTxTransTable0_ + * @brief Utopia Tx translation table Register + */ + struct UtTxTransTable0_ + { + + unsigned int phy0:5; /**< [31-27] Tx Mapping value of logical phy 0 */ + + unsigned int phy1:5; /**< [26-22] Tx Mapping value of logical phy 1 */ + + unsigned int phy2:5; /**< [21-17] Tx Mapping value of logical phy 2 */ + + unsigned int reserved_1:1; /**< [16] These bits are always 0.*/ + + unsigned int phy3:5; /**< [15-11] Tx Mapping value of logical phy 3 */ + + unsigned int phy4:5; /**< [10-6] Tx Mapping value of logical phy 4 */ + + unsigned int phy5:5; /**< [5-1] Tx Mapping value of logical phy 5 */ + + unsigned int reserved_2:1; /**< [0] These bits are always 0 */ + } utTxTransTable0; /**< Tx translation table */ + + /** + * @ingroup IxAtmdAccUtopiaCtrlAPI + * @struct UtTxTransTable1_ + * @brief Utopia Tx translation table Register + */ + struct UtTxTransTable1_ + { + + unsigned int phy6:5; /**< [31-27] Tx Mapping value of logical phy 6 */ + + unsigned int phy7:5; /**< [26-22] Tx Mapping value of logical phy 7 */ + + unsigned int phy8:5; /**< [21-17] Tx Mapping value of logical phy 8 */ + + unsigned int reserved_1:1; /**< [16-0] These bits are always 0 */ + + unsigned int phy9:5; /**< [15-11] Tx Mapping value of logical phy 3 */ + + unsigned int phy10:5; /**< [10-6] Tx Mapping value of logical phy 4 */ + + unsigned int phy11:5; /**< [5-1] Tx Mapping value of logical phy 5 */ + + unsigned int reserved_2:1; /**< [0] These bits are always 0 */ + } utTxTransTable1; /**< Tx translation table */ + + /** + * @ingroup IxAtmdAccUtopiaCtrlAPI + * @struct UtTxTransTable2_ + * @brief Utopia Tx translation table Register + */ + struct UtTxTransTable2_ + { + + unsigned int phy12:5; /**< [31-27] Tx Mapping value of logical phy 6 */ + + unsigned int phy13:5; /**< [26-22] Tx Mapping value of logical phy 7 */ + + unsigned int phy14:5; /**< [21-17] Tx Mapping value of logical phy 8 */ + + unsigned int reserved_1:1; /**< [16-0] These bits are always 0 */ + + unsigned int phy15:5; /**< [15-11] Tx Mapping value of logical phy 3 */ + + unsigned int phy16:5; /**< [10-6] Tx Mapping value of logical phy 4 */ + + unsigned int phy17:5; /**< [5-1] Tx Mapping value of logical phy 5 */ + + unsigned int reserved_2:1; /**< [0] These bits are always 0 */ + } utTxTransTable2; /**< Tx translation table */ + + /** + * @ingroup IxAtmdAccUtopiaCtrlAPI + * @struct UtTxTransTable3_ + * @brief Utopia Tx translation table Register + */ + struct UtTxTransTable3_ + { + + unsigned int phy18:5; /**< [31-27] Tx Mapping value of logical phy 6 */ + + unsigned int phy19:5; /**< [26-22] Tx Mapping value of logical phy 7 */ + + unsigned int phy20:5; /**< [21-17] Tx Mapping value of logical phy 8 */ + + unsigned int reserved_1:1; /**< [16-0] These bits are always 0 */ + + unsigned int phy21:5; /**< [15-11] Tx Mapping value of logical phy 3 */ + + unsigned int phy22:5; /**< [10-6] Tx Mapping value of logical phy 4 */ + + unsigned int phy23:5; /**< [5-1] Tx Mapping value of logical phy 5 */ + + unsigned int reserved_2:1; /**< [0] These bits are always 0 */ + } utTxTransTable3; /**< Tx translation table */ + + /** + * @ingroup IxAtmdAccUtopiaCtrlAPI + * @struct UtTxTransTable4_ + * @brief Utopia Tx translation table Register + */ + struct UtTxTransTable4_ + { + + unsigned int phy24:5; /**< [31-27] Tx Mapping value of logical phy 6 */ + + unsigned int phy25:5; /**< [26-22] Tx Mapping value of logical phy 7 */ + + unsigned int phy26:5; /**< [21-17] Tx Mapping value of logical phy 8 */ + + unsigned int reserved_1:1; /**< [16-0] These bits are always 0 */ + + unsigned int phy27:5; /**< [15-11] Tx Mapping value of logical phy 3 */ + + unsigned int phy28:5; /**< [10-6] Tx Mapping value of logical phy 4 */ + + unsigned int phy29:5; /**< [5-1] Tx Mapping value of logical phy 5 */ + + unsigned int reserved_2:1; /**< [0] These bits are always 0 */ + } utTxTransTable4; /**< Tx translation table */ + + /** + * @ingroup IxAtmdAccUtopiaCtrlAPI + * @struct UtTxTransTable5_ + * @brief Utopia Tx translation table Register + */ + struct UtTxTransTable5_ + { + + unsigned int phy30:5; /**< [31-27] Tx Mapping value of logical phy 6 */ + + unsigned int reserved_1:27; /**< [26-0] These bits are always 0 */ + + } utTxTransTable5; /**< Tx translation table */ + + /** + * @ingroup IxAtmdAccUtopiaCtrlAPI + * @struct UtRxConfig_ + * @brief Utopia Rx config Register + */ + struct UtRxConfig_ + { + + unsigned int rxInterface:1; /**< [31] Utopia Receive Interface. The following encoding is used + to set the Utopia Receive interface as ATM master or PHY slave: + @li 1 - PHY + @li 0 - ATM */ + + unsigned int rxMode:1; /**< [30] Utopia Receive Mode. The following encoding is used to set + the Utopia Receive mode to SPHY or MPHY: + @li 1 - SPHY + @li 0 - MPHY */ + + unsigned int rxOctet:1; /**< [29] Utopia Receive cell transfer protocol. Used to set the Utopia + cell transfer protocol to Octet-level handshaking. Note this is only + applicable in SPHY mode. + @li 1 - Octet-handshaking enabled + @li 0 - Cell-handshaking enabled */ + + unsigned int rxParity:1; /**< [28] Utopia Receive Parity Checking enable. + @li 1 - Parity checking enabled + @li 0 - Parity checking disabled */ + + unsigned int rxEvenParity:1;/**< [27] Utopia Receive Parity Mode + @li 1 - Check for Even Parity + @li 0 - Check for Odd Parity.*/ + + unsigned int rxHEC:1; /**< [26] RxHEC Header Error Check Mode. Enables/disables cell header + error checking on the received cell header. + @li 1 - HEC checking enabled + @li 0 - HEC checking disabled */ + + unsigned int rxCOSET:1; /**< [25] If enabled the HEC is Exclusive-ORÆed with the value 0x55 + before being tested with the received HEC. + @li 1 - Enable HEC ExOR with value 0x55. + @li 0 - Use generated HEC value.*/ + + unsigned int rxHECpass:1; /**< [24] Specifies if the incoming cell HEC byte should be transferred + after optional processing to the NPE2 Coprocessor Bus Interface or + if it should be discarded. + @li 1 - HEC maintained 53-byte/UDC cell sent to NPE2. + @li 0 - HEC discarded 52-byte/UDC cell sent to NPE2 coprocessor.*/ + + unsigned int reserved_1:1; /**< [23] These bits are always 0 */ + + unsigned int rxCellSize:7; /**< [22:16] Receive cell size. Configures the receive cell size. + Values between 52-64 are valid */ + + unsigned int rxHashEnbGFC:1; /**< [15] Specifies if the VPI field [11:8]/GFC field should be + included in the Hash data input or if the bits should be padded + with 1Æb0. + @li 1 - VPI [11:8]/GFC field valid and used in Hash residue calculation. + @li 0 - VPI [11:8]/GFC field padded with 1Æb0 */ + + unsigned int rxPreHash:1; /**< [14] Enable Pre-hash value generation. Specifies if the + incoming cell data should be pre-hashed to allow VPI/VCI header look-up + in a hash table. + @li 1 - Pre-hashing enabled + @li 0 - Pre-hashing disabled */ + + unsigned int reserved_2:1; /**< [13] These bits are always 0 */ + + unsigned int rxAddrRange:5; /**< [12:8] In ATM master, MPHY mode, + * this register specifies the upper + * limit of the PHY polling logical range. The number of active PHYs are + * RxAddrRange + 1. + */ + unsigned int reserved_3:3; /**< [7-5] These bits are always 0 .*/ + unsigned int rxPHYAddr:5; /**< [4:0] When configured as a slave in an MPHY system this register + * specifies the physical address of the PHY. + */ + } utRxConfig; /**< Rx config Utopia register */ + + /** + * @ingroup IxAtmdAccUtopiaCtrlAPI + * @struct UtRxStatsConfig_ + * @brief Utopia Rx stats config Register + */ + struct UtRxStatsConfig_ + { + + unsigned int vpi:12; /**< [31:20] ATM VPI VPI [11:0] OR GFC [3:0] and VPI [7:0] + @li Note: if VCStatsRxGFC is set to 0 the GFC field is ignored in test. */ + + unsigned int vci:16; /**< [19:4] VCI [15:0] or PHY Address [4] */ + + unsigned int pti:3; /**< [3:1] PTI [2:0] or or PHY Address [3:1] + @li Note: if VCStatsRxPTI is set to 0 the PTI field is ignored in test. + @li Note: if VCStatsRxEnb is set to 0 only the PHY port address is used + for statistics gathering.. */ + + unsigned int clp:1; /**< [0] CLP [0] or PHY Address [0] + @li Note: if VCStatsRxCLP is set to 0 the CLP field is ignored in test. + @li Note: if VCStatsRxEnb is set to 0 only the PHY port address is used + for statistics gathering.. */ + } utRxStatsConfig; /**< Rx stats config Utopia register */ + + /** + * @ingroup IxAtmdAccUtopiaCtrlAPI + * @struct UtRxDefineIdle_ + * @brief Utopia Rx idle cells config Register + */ + struct UtRxDefineIdle_ + { + + unsigned int vpi:12; /**< [31:20] ATM VPI [11:0] OR GFC [3:0] and VPI [7:0] + @li Note: if VCIdleRxGFC is set to 0 the GFC field is ignored in test. */ + + unsigned int vci:16; /**< [19:4] ATM VCI [15:0] */ + + unsigned int pti:3; /**< [3:1] ATM PTI PTI [2:0] + @li Note: if VCIdleRxPTI is set to 0 the PTI field is ignored in test.*/ + + unsigned int clp:1; /**< [0] ATM CLP [0] + @li Note: if VCIdleRxCLP is set to 0 the CLP field is ignored in test.*/ + } utRxDefineIdle; /**< Rx idle cell config Utopia register */ + + /** + * @ingroup IxAtmdAccUtopiaCtrlAPI + * @struct UtRxEnableFields_ + * @brief Utopia Rx enable Register + */ + struct UtRxEnableFields_ + { + + unsigned int defineRxIdleGFC:1;/**< [31] This register is used to include or exclude the GFC + field of the ATM header when testing for Idle cells. + @li 1 - GFC field is valid. + @li 0 - GFC field ignored.*/ + + unsigned int defineRxIdlePTI:1;/**< [30] This register is used to include or exclude the PTI + field of the ATM header when testing for Idle cells. + @li 1 - PTI field is valid. + @li 0 - PTI field ignored.*/ + + unsigned int defineRxIdleCLP:1;/**< [29] This register is used to include or exclude the CLP + field of the ATM header when testing for Idle cells. + @li 1 - CLP field is valid. + @li 0 - CLP field ignored.*/ + + unsigned int phyStatsRxEnb:1;/**< [28] This register is used to enable or disable ATM statistics + gathering based on the specified PHY address as defined in RxStatsConfig + register. + @li 1 - Enable statistics for specified receive PHY address. + @li 0 - Disable statistics for specified receive PHY address.*/ + + unsigned int vcStatsRxEnb:1;/**< [27] This register is used to enable or disable ATM statistics + gathering based on a specific VPI/VCI address. + @li 1 - Enable statistics for specified VPI/VCI address. + @li 0 - Disable statistics for specified VPI/VCI address.*/ + + unsigned int vcStatsRxGFC:1;/**< [26] This register is used to include or exclude the GFC field + of the ATM header when ATM VPI/VCI statistics are enabled. GFC is only + available at the UNI and uses the first 4-bits of the VPI field. + @li 1 - GFC field is valid. + @li 0 - GFC field ignored. */ + + unsigned int vcStatsRxPTI:1;/**< [25] This register is used to include or exclude the PTI field + of the ATM header when ATM VPI/VCI statistics are enabled. + @li 1 - PTI field is valid. + @li 0 - PTI field ignored.*/ + + unsigned int vcStatsRxCLP:1;/**< [24] This register is used to include or exclude the CLP field + of the ATM header when ATM VPI/VCI statistics are enabled. + @li 1 - CLP field is valid. + @li 0 - CLP field ignored. */ + + unsigned int discardHecErr:1;/**< [23] Discard cells with an invalid HEC. + @li 1 - Discard cells with HEC errors + @li 0 - Cells with HEC errors are passed */ + + unsigned int discardParErr:1;/**< [22] Discard cells containing parity errors. + @li 1 - Discard cells with parity errors + @li 0 - Cells with parity errors are passed */ + + unsigned int discardIdle:1; /**< [21] Discard Idle Cells based on DefineIdle register values + @li 1 - Discard IDLE cells + @li 0 - IDLE cells passed */ + + unsigned int enbHecErrCnt:1;/**< [20] Enable Receive HEC Error Count. + @li 1 - Enable count of received cells containing HEC errors + @li 0 - No count is maintained. */ + + unsigned int enbParErrCnt:1;/**< [19] Enable Parity Error Count + @li 1 - Enable count of received cells containing Parity errors + @li 0 - No count is maintained. */ + + unsigned int enbIdleCellCnt:1;/**< [18] Enable Receive Idle Cell Count. + @li 1 - Enable count of Idle cells received. + @li 0 - No count is maintained.*/ + + unsigned int enbSizeErrCnt:1;/**< [17] Enable Receive Size Error Count. + @li 1 - Enable count of received cells of incorrect size + @li 0 - No count is maintained. */ + + unsigned int enbRxCellCnt:1;/**< [16] Enable Receive Valid Cell Count of non-idle/non-error cells. + @li 1 - Enable count of valid cells received - non-idle/non-error + @li 0 - No count is maintained. */ + + unsigned int reserved_1:3; /**< [15:13] These bits are always 0 */ + + unsigned int rxCellOvrInt:1; /**< [12] Enable CBI Utopia Receive Status Condition if the RxCellCount + register overflows. + @li 1 - CBI Receive Status asserted. + @li 0 - No CBI Receive Status asserted.*/ + + unsigned int invalidHecOvrInt:1; /**< [11] Enable CBI Receive Status Condition if the InvalidHecCount + register overflows. + @li 1 - CBI Receive Condition asserted. + @li 0 - No CBI Receive Condition asserted */ + + unsigned int invalidParOvrInt:1; /**< [10] Enable CBI Receive Status Condition if the InvalidParCount + register overflows + @li 1 - CBI Receive Condition asserted. + @li 0 - No CBI Receive Condition asserted */ + + unsigned int invalidSizeOvrInt:1; /**< [9] Enable CBI Receive Status Condition if the InvalidSizeCount + register overflows. + @li 1 - CBI Receive Status Condition asserted. + @li¸0 - No CBI Receive Status asserted */ + + unsigned int rxIdleOvrInt:1; /**< [8] Enable CBI Receive Status Condition if the RxIdleCount overflows. + @li 1 - CBI Receive Condition asserted. + @li 0 - No CBI Receive Condition asserted */ + + unsigned int reserved_2:3; /**< [7:5] These bits are always 0 */ + + unsigned int rxAddrMask:5; /**< [4:0] This register is used as a mask to allow the user to increase + the PHY receive address range. The register should be programmed with + the address-range limit, i.e. if set to 0x3 the address range increases + to a maximum of 4 addresses. */ + } utRxEnableFields; /**< Rx enable Utopia register */ + + /** + * @ingroup IxAtmdAccUtopiaCtrlAPI + * @struct UtRxTransTable0_ + * @brief Utopia Rx translation table Register + */ + struct UtRxTransTable0_ + { + + unsigned int phy0:5; /**< [31-27] Rx Mapping value of logical phy 0 */ + + unsigned int phy1:5; /**< [26-22] Rx Mapping value of logical phy 1 */ + + unsigned int phy2:5; /**< [21-17] Rx Mapping value of logical phy 2 */ + + unsigned int reserved_1:1; /**< [16] These bits are always 0 */ + + unsigned int phy3:5; /**< [15-11] Rx Mapping value of logical phy 3 */ + + unsigned int phy4:5; /**< [10-6] Rx Mapping value of logical phy 4 */ + + unsigned int phy5:5; /**< [5-1] Rx Mapping value of logical phy 5 */ + + unsigned int reserved_2:1; /**< [0] These bits are always 0 */ + } + + utRxTransTable0; /**< Rx translation table */ + + /** + * @ingroup IxAtmdAccUtopiaCtrlAPI + * @struct UtRxTransTable1_ + * @brief Utopia Rx translation table Register + */ + struct UtRxTransTable1_ + { + + unsigned int phy6:5; /**< [31-27] Rx Mapping value of logical phy 6 */ + + unsigned int phy7:5; /**< [26-22] Rx Mapping value of logical phy 7 */ + + unsigned int phy8:5; /**< [21-17] Rx Mapping value of logical phy 8 */ + + unsigned int reserved_1:1; /**< [16-0] These bits are always 0 */ + + unsigned int phy9:5; /**< [15-11] Rx Mapping value of logical phy 3 */ + + unsigned int phy10:5; /**< [10-6] Rx Mapping value of logical phy 4 */ + + unsigned int phy11:5; /**< [5-1] Rx Mapping value of logical phy 5 */ + + unsigned int reserved_2:1; /**< [0] These bits are always 0 */ + } + + utRxTransTable1; /**< Rx translation table */ + + /** + * @ingroup IxAtmdAccUtopiaCtrlAPI + * @struct UtRxTransTable2_ + * @brief Utopia Rx translation table Register + */ + struct UtRxTransTable2_ + { + + unsigned int phy12:5; /**< [31-27] Rx Mapping value of logical phy 6 */ + + unsigned int phy13:5; /**< [26-22] Rx Mapping value of logical phy 7 */ + + unsigned int phy14:5; /**< [21-17] Rx Mapping value of logical phy 8 */ + + unsigned int reserved_1:1; /**< [16-0] These bits are always 0 */ + + unsigned int phy15:5; /**< [15-11] Rx Mapping value of logical phy 3 */ + + unsigned int phy16:5; /**< [10-6] Rx Mapping value of logical phy 4 */ + + unsigned int phy17:5; /**< [5-1] Rx Mapping value of logical phy 5 */ + + unsigned int reserved_2:1; /**< [0] These bits are always 0 */ + } utRxTransTable2; /**< Rx translation table */ + + /** + * @ingroup IxAtmdAccUtopiaCtrlAPI + * @struct UtRxTransTable3_ + * @brief Utopia Rx translation table Register + */ + struct UtRxTransTable3_ + { + + unsigned int phy18:5; /**< [31-27] Rx Mapping value of logical phy 6 */ + + unsigned int phy19:5; /**< [26-22] Rx Mapping value of logical phy 7 */ + + unsigned int phy20:5; /**< [21-17] Rx Mapping value of logical phy 8 */ + + unsigned int reserved_1:1; /**< [16-0] These bits are always 0 */ + + unsigned int phy21:5; /**< [15-11] Rx Mapping value of logical phy 3 */ + + unsigned int phy22:5; /**< [10-6] Rx Mapping value of logical phy 4 */ + + unsigned int phy23:5; /**< [5-1] Rx Mapping value of logical phy 5 */ + + unsigned int reserved_2:1; /**< [0] These bits are always 0 */ + } utRxTransTable3; /**< Rx translation table */ + + /** + * @ingroup IxAtmdAccUtopiaCtrlAPI + * @struct UtRxTransTable4_ + * @brief Utopia Rx translation table Register + */ + struct UtRxTransTable4_ + { + + unsigned int phy24:5; /**< [31-27] Rx Mapping value of logical phy 6 */ + + unsigned int phy25:5; /**< [26-22] Rx Mapping value of logical phy 7 */ + + unsigned int phy26:5; /**< [21-17] Rx Mapping value of logical phy 8 */ + + unsigned int reserved_1:1; /**< [16-0] These bits are always 0 */ + + unsigned int phy27:5; /**< [15-11] Rx Mapping value of logical phy 3 */ + + unsigned int phy28:5; /**< [10-6] Rx Mapping value of logical phy 4 */ + + unsigned int phy29:5; /**< [5-1] Rx Mapping value of logical phy 5 */ + + unsigned int reserved_2:1; /**< [0] These bits are always 0 */ + } utRxTransTable4; /**< Rx translation table */ + + /** + * @ingroup IxAtmdAccUtopiaCtrlAPI + * @struct UtRxTransTable5_ + * @brief Utopia Rx translation table Register + */ + struct UtRxTransTable5_ + { + + unsigned int phy30:5; /**< [31-27] Rx Mapping value of logical phy 6 */ + + unsigned int reserved_1:27; /**< [26-0] These bits are always 0 */ + + } utRxTransTable5; /**< Rx translation table */ + + /** + * @ingroup IxAtmdAccUtopiaCtrlAPI + * @struct UtSysConfig_ + * @brief NPE setup Register + */ + struct UtSysConfig_ + { + + unsigned int reserved_1:2; /**< [31-30] These bits are always 0 */ + unsigned int txEnbFSM:1; /**< [29] Enables the operation ofthe Utopia Transmit FSM + * @li 1 - FSM enabled + * @li 0 - FSM inactive + */ + unsigned int rxEnbFSM:1; /**< [28] Enables the operation ofthe Utopia Revieve FSM + * @li 1 - FSM enabled + * @li 0 - FSM inactive + */ + unsigned int disablePins:1; /**< [27] Disable Utopia interface I/O pins forcing the signals to an + * inactive state. Note that this bit is set on reset and must be + * de-asserted + * @li 0 - Normal data transfer + * @li 1 - Utopia interface pins are forced inactive + */ + unsigned int tstLoop:1; /**< [26] Test Loop Back Enable. + * @li Note: For loop back to function RxMode and Tx Mode must both be set + * to single PHY mode. + * @li 0 - Loop back + * @li 1 - Normal operating mode + */ + + unsigned int txReset:1; /**< [25] Resets the Utopia Coprocessor transmit module to a known state. + * @li Note: All transmit configuration and status registers will be reset + * to their reset values. + * @li 0 - Normal operating mode¸ + * @li 1 - Reset transmit modules + */ + + unsigned int rxReset:1; /**< [24] Resets the Utopia Coprocessor receive module to a known state. + * @li Note: All receive configuration and status registers will be reset + * to their reset values. + * @li 0 - Normal operating mode + * @li 1 - Reset receive modules + */ + + unsigned int reserved_2:24; /**< [23-0] These bits are always 0 */ + } utSysConfig; /**< NPE debug config */ + +} +IxAtmdAccUtopiaConfig; + +/** +* +* @brief Utopia status +* +* This structure is used to set/get the Utopia status parameters +* @li contains debug cell counters, to be accessed during a read operation +* +* @note - the exact description of all parameters is done in the Utopia reference +* documents. +* +*/ +typedef struct +{ + + unsigned int utTxCellCount; /**< count of cells transmitted */ + + unsigned int utTxIdleCellCount; /**< count of idle cells transmitted */ + + /** + * @ingroup IxAtmdAccUtopiaCtrlAPI + * @struct UtTxCellConditionStatus_ + * @brief Utopia Tx Status Register + */ + struct UtTxCellConditionStatus_ + { + + unsigned int reserved_1:2; /**< [31:30] These bits are always 0 */ + unsigned int txFIFO2Underflow:1; /**< [29] This bit is set if 64-byte + * Transmit FIFO2 indicates a FIFO underflow + * error condition. + */ + unsigned int txFIFO1Underflow:1; /**< [28] This bit is set if + * 64-byte Transmit FIFO1 indicates a FIFO + * underflow error condition. + */ + unsigned int txFIFO2Overflow:1; /**< [27] This bit is set if 64-byte + * Transmit FIFO2 indicates a FIFO overflow + * error condition. + */ + unsigned int txFIFO1Overflow:1; /**< [26] This bit is set if 64-byte + * Transmit FIFO1 indicates a FIFO overflow + * error condition. + */ + unsigned int txIdleCellCountOvr:1; /**< [25] This bit is set if the + * TxIdleCellCount register overflows. + */ + unsigned int txCellCountOvr:1; /**< [24] This bit is set if the + * TxCellCount register overflows + */ + unsigned int reserved_2:24; /**< [23:0] These bits are always 0 */ + } utTxCellConditionStatus; /**< Tx cells condition status */ + + unsigned int utRxCellCount; /**< count of cell received */ + unsigned int utRxIdleCellCount; /**< count of idle cell received */ + unsigned int utRxInvalidHECount; /**< count of invalid cell + * received because of HEC errors + */ + unsigned int utRxInvalidParCount; /**< count of invalid cell received + * because of parity errors + */ + unsigned int utRxInvalidSizeCount; /**< count of invalid cell + * received because of cell + * size errors + */ + + /** + * @ingroup IxAtmdAccUtopiaCtrlAPI + * @struct UtRxCellConditionStatus_ + * @brief Utopia Rx Status Register + */ + struct UtRxCellConditionStatus_ + { + + unsigned int reserved_1:3; /**< [31:29] These bits are always 0.*/ + unsigned int rxCellCountOvr:1; /**< [28] This bit is set if the RxCellCount register overflows. */ + unsigned int invalidHecCountOvr:1; /**< [27] This bit is set if the InvalidHecCount register overflows.*/ + unsigned int invalidParCountOvr:1; /**< [26] This bit is set if the InvalidParCount register overflows.*/ + unsigned int invalidSizeCountOvr:1; /**< [25] This bit is set if the InvalidSizeCount register overflows.*/ + unsigned int rxIdleCountOvr:1; /**< [24] This bit is set if the RxIdleCount register overflows.*/ + unsigned int reserved_2:4; /**< [23:20] These bits are always 0 */ + unsigned int rxFIFO2Underflow:1; /**< [19] This bit is set if 64-byte Receive FIFO2 + * indicates a FIFO underflow error condition. + */ + unsigned int rxFIFO1Underflow:1; /**< [18] This bit is set if 64-byte Receive + * FIFO1 indicates a FIFO underflow error condition + . */ + unsigned int rxFIFO2Overflow:1; /**< [17] This bit is set if 64-byte Receive FIFO2 + * indicates a FIFO overflow error condition. + */ + unsigned int rxFIFO1Overflow:1; /**< [16] This bit is set if 64-byte Receive FIFO1 + * indicates a FIFO overflow error condition. + */ + unsigned int reserved_3:16; /**< [15:0] These bits are always 0. */ + } utRxCellConditionStatus; /**< Rx cells condition status */ + +} IxAtmdAccUtopiaStatus; + +/** + * @} defgroup IxAtmdAccUtopiaCtrlAPI + */ + + /** + * + * @ingroup IxAtmdAccCtrlAPI + * + * @fn ixAtmdAccUtopiaConfigSet (const IxAtmdAccUtopiaConfig * + ixAtmdAccUtopiaConfigPtr) + * + * @brief Send the configuration structure to the Utopia interface + * + * This function downloads the @a IxAtmdAccUtopiaConfig structure to + * the Utopia and has the following effects + * @li setup the Utopia interface + * @li initialise the NPE + * @li reset the Utopia cell counters and status registers to known values + * + * This action has to be done once at initialisation. A lock is preventing + * the concurrent use of @a ixAtmdAccUtopiaStatusGet() and + * @A ixAtmdAccUtopiaConfigSet() + * + * @param *ixAtmdAccNPEConfigPtr @ref IxAtmdAccUtopiaConfig [in] - pointer to a structure to download to + * Utopia. This parameter cannot be a null pointer. + * + * @return @li IX_SUCCESS successful download + * @return @li IX_FAIL error in the parameters, or configuration is not + * complete or failed + * + * @sa ixAtmdAccUtopiaStatusGet + * + */ +PUBLIC IX_STATUS ixAtmdAccUtopiaConfigSet (const IxAtmdAccUtopiaConfig * + ixAtmdAccUtopiaConfigPtr); + +/** + * + * @ingroup IxAtmdAccCtrlAPI + * + * @fn ixAtmdAccUtopiaStatusGet (IxAtmdAccUtopiaStatus * + ixAtmdAccUtopiaStatus) + * + * @brief Get the Utopia interface configuration. + * + * This function reads the Utopia registers and the Cell counts + * and fills the @a IxAtmdAccUtopiaStatus structure + * + * A lock is preventing the concurrent + * use of @a ixAtmdAccUtopiaStatusGet() and @A ixAtmdAccUtopiaConfigSet() + * + * @param ixAtmdAccUtopiaStatus @ref IxAtmdAccUtopiaStatus [out] - pointer to structure to be updated from internal + * hardware counters. This parameter cannot be a NULL pointer. + * + * @return @li IX_SUCCESS successful read + * @return @li IX_FAIL error in the parameters null pointer, or + * configuration read is not complete or failed + * + * @sa ixAtmdAccUtopiaConfigSet + * + */ +PUBLIC IX_STATUS ixAtmdAccUtopiaStatusGet (IxAtmdAccUtopiaStatus * + ixAtmdAccUtopiaStatus); + +/** + * + * @ingroup IxAtmdAcc + * + * @fn ixAtmdAccPortEnable (IxAtmLogicalPort port) + * + * @brief enable a PHY logical port + * + * This function enables the transmission over one port. It should be + * called before accessing any resource from this port and before the + * establishment of a VC. + * + * When a port is enabled, the cell transmission to the Utopia interface + * is started. If there is no traffic already running, idle cells are + * sent over the interface. + * + * This function can be called multiple times. + * + * @param port @ref IxAtmLogicalPort [in] - logical PHY port [@a IX_UTOPIA_PORT_0 .. @a IX_UTOPIA_MAX_PORTS - 1] + * + * @return @li IX_SUCCESS enable is complete + * @return @li IX_ATMDACC_WARNING port already enabled + * @return @li IX_FAIL enable failed, wrong parameter, or cannot + * initialise this port (the port is maybe already in use, + * or there is a hardware issue) + * + * @note - This function needs internal locks and should not be + * called from an interrupt context + * + * @sa ixAtmdAccPortDisable + * + */ +PUBLIC IX_STATUS ixAtmdAccPortEnable (IxAtmLogicalPort port); + +/** + * + * @ingroup IxAtmdAccCtrlAPI + * + * @fn ixAtmdAccPortDisable (IxAtmLogicalPort port) + * + * @brief disable a PHY logical port + * + * This function disable the transmission over one port. + * + * When a port is disabled, the cell transmission to the Utopia interface + * is stopped. + * + * @param port @ref IxAtmLogicalPort [in] - logical PHY port [@a IX_UTOPIA_PORT_0 .. @a IX_UTOPIA_MAX_PORTS - 1] + * + * @return @li IX_SUCCESS disable is complete + * @return @li IX_ATMDACC_WARNING port already disabled + * @return @li IX_FAIL disable failed, wrong parameter . + * + * @note - This function needs internal locks and should not be called + * from an interrupt context + * + * @note - The response from hardware is done through the txDone mechanism + * to ensure the synchrnisation with tx resources. Therefore, the + * txDone mechanism needs to be serviced to make a PortDisable complete. + * + * @sa ixAtmdAccPortEnable + * @sa ixAtmdAccPortDisableComplete + * @sa ixAtmdAccTxDoneDispatch + * + */ +PUBLIC IX_STATUS ixAtmdAccPortDisable (IxAtmLogicalPort port); + +/** +* +* @ingroup IxAtmdAccCtrlAPI +* +* @fn ixAtmdAccPortDisableComplete (IxAtmLogicalPort port) +* +* @brief disable a PHY logical port +* +* This function indicates if the port disable for a port has completed. This +* function will return TRUE if the port has never been enabled. +* +* @param port @ref IxAtmLogicalPort [in] - logical PHY port [@a IX_UTOPIA_PORT_0 .. @a IX_UTOPIA_MAX_PORTS - 1] +* +* @return @li TRUE disable is complete +* @return @li FALSE disable failed, wrong parameter . +* +* @note - This function needs internal locks and should not be called +* from an interrupt context +* +* @sa ixAtmdAccPortEnable +* @sa ixAtmdAccPortDisable +* +*/ +PUBLIC BOOL ixAtmdAccPortDisableComplete (IxAtmLogicalPort port); + +#endif /* IXATMDACCCTRL_H */ + +/** + * @} defgroup IxAtmdAccCtrlAPI + */ + + diff --git a/cpu/ixp/npe/include/IxAtmm.h b/cpu/ixp/npe/include/IxAtmm.h new file mode 100644 index 0000000..fcf523f --- /dev/null +++ b/cpu/ixp/npe/include/IxAtmm.h @@ -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 */ + +/** @} */ diff --git a/cpu/ixp/npe/include/IxDmaAcc.h b/cpu/ixp/npe/include/IxDmaAcc.h new file mode 100644 index 0000000..53d2625 --- /dev/null +++ b/cpu/ixp/npe/include/IxDmaAcc.h @@ -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 */ + diff --git a/cpu/ixp/npe/include/IxEthAcc.h b/cpu/ixp/npe/include/IxEthAcc.h new file mode 100644 index 0000000..b424648 --- /dev/null +++ b/cpu/ixp/npe/include/IxEthAcc.h @@ -0,0 +1,2512 @@ +/** @file IxEthAcc.h + * + * @brief this file contains the public API of @ref IxEthAcc component + * + * Design notes: + * The IX_OSAL_MBUF address is to be specified on bits [31-5] and must + * be cache aligned (bits[4-0] cleared) + * + * + * @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 IxEthAcc_H +#define IxEthAcc_H + +#include +#include + +/** + * @defgroup IxEthAcc IXP400 Ethernet Access (IxEthAcc) API + * + * @brief ethAcc is a library that does provides access to the internal IXP400 10/100Bt Ethernet MACs. + * + *@{ + */ + +/** + * @ingroup IxEthAcc + * @brief Definition of the Ethernet Access status + */ +typedef enum /* IxEthAccStatus */ +{ + IX_ETH_ACC_SUCCESS = IX_SUCCESS, /**< return success*/ + IX_ETH_ACC_FAIL = IX_FAIL, /**< return fail*/ + IX_ETH_ACC_INVALID_PORT, /**< return invalid port*/ + IX_ETH_ACC_PORT_UNINITIALIZED, /**< return uninitialized*/ + IX_ETH_ACC_MAC_UNINITIALIZED, /**< return MAC uninitialized*/ + IX_ETH_ACC_INVALID_ARG, /**< return invalid arg*/ + IX_ETH_TX_Q_FULL, /**< return tx queue is full*/ + IX_ETH_ACC_NO_SUCH_ADDR /**< return no such address*/ +} IxEthAccStatus; + +/** + * @ingroup IxEthAcc + * @enum IxEthAccPortId + * @brief Definition of the IXP400 Mac Ethernet device. + */ +typedef enum +{ + IX_ETH_PORT_1 = 0, /**< Ethernet Port 1 */ + IX_ETH_PORT_2 = 1 /**< Ethernet port 2 */ + ,IX_ETH_PORT_3 = 2 /**< Ethernet port 3 */ +} IxEthAccPortId; + +/** + * @ingroup IxEthAcc + * + * @def IX_ETH_ACC_NUMBER_OF_PORTS + * + * @brief Definition of the number of ports + * + */ +#ifdef __ixp46X +#define IX_ETH_ACC_NUMBER_OF_PORTS (3) +#else +#define IX_ETH_ACC_NUMBER_OF_PORTS (2) +#endif + +/** + * @ingroup IxEthAcc + * + * @def IX_IEEE803_MAC_ADDRESS_SIZE + * + * @brief Definition of the size of the MAC address + * + */ +#define IX_IEEE803_MAC_ADDRESS_SIZE (6) + + +/** + * + * @brief Definition of the IEEE 802.3 Ethernet MAC address structure. + * + * The data should be packed with bytes xx:xx:xx:xx:xx:xx + * @note + * The data must be packed in network byte order. + */ +typedef struct +{ + UINT8 macAddress[IX_IEEE803_MAC_ADDRESS_SIZE]; /**< MAC address */ +} IxEthAccMacAddr; + +/** + * @ingroup IxEthAcc + * @def IX_ETH_ACC_NUM_TX_PRIORITIES + * @brief Definition of the number of transmit priorities + * + */ +#define IX_ETH_ACC_NUM_TX_PRIORITIES (8) + +/** + * @ingroup IxEthAcc + * @enum IxEthAccTxPriority + * @brief Definition of the relative priority used to transmit a frame + * + */ +typedef enum +{ + IX_ETH_ACC_TX_PRIORITY_0 = 0, /** STA */ + IX_ETHACC_RX_APTYPE = 0x30 /**< 802.11, AP <=> AP */ +} IxEthAccRxFrameType; + +/** + * @ingroup IxEthAcc + * @enum IxEthAccDuplexMode + * @brief Definition to provision the duplex mode of the MAC. + * + */ +typedef enum +{ + IX_ETH_ACC_FULL_DUPLEX, /**< Full duplex operation of the MAC */ + IX_ETH_ACC_HALF_DUPLEX /**< Half duplex operation of the MAC */ +} IxEthAccDuplexMode; + + +/** + * @ingroup IxEthAcc + * @struct IxEthAccNe + * @brief Definition of service-specific informations. + * + * This structure defines the Ethernet service-specific informations + * and enable QoS and VLAN features. + */ +typedef struct +{ + UINT32 ixReserved_next; /**< reserved for chaining */ + UINT32 ixReserved_lengths; /**< reserved for buffer lengths */ + UINT32 ixReserved_data; /**< reserved for buffer pointer */ + UINT8 ixDestinationPortId; /**< Destination portId for this packet, if known by NPE */ + UINT8 ixSourcePortId; /**< Source portId for this packet */ + UINT16 ixFlags; /**< BitField of option for this frame */ + UINT8 ixQoS; /**< QoS class of the frame */ + UINT8 ixReserved; /**< reserved */ + UINT16 ixVlanTCI; /**< Vlan TCI */ + UINT8 ixDestMac[IX_IEEE803_MAC_ADDRESS_SIZE]; /**< Destination MAC address */ + UINT8 ixSourceMac[IX_IEEE803_MAC_ADDRESS_SIZE]; /**< Source MAC address */ +} IxEthAccNe; + +/** + * @ingroup IxEthAcc + * + * @def IX_ETHACC_NE_PORT_UNKNOWN + * + * @brief Contents of the field @a IX_ETHACC_NE_DESTPORTID when no + * destination port can be found by the NPE for this frame. + * + */ +#define IX_ETHACC_NE_PORT_UNKNOWN (0xff) + +/** + * @ingroup IxEthAcc + * + * @def IX_ETHACC_NE_DESTMAC + * + * @brief The location of the destination MAC address in the Mbuf header. + * + */ +#define IX_ETHACC_NE_DESTMAC(mBufPtr) ((IxEthAccNe *)&((mBufPtr)->ix_ne))->ixDestMac + +/** + * @ingroup IxEthAcc + * + * @def IX_ETHACC_NE_SOURCEMAC + * + * @brief The location of the source MAC address in the Mbuf header. + * + */ +#define IX_ETHACC_NE_SOURCEMAC(mBufPtr) ((IxEthAccNe *)&((mBufPtr)->ix_ne))->ixSourceMac + +/** + * @ingroup IxEthAcc + * + * @def IX_ETHACC_NE_VLANTCI + * + * @brief The VLAN Tag Control Information associated with this frame + * + * The VLAN Tag Control Information associated with this frame. On Rx + * path, this field is extracted from the packet header. + * On Tx path, the value of this field is inserted in the frame when + * the port is configured to insert or replace vlan tags in the + * egress frames. + * + * @sa IX_ETHACC_NE_FLAGS + */ +#define IX_ETHACC_NE_VLANTCI(mBufPtr) ((IxEthAccNe *)&((mBufPtr)->ix_ne))->ixVlanTCI + +/** + * @ingroup IxEthAcc + * + * @def IX_ETHACC_NE_SOURCEPORTID + * + * @brief The port where this frame came from. + * + * The port where this frame came from. This field is set on receive + * with the port information. This field is ignored on Transmit path. + */ +#define IX_ETHACC_NE_SOURCEPORTID(mBufPtr) ((IxEthAccNe *)&((mBufPtr)->ix_ne))->ixSourcePortId + +/** + * @ingroup IxEthAcc + * + * @def IX_ETHACC_NE_DESTPORTID + * + * @brief The destination port where this frame should be sent. + * + * The destination port where this frame should be sent. + * + * @li In the transmit direction, this field contains the destination port + * and is ignored unless @a IX_ETHACC_NE_FLAG_DST is set. + * + * @li In the receive direction, this field contains the port where the + * destination MAC addresses has been learned. If the destination + * MAC address is unknown, then this value is set to the reserved value + * @a IX_ETHACC_NE_PORT_UNKNOWN + * + */ +#define IX_ETHACC_NE_DESTPORTID(mBufPtr) ((IxEthAccNe *)&((mBufPtr)->ix_ne))->ixDestinationPortId + +/** + * @ingroup IxEthAcc + * + * @def IX_ETHACC_NE_QOS + * + * @brief QualityOfService class (QoS) for this received frame. + * + */ +#define IX_ETHACC_NE_QOS(mBufPtr) ((IxEthAccNe *)&((mBufPtr)->ix_ne))->ixQoS + +/** + * @ingroup IxEthAcc + * + * @def IX_ETHACC_NE_FLAGS + * + * @brief Bit Mask of the different flags associated with a frame + * + * The flags are the bit-oring combination + * of the following different fields : + * + * @li IP flag (Rx @a IX_ETHACC_NE_IPMASK) + * @li Spanning Tree flag (Rx @a IX_ETHACC_NE_STMASK) + * @li Link layer type (Rx and Tx @a IX_ETHACC_NE_LINKMASK) + * @li VLAN Tagged Frame (Rx @a IX_ETHACC_NE_VLANMASK) + * @li New source MAC address (Rx @a IX_ETHACC_NE_NEWSRCMASK) + * @li Multicast flag (Rx @a IX_ETHACC_NE_MCASTMASK) + * @li Broadcast flag (Rx @a IX_ETHACC_NE_BCASTMASK) + * @li Destination port flag (Tx @a IX_ETHACC_NE_PORTMASK) + * @li Tag/Untag Tx frame (Tx @a IX_ETHACC_NE_TAGMODEMASK) + * @li Overwrite destination port (Tx @a IX_ETHACC_NE_PORTOVERMASK) + * @li Filtered frame (Rx @a IX_ETHACC_NE_STMASK) + * @li VLAN Enabled (Rx and Tx @a IX_ETHACC_NE_VLANENABLEMASK) + */ +#define IX_ETHACC_NE_FLAGS(mBufPtr) ((IxEthAccNe *)&((mBufPtr)->ix_ne))->ixFlags + +/** + * @ingroup IxEthAcc + * + * @def IX_ETHACC_NE_BCASTMASK + * + * @brief This mask defines if a received frame is a broadcast frame. + * + * This mask defines if a received frame is a broadcast frame. + * The BCAST flag is set when the destination MAC address of + * a frame is broadcast. + * + * @sa IX_ETHACC_NE_FLAGS + * + */ +#define IX_ETHACC_NE_BCASTMASK (0x1) + +/** + * @ingroup IxEthAcc + * + * @def IX_ETHACC_NE_MCASTMASK + * + * @brief This mask defines if a received frame is a multicast frame. + * + * This mask defines if a received frame is a multicast frame. + * The MCAST flag is set when the destination MAC address of + * a frame is multicast. + * + * @sa IX_ETHACC_NE_FLAGS + * + */ +#define IX_ETHACC_NE_MCASTMASK (0x1 << 1) + +/** + * @ingroup IxEthAcc + * + * @def IX_ETHACC_NE_IPMASK + * + * @brief This mask defines if a received frame is a IP frame. + * + * This mask applies to @a IX_ETHACC_NE_FLAGS and defines if a received + * frame is a IP frame. The IP flag is set on Rx direction, depending on + * the frame contents. The flag is set when the length/type field of a + * received frame is 0x8000. + * + * @sa IX_ETHACC_NE_FLAGS + * + */ +#define IX_ETHACC_NE_IPMASK (0x1 << 2) + +/** + * @ingroup IxEthAcc + * + * @def IX_ETHACC_NE_VLANMASK + * + * @brief This mask defines if a received frame is VLAN tagged. + * + * This mask defines if a received frame is VLAN tagged. + * When set, the Rx frame is VLAN-tagged and the tag value + * is available thru @a IX_ETHACC_NE_VLANID. + * Note that when sending frames which are already tagged + * this flag should be set, to avoid inserting another VLAN tag. + * + * @sa IX_ETHACC_NE_FLAGS + * @sa IX_ETHACC_NE_VLANID + * + */ +#define IX_ETHACC_NE_VLANMASK (0x1 << 3) + +/** + * @ingroup IxEthAcc + * + * @def IX_ETHACC_NE_LINKMASK + * + * @brief This mask is the link layer protocol indicator + * + * This mask applies to @a IX_ETHACC_NE_FLAGS. + * It reflects the state of a frame as it exits an NPE on the Rx path + * or enters an NPE on the Tx path. Its values are as follows: + * @li 0x00 - IEEE802.3 - 8802 (Rx) / IEEE802.3 - 8802 (Tx) + * @li 0x01 - IEEE802.3 - Ethernet (Rx) / IEEE802.3 - Ethernet (Tx) + * @li 0x02 - IEEE802.11 AP -> STA (Rx) / IEEE802.11 STA -> AP (Tx) + * @li 0x03 - IEEE802.11 AP -> AP (Rx) / IEEE802.11 AP->AP (Tx) + * + * @sa IX_ETHACC_NE_FLAGS + * + */ +#define IX_ETHACC_NE_LINKMASK (0x3 << 4) + +/** + * @ingroup IxEthAcc + * + * @def IX_ETHACC_NE_STMASK + * + * @brief This mask defines if a received frame is a Spanning Tree frame. + * + * This mask applies to @a IX_ETHACC_NE_FLAGS. + * On rx direction, it defines if a received if frame is a Spanning Tree frame. + * Setting this fkag on transmit direction overrides the port settings + * regarding the VLAN options and + * + * @sa IX_ETHACC_NE_FLAGS + * + */ +#define IX_ETHACC_NE_STMASK (0x1 << 6) + +/** + * @ingroup IxEthAcc + * + * @def IX_ETHACC_NE_FILTERMASK + * + * @brief This bit indicates whether a frame has been filtered by the Rx service. + * + * This mask applies to @a IX_ETHACC_NE_FLAGS. + * Certain frames, which should normally be fully filtered by the NPE to due + * the destination MAC address being on the same segment as the Rx port are + * still forwarded to the XScale (although the payload is invalid) in order + * to learn the MAC address of the transmitting station, if this is unknown. + * Normally EthAcc will filter and recycle these framess internally and no + * frames with the FILTER bit set will be received by the client. + * + * @sa IX_ETHACC_NE_FLAGS + * + */ +#define IX_ETHACC_NE_FILTERMASK (0x1 << 7) + +/** + * @ingroup IxEthAcc + * + * @def IX_ETHACC_NE_PORTMASK + * + * @brief This mask defines the rule to transmit a frame + * + * This mask defines the rule to transmit a frame. When set, a frame + * is transmitted to the destination port as set by the macro + * @a IX_ETHACC_NE_DESTPORTID. If not set, the destination port + * is searched using the destination MAC address. + * + * @note This flag is meaningful only for multiport Network Engines. + * + * @sa IX_ETHACC_NE_FLAGS + * @sa IX_ETHACC_NE_DESTPORTID + * + */ +#define IX_ETHACC_NE_PORTOVERMASK (0x1 << 8) + +/** + * @ingroup IxEthAcc + * + * @def IX_ETHACC_NE_TAGMODEMASK + * + * @brief This mask defines the tagging rules to apply to a transmit frame. + * + * This mask defines the tagging rules to apply to a transmit frame + * regardless of the default setting for a port. When used together + * with @a IX_ETHACC_NE_TAGOVERMASK and when set, the + * frame will be tagged prior to transmission. When not set, + * the frame will be untagged prior to transmission. This is accomplished + * irrespective of the Egress tagging rules, constituting a per-frame override. + * + * @sa IX_ETHACC_NE_FLAGS + * @sa IX_ETHACC_NE_TAGOVERMASK + * + */ +#define IX_ETHACC_NE_TAGMODEMASK (0x1 << 9) + +/** + * @ingroup IxEthAcc + * + * @def IX_ETHACC_NE_TAGOVERMASK + * + * @brief This mask defines the rule to transmit a frame + * + * This mask defines the rule to transmit a frame. When set, the + * default transmit rules of a port are overriden. + * When not set, the default rules as set by @ref IxEthDB should apply. + * + * @sa IX_ETHACC_NE_FLAGS + * @sa IX_ETHACC_NE_TAGMODEMASK + * + */ +#define IX_ETHACC_NE_TAGOVERMASK (0x1 << 10) + +/** + * @ingroup IxEthAcc + * + * @def IX_ETHACC_NE_VLANENABLEMASK + * + * @brief This mask defines if a frame is a VLAN frame or not + * + * When set, frames undergo normal VLAN processing on the Tx path + * (membership filtering, tagging, tag removal etc). If this flag is + * not set, the frame is considered to be a regular non-VLAN frame + * and no VLAN processing will be performed. + * + * Note that VLAN-enabled NPE images will always set this flag in all + * Rx frames, and images which are not VLAN enabled will clear this + * flag for all received frames. + * + * @sa IX_ETHACC_NE_FLAGS + * + */ +#define IX_ETHACC_NE_VLANENABLEMASK (0x1 << 14) + +/** + * @ingroup IxEthAcc + * + * @def IX_ETHACC_NE_NEWSRCMASK + * + * @brief This mask defines if a received frame has been learned. + * + * This mask defines if the source MAC address of a frame is + * already known. If the bit is set, the source MAC address was + * unknown to the NPE at the time the frame was received. + * + * @sa IX_ETHACC_NE_FLAGS + * + */ +#define IX_ETHACC_NE_NEWSRCMASK (0x1 << 15) + +/** + * @ingroup IxEthAcc + * + * @brief This defines the recommanded minimum size of MBUF's submitted + * to the frame receive service. + * + */ +#define IX_ETHACC_RX_MBUF_MIN_SIZE (2048) + +/** + * @ingroup IxEthAcc + * + * @brief This defines the highest MII address of any attached PHYs + * + * The maximum number for PHY address is 31, add on for range checking. + * + */ +#define IXP425_ETH_ACC_MII_MAX_ADDR 32 + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccInit(void) + * + * @brief Initializes the IXP400 Ethernet Access Service. + * + * @li Reentrant - no + * @li ISR Callable - no + * + * This should be called once per module initialization. + * @pre + * The NPE must first be downloaded with the required microcode which supports all + * required features. + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_FAIL : Service has failed to initialize. + * + *
+ */ +PUBLIC IxEthAccStatus ixEthAccInit(void); + + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccUnload(void) + * + * @brief Unload the Ethernet Access Service. + * + * @li Reentrant - no + * @li ISR Callable - no + * + * @return void + * + *
+ */ +PUBLIC void ixEthAccUnload(void); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortInit( IxEthAccPortId portId) + * + * @brief Initializes an NPE/Ethernet MAC Port. + * + * The NPE/Ethernet port initialisation includes the following steps + * @li Initialize the NPE/Ethernet MAC hardware. + * @li Verify NPE downloaded and operational. + * @li The NPE shall be available for usage once this API returns. + * @li Verify that the Ethernet port is present before initializing + * + * @li Reentrant - no + * @li ISR Callable - no + * + * This should be called once per mac device. + * The NPE/MAC shall be in disabled state after init. + * + * @pre + * The component must be initialized via @a ixEthAccInit + * The NPE must first be downloaded with the required microcode which supports all + * required features. + * + * Dependant on Services: (Must be initialized before using this service may be initialized) + * ixNPEmh - NPE Message handling service. + * ixQmgr - Queue Manager component. + * + * @param portId @ref IxEthAccPortId [in] + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS: if the ethernet port is not present, a warning is issued. + * @li @a IX_ETH_ACC_FAIL : The NPE processor has failed to initialize. + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * + *
+ */ +PUBLIC IxEthAccStatus ixEthAccPortInit(IxEthAccPortId portId); + + +/************************************************************************* + + ##### ## ##### ## ##### ## ##### # # + # # # # # # # # # # # # # # + # # # # # # # # # # # # ###### + # # ###### # ###### ##### ###### # # # + # # # # # # # # # # # # # + ##### # # # # # # # # # # # + +*************************************************************************/ + + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortTxFrameSubmit( + IxEthAccPortId portId, + IX_OSAL_MBUF *buffer, + IxEthAccTxPriority priority) + * + * @brief This function shall be used to submit MBUFs buffers for transmission on a particular MAC device. + * + * When the frame is transmitted, the buffer shall be returned thru the + * callback @a IxEthAccPortTxDoneCallback. + * + * In case of over-submitting, the order of the frames on the + * network may be modified. + * + * Buffers shall be not queued for transmission if the port is disabled. + * The port can be enabled using @a ixEthAccPortEnable + * + * + * @li Reentrant - yes + * @li ISR Callable - yes + * + * + * @pre + * @a ixEthAccPortTxDoneCallbackRegister must be called to register a function to allow this service to + * return the buffer to the calling service. + * + * @note + * If the buffer submit fails for any reason the user has retained ownership of the buffer. + * + * @param portId @ref IxEthAccPortId [in] - MAC port ID to transmit Ethernet frame on. + * @param buffer @ref IX_OSAL_MBUF [in] - pointer to an MBUF formatted buffer. Chained buffers are supported for transmission. + * Chained packets are not supported and the field IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR is ignored. + * @param priority @ref IxEthAccTxPriority [in] + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_FAIL : Failed to queue frame for transmission. + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is un-initialized + * + *
+ */ + +PUBLIC IxEthAccStatus ixEthAccPortTxFrameSubmit( + IxEthAccPortId portId, + IX_OSAL_MBUF *buffer, + IxEthAccTxPriority priority); + +/** + * @ingroup IxEthAcc + * + * @brief Function prototype for Ethernet Tx Buffer Done callback. Registered + * via @a ixEthAccTxBufferDoneCallbackRegister + * + * This function is called once the previously submitted buffer is no longer required by this service. + * It may be returned upon successful transmission of the frame or during the shutdown of + * the port prior to the transmission of a queued frame. + * The calling of this registered function is not a guarantee of successful transmission of the buffer. + * + * + * @li Reentrant - yes , The user provided function should be reentrant. + * @li ISR Callable - yes , The user provided function must be callable from an ISR. + * + * + * Calling Context : + * @par + * This callback is called in the context of the queue manager dispatch loop @a ixQmgrgrDispatcherLoopRun + * within the @ref IxQMgrAPI component. The calling context may be from interrupt or high priority thread. + * The decision is system specific. + * + * @param callbackTag UINT32 [in] - This tag is that provided when the callback was registered for a particular MAC + * via @a ixEthAccPortTxDoneCallbackRegister. It allows the same callback to be used for multiple MACs. + * @param mbuf @ref IX_OSAL_MBUF [in] - Pointer to the Tx mbuf descriptor. + * + * @return void + * + * @note + * The field IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR is modified by the access layer and reset to NULL. + * + *
+ */ +typedef void (*IxEthAccPortTxDoneCallback) ( UINT32 callbackTag, IX_OSAL_MBUF *buffer ); + + + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortTxDoneCallbackRegister( IxEthAccPortId portId, + IxEthAccPortTxDoneCallback txCallbackFn, + UINT32 callbackTag) + * + * @brief Register a callback function to allow + * the transmitted buffers to return to the user. + * + * This function registers the transmit buffer done function callback for a particular port. + * + * The registered callback function is called once the previously submitted buffer is no longer required by this service. + * It may be returned upon successful transmission of the frame or shutdown of port prior to submission. + * The calling of this registered function is not a guarantee of successful transmission of the buffer. + * + * If called several times the latest callback shall be registered for a particular port. + * + * @li Reentrant - yes + * @li ISR Callable - yes + * + * @pre + * The port must be initialized via @a ixEthAccPortInit + * + * + * @param portId @ref IxEthAccPortId [in] - Register callback for a particular MAC device. + * @param txCallbackFn @ref IxEthAccPortTxDoneCallback [in] - Function to be called to return transmit buffers to the user. + * @param callbackTag UINT32 [in] - This tag shall be provided to the callback function. + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is un-initialized + * @li @a IX_ETH_ACC_INVALID_ARG : An argument other than portId is invalid. + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccPortTxDoneCallbackRegister(IxEthAccPortId portId, + IxEthAccPortTxDoneCallback txCallbackFn, + UINT32 callbackTag); + + + +/** + * @ingroup IxEthAcc + * + * @brief Function prototype for Ethernet Frame Rx callback. Registered via @a ixEthAccPortRxCallbackRegister + * + * It is the responsibility of the user function to free any MBUF's which it receives. + * + * @li Reentrant - yes , The user provided function should be reentrant. + * @li ISR Callable - yes , The user provided function must be callable from an ISR. + * @par + * + * This function dispatches frames to the user level + * via the provided function. The invocation shall be made for each + * frame dequeued from the Ethernet QM queue. The user is required to free any MBUF's + * supplied via this callback. In addition the registered callback must free up MBUF's + * from the receive free queue when the port is disabled + * + * If called several times the latest callback shall be registered for a particular port. + * + * Calling Context : + * @par + * This callback is called in the context of the queue manager dispatch loop @a ixQmgrgrDispatcherLoopRun + * within the @ref IxQMgrAPI component. The calling context may be from interrupt or high priority thread. + * The decision is system specific. + * + * + * @param callbackTag UINT32 [in] - This tag is that provided when the callback was registered for a particular MAC + * via @a ixEthAccPortRxCallbackRegister. It allows the same callback to be used for multiple MACs. + * @param mbuf @ref IX_OSAL_MBUF [in] - Pointer to the Rx mbuf header. Mbufs may be chained if + * the frame length is greater than the supplied mbuf length. + * @param reserved [in] - deprecated parameter The information is passed + * thru the IxEthAccNe header destination port ID field + * (@sa IX_ETHACC_NE_DESTPORTID). For backward + * compatibility,the value is equal to IX_ETH_DB_UNKNOWN_PORT (0xff). + * + * @return void + * + * @note + * Buffers may not be filled up to the length supplied in + * @a ixEthAccPortRxFreeReplenish(). The firmware fills + * them to the previous 64 bytes boundary. The user has to be aware + * that the length of the received mbufs may be smaller than the length + * of the supplied mbufs. + * The mbuf header contains the following modified field + * @li @a IX_OSAL_MBUF_PKT_LEN is set in the header of the first mbuf and indicates + * the total frame size + * @li @a IX_OSAL_MBUF_MLEN is set each mbuf header and indicates the payload length + * @li @a IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR contains a pointer to the next + * mbuf, or NULL at the end of a chain. + * @li @a IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR is modified. Its value is reset to NULL + * @li @a IX_OSAL_MBUF_FLAGS contains the bit 4 set for a broadcast packet and the bit 5 + * set for a multicast packet. Other bits are unmodified. + * + *
+ */ +typedef void (*IxEthAccPortRxCallback) (UINT32 callbackTag, IX_OSAL_MBUF *buffer, UINT32 reserved); + +/** + * @ingroup IxEthAcc + * + * @brief Function prototype for Ethernet Frame Rx callback. Registered via @a ixEthAccPortMultiBufferRxCallbackRegister + * + * It is the responsibility of the user function to free any MBUF's which it receives. + * + * @li Reentrant - yes , The user provided function should be reentrant. + * @li ISR Callable - yes , The user provided function must be callable from an ISR. + * @par + * + * This function dispatches many frames to the user level + * via the provided function. The invocation shall be made for multiple frames + * dequeued from the Ethernet QM queue. The user is required to free any MBUF's + * supplied via this callback. In addition the registered callback must free up MBUF's + * from the receive free queue when the port is disabled + * + * If called several times the latest callback shall be registered for a particular port. + * + * Calling Context : + * @par + * This callback is called in the context of the queue manager dispatch loop @a ixQmgrDispatcherLoopRun + * within the @ref IxQMgrAPI component. The calling context may be from interrupt or high priority thread. + * The decision is system specific. + * + * + * @param callbackTag - This tag is that provided when the callback was registered for a particular MAC + * via @a ixEthAccPortMultiBufferRxCallbackRegister. It allows the same callback to be used for multiple MACs. + * @param mbuf - Pointer to an array of Rx mbuf headers. Mbufs + * may be chained if + * the frame length is greater than the supplied mbuf length. + * The end of the array contains a zeroed entry (NULL pointer). + * + * @return void + * + * @note The mbufs passed to this callback have the same structure than the + * buffers passed to @a IxEthAccPortRxCallback interfac. + * + * @note The usage of this callback is exclusive with the usage of + * @a ixEthAccPortRxCallbackRegister and @a IxEthAccPortRxCallback + * + * @sa ixEthAccPortMultiBufferRxCallbackRegister + * @sa IxEthAccPortMultiBufferRxCallback + * @sa ixEthAccPortRxCallbackRegister + * @sa IxEthAccPortRxCallback + *
+ */ + +typedef void (*IxEthAccPortMultiBufferRxCallback) (UINT32 callbackTag, IX_OSAL_MBUF **buffer); + + + + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortRxCallbackRegister( IxEthAccPortId portId, IxEthAccPortRxCallback rxCallbackFn, UINT32 callbackTag) + * + * @brief Register a callback function to allow + * the reception of frames. + * + * The registered callback function is called once a frame is received by this service. + * + * If called several times the latest callback shall be registered for a particular port. + * + * + * @li Reentrant - yes + * @li ISR Callable - yes + * + * + * @param portId @ref IxEthAccPortId [in] - Register callback for a particular MAC device. + * @param rxCallbackFn @ref IxEthAccPortRxCallback [in] - Function to be called when Ethernet frames are availble. + * @param callbackTag UINT32 [in] - This tag shall be provided to the callback function. + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is un-initialized + * @li @a IX_ETH_ACC_INVALID_ARG : An argument other than portId is invalid. + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccPortRxCallbackRegister(IxEthAccPortId portId, + IxEthAccPortRxCallback rxCallbackFn, + UINT32 callbackTag); + + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortMultiBufferRxCallbackRegister( IxEthAccPortId portId, IxEthAccPortMultiBufferRxCallback rxCallbackFn, UINT32 callbackTag) + * + * @brief Register a callback function to allow + * the reception of frames. + * + * The registered callback function is called once a frame is + * received by this service. If many frames are already received, + * the function is called once. + * + * If called several times the latest callback shall be registered for a particular port. + * + * @li Reentrant - yes + * @li ISR Callable - yes + * + * + * @param portId - Register callback for a particular MAC device. + * @param rxCallbackFn - @a IxEthAccMultiBufferRxCallbackFn - Function to be called when Ethernet frames are availble. + * @param callbackTag - This tag shall be provided to the callback function. + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is un-initialized + * @li @a IX_ETH_ACC_INVALID_ARG : An argument other than portId is invalid. + * + * @sa ixEthAccPortMultiBufferRxCallbackRegister + * @sa IxEthAccPortMultiBufferRxCallback + * @sa ixEthAccPortRxCallbackRegister + * @sa IxEthAccPortRxCallback + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccPortMultiBufferRxCallbackRegister(IxEthAccPortId portId, + IxEthAccPortMultiBufferRxCallback rxCallbackFn, + UINT32 callbackTag); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortRxFreeReplenish( IxEthAccPortId portId, IX_OSAL_MBUF *buffer) + * + * @brief This function provides buffers for the Ethernet receive path. + * + * This component does not have a buffer management mechanisms built in. All Rx buffers must be supplied to it + * via this interface. + * + * @li Reentrant - yes + * @li ISR Callable - yes + * + * @param portId @ref IxEthAccPortId [in] - Provide buffers only to specific Rx MAC. + * @param buffer @ref IX_OSAL_MBUF [in] - Provide an MBUF to the Ethernet receive mechanism. + * Buffers size smaller than IX_ETHACC_RX_MBUF_MIN_SIZE may result in poor + * performances and excessive buffer chaining. Buffers + * larger than this size may be suitable for jumbo frames. + * Chained packets are not supported and the field IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR must be NULL. + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_FAIL : Buffer has was not able to queue the + * buffer in the receive service. + * @li @a IX_ETH_ACC_FAIL : Buffer size is less than IX_ETHACC_RX_MBUF_MIN_SIZE + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is un-initialized + * + * @note + * If the buffer replenish operation fails it is the responsibility + * of the user to free the buffer. + * + * @note + * Sufficient buffers must be supplied to the component to maintain + * receive throughput and avoid rx buffer underflow conditions. + * To meet this goal, It is expected that the user preload the + * component with a sufficent number of buffers prior to enabling the + * NPE Ethernet receive path. The recommended minimum number of + * buffers is 8. + * + * @note + * For maximum performances, the mbuf size should be greater + * than the maximum frame size (Ethernet header, payload and FCS) + 64. + * Supplying smaller mbufs to the service results in mbuf + * chaining and degraded performances. The recommended size + * is @a IX_ETHACC_RX_MBUF_MIN_SIZE, which is + * enough to take care of 802.3 frames and "baby jumbo" frames without + * chaining, and "jumbo" frame within chaining. + * + * @note + * Buffers may not be filled up to their length. The firware fills + * them up to the previous 64 bytes boundary. The user has to be aware + * that the length of the received mbufs may be smaller than the length + * of the supplied mbufs. + * + * @warning This function checks the parameters if the NDEBUG + * flag is not defined. Turning on the argument checking (disabled by + * default) results in a lower EthAcc performance as this function + * is part of the data path. + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccPortRxFreeReplenish( IxEthAccPortId portId, IX_OSAL_MBUF *buffer); + + + +/*************************************************************** + + #### #### # # ##### ##### #### # + # # # # ## # # # # # # # + # # # # # # # # # # # # + # # # # # # # ##### # # # + # # # # # ## # # # # # # + #### #### # # # # # #### ###### + + + ##### # ## # # ###### + # # # # # ## # # + # # # # # # # # ##### + ##### # ###### # # # # + # # # # # ## # + # ###### # # # # ###### + +***************************************************************/ + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortEnable(IxEthAccPortId portId) + * + * @brief This enables an Ethernet port for both Tx and Rx. + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @pre The port must first be initialized via @a ixEthAccPortInit and the MAC address + * must be set using @a ixEthAccUnicastMacAddressSet before enabling it + * The rx and Tx Done callbacks registration via @a + * ixEthAccPortTxDoneCallbackRegister amd @a ixEthAccPortRxCallbackRegister + * has to be done before enabling the traffic. + * + * @param portId @ref IxEthAccPortId [in] - Port id to act upon. + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is not initialized + * @li @a IX_ETH_ACC_MAC_UNINITIALIZED : port MAC address is not initialized + * + *
+ */ +PUBLIC IxEthAccStatus ixEthAccPortEnable(IxEthAccPortId portId); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortDisable(IxEthAccPortId portId) + * + * @brief This disables an Ethernet port for both Tx and Rx. + * + * Free MBufs are returned to the user via the registered callback when the port is disabled + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @pre The port must be enabled with @a ixEthAccPortEnable, otherwise this + * function has no effect + * + * @param portId @ref IxEthAccPortId [in] - Port id to act upon. + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is not initialized + * @li @a IX_ETH_ACC_MAC_UNINITIALIZED : port MAC address is not initialized + * + *
+ */ +PUBLIC IxEthAccStatus ixEthAccPortDisable(IxEthAccPortId portId); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortEnabledQuery(IxEthAccPortId portId, BOOL *enabled) + * + * @brief Get the enabled state of a port. + * + * @li Reentrant - yes + * @li ISR Callable - yes + * + * @pre The port must first be initialized via @a ixEthAccPortInit + * + * @param portId @ref IxEthAccPortId [in] - Port id to act upon. + * @param enabled BOOL [out] - location to store the state of the port + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccPortEnabledQuery(IxEthAccPortId portId, BOOL *enabled); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortPromiscuousModeClear(IxEthAccPortId portId) + * + * @brief Put the Ethernet MAC device in non-promiscuous mode. + * + * In non-promiscuous mode the MAC filters all frames other than + * destination MAC address which matches the following criteria: + * @li Unicast address provisioned via @a ixEthAccUnicastMacAddressSet + * @li All broadcast frames. + * @li Multicast addresses provisioned via @a ixEthAccMulticastAddressJoin + * + * Other functions modify the MAC filtering + * + * @li @a ixEthAccPortMulticastAddressJoinAll() - all multicast + * frames are forwarded to the application + * @li @a ixEthAccPortMulticastAddressLeaveAll() - rollback the + * effects of @a ixEthAccPortMulticastAddressJoinAll() + * @li @a ixEthAccPortMulticastAddressLeave() - unprovision a new + * filtering address + * @li @a ixEthAccPortMulticastAddressJoin() - provision a new + * filtering address + * @li @a ixEthAccPortPromiscuousModeSet() - all frames are + * forwarded to the application regardless of the multicast + * address provisioned + * @li @a ixEthAccPortPromiscuousModeClear() - frames are forwarded + * to the application following the multicast address provisioned + * + * In all cases, unicast and broadcast addresses are forwarded to + * the application. + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @sa ixEthAccPortPromiscuousModeSet + * + * @param portId @ref IxEthAccPortId [in] - Ethernet port id. + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is un-initialized + * + *
+ */ +PUBLIC IxEthAccStatus ixEthAccPortPromiscuousModeClear(IxEthAccPortId portId); + + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortPromiscuousModeSet(IxEthAccPortId portId) + * + * @brief Put the MAC device in promiscuous mode. + * + * If the device is in promiscuous mode then all all received frames shall be forwared + * to the NPE for processing. + * + * Other functions modify the MAC filtering + * + * @li @a ixEthAccPortMulticastAddressJoinAll() - all multicast + * frames are forwarded to the application + * @li @a ixEthAccPortMulticastAddressLeaveAll() - rollback the + * effects of @a ixEthAccPortMulticastAddressJoinAll() + * @li @a ixEthAccPortMulticastAddressLeave() - unprovision a new + * filtering address + * @li @a ixEthAccPortMulticastAddressJoin() - provision a new + * filtering address + * @li @a ixEthAccPortPromiscuousModeSet() - all frames are + * forwarded to the application regardless of the multicast + * address provisioned + * @li @a ixEthAccPortPromiscuousModeClear() - frames are forwarded + * to the application following the multicast address provisioned + * + * In all cases, unicast and broadcast addresses are forwarded to + * the application. + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @sa ixEthAccPortPromiscuousModeClear + * + * @param portId @ref IxEthAccPortId [in] - Ethernet port id. + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is un-initialized + * + *
+ */ +PUBLIC IxEthAccStatus ixEthAccPortPromiscuousModeSet(IxEthAccPortId portId); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortUnicastMacAddressSet( IxEthAccPortId portId, + IxEthAccMacAddr *macAddr) + * + * @brief Configure unicast MAC address for a particular port + * + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @param portId @ref IxEthAccPortId [in] - Ethernet port id. + * @param *macAddr @ref IxEthAccMacAddr [in] - Ethernet Mac address. + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is un-initialized + * + *
+ */ +PUBLIC IxEthAccStatus ixEthAccPortUnicastMacAddressSet(IxEthAccPortId portId, + IxEthAccMacAddr *macAddr); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortUnicastMacAddressGet( IxEthAccPortId portId, + IxEthAccMacAddr *macAddr) + * + * @brief Get unicast MAC address for a particular MAC port + * + * @pre + * The MAC address must first be set via @a ixEthAccMacPromiscuousModeSet + * If the MAC address has not been set, the function returns a + * IX_ETH_ACC_MAC_UNINITIALIZED status + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @param portId @ref IxEthAccPortId [in] - Ethernet port id. + * @param *macAddr @ref IxEthAccMacAddr [out] - Ethernet MAC address. + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_MAC_UNINITIALIZED : port MAC address is not initialized. + * @li @a IX_ETH_ACC_FAIL : macAddr is invalid. + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccPortUnicastMacAddressGet(IxEthAccPortId portId, + IxEthAccMacAddr *macAddr); + + + + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortMulticastAddressJoin( IxEthAccPortId portId, + IxEthAccMacAddr *macAddr) + * + * @brief Add a multicast address to the MAC address table. + * + * @note + * Due to the operation of the Ethernet MAC multicast filtering mechanism, frames which do not + * have a multicast destination address which were provisioned via this API may be forwarded + * to the NPE's. This is a result of the hardware comparison algorithm used in the destination mac address logic + * within the Ethernet MAC. + * + * See Also: IXP425 hardware development manual. + * + * Other functions modify the MAC filtering + * + * @li @a ixEthAccPortMulticastAddressJoinAll() - all multicast + * frames are forwarded to the application + * @li @a ixEthAccPortMulticastAddressLeaveAll() - rollback the + * effects of @a ixEthAccPortMulticastAddressJoinAll() + * @li @a ixEthAccPortMulticastAddressLeave() - unprovision a new + * filtering address + * @li @a ixEthAccPortMulticastAddressJoin() - provision a new + * filtering address + * @li @a ixEthAccPortPromiscuousModeSet() - all frames are + * forwarded to the application regardless of the multicast + * address provisioned + * @li @a ixEthAccPortPromiscuousModeClear() - frames are forwarded + * to the application following the multicast address provisioned + * + * In all cases, unicast and broadcast addresses are forwarded to + * the application. + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @param portId @ref IxEthAccPortId [in] - Ethernet port id. + * @param *macAddr @ref IxEthAccMacAddr [in] - Ethernet Mac address. + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_FAIL : Error writing to the MAC registers + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is un-initialized + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccPortMulticastAddressJoin(IxEthAccPortId portId, + IxEthAccMacAddr *macAddr); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortMulticastAddressJoinAll( IxEthAccPortId portId) + * + * @brief Filter all frames with multicast dest. + * + * This function clears the MAC address table, and then sets + * the MAC to forward ALL multicast frames to the NPE. + * Specifically, it forwards all frames whose destination address + * has the LSB of the highest byte set (01:00:00:00:00:00). This + * bit is commonly referred to as the "multicast bit". + * Broadcast frames will still be forwarded. + * + * Other functions modify the MAC filtering + * + * @li @a ixEthAccPortMulticastAddressJoinAll() - all multicast + * frames are forwarded to the application + * @li @a ixEthAccPortMulticastAddressLeaveAll() - rollback the + * effects of @a ixEthAccPortMulticastAddressJoinAll() + * @li @a ixEthAccPortMulticastAddressLeave() - unprovision a new + * filtering address + * @li @a ixEthAccPortMulticastAddressJoin() - provision a new + * filtering address + * @li @a ixEthAccPortPromiscuousModeSet() - all frames are + * forwarded to the application regardless of the multicast + * address provisioned + * @li @a ixEthAccPortPromiscuousModeClear() - frames are forwarded + * to the application following the multicast address provisioned + * + * In all cases, unicast and broadcast addresses are forwarded to + * the application. + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @param portId @ref IxEthAccPortId [in] - Ethernet port id. + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is un-initialized + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccPortMulticastAddressJoinAll(IxEthAccPortId portId); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortMulticastAddressLeave( IxEthAccPortId portId, + IxEthAccMacAddr *macAddr) + * + * @brief Remove a multicast address from the MAC address table. + * + * Other functions modify the MAC filtering + * + * @li @a ixEthAccPortMulticastAddressJoinAll() - all multicast + * frames are forwarded to the application + * @li @a ixEthAccPortMulticastAddressLeaveAll() - rollback the + * effects of @a ixEthAccPortMulticastAddressJoinAll() + * @li @a ixEthAccPortMulticastAddressLeave() - unprovision a new + * filtering address + * @li @a ixEthAccPortMulticastAddressJoin() - provision a new + * filtering address + * @li @a ixEthAccPortPromiscuousModeSet() - all frames are + * forwarded to the application regardless of the multicast + * address provisioned + * @li @a ixEthAccPortPromiscuousModeClear() - frames are forwarded + * to the application following the multicast address provisioned + * + * In all cases, unicast and broadcast addresses are forwarded to + * the application. + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @param portId @ref IxEthAccPortId [in] - Ethernet port id. + * @param *macAddr @ref IxEthAccMacAddr [in] - Ethernet Mac address. + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_NO_SUCH_ADDR : Failed if MAC address was not in the table. + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is un-initialized + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccPortMulticastAddressLeave(IxEthAccPortId portId, + IxEthAccMacAddr *macAddr); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortMulticastAddressLeaveAll( IxEthAccPortId portId) + * + * @brief This function unconfigures the multicast filtering settings + * + * This function first clears the MAC address table, and then sets + * the MAC as configured by the promiscuous mode current settings. + * + * Other functions modify the MAC filtering + * + * @li @a ixEthAccPortMulticastAddressJoinAll() - all multicast + * frames are forwarded to the application + * @li @a ixEthAccPortMulticastAddressLeaveAll() - rollback the + * effects of @a ixEthAccPortMulticastAddressJoinAll() + * @li @a ixEthAccPortMulticastAddressLeave() - unprovision a new + * filtering address + * @li @a ixEthAccPortMulticastAddressJoin() - provision a new + * filtering address + * @li @a ixEthAccPortPromiscuousModeSet() - all frames are + * forwarded to the application regardless of the multicast + * address provisioned + * @li @a ixEthAccPortPromiscuousModeClear() - frames are forwarded + * to the application following the multicast address provisioned + * + * In all cases, unicast and broadcast addresses are forwarded to + * the application. + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @param portId @ref IxEthAccPortId [in] - Ethernet port id. + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is un-initialized + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccPortMulticastAddressLeaveAll(IxEthAccPortId portId); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortUnicastAddressShow(IxEthAccPortId portId) + * + * @brief Displays unicast MAC address + * + * Displays unicast address which is configured using + * @a ixEthAccUnicastMacAddressSet. This function also displays the MAC filter used + * to filter multicast frames. + * + * Other functions modify the MAC filtering + * + * @li @a ixEthAccPortMulticastAddressJoinAll() - all multicast + * frames are forwarded to the application + * @li @a ixEthAccPortMulticastAddressLeaveAll() - rollback the + * effects of @a ixEthAccPortMulticastAddressJoinAll() + * @li @a ixEthAccPortMulticastAddressLeave() - unprovision a new + * filtering address + * @li @a ixEthAccPortMulticastAddressJoin() - provision a new + * filtering address + * @li @a ixEthAccPortPromiscuousModeSet() - all frames are + * forwarded to the application regardless of the multicast + * address provisioned + * @li @a ixEthAccPortPromiscuousModeClear() - frames are forwarded + * to the application following the multicast address provisioned + * + * In all cases, unicast and broadcast addresses are forwarded to + * the application. + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @param portId @ref IxEthAccPortId [in] - Ethernet port id. + * + * @return void + * + *
+ */ +PUBLIC IxEthAccStatus ixEthAccPortUnicastAddressShow(IxEthAccPortId portId); + + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortMulticastAddressShow( IxEthAccPortId portId) + * + * @brief Displays multicast MAC address + * + * Displays multicast address which have been configured using @a ixEthAccMulticastAddressJoin + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @param portId @ref IxEthAccPortId [in] - Ethernet port id. + * + * @return void + * + *
+ */ +PUBLIC void ixEthAccPortMulticastAddressShow( IxEthAccPortId portId); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortDuplexModeSet( IxEthAccPortId portId, IxEthAccDuplexMode mode ) + * + * @brief Set the duplex mode for the MAC. + * + * Configure the IXP400 MAC to either full or half duplex. + * + * @note + * The configuration should match that provisioned on the PHY. + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @param portId @ref IxEthAccPortId [in] + * @param mode @ref IxEthAccDuplexMode [in] + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is un-initialized + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccPortDuplexModeSet(IxEthAccPortId portId,IxEthAccDuplexMode mode); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortDuplexModeGet( IxEthAccPortId portId, IxEthAccDuplexMode *mode ) + * + * @brief Get the duplex mode for the MAC. + * + * return the duplex configuration of the IXP400 MAC. + * + * @note + * The configuration should match that provisioned on the PHY. + * See @a ixEthAccDuplexModeSet + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @param portId @ref IxEthAccPortId [in] + * @param *mode @ref IxEthAccDuplexMode [out] + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is un-initialized + * + *
+ * + */ +PUBLIC IxEthAccStatus +ixEthAccPortDuplexModeGet(IxEthAccPortId portId,IxEthAccDuplexMode *mode ); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortTxFrameAppendPaddingEnable( IxEthAccPortId portId) + * + * @brief Enable padding bytes to be appended to runt frames submitted to + * this port + * + * Enable up to 60 null-bytes padding bytes to be appended to runt frames + * submitted to this port. This is the default behavior of the access + * component. + * + * @warning Do not change this behaviour while the port is enabled. + * + * @note When Tx padding is enabled, Tx FCS generation is turned on + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @sa ixEthAccPortTxFrameAppendFCSDusable + * + * @param portId @ref IxEthAccPortId [in] + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is un-initialized + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccPortTxFrameAppendPaddingEnable(IxEthAccPortId portId); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortTxFrameAppendPaddingDisable( IxEthAccPortId portId) + * + * @brief Disable padding bytes to be appended to runt frames submitted to + * this port + * + * Disable padding bytes to be appended to runt frames + * submitted to this port. This is not the default behavior of the access + * component. + * + * @warning Do not change this behaviour while the port is enabled. + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @param portId @ref IxEthAccPortId [in] + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is un-initialized + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccPortTxFrameAppendPaddingDisable(IxEthAccPortId portId); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortTxFrameAppendFCSEnable( IxEthAccPortId portId) + * + * @brief Enable the appending of Ethernet FCS to all frames submitted to this port + * + * When enabled, the FCS is added to the submitted frames. This is the default + * behavior of the access component. + * Do not change this behaviour while the port is enabled. + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @param portId @ref IxEthAccPortId [in] + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is un-initialized + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccPortTxFrameAppendFCSEnable(IxEthAccPortId portId); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortTxFrameAppendFCSDisable( IxEthAccPortId portId) + * + * @brief Disable the appending of Ethernet FCS to all frames submitted to this port. + * + * When disabled, the Ethernet FCS is not added to the submitted frames. + * This is not the default + * behavior of the access component. + * + * @note Since the FCS is not appended to the frame it is expected that the frame submitted to the + * component includes a valid FCS at the end of the data, although this will not be validated. + * + * The component shall forward the frame to the Ethernet MAC WITHOUT modification. + * + * Do not change this behaviour while the port is enabled. + * + * @note Tx FCS append is not disabled while Tx padding is enabled. + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @sa ixEthAccPortTxFrameAppendPaddingEnable + * + * @param portId @ref IxEthAccPortId [in] + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is un-initialized + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccPortTxFrameAppendFCSDisable(IxEthAccPortId portId); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortRxFrameAppendFCSEnable( IxEthAccPortId portId) + * + * @brief Forward frames with FCS included in the receive buffer. + * + * The FCS is not striped from the receive buffer. + * The received frame length includes the FCS size (4 bytes). ie. + * A minimum sized ethernet frame shall have a length of 64bytes. + * + * Frame FCS validity checks are still carried out on all received frames. + * + * This is not the default + * behavior of the access component. + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @param portId @ref IxEthAccPortId [in] + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is un-initialized + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccPortRxFrameAppendFCSEnable(IxEthAccPortId portId); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccPortRxFrameAppendFCSDisable( IxEthAccPortId portId) + * + * @brief Do not forward the FCS portion of the received Ethernet frame to the user. + * The FCS is striped from the receive buffer. + * The received frame length does not include the FCS size (4 bytes). + * Frame FCS validity checks are still carried out on all received frames. + * + * This is the default behavior of the component. + * Do not change this behaviour while the port is enabled. + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @param portId @ref IxEthAccPortId [in] + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is un-initialized + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccPortRxFrameAppendFCSDisable(IxEthAccPortId portId); + + + + +/** + * @ingroup IxEthAcc + * + * @enum IxEthAccSchedulerDiscipline + * + * @brief Definition for the port scheduling discipline + * + * Select the port scheduling discipline on receive and transmit path + * @li FIFO : No Priority : In this configuration all frames are processed + * in the access component in the strict order in which + * the component received them. + * @li FIFO : Priority : This shall be a very simple priority mechanism. + * Higher prior-ity frames shall be forwarded + * before lower priority frames. There shall be no + * fairness mechanisms applied across different + * priorities. Higher priority frames could starve + * lower priority frames indefinitely. + */ +typedef enum +{ + FIFO_NO_PRIORITY, /** + */ +PUBLIC IxEthAccStatus +ixEthAccTxSchedulingDisciplineSet(IxEthAccPortId portId, + IxEthAccSchedulerDiscipline sched); + + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccRxSchedulingDisciplineSet(IxEthAccSchedulerDiscipline sched) + * + * @brief Set the Rx scheduling to one of @a IxEthAccSchedulerDiscipline + * + * The default behavior of the component is @a FIFO_NO_PRIORITY. + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @pre + * + * @param sched : @a IxEthAccSchedulerDiscipline + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS : Set appropriate discipline. + * @li @a IX_ETH_ACC_FAIL : Invalid/unsupported discipline. + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccRxSchedulingDisciplineSet(IxEthAccSchedulerDiscipline sched); + +/** + * @ingroup IxEthAcc + * + * @fn IxEthAccStatus ixEthAccNpeLoopbackEnable(IxEthAccPortId portId) + * + * @brief Enable NPE loopback + * + * When this loopback mode is enabled all the transmitted frames are + * received on the same port, without payload. + * + * This function is recommended for power-up diagnostic checks and + * should never be used under normal Ethernet traffic operations. + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @pre + * + * @param portId : ID of the port + * + * @note Calling ixEthAccPortDisable followed by ixEthAccPortEnable is + * guaranteed to restore correct Ethernet Tx/Rx operation. + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS : NPE loopback mode enabled + * @li @a IX_ETH_ACC_FAIL : Invalid port or Ethernet service not initialized + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccPortNpeLoopbackEnable(IxEthAccPortId portId); + +/** + * @ingroup IxEthAcc + * + * @fn IxEthAccStatus ixEthAccPortNpeLoopbackDisable(IxEthAccPortId portId) + * + * @brief Disable NPE loopback + * + * This function is used to disable the NPE loopback if previously + * enabled using ixEthAccNpeLoopbackEnable. + * + * This function is recommended for power-up diagnostic checks and + * should never be used under normal Ethernet traffic operations. + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @pre + * + * @note Calling ixEthAccPortDisable followed by ixEthAccPortEnable is + * guaranteed to restore correct Ethernet Tx/Rx operation. + * + * @param portId : ID of the port + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS : NPE loopback successfully disabled + * @li @a IX_ETH_ACC_FAIL : Invalid port or Ethernet service not initialized + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccPortNpeLoopbackDisable(IxEthAccPortId portId); + +/** + * @ingroup IxEthAcc + * + * @fn IxEthAccStatus ixEthAccPortTxEnable(IxEthAccPortId portId) + * + * @brief Enable Tx on the port + * + * This function is the complement of ixEthAccPortTxDisable and should + * be used only after Tx was disabled. A MAC core reset is required before + * this function is called (see @a ixEthAccPortMacReset). + * + * This function is the recommended usage scenario for emergency security + * shutdown and hardware failure recovery and should never be used for throttling + * traffic. + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @pre + * + * @note Calling ixEthAccPortDisable followed by ixEthAccPortEnable is + * guaranteed to restore correct Ethernet Tx/Rx operation. + * + * @param portId : ID of the port + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS : Tx successfully enabled + * @li @a IX_ETH_ACC_FAIL : Invalid port or Ethernet service not initialized + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccPortTxEnable(IxEthAccPortId portId); + +/** + * @ingroup IxEthAcc + * + * @fn IxEthAccStatus ixEthAccPortTxDisable(IxEthAccPortId portId) + * + * @brief Disable Tx on the port + * + * This function can be used to disable Tx in the MAC core. + * Tx can be re-enabled, although this is not guaranteed, by performing + * a MAC core reset (@a ixEthAccPortMacReset) and calling ixEthAccPortTxEnable. + * Note that using this function is not recommended, except for shutting + * down Tx for emergency reasons. For proper port shutdown and re-enabling + * see ixEthAccPortEnable and ixEthAccPortDisable. + * + * This function is the recommended usage scenario for emergency security + * shutdown and hardware failure recovery and should never be used for throttling + * traffic. + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @note Calling ixEthAccPortDisable followed by ixEthAccPortEnable is + * guaranteed to restore correct Ethernet Tx/Rx operation. + * + * @pre + * + * @param portId : ID of the port + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS : Tx successfully disabled + * @li @a IX_ETH_ACC_FAIL : Invalid port or Ethernet service not initialized + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccPortTxDisable(IxEthAccPortId portId); + +/** + * @ingroup IxEthAcc + * + * @fn IxEthAccStatus ixEthAccPortRxEnable(IxEthAccPortId portId) + * + * @brief Enable Rx on the port + * + * This function is the complement of ixEthAccPortRxDisable and should + * be used only after Rx was disabled. + * + * This function is the recommended usage scenario for emergency security + * shutdown and hardware failure recovery and should never be used for throttling + * traffic. + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @note Calling ixEthAccPortDisable followed by ixEthAccPortEnable is + * guaranteed to restore correct Ethernet Tx/Rx operation. + * + * @pre + * + * @param portId : ID of the port + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS : Rx successfully enabled + * @li @a IX_ETH_ACC_FAIL : Invalid port or Ethernet service not initialized + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccPortRxEnable(IxEthAccPortId portId); + +/** + * @ingroup IxEthAcc + * + * @fn IxEthAccStatus ixEthAccPortRxDisable(IxEthAccPortId portId) + * + * @brief Disable Rx on the port + * + * This function can be used to disable Rx in the MAC core. + * Rx can be re-enabled, although this is not guaranteed, by performing + * a MAC core reset (@a ixEthAccPortMacReset) and calling ixEthAccPortRxEnable. + * Note that using this function is not recommended, except for shutting + * down Rx for emergency reasons. For proper port shutdown and re-enabling + * see ixEthAccPortEnable and ixEthAccPortDisable. + * + * This function is the recommended usage scenario for emergency security + * shutdown and hardware failure recovery and should never be used for throttling + * traffic. + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @pre + * + * @note Calling ixEthAccPortDisable followed by ixEthAccPortEnable is + * guaranteed to restore correct Ethernet Tx/Rx operation. + * + * @param portId : ID of the port + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS : Rx successfully disabled + * @li @a IX_ETH_ACC_FAIL : Invalid port or Ethernet service not initialized + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccPortRxDisable(IxEthAccPortId portId); + +/** + * @ingroup IxEthAcc + * + * @fn IxEthAccStatus ixEthAccPortMacReset(IxEthAccPortId portId) + * + * @brief Reset MAC core on the port + * + * This function will perform a MAC core reset (NPE Ethernet coprocessor). + * This function is inherently unsafe and the NPE recovery is not guaranteed + * after this function is called. The proper manner of performing port disable + * and enable (which will reset the MAC as well) is ixEthAccPortEnable/ixEthAccPortDisable. + * + * This function is the recommended usage scenario for hardware failure recovery + * and should never be used for throttling traffic. + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @pre + * + * @note Calling ixEthAccPortDisable followed by ixEthAccPortEnable is + * guaranteed to restore correct Ethernet Tx/Rx operation. + * + * @param portId : ID of the port + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS : MAC core reset + * @li @a IX_ETH_ACC_FAIL : Invalid port or Ethernet service not initialized + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccPortMacReset(IxEthAccPortId portId); + +/********************************************************************************* + #### ##### ## ##### # #### ##### # #### #### + # # # # # # # # # # # # + #### # # # # # #### # # # #### + # # ###### # # # # # # # + # # # # # # # # # # # # # # # + #### # # # # # #### # # #### #### +**********************************************************************************/ + + +/** + * + * @brief This struct defines the statistics returned by this component. + * + * The component returns MIB2 EthObj variables which are obtained from the + * hardware or maintained by this component. + * + * + */ +typedef struct +{ + UINT32 dot3StatsAlignmentErrors; /**< link error count (rx) */ + UINT32 dot3StatsFCSErrors; /**< link error count (rx) */ + UINT32 dot3StatsInternalMacReceiveErrors; /**< link error count (rx) */ + UINT32 RxOverrunDiscards; /**< NPE: discarded frames count (rx) */ + UINT32 RxLearnedEntryDiscards; /**< NPE: discarded frames count(rx) */ + UINT32 RxLargeFramesDiscards; /**< NPE: discarded frames count(rx) */ + UINT32 RxSTPBlockedDiscards; /**< NPE: discarded frames count(rx) */ + UINT32 RxVLANTypeFilterDiscards; /**< NPE: discarded frames count (rx) */ + UINT32 RxVLANIdFilterDiscards; /**< NPE: discarded frames count (rx) */ + UINT32 RxInvalidSourceDiscards; /**< NPE: discarded frames count (rx) */ + UINT32 RxBlackListDiscards; /**< NPE: discarded frames count (rx) */ + UINT32 RxWhiteListDiscards; /**< NPE: discarded frames count (rx) */ + UINT32 RxUnderflowEntryDiscards; /**< NPE: discarded frames count (rx) */ + UINT32 dot3StatsSingleCollisionFrames; /**< link error count (tx) */ + UINT32 dot3StatsMultipleCollisionFrames; /**< link error count (tx) */ + UINT32 dot3StatsDeferredTransmissions; /**< link error count (tx) */ + UINT32 dot3StatsLateCollisions; /**< link error count (tx) */ + UINT32 dot3StatsExcessiveCollsions; /**< link error count (tx) */ + UINT32 dot3StatsInternalMacTransmitErrors; /**< link error count (tx) */ + UINT32 dot3StatsCarrierSenseErrors; /**< link error count (tx) */ + UINT32 TxLargeFrameDiscards; /**< NPE: discarded frames count (tx) */ + UINT32 TxVLANIdFilterDiscards; /**< NPE: discarded frames count (tx) */ + +}IxEthEthObjStats; + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccMibIIStatsGet(IxEthAccPortId portId ,IxEthEthObjStats *retStats ) + * + * @brief Returns the statistics maintained for a port. + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @pre + * + * + * @param portId @ref IxEthAccPortId [in] + * @param retStats @ref IxEthEthObjStats [out] + * @note Please note the user is responsible for cache coheriency of the retStat + * buffer. The data is actually populated via the NPE's. As such cache safe + * memory should be used in the retStats argument. + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_FAIL : Invalid arguments. + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is un-initialized + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccMibIIStatsGet(IxEthAccPortId portId, IxEthEthObjStats *retStats ); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccMibIIStatsGetClear(IxEthAccPortId portId, IxEthEthObjStats *retStats) + * + * @brief Returns and clears the statistics maintained for a port. + * + * @li Reentrant - yes + * @li ISR Callable - yes + * + * @pre + * + * @param portId @ref IxEthAccPortId [in] + * @param retStats @ref IxEthEthObjStats [out] + * @note Please note the user is responsible for cache coheriency of the retStats + * buffer. The data is actually populated via the NPE's. As such cache safe + * memory should be used in the retStats argument. + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_FAIL : invalid arguments. + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is un-initialized + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccMibIIStatsGetClear(IxEthAccPortId portId, IxEthEthObjStats *retStats); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccMibIIStatsClear(IxEthAccPortId portId) + * + * @brief Clears the statistics maintained for a port. + * + * @li Reentrant - yes + * @li ISR Callable - no + * + * @pre + * + * @param portId @ref IxEthAccPortId [in] + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_FAIL : Invalid arguments. + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * @li @a IX_ETH_ACC_PORT_UNINITIALIZED : portId is un-initialized + * + *
+ */ +PUBLIC IxEthAccStatus ixEthAccMibIIStatsClear(IxEthAccPortId portId); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccMacInit(IxEthAccPortId portId) + * + * @brief Initializes the ethernet MAC settings + * + * @li Reentrant - no + * @li ISR Callable - no + * + * @param portId @ref IxEthAccPortId [in] + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_INVALID_PORT : portId is invalid. + * + *
+ */ +PUBLIC IxEthAccStatus ixEthAccMacInit(IxEthAccPortId portId); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccStatsShow(IxEthAccPortId portId) + * + * + * @brief Displays a ports statistics on the standard io console using printf. + * + * @li Reentrant - no + * @li ISR Callable - no + * + * @pre + * + * @param portId @ref IxEthAccPortId [in] + * + * @return void + * + *
+ */ +PUBLIC void ixEthAccStatsShow(IxEthAccPortId portId); + +/************************************************************************* + + # # # # # # ##### # #### + ## ## # # ## ## # # # # # + # ## # # # # ## # # # # # # + # # # # # # # # # # # + # # # # # # # # # # # + # # # # # # ##### # #### + +*************************************************************************/ + + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccMiiReadRtn (UINT8 phyAddr, + UINT8 phyReg, + UINT16 *value) + * + * + * @brief Reads a 16 bit value from a PHY + * + * Reads a 16-bit word from a register of a MII-compliant PHY. Reading + * is performed through the MII management interface. This function returns + * when the read operation has successfully completed, or when a timeout has elapsed. + * + * @li Reentrant - no + * @li ISR Callable - no + * + * @pre The MAC on Ethernet Port 2 (NPE C) must be initialised, and generating the MDIO clock. + * + * @param phyAddr UINT8 [in] - the address of the Ethernet PHY (0-31) + * @param phyReg UINT8 [in] - the number of the MII register to read (0-31) + * @param value UINT16 [in] - the value read from the register + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_FAIL : failed to read the register. + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccMiiReadRtn (UINT8 phyAddr, UINT8 phyReg, UINT16 *value); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccMiiWriteRtn (UINT8 phyAddr, + UINT8 phyReg, + UINT16 value) + * + * + * @brief Writes a 16 bit value to a PHY + * + * Writes a 16-bit word from a register of a MII-compliant PHY. Writing + * is performed through the MII management interface. This function returns + * when the write operation has successfully completed, or when a timeout has elapsed. + * + * @li Reentrant - no + * @li ISR Callable - no + * + * @pre The MAC on Ethernet Port 2 (NPE C) must be initialised, and generating the MDIO clock. + * + * @param phyAddr UINT8 [in] - the address of the Ethernet PHY (0-31) + * @param phyReg UINT8 [in] - the number of the MII register to write (0-31) + * @param value UINT16 [out] - the value to write to the register + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_FAIL : failed to write register. + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccMiiWriteRtn (UINT8 phyAddr, UINT8 phyReg, UINT16 value); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccMiiAccessTimeoutSet(UINT32 timeout) + * + * @brief Overrides the default timeout value and retry count when reading or + * writing MII registers using ixEthAccMiiWriteRtn or ixEthAccMiiReadRtn + * + * The default behavior of the component is to use a IX_ETH_ACC_MII_10TH_SEC_IN_MILLIS ms + * timeout (declared as 100 in IxEthAccMii_p.h) and a retry count of IX_ETH_ACC_MII_TIMEOUT_10TH_SECS + * (declared as 5 in IxEthAccMii_p.h). + * + * The MII read and write functions will attempt to read the status of the register up + * to the retry count times, delaying between each attempt with the timeout value. + * + * @li Reentrant - no + * @li ISR Callable - no + * + * @pre + * + * @param timeout UINT32 [in] - new timeout value, in milliseconds + * @param timeout UINT32 [in] - new retry count (a minimum value of 1 must be used) + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_FAIL : invalid parameter(s) + * + *
+ */ +PUBLIC IxEthAccStatus +ixEthAccMiiAccessTimeoutSet(UINT32 timeout, UINT32 retryCount); + +/** + * @ingroup IxEthAcc + * + * @fn ixEthAccMiiStatsShow (UINT32 phyAddr) + * + * + * @brief Displays detailed information on a specified PHY + * + * Displays the current values of the first eigth MII registers for a PHY, + * + * @li Reentrant - no + * @li ISR Callable - no + * + * @pre The MAC on Ethernet Port 2 (NPE C) must be initialised, and + * generating the MDIO clock. + * + * @param phyAddr UINT32 [in] - the address of the Ethernet PHY (0-31) + * + * @return IxEthAccStatus + * @li @a IX_ETH_ACC_SUCCESS + * @li @a IX_ETH_ACC_FAIL : invalid arguments. + * + *
+ */ +PUBLIC IxEthAccStatus ixEthAccMiiStatsShow (UINT32 phyAddr); + + + +/******* BOARD SPECIFIC DEPRECATED API *********/ + +/* The following functions are high level functions which rely + * on the properties and interface of some Ethernet PHYs. The + * implementation is hardware specific and has been moved to + * the hardware-specific component IxEthMii. + */ + + #include "IxEthMii.h" + +/** + * @ingroup IxEthAcc + * + * @def ixEthAccMiiPhyScan + * + * @brief : deprecated API entry point. This definition + * ensures backward compatibility + * + * See @ref ixEthMiiPhyScan + * + * @note this feature is board specific + * + */ +#define ixEthAccMiiPhyScan(phyPresent) ixEthMiiPhyScan(phyPresent,IXP425_ETH_ACC_MII_MAX_ADDR) + +/** + * @ingroup IxEthAcc + * + * @def ixEthAccMiiPhyConfig + * + * @brief : deprecated API entry point. This definition + * ensures backward compatibility + * + * See @ref ixEthMiiPhyConfig + * + * @note this feature is board specific + */ +#define ixEthAccMiiPhyConfig(phyAddr,speed100,fullDuplex,autonegotiate) \ + ixEthMiiPhyConfig(phyAddr,speed100,fullDuplex,autonegotiate) + +/** + * @ingroup IxEthAcc + * + * @def ixEthAccMiiPhyReset + * + * @brief : deprecated API entry point. This definition + * ensures backward compatibility + * + * See @ref ixEthMiiPhyReset + * + * @note this feature is board specific + */ +#define ixEthAccMiiPhyReset(phyAddr) \ + ixEthMiiPhyReset(phyAddr) + +/** + * @ingroup IxEthAcc + * + * @def ixEthAccMiiLinkStatus + * + * @brief : deprecated API entry point. This definition + * ensures backward compatibility + * + * See @ref ixEthMiiLinkStatus + * + * @note this feature is board specific + */ +#define ixEthAccMiiLinkStatus(phyAddr,linkUp,speed100,fullDuplex,autoneg) \ + ixEthMiiLinkStatus(phyAddr,linkUp,speed100,fullDuplex,autoneg) + + + +/** + * @ingroup IxEthAcc + * + * @def ixEthAccMiiShow + * + * @brief : deprecated API entry point. This definition + * ensures backward compatibility + * + * See @ref ixEthMiiPhyShow + * + * @note this feature is board specific + */ +#define ixEthAccMiiShow(phyAddr) \ + ixEthMiiPhyShow(phyAddr) + +#endif /* ndef IxEthAcc_H */ +/** + *@} + */ diff --git a/cpu/ixp/npe/include/IxEthAccDataPlane_p.h b/cpu/ixp/npe/include/IxEthAccDataPlane_p.h new file mode 100644 index 0000000..8b8e6b2 --- /dev/null +++ b/cpu/ixp/npe/include/IxEthAccDataPlane_p.h @@ -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 +#include + +/** + * @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 */ + + +/** + *@} + */ + diff --git a/cpu/ixp/npe/include/IxEthAccMac_p.h b/cpu/ixp/npe/include/IxEthAccMac_p.h new file mode 100644 index 0000000..93e9d98 --- /dev/null +++ b/cpu/ixp/npe/include/IxEthAccMac_p.h @@ -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*/ + diff --git a/cpu/ixp/npe/include/IxEthAccMii_p.h b/cpu/ixp/npe/include/IxEthAccMii_p.h new file mode 100644 index 0000000..aa42f9c --- /dev/null +++ b/cpu/ixp/npe/include/IxEthAccMii_p.h @@ -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*/ diff --git a/cpu/ixp/npe/include/IxEthAccQueueAssign_p.h b/cpu/ixp/npe/include/IxEthAccQueueAssign_p.h new file mode 100644 index 0000000..e5fd16e --- /dev/null +++ b/cpu/ixp/npe/include/IxEthAccQueueAssign_p.h @@ -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 ) diff --git a/cpu/ixp/npe/include/IxEthAcc_p.h b/cpu/ixp/npe/include/IxEthAcc_p.h new file mode 100644 index 0000000..37c5560 --- /dev/null +++ b/cpu/ixp/npe/include/IxEthAcc_p.h @@ -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 */ + + + diff --git a/cpu/ixp/npe/include/IxEthDB.h b/cpu/ixp/npe/include/IxEthDB.h new file mode 100644 index 0000000..43ee802 --- /dev/null +++ b/cpu/ixp/npe/include/IxEthDB.h @@ -0,0 +1,2373 @@ +/** @file IxEthDB.h + * + * @brief this file contains the public API of @ref IxEthDB 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 -- + * + */ + +#ifndef IxEthDB_H +#define IxEthDB_H + +#include +#include + +/** + * @defgroup IxEthDB IXP400 Ethernet Database (IxEthDB) API + * + * @brief ethDB is a library that does provides a MAC address database learning/filtering capability + * + *@{ + */ + +#define INLINE __inline__ + +#define IX_ETH_DB_PRIVATE PRIVATE /* imported from IxTypes.h */ + +#define IX_ETH_DB_PUBLIC PUBLIC + +/** + * @brief port ID => message handler NPE id conversion (0 => NPE_B, 1 => NPE_C) + */ +#define IX_ETH_DB_PORT_ID_TO_NPE(id) (id == 0 ? 1 : (id == 1 ? 2 : (id == 2 ? 0 : -1))) + +/** + * @def IX_ETH_DB_NPE_TO_PORT_ID(npe) + * @brief message handler NPE id => port ID conversion (NPE_B => 0, NPE_C => 1) + */ +#define IX_ETH_DB_NPE_TO_PORT_ID(npe) (npe == 0 ? 2 : (npe == 1 ? 0 : (npe == 2 ? 1 : -1))) + +/* temporary define - won't work for Azusa */ +#define IX_ETH_DB_PORT_ID_TO_NPE_LOGICAL_ID(id) (IX_ETH_DB_PORT_ID_TO_NPE(id) << 4) +#define IX_ETH_DB_NPE_LOGICAL_ID_TO_PORT_ID(id) (IX_ETH_DB_NPE_TO_PORT_ID(id >> 4)) + +/** + * @def IX_IEEE803_MAC_ADDRESS_SIZE + * @brief The size of the MAC address + */ +#define IX_IEEE803_MAC_ADDRESS_SIZE (6) + +/** + * @def IX_IEEE802_1Q_QOS_PRIORITY_COUNT + * @brief Number of QoS priorities defined by IEEE802.1Q + */ +#define IX_IEEE802_1Q_QOS_PRIORITY_COUNT (8) + +/** + * @enum IxEthDBStatus + * @brief Ethernet Database API return values + */ +typedef enum /* IxEthDBStatus */ +{ + IX_ETH_DB_SUCCESS = IX_SUCCESS, /**< Success */ + IX_ETH_DB_FAIL = IX_FAIL, /**< Failure */ + IX_ETH_DB_INVALID_PORT, /**< Invalid port */ + IX_ETH_DB_PORT_UNINITIALIZED, /**< Port not initialized */ + IX_ETH_DB_MAC_UNINITIALIZED, /**< MAC not initialized */ + IX_ETH_DB_INVALID_ARG, /**< Invalid argument */ + IX_ETH_DB_NO_SUCH_ADDR, /**< Address not found for search or delete operations */ + IX_ETH_DB_NOMEM, /**< Learning database memory full */ + IX_ETH_DB_BUSY, /**< Learning database cannot complete operation, access temporarily blocked */ + IX_ETH_DB_END, /**< Database browser passed the end of the record set */ + IX_ETH_DB_INVALID_VLAN, /**< Invalid VLAN ID (valid range is 0..4094, 0 signifies no VLAN membership, used for priority tagged frames) */ + IX_ETH_DB_INVALID_PRIORITY, /**< Invalid QoS priority/traffic class (valid range for QoS priority is 0..7, valid range for traffic class depends on run-time configuration) */ + IX_ETH_DB_NO_PERMISSION, /**< No permission for attempted operation */ + IX_ETH_DB_FEATURE_UNAVAILABLE, /**< Feature not available (or not enabled) */ + IX_ETH_DB_INVALID_KEY, /**< Invalid search key */ + IX_ETH_DB_INVALID_RECORD_TYPE /**< Invalid record type */ +} IxEthDBStatus; + +/** @brief VLAN ID type, valid range is 0..4094, 0 signifying no VLAN membership */ +typedef UINT32 IxEthDBVlanId; + +/** @brief 802.1Q VLAN tag, contains 3 bits user priority, 1 bit CFI, 12 bits VLAN ID */ +typedef UINT32 IxEthDBVlanTag; + +/** @brief QoS priority/traffic class type, valid range is 0..7, 0 being the lowest */ +typedef UINT32 IxEthDBPriority; + +/** @brief Priority mapping table; 0..7 QoS priorities used to index, table contains traffic classes */ +typedef UINT8 IxEthDBPriorityTable[8]; + +/** @brief A 4096 bit array used to map the complete VLAN ID range */ +typedef UINT8 IxEthDBVlanSet[512]; + +#define IX_ETH_DB_802_1Q_VLAN_MASK (0xFFF) +#define IX_ETH_DB_802_1Q_QOS_MASK (0x7) + +#define IX_ETH_DB_802_1Q_MAX_VLAN_ID (0xFFE) + +/** + * @def IX_ETH_DB_SET_VLAN_ID + * @brief returns the given 802.1Q tag with the VLAN ID field substituted with the given VLAN ID + * + * This macro is used to change the VLAN ID in a 802.1Q tag. + * + * Example: + * + * tag = IX_ETH_DB_SET_VLAN_ID(tag, 32) + * + * inserts the VLAN ID "32" in the given tag. + */ +#define IX_ETH_DB_SET_VLAN_ID(vlanTag, vlanID) (((vlanTag) & 0xF000) | ((vlanID) & IX_ETH_DB_802_1Q_VLAN_MASK)) + +/** +* @def IX_ETH_DB_GET_VLAN_ID +* @brief returns the VLAN ID from the given 802.1Q tag +*/ +#define IX_ETH_DB_GET_VLAN_ID(vlanTag) ((vlanTag) & IX_ETH_DB_802_1Q_VLAN_MASK) + +#define IX_ETH_DB_GET_QOS_PRIORITY(vlanTag) (((vlanTag) >> 13) & IX_ETH_DB_802_1Q_QOS_MASK) + +#define IX_ETH_DB_SET_QOS_PRIORITY(vlanTag, priority) (((vlanTag) & 0x1FFF) | (((priority) & IX_ETH_DB_802_1Q_QOS_MASK) << 13)) + +#define IX_ETH_DB_CHECK_VLAN_TAG(vlanTag) { if(((vlanTag & 0xFFFF0000) != 0) || (IX_ETH_DB_GET_VLAN_ID(vlanTag) > 4094)) return IX_ETH_DB_INVALID_VLAN; } + +#define IX_ETH_DB_CHECK_VLAN_ID(vlanId) { if (vlanId > IX_ETH_DB_802_1Q_MAX_VLAN_ID) return IX_ETH_DB_INVALID_VLAN; } + +#define IX_IEEE802_1Q_VLAN_TPID (0x8100) + +typedef enum +{ + IX_ETH_DB_UNTAGGED_FRAMES = 0x1, /**< Accepts untagged frames */ + IX_ETH_DB_VLAN_TAGGED_FRAMES = 0x2, /**< Accepts tagged frames */ + IX_ETH_DB_PRIORITY_TAGGED_FRAMES = 0x4, /**< Accepts tagged frames with VLAN ID set to 0 (no VLAN membership) */ + IX_ETH_DB_ACCEPT_ALL_FRAMES = + IX_ETH_DB_UNTAGGED_FRAMES | IX_ETH_DB_VLAN_TAGGED_FRAMES /**< Accepts all the frames */ +} IxEthDBFrameFilter; + +typedef enum +{ + IX_ETH_DB_PASS_THROUGH = 0x1, /**< Leave frame as-is */ + IX_ETH_DB_ADD_TAG = 0x2, /**< Add default port VLAN tag */ + IX_ETH_DB_REMOVE_TAG = 0x3 /**< Remove VLAN tag from frame */ +} IxEthDBTaggingAction; + +typedef enum +{ + IX_ETH_DB_FIREWALL_WHITE_LIST = 0x1, /**< Firewall operates in white-list mode (MAC address based admission) */ + IX_ETH_DB_FIREWALL_BLACK_LIST = 0x2 /**< Firewall operates in black-list mode (MAC address based blocking) */ +} IxEthDBFirewallMode; + +typedef enum +{ + IX_ETH_DB_FILTERING_RECORD = 0x01, /**< + *
Filtering record
MAC address static/dynamic type age + *
+ */ + IX_ETH_DB_FILTERING_VLAN_RECORD = 0x02, /**< + *
VLAN-enabled filtering record
MAC address static/dynamic type age 802.1Q tag + *
+ */ + IX_ETH_DB_WIFI_RECORD = 0x04, /**< + *
WiFi header conversion record
MAC address optional gateway MAC address + *
+ */ + IX_ETH_DB_FIREWALL_RECORD = 0x08, /**< + *
Firewall record
MAC address + *
+ */ + IX_ETH_DB_GATEWAY_RECORD = 0x10, /**< For internal use only */ + IX_ETH_DB_MAX_RECORD_TYPE_INDEX = 0x10, /**< For internal use only */ + IX_ETH_DB_NO_RECORD_TYPE = 0, /**< None of the registered record types */ + IX_ETH_DB_ALL_FILTERING_RECORDS = IX_ETH_DB_FILTERING_RECORD | IX_ETH_DB_FILTERING_VLAN_RECORD, /**< All the filtering records */ + IX_ETH_DB_ALL_RECORD_TYPES = IX_ETH_DB_FILTERING_RECORD | IX_ETH_DB_FILTERING_VLAN_RECORD | + IX_ETH_DB_WIFI_RECORD | IX_ETH_DB_FIREWALL_RECORD /**< All the record types registered within EthDB */ +} IxEthDBRecordType; + +typedef enum +{ + IX_ETH_DB_LEARNING = 0x01, /**< Learning feature; enables EthDB to learn MAC address (filtering) records, including 802.1Q enabled records */ + IX_ETH_DB_FILTERING = 0x02, /**< Filtering feature; enables EthDB to communicate with the NPEs for downloading filtering information in the NPEs; depends on the learning feature */ + IX_ETH_DB_VLAN_QOS = 0x04, /**< VLAN/QoS feature; enables EthDB to configure NPEs to operate in VLAN/QoS aware modes */ + IX_ETH_DB_FIREWALL = 0x08, /**< Firewall feature; enables EthDB to configure NPEs to operate in firewall mode, using white/black address lists */ + IX_ETH_DB_SPANNING_TREE_PROTOCOL = 0x10, /**< Spanning tree protocol feature; enables EthDB to configure the NPEs as STP nodes */ + IX_ETH_DB_WIFI_HEADER_CONVERSION = 0x20 /**< WiFi 802.3 to 802.11 header conversion feature; enables EthDB to handle WiFi conversion data */ +} IxEthDBFeature; + +typedef UINT32 IxEthDBProperty; /**< Property ID type */ + +typedef enum +{ + IX_ETH_DB_INTEGER_PROPERTY = 0x1, /**< 4 byte unsigned integer type */ + IX_ETH_DB_STRING_PROPERTY = 0x2, /**< NULL-terminated string type of maximum 255 characters (including the terminator) */ + IX_ETH_DB_MAC_ADDR_PROPERTY = 0x3, /**< 6 byte MAC address type */ + IX_ETH_DB_BOOL_PROPERTY = 0x4 /**< 4 byte boolean type; can contain only TRUE and FALSE values */ +} IxEthDBPropertyType; + +/* list of supported properties for the IX_ETH_DB_VLAN_QOS feature */ +#define IX_ETH_DB_QOS_TRAFFIC_CLASS_COUNT_PROPERTY (0x01) /**< Property identifying number the supported number of traffic classes */ +#define IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY (0x10) /**< Rx queue assigned to traffic class 0 */ +#define IX_ETH_DB_QOS_TRAFFIC_CLASS_1_RX_QUEUE_PROPERTY (0x11) /**< Rx queue assigned to traffic class 1 */ +#define IX_ETH_DB_QOS_TRAFFIC_CLASS_2_RX_QUEUE_PROPERTY (0x12) /**< Rx queue assigned to traffic class 2 */ +#define IX_ETH_DB_QOS_TRAFFIC_CLASS_3_RX_QUEUE_PROPERTY (0x13) /**< Rx queue assigned to traffic class 3 */ +#define IX_ETH_DB_QOS_TRAFFIC_CLASS_4_RX_QUEUE_PROPERTY (0x14) /**< Rx queue assigned to traffic class 4 */ +#define IX_ETH_DB_QOS_TRAFFIC_CLASS_5_RX_QUEUE_PROPERTY (0x15) /**< Rx queue assigned to traffic class 5 */ +#define IX_ETH_DB_QOS_TRAFFIC_CLASS_6_RX_QUEUE_PROPERTY (0x16) /**< Rx queue assigned to traffic class 6 */ +#define IX_ETH_DB_QOS_TRAFFIC_CLASS_7_RX_QUEUE_PROPERTY (0x17) /**< Rx queue assigned to traffic class 7 */ + +/* private property used by EthAcc to indicate queue configuration complete */ +#define IX_ETH_DB_QOS_QUEUE_CONFIGURATION_COMPLETE (0x18) + +/** + * + * @brief The IEEE 802.3 Ethernet MAC address structure. + * + * The data should be packed with bytes xx:xx:xx:xx:xx:xx + * + * @note The data must be packed in network byte order. + */ +typedef struct +{ + UINT8 macAddress[IX_IEEE803_MAC_ADDRESS_SIZE]; +} IxEthDBMacAddr; + +/** + * @ingroup IxEthDB + * + * @brief Definition of an IXP400 port. + */ +typedef UINT32 IxEthDBPortId; + +/** + * @ingroup IxEthDB + * + * @brief Port dependency map definition + */ +typedef UINT8 IxEthDBPortMap[32]; + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBInit(void) + * + * @brief Initializes the Ethernet learning/filtering database + * + * @note calling this function multiple times does not constitute an error; + * redundant calls will be ignored, returning IX_ETH_DB_SUCCESS + * + * @retval IX_ETH_DB_SUCCESS initialization was successful + * @retval IX_ETH_DB_FAIL initialization failed (OS error) + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBInit(void); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBUnload(void) + * + * @brief Stops and prepares the EthDB component for unloading. + * + * @retval IX_ETH_DB_SUCCESS de-initialization was successful + * @retval IX_ETH_DB_BUSY de-initialization failed, ports must be disabled first + * @retval IX_ETH_DB_FAIL de-initialization failed (OS error) + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBUnload(void); + +/** + * @ingroup IxEthDB + * + * @fn void ixEthDBPortInit(IxEthDBPortId portID) + * + * @brief Initializes a port + * + * This function is called automatically by the Ethernet Access + * ixEthAccPortInit() routine for Ethernet NPE ports and should be manually + * called for any user-defined port (any port that is not one of + * the two Ethernet NPEs). + * + * @param portID @ref IxEthDBPortId [in] - ID of the port to be initialized + * + * @see IxEthDBPortDefs.h for port definitions + * + * @note calling this function multiple times does not constitute an error; + * redundant calls will be ignored + */ +IX_ETH_DB_PUBLIC +void ixEthDBPortInit(IxEthDBPortId portID); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBPortEnable(IxEthDBPortId portID) + * + * @brief Enables a port + * + * This function is called automatically from the Ethernet Access component + * ixEthAccPortEnable() routine for Ethernet NPE ports and should be manually + * called for any user-defined port (any port that is not one of + * the Ethernet NPEs). + * + * @param portID @ref IxEthDBPortId [in] - ID of the port to enable processing on + * + * @retval IX_ETH_DB_SUCCESS if enabling is successful + * @retval IX_ETH_DB_FAIL if the enabling was not successful due to + * a message handler error + * @retval IX_ETH_DB_MAC_UNINITIALIZED the MAC address of this port was + * not initialized (only for Ethernet NPEs) + * @retval IX_ETH_DB_INVALID_PORT if portID is invalid + * + * @pre ixEthDBPortAddressSet needs to be called prior to enabling the port events + * for Ethernet NPEs + * + * @see ixEthDBPortAddressSet + * + * @see IxEthDBPortDefs.h for port definitions + * + * @note calling this function multiple times does not constitute an error; + * redundant calls will be ignored + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBPortEnable(IxEthDBPortId portID); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBPortDisable(IxEthDBPortId portID) + * + * @brief Disables processing on a port + * + * This function is called automatically from the Ethernet Access component + * ixEthAccPortDisable() routine for Ethernet NPE ports and should be manually + * called for any user-defined port (any port that is not one of + * the Ethernet NPEs). + * + * @note Calling ixEthAccPortDisable() will disable the respective Ethernet NPE. + * After Ethernet NPEs are disabled they are stopped therefore + * when re-enabled they need to be reset, downloaded with microcode and started. + * For learning to restart working the user needs to call again + * ixEthAccPortUnicastMacAddressSet or ixEthDBUnicastAddressSet + * with the respective port MAC address. + * Residual MAC addresses learnt before the port was disabled are deleted as soon + * as the port is disabled. This only applies to dynamic (learnt) entries, static + * entries do not dissapear when the port is disabled. + * + * @param portID @ref IxEthDBPortId [in] - ID of the port to disable processing on + * + * @retval IX_ETH_DB_SUCCESS if disabling is successful + * @retval IX_ETH_DB_FAIL if the disabling was not successful due to + * a message handler error + * @retval IX_ETH_DB_INVALID_PORT if portID is invalid + * + * @note calling this function multiple times after the first time completed successfully + * does not constitute an error; redundant calls will be ignored and return IX_ETH_DB_SUCCESS +*/ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBPortDisable(IxEthDBPortId portID); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBPortAddressSet(IxEthDBPortId portID, IxEthDBMacAddr *macAddr) + * + * @brief Sets the port MAC address + * + * This function is to be called from the Ethernet Access component top-level + * ixEthDBUnicastAddressSet(). Event processing cannot be enabled for a port + * until its MAC address has been set. + * + * @param portID @ref IxEthDBPortId [in] - ID of the port whose MAC address is set + * @param macAddr @ref IxEthDBMacAddr [in] - port MAC address + * + * @retval IX_ETH_DB_SUCCESS MAC address was set successfully + * @retval IX_ETH_DB_FAIL MAC address was not set due to a message handler failure + * @retval IX_ETH_DB_INVALID_PORT if the port is not an Ethernet NPE + * + * @see IxEthDBPortDefs.h for port definitions + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBPortAddressSet(IxEthDBPortId portID, IxEthDBMacAddr *macAddr); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBFilteringPortMaximumFrameSizeSet(IxEthDBPortId portID, UINT32 maximumFrameSize) + * + * @brief Set the maximum frame size supported on the given port ID + * + * This functions set the maximum frame size supported on a specific port ID + * + * - Reentrant - yes + * - ISR Callable - no + * + * @param portID @ref IxEthDBPortId [in] - port ID to configure + * @param maximumFrameSize UINT32 [in] - maximum frame size to configure + * + * @retval IX_ETH_DB_SUCCESS the port is configured + * @retval IX_ETH_DB_PORT_UNINITIALIZED the port has not been initialized + * @retval IX_ETH_DB_INVALID_PORT portID is invalid + * @retval IX_ETH_DB_INVALID_ARG size parameter is out of range + * @retval IX_ETH_DB_NO_PERMISSION selected port is not an Ethernet NPE + * @retval IX_FAIL unknown OS or NPE communication error + * + * @note + * This maximum frame size is used to filter the frames based on their + * destination addresses and the capabilities of the destination port. + * The mximum value that can be set for a NPE port is 16320. + * (IX_ETHNPE_ACC_FRAME_LENGTH_MAX) + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBFilteringPortMaximumFrameSizeSet(IxEthDBPortId portID, UINT32 maximumFrameSize); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBFilteringStaticEntryProvision(IxEthDBPortId portID, IxEthDBMacAddr *macAddr) + * + * @brief Populate the Ethernet learning/filtering database with a static MAC address + * + * Populates the Ethernet learning/filtering database with a static MAC address. The entry will not be subject to aging. + * If there is an entry (static or dynamic) with the corresponding MAC address on any port this entry will take precedence. + * Any other entry with the same MAC address will be removed. + * + * - Reentrant - yes + * - ISR Callable - yes + * + * @param portID @ref IxEthDBPortId [in] - port ID to add the static address to + * @param macAddr @ref IxEthDBMacAddr [in] - static MAC address to add + * + * @retval IX_ETH_DB_SUCCESS the add was successful + * @retval IX_ETH_DB_FAIL failed to populate the database entry + * @retval IX_ETH_DB_BUSY failed due to a temporary busy condition (i.e. lack of CPU cycles), try again later + * @retval IX_ETH_DB_INVALID_PORT portID is invalid + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_ARG invalid macAddr pointer argument + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE learning feature is disabled + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBFilteringStaticEntryProvision(IxEthDBPortId portID, IxEthDBMacAddr *macAddr); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBFilteringDynamicEntryProvision(IxEthDBPortId portID, IxEthDBMacAddr *macAddr) + * + * @brief Populate the Ethernet learning/filtering database with a dynamic MAC address + * + * Populates the Ethernet learning/filtering database with a dynamic MAC address. This entry will be subject to normal + * aging function, if aging is enabled on its port. + * If there is an entry (static or dynamic) with the same MAC address on any port this entry will take precedence. + * Any other entry with the same MAC address will be removed. + * + * - Reentrant - yes + * - ISR Callable - yes + * + * @param portID @ref IxEthDBPortId [in] - port ID to add the dynamic address to + * @param macAddr @ref IxEthDBMacAddr [in] - static MAC address to add + * + * @retval IX_ETH_DB_SUCCESS the add was successful + * @retval IX_ETH_DB_FAIL failed to populate the database entry + * @retval IX_ETH_DB_BUSY failed due to a temporary busy condition (i.e. lack of CPU cycles), try again later + * @retval IX_ETH_DB_INVALID_PORT portID is invalid + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_ARG invalid macAddr pointer argument + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE learning feature is disabled + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBFilteringDynamicEntryProvision(IxEthDBPortId portID, IxEthDBMacAddr *macAddr); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBFilteringEntryDelete(IxEthDBMacAddr *macAddr) + * + * @brief Removes a MAC address entry from the Ethernet learning/filtering database + * + * @param macAddr IxEthDBMacAddr [in] - MAC address to remove + * + * - Reentrant - yes + * - ISR Callable - no + * + * @retval IX_ETH_DB_SUCCESS the removal was successful + * @retval IX_ETH_DB_NO_SUCH_ADDR failed to remove the address (not in the database) + * @retval IX_ETH_DB_INVALID_ARG invalid macAddr pointer argument + * @retval IX_ETH_DB_BUSY failed due to a temporary busy condition (i.e. lack of CPU cycles), try again later + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBFilteringEntryDelete(IxEthDBMacAddr *macAddr); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBFilteringPortSearch(IxEthDBPortId portID, IxEthDBMacAddr *macAddr) + * + * @brief Search the Ethernet learning/filtering database for the given MAC address and port ID + * + * This functions searches the database for a specific port ID and MAC address. Both the port ID + * and the MAC address have to match in order for the record to be reported as found. + * + * - Reentrant - yes + * - ISR Callable - no + * + * @param portID @ref IxEthDBPortId [in] - port ID to search for + * @param macAddr @ref IxEthDBMacAddr [in] - MAC address to search for + * + * @retval IX_ETH_DB_SUCCESS the record exists in the database + * @retval IX_ETH_DB_INVALID_ARG invalid macAddr pointer argument + * @retval IX_ETH_DB_NO_SUCH_ADDR the record was not found in the database + * @retval IX_ETH_DB_INVALID_PORT portID is invalid + * @retval IX_ETH_DB_PORT_UNINITIALIZED port ID is not initialized + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE learning feature is disabled + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBFilteringPortSearch(IxEthDBPortId portID, IxEthDBMacAddr *macAddr); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBFilteringDatabaseSearch(IxEthDBPortId *portID, IxEthDBMacAddr *macAddr) + * + * @brief Search the Ethernet learning/filtering database for a MAC address and return the port ID + * + * Searches the database for a MAC address. The function returns the portID for the + * MAC address record, if found. If no match is found the function returns IX_ETH_DB_NO_SUCH_ADDR. + * The portID is only valid if the function finds a match. + * + * - Reentrant - yes + * - ISR Callable - no + * + * @param portID @ref IxEthDBPortId [in] - port ID the address belongs to (populated only on a successful search) + * @param macAddr @ref IxEthDBMacAddr [in] - MAC address to search for + * + * @retval IX_ETH_DB_SUCCESS the record exists in the database + * @retval IX_ETH_DB_NO_SUCH_ADDR the record was not found in the database + * @retval IX_ETH_DB_INVALID_ARG invalid macAddr or portID pointer argument(s) + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBFilteringDatabaseSearch(IxEthDBPortId *portID, IxEthDBMacAddr *macAddr); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBFilteringPortUpdatingSearch(IxEthDBPortId *portID, IxEthDBMacAddr *macAddr) + * + * @brief Search the filtering database for a MAC address, return the port ID and reset the record age + * + * Searches the database for a MAC address. The function returns the portID for the + * MAC address record and resets the entry age to 0, if found. + * If no match is found the function returns IX_ETH_DB_NO_SUCH_ADDR. + * The portID is only valid if the function finds a match. + * + * - Reentrant - yes + * - ISR Callable - no + * + * @retval IX_ETH_DB_SUCCESS the MAC address was found + * @retval IX_ETH_DB_NO_SUCH_ADDR the MAC address was not found + * @retval IX_ETH_DB_INVALID_ARG invalid macAddr or portID pointer argument(s) + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBFilteringPortUpdatingSearch(IxEthDBPortId *portID, IxEthDBMacAddr *macAddr); + +/** + * @ingroup IxEthDB + * + * @def IX_ETH_DB_MAINTENANCE_TIME + * + * @brief The @ref ixEthDBDatabaseMaintenance must be called by the user at a frequency of + * IX_ETH_DB_MAINTENANCE_TIME + * + */ +#define IX_ETH_DB_MAINTENANCE_TIME (1 * 60) /* 1 Minute */ + +/** + * @ingroup IxEthDB + * + * @def IX_ETH_DB_LEARNING_ENTRY_AGE_TIME + * + * @brief The define specifies the filtering database age entry time. Static entries older than + * IX_ETH_DB_LEARNING_ENTRY_AGE_TIME +/- IX_ETH_DB_MAINTENANCE_TIME shall be removed. + * + */ +#define IX_ETH_DB_LEARNING_ENTRY_AGE_TIME (15 * 60 ) /* 15 Mins */ + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBPortAgingDisable(IxEthDBPortId portID) + * + * @brief Disable the aging function for a specific port + * + * @param portID @ref IxEthDBPortId [in] - port ID to disable aging on + * + * - Reentrant - yes + * - ISR Callable - no + * + * @retval IX_ETH_DB_SUCCESS aging disabled successfully + * @retval IX_ETH_DB_INVALID_PORT portID is invalid + * @retval IX_ETH_DB_PORT_UNINITIALIZED port ID is not initialized + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE learning feature is disabled + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBPortAgingDisable(IxEthDBPortId portID); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBPortAgingEnable(IxEthDBPortId portID) + * + * @brief Enable the aging function for a specific port + * + * Enables the aging of dynamic MAC address entries stored in the learning/filtering database + * + * @note The aging function relies on the @ref ixEthDBDatabaseMaintenance being called with a period of + * @ref IX_ETH_DB_MAINTENANCE_TIME seconds. + * + * - Reentrant - yes + * - ISR Callable - no + * + * @param portID @ref IxEthDBPortId [in] - port ID to enable aging on + * + * @retval IX_ETH_DB_SUCCESS aging enabled successfully + * @retval IX_ETH_DB_INVALID_PORT portID is invalid + * @retval IX_ETH_DB_PORT_UNINITIALIZED port ID is not initialized + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE learning feature is disabled + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBPortAgingEnable(IxEthDBPortId portID); + +/** + * @ingroup IxEthDB + * + * @fn void ixEthDBDatabaseMaintenance(void) + * + * @brief Performs a maintenance operation on the Ethernet learning/filtering database + * + * In order to perform a database maintenance this function must be called every + * @ref IX_ETH_DB_MAINTENANCE_TIME seconds. It should be called regardless of whether learning is + * enabled or not. + * + * - Reentrant - no + * - ISR Callable - no + * + * @note this function call will be ignored if the learning feature is disabled + */ +IX_ETH_DB_PUBLIC +void ixEthDBDatabaseMaintenance(void); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBFilteringDatabaseShow(IxEthDBPortId portID) + * + * @brief This function displays the Mac Ethernet MAC address filtering tables. + * + * It displays the MAC address, port ID, entry type (dynamic/static),and age for + * the given port ID. + * + * - Reentrant - no + * - ISR Callable - no + * + * @param portID @ref IxEthDBPortId [in] - port ID to display the MAC address entries + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is invalid + * @retval IX_ETH_DB_PORT_UNINITIALIZED port ID is not initialized + * @retval IX_ETH_DB_FAIL record browser failed due to an internal busy or lock condition + * + * @note this function is deprecated and kept for compatibility reasons; use @ref ixEthDBFilteringDatabaseShowRecords instead + * + * @see ixEthDBFilteringDatabaseShowRecords + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBFilteringDatabaseShow(IxEthDBPortId portID); + +/** + * @ingroup IxEthDB + * + * @fn void ixEthDBFilteringDatabaseShowAll(void) + * + * @brief Displays the MAC address recorded in the filtering database for all registered + * ports (see IxEthDBPortDefs.h), grouped by port ID. + * + * - Reentrant - no + * - ISR Callable - no + * + * @retval void + * + * @note this function is deprecated and kept for compatibility reasons; use @ref ixEthDBFilteringDatabaseShowRecords instead + * + * @see ixEthDBFilteringDatabaseShowRecords + */ +IX_ETH_DB_PUBLIC +void ixEthDBFilteringDatabaseShowAll(void); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBFilteringDatabaseShowRecords(IxEthDBPortId portID, IxEthDBRecordType recordFilter) + * + * @brief This function displays per port database records, given a record type filter + * + * The supported record type filters are: + * + * - IX_ETH_DB_FILTERING_RECORD - displays the non-VLAN filtering records (MAC address, age, static/dynamic) + * - IX_ETH_DB_FILTERING_VLAN_RECORD - displays the VLAN filtering records (MAC address, age, static/dynamic, VLAN ID, CFI, QoS class) + * - IX_ETH_DB_FILTERING_RECORD | IX_ETH_DB_FILTERING_VLAN_RECORD - displays the previous two types of records + * - IX_ETH_DB_WIFI_RECORD - displays the WiFi header conversion records (MAC address, optional gateway MAC address) and WiFi header conversion parameters (BBSID, Duration/ID) + * - IX_ETH_DB_FIREWALL_RECORD - displays the firewall MAC address table and firewall operating mode (white list/black list) + * - IX_ETH_DB_ALL_RECORD_TYPES - displays all the record types + * - IX_ETH_DB_NO_RECORD_TYPE - displays only the port status (no records are displayed) + * + * Additionally, the status of each port will be displayed, containg the following information: type, capabilities, enabled status, + * aging enabled status, group membership and maximum frame size. + * + * The port ID can either be an actual port or IX_ETH_DB_ALL_PORTS, in which case the requested information + * will be displayed for all the ports (grouped by port) + * + * - Reentrant - no + * - ISR Callable - no + * + * @param portID ID of the port to display information on (use IX_ETH_DB_ALL_PORTS for all the ports) + * @param recordFilter record type filter + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is invalid + * @retval IX_ETH_DB_PORT_UNINITIALIZED port ID is not initialized + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBFilteringDatabaseShowRecords(IxEthDBPortId portID, IxEthDBRecordType recordFilter); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBPortDependencyMapSet(IxEthDBPortId portID, IxEthDBPortMap dependencyPortMap) + * + * @brief Sets the dependency port map for a port + * + * @param portID ID of the port to set the dependency map to + * @param dependencyPortMap new dependency map (as bitmap, each bit set indicates a port being included) + * + * This function is used to share filtering information between ports. + * By adding a port into another port's dependency map the target port + * filtering data will import the filtering data from the port it depends on. + * Any changes to filtering data for a port - such as adding, updating or removing records - + * will trigger updates in the filtering information for all the ports depending on + * on the updated port. + * + * For example, if ports 2 and 3 are set in the port 0 dependency map the filtering + * information for port 0 will also include the filtering information from ports 2 and 3. + * Adding a record to port 2 will also trigger an update not only on port 2 but also on + * port 0. + * + * The dependency map is a 256 bit array where each bit corresponds to a port corresponding to the + * bit offset (bit 0 - port 0, bit 1 - port 1 etc). Setting a bit to 1 indicates that the corresponding + * port is the port map. For example, a dependency port map of 0x14 consists in the ports with IDs 2 and 4. + * Note that the last bit (offset 255) is reserved and should never be set (it will be automatically + * cleared by the function). + * + * By default, each port has a dependency port map consisting only of itself, i.e. + * + * @verbatim + IxEthDBPortMap portMap; + + /* clear all ports from port map */ + memset(portMap, 0, sizeof (portMap)); + + /* include portID in port map */ + portMap[portID / 8] = 1 << (portID % 8); + @endverbatim + * + * - Reentrant - no + * - ISR Callable - no + * + * @note Setting dependency maps is useful for NPE ports, which benefit from automatic updates + * of filtering information. Setting dependency maps for user-defined ports is not an error + * but will have no actual effect. + * + * @note Including a port in its own dependency map is not compulsory, however note that + * in this case updating the port will not trigger an update on the port itself, which + * might not be the intended behavior + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_ARG invalid dependencyPortMap pointer + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE Filtering is not available or not enabled for the port + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBPortDependencyMapSet(IxEthDBPortId portID, IxEthDBPortMap dependencyPortMap); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBPortDependencyMapGet(IxEthDBPortId portID, IxEthDBPortMap dependencyPortMap) + * + * @brief Retrieves the dependency port map for a port + * + * @param portID ID of the port to set the dependency map to + * @param dependencyPortMap location where the port dependency map is to be copied + * + * This function will copy the port dependency map to a user specified location. + * + * - Reentrant - no + * - ISR Callable - no + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_ARG invalid dependencyPortMap pointer + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE Filtering is not available or not enabled for the port + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBPortDependencyMapGet(IxEthDBPortId portID, IxEthDBPortMap dependencyPortMap); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBPortVlanTagSet(IxEthDBPortId portID, IxEthDBVlanTag vlanTag) + * + * @brief Sets the default 802.1Q VLAN tag for a given port + * + * @param portID @ref IxEthDBPortId [in] - ID of the port to set the default VLAN tag to + * @param vlanTag @ref IxEthDBVlanTag [in] - default 802.1Q VLAN tag + * + * The tag format has 16 bits and it is defined in the IEEE802.1Q specification. + * This tag will be used for tagging untagged frames (if enabled) and classifying + * unexpedited traffic into an internal traffic class (using the user priority field). + * + * + *
802.1Q tag format
3 bits 1 bit 12 bits + *
user priority CFI VID + *
+ * + * User Priority : Defines user priority, giving eight (2^3) priority levels. IEEE 802.1P defines + * the operation for these 3 user priority bits + * + * CFI : Canonical Format Indicator is always set to zero for Ethernet switches. CFI is used for + * compatibility reason between Ethernet type network and Token Ring type network. If a frame received + * at an Ethernet port has a CFI set to 1, then that frame should not be forwarded as it is to an untagged port. + * + * VID : VLAN ID is the identification of the VLAN, which is basically used by the standard 802.1Q. + * It has 12 bits and allow the id entification of 4096 (2^12) VLANs. Of the 4096 possible VIDs, a VID of 0 + * is used to identify priority frames and value 4095 (FFF) is reserved, so the maximum possible VLAN + * configurations are 4,094. + * + * - Reentrant - no + * - ISR Callable - no + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE VLAN/QoS feature is not available or not enabled for the port + * @retval IX_ETH_DB_INVALID_VLAN vlanTag argument does not parse to a valid 802.1Q VLAN tag + * + * @note a VLAN ID value of 0 indicates that the port is not part of any VLAN + * @note the value of the cannonical frame indicator (CFI) field is ignored, the + * field being used only in frame tagging operations + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBPortVlanTagSet(IxEthDBPortId portID, IxEthDBVlanTag vlanTag); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBPortVlanTagGet(IxEthDBPortId portID, IxEthDBVlanTag *vlanTag) + * + * @brief Retrieves the default 802.1Q port VLAN tag for a given port (see also @ref ixEthDBPortVlanTagSet) + * + * @param portID @ref IxEthDBPortId [in] - ID of the port to retrieve the default VLAN tag from + * @param vlanTag @ref IxEthDBVlanTag [out] - location to write the default port 802.1Q VLAN tag to + * + * - Reentrant - no + * - ISR Callable - no + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_ARG invalid vlanTag pointer + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE VLAN/QoS feature is not available or not enabled for the port + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBPortVlanTagGet(IxEthDBPortId portID, IxEthDBVlanTag *vlanTag); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBVlanTagSet(IxEthDBMacAddr *macAddr, IxEthDBVlanTag vlanTag) + * + * @brief Sets the 802.1Q VLAN tag for a database record + * + * @param macAddr MAC address + * @param vlanTag 802.1Q VLAN tag + * + * This function is used together with @ref ixEthDBVlanTagGet to provide MAC-based VLAN classification support. + * Please note that the bridging application must contain specific code to make use of this feature (see below). + * + * VLAN tags can be set only in IX_ETH_DB_FILTERING_RECORD or IX_ETH_DB_FILTERING_VLAN_RECORD type records. + * If to an IX_ETH_DB_FILTERING_RECORD type record is added a VLAN tag the record type is automatically + * changed to IX_ETH_DB_FILTERING_VLAN_RECORD. Once this has occurred the record type will never + * revert to a non-VLAN type (unless deleted and re-added). + * + * Record types used for different purposes (such as IX_ETH_DB_WIFI_RECORD) will be ignored by + * this function. + * + * After using this function to associate a VLAN ID with a MAC address the VLAN ID can be extracted knowing the + * MAC address using @ref ixEthDBVlanTagGet. This mechanism can be used to implement MAC-based VLAN classification + * if a bridging application searches for the VLAN tag when receiving a frame based on the source MAC address + * (contained in the ixp_ne_src_mac field of the buffer header). + * If found in the database, the application can instruct the NPE to tag the frame by writing the VLAN tag + * in the ixp_ne_vlan_tci field of the buffer header. This way the NPE will inspect the Egress tagging + * rule associated with the given VLAN ID on the Tx port and tag the frame if Egress tagging on the VLAN is + * allowed. Additionally, Egress tagging can be forced by setting the ixp_ne_tx_flags.tag_over and + * ixp_ne_tx_flags.tag_mode flags in the buffer header. + * + * - Reentrant - no + * - ISR Callable - no + * + * @note this function will not add a filtering record, it can only be used to update an existing one + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_ARG invalid macAddr pointer + * @retval IX_ETH_DB_NO_SUCH_ADDR a filtering record with the specified MAC address was not found + * @retval IX_ETH_DB_INVALID_VLAN vlanTag argument does not parse to a valid 802.1Q VLAN tag + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBVlanTagSet(IxEthDBMacAddr *macAddr, IxEthDBVlanTag vlanTag); + +/** + * @ingroup IxEthDB + * + * @fn ixEthDBVlanTagGet(IxEthDBMacAddr *macAddr, IxEthDBVlanTag *vlanTag) + * + * @brief Retrieves the 802.1Q VLAN tag from a database record given the record MAC address + * + * @param macAddr MAC address + * @param vlanTag location to write the record 802.1Q VLAN tag to + * + * @note VLAN tags can be retrieved only from IX_ETH_DB_FILTERING_VLAN_RECORD type records + * + * This function is used together with ixEthDBVlanTagSet to provide MAC-based VLAN classification support. + * Please note that the bridging application must contain specific code to make use of this feature (see @ref ixEthDBVlanTagSet). + * + * - Reentrant - no + * - ISR Callable - no + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_ARG invalid macAddr or vlanTag pointer + * @retval IX_ETH_DB_NO_SUCH_ADDR a filtering record with the specified MAC address was not found + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBVlanTagGet(IxEthDBMacAddr *macAddr, IxEthDBVlanTag *vlanTag); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBPortVlanMembershipAdd(IxEthDBPortId portID, IxEthDBVlanId vlanID) + * + * @brief Adds a VLAN ID to a port's VLAN membership table + * + * Adding a VLAN ID to a port's VLAN membership table will cause frames tagged with the specified + * VLAN ID to be accepted by the frame filter, if Ingress VLAN membership filtering is enabled. + * + * - Reentrant - no + * - ISR Callable - no + * + * @param portID @ref IxEthDBPortId [in] - ID of the port to add the VLAN ID membership to + * @param vlanID @ref IxEthDBVlanId [in] - VLAN ID to be added to the port membership table + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_VLAN vlanID is not a valid VLAN ID + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE VLAN/QoS feature is not available or not enabled for the port + * @retval IX_FAIL unknown OS or NPE communication error + * + * @note A port's default VLAN ID is always in its own membership table, hence there + * is no need to explicitly add it using this function (although it is not an error + * to do so) + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBPortVlanMembershipAdd(IxEthDBPortId portID, IxEthDBVlanId vlanID); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBPortVlanMembershipRangeAdd(IxEthDBPortId portID, IxEthDBVlanId vlanIDMin, IxEthDBVlanId vlanIDMax) + * + * @brief Adds a VLAN ID range to a port's VLAN membership table + * + * All the VLAN IDs in the specified range will be added to the port VLAN + * membership table, including the range start and end VLAN IDs. Tagged frames with + * VLAN IDs in the specified range will be accepted by the frame filter, if Ingress VLAN + * membership filtering is enabled. + * + * - Reentrant - no + * - ISR Callable - no + * + * @param portID @ref IxEthDBPortId [in] - port ID to add the VLAN membership range into + * @param vlanIDMin @ref IxEthDBVlanId [in] - start of the VLAN ID range + * @param vlanIDMax @ref IxEthDBVlanId [in] - end of the VLAN ID range + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_VLAN the specified VLAN IDs are invalid or do not constitute a range + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE VLAN/QoS feature is not available or not enabled for the port + * @retval IX_FAIL unknown OS or NPE communication error + * + * @note Is is valid to use the same VLAN ID for both vlanIDMin and vlanIDMax, in which case this + * function will behave as @ref ixEthDBPortVlanMembershipAdd + * + * @note A port's default VLAN ID is always in its own membership table, hence there is no need + * to explicitly add it using this function (although it is not an error to do so) + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBPortVlanMembershipRangeAdd(IxEthDBPortId portID, IxEthDBVlanId vlanIDMin, IxEthDBVlanId vlanIDMax); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBPortVlanMembershipRemove(IxEthDBPortId portID, IxEthDBVlanId vlanID) + * + * @brief Removes a VLAN ID from a port's VLAN membership table + * + * Frames tagged with a VLAN ID which is not in a port's VLAN membership table + * will be discarded by the frame filter, if Ingress membership filtering is enabled. + * + * - Reentrant - no + * - ISR Callable - no + * + * @param portID @ref IxEthDBPortId [in] - ID of the port to remove the VLAN ID membership from + * @param vlanID @ref IxEthDBVlanId [in] - VLAN ID to be removed from the port membership table + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_INVALID_VLAN vlanID is not a valid VLAN ID + * @retval IX_ETH_DB_NO_PERMISSION attempted to remove the default VLAN ID + * from the port membership table (vlanID was set to the default port VLAN ID) + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE VLAN/QoS feature is not available or not enabled for the port + * @retval IX_FAIL unknown OS or NPE communication error + * + * @note A port's default VLAN ID cannot be removed from the port's membership + * table; attempting it will return IX_ETH_DB_NO_PERMISSION + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBPortVlanMembershipRemove(IxEthDBPortId portID, IxEthDBVlanId vlanID); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBPortVlanMembershipRangeRemove(IxEthDBPortId portID, IxEthDBVlanId vlanIDMin, IxEthDBVlanId vlanIDMax) + * + * @brief Removes a VLAN ID range from a port's VLAN membership table + * + * All the VLAN IDs in the specified range will be removed from the port VLAN + * membership table, including the range start and end VLAN IDs. Tagged frames + * with VLAN IDs in the range will be discarded by the frame filter, if Ingress + * membership filtering is enabled. + * + * - Reentrant - no + * - ISR Callable - no + * + * @param portID @ref IxEthDBPortId [in] - ID of the port to remove the VLAN membership range from + * @param vlanIDMin @ref IxEthDBVlanId [in] - start of the VLAN ID range + * @param vlanIDMax @ref IxEthDBVlanId [in] - end of the VLAN ID range + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_VLAN the specified VLAN IDs are invalid or do not constitute a range + * @retval IX_ETH_DB_NO_PERMISSION attempted to remove the default VLAN ID + * from the port membership table (both vlanIDMin and vlanIDMax were set to the default port VLAN ID) + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE VLAN/QoS feature is not available or not enabled for the port + * @retval IX_FAIL unknown OS or NPE communication error + * + * @note Is is valid to use the same VLAN ID for both vlanIDMin and vlanIDMax, in which case + * function will behave as @ref ixEthDBPortVlanMembershipRemove + * + * @note If the given range overlaps the default port VLAN ID this function + * will remove all the VLAN IDs in the range except for the port VLAN ID from its + * own membership table. This situation will be silently dealt with (no error message + * will be returned) as long as the range contains more than one value (i.e. at least + * one other value, apart from the default port VLAN ID). If the function is called + * with the vlanIDMin and vlanIDMax parameters both set to the port default VLAN ID, the + * function will infer that an attempt was specifically made to remove the default port + * VLAN ID from the port membership table, in which case the return value will be + * IX_ETH_DB_NO_PERMISSION. + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBPortVlanMembershipRangeRemove(IxEthDBPortId portID, IxEthDBVlanId vlanIDMin, IxEthDBVlanId vlanIDMax); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBPortVlanMembershipSet(IxEthDBPortId portID, IxEthDBVlanSet vlanSet) + * + * @brief Sets a port's VLAN membership table + * + * Sets a port's VLAN membership table from a complete VLAN table containing all the possible + * 4096 VLAN IDs. The table format is an array containing 4096 bits (512 bytes), where each bit + * indicates whether the VLAN at that bit index is in the port's membership list (if set) or + * not (unset). + * + * The bit at index 0, indicating VLAN ID 0, indicates no VLAN membership and therefore no + * other bit must be set if bit 0 is set. + * + * The bit at index 4095 is reserved and should never be set (it will be ignored if set). + * + * The bit referencing the same VLAN ID as the default port VLAN ID should always be set, as + * the membership list must contain at least the default port VLAN ID. + * + * - Reentrant - no + * - ISR Callable - no + * + * @param portID @ref IxEthDBPortId [in] - port ID to set the VLAN membership table to + * @param vlanSet @ref IxEthDBVlanSet [in] - pointer to the VLAN membership table + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_ARG invalid vlanSet pointer + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE VLAN/QoS feature is not available or not enabled for the port + * @retval IX_FAIL unknown OS or NPE communication error + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBPortVlanMembershipSet(IxEthDBPortId portID, IxEthDBVlanSet vlanSet); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBPortVlanMembershipGet(IxEthDBPortId portID, IxEthDBVlanSet vlanSet) + * + * @brief Retrieves a port's VLAN membership table + * + * Retrieves the complete VLAN membership table from a port, containing all the possible + * 4096 VLAN IDs. The table format is an array containing 4096 bits (512 bytes), where each bit + * indicates whether the VLAN at that bit index is in the port's membership list (if set) or + * not (unset). + * + * The bit at index 0, indicating VLAN ID 0, indicates no VLAN membership and therefore no + * other bit will be set if bit 0 is set. + * + * The bit at index 4095 is reserved and will not be set (it will be ignored if set). + * + * The bit referencing the same VLAN ID as the default port VLAN ID will always be set, as + * the membership list must contain at least the default port VLAN ID. + * + * - Reentrant - no + * - ISR Callable - no + * + * @param portID @ref IxEthDBPortId [in] - port ID to retrieve the VLAN membership table from + * @param vlanSet @ref IxEthDBVlanSet [out] - pointer a location where the VLAN membership table will be + * written to + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_ARG invalid vlanSet pointer + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE VLAN/QoS feature is not available or not enabled for the port + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBPortVlanMembershipGet(IxEthDBPortId portID, IxEthDBVlanSet vlanSet); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBAcceptableFrameTypeSet(IxEthDBPortId portID, IxEthDBFrameFilter frameFilter) + * + * @brief Sets a port's acceptable frame type filter + * + * The acceptable frame type is one (or a combination) of the following values: + * - IX_ETH_DB_ACCEPT_ALL_FRAMES - accepts all the frames + * - IX_ETH_DB_UNTAGGED_FRAMES - accepts untagged frames + * - IX_ETH_DB_VLAN_TAGGED_FRAMES - accepts tagged frames + * - IX_ETH_DB_PRIORITY_TAGGED_FRAMES - accepts tagged frames with VLAN ID set to 0 (no VLAN membership) + * + * Except for using the exact values given above only the following combinations are valid: + * - IX_ETH_DB_UNTAGGED_FRAMES | IX_ETH_DB_VLAN_TAGGED_FRAMES + * - IX_ETH_DB_UNTAGGED_FRAMES | IX_ETH_DB_PRIORITY_TAGGED_FRAMES + * + * Please note that IX_ETH_DB_UNTAGGED_FRAMES | IX_ETH_DB_VLAN_TAGGED_FRAMES is equivalent + * to IX_ETH_DB_ACCEPT_ALL_FRAMES. + * + * - Reentrant - no + * - ISR Callable - no + * + * @note by default the acceptable frame type filter is set to IX_ETH_DB_ACCEPT_ALL_FRAMES + * + * @note setting the acceptable frame type to PRIORITY_TAGGED_FRAMES is internally + * accomplished by changing the frame filter to VLAN_TAGGED_FRAMES and setting the + * VLAN membership list to include only VLAN ID 0; the membership list will need + * to be restored manually to an appropriate value if the acceptable frame type + * filter is changed back to ACCEPT_ALL_FRAMES or VLAN_TAGGED_FRAMES; failure to do so + * will filter all VLAN traffic bar frames tagged with VLAN ID 0 + * + * @param portID @ref IxEthDBPortId [in] - port ID to set the acceptable frame type filter to + * @param frameFilter @ref IxEthDBFrameFilter [in] - acceptable frame type filter + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_ARG invalid frame type filter + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE VLAN/QoS feature is not available or not enabled for the port + * @retval IX_FAIL unknown OS or NPE communication error + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBAcceptableFrameTypeSet(IxEthDBPortId portID, IxEthDBFrameFilter frameFilter); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBAcceptableFrameTypeGet(IxEthDBPortId portID, IxEthDBFrameFilter *frameFilter) + * + * @brief Retrieves a port's acceptable frame type filter + * + * For a description of the acceptable frame types see @ref ixEthDBAcceptableFrameTypeSet + * + * - Reentrant - no + * - ISR Callable - no + * + * @param portID @ref IxEthDBPortId [in] - port ID to retrieve the acceptable frame type filter from + * @param frameFilter @ref IxEthDBFrameFilter [out] - location to store the acceptable frame type filter + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_ARG invalid frameFilter pointer argument + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE VLAN/QoS feature is not available or not enabled for the port + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBAcceptableFrameTypeGet(IxEthDBPortId portID, IxEthDBFrameFilter *frameFilter); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBPriorityMappingTableSet(IxEthDBPortId portID, IxEthDBPriorityTable priorityTable) + * + * @brief Sets a port's priority mapping table + * + * The priority mapping table is an 8x2 table mapping a QoS (user) priority into an internal + * traffic class. There are 8 valid QoS priorities (0..7, 0 being the lowest) which can be + * mapped into one of the 4 available traffic classes (0..3, 0 being the lowest). + * If a custom priority mapping table is not specified using this function the following + * default priority table will be used (as per IEEE 802.1Q and IEEE 802.1D): + * + * + *
QoS traffic classes
QoS priority Default traffic class Traffic type + *
0 1 Best effort, default class for unexpedited traffic + *
1 0 Background traffic + *
2 0 Spare bandwidth + *
3 1 Excellent effort + *
4 2 Controlled load + *
5 2 Video traffic + *
6 3 Voice traffic + *
7 3 Network control + *
+ * + * - Reentrant - no + * - ISR Callable - no + * + * @param portID @ref IxEthDBPortId [in] - port ID of the port to set the priority mapping table to + * @param priorityTable @ref IxEthDBPriorityTable [in] - location of the user priority table + * + * @note The provided table will be copied into internal data structures in EthDB and + * can be deallocated by the called after this function has completed its execution, if + * so desired + * + * @warning The number of available traffic classes differs depending on the NPE images + * and queue configuration. Check IxEthDBQoS.h for up-to-date information on the availability of + * traffic classes. Note that specifiying a traffic class in the priority map which exceeds + * the system availability will produce an IX_ETH_DB_INVALID_PRIORITY return error code and no + * priority will be remapped. + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_ARG invalid priorityTable pointer + * @retval IX_ETH_DB_INVALID_PRIORITY at least one priority value exceeds + * the current number of available traffic classes + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE VLAN/QoS feature is not available or not enabled for the port + * @retval IX_FAIL unknown OS or NPE communication error + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBPriorityMappingTableSet(IxEthDBPortId portID, IxEthDBPriorityTable priorityTable); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBPriorityMappingTableGet(IxEthDBPortId portID, IxEthDBPriorityTable priorityTable) + * + * @brief Retrieves a port's priority mapping table + * + * The priority mapping table for the given port will be copied in the location + * specified by the caller using "priorityTable" + * + * - Reentrant - no + * - ISR Callable - no + * + * @param portID ID @ref IxEthDBPortId [in] - of the port to retrieve the priority mapping table from + * @param priorityTable @ref IxEthDBPriorityTable [out] - pointer to a user specified location where the table will be copied to + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_ARG invalid priorityTable pointer + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE VLAN/QoS feature is not available or not enabled for the port + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBPriorityMappingTableGet(IxEthDBPortId portID, IxEthDBPriorityTable priorityTable); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBPriorityMappingClassSet(IxEthDBPortId portID, IxEthDBPriority userPriority, IxEthDBPriority trafficClass) + * + * @brief Sets one QoS/user priority => traffic class mapping in a port's priority mapping table + * + * This function establishes a mapping between a user (QoS) priority and an internal traffic class. + * The mapping will be saved in the port's priority mapping table. Use this function when not all + * the QoS priorities need remapping (see also @ref ixEthDBPriorityMappingTableSet) + * + * - Reentrant - no + * - ISR Callable - no + * + * @param portID @ref IxEthDBPortId [in] - ID of the port to set the mapping to + * @param userPriority @ref IxEthDBPriority [in] - user (QoS) priority, between 0 and 7 (0 being the lowest) + * @param trafficClass @ref IxEthDBPriority [in] - internal traffic class, between 0 and 3 (0 being the lowest) + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_PRIORITY userPriority out of range or + * trafficClass is beyond the number of currently available traffic classes + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE VLAN/QoS feature is not available or not enabled for the port + * @retval IX_FAIL unknown OS or NPE communication error + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBPriorityMappingClassSet(IxEthDBPortId portID, IxEthDBPriority userPriority, IxEthDBPriority trafficClass); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBPriorityMappingClassGet(IxEthDBPortId portID, IxEthDBPriority userPriority, IxEthDBPriority *trafficClass) + * + * @brief Retrieves one QoS/user priority => traffic class mapping in a port's priority mapping table + * + * This function retrieves the internal traffic class associated with a QoS (user) priority from a given + * port's priority mapping table. Use this function when not all the QoS priority mappings are + * required (see also @ref ixEthDBPriorityMappingTableGet) + * + * - Reentrant - no + * - ISR Callable - no + * + * @param portID @ref IxEthDBPortId [in] - ID of the port to set the mapping to + * @param userPriority @ref IxEthDBPriority [in] - user (QoS) priority, between 0 and 7 (0 being the lowest) + * @param trafficClass @ref IxEthDBPriority [out] - location to write the corresponding internal traffic class to + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_PRIORITY invalid userPriority value (out of range) + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE VLAN/QoS feature is not available or not enabled for the port + * @retval IX_ETH_DB_INVALID_ARG invalid trafficClass pointer argument + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBPriorityMappingClassGet(IxEthDBPortId portID, IxEthDBPriority userPriority, IxEthDBPriority *trafficClass); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBEgressVlanEntryTaggingEnabledSet(IxEthDBPortId portID, IxEthDBVlanId vlanID, BOOL enabled) + * + * @brief Enables or disables Egress VLAN tagging for a port and a given VLAN + * + * This function enables or disables Egress VLAN tagging for the given port and VLAN ID. + * If the VLAN tagging for a certain VLAN ID is enabled then all the frames to be + * transmitted on the given port tagged with the same VLAN ID will be transmitted in a tagged format. + * If tagging is not enabled for the given VLAN ID, the VLAN tag from the frames matching + * this VLAN ID will be removed (the frames will be untagged). + * + * VLAN ID 4095 is reserved and should never be used with this function. + * VLAN ID 0 has the special meaning of "No VLAN membership" and it is used in this + * context to allow the port to send priority-tagged frames or not. + * + * By default, no Egress VLAN tagging is enabled on any port. + * + * - Reentrant - no + * - ISR Callable - no + * + * @param portID @ref IxEthDBPortId [in] - ID of the port to enable or disable the VLAN ID Egress tagging on + * @param vlanID @ref IxEthDBVlanId [in] - VLAN ID to be matched against outgoing frames + * @param enabled BOOL [in] - TRUE to enable Egress VLAN tagging on the port and given VLAN, and + * FALSE to disable Egress VLAN tagging + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_VLAN invalid VLAN ID (out of range) + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE VLAN/QoS feature is not available or not enabled for the port + * @retval IX_FAIL unknown OS or NPE communication error + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBEgressVlanEntryTaggingEnabledSet(IxEthDBPortId portID, IxEthDBVlanId vlanID, BOOL enabled); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBEgressVlanEntryTaggingEnabledGet(IxEthDBPortId portID, IxEthDBVlanId vlanID, BOOL *enabled) + * + * @brief Retrieves the Egress VLAN tagging enabling status for a port and VLAN ID + * + * @param portID [in] - ID of the port to extract the Egress VLAN ID tagging status from + * @param vlanID VLAN [in] - ID whose tagging status is to be extracted + * @param enabled [in] - user-specifed location where the status is copied to; following + * the successfull execution of this function the value will be TRUE if Egress VLAN + * tagging is enabled for the given port and VLAN ID, and FALSE otherwise + * + * - Reentrant - no + * - ISR Callable - no + * + * @see ixEthDBEgressVlanEntryTaggingEnabledGet + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_VLAN invalid VLAN ID (out of range) + * @retval IX_ETH_DB_INVALID_ARG invalid enabled argument pointer + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE VLAN/QoS feature is not available or not enabled for the port + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBEgressVlanEntryTaggingEnabledGet(IxEthDBPortId portID, IxEthDBVlanId vlanID, BOOL *enabled); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBEgressVlanRangeTaggingEnabledSet(IxEthDBPortId portID, IxEthDBVlanId vlanIDMin, IxEthDBVlanId vlanIDMax, BOOL enabled) + * + * @brief Enables or disables Egress VLAN tagging for a port and given VLAN range + * + * This function is very similar to @ref ixEthDBEgressVlanEntryTaggingEnabledSet with the + * difference that it can manipulate the Egress tagging status on multiple VLAN IDs, + * defined by a contiguous range. Note that both limits in the range are explicitly + * included in the execution of this function. + * + * - Reentrant - no + * - ISR Callable - no + * + * @param portID @ref IxEthDBPortId [in] - ID of the port to enable or disable the VLAN ID Egress tagging on + * @param vlanIDMin @ref IxEthDBVlanId [in] - start of the VLAN range to be matched against outgoing frames + * @param vlanIDMax @ref IxEthDBVlanId [in] - end of the VLAN range to be matched against outgoing frames + * @param enabled BOOL [in] - TRUE to enable Egress VLAN tagging on the port and given VLAN range, + * and FALSE to disable Egress VLAN tagging + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_VLAN invalid VLAN ID (out of range), or do not constitute a range + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE VLAN/QoS feature is not available or not enabled for the port + * @retval IX_ETH_DB_NO_PERMISSION attempted to explicitly remove the default port VLAN ID from the tagging table + * @retval IX_FAIL unknown OS or NPE communication error + * + * @note Specifically removing the default port VLAN ID from the Egress tagging table by setting both vlanIDMin and vlanIDMax + * to the VLAN ID portion of the PVID is not allowed by this function and will return IX_ETH_DB_NO_PERMISSION. + * However, this can be circumvented, should the user specifically desire this, by either using a + * larger range (vlanIDMin < vlanIDMax) or by using ixEthDBEgressVlanEntryTaggingEnabledSet. + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBEgressVlanRangeTaggingEnabledSet(IxEthDBPortId portID, IxEthDBVlanId vlanIDMin, IxEthDBVlanId vlanIDMax, BOOL enabled); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBEgressVlanTaggingEnabledSet(IxEthDBPortId portID, IxEthDBVlanSet vlanSet) + * + * @brief Sets the complete Egress VLAN tagging table for a port + * + * This function is used to set the VLAN tagging/untagging per VLAN ID for a given port + * covering the entire VLAN ID range (0..4094). The vlanSet parameter is a 4096 + * bit array, each bit indicating the Egress behavior for the corresponding VLAN ID. + * If a bit is set then outgoing frames with the corresponding VLAN ID will be transmitted + * with the VLAN tag, otherwise the frame will be transmitted without the VLAN tag. + * + * Bit 0 has a special significance, indicating tagging or tag removal for priority-tagged + * frames. + * + * Bit 4095 is reserved and should never be set (it will be ignored if set). + * + * - Reentrant - no + * - ISR Callable - no + * + * @param portID @ref IxEthDBPortId [in] - ID of the port whose Egress VLAN tagging behavior is set + * @param vlanSet @ref IxEthDBVlanSet [in] - 4096 bit array controlling per-VLAN tagging and untagging + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_ARG invalid vlanSet pointer + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE VLAN/QoS feature is not available or not enabled for the port + * @retval IX_FAIL unknown OS or NPE communication error + * + * @warning This function will automatically add the default port VLAN ID to the Egress tagging table + * every time it is called. The user should manually call ixEthDBEgressVlanEntryTaggingEnabledSet to + * prevent tagging on the default port VLAN ID if the default behavior is not intended. + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBEgressVlanTaggingEnabledSet(IxEthDBPortId portID, IxEthDBVlanSet vlanSet); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBEgressVlanTaggingEnabledGet(IxEthDBPortId portID, IxEthDBVlanSet vlanSet) + * + * @brief Retrieves the complete Egress VLAN tagging table from a port + * + * This function copies the 4096 bit table controlling the Egress VLAN tagging into a user specified + * area. Each bit in the array indicates whether tagging for the corresponding VLAN (the bit position + * in the array) is enabled (the bit is set) or not (the bit is unset). + * + * Bit 4095 is reserved and should not be set (it will be ignored if set). + * + * @see ixEthDBEgressVlanTaggingEnabledSet + * + * @param portID @ref IxEthDBPortId [in] - ID of the port whose Egress VLAN tagging behavior is retrieved + * @param vlanSet @ref IxEthDBVlanSet [out] - user location to copy the Egress tagging table into; should have + * room to store 4096 bits (512 bytes) + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_ARG invalid vlanSet pointer + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE VLAN/QoS feature is not available or not enabled for the port + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBEgressVlanTaggingEnabledGet(IxEthDBPortId portID, IxEthDBVlanSet vlanSet); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBIngressVlanTaggingEnabledSet(IxEthDBPortId portID, IxEthDBTaggingAction taggingAction) + * + * @brief Sets the Ingress VLAN tagging behavior for a port + * + * A port's Ingress tagging behavior is controlled by the taggingAction parameter, + * which can take one of the following values: + * + * - IX_ETH_DB_PASS_THROUGH - leaves the frame unchanged (does not add or remove the VLAN tag) + * - IX_ETH_DB_ADD_TAG - adds the VLAN tag if not present, using the default port VID + * - IX_ETH_DB_REMOVE_TAG - removes the VLAN tag if present + * + * @param portID @ref IxEthDBPortId [in] - ID of the port whose Ingress VLAN tagging behavior is set + * @param taggingAction @ref IxEthDBTaggingAction [in] - tagging behavior for the port + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_ARG invalid taggingAction argument + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE VLAN/QoS feature is not available or not enabled for the port + * @retval IX_FAIL unknown OS or NPE communication error + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBIngressVlanTaggingEnabledSet(IxEthDBPortId portID, IxEthDBTaggingAction taggingAction); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBIngressVlanTaggingEnabledGet(IxEthDBPortId portID, IxEthDBTaggingAction *taggingAction) + * + * @brief Retrieves the Ingress VLAN tagging behavior from a port (see @ref ixEthDBIngressVlanTaggingEnabledSet) + * + * @param portID @ref IxEthDBPortId [in] - ID of the port whose Ingress VLAN tagging behavior is set + * @param taggingAction @ref IxEthDBTaggingAction [out] - location where the tagging behavior for the port is written to + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_ARG invalid taggingAction pointer argument + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE VLAN/QoS feature is not available or not enabled for the port + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBIngressVlanTaggingEnabledGet(IxEthDBPortId portID, IxEthDBTaggingAction *taggingAction); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBVlanPortExtractionEnable(IxEthDBPortId portID, BOOL enable) + * + * @brief Enables or disables port ID extraction + * + * This feature can be used in the situation when a multi-port device (e.g. a switch) + * is connected to an IXP4xx port and the device can provide incoming frame port + * identification by tagging the TPID field in the Ethernet frame. Enabling + * port extraction will instruct the NPE to copy the TPID field from the frame and + * place it in the ixp_ne_src_port of the ixp_buf header. In addition, + * the NPE restores the TPID field to 0. + * + * If the frame is not tagged the NPE will fill the ixp_ne_src_port with the + * port ID of the MII interface the frame was received from. + * + * The TPID field is the least significant byte of the type/length field, which is + * normally set to 0x8100 for 802.1Q-tagged frames. + * + * This feature is disabled by default. + * + * @param portID ID of the port to configure port ID extraction on + * @param enable TRUE to enable port ID extraction and FALSE to disable it + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE VLAN/QoS feature is not available or not enabled for the port + * @retval IX_FAIL unknown OS or NPE communication error + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBVlanPortExtractionEnable(IxEthDBPortId portID, BOOL enable); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBFeatureCapabilityGet(IxEthDBPortId portID, IxEthDBFeature *featureSet) + * + * @brief Retrieves the feature capability set for a port + * + * This function retrieves the feature capability set for a port or the common capabilities shared between all + * the ports, writing the feature capability set in a user specified location. + * + * The feature capability set will consist of a set formed by OR-ing one or more of the following values: + * - IX_ETH_DB_LEARNING - Learning feature; enables EthDB to learn MAC address (filtering) records, including 802.1Q enabled records + * - IX_ETH_DB_FILTERING - Filtering feature; enables EthDB to communicate with the NPEs for downloading filtering information in the NPEs; depends on the learning feature + * - IX_ETH_DB_VLAN_QOS - VLAN/QoS feature; enables EthDB to configure NPEs to operate in VLAN/QoS aware modes + * - IX_ETH_DB_FIREWALL - Firewall feature; enables EthDB to configure NPEs to operate in firewall mode, using white/black address lists + * - IX_ETH_DB_SPANNING_TREE_PROTOCOL - Spanning tree protocol feature; enables EthDB to configure the NPEs as STP nodes + * - IX_ETH_DB_WIFI_HEADER_CONVERSION - WiFi 802.3 to 802.11 header conversion feature; enables EthDB to handle WiFi conversion data + * + * Note that EthDB provides only the LEARNING feature for non-NPE ports. + * + * @param portID @ref IxEthDBPortId [in] - ID of the port to retrieve the capability set for + * (use IX_ETH_DB_ALL_PORTS to retrieve the common capabilities shared between all the ports) + * @param featureSet @ref IxEthDBFeature [out] - location where the capability set will be written to + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_ARG invalid featureSet pointer + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBFeatureCapabilityGet(IxEthDBPortId portID, IxEthDBFeature *featureSet); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBFeatureEnable(IxEthDBPortId portID, IxEthDBFeature feature, BOOL enabled) + * + * @brief Enables or disables one or more EthDB features + * + * Selects one or more features (see @ref ixEthDBFeatureCapabilityGet for a description of the supported + * features) to be enabled or disabled on the selected port (or all the ports). + * + * Note that some features are mutually incompatible: + * - IX_ETH_DB_FILTERING is incompatible with IX_ETH_DB_WIFI_HEADER_CONVERSION + * + * Also note that some features require other features to be enabled: + * - IX_ETH_DB_FILTERING requires IX_ETH_DB_LEARNING + * + * This function will either enable the entire selected feature set for the selected port (or all the ports), + * in which case it will return IX_ETH_DB_SUCCESS, or in case of error it will not enable any feature at all + * and return an appropriate error message. + * + * The following features are enabled by default (for ports with the respective capability), + * for compatibility reasons with previous versions of CSR: + * - IX_ETH_DB_LEARNING + * - IX_ETH_DB_FILTERING + * + * All other features are disabled by default and require manual enabling using ixEthDBFeatureEnable. + * + * Default settings for VLAN, QoS, Firewall and WiFi header conversion features: + * + * VLAN + * + * When the VLAN/QoS feature is enabled for a port for the first time the default VLAN behavior + * of the port is set to be as permissive (it will accept all the frames) and + * non-interferential (it will not change any frames) as possible: + * - the port VLAN ID (VID) is set to 0 + * - the Ingress acceptable frame filter is set to accept all frames + * - the VLAN port membership is set to the complete VLAN range (0 - 4094) + * - the Ingress tagging mode is set to pass-through (will not change frames) + * - the Egress tagging mode is to send tagged frames in the entire VLAN range (0 - 4094) + * + * Note that further disabling and re-enabling the VLAN feature for a given port will not reset the port VLAN behavior + * to the settings listed above. Any VLAN settings made by the user are kept. + * + * QoS + * + * The following default priority mapping table will be used (as per IEEE 802.1Q and IEEE 802.1D): + * + * + *
QoS traffic classes
QoS priority Default traffic class Traffic type + *
0 1 Best effort, default class for unexpedited traffic + *
1 0 Background traffic + *
2 0 Spare bandwidth + *
3 1 Excellent effort + *
4 2 Controlled load + *
5 2 Video traffic + *
6 3 Voice traffic + *
7 3 Network control + *
+ * + * Firewall + * + * The port firewall is configured by default in black-list mode, and the firewall address table is empty. + * This means the firewall will not filter any frames until the feature is configured and the firewall table is + * downloaded to the NPE. + * + * Spanning Tree + * + * The port is set to STP unblocked mode, therefore it will accept all frames until re-configured. + * + * WiFi header conversion + * + * The WiFi header conversion database is empty, therefore no actual header conversion will take place until this + * feature is configured and the conversion table downloaded to the NPE. + * + * @param portID @ref IxEthDBPortId [in] - ID of the port to enable or disable the features on (use IX_ETH_DB_ALL_PORTS for all the ports) + * @param feature @ref IxEthDBFeature [in] - feature or feature set to enable or disable + * @param enabled BOOL [in] - TRUE to enable the feature and FALSE to disable it + * + * @note Certain features, from a functional point of view, cannot be disabled as such at NPE level; + * when such features are set to disabled using the EthDB API they will be configured in such + * a way to determine a behavior equivalent to the feature being disabled. As well as this, disabled + * features cannot be configured or accessed via the EthDB API (except for getting their status). + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_NO_PERMISSION attempted to enable mutually exclusive features, + * or a feature that depends on another feature which is not present or enabled + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE at least one of the features selected is unavailable + * @retval IX_FAIL unknown OS or NPE communication error + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBFeatureEnable(IxEthDBPortId portID, IxEthDBFeature feature, BOOL enabled); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBFeatureStatusGet(IxEthDBPortId portID, IxEthDBFeature feature, BOOL *present, BOOL *enabled) + * + * @brief Retrieves the availability and status of a feature set + * + * This function returns the availability and status for a feature set. + * Note that if more than one feature is selected (e.g. IX_ETH_DB_LEARNING | IX_ETH_DB_FILTERING) + * the "present" and "enabled" return values will be set to TRUE only if all the features in the + * feature set are present and enabled (not only some). + * + * @param portID @ref IxEthDBPortId [in] - ID of the port + * @param feature @ref IxEthDBFeature [in] - identifier of the feature to retrieve the status for + * @param present BOOL [out] - location where a boolean flag indicating whether this feature is present will be written to + * @param enabled BOOL [out] - location where a boolean flag indicating whether this feature is enabled will be written to + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_ARG either present or enabled pointer argument is invalid + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBFeatureStatusGet(IxEthDBPortId portID, IxEthDBFeature feature, BOOL *present, BOOL *enabled); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBFeaturePropertyGet(IxEthDBPortId portID, IxEthDBFeature feature, IxEthDBProperty property, IxEthDBPropertyType *type, void *value) + * + * @brief Retrieves the value of a feature property + * + * The EthDB features usually contain feature-specific properties describing or + * controlling how the feature operates. While essential properties (e.g. the + * firewall operating mode) have their own API, secondary properties can be + * retrieved using this function. + * + * Properties can be read-only or read-write. ixEthDBFeaturePropertyGet operates with + * both types of features. + * + * Properties have types associated with them. A descriptor indicating the property + * type is returned in the type argument for convenience. + * + * The currently supported properties and their corresponding features are as follows: + * + * + *
Properties for IX_ETH_DB_VLAN_QOS
Property identifier Property type Property value Read-Only + *
IX_ETH_DB_QOS_TRAFFIC_CLASS_COUNT_PROPERTY IX_ETH_DB_INTEGER_PROPERTY number of internal traffic classes Yes + *
IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY IX_ETH_DB_INTEGER_PROPERTY queue assignment for traffic class 0 Yes + *
IX_ETH_DB_QOS_TRAFFIC_CLASS_1_RX_QUEUE_PROPERTY IX_ETH_DB_INTEGER_PROPERTY queue assignment for traffic class 1 Yes + *
IX_ETH_DB_QOS_TRAFFIC_CLASS_2_RX_QUEUE_PROPERTY IX_ETH_DB_INTEGER_PROPERTY queue assignment for traffic class 2 Yes + *
IX_ETH_DB_QOS_TRAFFIC_CLASS_3_RX_QUEUE_PROPERTY IX_ETH_DB_INTEGER_PROPERTY queue assignment for traffic class 3 Yes + *
IX_ETH_DB_QOS_TRAFFIC_CLASS_4_RX_QUEUE_PROPERTY IX_ETH_DB_INTEGER_PROPERTY queue assignment for traffic class 4 Yes + *
IX_ETH_DB_QOS_TRAFFIC_CLASS_5_RX_QUEUE_PROPERTY IX_ETH_DB_INTEGER_PROPERTY queue assignment for traffic class 5 Yes + *
IX_ETH_DB_QOS_TRAFFIC_CLASS_6_RX_QUEUE_PROPERTY IX_ETH_DB_INTEGER_PROPERTY queue assignment for traffic class 6 Yes + *
IX_ETH_DB_QOS_TRAFFIC_CLASS_7_RX_QUEUE_PROPERTY IX_ETH_DB_INTEGER_PROPERTY queue assignment for traffic class 7 Yes + *
+ * + * @see ixEthDBFeaturePropertySet + * + * @param portID @ref IxEthDBPortId [in] - ID of the port + * @param feature @ref IxEthDBFeature [in] - EthDB feature for which the property is retrieved + * @param property @ref IxEthDBProperty [in] - property identifier + * @param type @ref IxEthDBPropertyType [out] - location where the property type will be stored + * @param value void [out] - location where the property value will be stored + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_INVALID_ARG invalid property identifier, type or value pointer arguments + * @retval IX_ETH_DB_FAIL incorrect property value or unknown error + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBFeaturePropertyGet(IxEthDBPortId portID, IxEthDBFeature feature, IxEthDBProperty property, IxEthDBPropertyType *type, void *value); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBFeaturePropertySet(IxEthDBPortId portID, IxEthDBFeature feature, IxEthDBProperty property, void *value) + * + * @brief Sets the value of a feature property + * + * Unlike @ref ixEthDBFeaturePropertyGet, this function operates only with read-write properties + * + * The currently supported properties and their corresponding features are as follows: + * + * - IX_ETH_DB_QOS_QUEUE_CONFIGURATION_COMPLETE (for IX_ETH_DB_VLAN_QOS): freezes the availability of traffic classes + * to the number of traffic classes currently in use + * + * Note that this function creates deep copies of the property values; once the function is invoked the client + * can free or reuse the memory area containing the original property value. + * + * Copy behavior for different property types is defined as follows: + * + * - IX_ETH_DB_INTEGER_PROPERTY - 4 bytes are copied from the source location + * - IX_ETH_DB_STRING_PROPERTY - the source string will be copied up to the NULL '\0' string terminator, maximum of 255 characters + * - IX_ETH_DB_MAC_ADDR_PROPERTY - 6 bytes are copied from the source location + * - IX_ETH_DB_BOOL_PROPERTY - 4 bytes are copied from the source location; the only allowed values are TRUE (1L) and false (0L) + * + * @see ixEthDBFeaturePropertySet + * + * @warning IX_ETH_DB_QOS_QUEUE_CONFIGURATION_COMPLETE is provided for EthAcc internal use; + * do not attempt to set this property directly + * + * @param portID @ref IxEthDBPortId [in] - ID of the port + * @param feature @ref IxEthDBFeature [in] - EthDB feature for which the property is set + * @param property @ref IxEthDBProperty [in] - property identifier + * @param value void [in] - location where the property value is to be copied from + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_INVALID_ARG invalid property identifier, value pointer, or invalid property value + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBFeaturePropertySet(IxEthDBPortId portID, IxEthDBFeature feature, IxEthDBProperty property, void *value); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBDatabaseClear(IxEthDBPortId portID, IxEthDBRecordType recordType) + * + * @brief Deletes a set of record types from the Ethernet Database + * + * This function deletes all the records of certain types (specified in the recordType filter) + * associated with a port. Additionally, the IX_ETH_DB_ALL_PORTS value can be used as port ID + * to indicate that the specified record types should be deleted for all the ports. + * + * The record type filter can be an ORed combination of the following types: + * + * Record types + * - IX_ETH_DB_FILTERING_RECORD + * + *
Filtering record
MAC address static/dynamic type age
+ * + * - IX_ETH_DB_FILTERING_VLAN_RECORD + * + *
VLAN-enabled filtering record
MAC address static/dynamic type age 802.1Q tag
+ * + * - IX_ETH_DB_WIFI_RECORD + * + *
WiFi header conversion record
MAC address optional gateway MAC address
+ * + * - IX_ETH_DB_FIREWALL_RECORD + * + *
Firewall record
MAC address
+ * - IX_ETH_DB_ALL_RECORD_TYPES + * + * Any combination of the above types is valid e.g. + * + * (IX_ETH_DB_FILTERING_RECORD | IX_ETH_DB_FILTERING_VLAN_RECORD | IX_ETH_DB_FIREWALL_RECORD), + * + * although some might be redundant (it is not an error to do so) e.g. + * + * (IX_ETH_DB_FILTERING_RECORD | IX_ETH_DB_ALL_RECORD_TYPES) + * + * @param portID @ref IxEthDBPortId [in] - ID of the port + * @param recordType @ref IxEthDBRecordType [in] - record type filter + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_INVALID_ARG invalid recordType filter + * + * @note If the record type filter contains any unrecognized value (hence the + * IX_ETH_DB_INVALID_ARG error value is returned) no actual records will be deleted. + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBDatabaseClear(IxEthDBPortId portID, IxEthDBRecordType recordType); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBWiFiStationEntryAdd(IxEthDBPortId portID, IxEthDBMacAddr *macAddr) + * + * @brief Adds an "Access Point to Station" record to the database, for 802.3 => 802.11 frame + * header conversion + * + * Frame header conversion is controlled by the set of MAC addresses + * added using @ref ixEthDBWiFiStationEntryAdd and @ref ixEthDBWiFiAccessPointEntryAdd. + * Conversion arguments are added using @ref ixEthDBWiFiFrameControlSet, + * @ref ixEthDBWiFiDurationIDSet and @ref ixEthDBWiFiBBSIDSet. + * + * Note that adding the same MAC address twice will not return an error + * (but will not accomplish anything either), while re-adding a record previously added + * as an "Access Point to Access Point" will migrate the record to the "Access Point + * to Station" type. + * + * @param portID @ref IxEthDBPortId [in] - ID of the port + * @param macAddr @ref IxEthDBMacAddr [in] - MAC address to add + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_INVALID_ARG macAddr is an invalid pointer + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE WiFi feature not enabled + * @retval IX_ETH_DB_INVALID_ARG invalid macAddr pointer argument + * @retval IX_ETH_DB_NOMEM maximum number of records reached + * @retval IX_ETH_DB_BUSY lock condition or transaction in progress, try again later + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBWiFiStationEntryAdd(IxEthDBPortId portID, IxEthDBMacAddr *macAddr); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBWiFiAccessPointEntryAdd(IxEthDBPortId portID, IxEthDBMacAddr *macAddr, IxEthDBMacAddr *gatewayMacAddr) + * + * @brief Adds an "Access Point to Access Point" record to the database + * + * @see ixEthDBWiFiStationEntryAdd + * + * Note that adding the same MAC address twice will simply overwrite the previously + * defined gateway MAC address value in the same record, if the record was previously of the + * "Access Point to Access Point" type. + * + * Re-adding a MAC address as "Access Point to Access Point", which was previously added as + * "Access Point to Station" will migrate the record type to "Access Point to Access Point" and + * record the gateway MAC address. + * + * @param portID @ref IxEthDBPortId [in] - ID of the port + * @param macAddr @ref IxEthDBMacAddr [in] - MAC address to add + * @param gatewayMacAddr @ref IxEthDBMacAddr [in] - MAC address of the gateway Access Point + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_ARG macAddr is an invalid pointer + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE WiFi feature not enabled + * @retval IX_ETH_DB_INVALID_ARG invalid macAddr or gatewayMacAddr pointer argument + * @retval IX_ETH_DB_NOMEM maximum number of records reached + * @retval IX_ETH_DB_BUSY lock condition or transaction in progress, try again later + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBWiFiAccessPointEntryAdd(IxEthDBPortId portID, IxEthDBMacAddr *macAddr, IxEthDBMacAddr *gatewayMacAddr); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBWiFiEntryRemove(IxEthDBPortId portID, IxEthDBMacAddr *macAddr) + * + * @brief Removes a WiFi station record + * + * This function removes both types of WiFi records ("Access Point to Station" and + * "Access Point to Access Point"). + * + * @param portID @ref IxEthDBPortId [in] - ID of the port + * @param macAddr @ref IxEthDBMacAddr [in] - MAC address to remove + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port is not initialized + * @retval IX_ETH_DB_INVALID_ARG invalid macAddr pointer argument + * @retval IX_ETH_DB_NO_SUCH_ADDR specified address was not found in the database + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE WiFi feature not enabled + * @retval IX_ETH_DB_BUSY lock condition or transaction in progress, try again later + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBWiFiEntryRemove(IxEthDBPortId portID, IxEthDBMacAddr *macAddr); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBWiFiConversionTableDownload(IxEthDBPortId portID) + * + * @brief Downloads the MAC address table for 802.3 => 802.11 frame header + * conversion to the NPE + * + * Note that the frame conversion MAC address table must be individually downloaded + * to each NPE for which the frame header conversion feature is enabled (i.e. it + * is not possible to specify IX_ETH_DB_ALL_PORTS). + * + * @param portID @ref IxEthDBPortId [in] - ID of the port + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_PORT_UNINITIALIZED port not initialized + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE WiFi feature not enabled + * @retval IX_ETH_DB_FAIL unknown OS or NPE communication error + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBWiFiConversionTableDownload(IxEthDBPortId portID); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBWiFiFrameControlSet(IxEthDBPortId portID, UINT16 frameControl) + * + * @brief Sets the GlobalFrameControl field + * + * The GlobalFrameControl field is a 2-byte value inserted in the Frame Control + * field for all 802.3 to 802.11 frame header conversions + * + * @param portID @ref IxEthDBPortId [in] - ID of the port + * @param frameControl UINT16 [in] - GlobalFrameControl value + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port not initialized + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE WiFi feature not enabled + * @retval IX_ETH_DB_FAIL unknown OS or NPE communication error + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBWiFiFrameControlSet(IxEthDBPortId portID, UINT16 frameControl); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBWiFiDurationIDSet(IxEthDBPortId portID, UINT16 durationID) + * + * @brief Sets the GlobalDurationID field + * + * The GlobalDurationID field is a 2-byte value inserted in the Duration/ID + * field for all 802.3 to 802.11 frame header conversions + * + * @param portID @ref IxEthDBPortId [in] - ID of the port + * @param durationID UINT16 [in] - GlobalDurationID field + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port not initialized + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE WiFi feature not enabled + * @retval IX_ETH_DB_FAIL unknown OS or NPE communication error + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBWiFiDurationIDSet(IxEthDBPortId portID, UINT16 durationID); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBWiFiBBSIDSet(IxEthDBPortId portID, IxEthDBMacAddr *bbsid) + * + * @brief Sets the BBSID field + * + * The BBSID field is a 6-byte value which + * identifies the infrastructure of the service set managed + * by the Access Point having the IXP400 as its processor. The value + * is written in the BBSID field of the 802.11 frame header. + * The BBSID value is the MAC address of the Access Point. + * + * @param portID @ref IxEthDBPortId [in] - ID of the port + * @param bbsid @ref IxEthDBMacAddr [in] - pointer to 6 bytes containing the BSSID + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port not initialized + * @retval IX_ETH_DB_INVALID_ARG invalid bbsid pointer argument + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE WiFi feature not enabled + * @retval IX_ETH_DB_FAIL unknown OS or NPE communication error + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBWiFiBBSIDSet(IxEthDBPortId portID, IxEthDBMacAddr *bbsid); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBSpanningTreeBlockingStateSet(IxEthDBPortId portID, BOOL blocked) + * + * @brief Sets the STP blocked/unblocked state for a port + * + * @param portID @ref IxEthDBPortId [in] - ID of the port + * @param blocked BOOL [in] - TRUE to set the port as STP blocked, FALSE to set it as unblocked + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port not initialized + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE Spanning Tree Protocol feature not enabled + * @retval IX_ETH_DB_FAIL unknown OS or NPE communication error + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBSpanningTreeBlockingStateSet(IxEthDBPortId portID, BOOL blocked); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBSpanningTreeBlockingStateGet(IxEthDBPortId portID, BOOL *blocked) + * + * @brief Retrieves the STP blocked/unblocked state for a port + * + * @param portID @ref IxEthDBPortId [in] - ID of the port + * @param blocked BOOL * [in] - set to TRUE if the port is STP blocked, FALSE otherwise + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port not initialized + * @retval IX_ETH_DB_INVALID_ARG invalid blocked pointer argument + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE Spanning Tree Protocol feature not enabled + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBSpanningTreeBlockingStateGet(IxEthDBPortId portID, BOOL *blocked); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBFirewallModeSet(IxEthDBPortId portID, IxEthDBFirewallMode mode) + * + * @brief Sets the firewall mode to use white or black listing + * + * When enabled, the NPE MAC address based firewall support operates in two modes: + * + * - white-list mode (MAC address based admission) + * - mode set to IX_ETH_DB_FIREWALL_WHITE_LIST + * - only packets originating from MAC addresses contained in the firewall address list + * are allowed on the Rx path + * - black-list mode (MAC address based blocking) + * - mode set to IX_ETH_DB_FIREWALL_BLACK_LIST + * - packets originating from MAC addresses contained in the firewall address list + * are discarded + * + * @param portID @ref IxEthDBPortId [in] - ID of the port + * @param mode @ref IxEthDBFirewallMode [in] - firewall mode (IX_ETH_DB_FIREWALL_WHITE_LIST or IX_ETH_DB_FIREWALL_BLACK_LIST) + * + * @note by default the firewall operates in black-list mode with an empty address + * list, hence it doesn't filter any packets + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port not initialized + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE Firewall feature not enabled + * @retval IX_ETH_DB_INVALID_ARGUMENT mode argument is not a valid firewall configuration mode + * @retval IX_ETH_DB_FAIL unknown OS or NPE communication error +*/ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBFirewallModeSet(IxEthDBPortId portID, IxEthDBFirewallMode mode); + +/** + * @ingroup IxEthDB + * + * @fn ixEthDBFirewallInvalidAddressFilterEnable(IxEthDBPortId portID, BOOL enable) + * + * @brief Enables or disables invalid MAC address filtering + * + * According to IEEE802 it is illegal for a source address to be a multicast + * or broadcast address. If this feature is enabled the NPE inspects the source + * MAC addresses of incoming frames and discards them if invalid addresses are + * detected. + * + * By default this service is enabled, if the firewall feature is supported by the + * NPE image. + * + * @param portID ID of the port + * @param enable TRUE to enable invalid MAC address filtering and FALSE to disable it + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port not initialized + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE Firewall feature not enabled + * @retval IX_ETH_DB_FAIL unknown OS or NPE communication error + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBFirewallInvalidAddressFilterEnable(IxEthDBPortId portID, BOOL enable); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBFirewallEntryAdd(IxEthDBPortId portID, IxEthDBMacAddr *macAddr) + * + * @brief Adds a MAC address to the firewall address list + * + * Note that adding the same MAC address twice will not return an error + * but will not actually accomplish anything. + * + * The firewall MAC address list has a limited number of entries; once + * the maximum number of entries has been reached this function will failed + * to add more addresses, returning IX_ETH_DB_NOMEM. + * + * @param portID @ref IxEthDBPortId [in] - ID of the port + * @param macAddr @ref IxEthDBMacAddr [in] - MAC address to be added + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port not initialized + * @retval IX_ETH_DB_INVALID_ARG invalid macAddr pointer argument + * @retval IX_ETH_DB_NOMEM maximum number of records reached + * @retval IX_ETH_DB_BUSY lock condition or transaction in progress, try again later + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE Firewall feature not enabled + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBFirewallEntryAdd(IxEthDBPortId portID, IxEthDBMacAddr *macAddr); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBFirewallEntryRemove(IxEthDBPortId portID, IxEthDBMacAddr *macAddr) + * + * @brief Removes a MAC address from the firewall address list + * + * @param portID @ref IxEthDBPortId [in] - ID of the port + * @param macAddr @ref IxEthDBMacAddr [in] - MAC address to be removed + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port not initialized + * @retval IX_ETH_DB_INVALID_ARG invalid macAddr pointer argument + * @retval IX_ETH_DB_NO_SUCH_ADDR address not found + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE Firewall feature not enabled + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBFirewallEntryRemove(IxEthDBPortId portID, IxEthDBMacAddr *macAddr); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBFirewallTableDownload(IxEthDBPortId portID) + * + * @brief Downloads the MAC firewall table to a port + * + * @param portID ID of the port + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier + * @retval IX_ETH_DB_PORT_UNINITIALIZED port not initialized + * @retval IX_ETH_DB_FEATURE_UNAVAILABLE Firewall feature not enabled + * @retval IX_ETH_DB_FAIL unknown OS or NPE communication error + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBFirewallTableDownload(IxEthDBPortId portID); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBUserFieldSet(IxEthDBRecordType recordType, IxEthDBMacAddr *macAddr, IxEthDBPortId portID, IxEthDBVlanId vlanID, void *field) + * + * @brief Adds a user-defined field to a database record + * + * This function associates a user-defined field to a database record. + * The user-defined field is passed as a (void *) parameter, hence it can be used + * for any purpose (such as identifying a structure). Retrieving the user-defined field from + * a record is done using @ref ixEthDBUserFieldGet. Note that EthDB never uses the user-defined + * field for any internal operation and it is not aware of the significance of its contents. The + * field is only stored as a pointer. + * + * The database record is identified using a combination of the given parameters, depending on the record type. + * All the record types require the record MAC address. + * + * - IX_ETH_DB_FILTERING_RECORD requires only the MAC address + * - IX_ETH_DB_VLAN_FILTERING_RECORD requires the MAC address and the VLAN ID + * - IX_ETH_DB_WIFI_RECORD requires the MAC address and the portID + * - IX_ETH_DB_FIREWALL_RECORD requires the MAC address and the portID + * + * Please note that if a parameter is not required it is completely ignored (it does not undergo parameter checking). + * The user-defined field can be cleared using a NULL field parameter. + * + * @param recordType @ref IxEthDBRecordType [in] - type of record (can be IX_ETH_DB_FILTERING_RECORD, + * IX_ETH_DB_FILTERING_VLAN_RECORD, IX_ETH_DB_WIFI_RECORD or IX_ETH_DB_FIREWALL_RECORD) + * @param portID @ref IxEthDBPortId [in] - ID of the port (required only for WIFI and FIREWALL records) + * @param macAddr @ref IxEthDBMacAddr * [in] - MAC address of the record + * @param vlanID @ref IxEthDBVlanId [in] - VLAN ID of the record (required only for FILTERING_VLAN records) + * @param field void * [in] - user defined field + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID was required but it is not a valid port identifier + * @retval IX_ETH_DB_INVALID_ARG invalid macAddr pointer argument + * @retval IX_ETH_DB_NO_SUCH_ADDR record not found + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBUserFieldSet(IxEthDBRecordType recordType, IxEthDBMacAddr *macAddr, IxEthDBPortId portID, IxEthDBVlanId vlanID, void *field); + +/** + * @ingroup IxEthDB + * + * @fn IxEthDBStatus ixEthDBUserFieldGet(IxEthDBRecordType recordType, IxEthDBMacAddr *macAddr, IxEthDBPortId portID, IxEthDBVlanId vlanID, void **field) + * + * @brief Retrieves a user-defined field from a database record + * + * The database record is identified using a combination of the given parameters, depending on the record type. + * All the record types require the record MAC address. + * + * - IX_ETH_DB_FILTERING_RECORD requires only the MAC address + * - IX_ETH_DB_VLAN_FILTERING_RECORD requires the MAC address and the VLAN ID + * - IX_ETH_DB_WIFI_RECORD requires the MAC address and the portID + * - IX_ETH_DB_FIREWALL_RECORD requires the MAC address and the portID + * + * Please note that if a parameter is not required it is completely ignored (it does not undergo parameter checking). + * + * If no user-defined field was registered with the specified record then NULL will be written + * at the location specified by field. + * + * @param recordType type of record (can be IX_ETH_DB_FILTERING_RECORD, IX_ETH_DB_FILTERING_VLAN_RECORD, IX_ETH_DB_WIFI_RECORD + * or IX_ETH_DB_FIREWALL_RECORD) + * @param portID ID of the port (required only for WIFI and FIREWALL records) + * @param macAddr MAC address of the record + * @param vlanID VLAN ID of the record (required only for FILTERING_VLAN records) + * @param field location to write the user defined field into + * + * @retval IX_ETH_DB_SUCCESS operation completed successfully + * @retval IX_ETH_DB_INVALID_PORT portID was required but it is not a valid port identifier + * @retval IX_ETH_DB_INVALID_ARG invalid macAddr or field pointer arguments + * @retval IX_ETH_DB_NO_SUCH_ADDR record not found + */ +IX_ETH_DB_PUBLIC +IxEthDBStatus ixEthDBUserFieldGet(IxEthDBRecordType recordType, IxEthDBMacAddr *macAddr, IxEthDBPortId portId, IxEthDBVlanId vlanID, void **field); + +/** + * @} + */ + +#endif /* IxEthDB_H */ diff --git a/cpu/ixp/npe/include/IxEthDBLocks_p.h b/cpu/ixp/npe/include/IxEthDBLocks_p.h new file mode 100644 index 0000000..1d8b24f --- /dev/null +++ b/cpu/ixp/npe/include/IxEthDBLocks_p.h @@ -0,0 +1,122 @@ +/** + * @file IxEthAccDBLocks_p.h + * + * @brief Definition of transaction lock stacks and lock utility macros + * + * @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 IxEthAccDBLocks_p_H +#define IxEthAccDBLocks_p_H + +#include "IxOsPrintf.h" + +/* Lock and lock stacks */ +typedef struct +{ + IxOsalFastMutex* locks[MAX_LOCKS]; + UINT32 stackPointer, basePointer; +} LockStack; + +#define TRY_LOCK(mutex) \ + { \ + if (ixOsalFastMutexTryLock(mutex) != IX_SUCCESS) \ + { \ + return IX_ETH_DB_BUSY; \ + } \ + } + + +#define UNLOCK(mutex) { ixOsalFastMutexUnlock(mutex); } + +#define INIT_STACK(stack) \ + { \ + (stack)->basePointer = 0; \ + (stack)->stackPointer = 0; \ + } + +#define PUSH_LOCK(stack, lock) \ + { \ + if ((stack)->stackPointer == MAX_LOCKS) \ + { \ + ERROR_LOG("Ethernet DB: maximum number of elements in a lock stack has been exceeded on push, heavy chaining?\n"); \ + UNROLL_STACK(stack); \ + \ + return IX_ETH_DB_NOMEM; \ + } \ + \ + if (ixOsalFastMutexTryLock(lock) == IX_SUCCESS) \ + { \ + (stack)->locks[(stack)->stackPointer++] = (lock); \ + } \ + else \ + { \ + UNROLL_STACK(stack); \ + \ + return IX_ETH_DB_BUSY; \ + } \ + } + +#define POP_LOCK(stack) \ + { \ + ixOsalFastMutexUnlock((stack)->locks[--(stack)->stackPointer]); \ + } + +#define UNROLL_STACK(stack) \ + { \ + while ((stack)->stackPointer > (stack)->basePointer) \ + { \ + POP_LOCK(stack); \ + } \ + } + +#define SHIFT_STACK(stack) \ + { \ + if ((stack)->basePointer == MAX_LOCKS - 1) \ + { \ + ERROR_LOG("Ethernet DB: maximum number of elements in a lock stack has been exceeded on shift, heavy chaining?\n"); \ + UNROLL_STACK(stack); \ + \ + return IX_ETH_DB_BUSY; \ + } \ + \ + ixOsalFastMutexUnlock((stack)->locks[(stack)->basePointer++]); \ + } + +#endif /* IxEthAccDBLocks_p_H */ diff --git a/cpu/ixp/npe/include/IxEthDBLog_p.h b/cpu/ixp/npe/include/IxEthDBLog_p.h new file mode 100644 index 0000000..1d6b0bb --- /dev/null +++ b/cpu/ixp/npe/include/IxEthDBLog_p.h @@ -0,0 +1,227 @@ +/** + * @file IxEthDBLog_p.h + * + * @brief definitions of log macros and log configuration + * + * @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 + +#ifdef IX_UNIT_TEST +#define NULL_PRINT_ROUTINE(format, arg...) /* nothing */ +#else +#define NULL_PRINT_ROUTINE if(0) printf +#endif + +/*************************************************** + * Globals * + ***************************************************/ +/* safe to permanently leave these on */ +#define HAS_ERROR_LOG +#define HAS_ERROR_IRQ_LOG +#define HAS_WARNING_LOG + +/*************************************************** + * Log Configuration * + ***************************************************/ + +/* debug output can be turned on unless specifically + declared as a non-debug build */ +#ifndef NDEBUG + +#undef HAS_EVENTS_TRACE +#undef HAS_EVENTS_VERBOSE_TRACE + +#undef HAS_SUPPORT_TRACE +#undef HAS_SUPPORT_VERBOSE_TRACE + +#undef HAS_NPE_TRACE +#undef HAS_NPE_VERBOSE_TRACE +#undef HAS_DUMP_NPE_TREE + +#undef HAS_UPDATE_TRACE +#undef HAS_UPDATE_VERBOSE_TRACE + +#endif /* NDEBUG */ + + +/*************************************************** + * Log Macros * + ***************************************************/ + +/************** Globals ******************/ + +#ifdef HAS_ERROR_LOG + + #define ERROR_LOG printf + +#else + + #define ERROR_LOG NULL_PRINT_ROUTINE + +#endif + +#ifdef HAS_ERROR_IRQ_LOG + + #define ERROR_IRQ_LOG(format, arg1, arg2, arg3, arg4, arg5, arg6) ixOsalLog(IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT, format, arg1, arg2, arg3, arg4, arg5, arg6) + +#else + + #define ERROR_IRQ_LOG(format, arg1, arg2, arg3, arg4, arg5, arg6) /* nothing */ + +#endif + +#ifdef HAS_WARNING_LOG + + #define WARNING_LOG printf + +#else + + #define WARNING_LOG NULL_PRINT_ROUTINE + +#endif + +/************** Events *******************/ + +#ifdef HAS_EVENTS_TRACE + + #define IX_ETH_DB_EVENTS_TRACE printf + #define IX_ETH_DB_IRQ_EVENTS_TRACE(format, arg1, arg2, arg3, arg4, arg5, arg6) ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, format, arg1, arg2, arg3, arg4, arg5, arg6) + + #ifdef HAS_EVENTS_VERBOSE_TRACE + + #define IX_ETH_DB_EVENTS_VERBOSE_TRACE printf + + #else + + #define IX_ETH_DB_EVENTS_VERBOSE_TRACE NULL_PRINT_ROUTINE + + #endif /* HAS_EVENTS_VERBOSE_TRACE */ + +#else + + #define IX_ETH_DB_EVENTS_TRACE NULL_PRINT_ROUTINE + #define IX_ETH_DB_EVENTS_VERBOSE_TRACE NULL_PRINT_ROUTINE + #define IX_ETH_DB_IRQ_EVENTS_TRACE(format, arg1, arg2, arg3, arg4, arg5, arg6) /* nothing */ + +#endif /* HAS_EVENTS_TRACE */ + +/************** Support *******************/ + +#ifdef HAS_SUPPORT_TRACE + + #define IX_ETH_DB_SUPPORT_TRACE printf + #define IX_ETH_DB_SUPPORT_IRQ_TRACE(format, arg1, arg2, arg3, arg4, arg5, arg6) ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, format, arg1, arg2, arg3, arg4, arg5, arg6) + + #ifdef HAS_SUPPORT_VERBOSE_TRACE + + #define IX_ETH_DB_SUPPORT_VERBOSE_TRACE printf + + #else + + #define IX_ETH_DB_SUPPORT_VERBOSE_TRACE NULL_PRINT_ROUTINE + + #endif /* HAS_SUPPORT_VERBOSE_TRACE */ + +#else + + #define IX_ETH_DB_SUPPORT_TRACE NULL_PRINT_ROUTINE + #define IX_ETH_DB_SUPPORT_VERBOSE_TRACE NULL_PRINT_ROUTINE + #define IX_ETH_DB_SUPPORT_IRQ_TRACE(format, arg1, arg2, arg3, arg4, arg5, arg6) /* nothing */ + +#endif /* HAS_SUPPORT_TRACE */ + +/************** NPE Adaptor *******************/ + +#ifdef HAS_NPE_TRACE + + #define IX_ETH_DB_NPE_TRACE printf + #define IX_ETH_DB_NPE_IRQ_TRACE(format, arg1, arg2, arg3, arg4, arg5, arg6) ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, format, arg1, arg2, arg3, arg4, arg5, arg6) + + #ifdef HAS_NPE_VERBOSE_TRACE + + #define IX_ETH_DB_NPE_VERBOSE_TRACE printf + + #else + + #define IX_ETH_DB_NPE_VERBOSE_TRACE NULL_PRINT_ROUTINE + + #endif /* HAS_NPE_VERBOSE_TRACE */ + +#else + + #define IX_ETH_DB_NPE_TRACE NULL_PRINT_ROUTINE + #define IX_ETH_DB_NPE_VERBOSE_TRACE NULL_PRINT_ROUTINE + #define IX_ETH_DB_NPE_IRQ_TRACE(format, arg1, arg2, arg3, arg4, arg5, arg6) /* nothing */ + +#endif /* HAS_NPE_TRACE */ + +#ifdef HAS_DUMP_NPE_TREE + +#define IX_ETH_DB_NPE_DUMP_ELT(eltBaseAddress, eltSize) ixEthELTDumpTree(eltBaseAddress, eltSize) + +#else + +#define IX_ETH_DB_NPE_DUMP_ELT(eltBaseAddress, eltSize) /* nothing */ + +#endif /* HAS_DUMP_NPE_TREE */ + +/************** Port Update *******************/ + +#ifdef HAS_UPDATE_TRACE + + #define IX_ETH_DB_UPDATE_TRACE printf + + #ifdef HAS_UPDATE_VERBOSE_TRACE + + #define IX_ETH_DB_UPDATE_VERBOSE_TRACE printf + + #else + + #define IX_ETH_DB_UPDATE_VERBOSE_TRACE NULL_PRINT_ROUTINE + + #endif + +#else /* HAS_UPDATE_VERBOSE_TRACE */ + + #define IX_ETH_DB_UPDATE_TRACE NULL_PRINT_ROUTINE + #define IX_ETH_DB_UPDATE_VERBOSE_TRACE NULL_PRINT_ROUTINE + +#endif /* HAS_UPDATE_TRACE */ diff --git a/cpu/ixp/npe/include/IxEthDBMessages_p.h b/cpu/ixp/npe/include/IxEthDBMessages_p.h new file mode 100644 index 0000000..ff18160 --- /dev/null +++ b/cpu/ixp/npe/include/IxEthDBMessages_p.h @@ -0,0 +1,258 @@ +/** + * @file IxEthDBMessages_p.h + * + * @brief Definitions of NPE messages + * + * @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 IxEthDBMessages_p_H +#define IxEthDBMessages_p_H + +#include +#include +#include "IxEthDB_p.h" + +/* events watched by the Eth event processor */ +#define IX_ETH_DB_MIN_EVENT_ID (IX_ETHNPE_EDB_GETMACADDRESSDATABASE) +#define IX_ETH_DB_MAX_EVENT_ID (IX_ETHNPE_PC_SETAPMACTABLE) + +/* macros to fill and extract data from NPE messages - place any endian conversions here */ +#define RESET_ELT_MESSAGE(message) { memset((void *) &(message), 0, sizeof((message))); } +#define NPE_MSG_ID(msg) ((msg).data[0] >> 24) + +#define FILL_SETPORTVLANTABLEENTRY_MSG(message, portID, setOffset, vlanMembershipSet, ttiSet) \ + do { \ + message.data[0] = (IX_ETHNPE_VLAN_SETPORTVLANTABLEENTRY << 24) | (portID << 16) | (setOffset * 2); \ + message.data[1] = (vlanMembershipSet << 8) | ttiSet; \ + } while (0); + +#define FILL_SETPORTVLANTABLERANGE_MSG(message, portID, offset, length, zone) \ + do { \ + message.data[0] = IX_ETHNPE_VLAN_SETPORTVLANTABLERANGE << 24 | portID << 16 | offset << 9 | length << 1; \ + message.data[1] = (UINT32) zone; \ + } while (0); + +#define FILL_SETDEFAULTRXVID_MSG(message, portID, tpid, vlanTag) \ + do { \ + message.data[0] = (IX_ETHNPE_VLAN_SETDEFAULTRXVID << 24) \ + | (portID << 16); \ + \ + message.data[1] = (tpid << 16) | vlanTag; \ + } while (0); + +#define FILL_SETRXTAGMODE_MSG(message, portID, filterMode, tagMode) \ + do { \ + message.data[0] = IX_ETHNPE_VLAN_SETRXTAGMODE << 24 \ + | portID << 16 \ + | filterMode << 2 \ + | tagMode; \ + \ + message.data[1] = 0; \ + } while (0); + +#define FILL_SETRXQOSENTRY(message, portID, classIndex, trafficClass, aqmQueue) \ + do { \ + message.data[0] = IX_ETHNPE_VLAN_SETRXQOSENTRY << 24 \ + | portID << 16 \ + | classIndex; \ + \ + message.data[1] = trafficClass << 24 \ + | 0x1 << 23 \ + | aqmQueue << 16 \ + | aqmQueue << 4; \ + } while (0); + +#define FILL_SETPORTIDEXTRACTIONMODE(message, portID, enable) \ + do { \ + message.data[0] = IX_ETHNPE_VLAN_SETPORTIDEXTRACTIONMODE << 24 \ + | portID << 16 \ + | (enable ? 0x1 : 0x0); \ + \ + message.data[1] = 0; \ + } while (0); + + +#define FILL_SETBLOCKINGSTATE_MSG(message, portID, blocked) \ + do { \ + message.data[0] = IX_ETHNPE_STP_SETBLOCKINGSTATE << 24 \ + | portID << 16 \ + | (blocked ? 0x1 : 0x0); \ + \ + message.data[1] = 0; \ + } while (0); + +#define FILL_SETBBSID_MSG(message, portID, bbsid) \ + do { \ + message.data[0] = IX_ETHNPE_PC_SETBBSID << 24 \ + | portID << 16 \ + | bbsid->macAddress[0] << 8 \ + | bbsid->macAddress[1]; \ + \ + message.data[1] = bbsid->macAddress[2] << 24 \ + | bbsid->macAddress[3] << 16 \ + | bbsid->macAddress[4] << 8 \ + | bbsid->macAddress[5]; \ + } while (0); + +#define FILL_SETFRAMECONTROLDURATIONID(message, portID, frameControlDurationID) \ + do { \ + message.data[0] = (IX_ETHNPE_PC_SETFRAMECONTROLDURATIONID << 24) | (portID << 16); \ + message.data[1] = frameControlDurationID; \ + } while (0); + +#define FILL_SETAPMACTABLE_MSG(message, zone) \ + do { \ + message.data[0] = IX_ETHNPE_PC_SETAPMACTABLE << 24 \ + | 0 << 8 /* always use index 0 */ \ + | 64; /* 32 entries, 8 bytes each, 4 bytes in a word */ \ + message.data[1] = (UINT32) zone; \ + } while (0); + +#define FILL_SETFIREWALLMODE_MSG(message, portID, epDelta, mode, address) \ + do { \ + message.data[0] = IX_ETHNPE_FW_SETFIREWALLMODE << 24 \ + | portID << 16 \ + | (epDelta & 0xFF) << 8 \ + | mode; \ + \ + message.data[1] = (UINT32) address; \ + } while (0); + +#define FILL_SETMACADDRESSDATABASE_MSG(message, portID, epDelta, blockCount, address) \ + do { \ + message.data[0] = IX_ETHNPE_EDB_SETMACADDRESSSDATABASE << 24 \ + | (epDelta & 0xFF) << 8 \ + | (blockCount & 0xFF); \ + \ + message.data[1] = (UINT32) address; \ + } while (0); + +#define FILL_GETMACADDRESSDATABASE(message, npeId, zone) \ + do { \ + message.data[0] = IX_ETHNPE_EDB_GETMACADDRESSDATABASE << 24; \ + message.data[1] = (UINT32) zone; \ + } while (0); + +#define FILL_SETMAXFRAMELENGTHS_MSG(message, portID, maxRxFrameSize, maxTxFrameSize) \ + do { \ + message.data[0] = IX_ETHNPE_SETMAXFRAMELENGTHS << 24 \ + | portID << 16 \ + | ((maxRxFrameSize + 63) / 64) << 8 /* max Rx 64-byte blocks */ \ + | (maxTxFrameSize + 63) / 64; /* max Tx 64-byte blocks */ \ + \ + message.data[1] = maxRxFrameSize << 16 | maxTxFrameSize; \ + } while (0); + +#define FILL_SETPORTADDRESS_MSG(message, portID, macAddress) \ + do { \ + message.data[0] = IX_ETHNPE_EDB_SETPORTADDRESS << 24 \ + | portID << 16 \ + | macAddress[0] << 8 \ + | macAddress[1]; \ + \ + message.data[1] = macAddress[2] << 24 \ + | macAddress[3] << 16 \ + | macAddress[4] << 8 \ + | macAddress[5]; \ + } while (0); + +/* access to a MAC node in the NPE tree */ +#define NPE_NODE_BYTE(eltNodeAddr, offset) (((UINT8 *) (eltNodeAddr))[offset]) + +/* browsing of the implicit linear binary tree structure of the NPE tree */ +#define LEFT_CHILD_OFFSET(offset) ((offset) << 1) +#define RIGHT_CHILD_OFFSET(offset) (((offset) << 1) + 1) + +#define IX_EDB_FLAGS_ACTIVE (0x2) +#define IX_EDB_FLAGS_VALID (0x1) +#define IX_EDB_FLAGS_RESERVED (0xfc) +#define IX_EDB_FLAGS_INACTIVE_VALID (0x1) + +#define IX_EDB_NPE_NODE_ELT_PORT_ID_OFFSET (6) +#define IX_EDB_NPE_NODE_ELT_FLAGS_OFFSET (7) +#define IX_EDB_NPE_NODE_WIFI_INDEX_OFFSET (6) +#define IX_EDB_NPE_NODE_WIFI_FLAGS_OFFSET (7) +#define IX_EDB_NPE_NODE_FW_FLAGS_OFFSET (1) +#define IX_EDB_NPE_NODE_FW_RESERVED_OFFSET (6) +#define IX_EDB_NPE_NODE_FW_ADDR_OFFSET (2) + +#define IX_EDB_NPE_NODE_VALID(address) ((NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_ELT_FLAGS_OFFSET) & IX_EDB_FLAGS_VALID) != 0) +#define IX_EDB_NPE_NODE_ACTIVE(address) ((NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_ELT_FLAGS_OFFSET) & IX_EDB_FLAGS_ACTIVE) != 0) +#define IX_EDB_NPE_NODE_PORT_ID(address) (NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_ELT_PORT_ID_OFFSET)) + +/* macros to send messages to the NPEs */ +#define IX_ETHDB_ASYNC_SEND_NPE_MSG(npeId, msg, result) \ + do { \ + result = ixNpeMhMessageSend(npeId, msg, IX_NPEMH_SEND_RETRIES_DEFAULT); \ + \ + if (result != IX_SUCCESS) \ + { \ + ERROR_LOG("DB: Failed to send NPE message\n"); \ + } \ + } while (0); + +#define IX_ETHDB_SYNC_SEND_NPE_MSG(npeId, msg, result) \ + do { \ + result = ixNpeMhMessageWithResponseSend(npeId, msg, msg.data[0] >> 24, ixEthDBNpeMsgAck, IX_NPEMH_SEND_RETRIES_DEFAULT); \ + \ + if (result == IX_SUCCESS) \ + { \ + result = ixOsalMutexLock(&ixEthDBPortInfo[IX_ETH_DB_NPE_TO_PORT_ID(npeId)].npeAckLock, IX_ETH_DB_NPE_TIMEOUT); \ + \ + if (result != IX_SUCCESS) \ + { \ + ERROR_LOG("DB: NPE failed to respond within %dms\n", IX_ETH_DB_NPE_TIMEOUT); \ + } \ + } \ + else \ + { \ + ERROR_LOG("DB: Failed to send NPE message\n"); \ + } \ + } while (0); + +#ifndef IX_NDEBUG +#define IX_ETH_DB_NPE_MSG_HISTORY_DEPTH (100) +extern IX_ETH_DB_PUBLIC UINT32 npeMsgHistory[IX_ETH_DB_NPE_MSG_HISTORY_DEPTH][2]; +extern IX_ETH_DB_PUBLIC UINT32 npeMsgHistoryLen; +#endif + +#define IX_ETHDB_SEND_NPE_MSG(npeId, msg, result) { LOG_NPE_MSG(msg); IX_ETHDB_SYNC_SEND_NPE_MSG(npeId, msg, result); } + +#endif /* IxEthDBMessages_p_H */ diff --git a/cpu/ixp/npe/include/IxEthDBPortDefs.h b/cpu/ixp/npe/include/IxEthDBPortDefs.h new file mode 100644 index 0000000..c3acbdd --- /dev/null +++ b/cpu/ixp/npe/include/IxEthDBPortDefs.h @@ -0,0 +1,163 @@ +/** + * @file IxEthDBPortDefs.h + * + * @brief Public definition of the ports and port capabilities + * + * @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 IxEthDBPortDefs IXP400 Ethernet Database Port Definitions (IxEthDBPortDefs) + * + * @brief IXP400 Public definition of the ports and port capabilities + * + * @{ + */ + +#ifndef IxEthDBPortDefs_H +#define IxEthDBPortDefs_H + +/** + * @brief Port types - currently only Ethernet NPEs are recognized as specific types + * All other (user-defined) ports must be specified as IX_ETH_GENERIC + */ +typedef enum +{ + IX_ETH_GENERIC = 0, /**< generic ethernet port */ + IX_ETH_NPE /**< specific Ethernet NPE */ +} IxEthDBPortType; + +/** + * @brief Port capabilities - used by ixEthAccDatabaseMaintenance to decide whether it + * should manually age entries or not depending on the port capabilities. + * + * Ethernet NPEs have aging capabilities, meaning that they will age the entries + * automatically (by themselves).*/ +typedef enum +{ + IX_ETH_NO_CAPABILITIES = 0, /**< no aging capabilities */ + IX_ETH_ENTRY_AGING = 0x1 /**< aging capabilities present */ +} IxEthDBPortCapability; + +/** + * @brief Port Definition - a structure contains the Port type and capabilities + */ +typedef struct +{ + IxEthDBPortType type; + IxEthDBPortCapability capabilities; +} IxEthDBPortDefinition; + +/** + * @brief Port definitions structure, indexed on the port ID + * @warning Ports 0 and 1 are used by the Ethernet access component therefore + * it is essential to be left untouched. Port 2 here (WAN) is given as + * an example port. The NPE firmware also assumes the NPE B to be + * the port 0 and NPE C to be the port 1. + * + * @note that only 32 ports (0..31) are supported by EthDB + */ +static const IxEthDBPortDefinition ixEthDBPortDefinitions[] = +{ + /* id type capabilities */ + { /* 0 */ IX_ETH_NPE, IX_ETH_NO_CAPABILITIES }, /* Ethernet NPE B */ + { /* 1 */ IX_ETH_NPE, IX_ETH_NO_CAPABILITIES }, /* Ethernet NPE C */ + { /* 2 */ IX_ETH_NPE, IX_ETH_NO_CAPABILITIES }, /* Ethernet NPE A */ + { /* 3 */ IX_ETH_GENERIC, IX_ETH_NO_CAPABILITIES }, /* WAN port */ +}; + +/** + * @def IX_ETH_DB_NUMBER_OF_PORTS + * @brief number of supported ports + */ +#define IX_ETH_DB_NUMBER_OF_PORTS (sizeof (ixEthDBPortDefinitions) / sizeof (ixEthDBPortDefinitions[0])) + +/** + * @def IX_ETH_DB_UNKNOWN_PORT + * @brief definition of an unknown port + */ +#define IX_ETH_DB_UNKNOWN_PORT (0xff) + +/** + * @def IX_ETH_DB_ALL_PORTS + * @brief Special port ID indicating all the ports + * @note This port ID can be used only by a subset of the EthDB API; each + * function specifically mentions whether this is a valid parameter as the port ID + */ +#define IX_ETH_DB_ALL_PORTS (IX_ETH_DB_NUMBER_OF_PORTS + 1) + +/** + * @def IX_ETH_DB_PORTS_ASSERTION + * @brief catch invalid port definitions (<2) with a + * compile-time assertion resulting in a duplicate case error. + */ +#define IX_ETH_DB_PORTS_ASSERTION { switch(0) { case 0 : ; case 1 : ; case IX_ETH_DB_NUMBER_OF_PORTS : ; }} + +/** + * @def IX_ETH_DB_CHECK_PORT(portID) + * @brief safety checks to verify whether the port is invalid or uninitialized + */ +#define IX_ETH_DB_CHECK_PORT(portID) \ +{ \ + if ((portID) >= IX_ETH_DB_NUMBER_OF_PORTS) \ + { \ + return IX_ETH_DB_INVALID_PORT; \ + } \ + \ + if (!ixEthDBPortInfo[(portID)].enabled) \ + { \ + return IX_ETH_DB_PORT_UNINITIALIZED; \ + } \ +} + +/** + * @def IX_ETH_DB_CHECK_PORT_ALL(portID) + * @brief safety checks to verify whether the port is invalid or uninitialized; + * tolerates the use of IX_ETH_DB_ALL_PORTS + */ +#define IX_ETH_DB_CHECK_PORT_ALL(portID) \ +{ \ + if ((portID) != IX_ETH_DB_ALL_PORTS) \ + IX_ETH_DB_CHECK_PORT(portID) \ +} + +#endif /* IxEthDBPortDefs_H */ +/** + *@} + */ diff --git a/cpu/ixp/npe/include/IxEthDBQoS.h b/cpu/ixp/npe/include/IxEthDBQoS.h new file mode 100644 index 0000000..6d34889 --- /dev/null +++ b/cpu/ixp/npe/include/IxEthDBQoS.h @@ -0,0 +1,154 @@ +/** + * @file IxEthDBQoS.h + * + * @brief Public definitions for QoS traffic classes + * + * @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 IxEthDBPortDefs IXP400 Ethernet QoS definitions + * + * @brief IXP00 Public definitions for QoS traffic classes + * + * @{ + */ + +#ifndef IxEthDBQoS_H +#define IxEthDBQoS_H + +/** + * @def IX_ETH_DB_QUEUE_UNAVAILABLE + * @brief alias to indicate a queue (traffic class) is not available + */ +#define IX_ETH_DB_QUEUE_UNAVAILABLE (0) + +#ifndef IX_IEEE802_1Q_QOS_PRIORITY_COUNT +/** + * @def IX_IEEE802_1Q_QOS_PRIORITY_COUNT + * @brief number of QoS priorities, according to IEEE 802.1Q + */ +#define IX_IEEE802_1Q_QOS_PRIORITY_COUNT (8) +#endif + +/** + * @brief array containing all the supported traffic class configurations + */ +static const +UINT8 ixEthDBQueueAssignments[][IX_IEEE802_1Q_QOS_PRIORITY_COUNT] = +{ + { 4, 5, 6, 7, IX_ETH_DB_QUEUE_UNAVAILABLE, IX_ETH_DB_QUEUE_UNAVAILABLE, IX_ETH_DB_QUEUE_UNAVAILABLE, IX_ETH_DB_QUEUE_UNAVAILABLE }, + { 15, 16, 17, 18, IX_ETH_DB_QUEUE_UNAVAILABLE, IX_ETH_DB_QUEUE_UNAVAILABLE, IX_ETH_DB_QUEUE_UNAVAILABLE, IX_ETH_DB_QUEUE_UNAVAILABLE }, + { 11, 23, 26, IX_ETH_DB_QUEUE_UNAVAILABLE, IX_ETH_DB_QUEUE_UNAVAILABLE, IX_ETH_DB_QUEUE_UNAVAILABLE, IX_ETH_DB_QUEUE_UNAVAILABLE, IX_ETH_DB_QUEUE_UNAVAILABLE }, + { 4, 5, 6, 7, 8, 9, 10, 11 } + /* add here all other cases of queue configuration structures and update ixEthDBTrafficClassDefinitions to use them */ +}; + +/** + * @brief value used to index the NPE A functionality ID in the traffic class definition table + */ +#define IX_ETH_DB_NPE_A_FUNCTIONALITY_ID_INDEX (0) + +/** + * @brief value used to index the traffic class count in the traffic class definition table + */ +#define IX_ETH_DB_TRAFFIC_CLASS_COUNT_INDEX (1) + +/** + * @brief value used to index the queue assignment index in the traffic class definition table + */ +#define IX_ETH_DB_QUEUE_ASSIGNMENT_INDEX (2) + +/** + * @brief traffic class definitions + * + * This array contains the default traffic class definition configuration, + * as well as any special cases dictated by the functionality ID of NPE A. + * + * The default case should not be removed (otherwise the Ethernet + * components will assert a fatal failure on initialization). + */ +static const +UINT8 ixEthDBTrafficClassDefinitions[][3] = +{ + /* NPE A functionality ID | traffic class count | queue assignment index (points to the queue enumeration in ixEthDBQueueAssignments) */ + { 0x00, 4, 0 }, /* default case - DO NOT REMOVE */ + { 0x04, 4, 1 }, /* NPE A image ID 0.4.0.0 */ + { 0x09, 3, 2 }, /* NPE A image ID 0.9.0.0 */ + { 0x80, 8, 3 }, /* NPE A image ID 10.80.02.0 */ + { 0x81, 8, 3 }, /* NPE A image ID 10.81.02.0 */ + { 0x82, 8, 3 } /* NPE A image ID 10.82.02.0 */ +}; + +/** + * @brief IEEE 802.1Q recommended QoS Priority => traffic class maps + * + * @verbatim + Number of available traffic classes + 1 2 3 4 5 6 7 8 + QoS Priority + 0 0 0 0 1 1 1 1 2 + 1 0 0 0 0 0 0 0 0 + 2 0 0 0 0 0 0 0 1 + 3 0 0 0 1 1 2 2 3 + 4 0 1 1 2 2 3 3 4 + 5 0 1 1 2 3 4 4 5 + 6 0 1 2 3 4 5 5 6 + 7 0 1 2 3 4 5 6 7 + + @endverbatim + */ +static const +UINT8 ixEthIEEE802_1QUserPriorityToTrafficClassMapping[IX_IEEE802_1Q_QOS_PRIORITY_COUNT][IX_IEEE802_1Q_QOS_PRIORITY_COUNT] = + { + { 0, 0, 0, 0, 0, 0, 0, 0 }, /* 1 traffic class available */ + { 0, 0, 0, 0, 1, 1, 1, 1 }, /* 2 traffic classes available */ + { 0, 0, 0, 0, 1, 1, 2, 2 }, /* 3 traffic classes available */ + { 1, 0, 0, 1, 2, 2, 3, 3 }, /* 4 traffic classes available */ + { 1, 0, 0, 1, 2, 3, 4, 4 }, /* 5 traffic classes available */ + { 1, 0, 0, 2, 3, 4, 5, 5 }, /* 6 traffic classes available */ + { 1, 0, 0, 2, 3, 4, 5, 6 }, /* 7 traffic classes available */ + { 2, 0, 1, 3, 4, 5, 6, 7 } /* 8 traffic classes available */ + }; + +#endif /* IxEthDBQoS_H */ + +/** + *@} + */ diff --git a/cpu/ixp/npe/include/IxEthDB_p.h b/cpu/ixp/npe/include/IxEthDB_p.h new file mode 100644 index 0000000..e7c67ae --- /dev/null +++ b/cpu/ixp/npe/include/IxEthDB_p.h @@ -0,0 +1,712 @@ +/** + * @file IxEthDB_p.h + * + * @brief Private MAC learning 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 -- + */ + +#ifndef IxEthDB_p_H +#define IxEthDB_p_H + +#include +#include +#include +#include +#include + +#include "IxEthDBMessages_p.h" +#include "IxEthDBLog_p.h" + +#if (CPU==SIMSPARCSOLARIS) + +/* when running unit tests intLock() won't protect the event queue so we lock it manually */ +#define TEST_FIXTURE_LOCK_EVENT_QUEUE { ixOsalMutexLock(&eventQueueLock, IX_OSAL_WAIT_FOREVER); } +#define TEST_FIXTURE_UNLOCK_EVENT_QUEUE { ixOsalMutexUnlock(&eventQueueLock); } + +#else + +#define TEST_FIXTURE_LOCK_EVENT_QUEUE /* nothing */ +#define TEST_FIXTURE_UNLOCK_EVENT_QUEUE /* nothing */ + +#endif /* #if(CPU==SIMSPARCSOLARIS) */ + +#ifndef IX_UNIT_TEST + +#define TEST_FIXTURE_INCREMENT_DB_CORE_ACCESS_COUNTER /* nothing */ +#define TEST_FIXTURE_MARK_OVERFLOW_EVENT /* nothing */ + +#else + +extern int dbAccessCounter; +extern int overflowEvent; + +#define TEST_FIXTURE_INCREMENT_DB_CORE_ACCESS_COUNTER { dbAccessCounter++; } +#define TEST_FIXTURE_MARK_OVERFLOW_EVENT { overflowEvent = 1; } + +#endif + +/* code readability markers */ +#define __mempool__ /* memory pool marker */ +#define __lock__ /* hash write locking marker */ +#define __smartpointer__ /* smart pointer marker - warning: use only clone() when duplicating! */ +#define __alignment__ /* marker for data used only as alignment zones */ + +/* constants */ +#define IX_ETH_DB_NPE_TIMEOUT (100) /* NPE response timeout, in ms */ + +/** + * number of hash table buckets + * it should be at least 8x the predicted number of entries for performance + * each bucket needs 8 bytes + */ +#define NUM_BUCKETS (8192) + +/** + * number of hash table buckets to preload when incrementing bucket iterator + * = two cache lines + */ +#define IX_ETHDB_CACHE_LINE_AHEAD (2) + +#define IX_ETHDB_BUCKETPTR_AHEAD ((IX_ETHDB_CACHE_LINE_AHEAD * IX_OSAL_CACHE_LINE_SIZE)/sizeof(void *)) + +#define IX_ETHDB_BUCKET_INDEX_MASK (((IX_OSAL_CACHE_LINE_SIZE)/sizeof(void *)) - 1) + +/* locks */ +#define MAX_LOCKS (20) /**< maximum number of locks used simultaneously, do not tamper with */ + +/* learning tree constants */ +#define INITIAL_ELT_SIZE (8) /**< initial byte size of tree (empty unused root size) */ +#define MAX_ELT_SIZE (512) /**< maximum number of entries (includes unused root) */ +#define MAX_GW_SIZE (32) /**< maximum number of gateway entries (including unused root) */ +#define MAX_FW_SIZE (32) /**< maximum number of firewall entries (including unused root) */ +#define ELT_ENTRY_SIZE (8) /**< entry size, in bytes */ +#define ELT_ROOT_OFFSET (ELT_ENTRY_SIZE) /**< tree root offset, in bytes - node preceeding root is unused */ +#define FULL_ELT_BYTE_SIZE (MAX_ELT_SIZE * ELT_ENTRY_SIZE) /**< full size of tree, in bytes, including unused root */ +#define FULL_GW_BYTE_SIZE (MAX_GW_SIZE * ELT_ENTRY_SIZE) /**< full size of gateway list, in bytes, including unused root */ +#define FULL_FW_BYTE_SIZE (MAX_FW_SIZE * ELT_ENTRY_SIZE) /**< full size of firewall table, in bytes, including unused root */ + +/* maximum size of the VLAN table: + * 4096 bits (one per VLAN) + * 8 bits in one byte + * interleaved VLAN membership and VLAN TTI (*2) */ +#define FULL_VLAN_BYTE_SIZE (4096 / 8 * 2) + +/* upper 9 bits used as set index, lower 3 bits as byte index */ +#define VLAN_SET_OFFSET(vlanID) ((vlanID) >> 3) +#define VLAN_SET_MASK(vlanID) (0x7 - ((vlanID) & 0x7)) + +/* Update zone definitions */ +#define NPE_TREE_MEM_SIZE (4096) /* ((511 entries + 1 unused root) * 8 bytes/entry) */ + +/* check the above value, we rely on 4k */ +#if NPE_TREE_MEM_SIZE != 4096 + #error NPE_TREE_MEM_SIZE is not defined to 4096 bytes! +#endif + +/* Size Filtering limits (Jumbo frame filtering) */ +#define IX_ETHDB_MAX_FRAME_SIZE 65535 /* other ports than NPE ports */ +#define IX_ETHDB_MIN_FRAME_SIZE 1 /* other ports than NPE ports */ +#define IX_ETHDB_MAX_NPE_FRAME_SIZE 16320 /* NPE ports firmware limit */ +#define IX_ETHDB_MIN_NPE_FRAME_SIZE 1 /* NPE ports firmware limit */ +#define IX_ETHDB_DEFAULT_FRAME_SIZE 1522 + +/* memory management pool sizes */ + +/* + * Note: + * + * NODE_POOL_SIZE controls the maximum number of elements in the database at any one time. + * It should be large enough to cover all the search trees of all the ports simultaneously. + * + * MAC_POOL_SIZE should be higher than NODE_POOL_SIZE by at least the total number of MAC addresses + * possible to be held at any time in all the ports. + * + * TREE_POOL_SIZE should follow the same guideline as for MAC_POOL_SIZE. + * + * The database structure described here (2000/4000/4000) is enough for two NPEs holding at most 511 + * entries each plus one PCI NIC holding at most 900 entries. + */ + +#define NODE_POOL_SIZE (2000) /**< number of HashNode objects - also master number of elements in the database; each entry has 16 bytes */ +#define MAC_POOL_SIZE (4000) /**< number of MacDescriptor objects; each entry has 28 bytes */ +#define TREE_POOL_SIZE (4000) /**< number of MacTreeNode objects; each entry has 16 bytes */ + +/* retry policies */ +#define BUSY_RETRY_ENABLED (TRUE) /**< if set to TRUE the API will retry automatically calls returning BUSY */ +#define FOREVER_RETRY (TRUE) /**< if set to TRUE the API will retry forever BUSY calls */ +#define MAX_RETRIES (400) /**< upper retry limit - used only when FOREVER_RETRY is FALSE */ +#define BUSY_RETRY_YIELD (5) /**< ticks to yield for every failed retry */ + +/* event management */ +#define EVENT_QUEUE_SIZE (500) /**< size of the sink collecting events from the Message Handler FIFO */ +#define EVENT_PROCESSING_LIMIT (100) /**< batch processing control size (how many events are extracted from the queue at once) */ + +/* MAC descriptors */ +#define STATIC_ENTRY (TRUE) +#define DYNAMIC_ENTRY (FALSE) + +/* age reset on next maintenance - incrementing by 1 will reset to 0 */ +#define AGE_RESET (0xFFFFFFFF) + +/* dependency maps */ +#define EMPTY_DEPENDENCY_MAP (0) + +/* trees */ +#define RIGHT (1) +#define LEFT (-1) + +/* macros */ +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +#define IX_ETH_DB_CHECK_PORT_EXISTS(portID) \ +{ \ + if ((portID) >= IX_ETH_DB_NUMBER_OF_PORTS) \ + { \ + return IX_ETH_DB_INVALID_PORT; \ + } \ +} + +#define IX_ETH_DB_CHECK_PORT_INITIALIZED(portID) \ +{ \ + if ((portID) >= IX_ETH_DB_NUMBER_OF_PORTS) \ + { \ + return IX_ETH_DB_INVALID_PORT; \ + } \ + else \ + { \ + if (!ixEthDBPortInfo[portID].initialized) \ + { \ + return IX_ETH_DB_PORT_UNINITIALIZED; \ + } \ + } \ +} + +/* single NPE check */ +#define IX_ETH_DB_CHECK_SINGLE_NPE(portID) \ + if (ixEthDBSingleEthNpeCheck(portID) != IX_ETH_DB_SUCCESS) \ + { \ + WARNING_LOG("EthDB: port ID %d is unavailable\n",(UINT32) portID); \ + \ + return IX_ETH_DB_INVALID_PORT; \ + } + +/* feature check */ +#define IX_ETH_DB_CHECK_FEATURE(portID, feature) \ + if ((ixEthDBPortInfo[portID].featureStatus & feature) == 0) \ + { \ + return IX_ETH_DB_FEATURE_UNAVAILABLE; \ + } + +/* busy retrying */ +#define BUSY_RETRY(functionCall) \ + { \ + UINT32 retries = 0; \ + IxEthDBStatus br_result; \ + \ + while ((br_result = functionCall) == IX_ETH_DB_BUSY \ + && BUSY_RETRY_ENABLED && (FOREVER_RETRY || ++retries < MAX_RETRIES)) { ixOsalSleep(BUSY_RETRY_YIELD); }; \ + \ + if ((!FOREVER_RETRY && retries == MAX_RETRIES) || (br_result == IX_ETH_DB_FAIL)) \ + {\ + ERROR_LOG("Ethernet Learning Database Error: BUSY_RETRY failed at %s:%d\n", __FILE__, __LINE__); \ + }\ + } + +#define BUSY_RETRY_WITH_RESULT(functionCall, brwr_result) \ + { \ + UINT32 retries = 0; \ + \ + while ((brwr_result = functionCall) == IX_ETH_DB_BUSY \ + && BUSY_RETRY_ENABLED && (FOREVER_RETRY || ++retries < MAX_RETRIES)) { ixOsalSleep(BUSY_RETRY_YIELD); }; \ + \ + if ((!FOREVER_RETRY && retries == MAX_RETRIES) || (brwr_result == IX_ETH_DB_FAIL)) \ + {\ + ERROR_LOG("Ethernet Learning Database Error: BUSY_RETRY_WITH_RESULT failed at %s:%d\n", __FILE__, __LINE__); \ + }\ + } + +/* iterators */ +#define IS_ITERATOR_VALID(iteratorPtr) ((iteratorPtr)->node != NULL) + +/* dependency port maps */ + +/* Warning: if port indexing starts from 1 replace (portID) with (portID - 1) in DEPENDENCY_MAP (and make sure IX_ETH_DB_NUMBER_OF_PORTS is big enough) */ + +/* gives an empty dependency map */ +#define SET_EMPTY_DEPENDENCY_MAP(map) { int i = 0; for (; i < 32 ; i++) map[i] = 0; } + +#define IS_EMPTY_DEPENDENCY_MAP(result, map) { int i = 0 ; result = TRUE; for (; i < 32 ; i++) if (map[i] != 0) { result = FALSE; break; }} + +/** + * gives a map consisting only of 'portID' + */ +#define SET_DEPENDENCY_MAP(map, portID) {SET_EMPTY_DEPENDENCY_MAP(map); map[portID >> 3] = 1 << (portID & 0x7);} + +/** + * gives a map resulting from joining map1 and map2 + */ +#define JOIN_MAPS(map, map1, map2) { int i = 0; for (; i < 32 ; i++) map[i] = map1[i] | map2[i]; } + +/** + * gives the map resulting from joining portID and map + */ +#define JOIN_PORT_TO_MAP(map, portID) { map[portID >> 3] |= 1 << (portID & 0x7); } + +/** + * gives the map resulting from excluding portID from map + */ +#define EXCLUDE_PORT_FROM_MAP(map, portID) { map[portID >> 3] &= ~(1 << (portID & 0x7); } + +/** + * returns TRUE if map1 is a subset of map2 and FALSE otherwise + */ +#define IS_MAP_SUBSET(result, map1, map2) { int i = 0; result = TRUE; for (; i < 32 ; i++) if ((map1[i] | map2[i]) != map2[i]) result = FALSE; } + +/** + * returns TRUE is portID is part of map and FALSE otherwise + */ +#define IS_PORT_INCLUDED(portID, map) ((map[portID >> 3] & (1 << (portID & 0x7))) != 0) + +/** + * returns the difference between map1 and map2 (ports included in map1 and not included in map2) + */ +#define DIFF_MAPS(map, map1, map2) { int i = 0; for (; i < 32 ; i++) map[i] = map1[i] ^ (map1[i] & map2[i]); } + +/** + * returns TRUE if the maps collide (have at least one port in common) and FALSE otherwise + */ +#define MAPS_COLLIDE(result, map1, map2) { int i = 0; result = FALSE; for (; i < 32 ; i++) if ((map1[i] & map2[i]) != 0) result = TRUE; } + +/* size (number of ports) of a dependency map */ +#define GET_MAP_SIZE(map, size) { int i = 0, b = 0; size = 0; for (; i < 32 ; i++) { char y = map[i]; for (; b < 8 && (y >>= 1); b++) size += (y & 1); }} + +/* copy map2 into map1 */ +#define COPY_DEPENDENCY_MAP(map1, map2) { memcpy (map1, map2, sizeof (map1)); } + +/* definition of a port map size/port number which cannot be reached (we support at most 32 ports) */ +#define MAX_PORT_SIZE (0xFF) +#define MAX_PORT_NUMBER (0xFF) + +#define IX_ETH_DB_CHECK_REFERENCE(ptr) { if ((ptr) == NULL) { return IX_ETH_DB_INVALID_ARG; } } +#define IX_ETH_DB_CHECK_MAP(portID, map) { if (!IS_PORT_INCLUDED(portID, map)) { return IX_ETH_DB_INVALID_ARG; } } + +/* event queue macros */ +#define EVENT_QUEUE_WRAP(offset) ((offset) >= EVENT_QUEUE_SIZE ? (offset) - EVENT_QUEUE_SIZE : (offset)) + +#define CAN_ENQUEUE(eventQueuePtr) ((eventQueuePtr)->length < EVENT_QUEUE_SIZE) + +#define QUEUE_HEAD(eventQueuePtr) (&(eventQueuePtr)->queue[EVENT_QUEUE_WRAP((eventQueuePtr)->base + (eventQueuePtr)->length)]) + +#define QUEUE_TAIL(eventQueuePtr) (&(eventQueuePtr)->queue[(eventQueuePtr)->base]) + +#define PUSH_UPDATE_QUEUE(eventQueuePtr) { (eventQueuePtr)->length++; } + +#define SHIFT_UPDATE_QUEUE(eventQueuePtr) \ + { \ + (eventQueuePtr)->base = EVENT_QUEUE_WRAP((eventQueuePtr)->base + 1); \ + (eventQueuePtr)->length--; \ + } + +#define RESET_QUEUE(eventQueuePtr) \ + { \ + (eventQueuePtr)->base = 0; \ + (eventQueuePtr)->length = 0; \ + } + +/* node stack macros - used to browse a tree without using a recursive function */ +#define NODE_STACK_INIT(stack) { (stack)->nodeCount = 0; } +#define NODE_STACK_PUSH(stack, node, offset) { (stack)->nodes[(stack)->nodeCount] = (node); (stack)->offsets[(stack)->nodeCount++] = (offset); } +#define NODE_STACK_POP(stack, node, offset) { (node) = (stack)->nodes[--(stack)->nodeCount]; offset = (stack)->offsets[(stack)->nodeCount]; } +#define NODE_STACK_NONEMPTY(stack) ((stack)->nodeCount != 0) + +#ifndef IX_NDEBUG +#define IX_ETH_DB_NPE_MSG_HISTORY_DEPTH (100) +#define LOG_NPE_MSG(msg) \ + do { \ + UINT32 npeMsgHistoryIndex = (npeMsgHistoryLen++) % IX_ETH_DB_NPE_MSG_HISTORY_DEPTH; \ + npeMsgHistory[npeMsgHistoryIndex][0] = msg.data[0]; \ + npeMsgHistory[npeMsgHistoryIndex][1] = msg.data[1]; \ + } while (0); +#else +#define LOG_NPE_MSG() /* nothing */ +#endif + +/* ----------- Data -------------- */ + +/* typedefs */ + +typedef UINT32 (*HashFunction)(void *entity); +typedef BOOL (*MatchFunction)(void *reference, void *entry); +typedef void (*FreeFunction)(void *entry); + +/** + * basic component of a hash table + */ +typedef struct HashNode_t +{ + void *data; /**< specific data */ + struct HashNode_t *next; /**< used for bucket chaining */ + + __mempool__ struct HashNode_t *nextFree; /**< memory pool management */ + + __lock__ IxOsalFastMutex lock; /**< node lock */ +} HashNode; + +/** + * @brief hash table iterator definition + * + * an iterator is an object which can be used + * to browse a hash table + */ +typedef struct +{ + UINT32 bucketIndex; /**< index of the currently iterated bucket */ + HashNode *previousNode; /**< reference to the previously iterated node within the current bucket */ + HashNode *node; /**< reference to the currently iterated node */ +} HashIterator; + +/** + * definition of a MAC descriptor (a database record) + */ + +typedef enum +{ + IX_ETH_DB_WIFI_AP_TO_STA = 0x0, + IX_ETH_DB_WIFI_AP_TO_AP = 0x1 +} IxEthDBWiFiRecordType; + +typedef union +{ + struct + { + UINT32 age; + BOOL staticEntry; /**< TRUE if this address is static (doesn't age) */ + } filteringData; + + struct + { + UINT32 age; + BOOL staticEntry; + UINT32 ieee802_1qTag; + } filteringVlanData; + + struct + { + IxEthDBWiFiRecordType type; /**< AP_TO_AP (0x1) or AP_TO_STA (0x0) */ + UINT32 gwAddressIndex; /**< used only when linearizing the entries for NPE usage */ + UINT8 gwMacAddress[IX_IEEE803_MAC_ADDRESS_SIZE]; + + __alignment__ UINT8 reserved2[2]; + } wifiData; +} IxEthDBRecordData; + +typedef struct MacDescriptor_t +{ + UINT8 macAddress[IX_IEEE803_MAC_ADDRESS_SIZE]; + + __alignment__ UINT8 reserved1[2]; + + UINT32 portID; + IxEthDBRecordType type; + IxEthDBRecordData recordData; + + /* used for internal operations, such as NPE linearization */ + void *internal; + + /* custom user data */ + void *user; + + __mempool__ struct MacDescriptor_t *nextFree; /**< memory pool management */ + __smartpointer__ UINT32 refCount; /**< smart pointer reference counter */ +} MacDescriptor; + +/** + * hash table definition + */ +typedef struct +{ + HashNode *hashBuckets[NUM_BUCKETS]; + UINT32 numBuckets; + + __lock__ IxOsalFastMutex bucketLocks[NUM_BUCKETS]; + + HashFunction entryHashFunction; + MatchFunction *matchFunctions; + FreeFunction freeFunction; +} HashTable; + +typedef enum +{ + IX_ETH_DB_MAC_KEY = 1, + IX_ETH_DB_MAC_PORT_KEY = 2, + IX_ETH_DB_MAC_VLAN_KEY = 3, + IX_ETH_DB_MAX_KEY_INDEX = 3 +} IxEthDBSearchKeyType; + +typedef struct MacTreeNode_t +{ + __smartpointer__ MacDescriptor *descriptor; + struct MacTreeNode_t *left, *right; + + __mempool__ struct MacTreeNode_t *nextFree; +} MacTreeNode; + +typedef IxEthDBStatus (*IxEthDBPortUpdateHandler)(IxEthDBPortId portID, IxEthDBRecordType type); + +typedef void (*IxEthDBNoteWriteFn)(void *address, MacTreeNode *node); + +typedef struct +{ + BOOL updateEnabled; /**< TRUE if updates are enabled for port */ + BOOL userControlled; /**< TRUE if the user has manually used ixEthDBPortUpdateEnableSet */ + BOOL treeInitialized; /**< TRUE if the NPE has received an initial tree */ + IxEthDBPortUpdateHandler updateHandler; /**< port update handler routine */ + void *npeUpdateZone; /**< port update memory zone */ + void *npeGwUpdateZone; /**< port update memory zone for gateways */ + void *vlanUpdateZone; /**< port update memory zone for VLAN tables */ + MacTreeNode *searchTree; /**< internal search tree, in MacTreeNode representation */ + BOOL searchTreePendingWrite; /**< TRUE if searchTree holds a tree pending write to the port */ +} PortUpdateMethod; + +typedef struct +{ + IxEthDBPortId portID; /**< port ID */ + BOOL enabled; /**< TRUE if the port is enabled */ + BOOL agingEnabled; /**< TRUE if aging on this port is enabled */ + BOOL initialized; + IxEthDBPortMap dependencyPortMap; /**< dependency port map for this port */ + PortUpdateMethod updateMethod; /**< update method structure */ + BOOL macAddressUploaded; /**< TRUE if the MAC address was uploaded into the port */ + UINT32 maxRxFrameSize; /**< maximum Rx frame size for this port */ + UINT32 maxTxFrameSize; /**< maximum Rx frame size for this port */ + + UINT8 bbsid[6]; + __alignment__ UINT8 reserved[2]; + UINT32 frameControlDurationID; /**< Frame Control - Duration/ID WiFi control */ + + IxEthDBVlanTag vlanTag; /**< default VLAN tag for port */ + IxEthDBPriorityTable priorityTable; /**< QoS <=> internal priority mapping */ + IxEthDBVlanSet vlanMembership; + IxEthDBVlanSet transmitTaggingInfo; + IxEthDBFrameFilter frameFilter; + IxEthDBTaggingAction taggingAction; + + UINT32 npeFrameFilter; + UINT32 npeTaggingAction; + + IxEthDBFirewallMode firewallMode; + BOOL srcAddressFilterEnabled; + + BOOL stpBlocked; + + IxEthDBFeature featureCapability; + IxEthDBFeature featureStatus; + + UINT32 ixEthDBTrafficClassAQMAssignments[IX_IEEE802_1Q_QOS_PRIORITY_COUNT]; + + UINT32 ixEthDBTrafficClassCount; + + UINT32 ixEthDBTrafficClassAvailable; + + + + __lock__ IxOsalMutex npeAckLock; +} PortInfo; + +/* list of port information structures indexed on port Ids */ +extern IX_ETH_DB_PUBLIC PortInfo ixEthDBPortInfo[IX_ETH_DB_NUMBER_OF_PORTS]; + +typedef enum +{ + IX_ETH_DB_ADD_FILTERING_RECORD = 0xFF0001, + IX_ETH_DB_REMOVE_FILTERING_RECORD = 0xFF0002 +} PortEventType; + +typedef struct +{ + UINT32 eventType; + IxEthDBPortId portID; + IxEthDBMacAddr macAddr; + BOOL staticEntry; +} PortEvent; + +typedef struct +{ + PortEvent queue[EVENT_QUEUE_SIZE]; + UINT32 base; + UINT32 length; +} PortEventQueue; + +typedef struct +{ + IxEthDBPortId portID; /**< originating port */ + MacDescriptor *macDescriptors[MAX_ELT_SIZE]; /**< addresses to be synced into db */ + UINT32 addressCount; /**< number of addresses */ +} TreeSyncInfo; + +typedef struct +{ + MacTreeNode *nodes[MAX_ELT_SIZE]; + UINT32 offsets[MAX_ELT_SIZE]; + UINT32 nodeCount; +} MacTreeNodeStack; + +/* Prototypes */ + +/* ----------- Memory management -------------- */ + +IX_ETH_DB_PUBLIC void ixEthDBInitMemoryPools(void); + +IX_ETH_DB_PUBLIC HashNode* ixEthDBAllocHashNode(void); +IX_ETH_DB_PUBLIC void ixEthDBFreeHashNode(HashNode *); + +IX_ETH_DB_PUBLIC __smartpointer__ MacDescriptor* ixEthDBAllocMacDescriptor(void); +IX_ETH_DB_PUBLIC __smartpointer__ MacDescriptor* ixEthDBCloneMacDescriptor(MacDescriptor *macDescriptor); +IX_ETH_DB_PUBLIC __smartpointer__ void ixEthDBFreeMacDescriptor(MacDescriptor *); + +IX_ETH_DB_PUBLIC __smartpointer__ MacTreeNode* ixEthDBAllocMacTreeNode(void); +IX_ETH_DB_PUBLIC __smartpointer__ MacTreeNode* ixEthDBCloneMacTreeNode(MacTreeNode *); +IX_ETH_DB_PUBLIC __smartpointer__ void ixEthDBFreeMacTreeNode(MacTreeNode *); + +IX_ETH_DB_PUBLIC void ixEthDBPoolFreeMacTreeNode(MacTreeNode *); +IX_ETH_DB_PUBLIC UINT32 ixEthDBSearchTreeUsageGet(MacTreeNode *tree); +IX_ETH_DB_PUBLIC int ixEthDBShowMemoryStatus(void); + +/* Hash Table */ +IX_ETH_DB_PUBLIC void ixEthDBInitHash(HashTable *hashTable, UINT32 numBuckets, HashFunction entryHashFunction, MatchFunction *matchFunctions, FreeFunction freeFunction); + +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBAddHashEntry(HashTable *hashTable, void *entry); +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBRemoveHashEntry(HashTable *hashTable, int keyType, void *reference); +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBSearchHashEntry(HashTable *hashTable, int keyType, void *reference, HashNode **searchResult); +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBPeekHashEntry(HashTable *hashTable, int keyType, void *reference); +IX_ETH_DB_PUBLIC void ixEthDBReleaseHashNode(HashNode *node); + +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBInitHashIterator(HashTable *hashTable, HashIterator *iterator); +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBIncrementHashIterator(HashTable *hashTable, HashIterator *iterator); +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBRemoveEntryAtHashIterator(HashTable *hashTable, HashIterator *iterator); +IX_ETH_DB_PUBLIC void ixEthDBReleaseHashIterator(HashIterator *iterator); + +/* API Support */ +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBPortAddressSet(IxEthDBPortId portID, IxEthDBMacAddr *macAddr); +IX_ETH_DB_PUBLIC void ixEthDBMaximumFrameSizeAckCallback(IxNpeMhNpeId npeID, IxNpeMhMessage msg); + +/* DB Core functions */ +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBInit(void); +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBAdd(MacDescriptor *newRecordTemplate, IxEthDBPortMap updateTrigger); +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBRemove(MacDescriptor *templateRecord, IxEthDBPortMap updateTrigger); +IX_ETH_DB_PUBLIC HashNode* ixEthDBSearch(IxEthDBMacAddr *macAddress, IxEthDBRecordType typeFilter); +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBPeek(IxEthDBMacAddr *macAddress, IxEthDBRecordType typeFilter); + +/* Learning support */ +IX_ETH_DB_PUBLIC UINT32 ixEthDBAddressCompare(UINT8 *mac1, UINT8 *mac2); +IX_ETH_DB_PUBLIC BOOL ixEthDBAddressMatch(void *reference, void *entry); +IX_ETH_DB_PUBLIC UINT32 ixEthDBEntryXORHash(void *macDescriptor); +IX_ETH_DB_PUBLIC UINT32 ixEthDBKeyXORHash(void *macAddress); + +/* Port updates */ +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBNPEUpdateHandler(IxEthDBPortId portID, IxEthDBRecordType type); +IX_ETH_DB_PUBLIC void ixEthDBUpdatePortLearningTrees(IxEthDBPortMap triggerPorts); +IX_ETH_DB_PUBLIC void ixEthDBNPEAccessRequest(IxEthDBPortId portID); +IX_ETH_DB_PUBLIC void ixEthDBUpdateLock(void); +IX_ETH_DB_PUBLIC void ixEthDBUpdateUnlock(void); +IX_ETH_DB_PUBLIC MacTreeNode* ixEthDBQuery(MacTreeNode *searchTree, IxEthDBPortMap query, IxEthDBRecordType recordFilter, UINT32 maximumEntries); +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBFirewallUpdate(IxEthDBPortId portID, void *address, UINT32 epDelta); + +/* Init/unload */ +IX_ETH_DB_PUBLIC void ixEthDBPortSetAckCallback(IxNpeMhNpeId npeID, IxNpeMhMessage msg); +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBEventProcessorInit(void); +IX_ETH_DB_PUBLIC void ixEthDBPortInit(IxEthDBPortId portID); +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBPortEnable(IxEthDBPortId portID); +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBPortDisable(IxEthDBPortId portID); +IX_ETH_DB_PUBLIC void ixEthDBNPEUpdateAreasInit(void); +IX_ETH_DB_PUBLIC UINT32 ixEthDBMatchMethodsRegister(MatchFunction *matchFunctions); +IX_ETH_DB_PUBLIC UINT32 ixEthDBRecordSerializeMethodsRegister(void); +IX_ETH_DB_PUBLIC UINT32 ixEthDBUpdateTypeRegister(BOOL *typeArray); +IX_ETH_DB_PUBLIC void ixEthDBNPEUpdateAreasUnload(void); +IX_ETH_DB_PUBLIC void ixEthDBFeatureCapabilityScan(void); +IX_ETH_DB_PUBLIC UINT32 ixEthDBKeyTypeRegister(UINT32 *keyType); + +/* Event processing */ +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBDefaultEventCallbackEnable(IxEthDBPortId portID, BOOL enable); +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBTriggerAddPortUpdate(IxEthDBMacAddr *macAddr, IxEthDBPortId portID, BOOL staticEntry); +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBTriggerRemovePortUpdate(IxEthDBMacAddr *macAddr, IxEthDBPortId portID); +IX_ETH_DB_PUBLIC void ixEthDBNPEEventCallback(IxNpeMhNpeId npeID, IxNpeMhMessage msg); + +/* NPE adaptor */ +IX_ETH_DB_PUBLIC void ixEthDBGetMacDatabaseCbk(IxNpeMhNpeId npeID, IxNpeMhMessage msg); +IX_ETH_DB_PUBLIC void ixEthDBNpeMsgAck(IxNpeMhNpeId npeID, IxNpeMhMessage msg); +IX_ETH_DB_PUBLIC void ixEthDBNPESyncScan(IxEthDBPortId portID, void *eltBaseAddress, UINT32 eltSize); +IX_ETH_DB_PUBLIC void ixEthDBNPETreeWrite(IxEthDBRecordType type, UINT32 totalSize, void *baseAddress, MacTreeNode *tree, UINT32 *blocks, UINT32 *startIndex); +IX_ETH_DB_PUBLIC void ixEthDBNPEGatewayNodeWrite(void *address, MacTreeNode *node); + +/* Other public API functions */ +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBStartLearningFunction(void); +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBStopLearningFunction(void); +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBPortUpdateEnableSet(IxEthDBPortId portID, BOOL enableUpdate); + +/* Maximum Tx/Rx public functions */ +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBFilteringPortMaximumRxFrameSizeSet(IxEthDBPortId portID, UINT32 maximumRxFrameSize); +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBFilteringPortMaximumTxFrameSizeSet(IxEthDBPortId portID, UINT32 maximumTxFrameSize); + +/* VLAN-related */ +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBPortVlanTableSet(IxEthDBPortId portID, IxEthDBVlanSet portVlanTable, IxEthDBVlanSet vlanSet); + +/* Record search */ +IX_ETH_DB_PUBLIC BOOL ixEthDBAddressRecordMatch(void *untypedReference, void *untypedEntry); +IX_ETH_DB_PUBLIC BOOL ixEthDBVlanRecordMatch(void *untypedReference, void *untypedEntry); +IX_ETH_DB_PUBLIC BOOL ixEthDBPortRecordMatch(void *untypedReference, void *untypedEntry); +IX_ETH_DB_PUBLIC BOOL ixEthDBNullMatch(void *reference, void *entry); +IX_ETH_DB_PUBLIC HashNode* ixEthDBPortSearch(IxEthDBMacAddr *macAddress, IxEthDBPortId portID, IxEthDBRecordType typeFilter); +IX_ETH_DB_PUBLIC HashNode* ixEthDBVlanSearch(IxEthDBMacAddr *macAddress, IxEthDBVlanId vlanID, IxEthDBRecordType typeFilter); + +/* Utilities */ +IX_ETH_DB_PUBLIC const char* mac2string(const unsigned char *mac); +IX_ETH_DB_PUBLIC void showHashInfo(void); +IX_ETH_DB_PUBLIC int ixEthDBAnalyzeHash(void); +IX_ETH_DB_PUBLIC const char* errorString(IxEthDBStatus error); +IX_ETH_DB_PUBLIC int numHashElements(void); +IX_ETH_DB_PUBLIC void zapHashtable(void); +IX_ETH_DB_PUBLIC BOOL ixEthDBCheckSingleBitValue(UINT32 value); + +/* Single Eth NPE Check */ +IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBSingleEthNpeCheck(IxEthDBPortId portId); + +#endif /* IxEthDB_p_H */ + diff --git a/cpu/ixp/npe/include/IxEthMii.h b/cpu/ixp/npe/include/IxEthMii.h new file mode 100644 index 0000000..a1bfe06 --- /dev/null +++ b/cpu/ixp/npe/include/IxEthMii.h @@ -0,0 +1,270 @@ +/** + * @file IxEthMii.h + * + * @brief this file contains the public API of @ref IxEthMii component + * + * Design notes : + * The main intent of this API is to inplement MII high level fonctionalitoes + * to support the codelets provided with the IXP400 software releases. It + * superceedes previous interfaces provided with @ref IxEThAcc component. + * + * This API has been tested with the PHYs provided with the + * IXP400 development platforms. It may not work for specific Ethernet PHYs + * used on specific boards. + * + * This source code detects and interface the LXT972, LXT973 and KS6995 + * Ethernet PHYs. + * + * This source code should be considered as an example which may need + * to be adapted for different hardware implementations. + * + * It is strongly recommended to use public domain and GPL utilities + * like libmii, mii-diag for MII interface support. + * + * + * + * @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 IxEthMii_H +#define IxEthMii_H + +#include + +/** + * @defgroup IxEthMii IXP400 Ethernet Phy Access (IxEthMii) API + * + * @brief ethMii is a library that does provides access to the + * Ethernet PHYs + * + *@{ + */ + +/** + * @ingroup IxEthMii + * + * @fn ixEthMiiPhyScan(BOOL phyPresent[], UINT32 maxPhyCount) + * + * @brief Scan the MDIO bus for PHYs + * This function scans PHY addresses 0 through 31, and sets phyPresent[n] to + * TRUE if a phy is discovered at address n. + * + * - Reentrant - no + * - ISR Callable - no + * + * @pre The MAC on Ethernet Port 2 (NPE C) must be initialised, and generating the MDIO clock. + * + * @param phyPresent BOOL [in] - boolean array of IXP425_ETH_ACC_MII_MAX_ADDR entries + * @param maxPhyCount UINT32 [in] - number of PHYs to search for (the scan will stop when + * the indicated number of PHYs is found). + * + * @return IX_STATUS + * - IX_ETH_ACC_SUCCESS + * - IX_ETH_ACC_FAIL : invalid arguments. + * + *
+ */ +PUBLIC IX_STATUS ixEthMiiPhyScan(BOOL phyPresent[], UINT32 maxPhyCount); + +/** + * @ingroup IxEthMii + * + * @fn ixEthMiiPhyConfig(UINT32 phyAddr, + BOOL speed100, + BOOL fullDuplex, + BOOL autonegotiate) + * + * + * @brief Configure a PHY + * Configure a PHY's speed, duplex and autonegotiation status + * + * - Reentrant - no + * - ISR Callable - no + * + * @pre The MAC on Ethernet Port 2 (NPE C) must be initialised, and generating the MDIO clock. + * + * @param phyAddr UINT32 [in] + * @param speed100 BOOL [in] - set to TRUE for 100Mbit/s operation, FALSE for 10Mbit/s + * @param fullDuplex BOOL [in] - set to TRUE for Full Duplex, FALSE for Half Duplex + * @param autonegotiate BOOL [in] - set to TRUE to enable autonegotiation + * + * @return IX_STATUS + * - IX_SUCCESS + * - IX_FAIL : invalid arguments. + * + *
+ */ +PUBLIC IX_STATUS ixEthMiiPhyConfig(UINT32 phyAddr, + BOOL speed100, + BOOL fullDuplex, + BOOL autonegotiate); + +/** + * @ingroup IxEthMii + * + * @fn ixEthMiiPhyLoopbackEnable(UINT32 phyAddr) + * + * + * @brief Enable PHY Loopback in a specific Eth MII port + * + * @note When PHY Loopback is enabled, frames sent out to the PHY from the + * IXP400 will be looped back to the IXP400. They will not be transmitted out + * on the wire. + * + * - Reentrant - no + * - ISR Callable - no + * + * @param phyAddr UINT32 [in] - the address of the Ethernet PHY (0-31) + * + * @return IX_STATUS + * - IX_SUCCESS + * - IX_FAIL : invalid arguments. + *
+ */ +PUBLIC IX_STATUS +ixEthMiiPhyLoopbackEnable (UINT32 phyAddr); + +/** + * @ingroup IxEthMii + * + * @fn ixEthMiiPhyLoopbackDisable(UINT32 phyAddr) + * + * + * @brief Disable PHY Loopback in a specific Eth MII port + * + * - Reentrant - no + * - ISR Callable - no + * + * @param phyAddr UINT32 [in] - the address of the Ethernet PHY (0-31) + * + * @return IX_STATUS + * - IX_SUCCESS + * - IX_FAIL : invalid arguments. + *
+ */ +PUBLIC IX_STATUS +ixEthMiiPhyLoopbackDisable (UINT32 phyAddr); + +/** + * @ingroup IxEthMii + * + * @fn ixEthMiiPhyReset(UINT32 phyAddr) + * + * @brief Reset a PHY + * Reset a PHY + * + * - Reentrant - no + * - ISR Callable - no + * + * @pre The MAC on Ethernet Port 2 (NPE C) must be initialised, and generating the MDIO clock. + * + * @param phyAddr UINT32 [in] - the address of the Ethernet PHY (0-31) + * + * @return IX_STATUS + * - IX_SUCCESS + * - IX_FAIL : invalid arguments. + * + *
+ */ +PUBLIC IX_STATUS ixEthMiiPhyReset(UINT32 phyAddr); + + +/** + * @ingroup IxEthMii + * + * @fn ixEthMiiLinkStatus(UINT32 phyAddr, + BOOL *linkUp, + BOOL *speed100, + BOOL *fullDuplex, + BOOL *autoneg) + * + * @brief Retrieve the current status of a PHY + * Retrieve the link, speed, duplex and autonegotiation status of a PHY + * + * - Reentrant - no + * - ISR Callable - no + * + * @pre The MAC on Ethernet Port 2 (NPE C) must be initialised, and generating the MDIO clock. + * + * @param phyAddr UINT32 [in] - the address of the Ethernet PHY (0-31) + * @param linkUp BOOL [out] - set to TRUE if the link is up + * @param speed100 BOOL [out] - set to TRUE indicates 100Mbit/s, FALSE indicates 10Mbit/s + * @param fullDuplex BOOL [out] - set to TRUE indicates Full Duplex, FALSE indicates Half Duplex + * @param autoneg BOOL [out] - set to TRUE indicates autonegotiation is enabled, FALSE indicates autonegotiation is disabled + * + * @return IX_STATUS + * - IX_SUCCESS + * - IX_FAIL : invalid arguments. + * + *
+ */ +PUBLIC IX_STATUS ixEthMiiLinkStatus(UINT32 phyAddr, + BOOL *linkUp, + BOOL *speed100, + BOOL *fullDuplex, + BOOL *autoneg); + +/** + * @ingroup IxEthMii + * + * @fn ixEthMiiPhyShow (UINT32 phyAddr) + * + * + * @brief Display information on a specified PHY + * Display link status, speed, duplex and Auto Negotiation status + * + * - Reentrant - no + * - ISR Callable - no + * + * @pre The MAC on Ethernet Port 2 (NPE C) must be initialised, and generating the MDIO clock. + * + * @param phyAddr UINT32 [in] - the address of the Ethernet PHY (0-31) + * + * @return IX_STATUS + * - IX_SUCCESS + * - IX_FAIL : invalid arguments. + * + *
+ */ +PUBLIC IX_STATUS ixEthMiiPhyShow (UINT32 phyAddr); + +#endif /* ndef IxEthMii_H */ +/** + *@} + */ diff --git a/cpu/ixp/npe/include/IxEthMii_p.h b/cpu/ixp/npe/include/IxEthMii_p.h new file mode 100644 index 0000000..104b65c --- /dev/null +++ b/cpu/ixp/npe/include/IxEthMii_p.h @@ -0,0 +1,185 @@ +/** + * @file IxEthMii_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 IxEthMii_p_H +#define IxEthMii_p_H + + +/* MII definitions - these have been verified against the LXT971 and + LXT972 PHYs*/ + +#define IX_ETH_MII_MAX_REG_NUM 0x20 /* max number of registers */ + +#define IX_ETH_MII_CTRL_REG 0x0 /* Control Register */ +#define IX_ETH_MII_STAT_REG 0x1 /* Status Register */ +#define IX_ETH_MII_PHY_ID1_REG 0x2 /* PHY identifier 1 Register */ +#define IX_ETH_MII_PHY_ID2_REG 0x3 /* PHY identifier 2 Register */ +#define IX_ETH_MII_AN_ADS_REG 0x4 /* Auto-Negotiation */ + /* Advertisement Register */ +#define IX_ETH_MII_AN_PRTN_REG 0x5 /* Auto-Negotiation */ + /* partner ability Register */ +#define IX_ETH_MII_AN_EXP_REG 0x6 /* Auto-Negotiation */ + /* Expansion Register */ +#define IX_ETH_MII_AN_NEXT_REG 0x7 /* Auto-Negotiation */ + /* next-page transmit Register */ + +#define IX_ETH_MII_STAT2_REG 0x11 /* Status Register 2*/ + + +/* MII control register bit */ + +#define IX_ETH_MII_CR_COLL_TEST 0x0080 /* collision test */ +#define IX_ETH_MII_CR_FDX 0x0100 /* FDX =1, half duplex =0 */ +#define IX_ETH_MII_CR_RESTART 0x0200 /* restart auto negotiation */ +#define IX_ETH_MII_CR_ISOLATE 0x0400 /* isolate PHY from MII */ +#define IX_ETH_MII_CR_POWER_DOWN 0x0800 /* power down */ +#define IX_ETH_MII_CR_AUTO_EN 0x1000 /* auto-negotiation enable */ +#define IX_ETH_MII_CR_100 0x2000 /* 0 = 10mb, 1 = 100mb */ +#define IX_ETH_MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */ +#define IX_ETH_MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */ +#define IX_ETH_MII_CR_NORM_EN 0x0000 /* just enable the PHY */ +#define IX_ETH_MII_CR_DEF_0_MASK 0xca7f /* they must return zero */ +#define IX_ETH_MII_CR_RES_MASK 0x007f /* reserved bits, return zero */ + +/* MII Status register bit definitions */ + +#define IX_ETH_MII_SR_LINK_STATUS 0x0004 /* link Status -- 1 = link */ +#define IX_ETH_MII_SR_AUTO_SEL 0x0008 /* auto speed select capable */ +#define IX_ETH_MII_SR_REMOTE_FAULT 0x0010 /* Remote fault detect */ +#define IX_ETH_MII_SR_AUTO_NEG 0x0020 /* auto negotiation complete */ +#define IX_ETH_MII_SR_10T_HALF_DPX 0x0800 /* 10BaseT HD capable */ +#define IX_ETH_MII_SR_10T_FULL_DPX 0x1000 /* 10BaseT FD capable */ +#define IX_ETH_MII_SR_TX_HALF_DPX 0x2000 /* TX HD capable */ +#define IX_ETH_MII_SR_TX_FULL_DPX 0x4000 /* TX FD capable */ +#define IX_ETH_MII_SR_T4 0x8000 /* T4 capable */ +#define IX_ETH_MII_SR_ABIL_MASK 0xff80 /* abilities mask */ +#define IX_ETH_MII_SR_EXT_CAP 0x0001 /* extended capabilities */ + + +/* LXT971/2 Status 2 register bit definitions */ +#define IX_ETH_MII_SR2_100 0x4000 +#define IX_ETH_MII_SR2_TX 0x2000 +#define IX_ETH_MII_SR2_RX 0x1000 +#define IX_ETH_MII_SR2_COL 0x0800 +#define IX_ETH_MII_SR2_LINK 0x0400 +#define IX_ETH_MII_SR2_FD 0x0200 +#define IX_ETH_MII_SR2_AUTO 0x0100 +#define IX_ETH_MII_SR2_AUTO_CMPLT 0x0080 +#define IX_ETH_MII_SR2_POLARITY 0x0020 +#define IX_ETH_MII_SR2_PAUSE 0x0010 +#define IX_ETH_MII_SR2_ERROR 0x0008 + +/* MII Link Code word bit definitions */ + +#define IX_ETH_MII_BP_FAULT 0x2000 /* remote fault */ +#define IX_ETH_MII_BP_ACK 0x4000 /* acknowledge */ +#define IX_ETH_MII_BP_NP 0x8000 /* nexp page is supported */ + +/* MII Next Page bit definitions */ + +#define IX_ETH_MII_NP_TOGGLE 0x0800 /* toggle bit */ +#define IX_ETH_MII_NP_ACK2 0x1000 /* acknowledge two */ +#define IX_ETH_MII_NP_MSG 0x2000 /* message page */ +#define IX_ETH_MII_NP_ACK1 0x4000 /* acknowledge one */ +#define IX_ETH_MII_NP_NP 0x8000 /* nexp page will follow */ + +/* MII Expansion Register bit definitions */ + +#define IX_ETH_MII_EXP_FAULT 0x0010 /* parallel detection fault */ +#define IX_ETH_MII_EXP_PRTN_NP 0x0008 /* link partner next-page able */ +#define IX_ETH_MII_EXP_LOC_NP 0x0004 /* local PHY next-page able */ +#define IX_ETH_MII_EXP_PR 0x0002 /* full page received */ +#define IX_ETH_MII_EXP_PRT_AN 0x0001 /* link partner auto neg able */ + +/* technology ability field bit definitions */ + +#define IX_ETH_MII_TECH_10BASE_T 0x0020 /* 10Base-T */ +#define IX_ETH_MII_TECH_10BASE_FD 0x0040 /* 10Base-T Full Duplex */ +#define IX_ETH_MII_TECH_100BASE_TX 0x0080 /* 100Base-TX */ +#define IX_ETH_MII_TECH_100BASE_TX_FD 0x0100 /* 100Base-TX Full Duplex */ + +#define IX_ETH_MII_TECH_100BASE_T4 0x0200 /* 100Base-T4 */ +#define IX_ETH_MII_ADS_TECH_MASK 0x1fe0 /* technology abilities mask */ +#define IX_ETH_MII_TECH_MASK IX_ETH_MII_ADS_TECH_MASK +#define IX_ETH_MII_ADS_SEL_MASK 0x001f /* selector field mask */ + +#define IX_ETH_MII_AN_FAIL 0x10 /* auto-negotiation fail */ +#define IX_ETH_MII_STAT_FAIL 0x20 /* errors in the status register */ +#define IX_ETH_MII_PHY_NO_ABLE 0x40 /* the PHY lacks some abilities */ + +/* Definitions for MII access routines*/ + +#define IX_ETH_MII_GO BIT(31) +#define IX_ETH_MII_WRITE BIT(26) +#define IX_ETH_MII_TIMEOUT_10TH_SECS (5) +#define IX_ETH_MII_10TH_SEC_IN_MILLIS (100) +#define IX_ETH_MII_READ_FAIL BIT(31) + +/* When we reset the PHY we delay for 2 seconds to allow the reset to + complete*/ +#define IX_ETH_MII_RESET_DELAY_MS (2000) +#define IX_ETH_MII_RESET_POLL_MS (50) + +#define IX_ETH_MII_REG_SHL 16 +#define IX_ETH_MII_ADDR_SHL 21 + +/* supported PHYs */ +#define IX_ETH_MII_LXT971_PHY_ID 0x001378E0 +#define IX_ETH_MII_LXT972_PHY_ID 0x001378E2 +#define IX_ETH_MII_LXT973_PHY_ID 0x00137A10 +#define IX_ETH_MII_LXT973A3_PHY_ID 0x00137A11 +#define IX_ETH_MII_KS8995_PHY_ID 0x00221450 +#define IX_ETH_MII_LXT9785_PHY_ID 0x001378FF + + +#define IX_ETH_MII_INVALID_PHY_ID 0x00000000 +#define IX_ETH_MII_UNKNOWN_PHY_ID 0xffffffff + +#endif /*IxEthAccMii_p_H*/ diff --git a/cpu/ixp/npe/include/IxEthNpe.h b/cpu/ixp/npe/include/IxEthNpe.h new file mode 100644 index 0000000..21bdedc --- /dev/null +++ b/cpu/ixp/npe/include/IxEthNpe.h @@ -0,0 +1,695 @@ +#ifndef __doxygen_HIDE /* This file is not part of the API */ + +/** + * @file IxEthNpe.h + * + * @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 IxEthNpe IXP400 Ethernet NPE (IxEthNpe) API + * + * @brief Contains the API for Ethernet NPE. + * + * All messages given to NPE, get back an acknowledgment. The acknowledgment + * is identical to the message sent to the NPE (except for NPE_GETSTATUS message). + * + * @{ + */ + + +/*-------------------------------------------------------------------------- + * APB Message IDs - XScale->NPE + *------------------------------------------------------------------------*/ + +/** + * @def IX_ETHNPE_NPE_GETSTATUS + * + * @brief Request from the XScale client for the NPE to return the firmware + * version of the currently executing image. + * + * Acknowledgment message id is same as the request message id. + * NPE returns the firmware version ID to XScale. + */ +#define IX_ETHNPE_NPE_GETSTATUS 0x00 + +/** + * @def IX_ETHNPE_EDB_SETPORTADDRESS + * + * @brief Request from the XScale client for the NPE to set the Ethernet + * port's port ID and MAC address. + */ +#define IX_ETHNPE_EDB_SETPORTADDRESS 0x01 + +/** + * @def IX_ETHNPE_EDB_GETMACADDRESSDATABASE + * + * @brief Request from XScale client to the NPE requesting upload of + * Ethernet Filtering Database or Header Conversion Database from NPE's + * data memory to XScale accessible SDRAM. + */ +#define IX_ETHNPE_EDB_GETMACADDRESSDATABASE 0x02 + +/** + * @def IX_ETHNPE_EDB_SETMACADDRESSSDATABASE + * + * @brief Request from XScale client to the NPE requesting download of + * Ethernet Filtering Database or Header Conversion Database from SDRAM + * to the NPE's datamemory. + */ +#define IX_ETHNPE_EDB_SETMACADDRESSSDATABASE 0x03 + +/** + * @def IX_ETHNPE_GETSTATS + * + * @brief Request from the XScale client for the current MAC port statistics + * data to be written to the (empty) statistics structure and the specified + * location in externa memory. + */ +#define IX_ETHNPE_GETSTATS 0x04 + +/** + * @def IX_ETHNPE_RESETSTATS + * + * @brief Request from the XScale client to the NPE to reset all of its internal + * MAC port statistics state variables. + * + * As a side effect, this message entails an implicit request that the NPE + * write the current MAC port statistics into the MAC statistics structure + * at the specified location in external memory. + */ +#define IX_ETHNPE_RESETSTATS 0x05 + +/** + * @def IX_ETHNPE_SETMAXFRAMELENGTHS + * + * @brief Request from the XScale client to the NPE to configure maximum framelengths + * and block sizes in receive and transmit direction. + */ +#define IX_ETHNPE_SETMAXFRAMELENGTHS 0x06 + +/** + * @def IX_ETHNPE_VLAN_SETRXTAGMODE + * + * @brief Request from the XScale client to the NPE to configure VLAN frame type + * filtering and VLAN the tagging mode for the receiver. + */ +#define IX_ETHNPE_VLAN_SETRXTAGMODE 0x07 + +/** + * @def IX_ETHNPE_VLAN_SETDEFAULTRXVID + * + * @brief Request from the XScale client to the NPE to set receiver's default + * VLAN tag (PVID)and internal traffic class. + */ +#define IX_ETHNPE_VLAN_SETDEFAULTRXVID 0x08 + +/** + * @def IX_ETHNPE_VLAN_SETPORTVLANTABLEENTRY + * + * @brief Request from the XScale client to the NPE to configure VLAN Port + * membership and Tx tagging for 8 consecutive VLANID's. + */ +#define IX_ETHNPE_VLAN_SETPORTVLANTABLEENTRY 0x09 + +/** + * @def IX_ETHNPE_VLAN_SETPORTVLANTABLERANGE + * + * @brief Request from the XScale client to the NPE to configure VLAN Port + * membership and Tx tagging for a range of VLANID's. + */ +#define IX_ETHNPE_VLAN_SETPORTVLANTABLERANGE 0x0A + +/** + * @def IX_ETHNPE_VLAN_SETRXQOSENTRY + * + * @brief Request from the XScale client to the NPE to map a user priority + * to QoS class and an AQM queue number. + */ +#define IX_ETHNPE_VLAN_SETRXQOSENTRY 0x0B + +/** + * @def IX_ETHNPE_VLAN_SETPORTIDEXTRACTIONMODE + * + * @brief Request from the XScale client to the NPE to enable or disable + * portID extraction from VLAN-tagged frames for the specified port. + */ +#define IX_ETHNPE_VLAN_SETPORTIDEXTRACTIONMODE 0x0C + +/** + * @def IX_ETHNPE_STP_SETBLOCKINGSTATE + * + * @brief Request from the XScale client to the NPE to block or unblock + * forwarding for spanning tree BPDUs. + */ +#define IX_ETHNPE_STP_SETBLOCKINGSTATE 0x0D + +/** + * @def IX_ETHNPE_FW_SETFIREWALLMODE + * + * @brief Request from the XScale client to the NPE to configure firewall + * services modes of operation and/or download Ethernet Firewall Database from + * SDRAM to NPE. + */ +#define IX_ETHNPE_FW_SETFIREWALLMODE 0x0E + +/** + * @def IX_ETHNPE_PC_SETFRAMECONTROLDURATIONID + * + * @brief Request from the XScale client to the NPE to set global frame control + * and duration/ID field for the 802.3 to 802.11 protocol header conversion + * service. + */ +#define IX_ETHNPE_PC_SETFRAMECONTROLDURATIONID 0x0F + +/** + * @def IX_ETHNPE_PC_SETBBSID + * + * @brief Request from the XScale client to the NPE to set global BBSID field + * value for the 802.3 to 802.11 protocol header conversion service. + */ +#define IX_ETHNPE_PC_SETBBSID 0x10 + +/** + * @def IX_ETHNPE_PC_SETAPMACTABLE + * + * @brief Request from the XScale client to the NPE to update a block/section/ + * range of the AP MAC Address Table. + */ +#define IX_ETHNPE_PC_SETAPMACTABLE 0x11 + +/** + * @def IX_ETHNPE_SETLOOPBACK_MODE + * + * @brief Turn on or off the NPE frame loopback. + */ +#define IX_ETHNPE_SETLOOPBACK_MODE (0x12) + +/*-------------------------------------------------------------------------- + * APB Message IDs - NPE->XScale + *------------------------------------------------------------------------*/ + +/** + * @def IX_ETHNPE_NPE_GETSTATUS_ACK + * + * @brief Acknowledgment to IX_ETHNPE_NPE_GETSTATUS message. NPE firmware version + * id is returned in the message. + */ +#define IX_ETHNPE_NPE_GETSTATUS_ACK 0x00 + +/** + * @def IX_ETHNPE_EDB_SETPORTADDRESS_ACK + * + * @brief Acknowledgment to IX_ETHNPE_EDB_SETPORTADDRESS message. + */ +#define IX_ETHNPE_EDB_SETPORTADDRESS_ACK 0x01 + +/** + * @def IX_ETHNPE_EDB_GETMACADDRESSDATABASE_ACK + * + * @brief Acknowledgment to IX_ETHNPE_EDB_GETMACADDRESSDATABASE message + */ +#define IX_ETHNPE_EDB_GETMACADDRESSDATABASE_ACK 0x02 + +/** + * @def IX_ETHNPE_EDB_SETMACADDRESSSDATABASE_ACK + * + * @brief Acknowledgment to IX_ETHNPE_EDB_SETMACADDRESSSDATABASE message. + */ +#define IX_ETHNPE_EDB_SETMACADDRESSSDATABASE_ACK 0x03 + +/** + * @def IX_ETHNPE_GETSTATS_ACK + * + * @brief Acknowledgment to IX_ETHNPE_GETSTATS message. + */ +#define IX_ETHNPE_GETSTATS_ACK 0x04 + +/** + * @def IX_ETHNPE_RESETSTATS_ACK + * + * @brief Acknowledgment to IX_ETHNPE_RESETSTATS message. + */ +#define IX_ETHNPE_RESETSTATS_ACK 0x05 + +/** + * @def IX_ETHNPE_SETMAXFRAMELENGTHS_ACK + * + * @brief Acknowledgment to IX_ETHNPE_SETMAXFRAMELENGTHS message. + */ +#define IX_ETHNPE_SETMAXFRAMELENGTHS_ACK 0x06 + +/** + * @def IX_ETHNPE_VLAN_SETRXTAGMODE_ACK + * + * @brief Acknowledgment to IX_ETHNPE_VLAN_SETRXTAGMODE message. + */ +#define IX_ETHNPE_VLAN_SETRXTAGMODE_ACK 0x07 + +/** + * @def IX_ETHNPE_VLAN_SETDEFAULTRXVID_ACK + * + * @brief Acknowledgment to IX_ETHNPE_VLAN_SETDEFAULTRXVID message. + */ +#define IX_ETHNPE_VLAN_SETDEFAULTRXVID_ACK 0x08 + +/** + * @def IX_ETHNPE_VLAN_SETPORTVLANTABLEENTRY_ACK + * + * @brief Acknowledgment to IX_ETHNPE_VLAN_SETPORTVLANTABLEENTRY message. + */ +#define IX_ETHNPE_VLAN_SETPORTVLANTABLEENTRY_ACK 0x09 + +/** + * @def IX_ETHNPE_VLAN_SETPORTVLANTABLERANGE_ACK + * + * @brief Acknowledgment to IX_ETHNPE_VLAN_SETPORTVLANTABLERANGE message. + */ +#define IX_ETHNPE_VLAN_SETPORTVLANTABLERANGE_ACK 0x0A + +/** + * @def IX_ETHNPE_VLAN_SETRXQOSENTRY_ACK + * + * @brief Acknowledgment to IX_ETHNPE_VLAN_SETRXQOSENTRY message. + */ +#define IX_ETHNPE_VLAN_SETRXQOSENTRY_ACK 0x0B + +/** + * @def IX_ETHNPE_VLAN_SETPORTIDEXTRACTIONMODE_ACK + * + * @brief Acknowledgment to IX_ETHNPE_VLAN_SETPORTIDEXTRACTIONMODE message. + */ +#define IX_ETHNPE_VLAN_SETPORTIDEXTRACTIONMODE_ACK 0x0C + +/** + * @def IX_ETHNPE_STP_SETBLOCKINGSTATE_ACK + * + * @brief Acknowledgment to IX_ETHNPE_STP_SETBLOCKINGSTATE message. + */ +#define IX_ETHNPE_STP_SETBLOCKINGSTATE_ACK 0x0D + +/** + * @def IX_ETHNPE_FW_SETFIREWALLMODE_ACK + * + * @brief Acknowledgment to IX_ETHNPE_FW_SETFIREWALLMODE message. + */ +#define IX_ETHNPE_FW_SETFIREWALLMODE_ACK 0x0E + +/** + * @def IX_ETHNPE_PC_SETFRAMECONTROLDURATIONID_ACK + * + * @brief Acknowledgment to IX_ETHNPE_PC_SETFRAMECONTROLDURATIONID message. + */ +#define IX_ETHNPE_PC_SETFRAMECONTROLDURATIONID_ACK 0x0F + +/** + * @def IX_ETHNPE_PC_SETBBSID_ACK + * + * @brief Acknowledgment to IX_ETHNPE_PC_SETBBSID message. + */ +#define IX_ETHNPE_PC_SETBBSID_ACK 0x10 + +/** + * @def IX_ETHNPE_PC_SETAPMACTABLE_ACK + * + * @brief Acknowledgment to IX_ETHNPE_PC_SETAPMACTABLE message. + */ +#define IX_ETHNPE_PC_SETAPMACTABLE_ACK 0x11 + +/** + * @def IX_ETHNPE_SETLOOPBACK_MODE_ACK + * + * @brief Acknowledgment to IX_ETHNPE_SETLOOPBACK_MODE message. + */ +#define IX_ETHNPE_SETLOOPBACK_MODE_ACK (0x12) + +/*-------------------------------------------------------------------------- + * Queue Manager Queue entry bit field boundary definitions + *------------------------------------------------------------------------*/ + +/** + * @def MASK(hi,lo) + * + * @brief Macro for mask + */ +#define MASK(hi,lo) (((1 << (1 + ((hi) - (lo)))) - 1) << (lo)) + +/** + * @def BITS(x,hi,lo) + * + * @brief Macro for bits + */ +#define BITS(x,hi,lo) (((x) & MASK(hi,lo)) >> (lo)) + +/** + * @def IX_ETHNPE_QM_Q_RXENET_LENGTH_MASK + * + * @brief QMgr Queue LENGTH field mask + */ +#define IX_ETHNPE_QM_Q_RXENET_LENGTH_MASK 0x3fff + +/** + * @def IX_ETHNPE_QM_Q_FIELD_FLAG_R + * + * @brief QMgr Queue FLAG field right boundary + */ +#define IX_ETHNPE_QM_Q_FIELD_FLAG_R 20 + +/** + * @def IX_ETHNPE_QM_Q_FIELD_FLAG_MASK + * + * @brief QMgr Queue FLAG field mask + * + * Multicast bit : BIT(4) + * Broadcast bit : BIT(5) + * IP bit : BIT(6) (linux only) + * + */ +#ifdef __vxworks +#define IX_ETHNPE_QM_Q_FIELD_FLAG_MASK 0x30 +#else +#define IX_ETHNPE_QM_Q_FIELD_FLAG_MASK 0x70 +#endif + + +/** + * @def IX_ETHNPE_QM_Q_FIELD_NPEID_L + * + * @brief QMgr Queue NPE ID field left boundary + */ +#define IX_ETHNPE_QM_Q_FIELD_NPEID_L 1 + +/** + * @def IX_ETHNPE_QM_Q_FIELD_NPEID_R + * + * @brief QMgr Queue NPE ID field right boundary + */ +#define IX_ETHNPE_QM_Q_FIELD_NPEID_R 0 + +/** + * @def IX_ETHNPE_QM_Q_FIELD_PRIOR_L + * + * @brief QMgr Queue Priority field left boundary + */ +#define IX_ETHNPE_QM_Q_FIELD_PRIOR_L 2 + +/** + * @def IX_ETHNPE_QM_Q_FIELD_PRIOR_R + * + * @brief QMgr Queue Priority field right boundary + */ +#define IX_ETHNPE_QM_Q_FIELD_PRIOR_R 0 + +/** + * @def IX_ETHNPE_QM_Q_FIELD_ADDR_L + * + * @brief QMgr Queue Address field left boundary + */ +#define IX_ETHNPE_QM_Q_FIELD_ADDR_L 31 + +/** + * @def IX_ETHNPE_QM_Q_FIELD_ADDR_R + * + * @brief QMgr Queue Address field right boundary + */ +#define IX_ETHNPE_QM_Q_FIELD_ADDR_R 5 + +/*-------------------------------------------------------------------------- + * Queue Manager Queue entry bit field masks + *------------------------------------------------------------------------*/ + +/** + * @def IX_ETHNPE_QM_Q_FREEENET_ADDR_MASK + * + * @brief Macro to mask the Address field of the FreeEnet Queue Manager Entry + */ +#define IX_ETHNPE_QM_Q_FREEENET_ADDR_MASK \ + MASK (IX_ETHNPE_QM_Q_FIELD_ADDR_L, \ + IX_ETHNPE_QM_Q_FIELD_ADDR_R) + +/** + * @def IX_ETHNPE_QM_Q_RXENET_NPEID_MASK + * + * @brief Macro to mask the NPE ID field of the RxEnet Queue Manager Entry + */ +#define IX_ETHNPE_QM_Q_RXENET_NPEID_MASK \ + MASK (IX_ETHNPE_QM_Q_FIELD_NPEID_L, \ + IX_ETHNPE_QM_Q_FIELD_NPEID_R) + +/** + * @def IX_ETHNPE_QM_Q_RXENET_ADDR_MASK + * + * @brief Macro to mask the Mbuf Address field of the RxEnet Queue Manager Entry + */ +#define IX_ETHNPE_QM_Q_RXENET_ADDR_MASK \ + MASK (IX_ETHNPE_QM_Q_FIELD_ADDR_L, \ + IX_ETHNPE_QM_Q_FIELD_ADDR_R) + +/** + * @def IX_ETHNPE_QM_Q_TXENET_PRIOR_MASK + * + * @brief Macro to mask the Priority field of the TxEnet Queue Manager Entry + */ +#define IX_ETHNPE_QM_Q_TXENET_PRIOR_MASK \ + MASK (IX_ETHNPE_QM_Q_FIELD_PRIOR_L, \ + IX_ETHNPE_QM_Q_FIELD_PRIOR_R) + +/** + * @def IX_ETHNPE_QM_Q_TXENET_ADDR_MASK + * + * @brief Macro to mask the Mbuf Address field of the TxEnet Queue Manager Entry + */ +#define IX_ETHNPE_QM_Q_TXENET_ADDR_MASK \ + MASK (IX_ETHNPE_QM_Q_FIELD_ADDR_L, \ + IX_ETHNPE_QM_Q_FIELD_ADDR_R) + +/** + * @def IX_ETHNPE_QM_Q_TXENETDONE_NPEID_MASK + * + * @brief Macro to mask the NPE ID field of the TxEnetDone Queue Manager Entry + */ +#define IX_ETHNPE_QM_Q_TXENETDONE_NPEID_MASK \ + MASK (IX_ETHNPE_QM_Q_FIELD_NPEID_L, \ + IX_ETHNPE_QM_Q_FIELD_NPEID_R) + +/** + * @def IX_ETHNPE_QM_Q_TXENETDONE_ADDR_MASK + * + * @brief Macro to mask the Mbuf Address field of the TxEnetDone Queue Manager + * Entry + */ +#define IX_ETHNPE_QM_Q_TXENETDONE_ADDR_MASK \ + MASK (IX_ETHNPE_QM_Q_FIELD_ADDR_L, \ + IX_ETHNPE_QM_Q_FIELD_ADDR_R) + +/*-------------------------------------------------------------------------- + * Queue Manager Queue entry bit field value extraction macros + *------------------------------------------------------------------------*/ + +/** + * @def IX_ETHNPE_QM_Q_FREEENET_ADDR_VAL(x) + * + * @brief Extraction macro for Address field of FreeNet Queue Manager Entry + * + * Pointer to an mbuf buffer descriptor + */ +#define IX_ETHNPE_QM_Q_FREEENET_ADDR_VAL(x) \ + ((x) & IX_ETHNPE_QM_Q_FREEENET_ADDR_MASK) + +/** + * @def IX_ETHNPE_QM_Q_RXENET_NPEID_VAL(x) + * + * @brief Extraction macro for NPE ID field of RxEnet Queue Manager Entry + * + * Set to 0 for entries originating from the Eth0 NPE; + * Set to 1 for entries originating from the Eth1 NPE. + */ +#define IX_ETHNPE_QM_Q_RXENET_NPEID_VAL(x) \ + BITS (x, IX_ETHNPE_QM_Q_FIELD_NPEID_L, \ + IX_ETHNPE_QM_Q_FIELD_NPEID_R) + +/** + * @def IX_ETHNPE_QM_Q_RXENET_PORTID_VAL(x) + * + * @brief Extraction macro for Port ID field of RxEnet Queue Manager Entry + * + * 0-5: Assignable (by the XScale client) to any of the physical ports. + * 6: It is reserved + * 7: Indication that the NPE did not find the associated frame's destination MAC address within + * its internal filtering database. + */ +#define IX_ETHNPE_QM_Q_RXENET_PORTID_VAL(x) \ + BITS (x, IX_ETHNPE_QM_Q_FIELD_PORTID_L, \ + IX_ETHNPE_QM_Q_Field_PortID_R) + +/** + * @def IX_ETHNPE_QM_Q_RXENET_ADDR_VAL(x) + * + * @brief Extraction macro for Address field of RxEnet Queue Manager Entry + * + * Pointer to an mbuf buffer descriptor + */ +#define IX_ETHNPE_QM_Q_RXENET_ADDR_VAL(x) \ + ((x) & IX_ETHNPE_QM_Q_RXENET_ADDR_MASK) + +/** + * @def IX_ETHNPE_QM_Q_TXENET_PRIOR_VAL(x) + * + * @brief Extraction macro for Priority field of TxEnet Queue Manager Entry + * + * Priority of the packet (as described in IEEE 802.1D). This field is + * cleared upon return from the Ethernet NPE to the TxEnetDone queue. + */ +#define IX_ETHNPE_QM_Q_TXENET_PRIOR_VAL(x) \ + BITS (x, IX_ETHNPE_QM_Q_FIELD_PRIOR_L, \ + IX_ETHNPE_QM_Q_FIELD_PRIOR_R) + +/** + * @def IX_ETHNPE_QM_Q_TXENET_ADDR_VAL(x) + * + * @brief Extraction macro for Address field of Queue Manager TxEnet Queue + * Manager Entry + * + * Pointer to an mbuf buffer descriptor + */ +#define IX_ETHNPE_QM_Q_TXENET_ADDR_VAL(x) \ + ((x) & IX_ETHNPE_QM_Q_TXENET_ADDR_MASK) + +/** + * @def IX_ETHNPE_QM_Q_TXENETDONE_NPEID_VAL(x) + * + * @brief Extraction macro for NPE ID field of TxEnetDone Queue Manager Entry + * + * Set to 0 for entries originating from the Eth0 NPE; set to 1 for en-tries + * originating from the Eth1 NPE. + */ +#define IX_ETHNPE_QM_Q_TXENETDONE_NPEID_VAL(x) \ + BITS (x, IX_ETHNPE_QM_Q_FIELD_NPEID_L, \ + IX_ETHNPE_QM_Q_FIELD_NPEID_R) + +/** + * @def IX_ETHNPE_QM_Q_TXENETDONE_ADDR_VAL(x) + * + * @brief Extraction macro for Address field of TxEnetDone Queue Manager Entry + * + * Pointer to an mbuf buffer descriptor + */ +#define IX_ETHNPE_QM_Q_TXENETDONE_ADDR_VAL(x) \ + ((x) & IX_ETHNPE_QM_Q_TXENETDONE_ADDR_MASK) + + +/*-------------------------------------------------------------------------- + * NPE limits + *------------------------------------------------------------------------*/ + +/** + * @def IX_ETHNPE_ACC_RXFREE_BUFFER_LENGTH_MIN + * + * @brief Macro to check the minimum length of a rx free buffer + */ +#define IX_ETHNPE_ACC_RXFREE_BUFFER_LENGTH_MIN (64) + +/** + * @def IX_ETHNPE_ACC_RXFREE_BUFFER_LENGTH_MASK + * + * @brief Mask to apply to the mbuf length before submitting it to the NPE + * (the NPE handles only rx free mbufs which are multiple of 64) + * + * @sa IX_ETHNPE_ACC_RXFREE_BUFFER_LENGTH_MASK + */ +#define IX_ETHNPE_ACC_RXFREE_BUFFER_LENGTH_MASK (~63) + +/** + * @def IX_ETHNPE_ACC_RXFREE_BUFFER_ROUND_UP(size) + * + * @brief Round up to get the size necessary to receive without chaining + * the frames which are (size) bytes (the NPE operates by multiple of 64) + * e.g. To receive 1514 bytes frames, the size of the buffers in replenish + * has to be at least (1514+63)&(~63) = 1536 bytes. + * + */ +#define IX_ETHNPE_ACC_RXFREE_BUFFER_ROUND_UP(size) (((size) + 63) & ~63) + +/** + * @def IX_ETHNPE_ACC_RXFREE_BUFFER_ROUND_DOWN(size) + * + * @brief Round down to apply to the mbuf length before submitting + * it to the NPE. (the NPE operates by multiple of 64) + * + */ +#define IX_ETHNPE_ACC_RXFREE_BUFFER_ROUND_DOWN(size) ((size) & ~63) + +/** + * @def IX_ETHNPE_ACC_FRAME_LENGTH_MAX + * + * @brief maximum mbuf length supported by the NPE + * + * @sa IX_ETHNPE_ACC_FRAME_LENGTH_MAX + */ +#define IX_ETHNPE_ACC_FRAME_LENGTH_MAX (16320) + +/** + * @def IX_ETHNPE_ACC_FRAME_LENGTH_DEFAULT + * + * @brief default mbuf length supported by the NPE + * + * @sa IX_ETHNPE_ACC_FRAME_LENGTH_DEFAULT + */ +#define IX_ETHNPE_ACC_FRAME_LENGTH_DEFAULT (1522) + +/** + * @def IX_ETHNPE_ACC_LENGTH_OFFSET + * + * @brief Offset of the cluster length field in the word shared with the NPEs + */ +#define IX_ETHNPE_ACC_LENGTH_OFFSET 16 + +/** + * @def IX_ETHNPE_ACC_PKTLENGTH_MASK + * + * @brief Mask of the cluster length field in the word shared with the NPEs + */ +#define IX_ETHNPE_ACC_PKTLENGTH_MASK 0x3fff + + +/** + *@} + */ + +#endif /* __doxygen_HIDE */ diff --git a/cpu/ixp/npe/include/IxFeatureCtrl.h b/cpu/ixp/npe/include/IxFeatureCtrl.h new file mode 100644 index 0000000..dabc38e --- /dev/null +++ b/cpu/ixp/npe/include/IxFeatureCtrl.h @@ -0,0 +1,742 @@ +/** + * @file IxFeatureCtrl.h + * + * @date 30-Jan-2003 + + * @brief This file contains the public API of the IXP400 Feature Control + * 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 -- +*/ +/* ------------------------------------------------------ + Doxygen group definitions + ------------------------------------------------------ */ +/** + * @defgroup IxFeatureCtrlAPI IXP400 Feature Control (IxFeatureCtrl) API + * + * @brief The Public API for the IXP400 Feature Control. + * + * @{ + */ + +#ifndef IXFEATURECTRL_H +#define IXFEATURECTRL_H + +/* + * User defined include files + */ +#include "IxOsal.h" + +/* + * #defines and macros + */ + +/************************************************************* + * The following are IxFeatureCtrlComponentCheck return values. + ************************************************************/ + +/** + * @ingroup IxFeatureCtrlAPI + * + * @def IX_FEATURE_CTRL_COMPONENT_DISABLED + * + * @brief Hardware Component is disabled/unavailable. + * Return status by ixFeatureCtrlComponentCheck() + */ +#define IX_FEATURE_CTRL_COMPONENT_DISABLED 0 + +/** + * @ingroup IxFeatureCtrlAPI + * + * @def IX_FEATURE_CTRL_COMPONENT_ENABLED + * + * @brief Hardware Component is available. + * Return status by ixFeatureCtrlComponentCheck() + */ +#define IX_FEATURE_CTRL_COMPONENT_ENABLED 1 + +/*********************************************************************************** + * Product ID in XScale CP15 - Register 0 + * - It contains information on the maximum XScale Core Frequency and + * Silicon Stepping. + * - XScale Core Frequency Id indicates only the maximum XScale frequency + * achievable and not the running XScale frequency (maybe stepped down). + * - The register is read by using ixFeatureCtrlProductIdRead. + * - Usage example: + * productId = ixFeatureCtrlProductIdRead(); + * if( (productId & IX_FEATURE_CTRL_SILICON_STEPPING_MASK) == + * IX_FEATURE_CTRL_SILICON_TYPE_A0 ) + * if( (productId & IX_FEATURE_CTRL_XSCALE_FREQ_MASK) == + * IX_FEATURE_CTRL_XSCALE_FREQ_533 ) + * + * 31 28 27 24 23 20 19 16 15 12 11 9 8 4 3 0 + * -------------------------------------------------------------------------------- + * | 0x6 | 0x9 | 0x0 | 0x5 | 0x4 | Device ID | XScale Core Freq Id | Si Stepping Id | + * -------------------------------------------------------------------------------- + * + * Maximum Achievable XScale Core Frequency Id : 533MHz - 0x1C + * 400MHz - 0x1D + * 266MHz - 0x1F + * + * THE CORE FREQUENCY ID IS NOT APPLICABLE TO IXP46X <\b> + * + * The above is applicable to IXP42X only. CP15 in IXP46X does not contain any + * Frequency ID. + * + * Si Stepping Id : A - 0x0 + * B - 0x1 + * + * XScale Core freq Id - Device ID [11:9] : IXP42X - 0x0 + * IXP46X - 0x1 + *************************************************************************************/ + +/** + * @ingroup IxFeatureCtrlAPI + * + * @def IX_FEATURE_CTRL_SILICON_TYPE_A0 + * + * @brief This is the value of A0 Silicon in product ID. + */ +#define IX_FEATURE_CTRL_SILICON_TYPE_A0 0 + +/** + * @ingroup IxFeatureCtrlAPI + * + * @def IX_FEATURE_CTRL_SILICON_TYPE_B0 + * + * @brief This is the value of B0 Silicon in product ID. + */ +#define IX_FEATURE_CTRL_SILICON_TYPE_B0 1 + +/** + * @ingroup IxFeatureCtrlAPI + * + * @def IX_FEATURE_CTRL_SILICON_STEPPING_MASK + * + * @brief This is the mask of silicon stepping in product ID. + */ +#define IX_FEATURE_CTRL_SILICON_STEPPING_MASK 0xF + +/** + * @ingroup IxFeatureCtrlAPI + * + * @def IX_FEATURE_CTRL_DEVICE_TYPE_MASK + * + * @brief This is the mask of silicon stepping in product ID. + */ +#define IX_FEATURE_CTRL_DEVICE_TYPE_MASK (0x7) + +/** + * @ingroup IxFeatureCtrlAPI + * + * @def IX_FEATURE_CTRL_DEVICE_TYPE_OFFSET + * + * @brief This is the mask of silicon stepping in product ID. + */ +#define IX_FEATURE_CTRL_DEVICE_TYPE_OFFSET 9 + + +/** + * @ingroup IxFeatureCtrlAPI + * + * @def IX_FEATURE_CTRL_XSCALE_FREQ_533 + * + * @brief This is the value of 533MHz XScale Core in product ID. + */ +#define IX_FEATURE_CTRL_XSCALE_FREQ_533 ((0x1C)<<4) + +/** + * @ingroup IxFeatureCtrlAPI + * + * @def IX_FEATURE_CTRL_XSCALE_FREQ_400 + * + * @brief This is the value of 400MHz XScale Core in product ID. + */ +#define IX_FEATURE_CTRL_XSCALE_FREQ_400 ((0x1D)<<4) + +/** + * @ingroup IxFeatureCtrlAPI + * + * @def IX_FEATURE_CTRL_XSCALE_FREQ_266 + * + * @brief This is the value of 266MHz XScale Core in product ID. + */ +#define IX_FEATURE_CTRL_XSCALE_FREQ_266 ((0x1F)<<4) + +/** + * @ingroup IxFeatureCtrlAPI + * + * @def IX_FEATURE_CTRL_XSCALE_FREQ_MASK + * + * @brief This is the mask of XScale Core in product ID. + */ +#define IX_FEATURE_CTRL_XSCALE_FREQ_MASK ((0xFF)<<4) + +/** + * @ingroup IxFeatureCtrlAPI + * + * @def IX_FEATURECTRL_REG_UTOPIA_32PHY + * + * @brief Maximum UTOPIA PHY available is 32. + * + */ +#define IX_FEATURECTRL_REG_UTOPIA_32PHY 0x0 + +/** + * @ingroup IxFeatureCtrlAPI + * + * @def IX_FEATURECTRL_REG_UTOPIA_16PHY + * + * @brief Maximum UTOPIA PHY available is 16. + * + */ +#define IX_FEATURECTRL_REG_UTOPIA_16PHY 0x1 + +/** + * @ingroup IxFeatureCtrlAPI + * + * @def IX_FEATURECTRL_REG_UTOPIA_8PHY + * + * @brief Maximum UTOPIA PHY available to is 8. + * + */ +#define IX_FEATURECTRL_REG_UTOPIA_8PHY 0x2 + +/** + * @ingroup IxFeatureCtrlAPI + * + * @def IX_FEATURECTRL_REG_UTOPIA_4PHY + * + * @brief Maximum UTOPIA PHY available to is 4. + * + */ +#define IX_FEATURECTRL_REG_UTOPIA_4PHY 0x3 + +#ifdef __ixp46X + +/** + * @ingroup IxFeatureCtrlAPI + * + * @def IX_FEATURECTRL_REG_XSCALE_533FREQ + * + * @brief Maximum frequency available to IXP46x is 533 MHz. + * + */ +#define IX_FEATURECTRL_REG_XSCALE_533FREQ 0x0 + +/** + * @ingroup IxFeatureCtrlAPI + * + * @def IX_FEATURECTRL_REG_XSCALE_667FREQ + * + * @brief Maximum frequency available to IXP46x is 667 MHz. + * + */ +#define IX_FEATURECTRL_REG_XSCALE_667FREQ 0x1 + +/** + * @ingroup IxFeatureCtrlAPI + * + * @def IX_FEATURECTRL_REG_XSCALE_400FREQ + * + * @brief Maximum frequency available to IXP46x is 400 MHz. + * + */ +#define IX_FEATURECTRL_REG_XSCALE_400FREQ 0x2 + +/** + * @ingroup IxFeatureCtrlAPI + * + * @def IX_FEATURECTRL_REG_XSCALE_266FREQ + * + * @brief Maximum frequency available to IXP46x is 266 MHz. + * + */ +#define IX_FEATURECTRL_REG_XSCALE_266FREQ 0x3 + +#endif /* __ixp46X */ + +/** + * @ingroup IxFeatureCtrlAPI + * + * @def IX_FEATURECTRL_COMPONENT_NOT_AVAILABLE + * + * @brief Component selected is not available for device + * + */ +#define IX_FEATURECTRL_COMPONENT_NOT_AVAILABLE 0x0000 + +/** + * @ingroup IxFeatureCtrlAPI + * + * @def IX_FEATURECTRL_COMPONENT_ALWAYS_AVAILABLE + * + * @brief Component selected is not available for device + * + */ +#define IX_FEATURECTRL_COMPONENT_ALWAYS_AVAILABLE 0xffff + +/** + * @defgroup IxFeatureCtrlSwConfig Software Configuration for Access Component + * + * @ingroup IxFeatureCtrlAPI + * + * @brief This section describes software configuration in access component. The + * configuration can be changed at run-time. ixFeatureCtrlSwConfigurationCheck( ) + * will be used across applicable access component to check the configuration. + * ixFeatureCtrlSwConfigurationWrite( ) is used to write the software configuration. + * + * @note All software configurations are default to be enabled. + * + * @{ + */ +/** + * @ingroup IxFeatureCtrlSwConfig + * + * @def IX_FEATURE_CTRL_SWCONFIG_DISABLED + * + * @brief Software configuration is disabled. + * + */ +#define IX_FEATURE_CTRL_SWCONFIG_DISABLED 0 + +/** + * @ingroup IxFeatureCtrlSwConfig + * + * @def IX_FEATURE_CTRL_SWCONFIG_ENABLED + * + * @brief Software configuration is enabled. + * + */ +#define IX_FEATURE_CTRL_SWCONFIG_ENABLED 1 + +/** + * Section for enums + **/ + +/** + * @ingroup IxFeatureCtrlBuildDevice + * + * @enum IxFeatureCtrlBuildDevice + * + * @brief Indicates software build type. + * + * Default build type is IXP42X + * + */ +typedef enum +{ + IX_FEATURE_CTRL_SW_BUILD_IXP42X = 0, /** + * - if(IX_FEATURE_CTRL_COMPONENT_DISABLED != + * ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH0))
+ * - if(IX_FEATURE_CTRL_COMPONENT_ENABLED == + * ixFeatureCtrlComponentCheck(IX_FEATURECTRL_PCI))
+ * + * This function is typically called during component initialization time. + * + * @param componentType @ref IxFeatureCtrlComponentType [in] - the type of a component as + * defined above as IX_FEATURECTRL_XXX (Exp: IX_FEATURECTRL_PCI, IX_FEATURECTRL_ETH0) + + * + * @return + * - IX_FEATURE_CTRL_COMPONENT_ENABLED if component is available + * - IX_FEATURE_CTRL_COMPONENT_DISABLED if component is unavailable + */ +PUBLIC IX_STATUS +ixFeatureCtrlComponentCheck (IxFeatureCtrlComponentType componentType); + +/** + * @ingroup IxFeatureCtrlAPI + * + * @fn IxFeatureCtrlProductId ixFeatureCtrlProductIdRead (void) + * + * @brief This function will return IXP400 product ID i.e. CP15, + * Register 0. + * + * @return + * - IxFeatureCtrlProductId - the value of product ID. + * + */ +PUBLIC IxFeatureCtrlProductId +ixFeatureCtrlProductIdRead (void) ; + +/** + * @ingroup IxFeatureCtrlAPI + * + * @fn IX_STATUS ixFeatureCtrlSwConfigurationCheck (IxFeatureCtrlSwConfig swConfigType) + * + * @brief This function checks whether the specified software configuration is + * enabled or disabled. + * + * Usage Example:
+ * - if(IX_FEATURE_CTRL_SWCONFIG_DISABLED != + * ixFeatureCtrlSwConfigurationCheck(IX_FEATURECTRL_ETH_LEARNING))
+ * - if(IX_FEATURE_CTRL_SWCONFIG_ENABLED == + * ixFeatureCtrlSwConfigurationCheck(IX_FEATURECTRL_ETH_LEARNING))
+ * + * This function is typically called during access component initialization time. + * + * @param swConfigType @ref IxFeatureCtrlSwConfig [in] - the type of a software configuration + * defined in IxFeatureCtrlSwConfig enumeration. + * + * @return + * - IX_FEATURE_CTRL_SWCONFIG_ENABLED if software configuration is enabled. + * - IX_FEATURE_CTRL_SWCONFIG_DISABLED if software configuration is disabled. + */ +PUBLIC IX_STATUS +ixFeatureCtrlSwConfigurationCheck (IxFeatureCtrlSwConfig swConfigType); + +/** + * @ingroup IxFeatureCtrlAPI + * + * @fn void ixFeatureCtrlSwConfigurationWrite (IxFeatureCtrlSwConfig swConfigType, BOOL enabled) + * + * @brief This function enable/disable the specified software configuration. + * + * Usage Example:
+ * - ixFeatureCtrlSwConfigurationWrite(IX_FEATURECTRL_ETH_LEARNING, TRUE) is used + * to enable Ethernet Learning Feature
+ * - ixFeatureCtrlSwConfigurationWrite(IX_FEATURECTRL_ETH_LEARNING, FALSE) is used + * to disable Ethernet Learning Feature
+ * + * @param swConfigType IxFeatureCtrlSwConfig [in] - the type of a software configuration + * defined in IxFeatureCtrlSwConfig enumeration. + * @param enabled BOOL [in] - To enable(TRUE) / disable (FALSE) the specified software + * configuration. + * + * @return none + * + */ +PUBLIC void +ixFeatureCtrlSwConfigurationWrite (IxFeatureCtrlSwConfig swConfigType, BOOL enabled); + +/** + * @ingroup IxFeatureCtrlAPI + * + * @fn void ixFeatureCtrlIxp400SwVersionShow (void) + * + * @brief This function shows the current software release information for IXP400 + * + * @return none + * + */ +PUBLIC void +ixFeatureCtrlIxp400SwVersionShow (void); + +#endif /* IXFEATURECTRL_H */ + +/** + * @} defgroup IxFeatureCtrlAPI + */ diff --git a/cpu/ixp/npe/include/IxHssAcc.h b/cpu/ixp/npe/include/IxHssAcc.h new file mode 100644 index 0000000..07bb119 --- /dev/null +++ b/cpu/ixp/npe/include/IxHssAcc.h @@ -0,0 +1,1316 @@ +/** + * @file IxHssAcc.h + * + * @date 07-DEC-2001 + * + * @brief This file contains the public API of the IXP400 HSS Access + * 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 -- +*/ + +/* ------------------------------------------------------ + Doxygen group definitions + ------------------------------------------------------ */ +/** + * @defgroup IxHssAccAPI IXP400 HSS Access (IxHssAcc) API + * + * @brief The public API for the IXP400 HssAccess component + * + * IxHssAcc is the access layer to the HSS packetised and channelised + * services + * + * Design Notes
+ *
    + *
  • When a packet-pipe is configured for 56Kbps RAW mode, byte alignment of + * the transmitted data is not preserved. All raw data that is transmitted + * will be received in proper order by the receiver, but the first bit of + * the packet may be seen at any offset within a byte; all subsequent bytes + * will have the same offset for the duration of the packet. The same offset + * also applies to all subsequent packets received on the packet-pipe too. + * (Similar results will occur for data received from remote end.) While + * this behavior will also occur for 56Kbps HDLC mode, the HDLC + * encoding/decoding will preserve the original byte alignment at the + * receiver end. + *
+ * + * 56Kbps Packetised Service Bandwidth Limitation
+ *
    + *
  • IxHssAcc supports 56Kbps packetised service at a maximum aggregate rate + * for all HSS ports/HDLC channels of 12.288Mbps[1] in each direction, i.e. + * it supports 56Kbps packetised service on up to 8 T1 trunks. It does + * not support 56Kbps packetised service on 8 E1 trunks (i.e. 4 trunks per + * HSS port) unless those trunks are running 'fractional E1' with maximum + * aggregate rate of 12.288 Mbps in each direction.
    + * [1] 12.288Mbps = 1.536Mbp * 8 T1 + *
+ * @{ */ + +#ifndef IXHSSACC_H +#define IXHSSACC_H + +#include "IxOsal.h" + +/* + * #defines for function return types, etc. + */ + +/** + * @def IX_HSSACC_TSLOTS_PER_HSS_PORT + * + * @brief The max number of TDM timeslots supported per HSS port - 4E1's = + * 32x4 = 128 + */ +#define IX_HSSACC_TSLOTS_PER_HSS_PORT 128 + +/* ----------------------------------------------------------- + The following are HssAccess return values returned through + service interfaces. The globally defined IX_SUCCESS (0) and + IX_FAIL (1) in IxOsalTypes.h are also used. + ----------------------------------------------------------- */ +/** + * @def IX_HSSACC_PARAM_ERR + * + * @brief HssAccess function return value for a parameter error + */ +#define IX_HSSACC_PARAM_ERR 2 + +/** + * @def IX_HSSACC_RESOURCE_ERR + * + * @brief HssAccess function return value for a resource error + */ +#define IX_HSSACC_RESOURCE_ERR 3 + +/** + * @def IX_HSSACC_PKT_DISCONNECTING + * + * @brief Indicates that a disconnect call is progressing and will + * disconnect soon + */ +#define IX_HSSACC_PKT_DISCONNECTING 4 + +/** + * @def IX_HSSACC_Q_WRITE_OVERFLOW + * + * @brief Indicates that an attempt to Tx or to replenish an + * RxFree Q failed due to Q overflow. + */ +#define IX_HSSACC_Q_WRITE_OVERFLOW 5 + +/* ------------------------------------------------------------------- + The following errors are HSS/NPE errors returned on error retrieval + ------------------------------------------------------------------- */ +/** + * @def IX_HSSACC_NO_ERROR + * + * @brief HSS port no error present + */ +#define IX_HSSACC_NO_ERROR 0 + +/** + * @def IX_HSSACC_TX_FRM_SYNC_ERR + * + * @brief HSS port TX Frame Sync error + */ +#define IX_HSSACC_TX_FRM_SYNC_ERR 1 + +/** + * @def IX_HSSACC_TX_OVER_RUN_ERR + * + * @brief HSS port TX over-run error + */ +#define IX_HSSACC_TX_OVER_RUN_ERR 2 + +/** + * @def IX_HSSACC_CHANNELISED_SW_TX_ERR + * + * @brief NPE software error in channelised TX + */ +#define IX_HSSACC_CHANNELISED_SW_TX_ERR 3 + +/** + * @def IX_HSSACC_PACKETISED_SW_TX_ERR + * + * @brief NPE software error in packetised TX + */ +#define IX_HSSACC_PACKETISED_SW_TX_ERR 4 + +/** + * @def IX_HSSACC_RX_FRM_SYNC_ERR + * + * @brief HSS port RX Frame Sync error + */ +#define IX_HSSACC_RX_FRM_SYNC_ERR 5 + +/** + * @def IX_HSSACC_RX_OVER_RUN_ERR + * + * @brief HSS port RX over-run error + */ +#define IX_HSSACC_RX_OVER_RUN_ERR 6 + +/** + * @def IX_HSSACC_CHANNELISED_SW_RX_ERR + * + * @brief NPE software error in channelised RX + */ +#define IX_HSSACC_CHANNELISED_SW_RX_ERR 7 + +/** + * @def IX_HSSACC_PACKETISED_SW_RX_ERR + * + * @brief NPE software error in packetised TX + */ +#define IX_HSSACC_PACKETISED_SW_RX_ERR 8 + +/* ----------------------------------- + Packetised service specific defines + ----------------------------------- */ + +/** + * @def IX_HSSACC_PKT_MIN_RX_MBUF_SIZE + * + * @brief Minimum size of the Rx mbuf in bytes which the client must supply + * to the component. + */ +#define IX_HSSACC_PKT_MIN_RX_MBUF_SIZE 64 + +/* -------------------------------------------------------------------- + Enumerated Types - these enumerated values may be used in setting up + the contents of hardware registers + -------------------------------------------------------------------- */ +/** + * @enum IxHssAccHssPort + * @brief The HSS port ID - There are two identical ports (0-1). + * + */ +typedef enum +{ + IX_HSSACC_HSS_PORT_0, /**< HSS Port 0 */ + IX_HSSACC_HSS_PORT_1, /**< HSS Port 1 */ + IX_HSSACC_HSS_PORT_MAX /**< Delimiter for error checks */ +} IxHssAccHssPort; + +/** + * @enum IxHssAccHdlcPort + * @brief The HDLC port ID - There are four identical HDLC ports (0-3) per + * HSS port and they correspond to the 4 E1/T1 trunks. + * + */ +typedef enum +{ + IX_HSSACC_HDLC_PORT_0, /**< HDLC Port 0 */ + IX_HSSACC_HDLC_PORT_1, /**< HDLC Port 1 */ + IX_HSSACC_HDLC_PORT_2, /**< HDLC Port 2 */ + IX_HSSACC_HDLC_PORT_3, /**< HDLC Port 3 */ + IX_HSSACC_HDLC_PORT_MAX /**< Delimiter for error checks */ +} IxHssAccHdlcPort; + +/** + * @enum IxHssAccTdmSlotUsage + * @brief The HSS TDM stream timeslot assignment types + * + */ +typedef enum +{ + IX_HSSACC_TDMMAP_UNASSIGNED, /**< Unassigned */ + IX_HSSACC_TDMMAP_HDLC, /**< HDLC - packetised */ + IX_HSSACC_TDMMAP_VOICE56K, /**< Voice56K - channelised */ + IX_HSSACC_TDMMAP_VOICE64K, /**< Voice64K - channelised */ + IX_HSSACC_TDMMAP_MAX /**< Delimiter for error checks */ +} IxHssAccTdmSlotUsage; + +/** + * @enum IxHssAccFrmSyncType + * @brief The HSS frame sync pulse type + * + */ +typedef enum +{ + IX_HSSACC_FRM_SYNC_ACTIVE_LOW, /**< Frame sync is sampled low */ + IX_HSSACC_FRM_SYNC_ACTIVE_HIGH, /**< sampled high */ + IX_HSSACC_FRM_SYNC_FALLINGEDGE, /**< sampled on a falling edge */ + IX_HSSACC_FRM_SYNC_RISINGEDGE, /**< sampled on a rising edge */ + IX_HSSACC_FRM_SYNC_TYPE_MAX /**< Delimiter for error checks */ +} IxHssAccFrmSyncType; + +/** + * @enum IxHssAccFrmSyncEnable + * @brief The IxHssAccFrmSyncEnable determines how the frame sync pulse is + * used + * */ +typedef enum +{ + IX_HSSACC_FRM_SYNC_INPUT, /**< Frame sync is sampled as an input */ + IX_HSSACC_FRM_SYNC_INVALID_VALUE, /**< 1 is not used */ + IX_HSSACC_FRM_SYNC_OUTPUT_FALLING, /**< Frame sync is an output generated + off a falling clock edge */ + IX_HSSACC_FRM_SYNC_OUTPUT_RISING, /**< Frame sync is an output generated + off a rising clock edge */ + IX_HSSACC_FRM_SYNC_ENABLE_MAX /**< Delimiter for error checks */ +} IxHssAccFrmSyncEnable; + +/** + * @enum IxHssAccClkEdge + * @brief IxHssAccClkEdge is used to determine the clk edge to use for + * framing and data + * + */ +typedef enum +{ + IX_HSSACC_CLK_EDGE_FALLING, /**< Clock sampled off a falling edge */ + IX_HSSACC_CLK_EDGE_RISING, /**< Clock sampled off a rising edge */ + IX_HSSACC_CLK_EDGE_MAX /**< Delimiter for error checks */ +} IxHssAccClkEdge; + +/** + * @enum IxHssAccClkDir + * @brief The HSS clock direction + * + */ +typedef enum +{ + IX_HSSACC_SYNC_CLK_DIR_INPUT, /**< Clock is an input */ + IX_HSSACC_SYNC_CLK_DIR_OUTPUT, /**< Clock is an output */ + IX_HSSACC_SYNC_CLK_DIR_MAX /**< Delimiter for error checks */ +} IxHssAccClkDir; + +/** + * @enum IxHssAccFrmPulseUsage + * @brief The HSS frame pulse usage + * + */ +typedef enum +{ + IX_HSSACC_FRM_PULSE_ENABLED, /**< Generate/Receive frame pulses */ + IX_HSSACC_FRM_PULSE_DISABLED, /**< Disregard frame pulses */ + IX_HSSACC_FRM_PULSE_MAX /**< Delimiter for error checks */ +} IxHssAccFrmPulseUsage; + +/** + * @enum IxHssAccDataRate + * @brief The HSS Data rate in relation to the clock + * + */ +typedef enum +{ + IX_HSSACC_CLK_RATE, /**< Data rate is at the configured clk speed */ + IX_HSSACC_HALF_CLK_RATE, /**< Data rate is half the configured clk speed */ + IX_HSSACC_DATA_RATE_MAX /**< Delimiter for error checks */ +} IxHssAccDataRate; + +/** + * @enum IxHssAccDataPolarity + * @brief The HSS data polarity type + * + */ +typedef enum +{ + IX_HSSACC_DATA_POLARITY_SAME, /**< Don't invert data between NPE and + HSS FIFOs */ + IX_HSSACC_DATA_POLARITY_INVERT, /**< Invert data between NPE and HSS + FIFOs */ + IX_HSSACC_DATA_POLARITY_MAX /**< Delimiter for error checks */ +} IxHssAccDataPolarity; + +/** + * @enum IxHssAccBitEndian + * @brief HSS Data endianness + * + */ +typedef enum +{ + IX_HSSACC_LSB_ENDIAN, /**< TX/RX Least Significant Bit first */ + IX_HSSACC_MSB_ENDIAN, /**< TX/RX Most Significant Bit first */ + IX_HSSACC_ENDIAN_MAX /**< Delimiter for the purposes of error checks */ +} IxHssAccBitEndian; + + +/** + * @enum IxHssAccDrainMode + * @brief Tx pin open drain mode + * + */ +typedef enum +{ + IX_HSSACC_TX_PINS_NORMAL, /**< Normal mode */ + IX_HSSACC_TX_PINS_OPEN_DRAIN, /**< Open Drain mode */ + IX_HSSACC_TX_PINS_MAX /**< Delimiter for error checks */ +} IxHssAccDrainMode; + +/** + * @enum IxHssAccSOFType + * @brief HSS start of frame types + * + */ +typedef enum +{ + IX_HSSACC_SOF_FBIT, /**< Framing bit transmitted and expected on rx */ + IX_HSSACC_SOF_DATA, /**< Framing bit not transmitted nor expected on rx */ + IX_HSSACC_SOF_MAX /**< Delimiter for error checks */ +} IxHssAccSOFType; + +/** + * @enum IxHssAccDataEnable + * @brief IxHssAccDataEnable is used to determine whether or not to drive + * the data pins + * + */ +typedef enum +{ + IX_HSSACC_DE_TRI_STATE, /**< TRI-State the data pins */ + IX_HSSACC_DE_DATA, /**< Push data out the data pins */ + IX_HSSACC_DE_MAX /**< Delimiter for error checks */ +} IxHssAccDataEnable; + +/** + * @enum IxHssAccTxSigType + * @brief IxHssAccTxSigType is used to determine how to drive the data pins + * + */ +typedef enum +{ + IX_HSSACC_TXSIG_LOW, /**< Drive the data pins low */ + IX_HSSACC_TXSIG_HIGH, /**< Drive the data pins high */ + IX_HSSACC_TXSIG_HIGH_IMP, /**< Drive the data pins with high impedance */ + IX_HSSACC_TXSIG_MAX /**< Delimiter for error checks */ +} IxHssAccTxSigType; + +/** + * @enum IxHssAccFbType + * @brief IxHssAccFbType determines how to drive the Fbit + * + * @warning This will only be used for T1 @ 1.544MHz + * + */ +typedef enum +{ + IX_HSSACC_FB_FIFO, /**< Fbit is dictated in FIFO */ + IX_HSSACC_FB_HIGH_IMP, /**< Fbit is high impedance */ + IX_HSSACC_FB_MAX /**< Delimiter for error checks */ +} IxHssAccFbType; + +/** + * @enum IxHssAcc56kEndianness + * @brief 56k data endianness when using the 56k type + * + */ +typedef enum +{ + IX_HSSACC_56KE_BIT_7_UNUSED, /**< High bit is unused */ + IX_HSSACC_56KE_BIT_0_UNUSED, /**< Low bit is unused */ + IX_HSSACC_56KE_MAX /**< Delimiter for error checks */ +} IxHssAcc56kEndianness; + +/** + * @enum IxHssAcc56kSel + * @brief 56k data transmission type when using the 56k type + * + */ +typedef enum +{ + IX_HSSACC_56KS_32_8_DATA, /**< 32/8 bit data */ + IX_HSSACC_56KS_56K_DATA, /**< 56K data */ + IX_HSSACC_56KS_MAX /**< Delimiter for error checks */ +} IxHssAcc56kSel; + + +/** + * @enum IxHssAccClkSpeed + * @brief IxHssAccClkSpeed represents the HSS clock speeds available + * + */ +typedef enum +{ + IX_HSSACC_CLK_SPEED_512KHZ, /**< 512KHz */ + IX_HSSACC_CLK_SPEED_1536KHZ, /**< 1.536MHz */ + IX_HSSACC_CLK_SPEED_1544KHZ, /**< 1.544MHz */ + IX_HSSACC_CLK_SPEED_2048KHZ, /**< 2.048MHz */ + IX_HSSACC_CLK_SPEED_4096KHZ, /**< 4.096MHz */ + IX_HSSACC_CLK_SPEED_8192KHZ, /**< 8.192MHz */ + IX_HSSACC_CLK_SPEED_MAX /**< Delimiter for error checking */ +} IxHssAccClkSpeed; + +/** + * @enum IxHssAccPktStatus + * @brief Indicates the status of packets passed to the client + * + */ +typedef enum +{ + IX_HSSACC_PKT_OK, /**< Error free.*/ + IX_HSSACC_STOP_SHUTDOWN_ERROR, /**< Errored due to stop or shutdown + occurrance.*/ + IX_HSSACC_HDLC_ALN_ERROR, /**< HDLC alignment error */ + IX_HSSACC_HDLC_FCS_ERROR, /**< HDLC Frame Check Sum error.*/ + IX_HSSACC_RXFREE_Q_EMPTY_ERROR, /**< RxFree Q became empty + while receiving this packet.*/ + IX_HSSACC_HDLC_MAX_FRAME_SIZE_EXCEEDED, /**< HDLC frame size + received is greater than + max specified at connect.*/ + IX_HSSACC_HDLC_ABORT_ERROR, /**< HDLC frame received is invalid due to an + abort sequence received.*/ + IX_HSSACC_DISCONNECT_IN_PROGRESS /**< Packet returned + because a disconnect is in progress */ +} IxHssAccPktStatus; + + +/** + * @enum IxHssAccPktCrcType + * @brief HDLC CRC type + * + */ +typedef enum +{ + IX_HSSACC_PKT_16_BIT_CRC = 16, /**< 16 bit CRC is being used */ + IX_HSSACC_PKT_32_BIT_CRC = 32 /**< 32 bit CRC is being used */ +} IxHssAccPktCrcType; + +/** + * @enum IxHssAccPktHdlcIdleType + * @brief HDLC idle transmission type + * + */ +typedef enum +{ + IX_HSSACC_HDLC_IDLE_ONES, /**< idle tx/rx will be a succession of ones */ + IX_HSSACC_HDLC_IDLE_FLAGS /**< idle tx/rx will be repeated flags */ +} IxHssAccPktHdlcIdleType; + +/** + * @brief Structure containing HSS port configuration parameters + * + * Note: All of these are used for TX. Only some are specific to RX. + * + */ +typedef struct +{ + IxHssAccFrmSyncType frmSyncType; /**< frame sync pulse type (tx/rx) */ + IxHssAccFrmSyncEnable frmSyncIO; /**< how the frame sync pulse is + used (tx/rx) */ + IxHssAccClkEdge frmSyncClkEdge; /**< frame sync clock edge type + (tx/rx) */ + IxHssAccClkEdge dataClkEdge; /**< data clock edge type (tx/rx) */ + IxHssAccClkDir clkDirection; /**< clock direction (tx/rx) */ + IxHssAccFrmPulseUsage frmPulseUsage; /**< whether to use the frame sync + pulse or not (tx/rx) */ + IxHssAccDataRate dataRate; /**< data rate in relation to the + clock (tx/rx) */ + IxHssAccDataPolarity dataPolarity; /**< data polarity type (tx/rx) */ + IxHssAccBitEndian dataEndianness; /**< data endianness (tx/rx) */ + IxHssAccDrainMode drainMode; /**< tx pin open drain mode (tx) */ + IxHssAccSOFType fBitUsage; /**< start of frame types (tx/rx) */ + IxHssAccDataEnable dataEnable; /**< whether or not to drive the data + pins (tx) */ + IxHssAccTxSigType voice56kType; /**< how to drive the data pins for + voice56k type (tx) */ + IxHssAccTxSigType unassignedType; /**< how to drive the data pins for + unassigned type (tx) */ + IxHssAccFbType fBitType; /**< how to drive the Fbit (tx) */ + IxHssAcc56kEndianness voice56kEndian;/**< 56k data endianness when using + the 56k type (tx) */ + IxHssAcc56kSel voice56kSel; /**< 56k data transmission type when + using the 56k type (tx) */ + unsigned frmOffset; /**< frame pulse offset in bits wrt + the first timeslot (0-1023) (tx/rx) */ + unsigned maxFrmSize; /**< frame size in bits (1-1024) + (tx/rx) */ +} IxHssAccPortConfig; + +/** + * @brief Structure containing HSS configuration parameters + * + */ +typedef struct +{ + IxHssAccPortConfig txPortConfig; /**< HSS tx port configuration */ + IxHssAccPortConfig rxPortConfig; /**< HSS rx port configuration */ + unsigned numChannelised; /**< The number of channelised + timeslots (0-32) */ + unsigned hssPktChannelCount; /**< The number of packetised + clients (0 - 4) */ + UINT8 channelisedIdlePattern; /**< The byte to be transmitted on + channelised service when there + is no client data to tx */ + BOOL loopback; /**< The HSS loopback state */ + unsigned packetizedIdlePattern; /**< The data to be transmitted on + packetised service when there is + no client data to tx */ + IxHssAccClkSpeed clkSpeed; /**< The HSS clock speed */ +} IxHssAccConfigParams; + +/** + * @brief This structure contains 56Kbps, HDLC-mode configuration parameters + * + */ +typedef struct +{ + BOOL hdlc56kMode; /**< 56kbps(TRUE)/64kbps(FALSE) HDLC */ + IxHssAcc56kEndianness hdlc56kEndian; /**< 56kbps data endianness + - ignored if hdlc56kMode is FALSE*/ + BOOL hdlc56kUnusedBitPolarity0; /**< The polarity '0'(TRUE)/'1'(FALSE) of the unused + bit while in 56kbps mode + - ignored if hdlc56kMode is FALSE*/ +} IxHssAccHdlcMode; + +/** + * @brief This structure contains information required by the NPE to + * configure the HDLC co-processor + * + */ +typedef struct +{ + IxHssAccPktHdlcIdleType hdlcIdleType; /**< What to transmit when a HDLC port is idle */ + IxHssAccBitEndian dataEndian; /**< The HDLC data endianness */ + IxHssAccPktCrcType crcType; /**< The CRC type to be used for this HDLC port */ +} IxHssAccPktHdlcFraming; + +/** + * @typedef UINT32 IxHssAccPktUserId + * + * @brief The client supplied value which will be supplied as a parameter + * with a given callback. + * + * This value will be passed into the ixHssAccPktPortConnect function once each + * with given callbacks. This value will then be passed back to the client + * as one of the parameters to each of these callbacks, + * when these callbacks are called. + */ +typedef UINT32 IxHssAccPktUserId; + + +/** + * @typedef IxHssAccLastErrorCallback + * @brief Prototype of the clients function to accept notification of the + * last error + * + * This function is registered through the config. The client will initiate + * the last error retrieval. The HssAccess component will send a message to + * the NPE through the NPE Message Handler. When a response to the read is + * received, the NPE Message Handler will callback the HssAccess component + * which will execute this function in the same IxNpeMh context. The client + * will be passed the last error and the related service port (packetised + * 0-3, channelised 0) + * + * @param lastHssError unsigned [in] - The last Hss error registered that + * has been registered. + * @param servicePort unsigned [in] - This is the service port number. + * (packetised 0-3, channelised 0) + * + * @return void + */ +typedef void (*IxHssAccLastErrorCallback) (unsigned lastHssError, + unsigned servicePort); + +/** + * @typedef IxHssAccPktRxCallback + * @brief Prototype of the clients function to accept notification of + * packetised rx + * + * This function is registered through the ixHssAccPktPortConnect. hssPktAcc will pass + * received data in the form of mbufs to the client. The mbuf passed back + * to the client could contain a chain of buffers, depending on the packet + * size received. + * + * @param *buffer @ref IX_OSAL_MBUF [in] - This is the mbuf which contains the + * payload received. + * @param numHssErrs unsigned [in] - This is the number of hssErrors + * the Npe has received + * @param pktStatus @ref IxHssAccPktStatus [in] - This is the status of the + * mbuf that has been received. + * @param rxUserId @ref IxHssAccPktUserId [in] - This is the client supplied value + * passed in at ixHssAccPktPortConnect time which is now returned to the client. + * + * @return void + */ +typedef void (*IxHssAccPktRxCallback) (IX_OSAL_MBUF *buffer, + unsigned numHssErrs, + IxHssAccPktStatus pktStatus, + IxHssAccPktUserId rxUserId); + +/** + * @typedef IxHssAccPktRxFreeLowCallback + * @brief Prototype of the clients function to accept notification of + * requirement of more Rx Free buffers + * + * The client can choose to register a callback of this type when + * calling a connecting. This function is registered through the ixHssAccPktPortConnect. + * If defined, the access layer will provide the trigger for + * this callback. The callback will be responsible for supplying mbufs to + * the access layer for use on the receive path from the HSS using + * ixHssPktAccFreeBufReplenish. + * + * @return void + */ +typedef void (*IxHssAccPktRxFreeLowCallback) (IxHssAccPktUserId rxFreeLowUserId); + +/** + * @typedef IxHssAccPktTxDoneCallback + * @brief Prototype of the clients function to accept notification of + * completion with Tx buffers + * + * This function is registered through the ixHssAccPktPortConnect. It enables + * the hssPktAcc to pass buffers back to the client + * when transmission is complete. + * + * @param *buffer @ref IX_OSAL_MBUF [in] - This is the mbuf which contained + * the payload that was for Tx. + * @param numHssErrs unsigned [in] - This is the number of hssErrors + * the Npe has received + * @param pktStatus @ref IxHssAccPktStatus [in] - This is the status of the + * mbuf that has been transmitted. + * @param txDoneUserId @ref IxHssAccPktUserId [in] - This is the client supplied value + * passed in at ixHssAccPktPortConnect time which is now returned to the client. + * + * @return void + */ +typedef void (*IxHssAccPktTxDoneCallback) (IX_OSAL_MBUF *buffer, + unsigned numHssErrs, + IxHssAccPktStatus pktStatus, + IxHssAccPktUserId txDoneUserId); + +/** + * @typedef IxHssAccChanRxCallback + * @brief Prototype of the clients function to accept notification of + * channelised rx + * + * This callback, if defined by the client in the connect, will get called + * in the context of an IRQ. The IRQ will be triggered when the hssSyncQMQ + * is not empty. The queued entry will be dequeued and this function will + * be executed. + * + * @param hssPortId @ref IxHssAccHssPort - The HSS port Id. There are two + * identical ports (0-1). + * @param txOffset unsigned [in] - an offset indicating from where within + * the txPtrList the NPE is currently transmitting from. + * @param rxOffset unsigned [in] - an offset indicating where within the + * receive buffers the NPE has just written the received data to. + * @param numHssErrs unsigned [in] - This is the number of hssErrors + * the Npe has received + * + * @return void + */ +typedef void (*IxHssAccChanRxCallback) (IxHssAccHssPort hssPortId, + unsigned rxOffset, + unsigned txOffset, + unsigned numHssErrs); + +/* + * Prototypes for interface functions. + */ + +/** + * + * @ingroup IxHssAccAPI + * + * @fn IX_STATUS ixHssAccPortInit (IxHssAccHssPort hssPortId, + IxHssAccConfigParams *configParams, + IxHssAccTdmSlotUsage *tdmMap, + IxHssAccLastErrorCallback lastHssErrorCallback) + * + * @brief Initialise a HSS port. No channelised or packetised connections + * should exist in the HssAccess layer while this interface is being called. + * + * @param hssPortId @ref IxHssAccHssPort [in] - The HSS port Id. There are two + * identical ports (0-1). + * @param *configParams @ref IxHssAccConfigParams [in] - A pointer to the HSS + * configuration structure + * @param *tdmMap @ref IxHssAccTdmSlotUsage [in] - A pointer to an array of size + * IX_HSSACC_TSLOTS_PER_HSS_PORT, defining the slot usage over the HSS port + * @param lastHssErrorCallback @ref IxHssAccLastErrorCallback [in] - Client + * callback to report last error + * + * @return + * - IX_SUCCESS The function executed successfully + * - IX_FAIL The function did not execute successfully + * - IX_HSSACC_PARAM_ERR The function did not execute successfully due to a + * parameter error + */ +PUBLIC IX_STATUS +ixHssAccPortInit (IxHssAccHssPort hssPortId, + IxHssAccConfigParams *configParams, + IxHssAccTdmSlotUsage *tdmMap, + IxHssAccLastErrorCallback lastHssErrorCallback); + +/** + * + * @ingroup IxHssAccAPI + * + * @fn IX_STATUS ixHssAccLastErrorRetrievalInitiate ( + IxHssAccHssPort hssPortId) + * + * @brief Initiate the retrieval of the last HSS error. The HSS port + * should be configured before attempting to call this interface. + * + * @param hssPortId @ref IxHssAccHssPort [in] - the HSS port ID + * + * @return + * - IX_SUCCESS The function executed successfully + * - IX_FAIL The function did not execute successfully + * - IX_HSSACC_PARAM_ERR The function did not execute successfully due to a + * parameter error + */ +PUBLIC IX_STATUS +ixHssAccLastErrorRetrievalInitiate (IxHssAccHssPort hssPortId); + + +/** + * + * @ingroup IxHssAccAPI + * + * @fn IX_STATUS ixHssAccInit () + * + * @brief This function is responsible for initialising resources for use + * by the packetised and channelised clients. It should be called after + * HSS NPE image has been downloaded into NPE-A and before any other + * HssAccess interface is called. + * No other HssAccPacketised interface should be called while this interface + * is being processed. + * + * @return + * - IX_SUCCESS The function executed successfully + * - IX_FAIL The function did not execute successfully + * - IX_HSSACC_RESOURCE_ERR The function did not execute successfully due + * to a resource error + */ +PUBLIC IX_STATUS +ixHssAccInit (void); + + +/** + * + * @ingroup IxHssAccAPI + * + * @fn ixHssAccPktPortConnect (IxHssAccHssPort hssPortId, + IxHssAccHdlcPort hdlcPortId, + BOOL hdlcFraming, + IxHssAccHdlcMode hdlcMode, + BOOL hdlcBitInvert, + unsigned blockSizeInWords, + UINT32 rawIdleBlockPattern, + IxHssAccPktHdlcFraming hdlcTxFraming, + IxHssAccPktHdlcFraming hdlcRxFraming, + unsigned frmFlagStart, + IxHssAccPktRxCallback rxCallback, + IxHssAccPktUserId rxUserId, + IxHssAccPktRxFreeLowCallback rxFreeLowCallback, + IxHssAccPktUserId rxFreeLowUserId, + IxHssAccPktTxDoneCallback txDoneCallback, + IxHssAccPktUserId txDoneUserId) + * + * @brief This function is responsible for connecting a client to one of + * the 4 available HDLC ports. The HSS port should be configured before + * attempting a connect. No other HssAccPacketised interface should be + * called while this connect is being processed. + * + * @param hssPortId @ref IxHssAccHssPort [in] - The HSS port Id. There are two + * identical ports (0-1). + * @param hdlcPortId @ref IxHssAccHdlcPort [in] - This is the number of the HDLC port and + * it corresponds to the physical E1/T1 trunk i.e. 0, 1, 2, 3 + * @param hdlcFraming BOOL [in] - This value determines whether the service + * will use HDLC data or the debug, raw data type i.e. no HDLC processing + * @param hdlcMode @ref IxHssAccHdlcMode [in] - This structure contains 56Kbps, HDLC-mode + * configuration parameters + * @param hdlcBitInvert BOOL [in] - This value determines whether bit inversion + * will occur between HDLC and HSS co-processors i.e. post-HDLC processing for + * transmit and pre-HDLC processing for receive, for the specified HDLC Termination + * Point + * @param blockSizeInWords unsigned [in] - The max tx/rx block size + * @param rawIdleBlockPattern UINT32 [in] - Tx idle pattern in raw mode + * @param hdlcTxFraming @ref IxHssAccPktHdlcFraming [in] - This structure contains + * the following information required by the NPE to configure the HDLC + * co-processor for TX + * @param hdlcRxFraming @ref IxHssAccPktHdlcFraming [in] - This structure contains + * the following information required by the NPE to configure the HDLC + * co-processor for RX + * @param frmFlagStart unsigned - Number of flags to precede to + * transmitted flags (0-2). + * @param rxCallback @ref IxHssAccPktRxCallback [in] - Pointer to + * the clients packet receive function. + * @param rxUserId @ref IxHssAccPktUserId [in] - The client supplied rx value + * to be passed back as an argument to the supplied rxCallback + * @param rxFreeLowCallback @ref IxHssAccPktRxFreeLowCallback [in] - Pointer to + * the clients Rx free buffer request function. If NULL, assume client will + * trigger independently. + * @param rxFreeLowUserId @ref IxHssAccPktUserId [in] - The client supplied RxFreeLow value + * to be passed back as an argument to the supplied rxFreeLowCallback + * @param txDoneCallback @ref IxHssAccPktTxDoneCallback [in] - Pointer to the + * clients Tx done callback function + * @param txDoneUserId @ref IxHssAccPktUserId [in] - The client supplied txDone value + * to be passed back as an argument to the supplied txDoneCallback + * + * @return + * - IX_SUCCESS The function executed successfully + * - IX_FAIL The function did not execute successfully + * - IX_HSSACC_PARAM_ERR The function did not execute successfully due to a + * parameter error + * - IX_HSSACC_RESOURCE_ERR The function did not execute successfully due + * to a resource error + */ +PUBLIC IX_STATUS +ixHssAccPktPortConnect (IxHssAccHssPort hssPortId, + IxHssAccHdlcPort hdlcPortId, + BOOL hdlcFraming, + IxHssAccHdlcMode hdlcMode, + BOOL hdlcBitInvert, + unsigned blockSizeInWords, + UINT32 rawIdleBlockPattern, + IxHssAccPktHdlcFraming hdlcTxFraming, + IxHssAccPktHdlcFraming hdlcRxFraming, + unsigned frmFlagStart, + IxHssAccPktRxCallback rxCallback, + IxHssAccPktUserId rxUserId, + IxHssAccPktRxFreeLowCallback rxFreeLowCallback, + IxHssAccPktUserId rxFreeLowUserId, + IxHssAccPktTxDoneCallback txDoneCallback, + IxHssAccPktUserId txDoneUserId); + +/** + * + * @ingroup IxHssAccAPI + * + * @fn IX_STATUS ixHssAccPktPortEnable (IxHssAccHssPort hssPortId, + IxHssAccHdlcPort hdlcPortId) + * + * @brief This function is responsible for enabling a packetised service + * for the specified HSS/HDLC port combination. It enables the RX flow. The + * client must have already connected to a packetised service and is responsible + * for ensuring an adequate amount of RX mbufs have been supplied to the access + * component before enabling the packetised service. This function must be called + * on a given port before any call to ixHssAccPktPortTx on the same port. + * No other HssAccPacketised interface should be called while this interface is + * being processed. + * + * @param hssPortId @ref IxHssAccHssPort [in] - The HSS port Id. There are two + * identical ports (0-1). + * @param hdlcPortId @ref IxHssAccHdlcPort [in] - The port id (0,1,2,3) to enable the service + * on. + * + * @return + * - IX_SUCCESS The function executed successfully + * - IX_FAIL The function did not execute successfully + * - IX_HSSACC_PARAM_ERR The function did not execute successfully due to a + * parameter error + */ +PUBLIC IX_STATUS +ixHssAccPktPortEnable (IxHssAccHssPort hssPortId, + IxHssAccHdlcPort hdlcPortId); + +/** + * @fn IX_STATUS ixHssAccPktPortDisable (IxHssAccHssPort hssPortId, + IxHssAccHdlcPort hdlcPortId) + * + * @brief This function is responsible for disabling a packetised service + * for the specified HSS/HDLC port combination. It disables the RX flow. + * The client must have already connected to and enabled a packetised service + * for the specified HDLC port. This disable interface can be called before a + * disconnect, but is not required to. + * + * @param hssPortId @ref IxHssAccHssPort [in] - The HSS port Id. There are two + * identical ports (0-1). + * @param hdlcPortId @ref IxHssAccHdlcPort [in] - The port id (0,1,2,3) to disable + * the service on. + * + * @return + * - IX_SUCCESS The function executed successfully + * - IX_FAIL The function did not execute successfully + * - IX_HSSACC_PARAM_ERR The function did not execute successfully due to a + * parameter error + */ +PUBLIC IX_STATUS +ixHssAccPktPortDisable (IxHssAccHssPort hssPortId, + IxHssAccHdlcPort hdlcPortId); + +/** + * + * @ingroup IxHssAccAPI + * + * @fn IX_STATUS ixHssAccPktPortDisconnect (IxHssAccHssPort hssPortId, + IxHssAccHdlcPort hdlcPortId) + * + * @brief This function is responsible for disconnecting a client from one + * of the 4 available HDLC ports. It is not required that the Rx Flow + * has been disabled before calling this function. If the RX Flow has not been + * disabled, the disconnect will disable it before proceeding with the + * disconnect. No other HssAccPacketised + * interface should be called while this interface is being processed. + * + * @param hssPortId @ref IxHssAccHssPort [in] - The HSS port Id. There are two + * identical ports (0-1). + * @param hdlcPortId @ref IxHssAccHdlcPort [in] - This is the number of the HDLC port + * to disconnect and it corresponds to the physical E1/T1 trunk i.e. 0, 1, 2, 3 + * + * @return + * - IX_SUCCESS The function executed successfully + * - IX_FAIL The function did not execute successfully + * - IX_HSSACC_PKT_DISCONNECTING The function has initiated the disconnecting + * procedure but it has not completed yet. + */ +PUBLIC IX_STATUS +ixHssAccPktPortDisconnect (IxHssAccHssPort hssPortId, + IxHssAccHdlcPort hdlcPortId); + +/** + * + * @ingroup IxHssAccAPI + * + * @fn BOOL ixHssAccPktPortIsDisconnectComplete (IxHssAccHssPort hssPortId, + IxHssAccHdlcPort hdlcPortId) + * + * @brief This function is called to check if a given HSS/HDLC port + * combination is in a connected state or not. This function may be called + * at any time to determine a ports state. No other HssAccPacketised + * interface should be called while this interface is being processed. + * + * @param hssPortId @ref IxHssAccHssPort [in] - The HSS port Id. There are two + * identical ports (0-1). + * @param hdlcPortId @ref IxHssAccHdlcPort [in] - This is the number of the HDLC port + * to disconnect and it corresponds to the physical E1/T1 trunk i.e. 0, 1, 2, 3 + * + * @return + * - TRUE The state of this HSS/HDLC port combination is disconnected, + * so if a disconnect was called, it is now completed. + * - FALSE The state of this HSS/HDLC port combination is connected, + * so if a disconnect was called, it is not yet completed. + */ +PUBLIC BOOL +ixHssAccPktPortIsDisconnectComplete (IxHssAccHssPort hssPortId, + IxHssAccHdlcPort hdlcPortId); + + +/** + * + * @ingroup IxHssAccAPI + * + * @fn IX_STATUS ixHssAccPktPortRxFreeReplenish (IxHssAccHssPort hssPortId, + IxHssAccHdlcPort hdlcPortId, + IX_OSAL_MBUF *buffer) + * + * @brief Function which the client calls at regular intervals to provide + * mbufs to the access component for RX. A connection should exist for + * the specified hssPortId/hdlcPortId combination before attempting to call this + * interface. Also, the connection should not be in a disconnecting state. + * + * @param hssPortId @ref IxHssAccHssPort [in] - The HSS port Id. There are two + * identical ports (0-1). + * @param hdlcPortId @ref IxHssAccHdlcPort [in] - This is the number of the HDLC port + * and it corresponds to the physical E1/T1 trunk i.e. 0, 1, 2, 3 + * @param *buffer @ref IX_OSAL_MBUF [in] - A pointer to a free mbuf to filled with payload. + * + * @return + * - IX_SUCCESS The function executed successfully + * - IX_FAIL The function did not execute successfully + * - IX_HSSACC_PARAM_ERR The function did not execute successfully due to a + * parameter error + * - IX_HSSACC_RESOURCE_ERR The function did not execute successfully due + * to a resource error + * - IX_HSSACC_Q_WRITE_OVERFLOW The function did not succeed due to a Q + * overflow + */ +PUBLIC IX_STATUS +ixHssAccPktPortRxFreeReplenish (IxHssAccHssPort hssPortId, + IxHssAccHdlcPort hdlcPortId, + IX_OSAL_MBUF *buffer); + +/** + * + * @ingroup IxHssAccAPI + * + * @fn IX_STATUS ixHssAccPktPortTx (IxHssAccHssPort hssPortId, + IxHssAccHdlcPort hdlcPortId, + IX_OSAL_MBUF *buffer) + * + * @brief Function which the client calls when it wants to transmit + * packetised data. An enabled connection should exist on the specified + * hssPortId/hdlcPortId combination before attempting to call this interface. + * No other HssAccPacketised + * interface should be called while this interface is being processed. + * + * @param hssPortId @ref IxHssAccHssPort [in] - The HSS port Id. There are two + * identical ports (0-1). + * @param hdlcPortId @ref IxHssAccHdlcPort [in] - This is the number of the HDLC port + * and it corresponds to the physical E1/T1 trunk i.e. 0, 1, 2, 3 + * @param *buffer @ref IX_OSAL_MBUF [in] - A pointer to a chain of mbufs which the + * client has filled with the payload + * + * @return + * - IX_SUCCESS The function executed successfully + * - IX_FAIL The function did not execute successfully + * - IX_HSSACC_PARAM_ERR The function did not execute successfully due to a + * parameter error + * - IX_HSSACC_RESOURCE_ERR The function did not execute successfully due + * to a resource error. See note. + * - IX_HSSACC_Q_WRITE_OVERFLOW The function did not succeed due to a Q + * overflow + * + * @note IX_HSSACC_RESOURCE_ERR is returned when a free descriptor cannot be + * obtained to send the chain of mbufs to the NPE. This is a normal scenario. + * HssAcc has a pool of descriptors and this error means that they are currently + * all in use. + * The recommended approach to this is to retry until a descriptor becomes free + * and the packet is successfully transmitted. + * Alternatively, the user could wait until the next IxHssAccPktTxDoneCallback + * callback is triggered, and then retry, as it is this event that causes a + * transmit descriptor to be freed. + */ +PUBLIC IX_STATUS +ixHssAccPktPortTx (IxHssAccHssPort hssPortId, + IxHssAccHdlcPort hdlcPortId, + IX_OSAL_MBUF *buffer); + +/** + * + * @ingroup IxHssAccAPI + * + * @fn IX_STATUS ixHssAccChanConnect (IxHssAccHssPort hssPortId, + unsigned bytesPerTSTrigger, + UINT8 *rxCircular, + unsigned numRxBytesPerTS, + UINT32 *txPtrList, + unsigned numTxPtrLists, + unsigned numTxBytesPerBlk, + IxHssAccChanRxCallback rxCallback) + * + * @brief This function allows the client to connect to the Tx/Rx NPE + * Channelised Service. There can only be one client per HSS port. The + * client is responsible for ensuring that the HSS port is configured + * appropriately before its connect request. No other HssAccChannelised + * interface should be called while this interface is being processed. + * + * @param hssPortId @ref IxHssAccHssPort [in] - The HSS port Id. There are two + * identical ports (0-1). + * @param bytesPerTSTrigger unsigned [in] - The NPE will trigger the access + * component after bytesPerTSTrigger have been received for all trunk + * timeslots. This figure is a multiple of 8 e.g. 8 for 1ms trigger, 16 for + * 2ms trigger. + * @param *rxCircular UINT8 [in] - A pointer to memory allocated by the + * client to be filled by data received. The buffer at this address is part + * of a pool of buffers to be accessed in a circular fashion. This address + * will be written to by the NPE. Therefore, it needs to be a physical address. + * @param numRxBytesPerTS unsigned [in] - The number of bytes allocated per + * timeslot within the receive memory. This figure will depend on the + * latency of the system. It needs to be deep enough for data to be read by + * the client before the NPE re-writes over that memory e.g. if the client + * samples at a rate of 40bytes per timeslot, numRxBytesPerTS may need to + * be 40bytes * 3. This would give the client 3 * 5ms of time before + * received data is over-written. + * @param *txPtrList UINT32 [in] - The address of an area of contiguous + * memory allocated by the client to be populated with pointers to data for + * transmission. Each pointer list contains a pointer per active channel. + * The txPtrs will point to data to be transmitted by the NPE. Therefore, + * they must point to physical addresses. + * @param numTxPtrLists unsigned [in] - The number of pointer lists in + * txPtrList. This figure is dependent on jitter. + * @param numTxBytesPerBlk unsigned [in] - The size of the Tx data, in + * bytes, that each pointer within the PtrList points to. + * @param rxCallback @ref IxHssAccChanRxCallback [in] - A client function + * pointer to be called back to handle the actual tx/rx of channelised + * data. If this is not NULL, an ISR will call this function. If this + * pointer is NULL, it implies that the client will use a polling mechanism + * to detect when the tx and rx of channelised data is to occur. The client + * will use hssChanAccStatus for this. + * + * @return + * - IX_SUCCESS The function executed successfully + * - IX_FAIL The function did not execute successfully + * - IX_HSSACC_PARAM_ERR The function did not execute successfully due to a + * parameter error + */ + +PUBLIC IX_STATUS +ixHssAccChanConnect (IxHssAccHssPort hssPortId, + unsigned bytesPerTSTrigger, + UINT8 *rxCircular, + unsigned numRxBytesPerTS, + UINT32 *txPtrList, + unsigned numTxPtrLists, + unsigned numTxBytesPerBlk, + IxHssAccChanRxCallback rxCallback); + +/** + * + * @ingroup IxHssAccAPI + * + * @fn IX_STATUS ixHssAccChanPortEnable (IxHssAccHssPort hssPortId) + * + * @brief This function is responsible for enabling a channelised service + * for the specified HSS port. It enables the NPE RX flow. The client must + * have already connected to a channelised service before enabling the + * channelised service. No other HssAccChannelised + * interface should be called while this interface is being processed. + * + * @param hssPortId @ref IxHssAccHssPort [in] - The HSS port Id. There are two + * identical ports (0-1). + * + * @return + * - IX_SUCCESS The function executed successfully + * - IX_FAIL The function did not execute successfully + * - IX_HSSACC_PARAM_ERR The function did not execute successfully due to a + * parameter error + */ +PUBLIC IX_STATUS +ixHssAccChanPortEnable (IxHssAccHssPort hssPortId); + +/** + * + * @ingroup IxHssAccAPI + * + * @fn IX_STATUS ixHssAccChanPortDisable (IxHssAccHssPort hssPortId) + * + * @brief This function is responsible for disabling a channelised service + * for the specified HSS port. It disables the NPE RX flow. The client must + * have already connected to and enabled a channelised service for the + * specified HSS port. This disable interface can be called before a + * disconnect, but is not required to. No other HssAccChannelised + * interface should be called while this interface is being processed. + * + * @param hssPortId @ref IxHssAccHssPort [in] - The HSS port Id. There are two + * identical ports (0-1). + * + * @return + * - IX_SUCCESS The function executed successfully + * - IX_FAIL The function did not execute successfully + * - IX_HSSACC_PARAM_ERR The function did not execute successfully due to a + * parameter error + */ +PUBLIC IX_STATUS +ixHssAccChanPortDisable (IxHssAccHssPort hssPortId); + +/** + * + * @ingroup IxHssAccAPI + * + * @fn IX_STATUS ixHssAccChanDisconnect (IxHssAccHssPort hssPortId) + * + * @brief This function allows the client to Disconnect from a channelised + * service. If the NPE RX Flow has not been disabled, the disconnect will + * disable it before proceeding with other disconnect functionality. + * No other HssAccChannelised interface should be called while this + * interface is being processed. + * + * @param hssPortId @ref IxHssAccHssPort [in] - The HSS port Id. There are two + * identical ports (0-1). + * + * @return + * - IX_SUCCESS The function executed successfully + * - IX_FAIL The function did not execute successfully + * - IX_HSSACC_PARAM_ERR The function did not execute successfully due to a + * parameter error + */ +PUBLIC IX_STATUS +ixHssAccChanDisconnect (IxHssAccHssPort hssPortId); + +/** + * + * @ingroup IxHssAccAPI + * + * @fn IX_STATUS ixHssAccChanStatusQuery (IxHssAccHssPort hssPortId, + BOOL *dataRecvd, + unsigned *rxOffset, + unsigned *txOffset, + unsigned *numHssErrs) + * + * @brief This function is called by the client to query whether or not + * channelised data has been received. If there is, hssChanAcc will return + * the details in the output parameters. An enabled connection should + * exist on the specified hssPortId before attempting to call this interface. + * No other HssAccChannelised interface should be called while this + * interface is being processed. + * + * @param hssPortId @ref IxHssAccHssPort [in] - The HSS port Id. There are two + * identical ports (0-1). + * @param *dataRecvd BOOL [out] - This BOOL indicates to the client whether + * or not the access component has read any data for the client. If + * FALSE, the other output parameters will not have been written to. + * @param *rxOffset unsigned [out] - An offset to indicate to the client + * where within the receive buffers the NPE has just written the received + * data to. + * @param *txOffset unsigned [out] - An offset to indicate to the client + * from where within the txPtrList the NPE is currently transmitting from + * @param *numHssErrs unsigned [out] - The total number of HSS port errors + * since initial port configuration + * + * + * @return + * - IX_SUCCESS The function executed successfully + * - IX_FAIL The function did not execute successfully + * - IX_HSSACC_PARAM_ERR The function did not execute successfully due to a + * parameter error + */ +PUBLIC IX_STATUS +ixHssAccChanStatusQuery (IxHssAccHssPort hssPortId, + BOOL *dataRecvd, + unsigned *rxOffset, + unsigned *txOffset, + unsigned *numHssErrs); + +/** + * + * @ingroup IxHssAccAPI + * + * @fn void ixHssAccShow (void) + * + * @brief This function will display the current state of the IxHssAcc + * component. The output is sent to stdout. + * + * @return void + */ +PUBLIC void +ixHssAccShow (void); + +/** + * + * @ingroup IxHssAccAPI + * + * @fn void ixHssAccStatsInit (void) + * + * @brief This function will reset the IxHssAcc statistics. + * + * @return void + */ +PUBLIC void +ixHssAccStatsInit (void); + +#endif /* IXHSSACC_H */ + +/** + * @} defgroup IxHssAcc + */ diff --git a/cpu/ixp/npe/include/IxI2cDrv.h b/cpu/ixp/npe/include/IxI2cDrv.h new file mode 100644 index 0000000..2472f31 --- /dev/null +++ b/cpu/ixp/npe/include/IxI2cDrv.h @@ -0,0 +1,867 @@ +/** + * @file IxI2cDrv.h + * + * @brief Header file for the IXP400 I2C Driver (IxI2cDrv) + * + * @version $Revision: 0.1 $ + * + * @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 IxI2cDrv IXP400 I2C Driver(IxI2cDrv) API + * + * @brief IXP400 I2C Driver Public API + * + * @{ + */ +#ifndef IXI2CDRV_H +#define IXI2CDRV_H + +#ifdef __ixp46X +#include "IxOsal.h" + +/* + * Section for #define + */ + +/** + * @ingroup IxI2cDrv + * @brief The interval of micro/mili seconds the IXP will wait before it polls for + * status from the ixI2cIntrXferStatus; Every 20us is 1 byte @ + * 400Kbps and 4 bytes @ 100Kbps. This is dependent on delay type selected + * through the API ixI2cDrvDelayTypeSelect. + */ +#define IX_I2C_US_POLL_FOR_XFER_STATUS 20 + +/** + * @ingroup IxI2cDrv + * @brief The number of tries that will be attempted to call a callback + * function if the callback does not or is unable to resolve the + * issue it is called to resolve + */ +#define IX_I2C_NUM_OF_TRIES_TO_CALL_CALLBACK_FUNC 10 + + +/** + * @ingroup IxI2cDrv + * @brief Number of tries slave will poll the IDBR Rx full bit before it + * gives up + */ +#define IX_I2C_NUM_TO_POLL_IDBR_RX_FULL 0x100 + +/** + * @ingroup IxI2cDrv + * @brief Number of tries slave will poll the IDBR Tx empty bit before it + * gives up + */ +#define IX_I2C_NUM_TO_POLL_IDBR_TX_EMPTY 0x100 + +/* + * Section for enum + */ + +/** + * @ingroup IxI2cDrv + * + * @enum IxI2cMasterStatus + * + * @brief The master status - transfer complete, bus error or arbitration loss + */ +typedef enum +{ + IX_I2C_MASTER_XFER_COMPLETE = IX_SUCCESS, + IX_I2C_MASTER_XFER_BUS_ERROR, + IX_I2C_MASTER_XFER_ARB_LOSS +} IxI2cMasterStatus; + + +/** + * @ingroup IxI2cDrv + * + * @enum IX_I2C_STATUS + * + * @brief The status that can be returned in a I2C driver initialization + */ +typedef enum +{ + IX_I2C_SUCCESS = IX_SUCCESS, /**< Success status */ + IX_I2C_FAIL, /**< Fail status */ + IX_I2C_NOT_SUPPORTED, /**< hardware does not have dedicated I2C hardware */ + IX_I2C_NULL_POINTER, /**< parameter passed in is NULL */ + IX_I2C_INVALID_SPEED_MODE_ENUM_VALUE, /**< speed mode selected is invalid */ + IX_I2C_INVALID_FLOW_MODE_ENUM_VALUE, /**< flow mode selected is invalid */ + IX_I2C_SLAVE_ADDR_CB_MISSING, /**< slave callback is NULL */ + IX_I2C_GEN_CALL_CB_MISSING, /**< general callback is NULL */ + IX_I2C_INVALID_SLAVE_ADDR, /**< invalid slave address specified */ + IX_I2C_INT_BIND_FAIL, /**< interrupt bind fail */ + IX_I2C_INT_UNBIND_FAIL, /**< interrupt unbind fail */ + IX_I2C_NOT_INIT, /**< I2C is not initialized yet */ + IX_I2C_MASTER_BUS_BUSY, /**< master detected a I2C bus busy */ + IX_I2C_MASTER_ARB_LOSS, /**< master experienced arbitration loss */ + IX_I2C_MASTER_XFER_ERROR, /**< master experienced a transfer error */ + IX_I2C_MASTER_BUS_ERROR, /**< master detected a I2C bus error */ + IX_I2C_MASTER_NO_BUFFER, /**< no buffer provided for master transfer */ + IX_I2C_MASTER_INVALID_XFER_MODE, /**< xfer mode selected is invalid */ + IX_I2C_SLAVE_ADDR_NOT_DETECTED, /**< polled slave addr not detected */ + IX_I2C_GEN_CALL_ADDR_DETECTED, /**< polling detected general call */ + IX_I2C_SLAVE_READ_DETECTED, /**< polling detected slave read request */ + IX_I2C_SLAVE_WRITE_DETECTED, /**< polling detected slave write request */ + IX_I2C_SLAVE_NO_BUFFER, /**< no buffer provided for slave transfers */ + IX_I2C_DATA_SIZE_ZERO, /**< data size transfer is zero - invalid */ + IX_I2C_SLAVE_WRITE_BUFFER_EMPTY, /**< slave buffer is used till empty */ + IX_I2C_SLAVE_WRITE_ERROR, /**< slave write experienced an error */ + IX_I2C_SLAVE_OR_GEN_READ_BUFFER_FULL, /**< slave buffer is filled up */ + IX_I2C_SLAVE_OR_GEN_READ_ERROR /**< slave read experienced an error */ +} IX_I2C_STATUS; + +/** + * @ingroup IxI2cDrv + * + * @enum IxI2cSpeedMode + * + * @brief Type of speed modes supported by the I2C hardware. + */ +typedef enum +{ + IX_I2C_NORMAL_MODE = 0x0, + IX_I2C_FAST_MODE +} IxI2cSpeedMode; + +/** + * @ingroup IxI2cDrv + * + * @enum IxI2cXferMode + * + * @brief Used for indicating it is a repeated start or normal transfer + */ +typedef enum +{ + IX_I2C_NORMAL = 0x0, + IX_I2C_REPEATED_START +} IxI2cXferMode; + +/** + * @ingroup IxI2cDrv + * + * @enum IxI2cFlowMode + * + * @brief Used for indicating it is a poll or interrupt mode + */ +typedef enum +{ + IX_I2C_POLL_MODE = 0x0, + IX_I2C_INTERRUPT_MODE +} IxI2cFlowMode; + +/** + * @ingroup IxI2cDrv + * + * @enum IxI2cDelayMode + * + * @brief Used for selecting looping delay or OS scheduler delay + */ +typedef enum +{ + IX_I2C_LOOP_DELAY = 1, /**< delay in microseconds */ + IX_I2C_SCHED_DELAY /**< delay in miliseconds */ +} IxI2cDelayMode; + +/** + * @ingroup IxI2cDrv + * + * @brief The pointer to the function that will be called when the master + * has completed its receive. The parameter that is passed will + * provide the status of the read (success, arb loss, or bus + * error), the transfer mode (normal or repeated start, the + * buffer pointer and number of bytes transferred. + */ +typedef void (*IxI2cMasterReadCallbackP)(IxI2cMasterStatus, IxI2cXferMode, char*, UINT32); + +/** + * @ingroup IxI2cDrv + * + * @brief The pointer to the function that will be called when the master + * has completed its transmit. The parameter that is passed will + * provide the status of the write (success, arb loss, or buss + * error), the transfer mode (normal or repeated start), the + * buffer pointer and number of bytes transferred. + */ +typedef void (*IxI2cMasterWriteCallbackP)(IxI2cMasterStatus, IxI2cXferMode, char*, UINT32); + +/** + * @ingroup IxI2cDrv + * + * @brief The pointer to the function that will be called when a slave + * address detected in interrupt mode for a read. The parameters + * that is passed will provide the read status, buffer pointer, + * buffer size, and the bytes received. When a start of a read + * is initiated there will be no buffer allocated and this callback + * will be called to request for a buffer. While receiving, if the + * buffer gets filled, this callback will be called to request for + * a new buffer while sending the filled buffer's pointer and size, + * and data size received. When the receive is complete, this + * callback will be called to process the data and free the memory + * by passing the buffer's pointer and size, and data size received. + */ +typedef void (*IxI2cSlaveReadCallbackP)(IX_I2C_STATUS, char*, UINT32, UINT32); + +/** + * @ingroup IxI2cDrv + * + * @brief The pointer to the function that will be called when a slave + * address detected in interrupt mode for a write. The parameters + * that is passed will provide the write status, buffer pointer, + * buffer size, and the bytes received. When a start of a write is + * initiated there will be no buffer allocated and this callback + * will be called to request for a buffer and to fill it with data. + * While transmitting, if the data in the buffer empties, this + * callback will be called to request for more data to be filled in + * the same or new buffer. When the transmit is complete, this + * callback will be called to free the memory or other actions to + * be taken. + */ +typedef void (*IxI2cSlaveWriteCallbackP)(IX_I2C_STATUS, char*, UINT32, UINT32); + +/** + * @ingroup IxI2cDrv + * + * @brief The pointer to the function that will be called when a general + * call detected in interrupt mode for a read. The parameters that + * is passed will provide the read status, buffer pointer, buffer + * size, and the bytes received. When a start of a read is + * initiated there will be no buffer allocated and this callback + * will be called to request for a buffer. While receiving, if the + * buffer gets filled, this callback will be called to request for + * a new buffer while sending the filled buffer's pointer and size, + * and data size received. When the receive is complete, this + * callback will be called to process the data and free the memory + * by passing the buffer's pointer and size, and data size received. + */ +typedef void (*IxI2cGenCallCallbackP)(IX_I2C_STATUS, char*, UINT32, UINT32); + +/* + * Section for struct + */ + +/** + * @brief contains all the variables required to initialize the I2C unit + * + * Structure to be filled and used for calling initialization + */ +typedef struct +{ + IxI2cSpeedMode I2cSpeedSelect; /** + * NOTE: 1) An individual callback is to be registered for each Slave and Master + * Auxiliary Time Stamp registers. Thus to register for both Master and Slave time + * stamp interrupts either the same callback or two separate callbacks the API has + * to be invoked twice. + * 2) On the IXDP465 Development Platform, the Auxiliary Timestamp signal for + * slave mode is tied to GPIO 8 pin. This signal is software routed by default to + * PCI for backwards compatibility with the IXDP425 Development Platform. This + * routing must be disabled for the auxiliary slave time stamp register to work + * properly. The following commands may be used to accomplish this. However, refer + * to the IXDP465 Development Platform Users Guide or the BSP/LSP documentation for + * more specific information. + * + * For Linux (at the Redboot prompt i.e., before loading zImage): + * mfill -b 0x54100000 -1 -l 1 -p 8 + * mfill -b 0x54100001 -1 -l 1 -p 0x7f + * For vxWorks, at the prompt: + * intDisable(25) + * ixdp400FpgaIODetach(8) + * + * + * @li Re-entrant : no + * @li ISR Callable : no + * + * @return @li IX_TIMESYNCACC_SUCCESS - Operation is successful + * @li IX_TIMESYNCACC_INVALIDPARAM - Null parameter passed for callback or + invalid auxiliary snapshot mode + * @li IX_TIMESYNCACC_FAILED - Internal error occurred + */ +PUBLIC IxTimeSyncAccStatus +ixTimeSyncAccAuxTimeInterruptEnable(IxTimeSyncAccAuxMode auxMode, + IxTimeSyncAccAuxTimeCallback auxTimeCallback); + +/** + * @ingroup IxTimeSyncAcc + * + * @fn IxTimeSyncAccStatus ixTimeSyncAccAuxTimeInterruptDisable( + IxTimeSyncAccAuxMode auxMode) + * + * @brief Disables the interrupt for the indicated mode of Auxiliary Time Stamp + * in the IEEE 1588 hardware assist block + * + * @param auxMode [in] - Auxiliary time stamp mode (slave or master) using which + * the interrupt will be disabled. + * + * This API will disable the Auxiliary Time Stamp Interrupt (Master or Slave) + * + * @li Re-entrant : yes + * @li ISR Callable : no + * + * @return @li IX_TIMESYNCACC_SUCCESS - Operation is successful + * @li IX_TIMESYNCACC_INVALIDPARAM - Invalid parameters passed + * @li IX_TIMESYNCACC_FAILED - Internal error occurred + */ +PUBLIC IxTimeSyncAccStatus +ixTimeSyncAccAuxTimeInterruptDisable(IxTimeSyncAccAuxMode auxMode); + +/** + * @ingroup IxTimeSyncAcc + * + * @fn IxTimeSyncAccStatus ixTimeSyncAccAuxTimePoll( + IxTimeSyncAccAuxMode auxMode, + BOOL *auxPollFlag, + IxTimeSyncAccTimeValue *auxTime) + * + * @brief Poll for the Auxiliary Time Stamp captured for the mode indicated + * (Master or Slave) + * + * @param auxMode [in] - Auxiliary Snapshot Register (Slave or Master) to be checked + * @param auxPollFlag [out] - TRUE if the time stamp captured in auxiliary + snapshot register + * FALSE if the time stamp not captured in + auxiliary snapshot register + * @param auxTime [out] - Copy the current Auxiliary Snapshot Register value into the + * client provided buffer + * + * Polls for the Time stamp in the appropriate Auxiliary Snapshot Registers based + * on the mode specified. Return true and the contents of the Auxiliary snapshot, + * if it is available else return false. + * + * Please refer to the note #2 of the API @ref ixTimeSyncAccAuxTimeInterruptEnable + * for more information for Auxiliary Slave mode. + * + * @li Re-entrant : yes + * @li ISR Callable : no + * + * @return @li IX_TIMESYNCACC_SUCCESS - Operation is successful + * @li IX_TIMESYNCACC_INVALIDPARAM - Null parameter passed for auxPollFlag, + callback or invalid auxiliary snapshot mode + * @li IX_TIMESYNCACC_FAILED - Internal error occurred + * @li IX_TIMESYNCACC_INTERRUPTMODEINUSE - Interrupt mode in use + */ +PUBLIC IxTimeSyncAccStatus +ixTimeSyncAccAuxTimePoll(IxTimeSyncAccAuxMode auxMode, + BOOL *auxPollFlag, + IxTimeSyncAccTimeValue *auxTime); + +/** + * @ingroup IxTimeSyncAcc + * + * @fn IxTimeSyncAccStatus ixTimeSyncAccReset(void) + * + * @brief Resets the IEEE 1588 hardware assist block + * + * Sets the reset bit in the IEEE1588 silicon which fully resets the silicon block + * + * @li Reentrant : yes + * @li ISR Callable : no + * + * @return @li IX_TIMESYNCACC_SUCCESS - Operation is successful + * @li IX_TIMESYNCACC_FAILED - Internal error occurred + */ +PUBLIC IxTimeSyncAccStatus +ixTimeSyncAccReset(void); + +/** + * @ingroup IxTimeSyncAcc + * + * @fn IxTimeSyncAccStatus ixTimeSyncAccStatsGet(IxTimeSyncAccStats + *timeSyncStats) + * + * @brief Returns the IxTimeSyncAcc Statistics in the client supplied buffer + * + * @param timeSyncStats [out] - TimeSync statistics counter values + * + * This API will return the statistics of the received or transmitted messages. + * + * NOTE: 1) These counters are updated only when the client polls for the time + * stamps or interrupt are enabled. This is because the IxTimeSyncAcc module + * does not either transmit or receive messages and does only run the code + * when explicit requests received by client application. + * + * 2) These statistics reflect the number of valid PTP messages exchanged + * in Master and Slave modes but includes all the messages (including valid + * non-PTP messages) while operating in the Any mode. + * + * @li Reentrant : no + * @li ISR Callable : no + * + * @return @li IX_TIMESYNCACC_SUCCESS - Operation is successful + * @li IX_TIMESYNCACC_INVALIDPARAM - NULL parameter passed + * @li IX_TIMESYNCACC_FAILED - Internal error occurred + */ +PUBLIC IxTimeSyncAccStatus +ixTimeSyncAccStatsGet(IxTimeSyncAccStats *timeSyncStats); + +/** + * @ingroup IxTimeSyncAcc + * + * @fn void ixTimeSyncAccStatsReset(void) + * + * @brief Reset Time Sync statistics + * + * This API will reset the statistics counters of the TimeSync access layer. + * + * @li Reentrant : yes + * @li ISR Callable: no + * + * @return @li None + */ +PUBLIC void +ixTimeSyncAccStatsReset(void); + +/** + * @ingroup IxTimeSyncAcc + * + * @fn IxTimeSyncAccStatus ixTimeSyncAccShow(void) + * + * @brief Displays the Time Sync current status + * + * This API will display status on the current configuration of the IEEE + * 1588 hardware assist block, contents of the various time stamp registers, + * outstanding interrupts and/or events. + * + * Note that this is intended for debug only, and in contrast to the other + * functions, it does not clear the any of the status bits associated with + * active timestamps and so is passive in its nature. + * + * @li Reentrant : yes + * @li ISR Callable : no + * + * @return @li IX_TIMESYNCACC_SUCCESS - Operation is successful + * @li IX_TIMESYNCACC_FAILED - Internal error occurred + */ +PUBLIC IxTimeSyncAccStatus +ixTimeSyncAccShow(void); + +#endif /* __ixp46X */ +#endif /* IXTIMESYNCACC_H */ + +/** + * @} defgroup IxTimeSyncAcc + */ + diff --git a/cpu/ixp/npe/include/IxTimerCtrl.h b/cpu/ixp/npe/include/IxTimerCtrl.h new file mode 100644 index 0000000..669dd3e --- /dev/null +++ b/cpu/ixp/npe/include/IxTimerCtrl.h @@ -0,0 +1,263 @@ +/** + * @file IxTimerCtrl.h + * @brief + * This is the header file for the Timer Control component. + * + * The timer callback control component provides a mechanism by which different + * client components can start a timer and have a supplied callback function + * invoked when the timer expires. + * The callbacks are all dispatched from one thread inside this component. + * Any component that needs to be called periodically should use this facility + * rather than create its own task with a sleep loop. + * + * @par + * + * @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 IxTimerCtrl IXP400 Timer Control (IxTimerCtrl) API + * + * @brief The public API for the IXP400 Timer Control Component. + * + * @{ + */ + +#ifndef IxTimerCtrl_H +#define IxTimerCtrl_H + + +#include "IxTypes.h" +/* #include "Ossl.h" */ + +/* + * #defines and macros used in this file. + */ + +/** + * @ingroup IxTimerCtrl + * + * @def IX_TIMERCTRL_NO_FREE_TIMERS + * + * @brief Timer schedule return code. + * + * Indicates that the request to start a timer failed because + * all available timer resources are used. + */ +#define IX_TIMERCTRL_NO_FREE_TIMERS 2 + + +/** + * @ingroup IxTimerCtrl + * + * @def IX_TIMERCTRL_PARAM_ERROR + * + * @brief Timer schedule return code. + * + * Indicates that the request to start a timer failed because + * the client has supplied invalid parameters. + */ +#define IX_TIMERCTRL_PARAM_ERROR 3 + + +/* + * Typedefs whose scope is limited to this file. + */ + +/** + * @ingroup IxTimerCtrl + * + * @brief A typedef for a pointer to a timer callback function. + * @para void * - This parameter is supplied by the client when the + * timer is started and passed back to the client in the callback. + * @note in general timer callback functions should not block or + * take longer than 100ms. This constraint is required to ensure that + * higher priority callbacks are not held up. + * All callbacks are called from the same thread. + * This thread is a shared resource. + * The parameter passed is provided when the timer is scheduled. + */ +typedef void (*IxTimerCtrlTimerCallback)(void *userParam); + + +/** + * @ingroup IxTimerCtrl + * + * @brief List used to identify the users of timers. + * @note The order in this list indicates priority. Components appearing + * higher in the list will be given priority over components lower in the + * list. When adding components, please insert at an appropriate position + * for priority ( i.e values should be less than IxTimerCtrlMaxPurpose ) . + */ +typedef enum +{ + IxTimerCtrlAdslPurpose, + /* Insert new purposes above this line only + */ + IxTimerCtrlMaxPurpose +} +IxTimerCtrlPurpose; + + +/* + * Function definition + */ + +/** + * @ingroup IxTimerCtrl + * + * @fn ixTimerCtrlSchedule(IxTimerCtrlTimerCallback func, + void *userParam, + IxTimerCtrlPurpose purpose, + UINT32 relativeTime, + unsigned *timerId ) + * + * @brief Schedules a callback function to be called after a period of "time". + * The callback function should not block or run for more than 100ms. + * This function + * + * @param func @ref IxTimerCtrlTimerCallback [in] - the callback function to be called. + * @param userParam void [in] - a parameter to send to the callback function, can be NULL. + * @param purpose @ref IxTimerCtrlPurpose [in] - the purpose of the callback, internally this component will + * decide the priority of callbacks with different purpose. + * @param relativeTime UINT32 [in] - time relative to now in milliseconds after which the callback + * will be called. The time must be greater than the duration of one OS tick. + * @param *timerId unsigned [out] - An id for the callback scheduled. + * This id can be used to cancel the callback. + * @return + * @li IX_SUCCESS - The timer was started successfully. + * @li IX_TIMERCTRL_NO_FREE_TIMERS - The timer was not started because the maximum number + * of running timers has been exceeded. + * @li IX_TIMERCTRL_PARAM_ERROR - The timer was not started because the client has supplied + * a NULL callback func, or the requested timeout is less than one OS tick. + * @note This function is re-entrant. The function accesses a list of running timers + * and may suspend the calling thread if this list is being accesed by another thread. + */ +PUBLIC IX_STATUS +ixTimerCtrlSchedule(IxTimerCtrlTimerCallback func, + void *userParam, + IxTimerCtrlPurpose purpose, + UINT32 relativeTime, + unsigned *timerId ); + + +/** + * @ingroup IxTimerCtrl + * + * @fn ixTimerCtrlScheduleRepeating(IxTimerCtrlTimerCallback func, + void *param, + IxTimerCtrlPurpose purpose, + UINT32 interval, + unsigned *timerId ) + * + * @brief Schedules a callback function to be called after a period of "time". + * The callback function should not block or run for more than 100ms. + * + * @param func @ref IxTimerCtrlTimerCallback [in] - the callback function to be called. + * @param userParam void [in] - a parameter to send to the callback function, can be NULL. + * @param purpose @ref IxTimerCtrlPurpose [in] - the purpose of the callback, internally this component will + * decide the priority of callbacks with different purpose. + * @param interval UINT32 [in] - the interval in milliseconds between calls to func. + * @param timerId unsigned [out] - An id for the callback scheduled. + * This id can be used to cancel the callback. + * @return + * @li IX_SUCCESS - The timer was started successfully. + * @li IX_TIMERCTRL_NO_FREE_TIMERS - The timer was not started because the maximum number + * of running timers has been exceeded. + * @li IX_TIMERCTRL_PARAM_ERROR - The timer was not started because the client has supplied + * a NULL callback func, or the requested timeout is less than one OS tick. + * @note This function is re-entrant. The function accesses a list of running timers + * and may suspend the calling thread if this list is being accesed by another thread. + */ +PUBLIC IX_STATUS +ixTimerCtrlScheduleRepeating(IxTimerCtrlTimerCallback func, + void *param, + IxTimerCtrlPurpose purpose, + UINT32 interval, + unsigned *timerId ); + +/** + * @ingroup IxTimerCtrl + * + * @fn ixTimerCtrlCancel (unsigned id) + * + * @brief Cancels a scheduled callback. + * + * @param id unsigned [in] - the id of the callback to be cancelled. + * @return + * @li IX_SUCCESS - The timer was successfully stopped. + * @li IX_FAIL - The id parameter did not corrrespond to any running timer.. + * @note This function is re-entrant. The function accesses a list of running timers + * and may suspend the calling thread if this list is being accesed by another thread. + */ +PUBLIC IX_STATUS +ixTimerCtrlCancel (unsigned id); + +/** + * @ingroup IxTimerCtrl + * + * @fn ixTimerCtrlInit(void) + * + * @brief Initialise the Timer Control Component. + * @return + * @li IX_SUCCESS - The timer control component initialized successfully. + * @li IX_FAIL - The timer control component initialization failed, + * or the component was already initialized. + * @note This must be done before any other API function is called. + * This function should be called once only and is not re-entrant. + */ +PUBLIC IX_STATUS +ixTimerCtrlInit(void); + + +/** + * @ingroup IxTimerCtrl + * + * @fn ixTimerCtrlShow( void ) + * + * @brief Display the status of the Timer Control Component. + * @return void + * @note Displays a list of running timers. + * This function is not re-entrant. This function does not suspend the calling thread. + */ +PUBLIC void +ixTimerCtrlShow( void ); + +#endif /* IXTIMERCTRL_H */ + diff --git a/cpu/ixp/npe/include/IxTypes.h b/cpu/ixp/npe/include/IxTypes.h new file mode 100644 index 0000000..c4c5a2d26 --- /dev/null +++ b/cpu/ixp/npe/include/IxTypes.h @@ -0,0 +1,86 @@ +/** + * @file IxTypes.h (Replaced by OSAL) + * + * @date 28-NOV-2001 + + * @brief This file contains basic types used by the IXP400 software + * + * Design Notes: + * This file shall only include fundamental types and definitions to be + * shared by all the IXP400 components. + * Please DO NOT add component-specific types here. + * + * + * @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 IxTypes IXP400 Types (IxTypes) + * + * @brief Basic data types used by the IXP400 project + * + * @{ + */ + +#ifndef IxTypes_H + +#ifndef __doxygen_HIDE + +#define IxTypes_H + +#endif /* __doxygen_HIDE */ + + +/* WR51880: Undefined data types workaround for backward compatibility */ +#ifdef __linux +#ifndef __INCvxTypesOldh +typedef int (*FUNCPTR)(void); +typedef int STATUS; +#define OK (0) +#define ERROR (-1) +#endif +#endif + +#include "IxOsalBackward.h" + +#endif /* IxTypes_H */ + +/** + * @} addtogroup IxTypes + */ diff --git a/cpu/ixp/npe/include/IxUART.h b/cpu/ixp/npe/include/IxUART.h new file mode 100644 index 0000000..03a4444 --- /dev/null +++ b/cpu/ixp/npe/include/IxUART.h @@ -0,0 +1,458 @@ +/** + * @file IxUART.h + * + * @date 12-OCT-01 + * + * @brief Public header for the Intel IXP400 internal UART, generic driver. + * + * Design Notes: + * This driver allows you to perform the following functions: + * Device Initialization, + * send/receive characters. + * + * Perform Uart IOCTL for the following: + * Set/Get the current baud rate, + * set parity, + * set the number of Stop bits, + * set the character Length (5,6,7,8), + * enable/disable Hardware flow control. + * + * Only Polled mode is supported for now. + * + * + * @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 IxUARTAccAPI IXP400 UART Access (IxUARTAcc) API + * + * @brief IXP400 UARTAcc Driver Public API + * + * @{ + */ + + +/* Defaults */ + +/** + * @defgroup DefaultDefines Defines for Default Values + * + * @brief Default values which can be used for UART configuration + * + * @sa ixUARTDev + */ + +/** + * @def IX_UART_DEF_OPTS + * + * @brief The default hardware options to set the UART to - + * no flow control, 8 bit word, 1 stop bit, no parity + * + * @ingroup DefaultDefines + */ +#define IX_UART_DEF_OPTS (CLOCAL | CS8) + +/** + * @def IX_UART_DEF_XMIT + * + * @brief The default UART FIFO size - must be no bigger than 64 + * + * @ingroup DefaultDefines + */ +#define IX_UART_DEF_XMIT 64 + +/** + * @def IX_UART_DEF_BAUD + * + * @brief The default UART baud rate - 9600 + * + * @ingroup DefaultDefines + */ +#define IX_UART_DEF_BAUD 9600 + +/** + * @def IX_UART_MIN_BAUD + * + * @brief The minimum UART baud rate - 9600 + * + * @ingroup DefaultDefines + */ +#define IX_UART_MIN_BAUD 9600 + +/** + * @def IX_UART_MAX_BAUD + * + * @brief The maximum UART baud rate - 926100 + * + * @ingroup DefaultDefines + */ +#define IX_UART_MAX_BAUD 926100 + +/** + * @def IX_UART_XTAL + * + * @brief The UART clock speed + * + * @ingroup DefaultDefines + */ +#define IX_UART_XTAL 14745600 + + + +/* IOCTL commands (Request codes) */ + +/** + * @defgroup IoctlCommandDefines Defines for IOCTL Commands + * + * @brief IOCTL Commands (Request codes) which can be used + * with @ref ixUARTIoctl + */ + + +/** + * @ingroup IoctlCommandDefines + * + * @def IX_BAUD_SET + * + * @brief Set the baud rate + */ +#define IX_BAUD_SET 0 + +/** + * @ingroup IoctlCommandDefines + * + * @def IX_BAUD_GET + * + * @brief Get the baud rate + */ +#define IX_BAUD_GET 1 + +/** + * @ingroup IoctlCommandDefines + * @def IX_MODE_SET + * @brief Set the UART mode of operation + */ +#define IX_MODE_SET 2 + +/** + * @ingroup IoctlCommandDefines + * + * @def IX_MODE_GET + * + * @brief Get the current UART mode of operation + */ +#define IX_MODE_GET 3 + +/** + * @ingroup IoctlCommandDefines + * + * @def IX_OPTS_SET + * + * @brief Set the UART device options + */ +#define IX_OPTS_SET 4 + +/** + * @ingroup IoctlCommandDefines + * + * @def IX_OPTS_GET + * + * @brief Get the UART device options + */ +#define IX_OPTS_GET 5 + +/** + * @ingroup IoctlCommandDefines + * + * @def IX_STATS_GET + * + * @brief Get the UART statistics + */ +#define IX_STATS_GET 6 + + +/* POSIX style ioctl arguments */ + +/** + * @defgroup IoctlArgDefines Defines for IOCTL Arguments + * + * @brief POSIX style IOCTL arguments which can be used + * with @ref ixUARTIoctl + * + * @sa ixUARTMode + */ + + +/** + * @ingroup IoctlArgDefines + * + * @def CLOCAL + * + * @brief Software flow control + */ +#ifdef CLOCAL +#undef CLOCAL +#endif +#define CLOCAL 0x1 + +/** + * @ingroup IoctlArgDefines + * + * @def CREAD + * + * @brief Enable interrupt receiver + */ +#ifdef CREAD +#undef CREAD +#endif +#define CREAD 0x2 + +/** + * @ingroup IoctlArgDefines + * + * @def CSIZE + * + * @brief Characters size + */ +#ifdef CSIZE +#undef CSIZE +#endif +#define CSIZE 0xc + +/** + * @ingroup IoctlArgDefines + * + * @def CS5 + * + * @brief 5 bits + */ +#ifdef CS5 +#undef CS5 +#endif +#define CS5 0x0 + +/** + * @ingroup IoctlArgDefines + * + * @def CS6 + * + * @brief 6 bits + */ +#ifdef CS6 +#undef CS6 +#endif +#define CS6 0x4 + +/** + * @ingroup IoctlArgDefines + * + * @def CS7 + * + * @brief 7 bits + */ +#ifdef CS7 +#undef CS7 +#endif +#define CS7 0x8 + +/** + * @ingroup IoctlArgDefines + * + * @def CS8 + * + * @brief 8 bits + */ +#ifdef CS8 +#undef CS8 +#endif +#define CS8 0xc + +/** + * @ingroup IoctlArgDefines + * + * @def STOPB + * + * @brief Send two stop bits (else one) + */ +#define STOPB 0x20 + +/** + * @ingroup IoctlArgDefines + * + * @def PARENB + * + * @brief Parity detection enabled (else disabled) + */ +#ifdef PARENB +#undef PARENB +#endif +#define PARENB 0x40 + +/** + * @ingroup IoctlArgDefines + * + * @def PARODD + * + * @brief Odd parity (else even) + */ +#ifdef PARODD +#undef PARODD +#endif +#define PARODD 0x80 + +/** + * @enum ixUARTMode + * @brief The mode to set to UART to. + */ +typedef enum +{ + INTERRUPT=0, /**< Interrupt mode */ + POLLED, /**< Polled mode */ + LOOPBACK /**< Loopback mode */ +} ixUARTMode; + +/** + * @struct ixUARTStats + * @brief Statistics for the UART. + */ +typedef struct +{ + UINT32 rxCount; + UINT32 txCount; + UINT32 overrunErr; + UINT32 parityErr; + UINT32 framingErr; + UINT32 breakErr; +} ixUARTStats; + +/** + * @struct ixUARTDev + * @brief Device descriptor for the UART. + */ +typedef struct +{ + UINT8 *addr; /**< device base address */ + ixUARTMode mode; /**< interrupt, polled or loopback */ + int baudRate; /**< baud rate */ + int freq; /**< UART clock frequency */ + int options; /**< hardware options */ + int fifoSize; /**< FIFO xmit size */ + + ixUARTStats stats; /**< device statistics */ +} ixUARTDev; + +/** + * @ingroup IxUARTAccAPI + * + * @fn IX_STATUS ixUARTInit(ixUARTDev* pUART) + * + * @param pUART @ref ixUARTDev [in] - pointer to UART structure describing our device. + * + * @brief Initialise the UART. This puts the chip in a quiescent state. + * + * @pre The base address for the UART must contain a valid value. + * Also the baud rate and hardware options must contain sensible values + * otherwise the defaults will be used as defined in ixUART.h + * + * @post UART is initialized and ready to send and receive data. + * + * @note This function should only be called once per device. + * + * @retval IX_SUCCESS - UART device successfully initialised. + * @retval IX_FAIL - Critical error, device not initialised. + ***************************************************************************/ +PUBLIC IX_STATUS ixUARTInit(ixUARTDev* pUART); + +/** + * @ingroup IxUARTAccAPI + * + * @fn IX_STATUS ixUARTPollOutput(ixUARTDev* pUART, int outChar) + * + * @param pUART @ref ixUARTDev [out] - pointer to UART structure describing our device. + * @param outChar int [out] - character to transmit. + * + * @brief Transmit a character in polled mode. + * + * @pre UART device must be initialised. + * + * @retval IX_SUCCESS - character was successfully transmitted. + * @retval IX_FAIL - output buffer is full (try again). + ***************************************************************************/ +PUBLIC IX_STATUS ixUARTPollOutput(ixUARTDev* pUART, int outChar); + +/** + * @ingroup IxUARTAccAPI + * + * @fn IX_STATUS ixUARTPollInput(ixUARTDev* pUART, char *inChar) + * + * @param pUART @ref ixUARTDev [in] - pointer to UART structure describing our device. + * @param *inChar char [in] - character read from the device. + * + * @brief Receive a character in polled mode. + * + * @pre UART device must be initialised. + * + * @retval IX_SUCCESS - character was successfully read. + * @retval IX_FAIL - input buffer empty (try again). + ***************************************************************************/ +PUBLIC IX_STATUS ixUARTPollInput(ixUARTDev* pUART, char *inChar); + +/** + * @ingroup IxUARTAccAPI + * + * @fn IX_STATUS ixUARTIoctl(ixUARTDev* pUART, int cmd, void* arg) + * + * @param pUART @ref ixUARTDev [in] - pointer to UART structure describing our device. + * @param cmd int [in] - an ioctl request code. + * @param arg void* [in] - optional argument used to set the device mode, + * baud rate, and hardware options. + * + * @brief Perform I/O control routines on the device. + * + * @retval IX_SUCCESS - requested feature was set/read successfully. + * @retval IX_FAIL - error setting/reading the requested feature. + * + * @sa IoctlCommandDefines + * @sa IoctlArgDefines + ***************************************************************************/ +PUBLIC IX_STATUS ixUARTIoctl(ixUARTDev* pUART, int cmd, void* arg); + +/** + * @} defgroup IxUARTAcc + */ diff --git a/cpu/ixp/npe/include/IxVersionId.h b/cpu/ixp/npe/include/IxVersionId.h new file mode 100644 index 0000000..27796ed --- /dev/null +++ b/cpu/ixp/npe/include/IxVersionId.h @@ -0,0 +1,155 @@ +/** + * @file IxVersionId.h + * + * @date 22-Aug-2002 + * + * @brief This file contains the IXP400 Software version identifier + * + * + * @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 IxVersionId IXP400 Version ID (IxVersionId) + * + * @brief Version Identifiers + * + * @{ + */ + +#ifndef IXVERSIONID_H +#define IXVERSIONID_H + +/** + * @brief Version Identifier String + * + * This string will be updated with each customer release of the IXP400 + * Software. + */ +#define IX_VERSION_ID "2_0" + +/** + * This string will be updated with each customer release of the IXP400 + * ADSL driver package. + */ +#define IX_VERSION_ADSL_ID "1_12" + + +/** + * This string will be updated with each customer release of the IXP400 + * USB Client driver package. + */ +#define IX_VERSION_USBRNDIS_ID "1_9" + +/** + * This string will be updated with each customer release of the IXP400 + * I2C Linux driver package. + */ +#define IX_VERSION_I2C_LINUX_ID "1_0" + +/** + * @brief Linux Ethernet Driver Patch Version Identifier String + * + * This string will be updated with each release of Linux Ethernet Patch + */ +#define LINUX_ETHERNET_DRIVER_PATCH_ID "1_4" + +/** + * @brief Linux Integration Patch Version Identifier String + * + * This String will be updated with each release of Linux Integration Patch + */ +#define LINUX_INTEGRATION_PATCH_ID "1_3" + +/** + * @brief Linux Ethernet Readme version Identifier String + * + * This string will be updated with each release of Linux Ethernet Readme + */ +#define LINUX_ETHERNET_README_ID "1_3" + +/** + * @brief Linux Integration Readme version Identifier String + * + * This string will be updated with each release of Linux Integration Readme + */ + +#define LINUX_INTEGRATION_README_ID "1_3" + +/** + * @brief Linux I2C driver Readme version Identifier String + * + * This string will be updated with each release of Linux I2C Driver Readme + */ +#define LINUX_I2C_DRIVER_README_ID "1_0" + +/** + * @brief ixp425_eth_update_nf_bridge.patch version Identifier String + * + * This string will be updated with each release of ixp425_eth_update_nf_bridge. +patch + * + */ + +#define IXP425_ETH_UPDATE_NF_BRIDGE_ID "1_3" + +/** + * @brief Internal Release Identifier String + * + * This string will be updated with each internal release (SQA drop) + * of the IXP400 Software. + */ +#define IX_VERSION_INTERNAL_ID "SQA3_5" + +/** + * @brief Compatible Tornado Version Identifier + */ +#define IX_VERSION_COMPATIBLE_TORNADO "Tornado2_2_1-PNE2_0" + +/** + * @brief Compatible Linux Version Identifier + */ +#define IX_VERSION_COMPATIBLE_LINUX "MVL3_1" + + +#endif /* IXVERSIONID_H */ + +/** + * @} addtogroup IxVersionId + */ diff --git a/cpu/ixp/npe/include/ix_error.h b/cpu/ixp/npe/include/ix_error.h new file mode 100644 index 0000000..d32ace2 --- /dev/null +++ b/cpu/ixp/npe/include/ix_error.h @@ -0,0 +1,66 @@ +/** + * ============================================================================ + * = COPYRIGHT + * + * @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 -- + * = PRODUCT + * Intel(r) IXP425 Software Release + * + * = FILENAME + * ix_error.h (Replaced by OSAL) + * + * = DESCRIPTION + * This file will describe the basic error type and support functions that + * will be used by the IXA SDK Framework API. + * + * = AUTHOR + * Intel Corporation + * + * = CHANGE HISTORY + * 4/22/2002 4:19:03 PM - creation time + * ============================================================================ + */ + +#if !defined(__IX_ERROR_H__) +#define __IX_ERROR_H__ + +#include "IxOsalBackward.h" + +#endif /* end !defined(__IX_ERROR_H__) */ + diff --git a/cpu/ixp/npe/include/ix_macros.h b/cpu/ixp/npe/include/ix_macros.h new file mode 100644 index 0000000..53f5942 --- /dev/null +++ b/cpu/ixp/npe/include/ix_macros.h @@ -0,0 +1,266 @@ +/** + * ============================================================================ + * = COPYRIGHT + * + * @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 -- + * = PRODUCT + * Intel(r) IXP425 Software Release + * + * = FILENAME + * ix_macros.h + * + * = DESCRIPTION + * This file will define the basic preprocessor macros that are going to be used + * the IXA SDK Framework API. + * + * = AUTHOR + * Intel Corporation + * + * = CHANGE HISTORY + * 4/22/2002 4:41:05 PM - creation time + * ============================================================================ + */ + +#if !defined(__IX_MACROS_H__) +#define __IX_MACROS_H__ + + +#if defined(__cplusplus) +extern "C" +{ +#endif /* end defined(__cplusplus) */ + + +/** + * MACRO NAME: IX_BIT_FIELD_MASK16 + * + * DESCRIPTION: Builds the mask required to extract the bit field from a 16 bit unsigned integer value. + * + * @Param: - IN arg_FieldLSBBit an unsigned integer value representing the position of the least significant + * bit of the bit field. + * @Param: - IN arg_FieldMSBBit an unsigned integer value representing the position of the most significant + * bit of the bit field. + * + * @Return: Returns a 16 bit mask that will extract the bit field from a 16 bit unsigned integer value. + */ +#define IX_BIT_FIELD_MASK16( \ + arg_FieldLSBBit, \ + arg_FieldMSBBit \ + ) \ + ((ix_bit_mask16)((((ix_uint16)1 << (arg_FieldMSBBit + 1 - arg_FieldLSBBit)) - \ + (ix_uint16)1) << arg_FieldLSBBit)) + + + +/** + * MACRO NAME: IX_GET_BIT_FIELD16 + * + * DESCRIPTION: Extracts a bit field from 16 bit unsigned integer. The returned value is normalized in + * in the sense that will be right aligned. + * + * @Param: - IN arg_PackedData16 a 16 bit unsigned integer that contains the bit field of interest. + * @Param: - IN arg_FieldLSBBit an unsigned integer value representing the position of the least significant + * bit of the bit field. + * @Param: - IN arg_FieldMSBBit an unsigned integer value representing the position of the most significant + * bit of the bit field. + * + * @Return: Returns the value of the bit field. The value can be from 0 to (1 << (arg_FieldMSBBit + 1 - + * arg_FieldLSBBit)) - 1. + */ +#define IX_GET_BIT_FIELD16( \ + arg_PackedData16, \ + arg_FieldLSBBit, \ + arg_FieldMSBBit \ + ) \ + (((ix_uint16)(arg_PackedData16) & IX_BIT_FIELD_MASK16(arg_FieldLSBBit, arg_FieldMSBBit)) >> \ + arg_FieldLSBBit) + + +/** + * MACRO NAME: IX_MAKE_BIT_FIELD16 + * + * DESCRIPTION: This macro will create a temporary 16 bit value with the bit field + * desired set to the desired value. + * + * @Param: - IN arg_BitFieldValue is the new value of the bit field. The value can be from 0 to + * (1 << (arg_FieldMSBBit + 1 - arg_FieldLSBBit)) - 1. + * @Param: - IN arg_FieldLSBBit an unsigned integer value representing the position of the least significant + * bit of the bit field. + * @Param: - IN arg_FieldMSBBit an unsigned integer value representing the position of the most significant + * bit of the bit field. + * + * @Return: Returns a temporary ix_uint16 value that has the bit field set to the appropriate value. + */ +#define IX_MAKE_BIT_FIELD16( \ + arg_BitFieldValue, \ + arg_FieldLSBBit, \ + arg_FieldMSBBit \ + ) \ + (((ix_uint16)(arg_BitFieldValue) << arg_FieldLSBBit) & \ + IX_BIT_FIELD_MASK16(arg_FieldLSBBit, arg_FieldMSBBit)) + +/** + * MACRO NAME: IX_SET_BIT_FIELD16 + * + * DESCRIPTION: Sets a new value for a bit field from a 16 bit unsigned integer. + * + * @Param: - IN arg_PackedData16 a 16 bit unsigned integer that contains the bit field of interest. + * @Param: - IN arg_BitFieldValue is the new vale of the bit field. The value can be from 0 to + * (1 << (arg_FieldMSBBit + 1 - arg_FieldLSBBit)) - 1. + * @Param: - IN arg_FieldLSBBit an unsigned integer value representing the position of the least significant + * bit of the bit field. + * @Param: - IN arg_FieldMSBBit an unsigned integer value representing the position of the most significant + * bit of the bit field. + * + * @Return: Returns the updated value of arg_PackedData16. + */ +#define IX_SET_BIT_FIELD16( \ + arg_PackedData16, \ + arg_BitFieldValue, \ + arg_FieldLSBBit, \ + arg_FieldMSBBit \ + ) \ + (arg_PackedData16 = (((ix_uint16)(arg_PackedData16) & \ + ~(IX_BIT_FIELD_MASK16(arg_FieldLSBBit, arg_FieldMSBBit))) | \ + IX_MAKE_BIT_FIELD16(arg_BitFieldValue, arg_FieldLSBBit, arg_FieldMSBBit))) + + +/** + * MACRO NAME: IX_BIT_FIELD_MASK32 + * + * DESCRIPTION: Builds the mask required to extract the bit field from a 32 bit unsigned integer value. + * + * @Param: - IN arg_FieldLSBBit an unsigned integer value representing the position of the least significant + * bit of the bit field. + * @Param: - IN arg_FieldMSBBit an unsigned integer value representing the position of the most significant + * bit of the bit field. + * + * @Return: Returns a 32 bit mask that will extract the bit field from a 32 bit unsigned integer value. + */ +#define IX_BIT_FIELD_MASK32( \ + arg_FieldLSBBit, \ + arg_FieldMSBBit \ + ) \ + ((ix_bit_mask32)((((ix_uint32)1 << (arg_FieldMSBBit + 1 - arg_FieldLSBBit)) - \ + (ix_uint32)1) << arg_FieldLSBBit)) + + + +/** + * MACRO NAME: IX_GET_BIT_FIELD32 + * + * DESCRIPTION: Extracts a bit field from 32 bit unsigned integer. The returned value is normalized in + * in the sense that will be right aligned. + * + * @Param: - IN arg_PackedData32 a 32 bit unsigned integer that contains the bit field of interest. + * @Param: - IN arg_FieldLSBBit an unsigned integer value representing the position of the least significant + * bit of the bit field. + * @Param: - IN arg_FieldMSBBit an unsigned integer value representing the position of the most significant + * bit of the bit field. + * + * @Return: Returns the value of the bit field. The value can be from 0 to (1 << (arg_FieldMSBBit + 1 - + * arg_FieldLSBBit)) - 1. + */ +#define IX_GET_BIT_FIELD32( \ + arg_PackedData32, \ + arg_FieldLSBBit, \ + arg_FieldMSBBit \ + ) \ + (((ix_uint32)(arg_PackedData32) & IX_BIT_FIELD_MASK32(arg_FieldLSBBit, arg_FieldMSBBit)) >> \ + arg_FieldLSBBit) + + + + +/** + * MACRO NAME: IX_MAKE_BIT_FIELD32 + * + * DESCRIPTION: This macro will create a temporary 32 bit value with the bit field + * desired set to the desired value. + * + * @Param: - IN arg_BitFieldValue is the new value of the bit field. The value can be from 0 to + * (1 << (arg_FieldMSBBit + 1 - arg_FieldLSBBit)) - 1. + * @Param: - IN arg_FieldLSBBit an unsigned integer value representing the position of the least significant + * bit of the bit field. + * @Param: - IN arg_FieldMSBBit an unsigned integer value representing the position of the most significant + * bit of the bit field. + * + * @Return: Returns a temporary ix_uint32 value that has the bit field set to the appropriate value. + */ +#define IX_MAKE_BIT_FIELD32( \ + arg_BitFieldValue, \ + arg_FieldLSBBit, \ + arg_FieldMSBBit \ + ) \ + (((ix_uint32)(arg_BitFieldValue) << arg_FieldLSBBit) & \ + IX_BIT_FIELD_MASK32(arg_FieldLSBBit, arg_FieldMSBBit)) + + +/** + * MACRO NAME: IX_SET_BIT_FIELD32 + * + * DESCRIPTION: Sets a new value for a bit field from a 32 bit unsigned integer. + * + * @Param: - IN arg_PackedData32 a 32 bit unsigned integer that contains the bit field of interest. + * @Param: - IN arg_BitFieldValue is the new value of the bit field. The value can be from 0 to + * (1 << (arg_FieldMSBBit + 1 - arg_FieldLSBBit)) - 1. + * @Param: - IN arg_FieldLSBBit an unsigned integer value representing the position of the least significant + * bit of the bit field. + * @Param: - IN arg_FieldMSBBit an unsigned integer value representing the position of the most significant + * bit of the bit field. + * + * @Return: Returns the updated value of arg_PackedData32. + */ +#define IX_SET_BIT_FIELD32( \ + arg_PackedData32, \ + arg_BitFieldValue, \ + arg_FieldLSBBit, \ + arg_FieldMSBBit \ + ) \ + (arg_PackedData32 = (((ix_uint32)(arg_PackedData32) & \ + ~(IX_BIT_FIELD_MASK32(arg_FieldLSBBit, arg_FieldMSBBit))) | \ + IX_MAKE_BIT_FIELD32(arg_BitFieldValue, arg_FieldLSBBit, arg_FieldMSBBit))) + + + +#if defined(__cplusplus) +} +#endif /* end defined(__cplusplus) */ + +#endif /* end !defined(__IX_MACROS_H__) */ diff --git a/cpu/ixp/npe/include/ix_os_type.h b/cpu/ixp/npe/include/ix_os_type.h new file mode 100644 index 0000000..8575096 --- /dev/null +++ b/cpu/ixp/npe/include/ix_os_type.h @@ -0,0 +1,65 @@ +/** + * ============================================================================ + * = COPYRIGHT + * + * @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 -- + * = PRODUCT + * Intel(r) IXP425 Software Release + * + * = FILENAME + * ix_os_type.h (Replaced by OSAL) + * + * = DESCRIPTION + * This file provides protable symbol definitions for the current OS type. + * + * = AUTHOR + * Intel Corporation + * + * = CHANGE HISTORY + * 4/22/2002 4:43:30 PM - creation time + * ============================================================================ + */ + +#if !defined(__IX_OS_TYPE_H__) +#define __IX_OS_TYPE_H__ + +#include "IxOsalBackward.h" + +#endif /* end !defined(__IX_OS_TYPE_H__) */ + diff --git a/cpu/ixp/npe/include/ix_ossl.h b/cpu/ixp/npe/include/ix_ossl.h new file mode 100644 index 0000000..b59f7d0 --- /dev/null +++ b/cpu/ixp/npe/include/ix_ossl.h @@ -0,0 +1,160 @@ +/** + * ============================================================================ + * = COPYRIGHT + * + * @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 -- + * = PRODUCT + * Intel(r) IXP425 Software Release + * + * = LIBRARY + * OSSL - Operating System Services Library + * + * = MODULE + * OSSL Abstraction layer header file + * + * = FILENAME + * ix_ossl.h (Replaced by OSAL) + * + * = DESCRIPTION + * This file contains the prototypes of OS-independent wrapper + * functions which allow the programmer not to be tied to a specific + * operating system. The OSSL functions can be divided into three classes: + * + * 1) synchronization-related wrapper functions around thread system calls + * 2) thread-related wrapper functions around thread calls + * 3) transactor/workbench osapi calls -- defined in osApi.h + * + * Both 1 and 2 classes of functions provide Thread Management, Thread + * Synchronization, Mutual Exclusion and Timer primitives. Namely, + * creation and deletion functions as well as the standard "wait" and + * "exit". Additionally, a couple of utility functions which enable to + * pause the execution of a thread are also provided. + * + * The 3rd class provides a slew of other OSAPI functions to handle + * Transactor/WorkBench OS calls. + * + * + * OSSL Thread APIs: + * The OSSL thread functions that allow for thread creation, + * get thread id, thread deletion and set thread priroity. + * + * ix_ossl_thread_create + * ix_ossl_thread_get_id + * ix_ossl_thread_exit + * ix_ossl_thread_kill + * ix_ossl_thread_set_priority + * ix_ossl_thread__delay + * + * OSSL Semaphore APIs: + * The OSSL semaphore functions that allow for initialization, + * posting, waiting and deletion of semaphores. + * + * ix_ossl_sem_init + * ix_ossl_sem_fini + * ix_ossl_sem_take + * ix_ossl_sem_give + * ix_ossl_sem_flush + * + * OSSL Mutex APIs: + * The OSSL wrapper functions that allow for initialization, + * posting, waiting and deletion of mutexes. + * + * ix_ossl_mutex_init + * ix_ossl_mutex_fini + * ix_ossl_mutex_lock + * ix_ossl_mutex_unlock + * + * OSSL Timer APIs: + * The timer APIs provide sleep and get time functions. + * + * ix_ossl_sleep + * ix_ossl_sleep_tick + * ix_ossl_time_get + * + * OSAPIs for Transactor/WorkBench: + * These OSAPI functions are used for transator OS calls. + * They are defined in osApi.h. + * + * Sem_Init + * Sem_Destroy + * Sem_Wait + * Sem_Wait + * Thread_Create + * Thread_Cancel + * Thread_SetPriority + * delayMs + * delayTick + * + * + * + ********************************************************************** + * + * + * = AUTHOR + * Intel Corporation + * + * = ACKNOWLEDGEMENTS + * + * + * = CREATION TIME + * 1/8/2002 1:53:42 PM + * + * = CHANGE HISTORY + * 02/22/2002 : Renamed osapi.h os_api.h + * Moved OS header file includes from OSSL.h to os_api.h + * Moved OS specific datatypes to os_api.h + * Modified data types, macros and functions as per + * 'C' coding guidelines. + * + * + * ============================================================================ + */ + +#ifndef _IX_OSSL_H +#ifndef __doxygen_hide +#define _IX_OSSL_H +#endif /* __doxygen_hide */ + +#include "IxOsalBackward.h" + +#endif /* _IX_OSSL_H */ + +/** + * @} defgroup IxOSSL + */ diff --git a/cpu/ixp/npe/include/ix_symbols.h b/cpu/ixp/npe/include/ix_symbols.h new file mode 100644 index 0000000..f7bb029 --- /dev/null +++ b/cpu/ixp/npe/include/ix_symbols.h @@ -0,0 +1,106 @@ +/** + * ============================================================================ + * = COPYRIGHT + * + * @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 -- + * = PRODUCT + * Intel(r) IXP425 Software Release + * + * = FILENAME + * ix_symbols.h + * + * = DESCRIPTION + * This file declares all the global preprocessor symbols required by + * the IXA SDK Framework API. + * + * = AUTHOR + * Intel Corporation + * + * = CHANGE HISTORY + * 4/23/2002 10:41:13 AM - creation time + * ============================================================================ + */ + +#if !defined(__IX_SYMBOLS_H__) +#define __IX_SYMBOLS_H__ + + +#if defined(__cplusplus) +extern "C" +{ +#endif /* end defined(__cplusplus) */ + +/** + * The IX_EXPORT_FUNCTION symbol will be used for compilation on different platforms. + * We are planning to provide a simulation version of the library that should work + * with the Transactor rather than the hardware. This implementation will be done on + * WIN32 in the form of a DLL that will need to export functions and symbols. + */ +#if (_IX_OS_TYPE_ == _IX_OS_WIN32_) +# if defined(_IX_LIB_INTERFACE_IMPLEMENTATION_) +# define IX_EXPORT_FUNCTION __declspec( dllexport ) +# elif defined(_IX_LIB_INTERFACE_IMPORT_DLL_) +# define IX_EXPORT_FUNCTION __declspec( dllimport ) +# else +# define IX_EXPORT_FUNCTION extern +# endif +#elif (_IX_OS_TYPE_ == _IX_OS_WINCE_) +# define IX_EXPORT_FUNCTION __declspec(dllexport) +#else +# define IX_EXPORT_FUNCTION extern +#endif + + +/** + * This symbols should be defined when we want to build for a multithreaded environment + */ +#define _IX_MULTI_THREADED_ 1 + + +/** + * This symbol should be defined in the case we to buils for a multithreaded environment + * but we want that our modules to work as if they are used in a single threaded environment. + */ +/* #define _IX_RM_EXPLICIT_SINGLE_THREADED_ 1 */ + +#if defined(__cplusplus) +} +#endif /* end defined(__cplusplus) */ + +#endif /* end !defined(__IX_SYMBOLS_H__) */ diff --git a/cpu/ixp/npe/include/ix_types.h b/cpu/ixp/npe/include/ix_types.h new file mode 100644 index 0000000..fc7b1e9 --- /dev/null +++ b/cpu/ixp/npe/include/ix_types.h @@ -0,0 +1,208 @@ +/** + * ============================================================================ + * = COPYRIGHT + * + * @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 -- + * = PRODUCT + * Intel(r) IXP425 Software Release + * + * = FILENAME + * ix_types.h + * + * = DESCRIPTION + * This file will define generic types that will guarantee the protability + * between different architectures and compilers. It should be used the entire + * IXA SDK Framework API. + * + * = AUTHOR + * Intel Corporation + * + * = CHANGE HISTORY + * 4/22/2002 4:44:17 PM - creation time + * ============================================================================ + */ + +#if !defined(__IX_TYPES_H__) +#define __IX_TYPES_H__ + + +#if defined(__cplusplus) +extern "C" +{ +#endif /* end defined(__cplusplus) */ + + +/** + * Define generic integral data types that will guarantee the size. + */ + +/** + * TYPENAME: ix_int8 + * + * DESCRIPTION: This type defines an 8 bit signed integer value. + * + */ +typedef signed char ix_int8; + + +/** + * TYPENAME: ix_uint8 + * + * DESCRIPTION: This type defines an 8 bit unsigned integer value. + * + */ +typedef unsigned char ix_uint8; + + +/** + * TYPENAME: ix_int16 + * + * DESCRIPTION: This type defines an 16 bit signed integer value. + * + */ +typedef signed short int ix_int16; + + +/** + * TYPENAME: ix_uint16 + * + * DESCRIPTION: This type defines an 16 bit unsigned integer value. + * + */ +typedef unsigned short int ix_uint16; + + +/** + * TYPENAME: ix_int32 + * + * DESCRIPTION: This type defines an 32 bit signed integer value. + * + */ +typedef signed int ix_int32; + + +/** + * TYPENAME: ix_uint32 + * + * DESCRIPTION: This type defines an 32 bit unsigned integer value. + * + */ +#ifndef __wince +typedef unsigned int ix_uint32; +#else +typedef unsigned long ix_uint32; +#endif + +/** + * TYPENAME: ix_int64 + * + * DESCRIPTION: This type defines an 64 bit signed integer value. + * + */ +#ifndef __wince +__extension__ typedef signed long long int ix_int64; +#endif + +/** + * TYPENAME: ix_uint64 + * + * DESCRIPTION: This type defines an 64 bit unsigned integer value. + * + */ +#ifndef __wince +__extension__ typedef unsigned long long int ix_uint64; +#endif + + +/** + * TYPENAME: ix_bit_mask8 + * + * DESCRIPTION: This is a generic type for a 8 bit mask. + */ +typedef ix_uint8 ix_bit_mask8; + + +/** + * TYPENAME: ix_bit_mask16 + * + * DESCRIPTION: This is a generic type for a 16 bit mask. + */ +typedef ix_uint16 ix_bit_mask16; + + +/** + * TYPENAME: ix_bit_mask32 + * + * DESCRIPTION: This is a generic type for a 32 bit mask. + */ +typedef ix_uint32 ix_bit_mask32; + + +/** + * TYPENAME: ix_bit_mask64 + * + * DESCRIPTION: This is a generic type for a 64 bit mask. + */ +#ifndef __wince +typedef ix_uint64 ix_bit_mask64; +#endif + + +/** + * TYPENAME: ix_handle + * + * DESCRIPTION: This type defines a generic handle. + * + */ +typedef ix_uint32 ix_handle; + + + +/** + * DESCRIPTION: This symbol defines a NULL handle + * + */ +#define IX_NULL_HANDLE ((ix_handle)0) + + +#if defined(__cplusplus) +} +#endif /* end defined(__cplusplus) */ + +#endif /* end !defined(__IX_TYPES_H__) */ diff --git a/cpu/ixp/npe/include/npe.h b/cpu/ixp/npe/include/npe.h new file mode 100644 index 0000000..e53458d --- /dev/null +++ b/cpu/ixp/npe/include/npe.h @@ -0,0 +1,90 @@ +/* + * (C) Copyright 2005 + * 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 + */ + +#ifndef NPE_H +#define NPE_H + +/* + * defines... + */ +#define CFG_NPE_NUMS 1 +#ifdef CONFIG_HAS_ETH1 +#undef CFG_NPE_NUMS +#define CFG_NPE_NUMS 2 +#endif + +#define NPE_NUM_PORTS 3 +#define ACTIVE_PORTS 1 + +#define NPE_PKT_SIZE 1600 + +#define CONFIG_DEVS_ETH_INTEL_NPE_MAX_RX_DESCRIPTORS 64 +#define CONFIG_DEVS_ETH_INTEL_NPE_MAX_TX_DESCRIPTORS 2 + +#define NPE_MBUF_POOL_SIZE \ + ((CONFIG_DEVS_ETH_INTEL_NPE_MAX_TX_DESCRIPTORS + \ + CONFIG_DEVS_ETH_INTEL_NPE_MAX_RX_DESCRIPTORS) * \ + sizeof(IX_OSAL_MBUF) * ACTIVE_PORTS) + +#define NPE_PKT_POOL_SIZE \ + ((CONFIG_DEVS_ETH_INTEL_NPE_MAX_TX_DESCRIPTORS + \ + CONFIG_DEVS_ETH_INTEL_NPE_MAX_RX_DESCRIPTORS) * \ + NPE_PKT_SIZE * ACTIVE_PORTS) + +#define NPE_MEM_POOL_SIZE (NPE_MBUF_POOL_SIZE + NPE_PKT_POOL_SIZE) + +#define PHY_AUTONEGOTIATE_TIMEOUT 4000 /* 4000 ms autonegotiate timeout */ + +/* + * structs... + */ +struct npe { + u8 active; /* NPE active */ + u8 eth_id; /* IX_ETH_PORT_1 or IX_ETH_PORT_2 */ + u8 phy_no; /* which PHY (0 - 31) */ + u8 mac_address[6]; + + IX_OSAL_MBUF *rxQHead; + IX_OSAL_MBUF *txQHead; + + u8 *tx_pkts; + u8 *rx_pkts; + IX_OSAL_MBUF *rx_mbufs; + IX_OSAL_MBUF *tx_mbufs; + + int print_speed; + + int rx_read; + int rx_write; + int rx_len[PKTBUFSRX]; +}; + +/* + * prototypes... + */ +extern int npe_miiphy_read (char *devname, unsigned char addr, + unsigned char reg, unsigned short *value); +extern int npe_miiphy_write (char *devname, unsigned char addr, + unsigned char reg, unsigned short value); + +#endif /* ifndef NPE_H */ diff --git a/cpu/ixp/npe/include/os_datatypes.h b/cpu/ixp/npe/include/os_datatypes.h new file mode 100644 index 0000000..4387b2a --- /dev/null +++ b/cpu/ixp/npe/include/os_datatypes.h @@ -0,0 +1,82 @@ +/** + * ============================================================================ + * = COPYRIGHT + * + * @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 -- + * = PRODUCT + * Intel(r) IXP425 Software Release + * + * = LIBRARY + * OSSL - Operating System Services Library + * + * = MODULE + * OS Specific Data Types header file + * + * = FILENAME + * OSSL.h (Replaced by OSAL) + * + * = DESCRIPTION + * This file contains definitions and encapsulations for OS specific data types. These + * encapsulated data types are used by OSSL header files and OS API functions. + * + * + ********************************************************************** + * + * + * = AUTHOR + * Intel Corporation + * + * = AKNOWLEDGEMENTS + * + * + * = CREATION TIME + * 1/8/2002 1:53:42 PM + * + * = CHANGE HISTORY + + * ============================================================================ + */ + +#ifndef _OS_DATATYPES_H +#define _OS_DATATYPES_H + +#include "IxOsalBackward.h" + +#endif /* _OS_DATATYPES_H */ + diff --git a/cpu/ixp/npe/miiphy.c b/cpu/ixp/npe/miiphy.c new file mode 100644 index 0000000..c63c54e --- /dev/null +++ b/cpu/ixp/npe/miiphy.c @@ -0,0 +1,118 @@ +/*-----------------------------------------------------------------------------+ + | + | This source code has been made available to you by IBM on an AS-IS + | basis. Anyone receiving this source is licensed under IBM + | copyrights to use it in any way he or she deems fit, including + | copying it, modifying it, compiling it, and redistributing it either + | with or without modifications. No license under IBM patents or + | patent applications is to be implied by the copyright license. + | + | Any user of this software should understand that IBM cannot provide + | technical support for this software and will not be responsible for + | any consequences resulting from the use of this software. + | + | Any person who transfers this source code or any derivative work + | must include the IBM copyright notice, this paragraph, and the + | preceding two paragraphs in the transferred software. + | + | COPYRIGHT I B M CORPORATION 1995 + | LICENSED MATERIAL - PROGRAM PROPERTY OF I B M + +-----------------------------------------------------------------------------*/ +/*-----------------------------------------------------------------------------+ + | + | File Name: miiphy.c + | + | Function: This module has utilities for accessing the MII PHY through + | the EMAC3 macro. + | + | Author: Mark Wisner + | + | Change Activity- + | + | Date Description of Change BY + | --------- --------------------- --- + | 05-May-99 Created MKW + | 01-Jul-99 Changed clock setting of sta_reg from 66Mhz to 50Mhz to + | better match OPB speed. Also modified delay times. JWB + | 29-Jul-99 Added Full duplex support MKW + | 24-Aug-99 Removed printf from dp83843_duplex() JWB + | 19-Jul-00 Ported to esd cpci405 sr + | 23-Dec-03 Ported from miiphy.c to 440GX Travis Sawyer TBS + | + | + +-----------------------------------------------------------------------------*/ + +#include +#include +#include "IxOsal.h" +#include "IxEthAcc.h" +#include "IxEthAcc_p.h" +#include "IxEthAccMac_p.h" +#include "IxEthAccMii_p.h" + +/***********************************************************/ +/* Dump out to the screen PHY regs */ +/***********************************************************/ + +void miiphy_dump (char *devname, unsigned char addr) +{ + unsigned long i; + unsigned short data; + + + for (i = 0; i < 0x1A; i++) { + if (miiphy_read (devname, addr, i, &data)) { + printf ("read error for reg %lx\n", i); + return; + } + printf ("Phy reg %lx ==> %4x\n", i, data); + + /* jump to the next set of regs */ + if (i == 0x07) + i = 0x0f; + + } /* end for loop */ +} /* end dump */ + + +/***********************************************************/ +/* (Re)start autonegotiation */ +/***********************************************************/ +int phy_setup_aneg (char *devname, unsigned char addr) +{ + unsigned short ctl, adv; + + /* Setup standard advertise */ + miiphy_read (devname, addr, PHY_ANAR, &adv); + adv |= (PHY_ANLPAR_ACK | PHY_ANLPAR_RF | PHY_ANLPAR_T4 | + PHY_ANLPAR_TXFD | PHY_ANLPAR_TX | PHY_ANLPAR_10FD | + PHY_ANLPAR_10); + miiphy_write (devname, addr, PHY_ANAR, adv); + + /* Start/Restart aneg */ + miiphy_read (devname, addr, PHY_BMCR, &ctl); + ctl |= (PHY_BMCR_AUTON | PHY_BMCR_RST_NEG); + miiphy_write (devname, addr, PHY_BMCR, ctl); + + return 0; +} + + +int npe_miiphy_read (char *devname, unsigned char addr, + unsigned char reg, unsigned short *value) +{ + u16 val; + + ixEthAccMiiReadRtn(addr, reg, &val); + *value = val; + + return 0; +} /* phy_read */ + + +int npe_miiphy_write (char *devname, unsigned char addr, + unsigned char reg, unsigned short value) +{ + ixEthAccMiiWriteRtn(addr, reg, value); + return 0; +} /* phy_write */ diff --git a/cpu/ixp/npe/npe.c b/cpu/ixp/npe/npe.c new file mode 100644 index 0000000..ab7ca8b --- /dev/null +++ b/cpu/ixp/npe/npe.c @@ -0,0 +1,694 @@ +/* + * (C) Copyright 2005-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 + */ + +#if 0 +#define DEBUG /* define for debug output */ +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef CONFIG_IXP4XX_NPE + +static IxQMgrDispatcherFuncPtr qDispatcherFunc = NULL; +static int npe_exists[NPE_NUM_PORTS]; +static int npe_used[NPE_NUM_PORTS]; + +/* A little extra so we can align to cacheline. */ +static u8 npe_alloc_pool[NPE_MEM_POOL_SIZE + CFG_CACHELINE_SIZE - 1]; +static u8 *npe_alloc_end; +static u8 *npe_alloc_free; + +static void *npe_alloc(int size) +{ + static int count = 0; + void *p = NULL; + + size = (size + (CFG_CACHELINE_SIZE-1)) & ~(CFG_CACHELINE_SIZE-1); + count++; + + if ((npe_alloc_free + size) < npe_alloc_end) { + p = npe_alloc_free; + npe_alloc_free += size; + } else { + printf("%s: failed (count=%d, size=%d)!\n", count, size); + } + return p; +} + +/* Not interrupt safe! */ +static void mbuf_enqueue(IX_OSAL_MBUF **q, IX_OSAL_MBUF *new) +{ + IX_OSAL_MBUF *m = *q; + + IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR(new) = NULL; + + if (m) { + while(IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR(m)) + m = IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR(m); + IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR(m) = new; + } else + *q = new; +} + +/* Not interrupt safe! */ +static IX_OSAL_MBUF *mbuf_dequeue(IX_OSAL_MBUF **q) +{ + IX_OSAL_MBUF *m = *q; + if (m) + *q = IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR(m); + return m; +} + +static void reset_tx_mbufs(struct npe* p_npe) +{ + IX_OSAL_MBUF *m; + int i; + + p_npe->txQHead = NULL; + + for (i = 0; i < CONFIG_DEVS_ETH_INTEL_NPE_MAX_TX_DESCRIPTORS; i++) { + m = &p_npe->tx_mbufs[i]; + + memset(m, 0, sizeof(*m)); + + IX_OSAL_MBUF_MDATA(m) = (void *)&p_npe->tx_pkts[i * NPE_PKT_SIZE]; + IX_OSAL_MBUF_MLEN(m) = IX_OSAL_MBUF_PKT_LEN(m) = NPE_PKT_SIZE; + mbuf_enqueue(&p_npe->txQHead, m); + } +} + +static void reset_rx_mbufs(struct npe* p_npe) +{ + IX_OSAL_MBUF *m; + int i; + + p_npe->rxQHead = NULL; + + HAL_DCACHE_INVALIDATE(p_npe->rx_pkts, NPE_PKT_SIZE * + CONFIG_DEVS_ETH_INTEL_NPE_MAX_RX_DESCRIPTORS); + + for (i = 0; i < CONFIG_DEVS_ETH_INTEL_NPE_MAX_RX_DESCRIPTORS; i++) { + m = &p_npe->rx_mbufs[i]; + + memset(m, 0, sizeof(*m)); + + IX_OSAL_MBUF_MDATA(m) = (void *)&p_npe->rx_pkts[i * NPE_PKT_SIZE]; + IX_OSAL_MBUF_MLEN(m) = IX_OSAL_MBUF_PKT_LEN(m) = NPE_PKT_SIZE; + + if(ixEthAccPortRxFreeReplenish(p_npe->eth_id, m) != IX_SUCCESS) { + printf("ixEthAccPortRxFreeReplenish failed for port %d\n", p_npe->eth_id); + break; + } + } +} + +static void init_rx_mbufs(struct npe* p_npe) +{ + p_npe->rxQHead = NULL; + + p_npe->rx_pkts = npe_alloc(NPE_PKT_SIZE * + CONFIG_DEVS_ETH_INTEL_NPE_MAX_RX_DESCRIPTORS); + if (p_npe->rx_pkts == NULL) { + printf("alloc of packets failed.\n"); + return; + } + + p_npe->rx_mbufs = (IX_OSAL_MBUF *) + npe_alloc(sizeof(IX_OSAL_MBUF) * + CONFIG_DEVS_ETH_INTEL_NPE_MAX_RX_DESCRIPTORS); + if (p_npe->rx_mbufs == NULL) { + printf("alloc of mbufs failed.\n"); + return; + } + + reset_rx_mbufs(p_npe); +} + +static void init_tx_mbufs(struct npe* p_npe) +{ + p_npe->tx_pkts = npe_alloc(NPE_PKT_SIZE * + CONFIG_DEVS_ETH_INTEL_NPE_MAX_TX_DESCRIPTORS); + if (p_npe->tx_pkts == NULL) { + printf("alloc of packets failed.\n"); + return; + } + + p_npe->tx_mbufs = (IX_OSAL_MBUF *) + npe_alloc(sizeof(IX_OSAL_MBUF) * + CONFIG_DEVS_ETH_INTEL_NPE_MAX_TX_DESCRIPTORS); + if (p_npe->tx_mbufs == NULL) { + printf("alloc of mbufs failed.\n"); + return; + } + + reset_tx_mbufs(p_npe); +} + +/* Convert IX_ETH_PORT_n to IX_NPEMH_NPEID_NPEx */ +static int __eth_to_npe(int eth_id) +{ + switch(eth_id) { + case IX_ETH_PORT_1: + return IX_NPEMH_NPEID_NPEB; + + case IX_ETH_PORT_2: + return IX_NPEMH_NPEID_NPEC; + + case IX_ETH_PORT_3: + return IX_NPEMH_NPEID_NPEA; + } + return 0; +} + +/* Poll the CSR machinery. */ +static void npe_poll(int eth_id) +{ + if (qDispatcherFunc != NULL) { + ixNpeMhMessagesReceive(__eth_to_npe(eth_id)); + (*qDispatcherFunc)(IX_QMGR_QUELOW_GROUP); + } +} + +/* ethAcc RX callback */ +static void npe_rx_callback(u32 cbTag, IX_OSAL_MBUF *m, IxEthAccPortId portid) +{ + struct npe* p_npe = (struct npe *)cbTag; + + if (IX_OSAL_MBUF_MLEN(m) > 0) { + mbuf_enqueue(&p_npe->rxQHead, m); + + if (p_npe->rx_write == ((p_npe->rx_read-1) & (PKTBUFSRX-1))) { + debug("Rx overflow: rx_write=%d rx_read=%d\n", + p_npe->rx_write, p_npe->rx_read); + } else { + debug("Received message #%d (len=%d)\n", p_npe->rx_write, + IX_OSAL_MBUF_MLEN(m)); + memcpy((void *)NetRxPackets[p_npe->rx_write], IX_OSAL_MBUF_MDATA(m), + IX_OSAL_MBUF_MLEN(m)); + p_npe->rx_len[p_npe->rx_write] = IX_OSAL_MBUF_MLEN(m); + p_npe->rx_write++; + if (p_npe->rx_write == PKTBUFSRX) + p_npe->rx_write = 0; + +#ifdef CONFIG_PRINT_RX_FRAMES + { + u8 *ptr = IX_OSAL_MBUF_MDATA(m); + int i; + + for (i=0; i<60; i++) { + debug("%02x ", *ptr++); + } + debug("\n"); + } +#endif + } + + m = mbuf_dequeue(&p_npe->rxQHead); + } else { + debug("Received frame with length 0!!!\n"); + m = mbuf_dequeue(&p_npe->rxQHead); + } + + /* Now return mbuf to NPE */ + IX_OSAL_MBUF_MLEN(m) = IX_OSAL_MBUF_PKT_LEN(m) = NPE_PKT_SIZE; + IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(m) = NULL; + IX_OSAL_MBUF_FLAGS(m) = 0; + + if(ixEthAccPortRxFreeReplenish(p_npe->eth_id, m) != IX_SUCCESS) { + debug("npe_rx_callback: Error returning mbuf.\n"); + } +} + +/* ethAcc TX callback */ +static void npe_tx_callback(u32 cbTag, IX_OSAL_MBUF *m) +{ + struct npe* p_npe = (struct npe *)cbTag; + + debug("%s\n", __FUNCTION__); + + IX_OSAL_MBUF_MLEN(m) = IX_OSAL_MBUF_PKT_LEN(m) = NPE_PKT_SIZE; + IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(m) = NULL; + IX_OSAL_MBUF_FLAGS(m) = 0; + + mbuf_enqueue(&p_npe->txQHead, m); +} + + +static int npe_set_mac_address(struct eth_device *dev) +{ + struct npe *p_npe = (struct npe *)dev->priv; + IxEthAccMacAddr npeMac; + + debug("%s\n", __FUNCTION__); + + /* Set MAC address */ + memcpy(npeMac.macAddress, dev->enetaddr, 6); + + if (ixEthAccPortUnicastMacAddressSet(p_npe->eth_id, &npeMac) != IX_ETH_ACC_SUCCESS) { + printf("Error setting unicast address! %02x:%02x:%02x:%02x:%02x:%02x\n", + npeMac.macAddress[0], npeMac.macAddress[1], + npeMac.macAddress[2], npeMac.macAddress[3], + npeMac.macAddress[4], npeMac.macAddress[5]); + return 0; + } + + return 1; +} + +/* Boot-time CSR library initialization. */ +static int npe_csr_load(void) +{ + int i; + + if (ixQMgrInit() != IX_SUCCESS) { + debug("Error initialising queue manager!\n"); + return 0; + } + + ixQMgrDispatcherLoopGet(&qDispatcherFunc); + + if(ixNpeMhInitialize(IX_NPEMH_NPEINTERRUPTS_YES) != IX_SUCCESS) { + printf("Error initialising NPE Message handler!\n"); + return 0; + } + + if (npe_used[IX_ETH_PORT_1] && npe_exists[IX_ETH_PORT_1] && + ixNpeDlNpeInitAndStart(IX_NPEDL_NPEIMAGE_NPEB_ETH_LEARN_FILTER_SPAN_FIREWALL_VLAN_QOS) + != IX_SUCCESS) { + printf("Error downloading firmware to NPE-B!\n"); + return 0; + } + + if (npe_used[IX_ETH_PORT_2] && npe_exists[IX_ETH_PORT_2] && + ixNpeDlNpeInitAndStart(IX_NPEDL_NPEIMAGE_NPEC_ETH_LEARN_FILTER_SPAN_FIREWALL_VLAN_QOS) + != IX_SUCCESS) { + printf("Error downloading firmware to NPE-C!\n"); + return 0; + } + + /* don't need this for U-Boot */ + ixFeatureCtrlSwConfigurationWrite(IX_FEATURECTRL_ETH_LEARNING, FALSE); + + if (ixEthAccInit() != IX_ETH_ACC_SUCCESS) { + printf("Error initialising Ethernet access driver!\n"); + return 0; + } + + for (i = 0; i < IX_ETH_ACC_NUMBER_OF_PORTS; i++) { + if (!npe_used[i] || !npe_exists[i]) + continue; + if (ixEthAccPortInit(i) != IX_ETH_ACC_SUCCESS) { + printf("Error initialising Ethernet port%d!\n", i); + } + if (ixEthAccTxSchedulingDisciplineSet(i, FIFO_NO_PRIORITY) != IX_ETH_ACC_SUCCESS) { + printf("Error setting scheduling discipline for port %d.\n", i); + } + if (ixEthAccPortRxFrameAppendFCSDisable(i) != IX_ETH_ACC_SUCCESS) { + printf("Error disabling RX FCS for port %d.\n", i); + } + if (ixEthAccPortTxFrameAppendFCSEnable(i) != IX_ETH_ACC_SUCCESS) { + printf("Error enabling TX FCS for port %d.\n", i); + } + } + + return 1; +} + +static int npe_init(struct eth_device *dev, bd_t * bis) +{ + struct npe *p_npe = (struct npe *)dev->priv; + int i; + u16 reg_short; + int speed; + int duplex; + + debug("%s: 1\n", __FUNCTION__); + + miiphy_read (dev->name, p_npe->phy_no, PHY_BMSR, ®_short); + + /* + * Wait if PHY is capable of autonegotiation and autonegotiation is not complete + */ + if ((reg_short & PHY_BMSR_AUTN_ABLE) && !(reg_short & PHY_BMSR_AUTN_COMP)) { + puts ("Waiting for PHY auto negotiation to complete"); + i = 0; + while (!(reg_short & PHY_BMSR_AUTN_COMP)) { + /* + * Timeout reached ? + */ + if (i > PHY_AUTONEGOTIATE_TIMEOUT) { + puts (" TIMEOUT !\n"); + break; + } + + if ((i++ % 1000) == 0) { + putc ('.'); + miiphy_read (dev->name, p_npe->phy_no, PHY_BMSR, ®_short); + } + udelay (1000); /* 1 ms */ + } + puts (" done\n"); + udelay (500000); /* another 500 ms (results in faster booting) */ + } + + speed = miiphy_speed (dev->name, p_npe->phy_no); + duplex = miiphy_duplex (dev->name, p_npe->phy_no); + + if (p_npe->print_speed) { + p_npe->print_speed = 0; + printf ("ENET Speed is %d Mbps - %s duplex connection\n", + (int) speed, (duplex == HALF) ? "HALF" : "FULL"); + } + + npe_alloc_end = npe_alloc_pool + sizeof(npe_alloc_pool); + npe_alloc_free = (u8 *)(((unsigned)npe_alloc_pool + + CFG_CACHELINE_SIZE - 1) & ~(CFG_CACHELINE_SIZE - 1)); + + /* initialize mbuf pool */ + init_rx_mbufs(p_npe); + init_tx_mbufs(p_npe); + + if (ixEthAccPortRxCallbackRegister(p_npe->eth_id, npe_rx_callback, + (u32)p_npe) != IX_ETH_ACC_SUCCESS) { + printf("can't register RX callback!\n"); + return 0; + } + + if (ixEthAccPortTxDoneCallbackRegister(p_npe->eth_id, npe_tx_callback, + (u32)p_npe) != IX_ETH_ACC_SUCCESS) { + printf("can't register TX callback!\n"); + return 0; + } + + npe_set_mac_address(dev); + + if (ixEthAccPortEnable(p_npe->eth_id) != IX_ETH_ACC_SUCCESS) { + printf("can't enable port!\n"); + return 0; + } + + p_npe->active = 1; + + return 1; +} + +#if 0 /* test-only: probably have to deal with it when booting linux (for a clean state) */ +/* Uninitialize CSR library. */ +static void npe_csr_unload(void) +{ + ixEthAccUnload(); + ixEthDBUnload(); + ixNpeMhUnload(); + ixQMgrUnload(); +} + +/* callback which is used by ethAcc to recover RX buffers when stopping */ +static void npe_rx_stop_callback(u32 cbTag, IX_OSAL_MBUF *m, IxEthAccPortId portid) +{ + debug("%s\n", __FUNCTION__); +} + +/* callback which is used by ethAcc to recover TX buffers when stopping */ +static void npe_tx_stop_callback(u32 cbTag, IX_OSAL_MBUF *m) +{ + debug("%s\n", __FUNCTION__); +} +#endif + +static void npe_halt(struct eth_device *dev) +{ + struct npe *p_npe = (struct npe *)dev->priv; + int i; + + debug("%s\n", __FUNCTION__); + + /* Delay to give time for recovery of mbufs */ + for (i = 0; i < 100; i++) { + npe_poll(p_npe->eth_id); + udelay(100); + } + +#if 0 /* test-only: probably have to deal with it when booting linux (for a clean state) */ + if (ixEthAccPortRxCallbackRegister(p_npe->eth_id, npe_rx_stop_callback, + (u32)p_npe) != IX_ETH_ACC_SUCCESS) { + debug("Error registering rx callback!\n"); + } + + if (ixEthAccPortTxDoneCallbackRegister(p_npe->eth_id, npe_tx_stop_callback, + (u32)p_npe) != IX_ETH_ACC_SUCCESS) { + debug("Error registering tx callback!\n"); + } + + if (ixEthAccPortDisable(p_npe->eth_id) != IX_ETH_ACC_SUCCESS) { + debug("npe_stop: Error disabling NPEB!\n"); + } + + /* Delay to give time for recovery of mbufs */ + for (i = 0; i < 100; i++) { + npe_poll(p_npe->eth_id); + udelay(10000); + } + + /* + * For U-Boot only, we are probably launching Linux or other OS that + * needs a clean slate for its NPE library. + */ +#if 0 /* test-only */ + for (i = 0; i < IX_ETH_ACC_NUMBER_OF_PORTS; i++) { + if (npe_used[i] && npe_exists[i]) + if (ixNpeDlNpeStopAndReset(__eth_to_npe(i)) != IX_SUCCESS) + printf("Failed to stop and reset NPE B.\n"); + } +#endif + +#endif + p_npe->active = 0; +} + + +static int npe_send(struct eth_device *dev, volatile void *packet, int len) +{ + struct npe *p_npe = (struct npe *)dev->priv; + u8 *dest; + int err; + IX_OSAL_MBUF *m; + + debug("%s\n", __FUNCTION__); + m = mbuf_dequeue(&p_npe->txQHead); + dest = IX_OSAL_MBUF_MDATA(m); + IX_OSAL_MBUF_PKT_LEN(m) = IX_OSAL_MBUF_MLEN(m) = len; + IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR(m) = NULL; + + memcpy(dest, (char *)packet, len); + + if ((err = ixEthAccPortTxFrameSubmit(p_npe->eth_id, m, IX_ETH_ACC_TX_DEFAULT_PRIORITY)) + != IX_ETH_ACC_SUCCESS) { + printf("npe_send: Can't submit frame. err[%d]\n", err); + mbuf_enqueue(&p_npe->txQHead, m); + return 0; + } + +#ifdef DEBUG_PRINT_TX_FRAMES + { + u8 *ptr = IX_OSAL_MBUF_MDATA(m); + int i; + + for (i=0; ieth_id); + + return len; +} + +static int npe_rx(struct eth_device *dev) +{ + struct npe *p_npe = (struct npe *)dev->priv; + + debug("%s\n", __FUNCTION__); + npe_poll(p_npe->eth_id); + + debug("%s: rx_write=%d rx_read=%d\n", __FUNCTION__, p_npe->rx_write, p_npe->rx_read); + while (p_npe->rx_write != p_npe->rx_read) { + debug("Reading message #%d\n", p_npe->rx_read); + NetReceive(NetRxPackets[p_npe->rx_read], p_npe->rx_len[p_npe->rx_read]); + p_npe->rx_read++; + if (p_npe->rx_read == PKTBUFSRX) + p_npe->rx_read = 0; + } + + return 0; +} + +int npe_initialize(bd_t * bis) +{ + static int virgin = 0; + struct eth_device *dev; + int eth_num = 0; + struct npe *p_npe = NULL; + + for (eth_num = 0; eth_num < CFG_NPE_NUMS; eth_num++) { + + /* See if we can actually bring up the interface, otherwise, skip it */ + switch (eth_num) { + default: /* fall through */ + case 0: + if (memcmp (bis->bi_enetaddr, "\0\0\0\0\0\0", 6) == 0) { + continue; + } + break; +#ifdef CONFIG_HAS_ETH1 + case 1: + if (memcmp (bis->bi_enet1addr, "\0\0\0\0\0\0", 6) == 0) { + continue; + } + break; +#endif + } + + /* Allocate device structure */ + dev = (struct eth_device *)malloc(sizeof(*dev)); + if (dev == NULL) { + printf ("%s: Cannot allocate eth_device %d\n", __FUNCTION__, eth_num); + return -1; + } + memset(dev, 0, sizeof(*dev)); + + /* Allocate our private use data */ + p_npe = (struct npe *)malloc(sizeof(struct npe)); + if (p_npe == NULL) { + printf("%s: Cannot allocate private hw data for eth_device %d", + __FUNCTION__, eth_num); + free(dev); + return -1; + } + memset(p_npe, 0, sizeof(struct npe)); + + switch (eth_num) { + default: /* fall through */ + case 0: + memcpy(dev->enetaddr, bis->bi_enetaddr, 6); + p_npe->eth_id = 0; + p_npe->phy_no = CONFIG_PHY_ADDR; + break; + +#ifdef CONFIG_HAS_ETH1 + case 1: + memcpy(dev->enetaddr, bis->bi_enet1addr, 6); + p_npe->eth_id = 1; + p_npe->phy_no = CONFIG_PHY1_ADDR; + break; +#endif + } + + sprintf(dev->name, "NPE%d", eth_num); + dev->priv = (void *)p_npe; + dev->init = npe_init; + dev->halt = npe_halt; + dev->send = npe_send; + dev->recv = npe_rx; + + p_npe->print_speed = 1; + + if (0 == virgin) { + virgin = 1; + + if (ixFeatureCtrlDeviceRead() == IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X) { + switch (ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK) { + case IX_FEATURE_CTRL_SILICON_TYPE_B0: + /* + * If it is B0 Silicon, we only enable port when its corresponding + * Eth Coprocessor is available. + */ + if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH0) == + IX_FEATURE_CTRL_COMPONENT_ENABLED) + npe_exists[IX_ETH_PORT_1] = TRUE; + + if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH1) == + IX_FEATURE_CTRL_COMPONENT_ENABLED) + npe_exists[IX_ETH_PORT_2] = TRUE; + break; + case IX_FEATURE_CTRL_SILICON_TYPE_A0: + /* + * If it is A0 Silicon, we enable both as both Eth Coprocessors + * are available. + */ + npe_exists[IX_ETH_PORT_1] = TRUE; + npe_exists[IX_ETH_PORT_2] = TRUE; + break; + } + } else if (ixFeatureCtrlDeviceRead() == IX_FEATURE_CTRL_DEVICE_TYPE_IXP46X) { + if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH0) == + IX_FEATURE_CTRL_COMPONENT_ENABLED) + npe_exists[IX_ETH_PORT_1] = TRUE; + + if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH1) == + IX_FEATURE_CTRL_COMPONENT_ENABLED) + npe_exists[IX_ETH_PORT_2] = TRUE; + } + + npe_used[IX_ETH_PORT_1] = 1; + npe_used[IX_ETH_PORT_2] = 1; + + npe_alloc_end = npe_alloc_pool + sizeof(npe_alloc_pool); + npe_alloc_free = (u8 *)(((unsigned)npe_alloc_pool + + CFG_CACHELINE_SIZE - 1) + & ~(CFG_CACHELINE_SIZE - 1)); + + if (!npe_csr_load()) + return 0; + } + + eth_register(dev); + +#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) + miiphy_register(dev->name, npe_miiphy_read, npe_miiphy_write); +#endif + + } /* end for each supported device */ + + return 1; +} + +#endif /* CONFIG_IXP4XX_NPE */ diff --git a/cpu/ixp/start.S b/cpu/ixp/start.S index 2726f65..757cfaa 100644 --- a/cpu/ixp/start.S +++ b/cpu/ixp/start.S @@ -211,7 +211,7 @@ reset: /* copy */ mov r0, #0 mov r4, r0 - add r2, r0, #0x40000 + add r2, r0, #CFG_MONITOR_LEN mov r1, #0x10000000 mov r5, r1 @@ -497,3 +497,29 @@ reset_cpu: reset_endless: b reset_endless + +#ifdef CONFIG_USE_IRQ + +.LC0: .word loops_per_jiffy + +/* + * 0 <= r0 <= 2000 + */ +.globl udelay +udelay: + mov r2, #0x6800 + orr r2, r2, #0x00db + mul r0, r2, r0 + ldr r2, .LC0 + ldr r2, [r2] @ max = 0x0fffffff + mov r0, r0, lsr #11 @ max = 0x00003fff + mov r2, r2, lsr #11 @ max = 0x0003ffff + mul r0, r2, r0 @ max = 2^32-1 + movs r0, r0, lsr #6 + +delay_loop: + subs r0, r0, #1 + bne delay_loop + mov pc, lr + +#endif /* CONFIG_USE_IRQ */ diff --git a/cpu/ixp/timer.c b/cpu/ixp/timer.c index 8df2a31..920f34e 100644 --- a/cpu/ixp/timer.c +++ b/cpu/ixp/timer.c @@ -1,5 +1,7 @@ -/* vi: set ts=8 sw=8 noet: */ /* + * (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * * (C) Copyright 2002 * Sysgo Real-Time Solutions, GmbH * Marius Groeger @@ -30,6 +32,7 @@ #include #include +#ifndef CONFIG_USE_IRQ ulong get_timer (ulong base) { return get_timer_masked () - base; @@ -77,3 +80,4 @@ ulong get_timer_masked (void) } return (reload_constant - current); } +#endif /* #ifndef CONFIG_USE_IRQ */ diff --git a/cpu/mcf52x2/cpu.c b/cpu/mcf52x2/cpu.c index 32a524f..e6e5d9b 100644 --- a/cpu/mcf52x2/cpu.c +++ b/cpu/mcf52x2/cpu.c @@ -25,6 +25,11 @@ #include #include +#ifdef CONFIG_M5271 +#include +#include +#endif + #ifdef CONFIG_M5272 #include #include @@ -38,6 +43,42 @@ #include #endif +#ifdef CONFIG_M5271 +int checkcpu (void) +{ + char buf[32]; + + printf ("CPU: Freescale Coldfire MCF5271 at %s MHz\n", strmhz(buf, CFG_CLK)); + return 0; +} + +int do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) { + mbar_writeByte(MCF_RCM_RCR, + MCF_RCM_RCR_SOFTRST | MCF_RCM_RCR_FRCRSTOUT); + return 0; +}; + +#if defined(CONFIG_WATCHDOG) +void watchdog_reset (void) +{ + mbar_writeShort(MCF_WTM_WSR, 0x5555); + mbar_writeShort(MCF_WTM_WSR, 0xAAAA); +} + +int watchdog_disable (void) +{ + mbar_writeShort(MCF_WTM_WCR, 0); + return (0); +} + +int watchdog_init (void) +{ + mbar_writeShort(MCF_WTM_WCR, MCF_WTM_WCR_EN); + return (0); +} +#endif /* #ifdef CONFIG_WATCHDOG */ + +#endif #ifdef CONFIG_M5272 int do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) { @@ -66,12 +107,12 @@ int checkcpu(void) { case 0x4: suf = "3K75N"; break; default: suf = NULL; - printf ("MOTOROLA MCF5272 (Mask:%01x)\n", msk); + printf ("Freescale MCF5272 (Mask:%01x)\n", msk); break; } if (suf) - printf ("MOTOROLA MCF5272 %s\n", suf); + printf ("Freescale MCF5272 %s\n", suf); return 0; }; @@ -117,7 +158,7 @@ int watchdog_init (void) #ifdef CONFIG_M5282 int checkcpu (void) { - puts ("CPU: MOTOROLA Coldfire MCF5282\n"); + puts ("CPU: Freescale Coldfire MCF5282\n"); return 0; } @@ -131,7 +172,7 @@ int checkcpu (void) { char buf[32]; - printf ("CPU: MOTOROLA Coldfire MCF5249 at %s MHz\n", strmhz(buf, CFG_CLK)); + printf ("CPU: Freescale Coldfire MCF5249 at %s MHz\n", strmhz(buf, CFG_CLK)); return 0; } diff --git a/cpu/mcf52x2/cpu_init.c b/cpu/mcf52x2/cpu_init.c index 350c431..451e3f3 100644 --- a/cpu/mcf52x2/cpu_init.c +++ b/cpu/mcf52x2/cpu_init.c @@ -12,7 +12,7 @@ * * 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 + * 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 @@ -24,6 +24,11 @@ #include #include +#ifdef CONFIG_M5271 +#include +#include +#endif + #ifdef CONFIG_M5272 #include #include @@ -38,6 +43,38 @@ #include #endif +#if defined(CONFIG_M5271) +void cpu_init_f (void) +{ +#ifndef CONFIG_WATCHDOG + /* Disable the watchdog if we aren't using it */ + mbar_writeShort(MCF_WTM_WCR, 0); +#endif + + /* Set clockspeed to 100MHz */ + mbar_writeShort(MCF_FMPLL_SYNCR, + MCF_FMPLL_SYNCR_MFD(0) | MCF_FMPLL_SYNCR_RFD(0)); + while (!mbar_readByte(MCF_FMPLL_SYNSR) & MCF_FMPLL_SYNSR_LOCK); + + /* Enable UART pins */ + mbar_writeShort(MCF_GPIO_PAR_UART, MCF_GPIO_PAR_UART_U0TXD | + MCF_GPIO_PAR_UART_U0RXD | + MCF_GPIO_PAR_UART_U1RXD_UART1 | + MCF_GPIO_PAR_UART_U1TXD_UART1); + + /* Enable Ethernet pins */ + mbar_writeByte(MCF_GPIO_PAR_FECI2C, CFG_FECI2C); +} + +/* + * initialize higher level parts of CPU like timers + */ +int cpu_init_r (void) +{ + return (0); +} +#endif + #if defined(CONFIG_M5272) /* * Breath some life into the CPU... @@ -60,7 +97,7 @@ void cpu_init_f (void) regp->sysctrl_reg.sc_scr = CFG_SCR; regp->sysctrl_reg.sc_spr = CFG_SPR; - /* Setup Ports: */ + /* Setup Ports: */ regp->gpio_reg.gpio_pacnt = CFG_PACNT; regp->gpio_reg.gpio_paddr = CFG_PADDR; regp->gpio_reg.gpio_padat = CFG_PADAT; @@ -110,15 +147,15 @@ void cpu_init_f (void) #endif /* #ifndef CONFIG_MONITOR_IS_IN_RAM */ - /* enable instruction cache now */ - icache_enable(); + /* enable instruction cache now */ + icache_enable(); } /* * initialize higher level parts of CPU like timers */ -int cpu_init_r (void) +int cpu_init_r (void) { return (0); } @@ -141,7 +178,7 @@ void cpu_init_f (void) /* * initialize higher level parts of CPU like timers */ -int cpu_init_r (void) +int cpu_init_r (void) { return (0); } @@ -165,23 +202,23 @@ void cpu_init_f (void) volatile unsigned long cpll = mbar2_readLong(MCFSIM_PLLCR); unsigned long pllcr; #ifdef CFG_FAST_CLK - pllcr = 0x925a3100; /* ~140MHz clock (PLL bypass = 0) */ + pllcr = 0x925a3100; /* ~140MHz clock (PLL bypass = 0) */ #else - pllcr = 0x135a4140; /* ~72MHz clock (PLL bypass = 0) */ + pllcr = 0x135a4140; /* ~72MHz clock (PLL bypass = 0) */ #endif - cpll = cpll & 0xfffffffe; /* Set PLL bypass mode = 0 (PSTCLK = crystal) */ - mbar2_writeLong(MCFSIM_PLLCR, cpll); /* Set the PLL to bypass mode (PSTCLK = crystal) */ - mbar2_writeLong(MCFSIM_PLLCR, pllcr); /* set the clock speed */ - pllcr ^= 0x00000001; /* Set pll bypass to 1 */ - mbar2_writeLong(MCFSIM_PLLCR, pllcr); /* Start locking (pll bypass = 1) */ - udelay(0x20); /* Wait for a lock ... */ + cpll = cpll & 0xfffffffe; /* Set PLL bypass mode = 0 (PSTCLK = crystal) */ + mbar2_writeLong(MCFSIM_PLLCR, cpll); /* Set the PLL to bypass mode (PSTCLK = crystal) */ + mbar2_writeLong(MCFSIM_PLLCR, pllcr); /* set the clock speed */ + pllcr ^= 0x00000001; /* Set pll bypass to 1 */ + mbar2_writeLong(MCFSIM_PLLCR, pllcr); /* Start locking (pll bypass = 1) */ + udelay(0x20); /* Wait for a lock ... */ #endif /* #ifndef CFG_PLL_BYPASS */ /* * NOTE: by setting the GPIO_FUNCTION registers, we ensure that the UART pins - * (UART0: gpio 30,27, UART1: gpio 31, 28) will be used as UART pins - * which is their primary function. - * ~Jeremy + * (UART0: gpio 30,27, UART1: gpio 31, 28) will be used as UART pins + * which is their primary function. + * ~Jeremy */ mbar2_writeLong(MCFSIM_GPIO_FUNC, CFG_GPIO_FUNC); mbar2_writeLong(MCFSIM_GPIO1_FUNC, CFG_GPIO1_FUNC); @@ -196,7 +233,7 @@ void cpu_init_f (void) * (Internal Register Display) command * ~Jeremy * - */ + */ mbar_writeByte(MCFSIM_MPARK, 0x30); /* 5249 Internal Core takes priority over DMA */ mbar_writeByte(MCFSIM_SYPCR, 0x00); mbar_writeByte(MCFSIM_SWIVR, 0x0f); @@ -215,9 +252,9 @@ void cpu_init_f (void) mbar_writeByte(MCFSIM_QSPIICR, 0x00); mbar2_writeLong(MCFSIM_GPIO_INT_EN, 0x00000080); - mbar2_writeByte(MCFSIM_INTBASE, 0x40); /* Base interrupts at 64 */ + mbar2_writeByte(MCFSIM_INTBASE, 0x40); /* Base interrupts at 64 */ mbar2_writeByte(MCFSIM_SPURVEC, 0x00); - mbar2_writeLong(MCFSIM_IDECONFIG1, 0x00000020); /* Enable a 1 cycle pre-drive cycle on CS1 */ + mbar2_writeLong(MCFSIM_IDECONFIG1, 0x00000020); /* Enable a 1 cycle pre-drive cycle on CS1 */ /* Setup interrupt priorities for gpio7 */ /* mbar2_writeLong(MCFSIM_INTLEV5, 0x70000000); */ @@ -245,7 +282,7 @@ void cpu_init_f (void) /* * initialize higher level parts of CPU like timers */ -int cpu_init_r (void) +int cpu_init_r (void) { return (0); } diff --git a/cpu/mcf52x2/fec.c b/cpu/mcf52x2/fec.c index a5c50af..f207dd6 100644 --- a/cpu/mcf52x2/fec.c +++ b/cpu/mcf52x2/fec.c @@ -25,6 +25,11 @@ #include #include +#ifdef CONFIG_M5271 +#include +#include +#endif + #ifdef CONFIG_M5272 #include #include @@ -41,7 +46,7 @@ #ifdef CONFIG_M5272 #define FEC_ADDR (CFG_MBAR + 0x840) #endif -#ifdef CONFIG_M5282 +#if defined(CONFIG_M5282) || defined(CONFIG_M5271) #define FEC_ADDR (CFG_MBAR + 0x1000) #endif @@ -240,10 +245,22 @@ int eth_init (bd_t * bd) #endif #undef ea +#ifdef CONFIG_M5271 + /* Clear multicast address hash table + */ + fecp->fec_ghash_table_high = 0; + fecp->fec_ghash_table_low = 0; + + /* Clear individual address hash table + */ + fecp->fec_ihash_table_high = 0; + fecp->fec_ihash_table_low = 0; +#else /* Clear multicast address hash table */ fecp->fec_hash_table_high = 0; fecp->fec_hash_table_low = 0; +#endif /* Set maximum receive buffer size. */ @@ -295,6 +312,9 @@ int eth_init (bd_t * bd) fecp->fec_x_cntrl = FEC_TCNTRL_FDEN; #else /* Half duplex mode */ fecp->fec_r_cntrl = FEC_RCNTRL_MII_MODE | FEC_RCNTRL_DRT; +#ifdef CONFIG_M5271 + fecp->fec_r_cntrl |= (PKT_MAXBUF_SIZE << 16); /* set max frame length */ +#endif fecp->fec_x_cntrl = 0; #endif /* Set MII speed */ diff --git a/cpu/mcf52x2/interrupts.c b/cpu/mcf52x2/interrupts.c index 868df39..116747a 100644 --- a/cpu/mcf52x2/interrupts.c +++ b/cpu/mcf52x2/interrupts.c @@ -27,6 +27,11 @@ #include #include +#ifdef CONFIG_M5271 +#include +#include +#endif + #ifdef CONFIG_M5272 #include #include @@ -171,7 +176,7 @@ int interrupt_init (void) } #endif -#ifdef CONFIG_M5282 +#if defined(CONFIG_M5282) || defined(CONFIG_M5271) int interrupt_init (void) { return 0; diff --git a/cpu/mcf52x2/serial.c b/cpu/mcf52x2/serial.c index 79628d0..1011788 100644 --- a/cpu/mcf52x2/serial.c +++ b/cpu/mcf52x2/serial.c @@ -23,9 +23,14 @@ #include #include +#include #include +#ifdef CONFIG_M5271 +#include +#endif + #ifdef CONFIG_M5272 #include #endif @@ -40,7 +45,7 @@ DECLARE_GLOBAL_DATA_PTR; -#ifdef CONFIG_M5249 +#if defined(CONFIG_M5249) || defined(CONFIG_M5271) #define DoubleClock(a) ((double)(CFG_CLK/2) / 32.0 / (double)(a)) #else #define DoubleClock(a) ((double)(CFG_CLK) / 32.0 / (double)(a)) @@ -48,9 +53,12 @@ DECLARE_GLOBAL_DATA_PTR; void rs_serial_setbaudrate(int port,int baudrate) { -#if defined(CONFIG_M5272) || defined(CONFIG_M5249) +#if defined(CONFIG_M5272) || defined(CONFIG_M5249) || defined(CONFIG_M5271) volatile unsigned char *uartp; - double clock, fraction; +#ifndef CONFIG_M5271 + double fraction; +#endif + double clock; if (port == 0) uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE1); @@ -59,12 +67,14 @@ void rs_serial_setbaudrate(int port,int baudrate) clock = DoubleClock(baudrate); /* Set baud above */ - fraction = ((clock - (int)clock) * 16.0) + 0.5; - uartp[MCFUART_UBG1] = (((int)clock >> 8) & 0xff); /* set msb baud */ uartp[MCFUART_UBG2] = ((int)clock & 0xff); /* set lsb baud */ + +#ifndef CONFIG_M5271 + fraction = ((clock - (int)clock) * 16.0) + 0.5; uartp[MCFUART_UFPD] = ((int)fraction & 0xf); /* set baud fraction adjust */ #endif +#endif }; void rs_serial_init(int port,int baudrate) @@ -79,8 +89,9 @@ void rs_serial_init(int port,int baudrate) else uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE2); - uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX; /* reset RX */ uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX; /* reset TX */ + uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX; /* reset RX */ + uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETMRPTR; /* reset MR pointer */ uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETERR; /* reset Error pointer */ @@ -90,9 +101,15 @@ void rs_serial_init(int port,int baudrate) uartp[MCFUART_UMR] = MCFUART_MR1_PARITYNONE | MCFUART_MR1_CS8; uartp[MCFUART_UMR] = MCFUART_MR2_STOP1; - rs_serial_setbaudrate(port,baudrate); + /* Mask UART interrupts */ + uartp[MCFUART_UIMR] = 0; + /* Set clock Select Register: Tx/Rx clock is timer */ uartp[MCFUART_UCSR] = MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER; + + rs_serial_setbaudrate(port,baudrate); + + /* Enable Tx/Rx */ uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE; return; @@ -158,7 +175,9 @@ void serial_puts (const char *s) { } int serial_getc(void) { - while(!rs_is_char()); + while(!rs_is_char()) + WATCHDOG_RESET(); + return rs_get_char(); } diff --git a/cpu/mcf52x2/start.S b/cpu/mcf52x2/start.S index b4926e2..3ab812b 100644 --- a/cpu/mcf52x2/start.S +++ b/cpu/mcf52x2/start.S @@ -55,7 +55,11 @@ */ _vectors: +#ifndef CONFIG_R5200 .long 0x00000000, _START +#else +.long 0x00000000, 0x400 /* Flash offset is 0 until we setup CS0 */ +#endif .long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT .long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT .long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT @@ -124,26 +128,42 @@ _start: movec %d0, %RAMBAR0 #endif /* #if defined(CONFIG_M5272) || defined(CONFIG_M5249) */ -#ifdef CONFIG_M5282 +#if defined(CONFIG_M5282) || defined(CONFIG_M5271) /* Initialize IPSBAR */ move.l #(CFG_MBAR + 1), %d0 /* set IPSBAR address + valid flag */ move.l %d0, 0x40000000 +#ifdef CONFIG_M5282 /* Initialize FLASHBAR: locate internal Flash and validate it */ move.l #(CFG_INT_FLASH_BASE + 0x21), %d0 movec %d0, %RAMBAR0 +#endif /* Initialize RAMBAR1: locate SRAM and validate it */ move.l #(CFG_INIT_RAM_ADDR + 0x21), %d0 movec %d0, %RAMBAR1 #endif +#ifdef CONFIG_R5200 + move.l #(_flash_setup-CFG_FLASH_BASE), %a0 + move.l #(_flash_setup_end-CFG_FLASH_BASE), %a1 + move.l #(CFG_INIT_RAM_ADDR), %a2 +_copy_flash: + move.l (%a0)+, (%a2)+ + cmp.l %a0, %a1 + bgt.s _copy_flash + jmp CFG_INIT_RAM_ADDR +_after_flash_copy: +#endif + +#if 0 /* invalidate and disable cache */ move.l #0x01000000, %d0 /* Invalidate cache cmd */ movec %d0, %CACR /* Invalidate cache */ move.l #0, %d0 movec %d0, %ACR0 movec %d0, %ACR1 +#endif /* set stackpointer to end of internal ram to get some stackspace for the first c-code */ move.l #(CFG_INIT_RAM_ADDR + CFG_INIT_SP_OFFSET), %sp @@ -154,10 +174,28 @@ _start: bsr cpu_init_f /* run low-level CPU init code (from flash) */ bsr board_init_f /* run low-level board init code (from flash) */ - /* board_init_f() does not return + /* board_init_f() does not return */ /*------------------------------------------------------------------------------*/ +#ifdef CONFIG_R5200 +_flash_setup: + /* CSAR0 */ + move.l #((CFG_FLASH_BASE & 0xffff0000) >> 16), %d0 + move.w %d0, 0x40000080 + + /* CSCR0 */ + move.l #0x2180, %d0 /* 8 wait states, 16bit port, auto ack, */ + move.w %d0, 0x4000008A + + /* CSMR0 */ + move.l #0x001f0001, %d0 /* 2 MB, valid */ + move.l %d0, 0x40000084 + + jmp _after_flash_copy.L +_flash_setup_end: +#endif + /* * void relocate_code (addr_sp, gd, addr_moni) * diff --git a/cpu/mpc8260/pci.c b/cpu/mpc8260/pci.c index ea5514f..b14fc15 100644 --- a/cpu/mpc8260/pci.c +++ b/cpu/mpc8260/pci.c @@ -34,7 +34,7 @@ #include #include -#if defined CONFIG_MPC8266ADS || defined CONFIG_MPC8272 +#if defined CONFIG_MPC8266ADS || defined CONFIG_MPC8272 || defined CONFIG_PM826 DECLARE_GLOBAL_DATA_PTR; #endif @@ -401,7 +401,7 @@ void pci_mpc8250_init (struct pci_controller *hose) hose->last_busno = 0xff; /* System memory space */ -#if defined CONFIG_MPC8266ADS || defined CONFIG_MPC8272 +#if defined CONFIG_MPC8266ADS || defined CONFIG_MPC8272 || defined CONFIG_PM826 pci_set_region (hose->regions + 0, PCI_SLV_MEM_BUS, PCI_SLV_MEM_LOCAL, diff --git a/cpu/mpc83xx/i2c.c b/cpu/mpc83xx/i2c.c index 4e70f80..70450f9 100644 --- a/cpu/mpc83xx/i2c.c +++ b/cpu/mpc83xx/i2c.c @@ -41,7 +41,7 @@ #include #include -#if defined(CONFIG_MPC8349ADS) || defined(CONFIG_TQM834X) +#if defined(CONFIG_MPC8349EMDS) || defined(CONFIG_TQM834X) i2c_t * mpc8349_i2c = (i2c_t*)(CFG_IMMRBAR + CFG_I2C_OFFSET); #endif diff --git a/cpu/ppc4xx/cpu.c b/cpu/ppc4xx/cpu.c index 0cd72b0..d9b5d32 100644 --- a/cpu/ppc4xx/cpu.c +++ b/cpu/ppc4xx/cpu.c @@ -1,5 +1,5 @@ /* - * (C) Copyright 2000-2003 + * (C) Copyright 2000-2006 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this @@ -223,12 +223,20 @@ int checkcpu (void) case PVR_440EP_RB: /* 440EP rev B and 440GR rev A have same PVR */ puts("EP Rev. B"); break; + + case PVR_440EP_RC: /* 440EP rev C and 440GR rev B have same PVR */ + puts("EP Rev. C"); + break; #endif /* CONFIG_440EP */ #ifdef CONFIG_440GR case PVR_440GR_RA: /* 440EP rev B and 440GR rev A have same PVR */ puts("GR Rev. A"); break; + + case PVR_440GR_RB: /* 440EP rev C and 440GR rev B have same PVR */ + puts("GR Rev. B"); + break; #endif /* CONFIG_440GR */ #endif /* CONFIG_440 */ diff --git a/cpu/ppc4xx/cpu_init.c b/cpu/ppc4xx/cpu_init.c index 1a139d7..b27567f 100644 --- a/cpu/ppc4xx/cpu_init.c +++ b/cpu/ppc4xx/cpu_init.c @@ -1,5 +1,5 @@ /* - * (C) Copyright 2000 + * (C) Copyright 2000-2006 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this @@ -101,6 +101,117 @@ DECLARE_GLOBAL_DATA_PTR; # endif #endif /* CFG_INIT_DCACHE_CS */ +#if defined(CFG_440_GPIO_TABLE) +gpio_param_s gpio_tab[GPIO_GROUP_MAX][GPIO_MAX] = CFG_440_GPIO_TABLE; + +void set_chip_gpio_configuration(gpio_param_s (*gpio_tab)[GPIO_GROUP_MAX][GPIO_MAX]) +{ + unsigned char i=0, j=0, reg_offset = 0, gpio_core; + unsigned long gpio_reg, gpio_core_add; + + for (gpio_core=0; gpio_core> (j*2)); + gpio_reg = gpio_reg | (GPIO_IN_SEL >> (j*2)); + out32(GPIO_IS1(gpio_core_add+reg_offset), gpio_reg); + break; + + case GPIO_ALT2: + gpio_reg = in32(GPIO_IS2(gpio_core_add+reg_offset)) + & ~(GPIO_MASK >> (j*2)); + gpio_reg = gpio_reg | (GPIO_IN_SEL >> (j*2)); + out32(GPIO_IS2(gpio_core_add+reg_offset), gpio_reg); + break; + + case GPIO_ALT3: + gpio_reg = in32(GPIO_IS3(gpio_core_add+reg_offset)) + & ~(GPIO_MASK >> (j*2)); + gpio_reg = gpio_reg | (GPIO_IN_SEL >> (j*2)); + out32(GPIO_IS3(gpio_core_add+reg_offset), gpio_reg); + break; + } + } + + if (((*gpio_tab)[gpio_core][i].in_out == GPIO_OUT) || + ((*gpio_tab)[gpio_core][i].in_out == GPIO_BI)) { + + switch ((*gpio_tab)[gpio_core][i].alt_nb) { + case GPIO_SEL: + if (gpio_core == GPIO0) { + gpio_reg = in32(GPIO0_TCR) | (0x80000000 >> (j)); + out32(GPIO0_TCR, gpio_reg); + } + + if (gpio_core == GPIO1) { + gpio_reg = in32(GPIO1_TCR) | (0x80000000 >> (j)); + out32(GPIO1_TCR, gpio_reg); + } + + gpio_reg = in32(GPIO_OS(gpio_core_add+reg_offset)) + & ~(GPIO_MASK >> (j*2)); + out32(GPIO_OS(gpio_core_add+reg_offset), gpio_reg); + gpio_reg = in32(GPIO_TS(gpio_core_add+reg_offset)) + & ~(GPIO_MASK >> (j*2)); + out32(GPIO_TS(gpio_core_add+reg_offset), gpio_reg); + break; + + case GPIO_ALT1: + gpio_reg = in32(GPIO_OS(gpio_core_add+reg_offset)) + & ~(GPIO_MASK >> (j*2)); + gpio_reg = gpio_reg | (GPIO_ALT1_SEL >> (j*2)); + out32(GPIO_OS(gpio_core_add+reg_offset), gpio_reg); + gpio_reg = in32(GPIO_TS(gpio_core_add+reg_offset)) + & ~(GPIO_MASK >> (j*2)); + gpio_reg = gpio_reg | (GPIO_ALT1_SEL >> (j*2)); + out32(GPIO_TS(gpio_core_add+reg_offset), gpio_reg); + break; + + case GPIO_ALT2: + gpio_reg = in32(GPIO_OS(gpio_core_add+reg_offset)) + & ~(GPIO_MASK >> (j*2)); + gpio_reg = gpio_reg | (GPIO_ALT2_SEL >> (j*2)); + out32(GPIO_OS(gpio_core_add+reg_offset), gpio_reg); + gpio_reg = in32(GPIO_TS(gpio_core_add+reg_offset)) + & ~(GPIO_MASK >> (j*2)); + gpio_reg = gpio_reg | (GPIO_ALT2_SEL >> (j*2)); + out32(GPIO_TS(gpio_core_add+reg_offset), gpio_reg); + break; + + case GPIO_ALT3: + gpio_reg = in32(GPIO_OS(gpio_core_add+reg_offset)) + & ~(GPIO_MASK >> (j*2)); + gpio_reg = gpio_reg | (GPIO_ALT3_SEL >> (j*2)); + out32(GPIO_OS(gpio_core_add+reg_offset), gpio_reg); + gpio_reg = in32(GPIO_TS(gpio_core_add+reg_offset)) + & ~(GPIO_MASK >> (j*2)); + gpio_reg = gpio_reg | (GPIO_ALT3_SEL >> (j*2)); + out32(GPIO_TS(gpio_core_add+reg_offset), gpio_reg); + break; + } + } + } + } +} +#endif /* CFG_440_GPIO_TABLE */ /* * Breath some life into the CPU... @@ -129,10 +240,16 @@ cpu_init_f (void) mtdcr(cpc0_epctl, CPC0_EPRCSR_E0NFE | CPC0_EPRCSR_E1NFE); #endif /* CONFIG_405EP */ +#if defined(CFG_440_GPIO_TABLE) + set_chip_gpio_configuration(&gpio_tab); +#endif /* CFG_440_GPIO_TABLE */ + /* * External Bus Controller (EBC) Setup */ #if (defined(CFG_EBC_PB0AP) && defined(CFG_EBC_PB0CR)) +#if (defined(CONFIG_405GP) || defined(CONFIG_405CR) || \ + defined(CONFIG_405EP) || defined(CONFIG_405)) /* * Move the next instructions into icache, since these modify the flash * we are running from! @@ -148,6 +265,7 @@ cpu_init_f (void) asm volatile(" ori 3, 3, 0xA000" ::: "r3"); asm volatile(" mtctr 3" ::: "ctr"); asm volatile("2: bdnz 2b" ::: "ctr", "cr0"); +#endif mtebc(pb0ap, CFG_EBC_PB0AP); mtebc(pb0cr, CFG_EBC_PB0CR); diff --git a/cpu/ppc4xx/start.S b/cpu/ppc4xx/start.S index 948de43..647088f 100644 --- a/cpu/ppc4xx/start.S +++ b/cpu/ppc4xx/start.S @@ -1198,12 +1198,19 @@ ppcSync: .globl relocate_code relocate_code: #if defined(CONFIG_440EP) || defined(CONFIG_440GR) - dccci 0,0 /* Invalidate data cache, now no longer our stack */ + /* + * On some 440er platforms the cache is enabled in the first TLB (Boot-CS) + * to speed up the boot process. Now this cache needs to be disabled. + */ + iccci 0,0 /* Invalidate inst cache */ + dccci 0,0 /* Invalidate data cache, now no longer our stack */ sync + isync addi r1,r0,0x0000 /* TLB entry #0 */ tlbre r0,r1,0x0002 /* Read contents */ ori r0,r0,0x0c00 /* Or in the inhibit, write through bit */ tlbwe r0,r1,0x0002 /* Save it out */ + sync isync #endif mr r1, r3 /* Set new stack pointer */ diff --git a/drivers/cfi_flash.c b/drivers/cfi_flash.c index 2e37480..fd0a186 100644 --- a/drivers/cfi_flash.c +++ b/drivers/cfi_flash.c @@ -793,6 +793,7 @@ static int flash_status_check (flash_info_t * info, flash_sect_t sector, flash_write_cmd (info, sector, 0, info->cmd_reset); return ERR_TIMOUT; } + udelay (1); /* also triggers watchdog */ } return ERR_OK; } diff --git a/include/asm-arm/arch-ixp/ixp425.h b/include/asm-arm/arch-ixp/ixp425.h index fbe6858..11dc356 100644 --- a/include/asm-arm/arch-ixp/ixp425.h +++ b/include/asm-arm/arch-ixp/ixp425.h @@ -73,21 +73,18 @@ * PCI Configuration space */ #define IXP425_PCI_CFG_BASE_PHYS (0xC0000000) -#define IXP425_PCI_CFG_BASE_VIRT (0xFFFD0000) #define IXP425_PCI_CFG_REGION_SIZE (0x00001000) /* * Expansion BUS Configuration registers */ #define IXP425_EXP_CFG_BASE_PHYS (0xC4000000) -#define IXP425_EXP_CFG_BASE_VIRT (0xFFFD1000) #define IXP425_EXP_CFG_REGION_SIZE (0x00001000) /* * Peripheral space */ #define IXP425_PERIPHERAL_BASE_PHYS (0xC8000000) -#define IXP425_PERIPHERAL_BASE_VIRT (0xFFFD2000) #define IXP425_PERIPHERAL_REGION_SIZE (0x0000C000) /* @@ -99,7 +96,6 @@ * Q Manager space .. not static mapped */ #define IXP425_QMGR_BASE_PHYS (0x60000000) -#define IXP425_QMGR_BASE_VIRT (0xFFFDE000) #define IXP425_QMGR_REGION_SIZE (0x00004000) /* @@ -113,10 +109,8 @@ */ #define IXP425_EXP_BUS_BASE1_PHYS (0x00000000) #define IXP425_EXP_BUS_BASE2_PHYS (0x50000000) -#define IXP425_EXP_BUS_BASE2_VIRT (0xF0000000) #define IXP425_EXP_BUS_BASE_PHYS IXP425_EXP_BUS_BASE2_PHYS -#define IXP425_EXP_BUS_BASE_VIRT IXP425_EXP_BUS_BASE2_VIRT #define IXP425_EXP_BUS_REGION_SIZE (0x08000000) #define IXP425_EXP_BUS_CSX_REGION_SIZE (0x01000000) @@ -130,20 +124,10 @@ #define IXP425_EXP_BUS_CS6_BASE_PHYS (IXP425_EXP_BUS_BASE2_PHYS + 0x06000000) #define IXP425_EXP_BUS_CS7_BASE_PHYS (IXP425_EXP_BUS_BASE2_PHYS + 0x07000000) -#define IXP425_EXP_BUS_CS0_BASE_VIRT (IXP425_EXP_BUS_BASE2_VIRT + 0x00000000) -#define IXP425_EXP_BUS_CS1_BASE_VIRT (IXP425_EXP_BUS_BASE2_VIRT + 0x01000000) -#define IXP425_EXP_BUS_CS2_BASE_VIRT (IXP425_EXP_BUS_BASE2_VIRT + 0x02000000) -#define IXP425_EXP_BUS_CS3_BASE_VIRT (IXP425_EXP_BUS_BASE2_VIRT + 0x03000000) -#define IXP425_EXP_BUS_CS4_BASE_VIRT (IXP425_EXP_BUS_BASE2_VIRT + 0x04000000) -#define IXP425_EXP_BUS_CS5_BASE_VIRT (IXP425_EXP_BUS_BASE2_VIRT + 0x05000000) -#define IXP425_EXP_BUS_CS6_BASE_VIRT (IXP425_EXP_BUS_BASE2_VIRT + 0x06000000) -#define IXP425_EXP_BUS_CS7_BASE_VIRT (IXP425_EXP_BUS_BASE2_VIRT + 0x07000000) - #define IXP425_FLASH_WRITABLE (0x2) #define IXP425_FLASH_DEFAULT (0xbcd23c40) #define IXP425_FLASH_WRITE (0xbcd23c42) - #define IXP425_EXP_CS0_OFFSET 0x00 #define IXP425_EXP_CS1_OFFSET 0x04 #define IXP425_EXP_CS2_OFFSET 0x08 @@ -161,7 +145,7 @@ * Expansion Bus Controller registers. */ #ifndef __ASSEMBLY__ -#define IXP425_EXP_REG(x) ((volatile u32 *)(IXP425_EXP_CFG_BASE_VIRT+(x))) +#define IXP425_EXP_REG(x) ((volatile u32 *)(IXP425_EXP_CFG_BASE_PHYS+(x))) #else #define IXP425_EXP_REG(x) (IXP425_EXP_CFG_BASE_PHYS+(x)) #endif @@ -288,7 +272,6 @@ #define MSR_DDSR (1 << 1) /* Delta Data Set Ready */ #define MSR_DCTS (1 << 0) /* Delta Clear To Send */ -#define IXP425_CONSOLE_UART_BASE_VIRT IXP425_UART1_BASE_VIRT #define IXP425_CONSOLE_UART_BASE_PHYS IXP425_UART1_BASE_PHYS /* * Peripheral Space Registers @@ -306,20 +289,6 @@ #define IXP425_EthB_BASE_PHYS (IXP425_PERIPHERAL_BASE_PHYS + 0xA000) #define IXP425_USB_BASE_PHYS (IXP425_PERIPHERAL_BASE_PHYS + 0xB000) -#define IXP425_UART1_BASE_VIRT (IXP425_PERIPHERAL_BASE_VIRT + 0x0000) -#define IXP425_UART2_BASE_VIRT (IXP425_PERIPHERAL_BASE_VIRT + 0x1000) -#define IXP425_PMU_BASE_VIRT (IXP425_PERIPHERAL_BASE_VIRT + 0x2000) -#define IXP425_INTC_BASE_VIRT (IXP425_PERIPHERAL_BASE_VIRT + 0x3000) -#define IXP425_GPIO_BASE_VIRT (IXP425_PERIPHERAL_BASE_VIRT + 0x4000) -#define IXP425_TIMER_BASE_VIRT (IXP425_PERIPHERAL_BASE_VIRT + 0x5000) -#define IXP425_NPEA_BASE_VIRT (IXP425_PERIPHERAL_BASE_VIRT + 0x6000) -#define IXP425_NPEB_BASE_VIRT (IXP425_PERIPHERAL_BASE_VIRT + 0x7000) -#define IXP425_NPEC_BASE_VIRT (IXP425_PERIPHERAL_BASE_VIRT + 0x8000) -#define IXP425_EthA_BASE_VIRT (IXP425_PERIPHERAL_BASE_VIRT + 0x9000) -#define IXP425_EthB_BASE_VIRT (IXP425_PERIPHERAL_BASE_VIRT + 0xA000) -#define IXP425_USB_BASE_VIRT (IXP425_PERIPHERAL_BASE_VIRT + 0xB000) - - /* * UART Register Definitions , Offsets only as there are 2 UARTS. * IXP425_UART1_BASE , IXP425_UART2_BASE. @@ -341,11 +310,14 @@ #define IXP425_ICIH_OFFSET 0x18 /* IRQ Highest Pri Int */ #define IXP425_ICFH_OFFSET 0x1C /* FIQ Highest Pri Int */ +#define N_IRQS 32 +#define IXP425_TIMER_2_IRQ 11 + /* * Interrupt Controller Register Definitions. */ #ifndef __ASSEMBLY__ -#define IXP425_INTC_REG(x) ((volatile u32 *)(IXP425_INTC_BASE_VIRT+(x))) +#define IXP425_INTC_REG(x) ((volatile u32 *)(IXP425_INTC_BASE_PHYS+(x))) #else #define IXP425_INTC_REG(x) (IXP425_INTC_BASE_PHYS+(x)) #endif @@ -375,7 +347,7 @@ * GPIO Register Definitions. * [Only perform 32bit reads/writes] */ -#define IXP425_GPIO_REG(x) ((volatile u32 *)(IXP425_GPIO_BASE_VIRT+(x))) +#define IXP425_GPIO_REG(x) ((volatile u32 *)(IXP425_GPIO_BASE_PHYS+(x))) #define IXP425_GPIO_GPOUTR IXP425_GPIO_REG(IXP425_GPIO_GPOUTR_OFFSET) #define IXP425_GPIO_GPOER IXP425_GPIO_REG(IXP425_GPIO_GPOER_OFFSET) @@ -387,6 +359,16 @@ #define IXP425_GPIO_GPDBSELR IXP425_GPIO_REG(IXP425_GPIO_GPDBSELR_OFFSET) /* + * Macros to make it easy to access the GPIO registers + */ +#define GPIO_OUTPUT_ENABLE(line) *IXP425_GPIO_GPOER &= ~(1 << (line)) +#define GPIO_OUTPUT_DISABLE(line) *IXP425_GPIO_GPOER |= (1 << (line)) +#define GPIO_OUTPUT_SET(line) *IXP425_GPIO_GPOUTR |= (1 << (line)) +#define GPIO_OUTPUT_CLEAR(line) *IXP425_GPIO_GPOUTR &= ~(1 << (line)) +#define GPIO_INT_ACT_LOW_SET(line) *IXP425_GPIO_GPIT1R = \ + (*IXP425_GPIO_GPIT1R & ~(0x7 << (line * 3))) | (0x1 << (line * 3)) + +/* * Constants to make it easy to access Timer Control/Status registers */ #define IXP425_OSTS_OFFSET 0x00 /* Continious TimeStamp */ @@ -409,7 +391,9 @@ #define IXP425_TIMER_REG(x) (IXP425_TIMER_BASE_PHYS+(x)) #endif +#if 0 /* test-only: also defined in npe/include/... */ #define IXP425_OSTS IXP425_TIMER_REG(IXP425_OSTS_OFFSET) +#endif #define IXP425_OST1 IXP425_TIMER_REG(IXP425_OST1_OFFSET) #define IXP425_OSRT1 IXP425_TIMER_REG(IXP425_OSRT1_OFFSET) #define IXP425_OST2 IXP425_TIMER_REG(IXP425_OST2_OFFSET) @@ -457,12 +441,12 @@ #define PCI_ATPDMA0_LENADDR_OFFSET 0x48 #define PCI_ATPDMA1_AHBADDR_OFFSET 0x4C #define PCI_ATPDMA1_PCIADDR_OFFSET 0x50 -#define PCI_ATPDMA1_LENADDR_OFFSET 0x54 +#define PCI_ATPDMA1_LENADDR_OFFSET 0x54 /* * PCI Control/Status Registers */ -#define IXP425_PCI_CSR(x) ((volatile u32 *)(IXP425_PCI_CFG_BASE_VIRT+(x))) +#define IXP425_PCI_CSR(x) ((volatile u32 *)(IXP425_PCI_CFG_BASE_PHYS+(x))) #define PCI_NP_AD IXP425_PCI_CSR(PCI_NP_AD_OFFSET) #define PCI_NP_CBE IXP425_PCI_CSR(PCI_NP_CBE_OFFSET) diff --git a/include/asm-arm/arch-omap/sizes.h b/include/asm-arm/arch-omap/sizes.h new file mode 100644 index 0000000..f8d92ca --- /dev/null +++ b/include/asm-arm/arch-omap/sizes.h @@ -0,0 +1,52 @@ +/* + * 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 + */ +/* DO NOT EDIT!! - this file automatically generated + * from .s file by awk -f s2h.awk + */ +/* Size defintions + * Copyright (C) ARM Limited 1998. All rights reserved. + */ + +#ifndef __sizes_h +#define __sizes_h 1 + +/* handy sizes */ +#define SZ_1K 0x00000400 +#define SZ_4K 0x00001000 +#define SZ_8K 0x00002000 +#define SZ_16K 0x00004000 +#define SZ_64K 0x00010000 +#define SZ_128K 0x00020000 +#define SZ_256K 0x00040000 +#define SZ_512K 0x00080000 + +#define SZ_1M 0x00100000 +#define SZ_2M 0x00200000 +#define SZ_4M 0x00400000 +#define SZ_8M 0x00800000 +#define SZ_16M 0x01000000 +#define SZ_32M 0x02000000 +#define SZ_64M 0x04000000 +#define SZ_128M 0x08000000 +#define SZ_256M 0x10000000 +#define SZ_512M 0x20000000 + +#define SZ_1G 0x40000000 +#define SZ_2G 0x80000000 + +#endif + +/* END */ diff --git a/include/asm-arm/mach-types.h b/include/asm-arm/mach-types.h index fd03748..7d7888e 100644 --- a/include/asm-arm/mach-types.h +++ b/include/asm-arm/mach-types.h @@ -736,6 +736,7 @@ extern unsigned int __machine_arch_type; #define MACH_TYPE_LN2410SBC 725 #define MACH_TYPE_CB3RUFC 726 #define MACH_TYPE_MP2USB 727 +#define MACH_TYPE_PDNB3 1002 #ifdef CONFIG_ARCH_EBSA110 # ifdef machine_arch_type diff --git a/include/asm-arm/u-boot.h b/include/asm-arm/u-boot.h index 146934c..c120312 100644 --- a/include/asm-arm/u-boot.h +++ b/include/asm-arm/u-boot.h @@ -48,6 +48,10 @@ typedef struct bd_info { ulong start; ulong size; } bi_dram[CONFIG_NR_DRAM_BANKS]; +#ifdef CONFIG_HAS_ETH1 + /* second onboard ethernet port */ + unsigned char bi_enet1addr[6]; +#endif } bd_t; #define bi_env_data bi_env->data diff --git a/include/asm-m68k/immap_5271.h b/include/asm-m68k/immap_5271.h new file mode 100644 index 0000000..424dc1d --- /dev/null +++ b/include/asm-m68k/immap_5271.h @@ -0,0 +1,98 @@ +/* + * MCF5272 Internal Memory Map + * + * Copyright (c) 2003 Josef Baumgartner + * 2006 Zachary P. Landau + * + * 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 + */ + +#ifndef __IMMAP_5271__ +#define __IMMAP_5271__ + +/* Interrupt module registers +*/ +typedef struct int_ctrl { + uint int_icr1; + uint int_icr2; + uint int_icr3; + uint int_icr4; + uint int_isr; + uint int_pitr; + uint int_piwr; + uchar res1[3]; + uchar int_pivr; +} intctrl_t; + +/* Timer module registers + */ +typedef struct timer_ctrl { + ushort timer_tmr; + ushort res1; + ushort timer_trr; + ushort res2; + ushort timer_tcap; + ushort res3; + ushort timer_tcn; + ushort res4; + ushort timer_ter; + uchar res5[14]; +} timer_t; + + /* Fast ethernet controller registers + */ +typedef struct fec { + uint res1; + uint fec_ievent; + uint fec_imask; + uint res2; + uint fec_r_des_active; + uint fec_x_des_active; + uint res3[3]; + uint fec_ecntrl; + uint res4[6]; + uint fec_mii_data; + uint fec_mii_speed; + uint res5[7]; + uint fec_mibc; + uint res6[7]; + uint fec_r_cntrl; + uint res7[15]; + uint fec_x_cntrl; + uint res8[7]; + uint fec_addr_low; + uint fec_addr_high; + uint fec_opd; + uint res9[10]; + uint fec_ihash_table_high; + uint fec_ihash_table_low; + uint fec_ghash_table_high; + uint fec_ghash_table_low; + uint res10[7]; + uint fec_tfwr; + uint res11; + uint fec_r_bound; + uint fec_r_fstart; + uint res12[11]; + uint fec_r_des_start; + uint fec_x_des_start; + uint fec_r_buff_size; +} fec_t; + +#endif /* __IMMAP_5271__ */ diff --git a/include/asm-m68k/m5271.h b/include/asm-m68k/m5271.h new file mode 100644 index 0000000..765414f --- /dev/null +++ b/include/asm-m68k/m5271.h @@ -0,0 +1,114 @@ +/* + * mcf5271.h -- Definitions for Motorola Coldfire 5271 + * + * (C) Copyright 2006, Lab X Technologies + * Based on mcf5272sim.h of uCLinux distribution: + * (C) Copyright 1999, Greg Ungerer (gerg@snapgear.com) + * (C) Copyright 2000, Lineo Inc. (www.lineo.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 + */ + + +#ifndef _MCF5271_H_ +#define _MCF5271_H_ + +#define mbar_readLong(x) *((volatile unsigned long *) (CFG_MBAR + x)) +#define mbar_readShort(x) *((volatile unsigned short *) (CFG_MBAR + x)) +#define mbar_readByte(x) *((volatile unsigned char *) (CFG_MBAR + x)) +#define mbar_writeLong(x,y) *((volatile unsigned long *) (CFG_MBAR + x)) = y +#define mbar_writeShort(x,y) *((volatile unsigned short *) (CFG_MBAR + x)) = y +#define mbar_writeByte(x,y) *((volatile unsigned char *) (CFG_MBAR + x)) = y + +#define MCF_FMPLL_SYNCR 0x120000 +#define MCF_FMPLL_SYNSR 0x120004 +#define MCF_FMPLL_SYNCR_MFD(x) ((x&0x7)<<24) +#define MCF_FMPLL_SYNCR_RFD(x) ((x&0x7)<<19) +#define MCF_FMPLL_SYNSR_LOCK 0x8 + +#define MCF_WTM_WCR 0x140000 +#define MCF_WTM_WCNTR 0x140004 +#define MCF_WTM_WSR 0x140006 +#define MCF_WTM_WCR_EN 0x0001 + +#define MCF_RCM_RCR 0x110000 +#define MCF_RCM_RCR_FRCRSTOUT 0x40 +#define MCF_RCM_RCR_SOFTRST 0x80 + +#define MCF_GPIO_PAR_AD 0x100040 +#define MCF_GPIO_PAR_CS 0x100045 +#define MCF_GPIO_PAR_SDRAM 0x100046 +#define MCF_GPIO_PAR_FECI2C 0x100047 +#define MCF_GPIO_PAR_UART 0x100048 + +#define MCF_GPIO_AD_ADDR23 0x80 +#define MCF_GPIO_AD_ADDR22 0x40 +#define MCF_GPIO_AD_ADDR21 0x20 +#define MCF_GPIO_AD_DATAL 0x01 +#define MCF_GPIO_AD_MASK 0xe1 + +#define MCF_GPIO_PAR_CS_PAR_CS2 0x04 + +#define MCF_GPIO_SDRAM_CSSDCS_00 0x00 /* CS[3:2] pins: CS3, CS2 */ +#define MCF_GPIO_SDRAM_CSSDCS_01 0x40 /* CS[3:2] pins: CS3, SD_CS0 */ +#define MCF_GPIO_SDRAM_CSSDCS_10 0x80 /* CS[3:2] pins: SD_CS1, SC2 */ +#define MCF_GPIO_SDRAM_CSSDCS_11 0xc0 /* CS[3:2] pins: SD_CS1, SD_CS0 */ +#define MCF_GPIO_SDRAM_SDWE 0x20 /* WE pin */ +#define MCF_GPIO_SDRAM_SCAS 0x10 /* CAS pin */ +#define MCF_GPIO_SDRAM_SRAS 0x08 /* RAS pin */ +#define MCF_GPIO_SDRAM_SCKE 0x04 /* CKE pin */ +#define MCF_GPIO_SDRAM_SDCS_00 0x00 /* SD_CS[0:1] pins: GPIO, GPIO */ +#define MCF_GPIO_SDRAM_SDCS_01 0x01 /* SD_CS[0:1] pins: GPIO, SD_CS0 */ +#define MCF_GPIO_SDRAM_SDCS_10 0x02 /* SD_CS[0:1] pins: SD_CS1, GPIO */ +#define MCF_GPIO_SDRAM_SDCS_11 0x03 /* SD_CS[0:1] pins: SD_CS1, SD_CS0 */ + +#define MCF_GPIO_PAR_UART_U0RTS 0x0001 +#define MCF_GPIO_PAR_UART_U0CTS 0x0002 +#define MCF_GPIO_PAR_UART_U0TXD 0x0004 +#define MCF_GPIO_PAR_UART_U0RXD 0x0008 +#define MCF_GPIO_PAR_UART_U1RXD_UART1 0x0C00 +#define MCF_GPIO_PAR_UART_U1TXD_UART1 0x0300 + +#define MCF_GPIO_PAR_SDRAM_PAR_CSSDCS(x) (((x)&0x03)<<6) + +#define MCF_SDRAMC_DCR 0x000040 +#define MCF_SDRAMC_DACR0 0x000048 +#define MCF_SDRAMC_DMR0 0x00004C + +#define MCF_SDRAMC_DCR_RC(x) (((x)&0x01FF)<<0) +#define MCF_SDRAMC_DCR_RTIM(x) (((x)&0x0003)<<9) +#define MCF_SDRAMC_DCR_IS 0x0800 +#define MCF_SDRAMC_DCR_COC 0x1000 +#define MCF_SDRAMC_DCR_NAM 0x2000 + +#define MCF_SDRAMC_DACRn_IP 0x00000008 +#define MCF_SDRAMC_DACRn_PS(x) (((x)&0x00000003)<<4) +#define MCF_SDRAMC_DACRn_MRS 0x00000040 +#define MCF_SDRAMC_DACRn_CBM(x) (((x)&0x00000007)<<8) +#define MCF_SDRAMC_DACRn_CASL(x) (((x)&0x00000003)<<12) +#define MCF_SDRAMC_DACRn_RE 0x00008000 +#define MCF_SDRAMC_DACRn_BA(x) (((x)&0x00003FFF)<<18) + +#define MCF_SDRAMC_DMRn_BAM_8M 0x007C0000 +#define MCF_SDRAMC_DMRn_BAM_16M 0x00FC0000 +#define MCF_SDRAMC_DMRn_V 0x00000001 + +#define MCFSIM_ICR1 0x000C41 + +#endif /* _MCF5271_H_ */ diff --git a/include/asm-m68k/mcftimer.h b/include/asm-m68k/mcftimer.h index 047950b..a73b80e 100644 --- a/include/asm-m68k/mcftimer.h +++ b/include/asm-m68k/mcftimer.h @@ -45,7 +45,7 @@ #elif defined(CONFIG_M5249) || defined(CONFIG_M5307) || defined(CONFIG_M5407) #define MCFTIMER_BASE1 0x140 /* Base address of TIMER1 */ #define MCFTIMER_BASE2 0x180 /* Base address of TIMER2 */ -#elif defined(CONFIG_M5282) +#elif defined(CONFIG_M5282) | defined(CONFIG_M5271) #define MCFTIMER_BASE1 0x150000 /* Base address of TIMER1 */ #define MCFTIMER_BASE2 0x160000 /* Base address of TIMER2 */ #define MCFTIMER_BASE3 0x170000 /* Base address of TIMER4 */ diff --git a/include/asm-m68k/mcfuart.h b/include/asm-m68k/mcfuart.h index e5082a9..7c0999d 100644 --- a/include/asm-m68k/mcfuart.h +++ b/include/asm-m68k/mcfuart.h @@ -46,7 +46,7 @@ #define MCFUART_BASE1 0x140 /* Base address of UART1 */ #define MCFUART_BASE2 0x180 /* Base address of UART2 */ #endif -#elif defined(CONFIG_M5282) +#elif defined(CONFIG_M5282) || defined(CONFIG_M5271) #define MCFUART_BASE1 0x200 /* Base address of UART1 */ #define MCFUART_BASE2 0x240 /* Base address of UART2 */ #define MCFUART_BASE3 0x280 /* Base address of UART3 */ diff --git a/include/asm-m68k/ptrace.h b/include/asm-m68k/ptrace.h index a6d3d74..75b2418 100644 --- a/include/asm-m68k/ptrace.h +++ b/include/asm-m68k/ptrace.h @@ -43,7 +43,7 @@ struct pt_regs { ulong a4; ulong a5; ulong a6; -#if defined(CONFIG_M5272) || defined(CONFIG_M5282) || defined(CONFIG_M5249) +#if defined(CONFIG_M5272) || defined(CONFIG_M5282) || defined(CONFIG_M5249) || defined(CONFIG_M5271) unsigned format : 4; /* frame format specifier */ unsigned vector : 12; /* vector offset */ unsigned short sr; diff --git a/include/asm-ppc/i2c.h b/include/asm-ppc/i2c.h index fa9d164..1680d3a 100644 --- a/include/asm-ppc/i2c.h +++ b/include/asm-ppc/i2c.h @@ -87,7 +87,7 @@ typedef struct i2c #error CFG_I2C_OFFSET is not defined in /include/configs/${BOARD}.h #endif -#if defined(CONFIG_MPC8349ADS) || defined(CONFIG_TQM834X) +#if defined(CONFIG_MPC8349EMDS) || defined(CONFIG_TQM834X) /* * MPC8349 have two i2c bus */ diff --git a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h index 1848aaf..3ba0bdf 100644 --- a/include/asm-ppc/processor.h +++ b/include/asm-ppc/processor.h @@ -735,7 +735,9 @@ #define PVR_440GP_RC 0x40120481 #define PVR_440EP_RA 0x42221850 #define PVR_440EP_RB 0x422218D3 /* 440EP rev B and 440GR rev A have same PVR */ +#define PVR_440EP_RC 0x422218D4 /* 440EP rev C and 440GR rev B have same PVR */ #define PVR_440GR_RA 0x422218D3 /* 440EP rev B and 440GR rev A have same PVR */ +#define PVR_440GR_RB 0x422218D4 /* 440EP rev C and 440GR rev B have same PVR */ #define PVR_440GX_RA 0x51B21850 #define PVR_440GX_RB 0x51B21851 #define PVR_440GX_RC 0x51B21892 diff --git a/include/commproc.h b/include/commproc.h index 7900166..061468e 100644 --- a/include/commproc.h +++ b/include/commproc.h @@ -2,7 +2,7 @@ * MPC8xx Communication Processor Module. * Copyright (c) 1997 Dan Malek (dmalek@jlc.net) * - * (C) Copyright 2000-2004 + * (C) Copyright 2000-2006 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * This file contains structures and information for the communication @@ -1412,6 +1412,7 @@ typedef struct scc_enet { defined(CONFIG_TQM823L) || defined(CONFIG_TQM823M) || \ defined(CONFIG_TQM850L) || defined(CONFIG_TQM850M) || \ defined(CONFIG_ETX094) || defined(CONFIG_RRVISION)|| \ + defined(CONFIG_VIRTLAB2)|| \ (defined(CONFIG_LANTEC) && CONFIG_LANTEC < 2) /* Bits in parallel I/O port registers that have to be set/cleared * to configure the pins for SCC2 use. diff --git a/include/configs/BC3450.h b/include/configs/BC3450.h index a79de40..5b54f30 100644 --- a/include/configs/BC3450.h +++ b/include/configs/BC3450.h @@ -42,21 +42,21 @@ #define CONFIG_MPC5200 1 /* (more precisely a MPC5200 CPU) */ #define CONFIG_TQM5200 1 /* ... on a TQM5200 module */ -#define CONFIG_BC3450 1 /* ... on a BC3450 mainboard */ -#define CONFIG_BC3450_PS2 1 /* + a PS/2 converter onboard */ -#define CONFIG_BC3450_IDE 1 /* + IDE drives (Compact Flash) */ +#define CONFIG_BC3450 1 /* ... on a BC3450 mainboard */ +#define CONFIG_BC3450_PS2 1 /* + a PS/2 converter onboard */ +#define CONFIG_BC3450_IDE 1 /* + IDE drives (Compact Flash) */ #define CONFIG_BC3450_USB 1 /* + USB support */ # define CONFIG_FAT 1 /* + FAT support */ # define CONFIG_EXT2 1 /* + EXT2 support */ #undef CONFIG_BC3450_BUZZER /* + Buzzer onboard */ #undef CONFIG_BC3450_CAN /* + CAN transceiver */ #undef CONFIG_BC3450_DS1340 /* + a RTC DS1340 onboard */ -#undef CONFIG_BC3450_DS3231 /* + a RTC DS3231 onboard tbd */ -#undef CONFIG_BC3450_AC97 /* + AC97 on PSC2, tbd */ +#undef CONFIG_BC3450_DS3231 /* + a RTC DS3231 onboard tbd */ +#undef CONFIG_BC3450_AC97 /* + AC97 on PSC2, tbd */ #define CONFIG_BC3450_FP 1 /* + enable FP O/P */ #undef CONFIG_BC3450_CRT /* + enable CRT O/P (Debug only!) */ -#define CFG_MPC5XXX_CLKIN 33000000 /* ... running at 33.000000MHz */ +#define CFG_MPC5XXX_CLKIN 33000000 /* ... running at 33.000000MHz */ #define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ #define BOOTFLAG_WARM 0x02 /* Software reboot */ @@ -91,7 +91,7 @@ */ # define CONFIG_PCI 1 # define CONFIG_PCI_PNP 1 -/* #define CONFIG_PCI_SCAN_SHOW 1 */ +/* #define CONFIG_PCI_SCAN_SHOW 1 */ #define CONFIG_PCI_MEM_BUS 0x40000000 #define CONFIG_PCI_MEM_PHYS CONFIG_PCI_MEM_BUS @@ -103,7 +103,7 @@ #define CONFIG_NET_MULTI 1 /*#define CONFIG_EEPRO100 XXX - FIXME: conflicts when CONFIG_MII is enabled */ -#define CFG_RX_ETH_BUFFER 8 /* use 8 rx buffer on eepro100 */ +#define CFG_RX_ETH_BUFFER 8 /* use 8 rx buffer on eepro100 */ #define CONFIG_NS8382X 1 #ifdef CONFIG_PCI @@ -132,15 +132,15 @@ # define ADD_BMP_CMD 0 #endif -/* - * Partitions +/* + * Partitions */ #define CONFIG_MAC_PARTITION #define CONFIG_DOS_PARTITION #define CONFIG_ISO_PARTITION -/* - * USB +/* + * USB */ #ifdef CONFIG_BC3450_USB # define CONFIG_USB_OHCI @@ -150,8 +150,8 @@ # define ADD_USB_CMD 0 #endif /* CONFIG_BC3450_USB */ -/* - * POST support +/* + * POST support */ #define CONFIG_POST (CFG_POST_MEMORY | \ CFG_POST_CPU | \ @@ -165,8 +165,8 @@ # define CFG_CMD_POST_DIAG 0 #endif /* CONFIG_POST */ -/* - * IDE +/* + * IDE */ #ifdef CONFIG_BC3450_IDE # define ADD_IDE_CMD CFG_CMD_IDE @@ -219,7 +219,7 @@ /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ #include -#define CONFIG_TIMESTAMP /* display image timestamps */ +#define CONFIG_TIMESTAMP /* display image timestamps */ #if (TEXT_BASE == 0xFC000000) /* Boot low */ # define CFG_LOWBOOT 1 @@ -242,14 +242,14 @@ "ipaddr=192.168.1.10\0" \ "serverip=192.168.1.3\0" \ "netmask=255.255.255.0\0" \ - "hostname=bc3450\0" \ + "hostname=bc3450\0" \ "rootpath=/opt/eldk/ppc_6xx\0" \ - "kernel_addr=fc0a0000\0" \ - "ramdisk_addr=fc1c0000\0" \ + "kernel_addr=fc0a0000\0" \ + "ramdisk_addr=fc1c0000\0" \ "ramargs=setenv bootargs root=/dev/ram rw\0" \ "nfsargs=setenv bootargs root=/dev/nfs rw " \ "nfsroot=$(serverip):$(rootpath)\0" \ - "ideargs=setenv bootargs root=/dev/hda2 ro\0" \ + "ideargs=setenv bootargs root=/dev/hda2 ro\0" \ "addip=setenv bootargs $(bootargs) " \ "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask)" \ ":$(hostname):$(netdev):off panic=1\0" \ @@ -260,10 +260,10 @@ "flash_nfs=run nfsargs addip addcons; bootm $(kernel_addr)\0" \ "net_nfs=tftp 200000 $(bootfile); " \ "run nfsargs addip addcons; bootm\0" \ - "ide_nfs=run nfsargs addip addcons; " \ - "disk 200000 0:1; bootm\0" \ - "ide_ide=run ideargs addip addcons; " \ - "disk 200000 0:1; bootm\0" \ + "ide_nfs=run nfsargs addip addcons; " \ + "disk 200000 0:1; bootm\0" \ + "ide_ide=run ideargs addip addcons; " \ + "disk 200000 0:1; bootm\0" \ "usb_self=run usbload; run ramargs addip addcons; " \ "bootm 200000 400000\0" \ "usbload=usb reset; usb scan; usbboot 200000 0:1; " \ @@ -288,7 +288,7 @@ * PCI Bus clocking configuration * * Actually a PCI Clock of 66 MHz is only set (in cpu_init.c) if - * CFG_IPBSPEED_133 is defined. This is because a PCI Clock of 66 MHz yet + * CFG_IPBSPEED_133 is defined. This is because a PCI Clock of 66 MHz yet * hasn't been tested with a IPB Bus Clock of 66 MHz. */ #if defined(CFG_IPBSPEED_133) @@ -314,9 +314,9 @@ #define CFG_I2C_SLAVE 0x7F /* - * EEPROM configuration for I²C EEPROM M24C32 + * EEPROM configuration for I²C EEPROM M24C32 * M24C64 should work also. For other EEPROMs config should be verified. - * + * * The TQM5200 module may hold an EEPROM at address 0x50. */ #define CFG_I2C_EEPROM_ADDR 0x50 /* 1010000x (TQM) */ @@ -376,7 +376,7 @@ #define CFG_ENV_SIZE 0x10000 #define CFG_ENV_SECT_SIZE 0x20000 #define CFG_ENV_ADDR_REDUND (CFG_ENV_ADDR + CFG_ENV_SECT_SIZE) -#define CFG_ENV_SIZE_REDUND (CFG_ENV_SIZE) +#define CFG_ENV_SIZE_REDUND (CFG_ENV_SIZE) /* * Memory map @@ -419,25 +419,25 @@ /* * GPIO configuration on BC3450 * - * PSC1: UART1 (Service-UART) [0x xxxxxxx4] - * PSC2: UART2 [0x xxxxxx4x] - * or: AC/97 if CONFIG_BC3450_AC97 [0x xxxxxx2x] - * PSC3: USB2 [0x xxxxx1xx] - * USB: UART4(ext.)/UART5(int.) [0x xxxx2xxx] - * (this has to match - * CONFIG_USB_CONFIG which is - * used by usb_ohci.c to set - * the USB ports) - * Eth: 10/100Mbit Ethernet [0x xxx0xxxx] - * (this is reset to '5' - * in FEC driver: fec.c) - * PSC6: UART6 (int. to PS/2 contr.) [0x xx5xxxxx] - * ATA/CS: ??? [0x x1xxxxxx] - * FIXME! UM Fig 2-10 suggests [0x x0xxxxxx] + * PSC1: UART1 (Service-UART) [0x xxxxxxx4] + * PSC2: UART2 [0x xxxxxx4x] + * or: AC/97 if CONFIG_BC3450_AC97 [0x xxxxxx2x] + * PSC3: USB2 [0x xxxxx1xx] + * USB: UART4(ext.)/UART5(int.) [0x xxxx2xxx] + * (this has to match + * CONFIG_USB_CONFIG which is + * used by usb_ohci.c to set + * the USB ports) + * Eth: 10/100Mbit Ethernet [0x xxx0xxxx] + * (this is reset to '5' + * in FEC driver: fec.c) + * PSC6: UART6 (int. to PS/2 contr.) [0x xx5xxxxx] + * ATA/CS: ??? [0x x1xxxxxx] + * FIXME! UM Fig 2-10 suggests [0x x0xxxxxx] * CS1: Use Pin gpio_wkup_6 as second - * SDRAM chip select (mem_cs1) + * SDRAM chip select (mem_cs1) * Timer: CAN2 / SPI - * I2C: CAN1 / I²C2 [0x bxxxxxxx] + * I2C: CAN1 / I²C2 [0x bxxxxxxx] */ #ifdef CONFIG_BC3450_AC97 # define CFG_GPS_PORT_CONFIG 0xb1502124 @@ -465,7 +465,7 @@ #define CFG_MEMTEST_START 0x00100000 /* memtest works on */ #define CFG_MEMTEST_END 0x00f00000 /* 1 ... 15 MB in DRAM */ -#define CFG_LOAD_ADDR 0x100000 /* default load address */ +#define CFG_LOAD_ADDR 0x100000 /* default load address */ #define CFG_HZ 1000 /* dec freq: 1ms ticks */ @@ -489,7 +489,7 @@ #define CFG_BOOTCS_START CFG_FLASH_BASE #define CFG_BOOTCS_SIZE CFG_FLASH_SIZE #ifdef CFG_PCISPEED_66 -# define CFG_BOOTCS_CFG 0x0008DF30 /* for pci_clk = 66 MHz */ +# define CFG_BOOTCS_CFG 0x0008DF30 /* for pci_clk = 66 MHz */ #else # define CFG_BOOTCS_CFG 0x0004DF30 /* for pci_clk = 33 MHz */ #endif @@ -533,17 +533,17 @@ * USB stuff */ #define CONFIG_USB_CLOCK 0x0001BBBB -#define CONFIG_USB_CONFIG 0x00002000 /* we're using Port 2 */ +#define CONFIG_USB_CONFIG 0x00002000 /* we're using Port 2 */ /* * IDE/ATA stuff Supports IDE harddisk */ #undef CONFIG_IDE_8xx_PCCARD /* Use IDE with PC Card Adapter */ -#undef CONFIG_IDE_8xx_DIRECT /* Direct IDE not supported */ -#undef CONFIG_IDE_LED /* LED for ide not supported */ +#undef CONFIG_IDE_8xx_DIRECT /* Direct IDE not supported */ +#undef CONFIG_IDE_LED /* LED for ide not supported */ -#define CONFIG_IDE_RESET /* reset for ide supported */ +#define CONFIG_IDE_RESET /* reset for ide supported */ #define CONFIG_IDE_PREINIT #define CFG_IDE_MAXBUS 1 /* max. 1 IDE bus */ diff --git a/include/configs/M5271EVB.h b/include/configs/M5271EVB.h new file mode 100644 index 0000000..f0fc013 --- /dev/null +++ b/include/configs/M5271EVB.h @@ -0,0 +1,156 @@ +/* + * Configuation settings for the Freescale M5271EVB + * + * Based on MC5272C3 and r5200 board configs + * (C) Copyright 2006 Lab X Technologies + * (C) Copyright 2003 Josef Baumgartner + * + * 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 + */ + +/* + * board/config.h - configuration options, board specific + */ + +#ifndef _M5271EVB_H +#define _M5271EVB_H + +#define DEBUG +#undef DEBUG + +/* + * High Level Configuration Options (easy to change) + */ +#define CONFIG_MCF52x2 /* define processor family */ +#define CONFIG_M5271 /* define processor type */ +#define CONFIG_M5271EVB /* define board type */ + +#define CONFIG_IPADDR 192.168.30.1 +#define CONFIG_SERVERIP 192.168.1.1 +#define CONFIG_ETHADDR 00:06:3b:01:41:55 + +#define CONFIG_BAUDRATE 19200 +#define CFG_BAUDRATE_TABLE { 9600 , 19200 , 38400 , 57600, 115200 } + +#undef CONFIG_WATCHDOG /* disable watchdog */ + +#define CONFIG_BOOTDELAY 5 + +/* Configuration for environment + * Environment is embedded in u-boot in the second sector of the flash + */ +#ifndef CONFIG_MONITOR_IS_IN_RAM +#define CFG_ENV_OFFSET 0x4000 +#define CFG_ENV_SECT_SIZE 0x2000 +#define CFG_ENV_IS_IN_FLASH 1 +#else +#define CFG_ENV_ADDR 0xffe04000 +#define CFG_ENV_SECT_SIZE 0x2000 +#define CFG_ENV_IS_IN_FLASH 1 +#endif + +#define CONFIG_COMMANDS ((CONFIG_CMD_DFL | CFG_CMD_PING | CFG_CMD_NET ) & ~(CFG_CMD_LOADS | CFG_CMD_LOADB)) + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include + +#define CFG_PROMPT "=> " +#define CFG_LONGHELP /* undef to save memory */ + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_LOAD_ADDR 0x00100000 + +#define CFG_MEMTEST_START 0x400 +#define CFG_MEMTEST_END 0x380000 + +#define CFG_HZ 1000000 +#define CFG_CLK 100000000 + +/* + * Low Level Configuration Settings + * (address mappings, register initial values, etc.) + * You should know what you are doing if you make changes here. + */ + +#define CFG_MBAR 0x40000000 /* Register Base Addrs */ + +/* Enable FEC ethernet */ +#define FEC_ENET +#define CONFIG_NET_RETRY_COUNT 5 +#define CFG_ENET_BD_BASE 0x480000 + +/* + * Definitions for initial stack pointer and data area (in DPRAM) + */ +#define CFG_INIT_RAM_ADDR 0x20000000 +#define CFG_INIT_RAM_END 0x1000 /* End of used area in internal SRAM */ +#define CFG_GBL_DATA_SIZE 64 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET + +/* + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_SDRAM_SIZE 16 /* SDRAM size in MB */ +#define CFG_FLASH_BASE 0xffe00000 + +#ifdef CONFIG_MONITOR_IS_IN_RAM +#define CFG_MONITOR_BASE 0x20000 +#else +#define CFG_MONITOR_BASE (CFG_FLASH_BASE + 0x400) +#endif + +#define CFG_MONITOR_LEN 0x40000 +#define CFG_MALLOC_LEN (256 << 10) +#define CFG_BOOTPARAMS_LEN (64*1024) + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization ?? + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ + +/* FLASH organization */ +#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 11 /* max number of sectors on one chip */ +#define CFG_FLASH_ERASE_TOUT 1000 + +#define CFG_FLASH_CFI 1 +#define CFG_FLASH_CFI_DRIVER 1 +#define CFG_FLASH_SIZE 0x200000 + +/* Cache Configuration */ +#define CFG_CACHELINE_SIZE 16 + +/* Port configuration */ +#define CFG_FECI2C 0xF0 + +#endif /* _M5271EVB_H */ diff --git a/include/configs/MPC8349ADS.h b/include/configs/MPC8349ADS.h deleted file mode 100644 index 1e9a1f7..0000000 --- a/include/configs/MPC8349ADS.h +++ /dev/null @@ -1,653 +0,0 @@ -/* - * Copyright 2004 Freescale Semiconductor. - * - * 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 - */ - -/* - * mpc8349ads board configuration file - * - * Please refer to doc/README.mpc83xxads for more info. - */ - -#ifndef __CONFIG_H -#define __CONFIG_H - -#undef DEBUG - -#define CONFIG_MII - -/* - * High Level Configuration Options - */ -#define CONFIG_E300 1 /* E300 Family */ -#define CONFIG_MPC83XX 1 /* MPC83XX family */ -#define CONFIG_MPC8349 1 /* MPC8349 specific */ -#define CONFIG_MPC8349ADS 1 /* MPC8349ADS board specific */ - -#define CONFIG_PCI -#undef CONFIG_MPC83XX_PCI2 /* support for 2nd PCI controller */ -#define CONFIG_TSEC_ENET /* tsec ethernet support */ -#define CONFIG_ENV_OVERWRITE - -#define CONFIG_SPD_EEPROM /* Use SPD EEPROM for DDR setup*/ - -#undef CONFIG_DDR_ECC /* only for ECC DDR module */ - -#define PCI_66M -#ifdef PCI_66M -#define CONFIG_83XX_CLKIN 66000000 /* in Hz */ -#else -#define CONFIG_83XX_CLKIN 33000000 /* in Hz */ -#endif - -#ifndef CONFIG_SYS_CLK_FREQ -#ifdef PCI_66M -#define CONFIG_SYS_CLK_FREQ 66000000 -#else -#define CONFIG_SYS_CLK_FREQ 33000000 -#endif -#endif - -#define CONFIG_BOARD_EARLY_INIT_F /* call board_pre_init */ - -#define CFG_IMMRBAR 0xE0000000 - -#undef CFG_DRAM_TEST /* memory test, takes time */ -#define CFG_MEMTEST_START 0x00000000 /* memtest region */ -#define CFG_MEMTEST_END 0x00100000 - -/* - * DDR Setup - */ - -#define CFG_DDR_BASE 0x00000000 /* DDR is system memory*/ -#define CFG_SDRAM_BASE CFG_DDR_BASE -#undef CONFIG_DDR_2T_TIMING -#define CFG_DDR_SDRAM_BASE CFG_DDR_BASE - -#if defined(CONFIG_SPD_EEPROM) - /* - * Determine DDR configuration from I2C interface. - */ - #define SPD_EEPROM_ADDRESS 0x51 /* DDR DIMM */ -#else - /* - * Manually set up DDR parameters - */ - #define CFG_DDR_SIZE 256 /* Mb */ - #define CFG_DDR_CONFIG (CSCONFIG_EN | CSCONFIG_ROW_BIT_13 | CSCONFIG_COL_BIT_9) - #define CFG_DDR_TIMING_1 0x37344321 - #define CFG_DDR_TIMING_2 0x00000800 /* P9-45,may need tuning */ - #define CFG_DDR_CONTROL 0xc2000000 /* unbuffered,no DYN_PWR */ - #define CFG_DDR_MODE 0x00000062 /* DLL,normal,seq,4/2.5 */ - #define CFG_DDR_INTERVAL 0x05200100 /* autocharge,no open page */ -#endif - -/* - * SDRAM on the Local Bus - */ -#define CFG_LBC_SDRAM_BASE 0xf0000000 /* Localbus SDRAM */ -#define CFG_LBC_SDRAM_SIZE 64 /* LBC SDRAM is 64MB */ - -/* - * FLASH on the Local Bus - */ -#define CFG_FLASH_CFI /* use the Common Flash Interface */ -#define CFG_FLASH_CFI_DRIVER /* use the CFI driver */ -#define CFG_FLASH_BASE 0xFE000000 /* start of FLASH */ -#define CFG_FLASH_SIZE 8 /* FLASH size in MB */ -/* #define CFG_FLASH_USE_BUFFER_WRITE */ - -#define CFG_BR0_PRELIM (CFG_FLASH_BASE | /* Flash Base address */ \ - (2 << BR_PS_SHIFT) | /* 32 bit port size */ \ - BR_V) /* valid */ -#define CFG_OR0_PRELIM 0xff806ff7 /* 16Mb Flash size*/ -#define CFG_LBLAWBAR0_PRELIM CFG_FLASH_BASE /* Window base at flash base */ -#define CFG_LBLAWAR0_PRELIM 0x80000016 /* 16Mb window size */ - -#define CFG_MAX_FLASH_BANKS 1 /* number of banks */ -#define CFG_MAX_FLASH_SECT 64 /* sectors per device */ - -#undef CFG_FLASH_CHECKSUM -#define CFG_FLASH_ERASE_TOUT 60000 /* Flash Erase Timeout (ms) */ -#define CFG_FLASH_WRITE_TOUT 500 /* Flash Write Timeout (ms) */ - -#define CFG_MID_FLASH_JUMP 0x7F000000 -#define CFG_MONITOR_BASE TEXT_BASE /* start of monitor */ - -#if (CFG_MONITOR_BASE < CFG_FLASH_BASE) -#define CFG_RAMBOOT -#else -#undef CFG_RAMBOOT -#endif - -/* - * BCSR register on local bus 32KB, 8-bit wide for ADS config reg - */ -#define CFG_BCSR 0xF8000000 -#define CFG_LBLAWBAR1_PRELIM CFG_BCSR /* Access window base at BCSR base */ -#define CFG_LBLAWAR1_PRELIM 0x8000000E /* Access window size 32K */ -#define CFG_BR1_PRELIM (CFG_BCSR|0x00000801) /* Port-size=8bit, MSEL=GPCM */ -#define CFG_OR1_PRELIM 0xFFFFE8f0 /* length 32K */ - -#define CONFIG_L1_INIT_RAM -#define CFG_INIT_RAM_LOCK 1 -#define CFG_INIT_RAM_ADDR 0x40000000 /* Initial RAM address */ -#define CFG_INIT_RAM_END 0x1000 /* End of used area in RAM*/ - -#define CFG_GBL_DATA_SIZE 0x100 /* num bytes initial data */ -#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) -#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET - -#define CFG_MONITOR_LEN (256 * 1024) /* Reserve 256 kB for Mon */ -#define CFG_MALLOC_LEN (128 * 1024) /* Reserved for malloc */ - -/* - * Local Bus LCRR and LBCR regs - * LCRR: DLL bypass, Clock divider is 4 - * External Local Bus rate is - * CLKIN * HRCWL_CSB_TO_CLKIN / HRCWL_LCL_BUS_TO_SCB_CLK / LCRR_CLKDIV - */ -#define CFG_LCRR (LCRR_DBYP | LCRR_CLKDIV_4) -#define CFG_LBC_LBCR 0x00000000 - -#define CFG_LB_SDRAM /* if board has SRDAM on local bus */ - -#ifdef CFG_LB_SDRAM -/*local bus BR2, OR2 definition for SDRAM if soldered on the ADS board*/ -/* - * Base Register 2 and Option Register 2 configure SDRAM. - * The SDRAM base address, CFG_LBC_SDRAM_BASE, is 0xf0000000. - * - * For BR2, need: - * Base address of 0xf0000000 = BR[0:16] = 1111 0000 0000 0000 0 - * port-size = 32-bits = BR2[19:20] = 11 - * no parity checking = BR2[21:22] = 00 - * SDRAM for MSEL = BR2[24:26] = 011 - * Valid = BR[31] = 1 - * - * 0 4 8 12 16 20 24 28 - * 1111 0000 0000 0000 0001 1000 0110 0001 = f0001861 - * - * FIXME: CFG_LBC_SDRAM_BASE should be masked and OR'ed into - * FIXME: the top 17 bits of BR2. - */ - -#define CFG_BR2_PRELIM 0xf0001861 /*Port-size=32bit, MSEL=SDRAM*/ -#define CFG_LBLAWBAR2_PRELIM 0xF0000000 -#define CFG_LBLAWAR2_PRELIM 0x80000019 /*64M*/ - -/* - * The SDRAM size in MB, CFG_LBC_SDRAM_SIZE, is 64. - * - * For OR2, need: - * 64MB mask for AM, OR2[0:7] = 1111 1100 - * XAM, OR2[17:18] = 11 - * 9 columns OR2[19-21] = 010 - * 13 rows OR2[23-25] = 100 - * EAD set for extra time OR[31] = 1 - * - * 0 4 8 12 16 20 24 28 - * 1111 1100 0000 0000 0110 1001 0000 0001 = fc006901 - */ - -#define CFG_OR2_PRELIM 0xfc006901 - -#define CFG_LBC_LSRT 0x32000000 /* LB sdram refresh timer, about 6us */ -#define CFG_LBC_MRTPR 0x20000000 /* LB refresh timer prescal, 266MHz/32*/ - -/* - * LSDMR masks - */ -#define CFG_LBC_LSDMR_RFEN (1 << (31 - 1)) -#define CFG_LBC_LSDMR_BSMA1516 (3 << (31 - 10)) -#define CFG_LBC_LSDMR_BSMA1617 (4 << (31 - 10)) -#define CFG_LBC_LSDMR_RFCR5 (3 << (31 - 16)) -#define CFG_LBC_LSDMR_RFCR8 (5 << (31 - 16)) -#define CFG_LBC_LSDMR_RFCR16 (7 << (31 - 16)) -#define CFG_LBC_LSDMR_PRETOACT3 (3 << (31 - 19)) -#define CFG_LBC_LSDMR_PRETOACT6 (5 << (31 - 19)) -#define CFG_LBC_LSDMR_PRETOACT7 (7 << (31 - 19)) -#define CFG_LBC_LSDMR_ACTTORW3 (3 << (31 - 22)) -#define CFG_LBC_LSDMR_ACTTORW7 (7 << (31 - 22)) -#define CFG_LBC_LSDMR_ACTTORW6 (6 << (31 - 22)) -#define CFG_LBC_LSDMR_BL8 (1 << (31 - 23)) -#define CFG_LBC_LSDMR_WRC2 (2 << (31 - 27)) -#define CFG_LBC_LSDMR_WRC3 (3 << (31 - 27)) -#define CFG_LBC_LSDMR_WRC4 (0 << (31 - 27)) -#define CFG_LBC_LSDMR_BUFCMD (1 << (31 - 29)) -#define CFG_LBC_LSDMR_CL3 (3 << (31 - 31)) - -#define CFG_LBC_LSDMR_OP_NORMAL (0 << (31 - 4)) -#define CFG_LBC_LSDMR_OP_ARFRSH (1 << (31 - 4)) -#define CFG_LBC_LSDMR_OP_SRFRSH (2 << (31 - 4)) -#define CFG_LBC_LSDMR_OP_MRW (3 << (31 - 4)) -#define CFG_LBC_LSDMR_OP_PRECH (4 << (31 - 4)) -#define CFG_LBC_LSDMR_OP_PCHALL (5 << (31 - 4)) -#define CFG_LBC_LSDMR_OP_ACTBNK (6 << (31 - 4)) -#define CFG_LBC_LSDMR_OP_RWINV (7 << (31 - 4)) - -#define CFG_LBC_LSDMR_COMMON ( CFG_LBC_LSDMR_RFEN \ - | CFG_LBC_LSDMR_BSMA1516 \ - | CFG_LBC_LSDMR_RFCR8 \ - | CFG_LBC_LSDMR_PRETOACT6 \ - | CFG_LBC_LSDMR_ACTTORW3 \ - | CFG_LBC_LSDMR_BL8 \ - | CFG_LBC_LSDMR_WRC3 \ - | CFG_LBC_LSDMR_CL3 \ - ) - -/* - * SDRAM Controller configuration sequence. - */ -#define CFG_LBC_LSDMR_1 ( CFG_LBC_LSDMR_COMMON \ - | CFG_LBC_LSDMR_OP_PCHALL) -#define CFG_LBC_LSDMR_2 ( CFG_LBC_LSDMR_COMMON \ - | CFG_LBC_LSDMR_OP_ARFRSH) -#define CFG_LBC_LSDMR_3 ( CFG_LBC_LSDMR_COMMON \ - | CFG_LBC_LSDMR_OP_ARFRSH) -#define CFG_LBC_LSDMR_4 ( CFG_LBC_LSDMR_COMMON \ - | CFG_LBC_LSDMR_OP_MRW) -#define CFG_LBC_LSDMR_5 ( CFG_LBC_LSDMR_COMMON \ - | CFG_LBC_LSDMR_OP_NORMAL) -#endif - -/* - * Serial Port - */ -#define CONFIG_CONS_INDEX 1 -#undef CONFIG_SERIAL_SOFTWARE_FIFO -#define CFG_NS16550 -#define CFG_NS16550_SERIAL -#define CFG_NS16550_REG_SIZE 1 -#define CFG_NS16550_CLK get_bus_freq(0) - -#define CFG_BAUDRATE_TABLE \ - {300, 600, 1200, 2400, 4800, 9600, 19200, 38400,115200} - -#define CFG_NS16550_COM1 (CFG_IMMRBAR+0x4500) -#define CFG_NS16550_COM2 (CFG_IMMRBAR+0x4600) - -/* Use the HUSH parser */ -#define CFG_HUSH_PARSER -#ifdef CFG_HUSH_PARSER -#define CFG_PROMPT_HUSH_PS2 "> " -#endif - -/* I2C */ -#define CONFIG_HARD_I2C /* I2C with hardware support*/ -#undef CONFIG_SOFT_I2C /* I2C bit-banged */ -#define CFG_I2C_SPEED 400000 /* I2C speed and slave address */ -#define CFG_I2C_SLAVE 0x7F -#define CFG_I2C_NOPROBES {0x69} /* Don't probe these addrs */ -#define CFG_I2C_OFFSET 0x3000 -#define CFG_I2C2_OFFSET 0x3100 - -/* TSEC */ -#define CFG_TSEC1_OFFSET 0x24000 -#define CFG_TSEC1 (CFG_IMMRBAR+CFG_TSEC1_OFFSET) -#define CFG_TSEC2_OFFSET 0x25000 -#define CFG_TSEC2 (CFG_IMMRBAR+CFG_TSEC2_OFFSET) - -/* IO Configuration */ -#define CFG_IO_CONF (\ - IO_CONF_UART |\ - IO_CONF_TSEC1 |\ - IO_CONF_IRQ0 |\ - IO_CONF_IRQ1 |\ - IO_CONF_IRQ2 |\ - IO_CONF_IRQ3 |\ - IO_CONF_IRQ4 |\ - IO_CONF_IRQ5 |\ - IO_CONF_IRQ6 |\ - IO_CONF_IRQ7 ) - -/* - * General PCI - * Addresses are mapped 1-1. - */ - -#define CFG_PCI1_MEM_BASE 0x80000000 -#define CFG_PCI1_MEM_PHYS CFG_PCI1_MEM_BASE -#define CFG_PCI1_MEM_SIZE 0x10000000 /* 256M */ -#define CFG_PCI1_MMIO_BASE 0x90000000 -#define CFG_PCI1_MMIO_PHYS CFG_PCI1_MMIO_BASE -#define CFG_PCI1_MMIO_SIZE 0x10000000 /* 256M */ -#define CFG_PCI1_IO_BASE 0x00000000 -#define CFG_PCI1_IO_PHYS 0xe2000000 -#define CFG_PCI1_IO_SIZE 0x00100000 /* 1M */ - -#define CFG_PCI2_MEM_BASE 0xa0000000 -#define CFG_PCI2_MEM_PHYS CFG_PCI2_MEM_BASE -#define CFG_PCI2_MEM_SIZE 0x10000000 /* 256M */ -#define CFG_PCI2_MMIO_BASE 0xb0000000 -#define CFG_PCI2_MMIO_PHYS CFG_PCI2_MMIO_BASE -#define CFG_PCI2_MMIO_SIZE 0x10000000 /* 256M */ -#define CFG_PCI2_IO_BASE 0x00000000 -#define CFG_PCI2_IO_PHYS 0xe2100000 -#define CFG_PCI2_IO_SIZE 0x00100000 /* 1M */ -#if defined(CONFIG_PCI) - -#define PCI_ALL_PCI1 -#if defined(PCI_64BIT) -#undef PCI_ALL_PCI1 -#undef PCI_TWO_PCI1 -#undef PCI_ONE_PCI1 -#endif - -#define CONFIG_NET_MULTI -#define CONFIG_PCI_PNP /* do pci plug-and-play */ - -#undef CONFIG_EEPRO100 -#undef CONFIG_TULIP - -#if !defined(CONFIG_PCI_PNP) - #define PCI_ENET0_IOADDR 0xFIXME - #define PCI_ENET0_MEMADDR 0xFIXME - #define PCI_IDSEL_NUMBER 0x0c /* slot0->3(IDSEL)=12->15 */ -#endif - -#undef CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ -#define CFG_PCI_SUBSYS_VENDORID 0x1057 /* Motorola */ - -#endif /* CONFIG_PCI */ - -#if defined(CONFIG_TSEC_ENET) -#ifndef CONFIG_NET_MULTI -#define CONFIG_NET_MULTI 1 -#endif - -#define CONFIG_GMII 1 /* MII PHY management */ -#define CONFIG_MPC83XX_TSEC1 1 -#define CONFIG_MPC83XX_TSEC1_NAME "TSEC0" -#define CONFIG_MPC83XX_TSEC2 1 -#define CONFIG_MPC83XX_TSEC2_NAME "TSEC1" -#define TSEC1_PHY_ADDR 0 -#define TSEC2_PHY_ADDR 1 -#define TSEC1_PHYIDX 0 -#define TSEC2_PHYIDX 0 - -/* Options are: TSEC[0-1] */ -#define CONFIG_ETHPRIME "TSEC0" - -#endif /* CONFIG_TSEC_ENET */ - -/* - * Environment - */ -#ifndef CFG_RAMBOOT - #define CFG_ENV_IS_IN_FLASH 1 - #define CFG_ENV_ADDR (CFG_MONITOR_BASE + 0x40000) - #define CFG_ENV_SECT_SIZE 0x40000 /* 256K(one sector) for env */ - #define CFG_ENV_SIZE 0x2000 -#else - #define CFG_NO_FLASH 1 /* Flash is not usable now */ - #define CFG_ENV_IS_NOWHERE 1 /* Store ENV in memory only */ - #define CFG_ENV_ADDR (CFG_MONITOR_BASE - 0x1000) - #define CFG_ENV_SIZE 0x2000 -#endif - -#define CONFIG_LOADS_ECHO 1 /* echo on for serial download */ -#define CFG_LOADS_BAUD_CHANGE 1 /* allow baudrate change */ - -#if defined(CFG_RAMBOOT) -#if defined(CONFIG_PCI) -#define CONFIG_COMMANDS ((CONFIG_CMD_DFL \ - | CFG_CMD_PING \ - | CFG_CMD_PCI \ - | CFG_CMD_I2C) \ - & \ - ~(CFG_CMD_ENV \ - | CFG_CMD_LOADS)) -#else -#define CONFIG_COMMANDS ((CONFIG_CMD_DFL \ - | CFG_CMD_PING \ - | CFG_CMD_I2C) \ - & \ - ~(CFG_CMD_ENV \ - | CFG_CMD_LOADS)) -#endif -#else -#if defined(CONFIG_PCI) -#define CONFIG_COMMANDS (CONFIG_CMD_DFL \ - | CFG_CMD_PCI \ - | CFG_CMD_PING \ - | CFG_CMD_I2C) -#else -#define CONFIG_COMMANDS (CONFIG_CMD_DFL \ - | CFG_CMD_PING \ - | CFG_CMD_I2C \ - | CFG_CMD_MII \ - ) -#endif -#endif - -#include - -#undef CONFIG_WATCHDOG /* watchdog disabled */ - -/* - * Miscellaneous configurable options - */ -#define CFG_LONGHELP /* undef to save memory */ -#define CFG_LOAD_ADDR 0x2000000 /* default load address */ -#define CFG_PROMPT "=> " /* Monitor Command Prompt */ - -#if (CONFIG_COMMANDS & CFG_CMD_KGDB) - #define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ -#else - #define CFG_CBSIZE 256 /* Console I/O Buffer Size */ -#endif - -#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ -#define CFG_MAXARGS 16 /* max number of command args */ -#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ -#define CFG_HZ 1000 /* decrementer freq: 1ms ticks */ - -/* - * For booting Linux, the board info and command line data - * have to be in the first 8 MB of memory, since this is - * the maximum mapped by the Linux kernel during initialization. - */ -#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux*/ - -/* Cache Configuration */ -#define CFG_DCACHE_SIZE 32768 -#define CFG_CACHELINE_SIZE 32 -#if (CONFIG_COMMANDS & CFG_CMD_KGDB) -#define CFG_CACHELINE_SHIFT 5 /*log base 2 of the above value*/ -#endif - -#define CFG_RCWH_PCIHOST 0x80000000 /* PCIHOST */ - -#define CFG_HRCW_LOW (\ - HRCWL_LCL_BUS_TO_SCB_CLK_1X1 |\ - HRCWL_DDR_TO_SCB_CLK_1X1 |\ - HRCWL_CSB_TO_CLKIN_4X1 |\ - HRCWL_VCO_1X2 |\ - HRCWL_CORE_TO_CSB_2X1) - -#if defined(PCI_64BIT) -#define CFG_HRCW_HIGH (\ - HRCWH_PCI_HOST |\ - HRCWH_64_BIT_PCI |\ - HRCWH_PCI1_ARBITER_ENABLE |\ - HRCWH_PCI2_ARBITER_DISABLE |\ - HRCWH_CORE_ENABLE |\ - HRCWH_FROM_0X00000100 |\ - HRCWH_BOOTSEQ_DISABLE |\ - HRCWH_SW_WATCHDOG_DISABLE |\ - HRCWH_ROM_LOC_LOCAL_16BIT |\ - HRCWH_TSEC1M_IN_GMII |\ - HRCWH_TSEC2M_IN_GMII ) -#else -#define CFG_HRCW_HIGH (\ - HRCWH_PCI_HOST |\ - HRCWH_32_BIT_PCI |\ - HRCWH_PCI1_ARBITER_ENABLE |\ - HRCWH_PCI2_ARBITER_ENABLE |\ - HRCWH_CORE_ENABLE |\ - HRCWH_FROM_0X00000100 |\ - HRCWH_BOOTSEQ_DISABLE |\ - HRCWH_SW_WATCHDOG_DISABLE |\ - HRCWH_ROM_LOC_LOCAL_16BIT |\ - HRCWH_TSEC1M_IN_GMII |\ - HRCWH_TSEC2M_IN_GMII ) -#endif - -/* System IO Config */ -#define CFG_SICRH SICRH_TSOBI1 -#define CFG_SICRL SICRL_LDP_A - -#define CFG_HID0_INIT 0x000000000 - -#define CFG_HID0_FINAL CFG_HID0_INIT - -/* #define CFG_HID0_FINAL (\ - HID0_ENABLE_INSTRUCTION_CACHE |\ - HID0_ENABLE_M_BIT |\ - HID0_ENABLE_ADDRESS_BROADCAST ) */ - -#define CFG_HID2 HID2_HBE - -/* DDR 0 - 256MB */ -#define CFG_IBAT0L (CFG_SDRAM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE) -#define CFG_IBAT0U (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP) - -/* stack in DCACHE @ 1GB (no backing mem) */ -#define CFG_IBAT1L (CFG_INIT_RAM_ADDR | BATL_PP_10 | BATL_MEMCOHERENCE) -#define CFG_IBAT1U (CFG_INIT_RAM_ADDR | BATU_BL_128K | BATU_VS | BATU_VP) - -/* 2G - 3G PCI */ -#ifdef CONFIG_PCI -#define CFG_IBAT2L (CFG_PCI1_MEM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE) -#define CFG_IBAT2U (CFG_PCI1_MEM_BASE | BATU_BL_256M | BATU_VS | BATU_VP) -#define CFG_IBAT3L (CFG_PCI1_MMIO_BASE | BATL_PP_10 | BATL_CACHEINHIBIT | BATL_GUARDEDSTORAGE) -#define CFG_IBAT3U (CFG_PCI1_MMIO_BASE | BATU_BL_256M | BATU_VS | BATU_VP) -#else -#define CFG_IBAT2L (0) -#define CFG_IBAT2U (0) -#define CFG_IBAT3L (0) -#define CFG_IBAT3U (0) -#endif - -#ifdef CONFIG_MPC83XX_PCI2 -#define CFG_IBAT4L (CFG_PCI2_MEM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE) -#define CFG_IBAT4U (CFG_PCI2_MEM_BASE | BATU_BL_256M | BATU_VS | BATU_VP) -#define CFG_IBAT5L (CFG_PCI2_MMIO_BASE | BATL_PP_10 | BATL_CACHEINHIBIT | BATL_GUARDEDSTORAGE) -#define CFG_IBAT5U (CFG_PCI2_MMIO_BASE | BATU_BL_256M | BATU_VS | BATU_VP) -#else -#define CFG_IBAT4L (0) -#define CFG_IBAT4U (0) -#define CFG_IBAT5L (0) -#define CFG_IBAT5U (0) -#endif - -/* IMMRBAR */ -#define CFG_IBAT6L (CFG_IMMRBAR | BATL_PP_10 | BATL_CACHEINHIBIT | BATL_GUARDEDSTORAGE) -#define CFG_IBAT6U (CFG_IMMRBAR | BATU_BL_256M | BATU_VS | BATU_VP) - -/* SDRAM, BCSR & FLASH */ -#define CFG_IBAT7L (0xf0000000 | BATL_PP_10 | BATL_CACHEINHIBIT | BATL_GUARDEDSTORAGE) -#define CFG_IBAT7U (0xf0000000 | BATU_BL_256M | BATU_VS | BATU_VP) - -#define CFG_DBAT0L CFG_IBAT0L -#define CFG_DBAT0U CFG_IBAT0U -#define CFG_DBAT1L CFG_IBAT1L -#define CFG_DBAT1U CFG_IBAT1U -#define CFG_DBAT2L CFG_IBAT2L -#define CFG_DBAT2U CFG_IBAT2U -#define CFG_DBAT3L CFG_IBAT3L -#define CFG_DBAT3U CFG_IBAT3U -#define CFG_DBAT4L CFG_IBAT4L -#define CFG_DBAT4U CFG_IBAT4U -#define CFG_DBAT5L CFG_IBAT5L -#define CFG_DBAT5U CFG_IBAT5U -#define CFG_DBAT6L CFG_IBAT6L -#define CFG_DBAT6U CFG_IBAT6U -#define CFG_DBAT7L CFG_IBAT7L -#define CFG_DBAT7U CFG_IBAT7U - - -/* - * Internal Definitions - * - * Boot Flags - */ -#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ -#define BOOTFLAG_WARM 0x02 /* Software reboot */ - -#if (CONFIG_COMMANDS & CFG_CMD_KGDB) -#define CONFIG_KGDB_BAUDRATE 230400 /* speed of kgdb serial port */ -#define CONFIG_KGDB_SER_INDEX 2 /* which serial port to use */ -#endif - -/* - * Environment Configuration - */ - -#if defined(CONFIG_TSEC_ENET) -#define CONFIG_ETHADDR 00:04:9f:11:22:33 -#define CONFIG_HAS_ETH1 -#define CONFIG_ETH1ADDR 00:E0:0C:00:7D:01 -#endif - -#define CONFIG_IPADDR 192.168.1.253 - -#define CONFIG_HOSTNAME unknown -#define CONFIG_ROOTPATH /nfsroot -#define CONFIG_BOOTFILE your.uImage - -#define CONFIG_SERVERIP 192.168.1.1 -#define CONFIG_GATEWAYIP 192.168.1.1 -#define CONFIG_NETMASK 255.255.255.0 - -#define CONFIG_LOADADDR 200000 /* default location for tftp and bootm */ - -#define CONFIG_BOOTDELAY 6 /* -1 disables auto-boot */ -#undef CONFIG_BOOTARGS /* the boot command will set bootargs */ - -#define CONFIG_BAUDRATE 115200 - - -#define CONFIG_EXTRA_ENV_SETTINGS \ - "netdev=eth0\0" \ - "consoledev=ttyS0\0" \ - "ramdiskaddr=400000\0" \ - "ramdiskfile=ramfs.83xx\0" - -#define CONFIG_NFSBOOTCOMMAND \ - "setenv bootargs root=/dev/nfs rw " \ - "nfsroot=$serverip:$rootpath " \ - "ip=$ipaddr:$serverip:$gatewayip:$netmask:$hostname:$netdev:off " \ - "console=$consoledev,$baudrate $othbootargs;" \ - "tftp $loadaddr $bootfile;" \ - "bootm $loadaddr" - -#define CONFIG_RAMBOOTCOMMAND \ - "setenv bootargs root=/dev/ram rw " \ - "console=$consoledev,$baudrate $othbootargs;" \ - "tftp $ramdiskaddr $ramdiskfile;" \ - "tftp $loadaddr $bootfile;" \ - "bootm $loadaddr $ramdiskaddr" - -#define CONFIG_BOOTCOMMAND CONFIG_NFSBOOTCOMMAND - -#endif /* __CONFIG_H */ diff --git a/include/configs/MPC8349EMDS.h b/include/configs/MPC8349EMDS.h index 1a47980..66f1646 100644 --- a/include/configs/MPC8349EMDS.h +++ b/include/configs/MPC8349EMDS.h @@ -29,7 +29,6 @@ #ifndef __CONFIG_H #define __CONFIG_H -#define DEBUG #undef DEBUG /* @@ -40,8 +39,8 @@ #define CONFIG_MPC8349 1 /* MPC8349 specific */ #define CONFIG_MPC8349EMDS 1 /* MPC8349EMDS board specific */ -/* FIXME: Real PCI support will come in a follow-up update. */ #undef CONFIG_PCI +#undef CONFIG_MPC83XX_PCI2 /* support for 2nd PCI controller */ #define PCI_66M #ifdef PCI_66M @@ -53,8 +52,10 @@ #ifndef CONFIG_SYS_CLK_FREQ #ifdef PCI_66M #define CONFIG_SYS_CLK_FREQ 66000000 +#define HRCWL_CSB_TO_CLKIN HRCWL_CSB_TO_CLKIN_4X1 #else #define CONFIG_SYS_CLK_FREQ 33000000 +#define HRCWL_CSB_TO_CLKIN HRCWL_CSB_TO_CLKIN_8X1 #endif #endif @@ -69,7 +70,7 @@ /* * DDR Setup */ -#define CONFIG_DDR_ECC /* only for ECC DDR module */ +#undef CONFIG_DDR_ECC /* only for ECC DDR module */ #define CONFIG_DDR_ECC_CMD /* use DDR ECC user commands */ #define CONFIG_SPD_EEPROM /* use SPD EEPROM for DDR setup*/ @@ -157,7 +158,7 @@ /* * BCSR register on local bus 32KB, 8-bit wide for MDS config reg */ -#define CFG_BCSR 0xF8000000 +#define CFG_BCSR 0xE2400000 #define CFG_LBLAWBAR1_PRELIM CFG_BCSR /* Access window base at BCSR base */ #define CFG_LBLAWAR1_PRELIM 0x8000000E /* Access window size 32K */ #define CFG_BR1_PRELIM (CFG_BCSR|0x00000801) /* Port-size=8bit, MSEL=GPCM */ @@ -165,7 +166,7 @@ #define CONFIG_L1_INIT_RAM #define CFG_INIT_RAM_LOCK 1 -#define CFG_INIT_RAM_ADDR 0xE8000000 /* Initial RAM address */ +#define CFG_INIT_RAM_ADDR 0xFD000000 /* Initial RAM address */ #define CFG_INIT_RAM_END 0x1000 /* End of used area in RAM*/ #define CFG_GBL_DATA_SIZE 0x100 /* num bytes initial data */ @@ -322,18 +323,8 @@ #define CFG_TSEC2_OFFSET 0x25000 #define CFG_TSEC2 (CFG_IMMRBAR+CFG_TSEC2_OFFSET) -/* IO Configuration */ -#define CFG_IO_CONF (\ - IO_CONF_UART |\ - IO_CONF_TSEC1 |\ - IO_CONF_IRQ0 |\ - IO_CONF_IRQ1 |\ - IO_CONF_IRQ2 |\ - IO_CONF_IRQ3 |\ - IO_CONF_IRQ4 |\ - IO_CONF_IRQ5 |\ - IO_CONF_IRQ6 |\ - IO_CONF_IRQ7 ) +/* USB */ +#define CFG_USE_MPC834XSYS_USB_PHY 1 /* Use SYS board PHY */ /* * General PCI @@ -341,21 +332,27 @@ */ #define CFG_PCI1_MEM_BASE 0x80000000 #define CFG_PCI1_MEM_PHYS CFG_PCI1_MEM_BASE -#define CFG_PCI1_MEM_SIZE 0x20000000 /* 512M */ +#define CFG_PCI1_MEM_SIZE 0x10000000 /* 256M */ +#define CFG_PCI1_MMIO_BASE 0x90000000 +#define CFG_PCI1_MMIO_PHYS CFG_PCI1_MMIO_BASE +#define CFG_PCI1_MMIO_SIZE 0x10000000 /* 256M */ #define CFG_PCI1_IO_BASE 0x00000000 -#define CFG_PCI1_IO_PHYS 0xe2000000 -#define CFG_PCI1_IO_SIZE 0x1000000 /* 16M */ +#define CFG_PCI1_IO_PHYS 0xE2000000 +#define CFG_PCI1_IO_SIZE 0x00100000 /* 1M */ #define CFG_PCI2_MEM_BASE 0xA0000000 #define CFG_PCI2_MEM_PHYS CFG_PCI2_MEM_BASE -#define CFG_PCI2_MEM_SIZE 0x20000000 /* 512M */ +#define CFG_PCI2_MEM_SIZE 0x10000000 /* 256M */ +#define CFG_PCI2_MMIO_BASE 0xB0000000 +#define CFG_PCI2_MMIO_PHYS CFG_PCI2_MMIO_BASE +#define CFG_PCI2_MMIO_SIZE 0x10000000 /* 256M */ #define CFG_PCI2_IO_BASE 0x00000000 -#define CFG_PCI2_IO_PHYS 0xe3000000 -#define CFG_PCI2_IO_SIZE 0x1000000 /* 16M */ +#define CFG_PCI2_IO_PHYS 0xE2100000 +#define CFG_PCI2_IO_SIZE 0x00100000 /* 1M */ #if defined(CONFIG_PCI) -#define PCI_ALL_PCI1 +#define PCI_ONE_PCI1 #if defined(PCI_64BIT) #undef PCI_ALL_PCI1 #undef PCI_TWO_PCI1 @@ -512,35 +509,35 @@ #define CFG_HRCW_LOW (\ HRCWL_LCL_BUS_TO_SCB_CLK_1X1 |\ HRCWL_DDR_TO_SCB_CLK_1X1 |\ - HRCWL_CSB_TO_CLKIN_4X1 |\ + HRCWL_CSB_TO_CLKIN |\ HRCWL_VCO_1X2 |\ HRCWL_CORE_TO_CSB_2X1) #elif 0 /*396/132*/ #define CFG_HRCW_LOW (\ HRCWL_LCL_BUS_TO_SCB_CLK_1X1 |\ HRCWL_DDR_TO_SCB_CLK_1X1 |\ - HRCWL_CSB_TO_CLKIN_2X1 |\ + HRCWL_CSB_TO_CLKIN |\ HRCWL_VCO_1X4 |\ HRCWL_CORE_TO_CSB_3X1) #elif 0 /*264/132*/ #define CFG_HRCW_LOW (\ HRCWL_LCL_BUS_TO_SCB_CLK_1X1 |\ HRCWL_DDR_TO_SCB_CLK_1X1 |\ - HRCWL_CSB_TO_CLKIN_2X1 |\ + HRCWL_CSB_TO_CLKIN |\ HRCWL_VCO_1X4 |\ HRCWL_CORE_TO_CSB_2X1) #elif 0 /*132/132*/ #define CFG_HRCW_LOW (\ HRCWL_LCL_BUS_TO_SCB_CLK_1X1 |\ HRCWL_DDR_TO_SCB_CLK_1X1 |\ - HRCWL_CSB_TO_CLKIN_2X1 |\ + HRCWL_CSB_TO_CLKIN |\ HRCWL_VCO_1X4 |\ HRCWL_CORE_TO_CSB_1X1) #elif 0 /*264/264 */ #define CFG_HRCW_LOW (\ HRCWL_LCL_BUS_TO_SCB_CLK_1X1 |\ HRCWL_DDR_TO_SCB_CLK_1X1 |\ - HRCWL_CSB_TO_CLKIN_4X1 |\ + HRCWL_CSB_TO_CLKIN |\ HRCWL_VCO_1X4 |\ HRCWL_CORE_TO_CSB_1X1) #endif @@ -578,7 +575,7 @@ #define CFG_SICRL SICRL_LDP_A #define CFG_HID0_INIT 0x000000000 -#define CFG_HID0_FINAL CFG_HID0_INIT +#define CFG_HID0_FINAL HID0_ENABLE_MACHINE_CHECK /* #define CFG_HID0_FINAL (\ HID0_ENABLE_INSTRUCTION_CACHE |\ @@ -605,25 +602,28 @@ #define CFG_IBAT2U (0) #endif -/* IMMRBAR @ 0xE0000000 */ -#define CFG_IBAT3L (CFG_IMMRBAR | BATL_PP_10 | BATL_CACHEINHIBIT | BATL_GUARDEDSTORAGE) -#define CFG_IBAT3U (CFG_IMMRBAR | BATU_BL_1M | BATU_VS | BATU_VP) - -/* stack in DCACHE (no backing mem) @ 0xE8000000 */ -#define CFG_IBAT4L (CFG_INIT_RAM_ADDR | BATL_PP_10 | BATL_MEMCOHERENCE) -#define CFG_IBAT4U (CFG_INIT_RAM_ADDR | BATU_BL_128K | BATU_VS | BATU_VP) +#ifdef CONFIG_MPC83XX_PCI2 +#define CFG_IBAT3L (CFG_PCI2_MEM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE) +#define CFG_IBAT3U (CFG_PCI2_MEM_BASE | BATU_BL_256M | BATU_VS | BATU_VP) +#define CFG_IBAT4L (CFG_PCI2_MMIO_BASE | BATL_PP_10 | BATL_CACHEINHIBIT | BATL_GUARDEDSTORAGE) +#define CFG_IBAT4U (CFG_PCI2_MMIO_BASE | BATU_BL_256M | BATU_VS | BATU_VP) +#else +#define CFG_IBAT3L (0) +#define CFG_IBAT3U (0) +#define CFG_IBAT4L (0) +#define CFG_IBAT4U (0) +#endif -/* LBC SDRAM @ 0xF0000000 */ -#define CFG_IBAT5L (CFG_LBC_SDRAM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE) -#define CFG_IBAT5U (CFG_LBC_SDRAM_BASE | BATU_BL_64M | BATU_VS | BATU_VP) +/* IMMRBAR @ 0xE0000000, PCI IO @ 0xE2000000 & BCSR @ 0xE2400000 */ +#define CFG_IBAT5L (CFG_IMMRBAR | BATL_PP_10 | BATL_CACHEINHIBIT | BATL_GUARDEDSTORAGE) +#define CFG_IBAT5U (CFG_IMMRBAR | BATU_BL_256M | BATU_VS | BATU_VP) -/* BCSR @ 0xF8000000 */ -#define CFG_IBAT6L (CFG_BCSR | BATL_PP_10 | BATL_CACHEINHIBIT | BATL_GUARDEDSTORAGE) -#define CFG_IBAT6U (CFG_BCSR | BATU_BL_128K | BATU_VS | BATU_VP) +/* SDRAM @ 0xF0000000, stack in DCACHE 0xFDF00000 & FLASH @ 0xFE000000 */ +#define CFG_IBAT6L (0xF0000000 | BATL_PP_10 | BATL_MEMCOHERENCE) +#define CFG_IBAT6U (0xF0000000 | BATU_BL_256M | BATU_VS | BATU_VP) -/* FLASH @ 0xFE000000 */ -#define CFG_IBAT7L (CFG_FLASH_BASE | BATL_PP_10 | BATL_MEMCOHERENCE) -#define CFG_IBAT7U (CFG_FLASH_BASE | BATU_BL_8M | BATU_VS | BATU_VP) +#define CFG_IBAT7L (0) +#define CFG_IBAT7U (0) #define CFG_DBAT0L CFG_IBAT0L #define CFG_DBAT0U CFG_IBAT0U diff --git a/include/configs/delta.h b/include/configs/delta.h index e4c8cca..91284fd 100644 --- a/include/configs/delta.h +++ b/include/configs/delta.h @@ -66,6 +66,17 @@ #define CFG_I2C_INIT_BOARD 1 /* #define CONFIG_HW_WATCHDOG 1 /\* Required for hitting the DA9030 WD *\/ */ +#define DELTA_CHECK_KEYBD 1 /* check for keys pressed during boot */ +#define CONFIG_PREBOOT "\0" + +#ifdef DELTA_CHECK_KEYBD +# define KEYBD_DATALEN 4 /* we have four keys */ +# define KEYBD_KP_DKIN0 0x1 /* vol+ */ +# define KEYBD_KP_DKIN1 0x2 /* vol- */ +# define KEYBD_KP_DKIN2 0x3 /* multi */ +# define KEYBD_KP_DKIN5 0x4 /* SWKEY_GN */ +#endif /* DELTA_CHECK_KEYBD */ + /* * select serial console configuration */ diff --git a/include/configs/ixdp425.h b/include/configs/ixdp425.h index b0a80a3..9f9fdb2 100644 --- a/include/configs/ixdp425.h +++ b/include/configs/ixdp425.h @@ -33,6 +33,9 @@ #define CONFIG_IXP425 1 /* This is an IXP425 CPU */ #define CONFIG_IXDP425 1 /* on an IXDP425 Board */ +#define CONFIG_DISPLAY_CPUINFO 1 /* display cpu info (and speed) */ +#define CONFIG_DISPLAY_BOARDINFO 1 /* display board info */ + /*************************************************************** * U-boot generic defines start here. ***************************************************************/ @@ -135,6 +138,8 @@ #define CFG_DRAM_SIZE 0x01000000 #define CFG_FLASH_BASE PHYS_FLASH_1 +#define CFG_MONITOR_BASE CFG_FLASH_BASE +#define CFG_MONITOR_LEN (256 << 10) /* Reserve 256 kB for Monitor */ /* * Expansion bus settings @@ -155,16 +160,27 @@ /* * FLASH and environment organization */ +/* + * FLASH and environment organization + */ #define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */ -#define CFG_MAX_FLASH_SECT 128 /* max number of sectors on one chip */ +#define CFG_MAX_FLASH_SECT 128 /* max number of sectors on one chip */ + +#define CFG_FLASH_CFI /* The flash is CFI compatible */ +#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */ +#define CFG_ENV_IS_IN_FLASH 1 + +#define CFG_FLASH_BANKS_LIST { PHYS_FLASH_1 } + +#define CFG_FLASH_CFI_WIDTH FLASH_CFI_16BIT /* no byte writes on IXP4xx */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ -/* timeout values are in ticks */ -#define CFG_FLASH_ERASE_TOUT (25*CFG_HZ) /* Timeout for Flash Erase */ -#define CFG_FLASH_WRITE_TOUT (25*CFG_HZ) /* Timeout for Flash Write */ +#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */ -/* FIXME */ -#define CFG_ENV_IS_IN_FLASH 1 -#define CFG_ENV_ADDR (PHYS_FLASH_1 + 0x20000) /* Addr of Environment Sector */ -#define CFG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */ +#define CFG_ENV_SECT_SIZE 0x20000 /* size of one complete sector */ +#define CFG_ENV_ADDR (PHYS_FLASH_1 + 0x20000) +#define CFG_ENV_SIZE 0x2000 /* Total Size of Environment Sector */ #endif /* __CONFIG_H */ diff --git a/include/configs/ixdpg425.h b/include/configs/ixdpg425.h new file mode 100644 index 0000000..af4ecf6 --- /dev/null +++ b/include/configs/ixdpg425.h @@ -0,0 +1,240 @@ +/* + * (C) Copyright 2005-2006 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * (C) Copyright 2003 + * Martijn de Gouw, Prodrive B.V., martijn.de.gouw@prodrive.nl + * + * Configuation settings for the IXDPG425 board. + * + * 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 + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * High Level Configuration Options + * (easy to change) + */ +#define CONFIG_IXP425 1 /* This is an IXP425 CPU */ +#define CONFIG_IXDPG425 1 /* on an IXDPG425 Board */ + +#define CONFIG_DISPLAY_CPUINFO 1 /* display cpu info (and speed) */ +#define CONFIG_DISPLAY_BOARDINFO 1 /* display board info */ + +/* + * Ethernet + */ +#define CONFIG_IXP4XX_NPE 1 /* include IXP4xx NPE support */ +#define CONFIG_NET_MULTI 1 +#define CONFIG_PHY_ADDR 5 /* NPE0 PHY address */ +#define CONFIG_HAS_ETH1 +#define CONFIG_PHY1_ADDR 4 /* NPE1 PHY address */ +#define CONFIG_MII 1 /* MII PHY management */ +#define CFG_RX_ETH_BUFFER 16 /* Number of ethernet rx buffers & descriptors */ + +/* + * Misc configuration options + */ +#undef CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */ +#define CONFIG_USE_IRQ 1 /* we need IRQ stuff for timer */ + +#define CONFIG_BOOTCOUNT_LIMIT /* support for bootcount limit */ +#define CFG_BOOTCOUNT_ADDR 0x60003000 /* inside qmrg sram */ + +#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ +#define CONFIG_SETUP_MEMORY_TAGS 1 +#define CONFIG_INITRD_TAG 1 + +/* + * Size of malloc() pool + */ +#define CFG_MALLOC_LEN (256 << 10) +#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */ + +/* allow to overwrite serial and ethaddr */ +#define CONFIG_ENV_OVERWRITE + +#define CONFIG_BAUDRATE 115200 +#define CFG_IXP425_CONSOLE IXP425_UART1 /* we use UART1 for console */ + +#define CONFIG_COMMANDS (CONFIG_CMD_DFL | \ + CFG_CMD_DHCP | \ + CFG_CMD_ELF | \ + CFG_CMD_NET | \ + CFG_CMD_MII | \ + CFG_CMD_PING) + +/* This must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +/* These are u-boot generic parameters */ +#include + +#define CONFIG_ZERO_BOOTDELAY_CHECK /* check for keypress on bootdelay==0 */ +#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */ + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_MEMTEST_START 0x00400000 /* memtest works on */ +#define CFG_MEMTEST_END 0x00800000 /* 4 ... 8 MB in DRAM */ +#define CFG_LOAD_ADDR 0x00010000 /* default load address */ + +#undef CFG_CLKS_IN_HZ /* everything, incl board info, in Hz */ +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + + /* valid baudrates */ +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } + +/* + * Stack sizes + * + * The stack sizes are set up in start.S using the settings below + */ +#define CONFIG_STACKSIZE (128*1024) /* regular stack */ +#ifdef CONFIG_USE_IRQ +#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */ +#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */ +#endif + +/*************************************************************** + * Platform/Board specific defines start here. + ***************************************************************/ + +/*----------------------------------------------------------------------- + * Default configuration (environment varibles...) + *----------------------------------------------------------------------*/ +#define CONFIG_PREBOOT "echo;" \ + "echo Type \"run flash_nfs\" to mount root filesystem over NFS;" \ + "echo" + +#undef CONFIG_BOOTARGS + +#define CONFIG_EXTRA_ENV_SETTINGS \ + "netdev=eth0\0" \ + "hostname=ixdpg425\0" \ + "nfsargs=setenv bootargs root=/dev/nfs rw " \ + "nfsroot=${serverip}:${rootpath}\0" \ + "ramargs=setenv bootargs root=/dev/ram rw\0" \ + "addip=setenv bootargs ${bootargs} " \ + "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}" \ + ":${hostname}:${netdev}:off panic=1\0" \ + "addtty=setenv bootargs ${bootargs} console=ttyS0,${baudrate}\0"\ + "flash_nfs=run nfsargs addip addtty;" \ + "bootm ${kernel_addr}\0" \ + "flash_self=run ramargs addip addtty;" \ + "bootm ${kernel_addr} ${ramdisk_addr}\0" \ + "net_nfs=tftp 200000 ${bootfile};run nfsargs addip addtty;" \ + "bootm\0" \ + "rootpath=/opt/eldk/arm\0" \ + "bootfile=/tftpboot/ixdpg425/uImage\0" \ + "kernel_addr=50080000\0" \ + "ramdisk_addr=50200000\0" \ + "load=tftp 100000 /tftpboot/ixdpg425/u-boot.bin\0" \ + "update=protect off 50000000 5003ffff;era 50000000 5003ffff;" \ + "cp.b 100000 50000000 40000;" \ + "setenv filesize;saveenv\0" \ + "upd=run load;run update\0" \ + "" +#define CONFIG_BOOTCOMMAND "run net_nfs" + +/* + * Physical Memory Map + */ +#define CONFIG_NR_DRAM_BANKS 1 /* we have 2 banks of DRAM */ +#define PHYS_SDRAM_1 0x00000000 /* SDRAM Bank #1 */ +#define PHYS_SDRAM_1_SIZE 0x02000000 /* 32 MB */ + +#define PHYS_FLASH_1 0x50000000 /* Flash Bank #1 */ +#define PHYS_FLASH_SIZE 0x01000000 /* 16 MB */ +#define PHYS_FLASH_BANK_SIZE 0x01000000 /* 16 MB Banks */ +#define PHYS_FLASH_SECT_SIZE 0x00020000 /* 128 KB sectors (x1) */ + +#define CFG_DRAM_BASE 0x00000000 +#define CFG_DRAM_SIZE 0x01000000 + +#define CFG_FLASH_BASE PHYS_FLASH_1 +#define CFG_MONITOR_BASE CFG_FLASH_BASE +#define CFG_MONITOR_LEN (256 << 10) /* Reserve 256 kB for Monitor */ + +/* + * Expansion bus settings + */ +#define CFG_EXP_CS0 0xbcd23c42 + +/* + * SDRAM settings + */ +#define CFG_SDR_CONFIG 0x18 +#define CFG_SDR_MODE_CONFIG 0x1 +#define CFG_SDRAM_REFRESH_CNT 0x81a + +/* + * FLASH and environment organization + */ +#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 128 /* max number of sectors on one chip */ + +#define CFG_FLASH_CFI /* The flash is CFI compatible */ +#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */ +#define CFG_ENV_IS_IN_FLASH 1 + +#define CFG_FLASH_USE_BUFFER_WRITE 1 /* use buffered writes (20x faster) */ +#define CFG_FLASH_PROTECTION 1 /* hardware flash protection */ + +#define CFG_FLASH_BANKS_LIST { PHYS_FLASH_1 } + +#define CFG_FLASH_CFI_WIDTH FLASH_CFI_16BIT /* no byte writes on IXP4xx */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + +#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */ + +#define CFG_ENV_SECT_SIZE 0x20000 /* size of one complete sector */ +#define CFG_ENV_ADDR (PHYS_FLASH_1 + 0x40000) +#define CFG_ENV_SIZE 0x2000 /* Total Size of Environment Sector */ + +/* Address and size of Redundant Environment Sector */ +#define CFG_ENV_ADDR_REDUND (CFG_ENV_ADDR + CFG_ENV_SECT_SIZE) +#define CFG_ENV_SIZE_REDUND (CFG_ENV_SIZE) + +/* + * GPIO settings + */ +#define CFG_GPIO_PCI_INTA_N 6 +#define CFG_GPIO_PCI_INTB_N 7 +#define CFG_GPIO_SWITCH_RESET_N 8 +#define CFG_GPIO_SLIC_RESET_N 13 +#define CFG_GPIO_PCI_CLK 14 +#define CFG_GPIO_EXTBUS_CLK 15 + +/* + * Cache Configuration + */ +#define CFG_CACHELINE_SIZE 32 + +#endif /* __CONFIG_H */ diff --git a/include/configs/mcc200.h b/include/configs/mcc200.h index 2b1c0d0..d8d63a1 100644 --- a/include/configs/mcc200.h +++ b/include/configs/mcc200.h @@ -172,6 +172,10 @@ #define CONFIG_ENV_OVERWRITE 1 /* allow modification of vendor params */ +#if TEXT_BASE == CFG_FLASH_BASE +#define CFG_LOWBOOT 1 +#endif + /* * Memory map */ diff --git a/include/configs/omap5912osk.h b/include/configs/omap5912osk.h index 605563a..5db4f52 100644 --- a/include/configs/omap5912osk.h +++ b/include/configs/omap5912osk.h @@ -35,6 +35,9 @@ #define CONFIG_OMAP1610 1 /* 5912 is same as 1610 */ #define CONFIG_OSK_OMAP5912 1 /* a OSK Board */ +#define CONFIG_DISPLAY_CPUINFO 1 /* display cpu info (and speed) */ +#define CONFIG_DISPLAY_BOARDINFO 1 /* display board info */ + /* input clock of PLL */ /* the OMAP5912 OSK has 12MHz input clock */ #define CONFIG_SYS_CLK_FREQ 12000000 @@ -45,11 +48,13 @@ #define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ #define CONFIG_SETUP_MEMORY_TAGS 1 +#define CONFIG_INITRD_TAG 1 /* Required for ramdisk support */ /* * Size of malloc() pool */ #define CFG_MALLOC_LEN (CFG_ENV_SIZE + 128*1024) +#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */ /* * Hardware drivers @@ -142,27 +147,44 @@ * Physical Memory Map */ #define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */ -#define PHYS_SDRAM_1 0x10000000 /* SDRAM Bank #1 */ +#define PHYS_SDRAM_1 0x10000000 /* SDRAM Bank #1 */ #define PHYS_SDRAM_1_SIZE 0x02000000 /* 32 MB */ -#define PHYS_FLASH_1 0x00000000 /* Flash Bank #1 */ +#define PHYS_FLASH_1 0x00000000 /* Flash Bank #1 */ +#define PHYS_FLASH_2 0x01000000 /* Flash Bank #2 */ + +#define CFG_FLASH_BASE PHYS_FLASH_1 -#define CFG_FLASH_BASE PHYS_FLASH_1 +#define CFG_MONITOR_BASE CFG_FLASH_BASE /* Monitor at beginning of flash */ /*----------------------------------------------------------------------- - * FLASH and environment organization + * FLASH driver setup */ -#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */ +#define CFG_FLASH_CFI 1 /* Flash memory is CFI compliant */ +#define CFG_FLASH_CFI_DRIVER 1 /* Use drivers/cfi_flash.c */ + +#define CFG_FLASH_BANKS_LIST { PHYS_FLASH_1, PHYS_FLASH_2 } + +#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */ #define PHYS_FLASH_SIZE 0x02000000 /* 32MB */ #define CFG_MAX_FLASH_SECT (259) /* max number of sectors on one chip */ -/* addr of environment */ -#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x020000) + +#define CFG_FLASH_USE_BUFFER_WRITE 1 /* Use buffered writes (~10x faster) */ +#define CFG_FLASH_PROTECTION 1 /* Use hardware sector protection */ + +#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */ /* timeout values are in ticks */ #define CFG_FLASH_ERASE_TOUT (20*CFG_HZ) /* Timeout for Flash Erase */ #define CFG_FLASH_WRITE_TOUT (20*CFG_HZ) /* Timeout for Flash Write */ +/*----------------------------------------------------------------------- + * FLASH and environment organization + */ #define CFG_ENV_IS_IN_FLASH 1 +/* addr of environment */ +#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x020000) + #define CFG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */ #define CFG_ENV_OFFSET 0x20000 /* environment starts here */ diff --git a/include/configs/pcs440ep.h b/include/configs/pcs440ep.h new file mode 100644 index 0000000..64bbca3 --- /dev/null +++ b/include/configs/pcs440ep.h @@ -0,0 +1,412 @@ +/* + * (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 + */ + +/************************************************************************ + * pcs440ep.h - configuration for PCS440EP board + ***********************************************************************/ +#ifndef __CONFIG_H +#define __CONFIG_H + +/*----------------------------------------------------------------------- + * High Level Configuration Options + *----------------------------------------------------------------------*/ +#define CONFIG_PCS440EP 1 /* Board is PCS440EP */ +#define CONFIG_440EP 1 /* Specific PPC440EP support */ +#define CONFIG_4xx 1 /* ... PPC4xx family */ +#define CONFIG_SYS_CLK_FREQ 33333333 /* external freq to pll */ + +#define CONFIG_BOARD_EARLY_INIT_F 1 /* Call board_early_init_f */ +#define CONFIG_MISC_INIT_R 1 /* call misc_init_r() */ + +/*----------------------------------------------------------------------- + * Base addresses -- Note these are effective addresses where the + * actual resources get mapped (not physical addresses) + *----------------------------------------------------------------------*/ +#define CFG_MONITOR_LEN (384 * 1024) /* Reserve 384 kB for Monitor */ +#define CFG_MALLOC_LEN (256 * 1024) /* Reserve 256 kB for malloc() */ +#define CFG_MONITOR_BASE (-CFG_MONITOR_LEN) +#define CFG_SDRAM_BASE 0x00000000 /* _must_ be 0 */ +#define CFG_FLASH_BASE 0xfff00000 /* start of FLASH */ +#define CFG_PCI_MEMBASE 0xa0000000 /* mapped pci memory*/ +#define CFG_PCI_MEMBASE1 CFG_PCI_MEMBASE + 0x10000000 +#define CFG_PCI_MEMBASE2 CFG_PCI_MEMBASE1 + 0x10000000 +#define CFG_PCI_MEMBASE3 CFG_PCI_MEMBASE2 + 0x10000000 + +/*Don't change either of these*/ +#define CFG_PERIPHERAL_BASE 0xef600000 /* internal peripherals*/ +#define CFG_PCI_BASE 0xe0000000 /* internal PCI regs*/ +/*Don't change either of these*/ + +#define CFG_USB_DEVICE 0x50000000 +#define CFG_BOOT_BASE_ADDR 0xf0000000 + +/*----------------------------------------------------------------------- + * Initial RAM & stack pointer (placed in SDRAM) + *----------------------------------------------------------------------*/ +#define CFG_INIT_RAM_ADDR 0x70000000 /* DCache */ +#define CFG_INIT_RAM_END (8 << 10) +#define CFG_GBL_DATA_SIZE 256 /* num bytes initial data*/ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET + +/*----------------------------------------------------------------------- + * Serial Port + *----------------------------------------------------------------------*/ +#undef CFG_EXT_SERIAL_CLOCK /* no external clk used */ +#define CONFIG_BAUDRATE 115200 +#define CONFIG_SERIAL_MULTI 1 +/*define this if you want console on UART1*/ +#undef CONFIG_UART1_CONSOLE + +#define CFG_BAUDRATE_TABLE \ + {300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200} + +/*----------------------------------------------------------------------- + * Environment + *----------------------------------------------------------------------*/ +#define CFG_ENV_IS_IN_FLASH 1 /* use FLASH for environment vars */ + +/*----------------------------------------------------------------------- + * FLASH related + *----------------------------------------------------------------------*/ +#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 256 /* max number of sectors on one chip */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + +#define CFG_FLASH_WORD_SIZE unsigned char /* flash word size (width) */ +#define CFG_FLASH_ADDR0 0x5555 /* 1st address for flash config cycles */ +#define CFG_FLASH_ADDR1 0x2AAA /* 2nd address for flash config cycles */ + +#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */ + +#ifdef CFG_ENV_IS_IN_FLASH +#define CFG_ENV_SECT_SIZE 0x10000 /* size of one complete sector */ +#define CFG_ENV_ADDR (CFG_MONITOR_BASE-CFG_ENV_SECT_SIZE) +#define CFG_ENV_SIZE 0x2000 /* Total Size of Environment Sector */ + +/* Address and size of Redundant Environment Sector */ +#define CFG_ENV_ADDR_REDUND (CFG_ENV_ADDR-CFG_ENV_SECT_SIZE) +#define CFG_ENV_SIZE_REDUND (CFG_ENV_SIZE) +#endif /* CFG_ENV_IS_IN_FLASH */ + +/*----------------------------------------------------------------------- + * DDR SDRAM + *----------------------------------------------------------------------*/ +#define CONFIG_SPD_EEPROM /* Use SPD EEPROM for setup */ +#undef CONFIG_DDR_ECC /* don't use ECC */ +#define SPD_EEPROM_ADDRESS {0x50, 0x51} + +/*----------------------------------------------------------------------- + * I2C + *----------------------------------------------------------------------*/ +#define CONFIG_HARD_I2C 1 /* I2C with hardware support */ +#undef CONFIG_SOFT_I2C /* I2C bit-banged */ +#define CFG_I2C_SPEED 400000 /* I2C speed and slave address */ +#define CFG_I2C_SLAVE 0x7F + +#define CFG_I2C_MULTI_EEPROMS +#define CFG_I2C_EEPROM_ADDR (0xa8>>1) +#define CFG_I2C_EEPROM_ADDR_LEN 1 +#define CFG_EEPROM_PAGE_WRITE_ENABLE +#define CFG_EEPROM_PAGE_WRITE_BITS 3 +#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10 + +#define CONFIG_PREBOOT "echo;" \ + "echo Type \"run flash_nfs\" to mount root filesystem over NFS;" \ + "echo" + +#undef CONFIG_BOOTARGS + +#define CONFIG_EXTRA_ENV_SETTINGS \ + "netdev=eth0\0" \ + "hostname=pcs440ep\0" \ + "nfsargs=setenv bootargs root=/dev/nfs rw " \ + "nfsroot=${serverip}:${rootpath}\0" \ + "ramargs=setenv bootargs root=/dev/ram rw\0" \ + "addip=setenv bootargs ${bootargs} " \ + "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}" \ + ":${hostname}:${netdev}:off panic=1\0" \ + "addtty=setenv bootargs ${bootargs} console=ttyS0,${baudrate}\0"\ + "flash_nfs=run nfsargs addip addtty;" \ + "bootm ${kernel_addr}\0" \ + "flash_self=run ramargs addip addtty;" \ + "bootm ${kernel_addr} ${ramdisk_addr}\0" \ + "net_nfs=tftp 200000 ${bootfile};run nfsargs addip addtty;" \ + "bootm\0" \ + "rootpath=/opt/eldk/ppc_4xx\0" \ + "bootfile=/tftpboot/pcs440ep/uImage\0" \ + "kernel_addr=FFF00000\0" \ + "ramdisk_addr=FFF00000\0" \ + "load=tftp 100000 /tftpboot/pcs440ep/u-boot.bin\0" \ + "update=protect off FFFA0000 FFFFFFFF;era FFFA0000 FFFFFFFF;" \ + "cp.b 100000 FFFA0000 60000\0" \ + "upd=run load;run update\0" \ + "" +#define CONFIG_BOOTCOMMAND "run flash_self" + +#if 0 +#define CONFIG_BOOTDELAY -1 /* autoboot disabled */ +#else +#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */ +#endif + +#define CONFIG_BAUDRATE 115200 + +#define CONFIG_LOADS_ECHO 1 /* echo on for serial download */ +#define CFG_LOADS_BAUD_CHANGE 1 /* allow baudrate change */ + +#define CONFIG_MII 1 /* MII PHY management */ +#define CONFIG_NET_MULTI 1 /* required for netconsole */ +#define CONFIG_HAS_ETH1 1 /* add support for "eth1addr" */ +#define CONFIG_PHY_ADDR 1 /* PHY address, See schematics */ +#define CONFIG_PHY1_ADDR 2 + +#define CFG_RX_ETH_BUFFER 32 /* Number of ethernet rx buffers & descriptors */ + +#define CONFIG_NETCONSOLE /* include NetConsole support */ + +/* Partitions */ +#define CONFIG_MAC_PARTITION +#define CONFIG_DOS_PARTITION +#define CONFIG_ISO_PARTITION + +#ifdef CONFIG_440EP +/* USB */ +#define CONFIG_USB_OHCI +#define CONFIG_USB_STORAGE + +/*Comment this out to enable USB 1.1 device*/ +#define USB_2_0_DEVICE +#endif /*CONFIG_440EP*/ + +#ifdef DEBUG +#define CONFIG_PANIC_HANG +#else +#define CONFIG_HW_WATCHDOG /* watchdog */ +#endif + +#define CONFIG_COMMANDS (CONFIG_CMD_DFL | \ + CFG_CMD_ASKENV | \ + CFG_CMD_DHCP | \ + CFG_CMD_DIAG | \ + CFG_CMD_ELF | \ + CFG_CMD_I2C | \ + CFG_CMD_IRQ | \ + CFG_CMD_MII | \ + CFG_CMD_NET | \ + CFG_CMD_NFS | \ + CFG_CMD_PCI | \ + CFG_CMD_PING | \ + CFG_CMD_REGINFO | \ + CFG_CMD_SDRAM | \ + CFG_CMD_EXT2 | \ + CFG_CMD_FAT | \ + CFG_CMD_USB ) + + +#define CONFIG_SUPPORT_VFAT + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_MEMTEST_START 0x0400000 /* memtest works on */ +#define CFG_MEMTEST_END 0x0C00000 /* 4 ... 12 MB in DRAM */ + +#define CFG_LOAD_ADDR 0x100000 /* default load address */ +#define CFG_EXTBDINFO 1 /* To use extended board_into (bd_t) */ +#define CONFIG_LYNXKDI 1 /* support kdi files */ + +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +/*----------------------------------------------------------------------- + * PCI stuff + *----------------------------------------------------------------------- + */ +/* General PCI */ +#define CONFIG_PCI /* include pci support */ +#undef CONFIG_PCI_PNP /* do (not) pci plug-and-play */ +#define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ +#define CFG_PCI_TARGBASE 0x80000000 /* PCIaddr mapped to CFG_PCI_MEMBASE*/ + +/* Board-specific PCI */ +#define CFG_PCI_PRE_INIT /* enable board pci_pre_init() */ +#define CFG_PCI_TARGET_INIT +#define CFG_PCI_MASTER_INIT + +#define CFG_PCI_SUBSYS_VENDORID 0x10e8 /* AMCC */ +#define CFG_PCI_SUBSYS_ID 0xcafe /* Whatever */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ + +/*----------------------------------------------------------------------- + * External Bus Controller (EBC) Setup + *----------------------------------------------------------------------*/ +#define FLASH_BASE0_PRELIM 0xFFF00000 /* FLASH bank #0 */ +#define FLASH_BASE1_PRELIM 0xFFF80000 /* FLASH bank #1 */ + +#define CFG_FLASH FLASH_BASE0_PRELIM +#define CFG_SRAM 0xF1000000 +#define CFG_FPGA 0xF2000000 +#define CFG_CF1 0xF0000000 +#define CFG_CF2 0xF0100000 + +/* Memory Bank 0 (Flash Bank 0, NOR-FLASH) initialization */ +#define CFG_EBC_PB0AP 0x02010000 /* TWT=4,OEN=1 */ +#define CFG_EBC_PB0CR (CFG_FLASH | 0x18000) /* BS=1MB,BU=R/W,BW=8bit */ + +/* Memory Bank 1 (SRAM) initialization */ +#define CFG_EBC_PB1AP 0x01810040 /* TWT=3,OEN=1,BEM=1 */ +#define CFG_EBC_PB1CR (CFG_SRAM | 0x5A000) /* BS=4MB,BU=R/W,BW=16bit */ + +/* Memory Bank 2 (FPGA) initialization */ +#define CFG_EBC_PB2AP 0x01010440 /* TWT=2,OEN=1,TH=2,BEM=1 */ +#define CFG_EBC_PB2CR (CFG_FPGA | 0x5A000) /* BS=4MB,BU=R/W,BW=16bit */ + +/* Memory Bank 3 (CompactFlash) initialization */ +#define CFG_EBC_PB3AP 0x080BD400 +#define CFG_EBC_PB3CR (CFG_CF1 | 0x1A000) /* BS=1MB,BU=R/W,BW=16bit */ + +/* Memory Bank 4 (CompactFlash) initialization */ +#define CFG_EBC_PB4AP 0x080BD400 +#define CFG_EBC_PB4CR (CFG_CF2 | 0x1A000) /* BS=1MB,BU=R/W,BW=16bit */ + +/*----------------------------------------------------------------------- + * PPC440 GPIO Configuration + */ +#define CFG_440_GPIO_TABLE { /* GPIO Alternate1 Alternate2 Alternate3 */ \ +{ \ +/* GPIO Core 0 */ \ +{ GPIO0_BASE, GPIO_OUT, GPIO_SEL }, /* GPIO0 EBC_ADDR(7) DMA_REQ(2) */ \ +{ GPIO0_BASE, GPIO_OUT, GPIO_SEL }, /* GPIO1 EBC_ADDR(6) DMA_ACK(2) */ \ +{ GPIO0_BASE, GPIO_OUT, GPIO_SEL }, /* GPIO2 EBC_ADDR(5) DMA_EOT/TC(2) */ \ +{ GPIO0_BASE, GPIO_OUT, GPIO_SEL }, /* GPIO3 EBC_ADDR(4) DMA_REQ(3) */ \ +{ GPIO0_BASE, GPIO_OUT, GPIO_SEL }, /* GPIO4 EBC_ADDR(3) DMA_ACK(3) */ \ +{ GPIO0_BASE, GPIO_OUT, GPIO_SEL }, /* GPIO5 EBC_ADDR(2) DMA_EOT/TC(3) */ \ +{ GPIO0_BASE, GPIO_OUT, GPIO_ALT1 }, /* GPIO6 EBC_CS_N(1) */ \ +{ GPIO0_BASE, GPIO_OUT, GPIO_ALT1 }, /* GPIO7 EBC_CS_N(2) */ \ +{ GPIO0_BASE, GPIO_OUT, GPIO_ALT1 }, /* GPIO8 EBC_CS_N(3) */ \ +{ GPIO0_BASE, GPIO_OUT, GPIO_ALT1 }, /* GPIO9 EBC_CS_N(4) */ \ +{ GPIO0_BASE, GPIO_OUT, GPIO_SEL }, /* GPIO10 EBC_CS_N(5) */ \ +{ GPIO0_BASE, GPIO_OUT, GPIO_SEL }, /* GPIO11 EBC_BUS_ERR */ \ +{ GPIO0_BASE, GPIO_IN, GPIO_ALT1 }, /* GPIO12 ZII_p0Rxd(0) */ \ +{ GPIO0_BASE, GPIO_IN, GPIO_ALT1 }, /* GPIO13 ZII_p0Rxd(1) */ \ +{ GPIO0_BASE, GPIO_IN, GPIO_ALT1 }, /* GPIO14 ZII_p0Rxd(2) */ \ +{ GPIO0_BASE, GPIO_IN, GPIO_ALT1 }, /* GPIO15 ZII_p0Rxd(3) */ \ +{ GPIO0_BASE, GPIO_OUT, GPIO_ALT1 }, /* GPIO16 ZII_p0Txd(0) */ \ +{ GPIO0_BASE, GPIO_OUT, GPIO_ALT1 }, /* GPIO17 ZII_p0Txd(1) */ \ +{ GPIO0_BASE, GPIO_OUT, GPIO_ALT1 }, /* GPIO18 ZII_p0Txd(2) */ \ +{ GPIO0_BASE, GPIO_OUT, GPIO_ALT1 }, /* GPIO19 ZII_p0Txd(3) */ \ +{ GPIO0_BASE, GPIO_IN, GPIO_ALT1 }, /* GPIO20 ZII_p0Rx_er */ \ +{ GPIO0_BASE, GPIO_IN, GPIO_ALT1 }, /* GPIO21 ZII_p0Rx_dv */ \ +{ GPIO0_BASE, GPIO_IN, GPIO_ALT1 }, /* GPIO22 ZII_p0RxCrs */ \ +{ GPIO0_BASE, GPIO_OUT, GPIO_ALT1 }, /* GPIO23 ZII_p0Tx_er */ \ +{ GPIO0_BASE, GPIO_OUT, GPIO_ALT1 }, /* GPIO24 ZII_p0Tx_en */ \ +{ GPIO0_BASE, GPIO_IN, GPIO_ALT1 }, /* GPIO25 ZII_p0Col */ \ +{ GPIO0_BASE, GPIO_IN, GPIO_SEL }, /* GPIO26 USB2D_RXVALID */ \ +{ GPIO0_BASE, GPIO_IN, GPIO_SEL }, /* GPIO27 EXT_EBC_REQ USB2D_RXERROR */ \ +{ GPIO0_BASE, GPIO_IN, GPIO_SEL }, /* GPIO28 USB2D_TXVALID */ \ +{ GPIO0_BASE, GPIO_IN, GPIO_SEL }, /* GPIO29 EBC_EXT_HDLA USB2D_PAD_SUSPNDM */ \ +{ GPIO0_BASE, GPIO_IN, GPIO_SEL }, /* GPIO30 EBC_EXT_ACK USB2D_XCVRSELECT*/ \ +{ GPIO0_BASE, GPIO_IN, GPIO_SEL }, /* GPIO31 EBC_EXR_BUSREQ USB2D_TERMSELECT*/ \ +}, \ +{ \ +/* GPIO Core 1 */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_SEL }, /* GPIO32 USB2D_OPMODE0 */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_SEL }, /* GPIO33 USB2D_OPMODE1 */ \ +{ GPIO1_BASE, GPIO_OUT, GPIO_ALT3 }, /* GPIO34 UART0_DCD_N UART1_DSR_CTS_N UART2_SOUT*/ \ +{ GPIO1_BASE, GPIO_IN, GPIO_ALT3 }, /* GPIO35 UART0_8PIN_DSR_N UART1_RTS_DTR_N UART2_SIN*/ \ +{ GPIO1_BASE, GPIO_IN, GPIO_ALT1 }, /* GPIO36 UART0_8PIN_CTS_N UART3_SIN*/ \ +{ GPIO1_BASE, GPIO_OUT, GPIO_ALT1 }, /* GPIO37 UART0_RTS_N */ \ +{ GPIO1_BASE, GPIO_OUT, GPIO_ALT2 }, /* GPIO38 UART0_DTR_N UART1_SOUT */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_ALT2 }, /* GPIO39 UART0_RI_N UART1_SIN */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_ALT1 }, /* GPIO40 UIC_IRQ(0) */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_ALT1 }, /* GPIO41 UIC_IRQ(1) */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_ALT1 }, /* GPIO42 UIC_IRQ(2) */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_ALT1 }, /* GPIO43 UIC_IRQ(3) */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_ALT1 }, /* GPIO44 UIC_IRQ(4) DMA_ACK(1) */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_SEL }, /* GPIO45 UIC_IRQ(6) DMA_EOT/TC(1) */ \ +{ GPIO1_BASE, GPIO_BI, GPIO_SEL }, /* GPIO46 UIC_IRQ(7) DMA_REQ(0) */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_SEL }, /* GPIO47 UIC_IRQ(8) DMA_ACK(0) */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_SEL }, /* GPIO48 UIC_IRQ(9) DMA_EOT/TC(0) */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_SEL }, /* GPIO49 Unselect via TraceSelect Bit */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_SEL }, /* GPIO50 Unselect via TraceSelect Bit */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_SEL }, /* GPIO51 Unselect via TraceSelect Bit */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_SEL }, /* GPIO52 Unselect via TraceSelect Bit */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_SEL }, /* GPIO53 Unselect via TraceSelect Bit */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_SEL }, /* GPIO54 Unselect via TraceSelect Bit */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_SEL }, /* GPIO55 Unselect via TraceSelect Bit */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_SEL }, /* GPIO56 Unselect via TraceSelect Bit */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_SEL }, /* GPIO57 Unselect via TraceSelect Bit */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_SEL }, /* GPIO58 Unselect via TraceSelect Bit */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_SEL }, /* GPIO59 Unselect via TraceSelect Bit */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_SEL }, /* GPIO60 Unselect via TraceSelect Bit */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_SEL }, /* GPIO61 Unselect via TraceSelect Bit */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_SEL }, /* GPIO62 Unselect via TraceSelect Bit */ \ +{ GPIO1_BASE, GPIO_IN, GPIO_SEL }, /* GPIO63 Unselect via TraceSelect Bit */ \ +} \ +} + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_DCACHE_SIZE (32<<10) /* For AMCC 440 CPUs */ +#define CFG_CACHELINE_SIZE 32 /* ... */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */ +#endif + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CONFIG_KGDB_BAUDRATE 230400 /* speed to run kgdb serial port */ +#define CONFIG_KGDB_SER_INDEX 2 /* which serial port to use */ +#endif + +#endif /* __CONFIG_H */ diff --git a/include/configs/pdnb3.h b/include/configs/pdnb3.h new file mode 100644 index 0000000..ba6b113 --- /dev/null +++ b/include/configs/pdnb3.h @@ -0,0 +1,307 @@ +/* + * (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * Configuation settings for the PDNB3 board. + * + * 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 + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * High Level Configuration Options + * (easy to change) + */ +#define CONFIG_IXP425 1 /* This is an IXP425 CPU */ +#define CONFIG_PDNB3 1 /* on an PDNB3 board */ + +#define CONFIG_DISPLAY_CPUINFO 1 /* display cpu info (and speed) */ +#define CONFIG_DISPLAY_BOARDINFO 1 /* display board info */ + +/* + * Ethernet + */ +#define CONFIG_IXP4XX_NPE 1 /* include IXP4xx NPE support */ +#define CONFIG_NET_MULTI 1 +#define CONFIG_PHY_ADDR 16 /* NPE0 PHY address */ +#define CONFIG_HAS_ETH1 +#define CONFIG_PHY1_ADDR 18 /* NPE1 PHY address */ +#define CONFIG_MII 1 /* MII PHY management */ +#define CFG_RX_ETH_BUFFER 16 /* Number of ethernet rx buffers & descriptors */ + +/* + * Misc configuration options + */ +#define CONFIG_USE_IRQ 1 /* we need IRQ stuff for timer */ + +#define CONFIG_BOOTCOUNT_LIMIT /* support for bootcount limit */ +#define CFG_BOOTCOUNT_ADDR 0x60003000 /* inside qmrg sram */ + +#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ +#define CONFIG_SETUP_MEMORY_TAGS 1 +#define CONFIG_INITRD_TAG 1 + +/* + * Size of malloc() pool + */ +#define CFG_MALLOC_LEN (1 << 20) +#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */ + +/* allow to overwrite serial and ethaddr */ +#define CONFIG_ENV_OVERWRITE + +#define CONFIG_BAUDRATE 115200 +#define CFG_IXP425_CONSOLE IXP425_UART1 /* we use UART1 for console */ + +#define CONFIG_COMMANDS (CONFIG_CMD_DFL | \ + CFG_CMD_DHCP | \ + CFG_CMD_DATE | \ + CFG_CMD_NET | \ + CFG_CMD_MII | \ + CFG_CMD_NAND | \ + CFG_CMD_I2C | \ + CFG_CMD_ELF | \ + CFG_CMD_PING) + +/* This must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +/* These are u-boot generic parameters */ +#include + +#define CONFIG_ZERO_BOOTDELAY_CHECK /* check for keypress on bootdelay==0 */ +#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */ + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_MEMTEST_START 0x00400000 /* memtest works on */ +#define CFG_MEMTEST_END 0x00800000 /* 4 ... 8 MB in DRAM */ +#define CFG_LOAD_ADDR 0x00010000 /* default load address */ + +#undef CFG_CLKS_IN_HZ /* everything, incl board info, in Hz */ +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + /* valid baudrates */ +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } + +/* + * Stack sizes + * + * The stack sizes are set up in start.S using the settings below + */ +#define CONFIG_STACKSIZE (128*1024) /* regular stack */ +#ifdef CONFIG_USE_IRQ +#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */ +#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */ +#endif + +/*************************************************************** + * Platform/Board specific defines start here. + ***************************************************************/ + +/*----------------------------------------------------------------------- + * Default configuration (environment varibles...) + *----------------------------------------------------------------------*/ +#define CONFIG_PREBOOT "echo;" \ + "echo Type \"run flash_nfs\" to mount root filesystem over NFS;" \ + "echo" + +#undef CONFIG_BOOTARGS + +#define CONFIG_EXTRA_ENV_SETTINGS \ + "netdev=eth0\0" \ + "hostname=pdnb3\0" \ + "nfsargs=setenv bootargs root=/dev/nfs rw " \ + "nfsroot=${serverip}:${rootpath}\0" \ + "ramargs=setenv bootargs root=/dev/ram rw\0" \ + "addip=setenv bootargs ${bootargs} ethaddr=${ethaddr} " \ + "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}" \ + ":${hostname}:${netdev}:off panic=1\0" \ + "addtty=setenv bootargs ${bootargs} console=ttyS0,${baudrate} " \ + "mtdparts=${mtdparts}\0" \ + "flash_nfs=run nfsargs addip addtty;" \ + "bootm ${kernel_addr}\0" \ + "flash_self=run ramargs addip addtty;" \ + "bootm ${kernel_addr} ${ramdisk_addr}\0" \ + "net_nfs=tftp 200000 ${bootfile};run nfsargs addip addtty;" \ + "bootm\0" \ + "rootpath=/opt/buildroot\0" \ + "bootfile=/tftpboot/netbox/uImage\0" \ + "kernel_addr=50080000\0" \ + "ramdisk_addr=50200000\0" \ + "load=tftp 100000 /tftpboot/netbox/u-boot.bin\0" \ + "update=protect off 50000000 5007dfff;era 50000000 5007dfff;" \ + "cp.b 100000 50000000 ${filesize};" \ + "setenv filesize;saveenv\0" \ + "upd=run load;run update\0" \ + "ipaddr=10.0.0.233\0" \ + "serverip=10.0.0.152\0" \ + "netmask=255.255.0.0\0" \ + "ethaddr=c6:6f:13:36:f3:81\0" \ + "eth1addr=c6:6f:13:36:f3:82\0" \ + "mtdparts=IXP4XX-Flash.0:504k@0(uboot),4k@504k(env)," \ + "4k@508k(renv)\0" \ + "" +#define CONFIG_BOOTCOMMAND "run net_nfs" + +/* + * Physical Memory Map + */ +#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */ +#define PHYS_SDRAM_1 0x00000000 /* SDRAM Bank #1 */ +#define PHYS_SDRAM_1_SIZE 0x02000000 /* 32 MB */ + +#define CFG_FLASH_BASE 0x50000000 +#define CFG_MONITOR_BASE CFG_FLASH_BASE +#define CFG_MONITOR_LEN (504 << 10) /* Reserve 512 kB for Monitor */ + +/* + * Expansion bus settings + */ +#define CFG_EXP_CS0 0x94913C43 /* 8bit, max size */ +#define CFG_EXP_CS1 0x85000043 /* 8bit, 512bytes */ + +/* + * SDRAM settings + */ +#define CFG_SDR_CONFIG 0x18 +#define CFG_SDR_MODE_CONFIG 0x1 +#define CFG_SDRAM_REFRESH_CNT 0x81a + +/* + * FLASH and environment organization + */ +#define FLASH_BASE0_PRELIM CFG_FLASH_BASE /* FLASH bank #0 */ + +#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 256 /* max number of sectors on one chip */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 1000 /* Timeout for Flash Write (in ms) */ + +#define CFG_FLASH_WORD_SIZE unsigned char /* flash word size (width) */ +#define CFG_FLASH_ADDR0 0x5555 /* 1st address for flash config cycles */ +#define CFG_FLASH_ADDR1 0x2AAA /* 2nd address for flash config cycles */ +/* + * The following defines are added for buggy IOP480 byte interface. + * All other boards should use the standard values (CPCI405 etc.) + */ +#define CFG_FLASH_READ0 0x0000 /* 0 is standard */ +#define CFG_FLASH_READ1 0x0001 /* 1 is standard */ +#define CFG_FLASH_READ2 0x0002 /* 2 is standard */ + +#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */ + +#define CFG_ENV_IS_IN_FLASH 1 + +#define CFG_ENV_SECT_SIZE 0x1000 /* size of one complete sector */ +#define CFG_ENV_ADDR (CFG_FLASH_BASE + CFG_MONITOR_LEN) +#define CFG_ENV_SIZE 0x1000 /* Total Size of Environment Sector */ + +/* Address and size of Redundant Environment Sector */ +#define CFG_ENV_ADDR_REDUND (CFG_ENV_ADDR + CFG_ENV_SECT_SIZE) +#define CFG_ENV_SIZE_REDUND (CFG_ENV_SIZE) + +/* + * NAND-FLASH stuff + */ +#define CFG_MAX_NAND_DEVICE 1 +#define NAND_MAX_CHIPS 1 +#define CFG_NAND_BASE 0x51000000 /* NAND FLASH Base Address */ + +/* + * GPIO settings + */ + +/* FPGA program pin configuration */ +#define CFG_GPIO_PRG 12 /* FPGA program pin (cpu output)*/ +#define CFG_GPIO_CLK 10 /* FPGA clk pin (cpu output) */ +#define CFG_GPIO_DATA 14 /* FPGA data pin (cpu output) */ +#define CFG_GPIO_INIT 13 /* FPGA init pin (cpu input) */ +#define CFG_GPIO_DONE 11 /* FPGA done pin (cpu input) */ + +/* other GPIO's */ +#define CFG_GPIO_RESTORE_INT 0 +#define CFG_GPIO_RESTART_INT 1 +#define CFG_GPIO_SYS_RUNNING 2 +#define CFG_GPIO_PCI_INTA 3 +#define CFG_GPIO_PCI_INTB 4 +#define CFG_GPIO_I2C_SCL 6 +#define CFG_GPIO_I2C_SDA 7 +#define CFG_GPIO_FPGA_RESET 9 +#define CFG_GPIO_CLK_33M 15 + +/* + * I2C stuff + */ + +/* enable I2C and select the hardware/software driver */ +#undef CONFIG_HARD_I2C /* I2C with hardware support */ +#define CONFIG_SOFT_I2C 1 /* I2C bit-banged */ + +#define CFG_I2C_SPEED 83000 /* 83 kHz is supposed to work */ +#define CFG_I2C_SLAVE 0xFE + +/* + * Software (bit-bang) I2C driver configuration + */ +#define PB_SCL (1 << CFG_GPIO_I2C_SCL) +#define PB_SDA (1 << CFG_GPIO_I2C_SDA) + +#define I2C_INIT GPIO_OUTPUT_ENABLE(CFG_GPIO_I2C_SCL) +#define I2C_ACTIVE GPIO_OUTPUT_ENABLE(CFG_GPIO_I2C_SDA) +#define I2C_TRISTATE GPIO_OUTPUT_DISABLE(CFG_GPIO_I2C_SDA) +#define I2C_READ ((*IXP425_GPIO_GPINR & PB_SDA) != 0) +#define I2C_SDA(bit) if (bit) GPIO_OUTPUT_SET(CFG_GPIO_I2C_SDA); \ + else GPIO_OUTPUT_CLEAR(CFG_GPIO_I2C_SDA) +#define I2C_SCL(bit) if (bit) GPIO_OUTPUT_SET(CFG_GPIO_I2C_SCL); \ + else GPIO_OUTPUT_CLEAR(CFG_GPIO_I2C_SCL) +#define I2C_DELAY udelay(3) /* 1/4 I2C clock duration */ + +/* + * I2C RTC + */ +#define CONFIG_RTC_M41T11 1 +#define CFG_I2C_RTC_ADDR 0x68 +#define CFG_M41T11_BASE_YEAR 1900 /* play along with the linux driver */ + +/* + * Spartan3 FPGA configuration support + */ +#define CFG_FPGA_MAX_SIZE 700*1024 /* 700kByte for XC3S500E */ + +#define CFG_FPGA_PRG (1 << CFG_GPIO_PRG) /* FPGA program pin (cpu output)*/ +#define CFG_FPGA_CLK (1 << CFG_GPIO_CLK) /* FPGA clk pin (cpu output) */ +#define CFG_FPGA_DATA (1 << CFG_GPIO_DATA) /* FPGA data pin (cpu output) */ +#define CFG_FPGA_INIT (1 << CFG_GPIO_INIT) /* FPGA init pin (cpu input) */ +#define CFG_FPGA_DONE (1 << CFG_GPIO_DONE) /* FPGA done pin (cpu input) */ + +/* + * Cache Configuration + */ +#define CFG_CACHELINE_SIZE 32 + +#endif /* __CONFIG_H */ diff --git a/include/configs/r5200.h b/include/configs/r5200.h new file mode 100644 index 0000000..e1e406b --- /dev/null +++ b/include/configs/r5200.h @@ -0,0 +1,169 @@ +/* + * Configuation settings for the R5200 board + * + * (C) Copyright 2006 Lab X Technologies + * Based on Motorola MC5272C3 board config + * (C) Copyright 2003 Josef Baumgartner + * + * 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 + */ + +/* + * board/config.h - configuration options, board specific + */ + +#ifndef _R5200_H +#define _R5200_H + +/* + * High Level Configuration Options + * (easy to change) + */ +#define CONFIG_MCF52x2 /* define processor family */ +#define CONFIG_M5271 /* define processor type */ +#define CONFIG_R5200 /* define board type */ + +#define FEC_ENET +#define CONFIG_NET_RETRY_COUNT 5 + +#define CONFIG_IPADDR 192.168.0.172 +#define CONFIG_SERVERIP 192.168.0.148 +#define CONFIG_ETHADDR 00:06:3b:00:44:55 + +#define CONFIG_BAUDRATE 19200 +#define CFG_BAUDRATE_TABLE { 9600 , 19200 , 38400 , 57600, 115200 } + +#define CONFIG_WATCHDOG +#define CONFIG_WATCHDOG_TIMEOUT 0xFFFF /* clock modulus */ + +/* Configuration for environment + * Environment is embedded in u-boot in the second sector of the flash + */ +#ifndef CONFIG_MONITOR_IS_IN_RAM +#define CFG_ENV_OFFSET 0x20000 +#define CFG_ENV_SECT_SIZE 0x20000 +#define CFG_ENV_IS_IN_FLASH 1 +#define CFG_ENV_IS_EMBEDDED 1 +#else +#define CFG_ENV_ADDR 0xf0020000 +#define CFG_ENV_SECT_SIZE 0x2000 +#define CFG_ENV_IS_IN_FLASH 1 +#endif + +#define CONFIG_COMMANDS ((CONFIG_CMD_DFL | CFG_CMD_PING | CFG_CMD_NET ) & ~(CFG_CMD_LOADS | CFG_CMD_LOADB)) + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include + +/* Note: We only copy one sectors worth of application code from location + * 10200000 for speed purposes. Increase the size if necessary */ +#define CONFIG_BOOTCOMMAND "cp.b 10200000 0 20000; go 400" +#define CONFIG_BOOTDELAY 1 + +#define CFG_PROMPT "u-boot> " +#define CFG_LONGHELP /* undef to save memory */ + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_LOAD_ADDR 0x00002000 + +#define CFG_MEMTEST_START 0x400 +#define CFG_MEMTEST_END 0x380000 + +#define CFG_HZ 1000000 +#define CFG_CLK 100000000 + +/* + * Low Level Configuration Settings + * (address mappings, register initial values, etc.) + * You should know what you are doing if you make changes here. + */ + +#define CFG_MBAR 0x40000000 /* Register Base Addrs */ + +#define CFG_ENET_BD_BASE 0x480000 + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area (in DPRAM) + */ +#define CFG_INIT_RAM_ADDR 0x20000000 +#define CFG_INIT_RAM_END 0x1000 /* End of used area in internal SRAM */ +#define CFG_GBL_DATA_SIZE 64 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_SDRAM_SIZE 8 /* SDRAM size in MB */ +#define CFG_FLASH_BASE 0x10000000 + +#ifdef CONFIG_MONITOR_IS_IN_RAM +#define CFG_MONITOR_BASE 0x20000 +#else +#define CFG_MONITOR_BASE (CFG_FLASH_BASE + 0x400) +#endif + +#define CFG_MONITOR_LEN 0x20001 +#define CFG_MALLOC_LEN (256 << 10) +#define CFG_BOOTPARAMS_LEN 64*1024 + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization ?? + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ + +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 1024 /* max number of sectors on one chip */ +#define CFG_FLASH_ERASE_TOUT 1000 + +#define CFG_FLASH_CFI 1 +#define CFG_FLASH_CFI_DRIVER 1 +#define CFG_FLASH_SIZE 0x800000 + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_CACHELINE_SIZE 16 + +/*----------------------------------------------------------------------- + * Memory bank definitions + */ + +/*----------------------------------------------------------------------- + * Port configuration + */ +#define CFG_FECI2C 0xF0 + +#endif /* _R5200_H */ diff --git a/include/configs/virtlab2.h b/include/configs/virtlab2.h new file mode 100644 index 0000000..06d8536 --- /dev/null +++ b/include/configs/virtlab2.h @@ -0,0 +1,461 @@ +/* + * (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 + */ + +/* + * board/config.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_MPC823 1 /* This is a MPC823 CPU */ +#define CONFIG_VIRTLAB2 1 /* ...on a virtlab2 module */ +#define CONFIG_TQM8xxL 1 + +#ifdef CONFIG_LCD /* with LCD controller ? */ +#define CONFIG_SPLASH_SCREEN /* ... with splashscreen support*/ +#endif + +#define CONFIG_8xx_CONS_SMC1 1 /* Console is on SMC1 */ +#undef CONFIG_8xx_CONS_SMC2 +#undef CONFIG_8xx_CONS_NONE +#define CONFIG_BAUDRATE 115200 /* console baudrate = 115kbps */ + +#define CONFIG_BOOTCOUNT_LIMIT + +#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */ + +#define CONFIG_BOARD_TYPES 1 /* support board types */ + +#define CONFIG_PREBOOT "echo;echo Type \"run flash_nfs\" to mount root filesystem over NFS;echo" + +#undef CONFIG_BOOTARGS + +#define CONFIG_EXTRA_ENV_SETTINGS \ + "netdev=eth0\0" \ + "nfsargs=setenv bootargs root=/dev/nfs rw " \ + "nfsroot=${serverip}:${rootpath}\0" \ + "ramargs=setenv bootargs root=/dev/ram rw\0" \ + "addip=setenv bootargs ${bootargs} " \ + "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}" \ + ":${hostname}:${netdev}:off panic=1\0" \ + "flash_nfs=run nfsargs addip;" \ + "bootm ${kernel_addr}\0" \ + "flash_self=run ramargs addip;" \ + "bootm ${kernel_addr} ${ramdisk_addr}\0" \ + "net_nfs=tftp 200000 ${bootfile};run nfsargs addip;bootm\0" \ + "rootpath=/opt/eldk/ppc_8xx\0" \ + "bootfile=/tftpboot/TQM823L/uImage\0" \ + "kernel_addr=40040000\0" \ + "ramdisk_addr=40100000\0" \ + "" +#define CONFIG_BOOTCOMMAND "run flash_self" + +#define CONFIG_LOADS_ECHO 1 /* echo on for serial download */ +#undef CFG_LOADS_BAUD_CHANGE /* don't allow baudrate change */ + +#undef CONFIG_WATCHDOG /* watchdog disabled */ + +#if defined(CONFIG_LCD) +# undef CONFIG_STATUS_LED /* disturbs display */ +#else +# define CONFIG_STATUS_LED 1 /* Status LED enabled */ +#endif /* CONFIG_LCD */ + +#undef CONFIG_CAN_DRIVER /* CAN Driver support disabled */ + +#define CONFIG_BOOTP_MASK (CONFIG_BOOTP_DEFAULT | CONFIG_BOOTP_BOOTFILESIZE) + +#define CONFIG_MAC_PARTITION +#define CONFIG_DOS_PARTITION + +#define CONFIG_RTC_MPC8xx /* use internal RTC of MPC8xx */ + +#ifdef CONFIG_SPLASH_SCREEN +# define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \ + CFG_CMD_ASKENV | \ + CFG_CMD_BMP | \ + CFG_CMD_DATE | \ + CFG_CMD_DHCP | \ + CFG_CMD_IDE | \ + CFG_CMD_NFS | \ + CFG_CMD_SNTP ) +#else +# define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \ + CFG_CMD_ASKENV | \ + CFG_CMD_DATE | \ + CFG_CMD_DHCP | \ + CFG_CMD_IDE | \ + CFG_CMD_NFS | \ + CFG_CMD_SNTP ) +#endif + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ + +#if 0 +#define CFG_HUSH_PARSER 1 /* use "hush" command parser */ +#endif +#ifdef CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2 "> " +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_MEMTEST_START 0x0400000 /* memtest works on */ +#define CFG_MEMTEST_END 0x0C00000 /* 4 ... 12 MB in DRAM */ + +#define CFG_LOAD_ADDR 0x100000 /* default load address */ + +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } + +/* + * Low Level Configuration Settings + * (address mappings, register initial values, etc.) + * You should know what you are doing if you make changes here. + */ +/*----------------------------------------------------------------------- + * Internal Memory Mapped Register + */ +#define CFG_IMMR 0xFFF00000 + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area (in DPRAM) + */ +#define CFG_INIT_RAM_ADDR CFG_IMMR +#define CFG_INIT_RAM_END 0x2F00 /* End of used area in DPRAM */ +#define CFG_GBL_DATA_SIZE 64 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_FLASH_BASE 0x40000000 +#define CFG_MONITOR_LEN (256 << 10) /* Reserve 256 kB for Monitor */ +#define CFG_MONITOR_BASE CFG_FLASH_BASE +#define CFG_MALLOC_LEN (128 << 10) /* Reserve 128 kB for malloc() */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ + +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 71 /* max number of sectors on one chip */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + +#define CFG_ENV_IS_IN_FLASH 1 +#define CFG_ENV_OFFSET 0x8000 /* Offset of Environment Sector */ +#define CFG_ENV_SIZE 0x4000 /* Total Size of Environment Sector */ + +/* Address and size of Redundant Environment Sector */ +#define CFG_ENV_OFFSET_REDUND (CFG_ENV_OFFSET+CFG_ENV_SIZE) +#define CFG_ENV_SIZE_REDUND (CFG_ENV_SIZE) + +/*----------------------------------------------------------------------- + * Hardware Information Block + */ +#define CFG_HWINFO_OFFSET 0x0003FFC0 /* offset of HW Info block */ +#define CFG_HWINFO_SIZE 0x00000040 /* size of HW Info block */ +#define CFG_HWINFO_MAGIC 0x54514D38 /* 'TQM8' */ + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_CACHELINE_SIZE 16 /* For all MPC8xx CPUs */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CACHELINE_SHIFT 4 /* log base 2 of the above value */ +#endif + +/*----------------------------------------------------------------------- + * SYPCR - System Protection Control 11-9 + * SYPCR can only be written once after reset! + *----------------------------------------------------------------------- + * Software & Bus Monitor Timer max, Bus Monitor enable, SW Watchdog freeze + */ +#if defined(CONFIG_WATCHDOG) +#define CFG_SYPCR (SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF | \ + SYPCR_SWE | SYPCR_SWRI| SYPCR_SWP) +#else +#define CFG_SYPCR (SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF | SYPCR_SWP) +#endif + +/*----------------------------------------------------------------------- + * SIUMCR - SIU Module Configuration 11-6 + *----------------------------------------------------------------------- + * PCMCIA config., multi-function pin tri-state + */ +#ifndef CONFIG_CAN_DRIVER +#define CFG_SIUMCR (SIUMCR_DBGC00 | SIUMCR_DBPC00 | SIUMCR_MLRC01) +#else /* we must activate GPL5 in the SIUMCR for CAN */ +#define CFG_SIUMCR (SIUMCR_DBGC11 | SIUMCR_DBPC00 | SIUMCR_MLRC01) +#endif /* CONFIG_CAN_DRIVER */ + +/*----------------------------------------------------------------------- + * TBSCR - Time Base Status and Control 11-26 + *----------------------------------------------------------------------- + * Clear Reference Interrupt Status, Timebase freezing enabled + */ +#define CFG_TBSCR (TBSCR_REFA | TBSCR_REFB | TBSCR_TBF) + +/*----------------------------------------------------------------------- + * RTCSC - Real-Time Clock Status and Control Register 11-27 + *----------------------------------------------------------------------- + */ +#define CFG_RTCSC (RTCSC_SEC | RTCSC_ALR | RTCSC_RTF| RTCSC_RTE) + +/*----------------------------------------------------------------------- + * PISCR - Periodic Interrupt Status and Control 11-31 + *----------------------------------------------------------------------- + * Clear Periodic Interrupt Status, Interrupt Timer freezing enabled + */ +#define CFG_PISCR (PISCR_PS | PISCR_PITF) + +/*----------------------------------------------------------------------- + * PLPRCR - PLL, Low-Power, and Reset Control Register 15-30 + *----------------------------------------------------------------------- + * Reset PLL lock status sticky bit, timer expired status bit and timer + * interrupt status bit + */ +#define CFG_PLPRCR (PLPRCR_SPLSS | PLPRCR_TEXPS | PLPRCR_TMIST) + +/*----------------------------------------------------------------------- + * SCCR - System Clock and reset Control Register 15-27 + *----------------------------------------------------------------------- + * Set clock output, timebase and RTC source and divider, + * power management and some other internal clocks + */ +#define SCCR_MASK SCCR_EBDF11 +#define CFG_SCCR (SCCR_COM00 | SCCR_DFSYNC00 | SCCR_DFBRG00 | \ + SCCR_DFNL000 | SCCR_DFNH000 | SCCR_DFLCD000 | \ + SCCR_DFALCD00) + +/*----------------------------------------------------------------------- + * PCMCIA stuff + *----------------------------------------------------------------------- + * + */ +#define CFG_PCMCIA_MEM_ADDR (0xE0000000) +#define CFG_PCMCIA_MEM_SIZE ( 64 << 20 ) +#define CFG_PCMCIA_DMA_ADDR (0xE4000000) +#define CFG_PCMCIA_DMA_SIZE ( 64 << 20 ) +#define CFG_PCMCIA_ATTRB_ADDR (0xE8000000) +#define CFG_PCMCIA_ATTRB_SIZE ( 64 << 20 ) +#define CFG_PCMCIA_IO_ADDR (0xEC000000) +#define CFG_PCMCIA_IO_SIZE ( 64 << 20 ) + +/*----------------------------------------------------------------------- + * IDE/ATA stuff (Supports IDE harddisk on PCMCIA Adapter) + *----------------------------------------------------------------------- + */ + +#define CONFIG_IDE_8xx_PCCARD 1 /* Use IDE with PC Card Adapter */ + +#undef CONFIG_IDE_8xx_DIRECT /* Direct IDE not supported */ +#undef CONFIG_IDE_LED /* LED for ide not supported */ +#undef CONFIG_IDE_RESET /* reset for ide not supported */ + +#define CFG_IDE_MAXBUS 1 /* max. 1 IDE bus */ +#define CFG_IDE_MAXDEVICE 1 /* max. 1 drive per IDE bus */ + +#define CFG_ATA_IDE0_OFFSET 0x0000 + +#define CFG_ATA_BASE_ADDR CFG_PCMCIA_MEM_ADDR + +/* Offset for data I/O */ +#define CFG_ATA_DATA_OFFSET (CFG_PCMCIA_MEM_SIZE + 0x320) + +/* Offset for normal register accesses */ +#define CFG_ATA_REG_OFFSET (2 * CFG_PCMCIA_MEM_SIZE + 0x320) + +/* Offset for alternate registers */ +#define CFG_ATA_ALT_OFFSET 0x0100 + +/*----------------------------------------------------------------------- + * + *----------------------------------------------------------------------- + * + */ +#define CFG_DER 0 + +/* + * Init Memory Controller: + * + * BR0/1 and OR0/1 (FLASH) + */ + +#define FLASH_BASE0_PRELIM 0x40000000 /* FLASH bank #0 */ +#define FLASH_BASE1_PRELIM 0x60000000 /* FLASH bank #0 */ + +/* used to re-map FLASH both when starting from SRAM or FLASH: + * restrict access enough to keep SRAM working (if any) + * but not too much to meddle with FLASH accesses + */ +#define CFG_REMAP_OR_AM 0x80000000 /* OR addr mask */ +#define CFG_PRELIM_OR_AM 0xE0000000 /* OR addr mask */ + +/* + * FLASH timing: + */ +#define CFG_OR_TIMING_FLASH (OR_ACS_DIV1 | OR_TRLX | OR_CSNT_SAM | \ + OR_SCY_3_CLK | OR_EHTR | OR_BI) + +#define CFG_OR0_REMAP (CFG_REMAP_OR_AM | CFG_OR_TIMING_FLASH) +#define CFG_OR0_PRELIM (CFG_PRELIM_OR_AM | CFG_OR_TIMING_FLASH) +#define CFG_BR0_PRELIM ((FLASH_BASE0_PRELIM & BR_BA_MSK) | BR_V ) + +#define CFG_OR1_REMAP CFG_OR0_REMAP +#define CFG_OR1_PRELIM CFG_OR0_PRELIM +#define CFG_BR1_PRELIM ((FLASH_BASE1_PRELIM & BR_BA_MSK) | BR_V ) + +/* + * BR2/3 and OR2/3 (SDRAM) + * + */ +#define SDRAM_BASE2_PRELIM 0x00000000 /* SDRAM bank #0 */ +#define SDRAM_BASE3_PRELIM 0x20000000 /* SDRAM bank #1 */ +#define SDRAM_MAX_SIZE 0x04000000 /* max 64 MB per bank */ + +/* SDRAM timing: Multiplexed addresses, GPL5 output to GPL5_A (don't care) */ +#define CFG_OR_TIMING_SDRAM 0x00000A00 + +#define CFG_OR2_PRELIM (CFG_PRELIM_OR_AM | CFG_OR_TIMING_SDRAM ) +#define CFG_BR2_PRELIM ((SDRAM_BASE2_PRELIM & BR_BA_MSK) | BR_MS_UPMA | BR_V ) + +#ifndef CONFIG_CAN_DRIVER +#define CFG_OR3_PRELIM CFG_OR2_PRELIM +#define CFG_BR3_PRELIM ((SDRAM_BASE3_PRELIM & BR_BA_MSK) | BR_MS_UPMA | BR_V ) +#else /* CAN uses CS3#, so we can have only one SDRAM bank anyway */ +#define CFG_CAN_BASE 0xC0000000 /* CAN mapped at 0xC0000000 */ +#define CFG_CAN_OR_AM 0xFFFF8000 /* 32 kB address mask */ +#define CFG_OR3_CAN (CFG_CAN_OR_AM | OR_G5LA | OR_BI) +#define CFG_BR3_CAN ((CFG_CAN_BASE & BR_BA_MSK) | \ + BR_PS_8 | BR_MS_UPMB | BR_V ) +#endif /* CONFIG_CAN_DRIVER */ + +/* + * Memory Periodic Timer Prescaler + * + * The Divider for PTA (refresh timer) configuration is based on an + * example SDRAM configuration (64 MBit, one bank). The adjustment to + * the number of chip selects (NCS) and the actually needed refresh + * rate is done by setting MPTPR. + * + * PTA is calculated from + * PTA = (gclk * Trefresh) / ((2 ^ (2 * DFBRG)) * PTP * NCS) + * + * gclk CPU clock (not bus clock!) + * Trefresh Refresh cycle * 4 (four word bursts used) + * + * 4096 Rows from SDRAM example configuration + * 1000 factor s -> ms + * 32 PTP (pre-divider from MPTPR) from SDRAM example configuration + * 4 Number of refresh cycles per period + * 64 Refresh cycle in ms per number of rows + * -------------------------------------------- + * Divider = 4096 * 32 * 1000 / (4 * 64) = 512000 + * + * 50 MHz => 50.000.000 / Divider = 98 + * 66 Mhz => 66.000.000 / Divider = 129 + * 80 Mhz => 80.000.000 / Divider = 156 + */ + +#define CFG_PTA_PER_CLK ((4096 * 32 * 1000) / (4 * 64)) +#define CFG_MAMR_PTA 98 + +/* + * For 16 MBit, refresh rates could be 31.3 us + * (= 64 ms / 2K = 125 / quad bursts). + * For a simpler initialization, 15.6 us is used instead. + * + * #define CFG_MPTPR_2BK_2K MPTPR_PTP_DIV32 for 2 banks + * #define CFG_MPTPR_1BK_2K MPTPR_PTP_DIV64 for 1 bank + */ +#define CFG_MPTPR_2BK_4K MPTPR_PTP_DIV16 /* setting for 2 banks */ +#define CFG_MPTPR_1BK_4K MPTPR_PTP_DIV32 /* setting for 1 bank */ + +/* refresh rate 7.8 us (= 64 ms / 8K = 31.2 / quad bursts) for 256 MBit */ +#define CFG_MPTPR_2BK_8K MPTPR_PTP_DIV8 /* setting for 2 banks */ +#define CFG_MPTPR_1BK_8K MPTPR_PTP_DIV16 /* setting for 1 bank */ + +/* + * MAMR settings for SDRAM + */ + +/* 8 column SDRAM */ +#define CFG_MAMR_8COL ((CFG_MAMR_PTA << MAMR_PTA_SHIFT) | MAMR_PTAE | \ + MAMR_AMA_TYPE_0 | MAMR_DSA_1_CYCL | MAMR_G0CLA_A11 | \ + MAMR_RLFA_1X | MAMR_WLFA_1X | MAMR_TLFA_4X) +/* 9 column SDRAM */ +#define CFG_MAMR_9COL ((CFG_MAMR_PTA << MAMR_PTA_SHIFT) | MAMR_PTAE | \ + MAMR_AMA_TYPE_1 | MAMR_DSA_1_CYCL | MAMR_G0CLA_A10 | \ + MAMR_RLFA_1X | MAMR_WLFA_1X | MAMR_TLFA_4X) + + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + +/* Map peripheral control registers on CS4 */ +#define CFG_PERIPHERAL_BASE 0xA0000000 +#define CFG_PERIPHERAL_OR_AM 0xFFFF8000 /* 32 kB address mask */ +#define CFG_OR4_PRELIM (CFG_PERIPHERAL_OR_AM | OR_TRLX | OR_CSNT_SAM | \ + OR_SCY_2_CLK) +#define CFG_BR4_PRELIM ((CFG_PERIPHERAL_BASE & BR_BA_MSK) | BR_PS_8 | BR_V) +#define PCMCIA_CTRL (CFG_PERIPHERAL_BASE + 0xB00) +#endif /* __CONFIG_H */ diff --git a/include/configs/yellowstone.h b/include/configs/yellowstone.h index d3e9671..7d55566 100644 --- a/include/configs/yellowstone.h +++ b/include/configs/yellowstone.h @@ -1,5 +1,5 @@ /* - * (C) Copyright 2005 + * (C) Copyright 2005-2006 * Stefan Roese, DENX Software Engineering, sr@denx.de. * * See file CREDITS for list of people who contributed to this @@ -174,7 +174,7 @@ "rootpath=/opt/eldk/ppc_4xx\0" \ "bootfile=/tftpboot/yellowstone/uImage\0" \ "kernel_addr=fc000000\0" \ - "ramdisk_addr=fc100000\0" \ + "ramdisk_addr=fc180000\0" \ "load=tftp 100000 /tftpboot/yellowstone/u-boot.bin\0" \ "update=protect off fff80000 ffffffff;era fff80000 ffffffff;" \ "cp.b 100000 fff80000 80000;" \ diff --git a/include/configs/yosemite.h b/include/configs/yosemite.h index a67b834..a81cf34 100644 --- a/include/configs/yosemite.h +++ b/include/configs/yosemite.h @@ -1,5 +1,5 @@ /* - * (C) Copyright 2005 + * (C) Copyright 2005-2006 * Stefan Roese, DENX Software Engineering, sr@denx.de. * * See file CREDITS for list of people who contributed to this @@ -109,6 +109,8 @@ #define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ #define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ +#define CFG_FLASH_USE_BUFFER_WRITE 1 /* use buffered writes (20x faster) */ + #define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */ #ifdef CFG_ENV_IS_IN_FLASH @@ -174,7 +176,7 @@ "rootpath=/opt/eldk/ppc_4xx\0" \ "bootfile=/tftpboot/yosemite/uImage\0" \ "kernel_addr=fc000000\0" \ - "ramdisk_addr=fc100000\0" \ + "ramdisk_addr=fc180000\0" \ "load=tftp 100000 /tftpboot/yosemite/u-boot.bin\0" \ "update=protect off fff80000 ffffffff;era fff80000 ffffffff;" \ "cp.b 100000 fff80000 80000;" \ diff --git a/include/configs/zylonite.h b/include/configs/zylonite.h index 4232d50..c6aa8ec 100644 --- a/include/configs/zylonite.h +++ b/include/configs/zylonite.h @@ -76,14 +76,17 @@ #define CONFIG_BAUDRATE 115200 -/* #define CONFIG_COMMANDS (CONFIG_CMD_DFL | CFG_CMD_MMC | CFG_CMD_FAT) */ #ifdef TURN_ON_ETHERNET # define CONFIG_COMMANDS (CONFIG_CMD_DFL | CFG_CMD_PING) #else -# define CONFIG_COMMANDS (CONFIG_CMD_DFL & ~CFG_CMD_NET) +# define CONFIG_COMMANDS ((CONFIG_CMD_DFL \ + | CFG_CMD_ENV \ + | CFG_CMD_NAND) \ + & ~(CFG_CMD_NET \ + | CFG_CMD_FLASH \ + | CFG_CMD_IMLS)) #endif - /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ #include @@ -127,8 +130,11 @@ #define CFG_LOAD_ADDR (CFG_DRAM_BASE + 0x8000) /* default load address */ -#define CFG_HZ 3686400 /* incrementer freq: 3.6864 MHz */ -#define CFG_CPUSPEED 0x161 /* set core clock to 400/200/100 MHz */ +#define CFG_HZ 3250000 /* incrementer freq: 3.25 MHz */ + +/* Monahans Core Frequency */ +#define CFG_MONAHANS_RUN_MODE_OSC_RATIO 16 /* valid values: 8, 16, 24, 31 */ +#define CFG_MONAHANS_TURBO_RUN_MODE_RATIO 1 /* valid values: 1, 2 */ /* valid baudrates */ #define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } @@ -159,98 +165,64 @@ #define PHYS_SDRAM_4 0xac000000 /* SDRAM Bank #4 */ #define PHYS_SDRAM_4_SIZE 0x00000000 /* 0 MB */ -#define PHYS_FLASH_1 0x00000000 /* Flash Bank #1 */ -#define PHYS_FLASH_2 0x04000000 /* Flash Bank #2 */ -#define PHYS_FLASH_SIZE 0x02000000 /* 32 MB */ -#define PHYS_FLASH_BANK_SIZE 0x02000000 /* 32 MB Banks */ -#define PHYS_FLASH_SECT_SIZE 0x00040000 /* 256 KB sectors (x2) */ +#define CFG_DRAM_BASE 0x80000000 /* at CS0 */ +#define CFG_DRAM_SIZE 0x04000000 /* 64 MB Ram */ -#define CFG_DRAM_BASE 0xa0000000 -#define CFG_DRAM_SIZE 0x04000000 +#undef CFG_SKIP_DRAM_SCRUB -#define CFG_FLASH_BASE PHYS_FLASH_1 - -#define FPGA_REGS_BASE_PHYSICAL 0x08000000 /* - * GPIO settings + * NAND Flash */ -#define CFG_GPSR0_VAL 0x00008000 -#define CFG_GPSR1_VAL 0x00FC0382 -#define CFG_GPSR2_VAL 0x0001FFFF -#define CFG_GPCR0_VAL 0x00000000 -#define CFG_GPCR1_VAL 0x00000000 -#define CFG_GPCR2_VAL 0x00000000 -#define CFG_GPDR0_VAL 0x0060A800 -#define CFG_GPDR1_VAL 0x00FF0382 -#define CFG_GPDR2_VAL 0x0001C000 -#define CFG_GAFR0_L_VAL 0x98400000 -#define CFG_GAFR0_U_VAL 0x00002950 -#define CFG_GAFR1_L_VAL 0x000A9558 -#define CFG_GAFR1_U_VAL 0x0005AAAA -#define CFG_GAFR2_L_VAL 0xA0000000 -#define CFG_GAFR2_U_VAL 0x00000002 - -#define CFG_PSSR_VAL 0x20 +/* Use the new NAND code. (BOARDLIBS = drivers/nand/libnand.a required) */ +#define CONFIG_NEW_NAND_CODE +#define CFG_NAND0_BASE 0x0 +#undef CFG_NAND1_BASE -/* - * Memory settings - */ -#define CFG_MSC0_VAL 0x23F223F2 -#define CFG_MSC1_VAL 0x3FF1A441 -#define CFG_MSC2_VAL 0x7FF97FF1 -#define CFG_MDCNFG_VAL 0x00001AC9 -#define CFG_MDREFR_VAL 0x00018018 -#define CFG_MDMRS_VAL 0x00000000 +#define CFG_NAND_BASE_LIST { CFG_NAND0_BASE } +#define CFG_MAX_NAND_DEVICE 1 /* Max number of NAND devices */ -/* - * PCMCIA and CF Interfaces - */ -#define CFG_MECR_VAL 0x00000000 -#define CFG_MCMEM0_VAL 0x00010504 -#define CFG_MCMEM1_VAL 0x00010504 -#define CFG_MCATT0_VAL 0x00010504 -#define CFG_MCATT1_VAL 0x00010504 -#define CFG_MCIO0_VAL 0x00004715 -#define CFG_MCIO1_VAL 0x00004715 +/* nand timeout values */ +#define CFG_NAND_PROG_ERASE_TO 3000 +#define CFG_NAND_OTHER_TO 100 +#define CFG_NAND_SENDCMD_RETRY 3 +#undef NAND_ALLOW_ERASE_ALL /* Allow erasing bad blocks - don't use */ -#define _LED 0x08000010 -#define LED_BLANK 0x08000040 +/* NAND Timing Parameters (in ns) */ +#define NAND_TIMING_tCH 10 +#define NAND_TIMING_tCS 0 +#define NAND_TIMING_tWH 20 +#define NAND_TIMING_tWP 40 -/* - * FLASH and environment organization - */ -#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */ -#define CFG_MAX_FLASH_SECT 128 /* max number of sectors on one chip */ +#define NAND_TIMING_tRH 20 +#define NAND_TIMING_tRP 40 -/* timeout values are in ticks */ -#define CFG_FLASH_ERASE_TOUT (25*CFG_HZ) /* Timeout for Flash Erase */ -#define CFG_FLASH_WRITE_TOUT (25*CFG_HZ) /* Timeout for Flash Write */ +#define NAND_TIMING_tR 11123 +#define NAND_TIMING_tWHR 100 +#define NAND_TIMING_tAR 10 -/* NOTE: many default partitioning schemes assume the kernel starts at the - * second sector, not an environment. You have been warned! - */ -#define CFG_MONITOR_LEN PHYS_FLASH_SECT_SIZE +/* NAND debugging */ +#define CFG_DFC_DEBUG1 /* usefull */ +#undef CFG_DFC_DEBUG2 /* noisy */ +#undef CFG_DFC_DEBUG3 /* extremly noisy */ -#define CFG_ENV_IS_IN_FLASH 1 -#define CFG_ENV_ADDR (PHYS_FLASH_1 + PHYS_FLASH_SECT_SIZE) -#define CFG_ENV_SECT_SIZE PHYS_FLASH_SECT_SIZE -#define CFG_ENV_SIZE (PHYS_FLASH_SECT_SIZE / 16) +#define CONFIG_MTD_DEBUG +#define CONFIG_MTD_DEBUG_VERBOSE 1 +#define ADDR_COLUMN 1 +#define ADDR_PAGE 2 +#define ADDR_COLUMN_PAGE 3 + +#define NAND_ChipID_UNKNOWN 0x00 +#define NAND_MAX_FLOORS 1 +#define NAND_MAX_CHIPS 1 + +#define CFG_NO_FLASH 1 + +#define CFG_ENV_IS_IN_NAND 1 +#define CFG_ENV_OFFSET 0x40000 +#define CFG_ENV_OFFSET_REDUND 0x44000 +#define CFG_ENV_SIZE 0x4000 -/* - * FPGA Offsets - */ -#define WHOAMI_OFFSET 0x00 -#define HEXLED_OFFSET 0x10 -#define BLANKLED_OFFSET 0x40 -#define DISCRETELED_OFFSET 0x40 -#define CNFG_SWITCHES_OFFSET 0x50 -#define USER_SWITCHES_OFFSET 0x60 -#define MISC_WR_OFFSET 0x80 -#define MISC_RD_OFFSET 0x90 -#define INT_MASK_OFFSET 0xC0 -#define INT_CLEAR_OFFSET 0xD0 -#define GP_OFFSET 0x100 #endif /* __CONFIG_H */ diff --git a/include/flash.h b/include/flash.h index a84dc68..84b48a9 100644 --- a/include/flash.h +++ b/include/flash.h @@ -234,6 +234,7 @@ extern void flash_read_factory_serial(flash_info_t * info, void * buffer, int of #define SST_ID_xF3202 0x235A235A /* 39xF3202 ID (32M = 2M x 16 ) */ #define SST_ID_xF6401 0x236B236B /* 39xF6401 ID (64M = 4M x 16 ) */ #define SST_ID_xF6402 0x236A236A /* 39xF6402 ID (64M = 4M x 16 ) */ +#define SST_ID_xF020 0xBFD6BFD6 /* 39xF020 ID (256KB = 2Mbit x 8) */ #define SST_ID_xF040 0xBFD7BFD7 /* 39xF040 ID (512KB = 4Mbit x 8) */ #define STM_ID_F040B 0xE2 /* M29F040B ID ( 4M = 512K x 8 ) */ @@ -343,6 +344,7 @@ extern void flash_read_factory_serial(flash_info_t * info, void * buffer, int of #define FLASH_SST160A 0x0046 /* SST 39xF160A ID ( 16M = 1M x 16 ) */ #define FLASH_SST320 0x0048 /* SST 39xF160A ID ( 16M = 1M x 16 ) */ #define FLASH_SST640 0x004A /* SST 39xF160A ID ( 16M = 1M x 16 ) */ +#define FLASH_SST020 0x0024 /* SST 39xF020 ID (256KB = 2Mbit x 8 ) */ #define FLASH_SST040 0x000E /* SST 39xF040 ID (512KB = 4Mbit x 8 ) */ #define FLASH_STM800AB 0x0051 /* STM M29WF800AB ( 8M = 512K x 16 ) */ diff --git a/include/linux/string.h b/include/linux/string.h index 1a45fd3..6239039 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -38,7 +38,7 @@ extern int strcmp(const char *,const char *); #ifndef __HAVE_ARCH_STRNCMP extern int strncmp(const char *,const char *,__kernel_size_t); #endif -#ifndef __HAVE_ARCH_STRNICMP +#if 0 /* not used - was: #ifndef __HAVE_ARCH_STRNICMP */ extern int strnicmp(const char *, const char *, __kernel_size_t); #endif #ifndef __HAVE_ARCH_STRCHR diff --git a/include/ppc440.h b/include/ppc440.h index 018f7be..53f14b5 100644 --- a/include/ppc440.h +++ b/include/ppc440.h @@ -1357,56 +1357,106 @@ /****************************************************************************** * GPIO macro register defines ******************************************************************************/ +#define GPIO0 0 +#define GPIO1 1 + #if defined(CONFIG_440GP) -#define GPIO_BASE0 (CFG_PERIPHERAL_BASE+0x00000700) +#define GPIO0_BASE (CFG_PERIPHERAL_BASE+0x00000700) -#define GPIO0_OR (GPIO_BASE0+0x0) -#define GPIO0_TCR (GPIO_BASE0+0x4) -#define GPIO0_ODR (GPIO_BASE0+0x18) -#define GPIO0_IR (GPIO_BASE0+0x1C) +#define GPIO0_OR (GPIO0_BASE+0x0) +#define GPIO0_TCR (GPIO0_BASE+0x4) +#define GPIO0_ODR (GPIO0_BASE+0x18) +#define GPIO0_IR (GPIO0_BASE+0x1C) #endif /* CONFIG_440GP */ #if defined(CONFIG_440EP) || defined(CONFIG_440GR) -#define GPIO_BASE0 (CFG_PERIPHERAL_BASE+0x00000B00) -#define GPIO_BASE1 (CFG_PERIPHERAL_BASE+0x00000C00) - -#define GPIO0_OR (GPIO_BASE0+0x0) -#define GPIO0_TCR (GPIO_BASE0+0x4) -#define GPIO0_OSRL (GPIO_BASE0+0x8) -#define GPIO0_OSRH (GPIO_BASE0+0xC) -#define GPIO0_TSRL (GPIO_BASE0+0x10) -#define GPIO0_TSRH (GPIO_BASE0+0x14) -#define GPIO0_ODR (GPIO_BASE0+0x18) -#define GPIO0_IR (GPIO_BASE0+0x1C) -#define GPIO0_RR1 (GPIO_BASE0+0x20) -#define GPIO0_RR2 (GPIO_BASE0+0x24) -#define GPIO0_RR3 (GPIO_BASE0+0x28) -#define GPIO0_ISR1L (GPIO_BASE0+0x30) -#define GPIO0_ISR1H (GPIO_BASE0+0x34) -#define GPIO0_ISR2L (GPIO_BASE0+0x38) -#define GPIO0_ISR2H (GPIO_BASE0+0x3C) -#define GPIO0_ISR3L (GPIO_BASE0+0x40) -#define GPIO0_ISR3H (GPIO_BASE0+0x44) - -#define GPIO1_OR (GPIO_BASE1+0x0) -#define GPIO1_TCR (GPIO_BASE1+0x4) -#define GPIO1_OSRL (GPIO_BASE1+0x8) -#define GPIO1_OSRH (GPIO_BASE1+0xC) -#define GPIO1_TSRL (GPIO_BASE1+0x10) -#define GPIO1_TSRH (GPIO_BASE1+0x14) -#define GPIO1_ODR (GPIO_BASE1+0x18) -#define GPIO1_IR (GPIO_BASE1+0x1C) -#define GPIO1_RR1 (GPIO_BASE1+0x20) -#define GPIO1_RR2 (GPIO_BASE1+0x24) -#define GPIO1_RR3 (GPIO_BASE1+0x28) -#define GPIO1_ISR1L (GPIO_BASE1+0x30) -#define GPIO1_ISR1H (GPIO_BASE1+0x34) -#define GPIO1_ISR2L (GPIO_BASE1+0x38) -#define GPIO1_ISR2H (GPIO_BASE1+0x3C) -#define GPIO1_ISR3L (GPIO_BASE1+0x40) -#define GPIO1_ISR3H (GPIO_BASE1+0x44) +#define GPIO0_BASE (CFG_PERIPHERAL_BASE+0x00000B00) +#define GPIO1_BASE (CFG_PERIPHERAL_BASE+0x00000C00) + +/* Offsets */ +#define GPIOx_OR 0x00 /* GPIO Output Register */ +#define GPIOx_TCR 0x04 /* GPIO Three-State Control Register */ +#define GPIOx_OSL 0x08 /* GPIO Output Select Register (Bits 0-31) */ +#define GPIOx_OSH 0x0C /* GPIO Ouput Select Register (Bits 32-63) */ +#define GPIOx_TSL 0x10 /* GPIO Three-State Select Register (Bits 0-31) */ +#define GPIOx_TSH 0x14 /* GPIO Three-State Select Register (Bits 32-63) */ +#define GPIOx_ODR 0x18 /* GPIO Open drain Register */ +#define GPIOx_IR 0x1C /* GPIO Input Register */ +#define GPIOx_RR1 0x20 /* GPIO Receive Register 1 */ +#define GPIOx_RR2 0x24 /* GPIO Receive Register 2 */ +#define GPIOx_RR3 0x28 /* GPIO Receive Register 3 */ +#define GPIOx_IS1L 0x30 /* GPIO Input Select Register 1 (Bits 0-31) */ +#define GPIOx_IS1H 0x34 /* GPIO Input Select Register 1 (Bits 32-63) */ +#define GPIOx_IS2L 0x38 /* GPIO Input Select Register 2 (Bits 0-31) */ +#define GPIOx_IS2H 0x3C /* GPIO Input Select Register 2 (Bits 32-63) */ +#define GPIOx_IS3L 0x40 /* GPIO Input Select Register 3 (Bits 0-31) */ +#define GPIOx_IS3H 0x44 /* GPIO Input Select Register 3 (Bits 32-63) */ + +#define GPIO_OS(x) (x+GPIOx_OSL) /* GPIO Output Register High or Low */ +#define GPIO_TS(x) (x+GPIOx_TSL) /* GPIO Three-state Control Reg High or Low */ +#define GPIO_IS1(x) (x+GPIOx_IS1L) /* GPIO Input register1 High or Low */ +#define GPIO_IS2(x) (x+GPIOx_IS2L) /* GPIO Input register2 High or Low */ +#define GPIO_IS3(x) (x+GPIOx_IS3L) /* GPIO Input register3 High or Low */ + +#define GPIO0_OR (GPIO0_BASE+0x0) +#define GPIO0_TCR (GPIO0_BASE+0x4) +#define GPIO0_OSRL (GPIO0_BASE+0x8) +#define GPIO0_OSRH (GPIO0_BASE+0xC) +#define GPIO0_TSRL (GPIO0_BASE+0x10) +#define GPIO0_TSRH (GPIO0_BASE+0x14) +#define GPIO0_ODR (GPIO0_BASE+0x18) +#define GPIO0_IR (GPIO0_BASE+0x1C) +#define GPIO0_RR1 (GPIO0_BASE+0x20) +#define GPIO0_RR2 (GPIO0_BASE+0x24) +#define GPIO0_RR3 (GPIO0_BASE+0x28) +#define GPIO0_ISR1L (GPIO0_BASE+0x30) +#define GPIO0_ISR1H (GPIO0_BASE+0x34) +#define GPIO0_ISR2L (GPIO0_BASE+0x38) +#define GPIO0_ISR2H (GPIO0_BASE+0x3C) +#define GPIO0_ISR3L (GPIO0_BASE+0x40) +#define GPIO0_ISR3H (GPIO0_BASE+0x44) + +#define GPIO1_OR (GPIO1_BASE+0x0) +#define GPIO1_TCR (GPIO1_BASE+0x4) +#define GPIO1_OSRL (GPIO1_BASE+0x8) +#define GPIO1_OSRH (GPIO1_BASE+0xC) +#define GPIO1_TSRL (GPIO1_BASE+0x10) +#define GPIO1_TSRH (GPIO1_BASE+0x14) +#define GPIO1_ODR (GPIO1_BASE+0x18) +#define GPIO1_IR (GPIO1_BASE+0x1C) +#define GPIO1_RR1 (GPIO1_BASE+0x20) +#define GPIO1_RR2 (GPIO1_BASE+0x24) +#define GPIO1_RR3 (GPIO1_BASE+0x28) +#define GPIO1_ISR1L (GPIO1_BASE+0x30) +#define GPIO1_ISR1H (GPIO1_BASE+0x34) +#define GPIO1_ISR2L (GPIO1_BASE+0x38) +#define GPIO1_ISR2H (GPIO1_BASE+0x3C) +#define GPIO1_ISR3L (GPIO1_BASE+0x40) +#define GPIO1_ISR3H (GPIO1_BASE+0x44) #endif +#define GPIO_GROUP_MAX 2 +#define GPIO_MAX 32 +#define GPIO_ALT1_SEL 0x40000000 /* GPIO_OUT value put in GPIO_TSx for the GPIO nb 0 */ +#define GPIO_ALT2_SEL 0x80000000 /* GPIO_OUT value put in GPIO_TSx for the GPIO nb 1 */ +#define GPIO_ALT3_SEL 0xC0000000 /* GPIO_OUT value put in GPIO_TSx for the GPIO nb 2 */ +#define GPIO_MASK 0xC0000000 /* GPIO_MASK */ +#define GPIO_IN_SEL 0x40000000 /* GPIO_IN value put in GPIO_ISx for the GPIO nb 0 */ + /* For the other GPIO number, you must shift */ + +#ifndef __ASSEMBLY__ + +typedef enum gpio_select { GPIO_SEL, GPIO_ALT1, GPIO_ALT2, GPIO_ALT3 } gpio_select_t; +typedef enum gpio_driver { GPIO_DIS, GPIO_IN, GPIO_OUT, GPIO_BI } gpio_driver_t; + +typedef struct { unsigned long add; /* gpio core base address */ + gpio_driver_t in_out; /* Driver Setting */ + gpio_select_t alt_nb; /* Selected Alternate */ +} gpio_param_s; + + +#endif /* __ASSEMBLY__ */ + /* * Macros for accessing the indirect EBC registers */ diff --git a/lib_arm/Makefile b/lib_arm/Makefile index de5e5dd..e56e06b 100644 --- a/lib_arm/Makefile +++ b/lib_arm/Makefile @@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk LIB = lib$(ARCH).a -AOBJS = _udivsi3.o _umodsi3.o +AOBJS = _ashldi3.o _ashrdi3.o _divsi3.o _modsi3.o _udivsi3.o _umodsi3.o COBJS = armlinux.o board.o \ cache.o div0.o diff --git a/lib_arm/_ashldi3.S b/lib_arm/_ashldi3.S new file mode 100644 index 0000000..de4403d --- /dev/null +++ b/lib_arm/_ashldi3.S @@ -0,0 +1,46 @@ +/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005 + Free Software Foundation, Inc. + +This file 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, or (at your option) any +later version. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file into combinations with other programs, +and to distribute those combinations without any restriction coming +from the use of this file. (The General Public License restrictions +do apply in other respects; for example, they cover modification of +the file, and distribution when not linked into a combine +executable.) + +This file 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; see the file COPYING. If not, write to +the Free Software Foundation, 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ + + +#ifdef __ARMEB__ +#define al r1 +#define ah r0 +#else +#define al r0 +#define ah r1 +#endif + +.globl __ashldi3 +__ashldi3: + + subs r3, r2, #32 + rsb ip, r2, #32 + movmi ah, ah, lsl r2 + movpl ah, al, lsl r3 + orrmi ah, ah, al, lsr ip + mov al, al, lsl r2 + mov pc, lr diff --git a/lib_arm/_ashrdi3.S b/lib_arm/_ashrdi3.S new file mode 100644 index 0000000..5edbcb3 --- /dev/null +++ b/lib_arm/_ashrdi3.S @@ -0,0 +1,46 @@ +/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005 + Free Software Foundation, Inc. + +This file 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, or (at your option) any +later version. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file into combinations with other programs, +and to distribute those combinations without any restriction coming +from the use of this file. (The General Public License restrictions +do apply in other respects; for example, they cover modification of +the file, and distribution when not linked into a combine +executable.) + +This file 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; see the file COPYING. If not, write to +the Free Software Foundation, 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ + + +#ifdef __ARMEB__ +#define al r1 +#define ah r0 +#else +#define al r0 +#define ah r1 +#endif + +.globl __ashrdi3 +__ashrdi3: + + subs r3, r2, #32 + rsb ip, r2, #32 + movmi al, al, lsr r2 + movpl al, ah, asr r3 + orrmi al, al, ah, lsl ip + mov ah, ah, asr r2 + mov pc, lr diff --git a/lib_arm/_divsi3.S b/lib_arm/_divsi3.S new file mode 100644 index 0000000..9dc15f6 --- /dev/null +++ b/lib_arm/_divsi3.S @@ -0,0 +1,140 @@ + +.macro ARM_DIV_BODY dividend, divisor, result, curbit + +#if __LINUX_ARM_ARCH__ >= 5 + + clz \curbit, \divisor + clz \result, \dividend + sub \result, \curbit, \result + mov \curbit, #1 + mov \divisor, \divisor, lsl \result + mov \curbit, \curbit, lsl \result + mov \result, #0 + +#else + + @ Initially shift the divisor left 3 bits if possible, + @ set curbit accordingly. This allows for curbit to be located + @ at the left end of each 4 bit nibbles in the division loop + @ to save one loop in most cases. + tst \divisor, #0xe0000000 + moveq \divisor, \divisor, lsl #3 + moveq \curbit, #8 + movne \curbit, #1 + + @ Unless the divisor is very big, shift it up in multiples of + @ four bits, since this is the amount of unwinding in the main + @ division loop. Continue shifting until the divisor is + @ larger than the dividend. +1: cmp \divisor, #0x10000000 + cmplo \divisor, \dividend + movlo \divisor, \divisor, lsl #4 + movlo \curbit, \curbit, lsl #4 + blo 1b + + @ For very big divisors, we must shift it a bit at a time, or + @ we will be in danger of overflowing. +1: cmp \divisor, #0x80000000 + cmplo \divisor, \dividend + movlo \divisor, \divisor, lsl #1 + movlo \curbit, \curbit, lsl #1 + blo 1b + + mov \result, #0 + +#endif + + @ Division loop +1: cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor + orrhs \result, \result, \curbit + cmp \dividend, \divisor, lsr #1 + subhs \dividend, \dividend, \divisor, lsr #1 + orrhs \result, \result, \curbit, lsr #1 + cmp \dividend, \divisor, lsr #2 + subhs \dividend, \dividend, \divisor, lsr #2 + orrhs \result, \result, \curbit, lsr #2 + cmp \dividend, \divisor, lsr #3 + subhs \dividend, \dividend, \divisor, lsr #3 + orrhs \result, \result, \curbit, lsr #3 + cmp \dividend, #0 @ Early termination? + movnes \curbit, \curbit, lsr #4 @ No, any more bits to do? + movne \divisor, \divisor, lsr #4 + bne 1b + +.endm + +.macro ARM_DIV2_ORDER divisor, order + +#if __LINUX_ARM_ARCH__ >= 5 + + clz \order, \divisor + rsb \order, \order, #31 + +#else + + cmp \divisor, #(1 << 16) + movhs \divisor, \divisor, lsr #16 + movhs \order, #16 + movlo \order, #0 + + cmp \divisor, #(1 << 8) + movhs \divisor, \divisor, lsr #8 + addhs \order, \order, #8 + + cmp \divisor, #(1 << 4) + movhs \divisor, \divisor, lsr #4 + addhs \order, \order, #4 + + cmp \divisor, #(1 << 2) + addhi \order, \order, #3 + addls \order, \order, \divisor, lsr #1 + +#endif + +.endm + + .align 5 +.globl __divsi3 +__divsi3: + cmp r1, #0 + eor ip, r0, r1 @ save the sign of the result. + beq Ldiv0 + rsbmi r1, r1, #0 @ loops below use unsigned. + subs r2, r1, #1 @ division by 1 or -1 ? + beq 10f + movs r3, r0 + rsbmi r3, r0, #0 @ positive dividend value + cmp r3, r1 + bls 11f + tst r1, r2 @ divisor is power of 2 ? + beq 12f + + ARM_DIV_BODY r3, r1, r0, r2 + + cmp ip, #0 + rsbmi r0, r0, #0 + mov pc, lr + +10: teq ip, r0 @ same sign ? + rsbmi r0, r0, #0 + mov pc, lr + +11: movlo r0, #0 + moveq r0, ip, asr #31 + orreq r0, r0, #1 + mov pc, lr + +12: ARM_DIV2_ORDER r1, r2 + + cmp ip, #0 + mov r0, r3, lsr r2 + rsbmi r0, r0, #0 + mov pc, lr + +Ldiv0: + + str lr, [sp, #-4]! + bl __div0 + mov r0, #0 @ About as wrong as it could be. + ldr pc, [sp], #4 diff --git a/lib_arm/_modsi3.S b/lib_arm/_modsi3.S new file mode 100644 index 0000000..539c584 --- /dev/null +++ b/lib_arm/_modsi3.S @@ -0,0 +1,99 @@ + +.macro ARM_MOD_BODY dividend, divisor, order, spare + +#if __LINUX_ARM_ARCH__ >= 5 + + clz \order, \divisor + clz \spare, \dividend + sub \order, \order, \spare + mov \divisor, \divisor, lsl \order + +#else + + mov \order, #0 + + @ Unless the divisor is very big, shift it up in multiples of + @ four bits, since this is the amount of unwinding in the main + @ division loop. Continue shifting until the divisor is + @ larger than the dividend. +1: cmp \divisor, #0x10000000 + cmplo \divisor, \dividend + movlo \divisor, \divisor, lsl #4 + addlo \order, \order, #4 + blo 1b + + @ For very big divisors, we must shift it a bit at a time, or + @ we will be in danger of overflowing. +1: cmp \divisor, #0x80000000 + cmplo \divisor, \dividend + movlo \divisor, \divisor, lsl #1 + addlo \order, \order, #1 + blo 1b + +#endif + + @ Perform all needed substractions to keep only the reminder. + @ Do comparisons in batch of 4 first. + subs \order, \order, #3 @ yes, 3 is intended here + blt 2f + +1: cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor + cmp \dividend, \divisor, lsr #1 + subhs \dividend, \dividend, \divisor, lsr #1 + cmp \dividend, \divisor, lsr #2 + subhs \dividend, \dividend, \divisor, lsr #2 + cmp \dividend, \divisor, lsr #3 + subhs \dividend, \dividend, \divisor, lsr #3 + cmp \dividend, #1 + mov \divisor, \divisor, lsr #4 + subges \order, \order, #4 + bge 1b + + tst \order, #3 + teqne \dividend, #0 + beq 5f + + @ Either 1, 2 or 3 comparison/substractions are left. +2: cmn \order, #2 + blt 4f + beq 3f + cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor + mov \divisor, \divisor, lsr #1 +3: cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor + mov \divisor, \divisor, lsr #1 +4: cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor +5: +.endm + + .align 5 +.globl __modsi3 +__modsi3: + cmp r1, #0 + beq Ldiv0 + rsbmi r1, r1, #0 @ loops below use unsigned. + movs ip, r0 @ preserve sign of dividend + rsbmi r0, r0, #0 @ if negative make positive + subs r2, r1, #1 @ compare divisor with 1 + cmpne r0, r1 @ compare dividend with divisor + moveq r0, #0 + tsthi r1, r2 @ see if divisor is power of 2 + andeq r0, r0, r2 + bls 10f + + ARM_MOD_BODY r0, r1, r2, r3 + +10: cmp ip, #0 + rsbmi r0, r0, #0 + mov pc, lr + + +Ldiv0: + + str lr, [sp, #-4]! + bl __div0 + mov r0, #0 @ About as wrong as it could be. + ldr pc, [sp], #4 diff --git a/lib_arm/board.c b/lib_arm/board.c index 1028b04..babc254 100644 --- a/lib_arm/board.c +++ b/lib_arm/board.c @@ -297,7 +297,7 @@ void start_armboot (void) mem_malloc_init (_armboot_start - CFG_MALLOC_LEN); #if (CONFIG_COMMANDS & CFG_CMD_NAND) - puts ("NAND:"); + puts ("NAND: "); nand_init(); /* go init the NAND */ #endif diff --git a/lib_generic/string.c b/lib_generic/string.c index 0e99d1b..e0b793a 100644 --- a/lib_generic/string.c +++ b/lib_generic/string.c @@ -21,7 +21,7 @@ #include -#ifndef __HAVE_ARCH_STRNICMP +#if 0 /* not used - was: #ifndef __HAVE_ARCH_STRNICMP */ /** * strnicmp - Case insensitive, length-limited string comparison * @s1: One string diff --git a/lib_m68k/board.c b/lib_m68k/board.c index e25833b..6aaf609 100644 --- a/lib_m68k/board.c +++ b/lib_m68k/board.c @@ -261,6 +261,7 @@ board_init_f (ulong bootflag) { bd_t *bd; ulong len, addr, addr_sp; + ulong *paddr; gd_t *id; init_fnc_t **init_fnc_ptr; #ifdef CONFIG_PRAM @@ -357,8 +358,12 @@ board_init_f (ulong bootflag) */ addr_sp -= 16; addr_sp &= ~0xF; - *((ulong *) addr_sp)-- = 0; - *((ulong *) addr_sp)-- = 0; + + paddr = (ulong *)addr_sp; + *paddr-- = 0; + *paddr-- = 0; + addr_sp = (ulong)paddr; + debug ("Stack Pointer at: %08lx\n", addr_sp); /* @@ -631,7 +636,7 @@ void board_init_r (gd_t *id, ulong dest_addr) #if (CONFIG_COMMANDS & CFG_CMD_NAND) WATCHDOG_RESET (); - puts ("NAND:"); + puts ("NAND: "); nand_init(); /* go init the NAND */ #endif diff --git a/lib_m68k/time.c b/lib_m68k/time.c index 1d6d297..d45e470 100644 --- a/lib_m68k/time.c +++ b/lib_m68k/time.c @@ -27,6 +27,11 @@ #include +#ifdef CONFIG_M5271 +#include +#include +#endif + #ifdef CONFIG_M5272 #include #include @@ -43,7 +48,7 @@ static ulong timestamp; -#ifdef CONFIG_M5282 +#if defined(CONFIG_M5282) || defined(CONFIG_M5271) static unsigned short lastinc; #endif @@ -127,7 +132,7 @@ void set_timer (ulong t) } #endif -#if defined(CONFIG_M5282) +#if defined(CONFIG_M5282) || defined(CONFIG_M5271) void udelay(unsigned long usec) { diff --git a/net/eth.c b/net/eth.c index 3039fc8..e8ac251 100644 --- a/net/eth.c +++ b/net/eth.c @@ -53,6 +53,7 @@ extern int rtl8169_initialize(bd_t*); extern int scc_initialize(bd_t*); extern int skge_initialize(bd_t*); extern int tsec_initialize(bd_t*, int, char *); +extern int npe_initialize(bd_t *); static struct eth_device *eth_devices, *eth_current; @@ -217,6 +218,9 @@ int eth_initialize(bd_t *bis) #if defined(CONFIG_AU1X00) au1x00_enet_initialize(bis); #endif +#if defined(CONFIG_IXP4XX_NPE) + npe_initialize(bis); +#endif #ifdef CONFIG_E1000 e1000_initialize(bis); #endif diff --git a/rtc/ds1306.c b/rtc/ds1306.c index e143bf7..e01e1ce 100644 --- a/rtc/ds1306.c +++ b/rtc/ds1306.c @@ -360,13 +360,13 @@ void rtc_set (struct rtc_time *tmp) tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec); - rtc_write (RTC_YEAR, bin2bcd (tmp->tm_year - 2000)); - rtc_write (RTC_MONTH, bin2bcd (tmp->tm_mon)); - rtc_write (RTC_DATE_OF_MONTH, bin2bcd (tmp->tm_mday)); - rtc_write (RTC_DAY_OF_WEEK, bin2bcd (tmp->tm_wday + 1)); - rtc_write (RTC_HOURS, bin2bcd (tmp->tm_hour)); - rtc_write (RTC_MINUTES, bin2bcd (tmp->tm_min)); rtc_write (RTC_SECONDS, bin2bcd (tmp->tm_sec)); + rtc_write (RTC_MINUTES, bin2bcd (tmp->tm_min)); + rtc_write (RTC_HOURS, bin2bcd (tmp->tm_hour)); + rtc_write (RTC_DAY_OF_WEEK, bin2bcd (tmp->tm_wday + 1)); + rtc_write (RTC_DATE_OF_MONTH, bin2bcd (tmp->tm_mday)); + rtc_write (RTC_MONTH, bin2bcd (tmp->tm_mon)); + rtc_write (RTC_YEAR, bin2bcd (tmp->tm_year - 2000)); } /* ------------------------------------------------------------------------- */ diff --git a/tools/mkimage.c b/tools/mkimage.c index 5222bb2..fea3e5b 100644 --- a/tools/mkimage.c +++ b/tools/mkimage.c @@ -277,7 +277,8 @@ NXTARG: ; */ if (xflag) { if (ep != addr + sizeof(image_header_t)) { - fprintf (stderr, "%s: For XIP, the entry point must be the load addr + %lu\n", + fprintf (stderr, + "%s: For XIP, the entry point must be the load addr + %lu\n", cmdname, (unsigned long)sizeof(image_header_t)); exit (EXIT_FAILURE); @@ -347,8 +348,9 @@ NXTARG: ; if (crc32 (0, data, len) != checksum) { fprintf (stderr, - "*** Warning: \"%s\" has bad header checksum!\n", - imagefile); + "%s: ERROR: \"%s\" has bad header checksum!\n", + cmdname, imagefile); + exit (EXIT_FAILURE); } data = (char *)(ptr + sizeof(image_header_t)); @@ -356,8 +358,9 @@ NXTARG: ; if (crc32 (0, data, len) != ntohl(hdr->ih_dcrc)) { fprintf (stderr, - "*** Warning: \"%s\" has corrupted data!\n", - imagefile); + "%s: ERROR: \"%s\" has corrupted data!\n", + cmdname, imagefile); + exit (EXIT_FAILURE); } /* for multi-file images we need the data part, too */