diff options
Diffstat (limited to 'cfe/cfe/arch/mips/board')
36 files changed, 16281 insertions, 0 deletions
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm63xx_util.h b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm63xx_util.h new file mode 100755 index 0000000..273b9c7 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm63xx_util.h @@ -0,0 +1,167 @@ +/*************************************************************************** + * Broadcom Corp. Confidential + * Copyright 2001, 2002 Broadcom Corp. All Rights Reserved. + * + * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED + * SOFTWARE LICENSE AGREEMENT BETWEEN THE USER AND BROADCOM. + * YOU HAVE NO RIGHT TO USE OR EXPLOIT THIS MATERIAL EXCEPT + * SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. + * + *************************************************************************** + * File Name : bcm63xx_util.h + * + * Created on : 04/18/2002 seanl + ***************************************************************************/ + +#if !defined(_BCM63XX_UTIL_H_) +#define _BCM63XX_UTIL_H_ + +#include "lib_types.h" +#include "lib_string.h" +#include "lib_queue.h" +#include "lib_malloc.h" +#include "lib_printf.h" +#include "cfe_iocb.h" +#include "cfe_device.h" +#include "cfe_console.h" +#include "cfe_devfuncs.h" +#include "cfe_timer.h" +#include "cfe_ioctl.h" +#include "cfe_error.h" +#include "env_subr.h" +#include "ui_command.h" +#include "cfe.h" +#include "net_ebuf.h" +#include "net_ether.h" +#include "net_api.h" +#include "cfe_fileops.h" +#include "bsp_config.h" +#include "cfe_mem.h" +#include "cfe_loader.h" +#include "addrspace.h" + +#include "dev_bcm63xx_flash.h" +#include "bcm_hwdefs.h" +#include "bcmTag.h" +#include "boardparms.h" +#include "boardparms_voice.h" +#include "bcm_map.h" + +extern unsigned long cfe_sdramsize; + +#define NAND_FLASH_BOOT_IMAGE_NAME "vmlinux.lz" + +#define BOARD_IMAGE_DOWNLOAD_ADDRESS \ + ((cfe_sdramsize > 0x00800000) ? 0x80800000 : 0x80000000) +#define BOARD_IMAGE_DOWNLOAD_SIZE \ + ((cfe_sdramsize > 0x00800000) ? cfe_sdramsize - 0x00800000 : 0x00400000) + +#define MAX_PROMPT_LEN 50 // assume no one wants to type more than 50 chars +#define MAX_MAC_STR_LEN 19 // mac address string 18+1 in regular format +#define PROMPT_DEFINE_LEN 2 +#define MASK_LEN 8 // vxworks like ffffff00 + +typedef struct +{ + char* promptName; + char* errorPrompt; + char promptDefine[PROMPT_DEFINE_LEN]; + char parameter[MAX_PROMPT_LEN]; + int maxValueLength; + int (*func)(char *); + int enabled; +} PARAMETER_SETTING, *PPARAMETER_SETTING; + +#define IP_PROMPT "Invalid ip address. eg. 192.168.1.200[:ffffff00]" +#define RUN_FROM_PROMPT "f = jump to flash; h = tftpd from host" +#define HOST_FN_PROMPT "eg. vmlinux" +#define FLASH_FN_PROMPT "eg. bcm963xx_fs_kernel" +#define BOOT_DELAY_PROMPT "range 0-9, 0=forever prompt" +#define BOOT_PARTITION_PROMPT "1 = latest image, 2 = previous image" +#define AFE_PROMPT "Invalid AFE ID eg. 0x10608100" + +// error input prompts +#define BOARDID_STR_PROMPT "Invalid board ID" +#define MAC_CT_PROMPT "Invalid MAC addresses number: 1 - 32" +#define MAC_ADDR_PROMPT "Invalid MAC address format: eg. 12:34:56:ab:cd:ef or 123456abcdef" +#define PSI_SIZE_PROMPT "Invalid PSI size: (1-64) Kbytes" +#define BACKUP_PSI_PROMPT "Enable Backup PSI (0 or 1)" +#define SYSLOG_SIZE_PROMPT "Invalid System Log size: (0-256) Kbytes" +#define CPU_TP_PROMPT "Invalid thread number: [0|1]" +#define GPON_SN_PROMPT "Invalid GPON Serial Number" +#define GPON_PW_PROMPT "Invalid GPON Password" +#define WPS_DEVICE_PIN_PROMPT "Invalid WPS Device Pin" + +// bootline definition: +// Space is the deliminator of the parameters. Currently supports following parameters: +// t=xxx.xxx.xxx.xxx h=xxx.xxx.xxx.xxx g=xxx.xxx.xxx.xxx r=f/h (run from flash or host) +// f=vmlinux (if r=h) i=bcm963xx_fs_kernel d=3 (default delay, range 0-9, 0=forever prompt) + +#define BOOT_IP_LEN 18 // "t=xxx.xxx.xxx.xxx" +#define BOOT_FILENAME_LEN 50 // "f=vmlinux" + +typedef struct +{ + char boardIp[BOOT_IP_LEN]; + char boardMask[BOOT_IP_LEN]; // set for the board only and ignore for the host/gw. fmt :ffffff00 + char hostIp[BOOT_IP_LEN]; + char gatewayIp[BOOT_IP_LEN]; + char runFrom; + char hostFileName[BOOT_FILENAME_LEN]; + char flashFileName[BOOT_FILENAME_LEN]; + int bootDelay; + char bootPartition; +} BOOT_INFO, *PBOOT_INFO; + +#define LED_OFF 0 +#define LED_ON 1 + +extern void getBootLine(void); +extern void setDefaultBootline(void); +extern int printSysInfo(void); +extern int changeBootLine(void); +extern int changeAfeId(void); +extern void dumpHex(unsigned char *start, int len); +extern BOOT_INFO bootInfo; +extern void enet_init(void); +extern int verifyTag(PFILE_TAG pTag, int verbose); +extern int flashImage(unsigned char *ptr); +extern int writeWholeImage(unsigned char *ptr, int size); + +/* Foxconn add start by Cliff Wang, 03/23/2010 */ +extern int bcm63xx_run(int breakIntoCfe); +/* Foxconn add end by Cliff Wang, 03/23/2010 */ + +extern int getPartitionFromTag( PFILE_TAG pTag ); +extern PFILE_TAG getTagFromPartition(int imageNumber); +extern PFILE_TAG getBootImageTag(void); +extern int parsexdigit(char str); +extern int setDefaultBoardParam(void); /* Bob added to set default board parameters, 11/01/2010 */ +extern int setBoardParam(void); +extern int setGponBoardParam(void); +extern int setWpsDevicePinBoardParam(void); +extern int setVoiceBoardParam(void); +extern int getBoardParam(void); +extern void displayBoardParam(void); +extern int processPrompt(PPARAMETER_SETTING promptPtr, int promptCt); +extern UINT32 getCrc32(unsigned char *pdata, UINT32 size, UINT32 crc); +extern int yesno(void); +extern int bcm63xx_cfe_rawload(cfe_loadargs_t *la); +extern int bcm63xx_cfe_elfload(cfe_loadargs_t *la); +extern void setGpio (unsigned short led_gpio, unsigned short led_state); +extern void setLed ( unsigned short led, unsigned short led_state ); +extern void setAllLedsOff(void); +extern void setPowerOnLedOn(void); +extern void setBreakIntoCfeLed(void); +extern void softReset(void); +extern void validateNandPartTbl(PNVRAM_DATA pNvramData); +extern void writeNvramData(PNVRAM_DATA pNvramData); +extern int readNvramData(PNVRAM_DATA pNvramData); + +/* Foxconn add start by Jenny Zhao, 07/02/2008*/ +extern int nmrp_led_toggle(void); +extern int power_led_toggle(int state); +extern int verify_board_id(char *buf); +/* Foxconn add end by Jenny Zhao, 07/02/2008*/ +#endif // _BCM63XX_UTIL_H_ + diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm_common.h b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm_common.h new file mode 100755 index 0000000..136267a --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm_common.h @@ -0,0 +1,32 @@ +/* +<:copyright-broadcom + + Copyright (c) 2004 Broadcom Corporation + All Rights Reserved + No portions of this material may be reproduced in any form without the + written permission of: + Broadcom Corporation + 16215 Alton Parkway + Irvine, California 92619 + All information contained in this document is Broadcom Corporation + company private, proprietary, and trade secret. + +:> +*/ +#ifndef __BCM_COMMON_H +#define __BCM_COMMON_H + +#if defined (_BCM96328_) +#include "6328_common.h" +#endif +#if defined (_BCM96362_) +#include "6362_common.h" +#endif +#if defined (_BCM96368_) +#include "6368_common.h" +#endif +#if defined (_BCM96816_) +#include "6816_common.h" +#endif + +#endif diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm_cpu.h b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm_cpu.h new file mode 100755 index 0000000..e033936 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm_cpu.h @@ -0,0 +1,32 @@ +/* +<:copyright-broadcom + + Copyright (c) 2004 Broadcom Corporation + All Rights Reserved + No portions of this material may be reproduced in any form without the + written permission of: + Broadcom Corporation + 16215 Alton Parkway + Irvine, California 92619 + All information contained in this document is Broadcom Corporation + company private, proprietary, and trade secret. + +:> +*/ +#ifndef __BCM_CPU_H +#define __BCM_CPU_H + +#if defined (_BCM96328_) +#include "6328_cpu.h" +#endif +#if defined (_BCM96362_) +#include "6362_cpu.h" +#endif +#if defined (_BCM96368_) +#include "6368_cpu.h" +#endif +#if defined (_BCM96816_) +#include "6816_cpu.h" +#endif + +#endif diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm_map.h b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm_map.h new file mode 100755 index 0000000..0383431 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm_map.h @@ -0,0 +1,32 @@ +/* +<:copyright-broadcom + + Copyright (c) 2004 Broadcom Corporation + All Rights Reserved + No portions of this material may be reproduced in any form without the + written permission of: + Broadcom Corporation + 16215 Alton Parkway + Irvine, California 92619 + All information contained in this document is Broadcom Corporation + company private, proprietary, and trade secret. + +:> +*/ +#ifndef __BCM_MAP_H +#define __BCM_MAP_H + +#if defined (_BCM96328_) +#include "6328_map.h" +#endif +#if defined (_BCM96362_) +#include "6362_map.h" +#endif +#if defined (_BCM96368_) +#include "6368_map.h" +#endif +#if defined (_BCM96816_) +#include "6816_map.h" +#endif + +#endif diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcmmii.h b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcmmii.h new file mode 100755 index 0000000..a33de5c --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcmmii.h @@ -0,0 +1,164 @@ +/* +<:copyright-broadcom + + Copyright (c) 2004 Broadcom Corporation + All Rights Reserved + No portions of this material may be reproduced in any form without the + written permission of: + Broadcom Corporation + 16215 Alton Parkway + Irvine, California 92619 + All information contained in this document is Broadcom Corporation + company private, proprietary, and trade secret. + +:> +*/ +#ifndef _BCMMII_H_ +#define _BCMMII_H_ + +#include "dev_bcm63xx_eth.h" + +/*---------------------------------------------------------------------*/ +/* Broadcom PHY MII register address */ +/* use when PhyType is BP_ENET_INTERNAL_PHY */ +/*---------------------------------------------------------------------*/ +#define BCM_PHY_ID_M 0x1F +#define IsExtPhyId(id) ((id & BCM_PHY_ID_M) >= 0x10) +//#define BCM_WAN_PORT 0x40 +//#define IsWanPort(id) (((id) & BCM_WAN_PORT) && ((id) != 0xFF)) + +#define MII_ASR 0x19 +#define MII_INTERRUPT 0x1A +#define MII_RESERVED_1B 0x1B +#define MII_BRCM_TEST 0x1F + +/* MII ASR register. */ +#define MII_ASR_DONE(r) ((r & 0x8000) != 0) +#define MII_ASR_LINK(r) ((r & 0x0004) != 0) +#define MII_ASR_FDX(r) (((r & 0x0700) == 0x0700) || ((r & 0x0700) == 0x0500) || ((r & 0x0700) == 0x0200)) +#define MII_ASR_1000(r) (((r & 0x0700) == 0x0700) || ((r & 0x0700) == 0x0600)) +#define MII_ASR_100(r) (((r & 0x0700) == 0x0500) || ((r & 0x0700) == 0x0300)) +#define MII_ASR_10(r) (((r & 0x0700) == 0x0200) || ((r & 0x0700) == 0x0100)) + +/* Reserved 0x1B register */ +#define MII_RESERVED_1B_ACT_LED 0x0004 + +/* Broadcom Test register. */ +#define MII_BRCM_TEST_SHADOW2_ENABLE 0x0004 + +/* MII Interrupt register. */ +#define MII_INTR_ENABLE 0x4000 + +#define BCM54610_PHYID2 0xBD63 +#define BCM_PHYID_M 0xFFF0 + +#define MII_REGISTER_1C 0x1c + #define MII_1C_WRITE_ENABLE (1 << 15) + #define MII_1C_SHADOW_REG_SEL_S 10 + #define MII_1C_SHADOW_REG_SEL_M 0x1F +#define MII_1C_SHADOW_CLK_ALIGN_CTRL 0x3 + #define GTXCLK_DELAY_BYPASS_DISABLE (1 << 9) +#define MII_1C_SHADOW_LED_CONTROL 0x9 + #define ACT_LINK_LED_ENABLE (1 << 4) +#define MII_1C_EXTERNAL_CONTROL_1 0xB + #define LOM_LED_MODE (1 << 2) + +#define PAGE_CONTROL 0x00 +#define PAGE_SELECT 0xff +#define PAGE_MANAGEMENT 0x02 + +/* Control page registers */ +#define REG_MII_PORT_CONTROL 0x08 +#define REG_SWITCH_MODE 0x0b +#define REG_CONTROL_MII1_PORT_STATE_OVERRIDE 0x0e +#define REG_POWER_DOWN_MODE 0x0f + +/* MII Port Control Register, Page 0x00 Address 0x08 */ +#define REG_MII_PORT_CONTROL_RX_UCST_EN 0x10 +#define REG_MII_PORT_CONTROL_RX_MCST_EN 0x08 +#define REG_MII_PORT_CONTROL_RX_BCST_EN 0x04 + +/* Switch mode register, Page 0x00 Address 0x0b */ +#define REG_SWITCH_MODE_FRAME_MANAGE_MODE 0x01 +#define REG_SWITCH_MODE_SW_FWDG_EN 0x02 + +/* MII1 Port State Override Register Page 0x00 Address 0x0e */ +#define REG_CONTROL_MPSO_MII_SW_OVERRIDE 0x80 +#define REG_CONTROL_MPSO_REVERSE_MII 0x10 +#define REG_CONTROL_MPSO_LP_FLOW_CONTROL 0x08 +#define REG_CONTROL_MPSO_SPEED100 0x04 +#define REG_CONTROL_MPSO_SPEED1000 0x08 +#define REG_CONTROL_MPSO_FDX 0x02 +#define REG_CONTROL_MPSO_LINKPASS 0x01 + +/* Power down mode register Page 0x00 Address 0x0f */ +#define REG_POWER_DOWN_MODE_PORT1_PHY_DISABLE 0x01 +#define REG_POWER_DOWN_MODE_PORT2_PHY_DISABLE 0x02 +#define REG_POWER_DOWN_MODE_PORT3_PHY_DISABLE 0x04 +#define REG_POWER_DOWN_MODE_PORT4_PHY_DISABLE 0x08 +#define REG_POWER_DOWN_MODE_PORT5_PHY_DISABLE 0x10 + +/* Switch control register page 0x0 */ +#define REG_SWITCH_CONTROL 0x20 +#define REG_SWITCH_CONTROL_MII_DUMP_FWD_EN 0x1 + +/* Device ID register page 0x02 */ +#define REG_DEVICE_ID 0x30 +#define REG_GLOBAL_CONFIG 0x00 +#define REG_BRCM_HDR_CTRL 0x03 + +/* Global Configuration Regiater Page 0x02 Address 0x00 */ +#define ENABLE_MII_PORT 0x80 + +/* Broadcom Header Control Register Page 0x02 Address 0x03*/ +#define REG_BRCM_HDR_ENABLE 0x01 + + + +/*---------------------------------------------------------------------*/ +/* 5325 Switch SPI Interface */ +/* use when configuration type is BP_ENET_CONFIG_SPI_SSB_x */ +/*---------------------------------------------------------------------*/ +#define BCM5325_SPI_CMD_LEN 1 +#define BCM5325_SPI_ADDR_LEN 1 +#define BCM5325_SPI_PREPENDCNT (BCM5325_SPI_CMD_LEN+BCM5325_SPI_ADDR_LEN) + +/* 5325 SPI Status Register */ +#define BCM5325_SPI_STS 0xfe + +/* 5325 SPI Status Register definition */ +#define BCM5325_SPI_CMD_RACK 0x20 + +/* 5325 Command Byte definition */ +#define BCM5325_SPI_CMD_READ 0x00 /* bit 0 - Read/Write */ +#define BCM5325_SPI_CMD_WRITE 0x01 /* bit 0 - Read/Write */ +#define BCM5325_SPI_CHIPID_MASK 0x7 /* bit 3:1 - Chip ID */ +#define BCM5325_SPI_CHIPID_SHIFT 1 +#define BCM5325_SPI_CMD_NORMAL 0x60 /* bit 7:4 - Mode */ +#define BCM5325_SPI_CMD_FAST 0x10 /* bit 4 - Mode */ + +/*---------------------------------------------------------------------*/ +/* 5325 Switch Pseudo PHY MII Register */ +/* use when configuration type is BP_ENET_CONFIG_MDIO_PSEUDO_PHY */ +/*---------------------------------------------------------------------*/ +#define PSEUDO_PHY_ADDR 0x1e /* Pseduo PHY address */ + +/* Pseudo PHY MII registers */ +#define REG_PSEUDO_PHY_MII_REG16 0x10 /* register 16 - Switch Register Set Access Control Register */ +#define REG_PSEUDO_PHY_MII_REG17 0x11 /* register 17 - Switch Register Set Read/Write Control Register */ +#define REG_PSEUDO_PHY_MII_REG24 0x18 /* register 24 - Switch Accesss Register bit 15:0 */ +#define REG_PSEUDO_PHY_MII_REG25 0x19 /* register 25 - Switch Accesss Register bit 31:16 */ +#define REG_PSEUDO_PHY_MII_REG26 0x20 /* register 26 - Switch Accesss Register bit 47:32 */ +#define REG_PSEUDO_PHY_MII_REG27 0x21 /* register 27 - Switch Accesss Register bit 63:48 */ + +/*Pseudo PHY MII register 16 Switch Register Set Access Control Register */ +#define REG_PPM_REG16_SWITCH_PAGE_NUMBER_SHIFT 8 /* bit 8..15 - switch page number */ +#define REG_PPM_REG16_MDIO_ENABLE 0x01 /* bit 0 - set MDC/MDIO access enable */ + +/*Pseudo PHY MII register 17 Switch Register Set Read/Write Control Register */ +#define REG_PPM_REG17_REG_NUMBER_SHIFT 8 /* bit 8..15 - switch register number */ +#define REG_PPM_REG17_OP_DONE 0x00 /* bit 0..1 - no operation */ +#define REG_PPM_REG17_OP_WRITE 0x01 /* bit 0..1 - write operation */ +#define REG_PPM_REG17_OP_READ 0x02 /* bit 0..1 - read operation */ + +#endif /* _BCMMII_H_ */ diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcmtypes.h b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcmtypes.h new file mode 100755 index 0000000..9359663 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcmtypes.h @@ -0,0 +1,144 @@ +// +// bcmtypes.h - misc useful typedefs +// +#ifndef BCMTYPES_H +#define BCMTYPES_H + +// These are also defined in typedefs.h in the application area, so I need to +// protect against re-definition. + +#ifndef _TYPEDEFS_H_ +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned long uint32; +typedef unsigned long long uint64; +typedef signed char int8; +typedef signed short int16; +typedef signed long int32; +typedef signed long long int64; +#if !defined(__cplusplus) +typedef int bool; +#endif +#endif + +typedef unsigned char byte; +typedef unsigned long sem_t; + +typedef unsigned long HANDLE,*PULONG,DWORD,*PDWORD; +typedef signed long LONG,*PLONG; + +typedef unsigned int *PUINT; +typedef signed int INT; + +typedef unsigned short *PUSHORT; +typedef signed short SHORT,*PSHORT,WORD,*PWORD; + +typedef unsigned char *PUCHAR; +typedef signed char *PCHAR; + +typedef void *PVOID; + +typedef unsigned char BOOLEAN, *PBOOL, *PBOOLEAN; + +typedef unsigned char BYTE,*PBYTE; + +//#ifndef __GNUC__ +//The following has been defined in Vxworks internally: vxTypesOld.h +//redefine under vxworks will cause error +typedef signed int *PINT; + +typedef signed char INT8; +typedef signed short INT16; +typedef signed long INT32; + +typedef unsigned char UINT8; +typedef unsigned short UINT16; +typedef unsigned long UINT32; + +typedef unsigned char UCHAR; +typedef unsigned short USHORT; +typedef unsigned int UINT; +typedef unsigned long ULONG; + +typedef void VOID; +typedef unsigned char BOOL; + +//#endif /* __GNUC__ */ + + +// These are also defined in typedefs.h in the application area, so I need to +// protect against re-definition. +#ifndef TYPEDEFS_H + +#define MAX_INT16 32767 +#define MIN_INT16 -32768 + +// Useful for true/false return values. This uses the +// Taligent notation (k for constant). +typedef enum +{ + kFalse = 0, + kTrue = 1 +} Bool; + +#endif + +/* macros to protect against unaligned accesses */ + +#if 0 +/* first arg is an address, second is a value */ +#define PUT16( a, d ) { \ + *((byte *)a) = (byte)((d)>>8); \ + *(((byte *)a)+1) = (byte)(d); \ +} + +#define PUT32( a, d ) { \ + *((byte *)a) = (byte)((d)>>24); \ + *(((byte *)a)+1) = (byte)((d)>>16); \ + *(((byte *)a)+2) = (byte)((d)>>8); \ + *(((byte *)a)+3) = (byte)(d); \ +} + +/* first arg is an address, returns a value */ +#define GET16( a ) ( \ + (*((byte *)a) << 8) | \ + (*(((byte *)a)+1)) \ +) + +#define GET32( a ) ( \ + (*((byte *)a) << 24) | \ + (*(((byte *)a)+1) << 16) | \ + (*(((byte *)a)+2) << 8) | \ + (*(((byte *)a)+3)) \ +) +#endif + +#ifndef YES +#define YES 1 +#endif + +#ifndef NO +#define NO 0 +#endif + +#ifndef IN +#define IN +#endif + +#ifndef OUT +#define OUT +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define READ32(addr) (*(volatile UINT32 *)((ULONG)&addr)) +#define READ16(addr) (*(volatile UINT16 *)((ULONG)&addr)) +#define READ8(addr) (*(volatile UINT8 *)((ULONG)&addr)) + +#endif diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bsp_config.h b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bsp_config.h new file mode 100755 index 0000000..57e51bb --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bsp_config.h @@ -0,0 +1,94 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * BSP Configuration file File: bsp_config.h + * + * This module contains global parameters and conditional + * compilation settings for building CFE. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + +#define CFG_CMT 1 + +#define CFG_INIT_L1 1 /* initialize the L1 cache */ +#define CFG_INIT_L2 0 /* there is no L2 cache */ + +#define CFG_INIT_DRAM 1 /* initialize DRAM controller */ +#define CFG_DRAM_SIZE xxx /* size of DRAM if you don't initialize */ + /* NOTE : Size is in kilobytes. */ + +#define CFG_NETWORK 1 /* define to include network support */ + +#define CFG_FATFS 0 +#define CFG_UI 1 /* Define to enable user interface */ + +#define CFG_MULTI_CPUS 0 /* no multi-cpu support */ + +#define CFG_HEAP_SIZE 1024 /* heap size in kilobytes */ + +#define CFG_STACK_SIZE 8192 /* stack size (bytes, rounded up to K) */ + +#define CFG_SERIAL_BAUD_RATE 115200 /* normal console speed */ + +#define CFG_VENDOR_EXTENSIONS 0 +#define CFG_MINIMAL_SIZE 1 + +/* + * These parameters control the flash driver's sector buffer. + * If you write environment variables or make small changes to + * flash sectors from user applications, you + * need to have the heap big enough to store a temporary sector + * for merging in small changes to flash sectors, so you + * should set CFG_FLASH_ALLOC_SECTOR_BUFFER in that case. + * Otherwise, you can provide an address in unallocated memory + * of where to place the sector buffer. + */ + +#define CFG_FLASH_ALLOC_SECTOR_BUFFER 0 /* '1' to allocate sector buffer from the heap */ +#define CFG_FLASH_SECTOR_BUFFER_ADDR (1*1024*1024-128*1024) /* 1MB - 128K */ +#define CFG_FLASH_SECTOR_BUFFER_SIZE (128*1024) + +/* + * The flash staging buffer is where we store a flash image before we write + * it to the flash. It's too big for the heap. + */ + +#define CFG_FLASH_STAGING_BUFFER_ADDR (1*1024*1024) +#define CFG_FLASH_STAGING_BUFFER_SIZE (1*1024*1024) diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/include/dev_bcm63xx_eth.h b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/dev_bcm63xx_eth.h new file mode 100755 index 0000000..7432231 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/dev_bcm63xx_eth.h @@ -0,0 +1,127 @@ +/* +<:copyright-broadcom + + Copyright (c) 2002 Broadcom Corporation + All Rights Reserved + No portions of this material may be reproduced in any form without the + written permission of: + Broadcom Corporation + 16215 Alton Parkway + Irvine, California 92619 + All information contained in this document is Broadcom Corporation + company private, proprietary, and trade secret. + +:> +*/ +#ifndef __BCM63XX_ETH_H +#define __BCM63XX_ETH_H + +#include "bcm_hwdefs.h" +#include "bcm_map.h" +#include "boardparms.h" + +// from linux if_ether.h +#define ETH_ALEN 6 /* Octets in one ethernet addr */ +#define ETH_HLEN 14 /* Total octets in header. */ +#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */ +#define ETH_DATA_LEN 1500 /* Max. octets in payload */ +#define ETH_CRC_LEN 4 /* CRC length */ +// end if_ether.h + +/*---------------------------------------------------------------------*/ +/* specify number of BDs and buffers to use */ +/*---------------------------------------------------------------------*/ +#define NR_TX_BDS 20 +#define NR_RX_BDS 20 +#define ENET_MAX_MTU_SIZE 1522 /* Body(1500) + EH_SIZE(14) + FCS(4) + VLAN(4) */ +#define DMA_MAX_BURST_LENGTH 8 /* in 64 bit words */ +#define ENET_BUF_SIZE ((ENET_MAX_MTU_SIZE + 63) & ~63) +#define DMA_FC_THRESH_LO 5 +#define DMA_FC_THRESH_HI 10 +#define EMAC_TX_WATERMARK 32 + +#define MAKE4(x) ((x[3] & 0xFF) | ((x[2] & 0xFF) << 8) | ((x[1] & 0xFF) << 16) | ((x[0] & 0xFF) << 24)) +#define MAKE2(x) ((x[1] & 0xFF) | ((x[0] & 0xFF) << 8)) + + +#define ERROR(x) xsprintf x +#ifndef ASSERT +#define ASSERT(x) if (x); else ERROR(("assert: "__FILE__" line %d\n", __LINE__)); +#endif + +//#define DUMP_TRACE + +#if defined(DUMP_TRACE) +#define TRACE (x) xprintf x +#else +#define TRACE(x) +#endif + +typedef struct PM_Addr { + uint16 valid; /* 1 indicates the corresponding address is valid */ + unsigned char dAddr[ETH_ALEN];/* perfect match register's destination address */ + unsigned int ref; /* reference count */ +} PM_Addr; +#define MAX_PMADDR 4 /* # of perfect match address */ + +#define NUM_PORTS 1 + +typedef struct gpio_reg_addrs_t { + volatile uint16 *gpio_direction_reg;/* GPIO direction register */ + volatile uint16 *gpio_value_reg; /* GPIO value register */ +} gpio_reg_addrs_t; + +typedef struct ethsw_info_t { + gpio_reg_addrs_t sbh; + uint32 ssl, clk, mosi, miso; /* GPIO mapping */ + int cid, page; /* Current chip ID and page */ +} ethsw_info_t; + +typedef struct bcmenet_softc { + + volatile DmaRegs *dmaCtrl; + + /* transmit variables */ + volatile DmaChannelCfg *txDma; /* location of transmit DMA register set */ + volatile DmaDesc *txBds; /* Memory location of tx Dma BD ring */ + volatile DmaDesc *txFirstBdPtr; /* ptr to first allocated Tx BD */ + volatile DmaDesc *txNextBdPtr; /* ptr to next Tx BD to transmit with */ + volatile DmaDesc *txLastBdPtr; /* ptr to last allocated Tx BD */ + + /* receive variables */ + volatile DmaChannelCfg *rxDma; /* location of receive DMA register set */ + volatile DmaDesc *rxBds; /* Memory location of rx bd ring */ + volatile DmaDesc *rxFirstBdPtr; /* ptr to first allocated rx bd */ + volatile DmaDesc *rxBdReadPtr; /* ptr to next rx bd to be processed */ + volatile DmaDesc *rxLastBdPtr; /* ptr to last allocated rx bd */ + + uint32_t rxBuffers; + uint32_t txBuffers; + + uint16 chipId; /* chip's id */ + uint16 chipRev; /* step */ + uint8_t hwaddr[ETH_ALEN]; + ethsw_info_t ethSwitch; /* external switch */ + ETHERNET_MAC_INFO EnetInfo; + uint32_t dmaPort; + uint32_t linkCheck; +} bcmenet_softc; + + + +#define IncRxBdPtr(x, s) if (x == ((bcmenet_softc *)s)->rxLastBdPtr) \ + x = ((bcmenet_softc *)s)->rxBds; \ + else x++ +#define InctxBdPtr(x, s) if (x == ((bcmenet_softc *)s)->txLastBdPtr) \ + x = ((bcmenet_softc *)s)->txBds; \ + else x++ + +// extern and function prototype + +extern int32_t _getticks(void); + +#ifdef DUMP_DATA +static void hexdump( unsigned char * src, int srclen, int rowlen, int rows ); +#endif + +#endif // __BCM63XX_ETH_H diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/include/dev_bcm63xx_flash.h b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/dev_bcm63xx_flash.h new file mode 100755 index 0000000..d8e7f1d --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/dev_bcm63xx_flash.h @@ -0,0 +1,38 @@ +/*************************************************************************** + * Broadcom Corp. Confidential + * Copyright 2001 Broadcom Corp. All Rights Reserved. + * + * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED + * SOFTWARE LICENSE AGREEMENT BETWEEN THE USER AND BROADCOM. + * YOU HAVE NO RIGHT TO USE OR EXPLOIT THIS MATERIAL EXCEPT + * SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. + * + *************************************************************************** + * File Name : dev_bcm63xx_flash.h + * + * Created on : 04/18/2002 seanl + ***************************************************************************/ + +#if !defined(_DEV_BCM63XX_FLASH_) +#define _DEV_BCM63XX_FLASH_ + +#include "bcmtypes.h" +#include "bcm_hwdefs.h" + +// Used for images that do not contain a FILE_TAG record. +#define FLASH_IMAGE_START_ADDR (FLASH_BASE + FLASH_LENGTH_BOOT_ROM) + +// FLASH_ADDR_INFO is now defined in flash_common.h +#include "flash_common.h" + +extern void kerSysFlashInit(void); +extern void kerSysFlashAddrInfoGet(PFLASH_ADDR_INFO pflash_addr_info); +extern int kerSysNvRamSet(unsigned char *string,int strLen,int offset); +extern int kerSysNvRamGet(unsigned char *string,int strLen,int offset); +extern int kerSysBcmImageSet( int flash_start_addr, unsigned char *string, int size, int fWholeImage); +extern int kerSysErasePsi(void); +extern int kerSysEraseNvRam(void); +extern unsigned long kerSysReadFromFlash(void *toaddr, unsigned long fromaddr, unsigned long len); + +#endif /* _DEV_BCM63XX_FLASH_ */ + diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/include/jffs2.h b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/jffs2.h new file mode 100755 index 0000000..586fb55 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/jffs2.h @@ -0,0 +1,251 @@ +/* + * JFFS2 -- Journalling Flash File System, Version 2. + * + * Copyright (C) 2001-2003 Red Hat, Inc. + * + * Created by David Woodhouse <dwmw2@infradead.org> + * + * For licensing information, see the file 'LICENCE' in the + * jffs2 directory. + * + * $Id: jffs2.h,v 1.38 2005/09/26 11:37:23 havasi Exp $ + * + */ + +#ifndef __LINUX_JFFS2_H__ +#define __LINUX_JFFS2_H__ + +//include <linux/magic.h> + +/* You must include something which defines the C99 uintXX_t types. + We don't do it from here because this file is used in too many + different environments. */ + +/* Values we may expect to find in the 'magic' field */ +#define JFFS2_OLD_MAGIC_BITMASK 0x1984 +#define JFFS2_MAGIC_BITMASK 0x1985 +#define KSAMTIB_CIGAM_2SFFJ 0x8519 /* For detecting wrong-endian fs */ +#define JFFS2_EMPTY_BITMASK 0xffff +#define JFFS2_DIRTY_BITMASK 0x0000 + +#if defined(CONFIG_MTD_BRCMNAND) +/* JFFS2 eraseblock header compat/incompat/rocompat features set */ +#define JFFS2_EBH_COMPAT_FSET 0x00 +#define JFFS2_EBH_INCOMPAT_FSET 0x00 +#define JFFS2_EBH_ROCOMPAT_FSET 0x00 +#endif + +/* Summary node MAGIC marker */ +#define JFFS2_SUM_MAGIC 0x02851885 + +/* We only allow a single char for length, and 0xFF is empty flash so + we don't want it confused with a real length. Hence max 254. +*/ +#define JFFS2_MAX_NAME_LEN 254 + +/* How small can we sensibly write nodes? */ +#define JFFS2_MIN_DATA_LEN 128 + +#define JFFS2_COMPR_NONE 0x00 +#define JFFS2_COMPR_ZERO 0x01 +#define JFFS2_COMPR_RTIME 0x02 +#define JFFS2_COMPR_RUBINMIPS 0x03 +#define JFFS2_COMPR_COPY 0x04 +#define JFFS2_COMPR_DYNRUBIN 0x05 +#define JFFS2_COMPR_ZLIB 0x06 +/* Compatibility flags. */ +#define JFFS2_COMPAT_MASK 0xc000 /* What do to if an unknown nodetype is found */ +#define JFFS2_NODE_ACCURATE 0x2000 +/* INCOMPAT: Fail to mount the filesystem */ +#define JFFS2_FEATURE_INCOMPAT 0xc000 +/* ROCOMPAT: Mount read-only */ +#define JFFS2_FEATURE_ROCOMPAT 0x8000 +/* RWCOMPAT_COPY: Mount read/write, and copy the node when it's GC'd */ +#define JFFS2_FEATURE_RWCOMPAT_COPY 0x4000 +/* RWCOMPAT_DELETE: Mount read/write, and delete the node when it's GC'd */ +#define JFFS2_FEATURE_RWCOMPAT_DELETE 0x0000 + +#define JFFS2_NODETYPE_DIRENT (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 1) +#define JFFS2_NODETYPE_INODE (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 2) +#define JFFS2_NODETYPE_CLEANMARKER (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3) +#define JFFS2_NODETYPE_PADDING (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 4) + +#define JFFS2_NODETYPE_SUMMARY (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 6) + +#define JFFS2_NODETYPE_XATTR (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 8) +#define JFFS2_NODETYPE_XREF (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 9) + +#if defined(CONFIG_MTD_BRCMNAND) +#define JFFS2_NODETYPE_ERASEBLOCK_HEADER (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 5) +#endif + +/* XATTR Related */ +#define JFFS2_XPREFIX_USER 1 /* for "user." */ +#define JFFS2_XPREFIX_SECURITY 2 /* for "security." */ +#define JFFS2_XPREFIX_ACL_ACCESS 3 /* for "system.posix_acl_access" */ +#define JFFS2_XPREFIX_ACL_DEFAULT 4 /* for "system.posix_acl_default" */ +#define JFFS2_XPREFIX_TRUSTED 5 /* for "trusted.*" */ + +#define JFFS2_ACL_VERSION 0x0001 + +// Maybe later... +//#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3) +//#define JFFS2_NODETYPE_OPTIONS (JFFS2_FEATURE_RWCOMPAT_COPY | JFFS2_NODE_ACCURATE | 4) + + +#define JFFS2_INO_FLAG_PREREAD 1 /* Do read_inode() for this one at + mount time, don't wait for it to + happen later */ +#define JFFS2_INO_FLAG_USERCOMPR 2 /* User has requested a specific + compression type */ + + +/* These can go once we've made sure we've caught all uses without + byteswapping */ + +typedef struct { + uint32_t v32; +} __attribute__((packed)) jint32_t; + +typedef struct { + uint32_t m; +} __attribute__((packed)) jmode_t; + +typedef struct { + uint16_t v16; +} __attribute__((packed)) jint16_t; + +struct jffs2_unknown_node +{ + /* All start like this */ + jint16_t magic; + jint16_t nodetype; + jint32_t totlen; /* So we can skip over nodes we don't grok */ + jint32_t hdr_crc; +}; + +struct jffs2_raw_dirent +{ + jint16_t magic; + jint16_t nodetype; /* == JFFS2_NODETYPE_DIRENT */ + jint32_t totlen; + jint32_t hdr_crc; + jint32_t pino; + jint32_t version; + jint32_t ino; /* == zero for unlink */ + jint32_t mctime; + uint8_t nsize; + uint8_t type; + uint8_t unused[2]; + jint32_t node_crc; + jint32_t name_crc; + uint8_t name[0]; +}; + +/* The JFFS2 raw inode structure: Used for storage on physical media. */ +/* The uid, gid, atime, mtime and ctime members could be longer, but + are left like this for space efficiency. If and when people decide + they really need them extended, it's simple enough to add support for + a new type of raw node. +*/ +struct jffs2_raw_inode +{ + jint16_t magic; /* A constant magic number. */ + jint16_t nodetype; /* == JFFS2_NODETYPE_INODE */ + jint32_t totlen; /* Total length of this node (inc data, etc.) */ + jint32_t hdr_crc; + jint32_t ino; /* Inode number. */ + jint32_t version; /* Version number. */ + jmode_t mode; /* The file's type or mode. */ + jint16_t uid; /* The file's owner. */ + jint16_t gid; /* The file's group. */ + jint32_t isize; /* Total resultant size of this inode (used for truncations) */ + jint32_t atime; /* Last access time. */ + jint32_t mtime; /* Last modification time. */ + jint32_t ctime; /* Change time. */ + jint32_t offset; /* Where to begin to write. */ + jint32_t csize; /* (Compressed) data size */ + jint32_t dsize; /* Size of the node's data. (after decompression) */ + uint8_t compr; /* Compression algorithm used */ + uint8_t usercompr; /* Compression algorithm requested by the user */ + jint16_t flags; /* See JFFS2_INO_FLAG_* */ + jint32_t data_crc; /* CRC for the (compressed) data. */ + jint32_t node_crc; /* CRC for the raw inode (excluding data) */ + uint8_t data[0]; +}; + +struct jffs2_raw_xattr { + jint16_t magic; + jint16_t nodetype; /* = JFFS2_NODETYPE_XATTR */ + jint32_t totlen; + jint32_t hdr_crc; + jint32_t xid; /* XATTR identifier number */ + jint32_t version; + uint8_t xprefix; + uint8_t name_len; + jint16_t value_len; + jint32_t data_crc; + jint32_t node_crc; + uint8_t data[0]; +} __attribute__((packed)); + +struct jffs2_raw_xref +{ + jint16_t magic; + jint16_t nodetype; /* = JFFS2_NODETYPE_XREF */ + jint32_t totlen; + jint32_t hdr_crc; + jint32_t ino; /* inode number */ + jint32_t xid; /* XATTR identifier number */ + jint32_t xseqno; /* xref sequencial number */ + jint32_t node_crc; +} __attribute__((packed)); + +struct jffs2_raw_summary +{ + jint16_t magic; + jint16_t nodetype; /* = JFFS2_NODETYPE_SUMMARY */ + jint32_t totlen; + jint32_t hdr_crc; + jint32_t sum_num; /* number of sum entries*/ + jint32_t cln_mkr; /* clean marker size, 0 = no cleanmarker */ + jint32_t padded; /* sum of the size of padding nodes */ + jint32_t sum_crc; /* summary information crc */ + jint32_t node_crc; /* node crc */ + jint32_t sum[0]; /* inode summary info */ +}; + +#if defined(CONFIG_MTD_BRCMNAND) +struct jffs2_raw_ebh +{ + jint16_t magic; + jint16_t nodetype; /* == JFFS2_NODETYPE_ERASEBLOCK_HEADER */ + jint32_t totlen; + jint32_t hdr_crc; + jint32_t node_crc; + uint8_t reserved; /* reserved for future use and alignment */ + uint8_t compat_fset; + uint8_t incompat_fset; + uint8_t rocompat_fset; + jint32_t erase_count; /* the erase count of this erase block */ + jint32_t data[0]; +} __attribute__((packed)); +#endif + +union jffs2_node_union +{ + struct jffs2_raw_inode i; + struct jffs2_raw_dirent d; + struct jffs2_raw_xattr x; + struct jffs2_raw_xref r; + struct jffs2_raw_summary s; + struct jffs2_unknown_node u; +}; + +/* Data payload for device nodes. */ +union jffs2_device_node { + jint16_t old; + jint32_t new; +}; + +#endif /* __LINUX_JFFS2_H__ */ diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/Makefile b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/Makefile new file mode 100755 index 0000000..7320c9d --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/Makefile @@ -0,0 +1,55 @@ +BSPOBJS += \ + dev_bcm63xx_eth.o \ + dev_bcm63xx_uart.o \ + dev_bcm63xx_flash.o \ + flash_api.o \ + flash_common.o \ + bcm63xx_ram_boot.o \ + bcm63xx_devs.o \ + bcm63xx_board.o \ + bcm63xx_cmd.o \ + bcm63xx_util.o \ + bcm63xx_ldr_raw.o \ + bcm63xx_ldr_elf.o \ + bcm63xx_main.o \ + bcm63xx_env_subr.o \ + bcm63xx_net_icmp.o \ + bcm63xx_httpd.o \ + bcmSpiRes.o \ + bcmLegSpi.o \ + boardparms.o \ + boardparms_voice.o + +ifneq ($(strip $(BRCM_CHIP)),6368) +BSPOBJS += \ + bcmHsSpi.o +endif + +BSPOBJS += \ + robosw_reg.o + +ifeq ($(strip ${INC_CFI_FLASH_DRIVER}),1) +BSPOBJS += \ + cfiflash.o +endif + +ifeq ($(strip ${INC_SPI_FLASH_DRIVER}),1) +BSPOBJS += \ + spiflash.o +endif + +ifeq ($(strip ${INC_SPI_PROG_NAND}),1) +BSPOBJS += \ + nandflash.o +endif + +ifeq ($(strip ${INC_NAND_FLASH_DRIVER}),1) +BSPOBJS += \ + nandflash.o +endif + +ifeq ($(strip ${CFG_WEB_SERVER}),1) +BSPOBJS += \ + ul.o \ + ulinfo.o +endif diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_board.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_board.c new file mode 100755 index 0000000..5baa66c --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_board.c @@ -0,0 +1,830 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * bcm63xx_board.c utility functions for bcm63xx board + * + * Created on : 09/25/2002 seanl + * + ********************************************************************* + +<:copyright-broadcom + + Copyright (c) 2002 Broadcom Corporation + All Rights Reserved + No portions of this material may be reproduced in any form without the + written permission of: + Broadcom Corporation + 16215 Alton Parkway + Irvine, California 92619 + All information contained in this document is Broadcom Corporation + company private, proprietary, and trade secret. + +:> +*/ + +#include "bcm63xx_util.h" +#include "foxconnCfg.h" + +#define MAX_BOARD_ID_NAMES 16 +#define MAX_VOICE_BOARD_ID_NAMES 20 + +static char g_boardIdNames[BP_BOARD_ID_LEN * MAX_BOARD_ID_NAMES]; +static int g_numBoardIdNames = 0; + +static char g_voiceBoardIdNames[BP_BOARD_ID_LEN * MAX_VOICE_BOARD_ID_NAMES]; +static int g_numVoiceBoardIdNames = 0; + +static int parsehwaddr(char *, uint8_t *); +static int parseBoardIdStr(char *); +static int parseVoiceBoardIdStr(char *); +static int parsePsiSize(char *); +static int parseBackupPsi(char *tpStr); +static int parseSyslogSize(char *tpStr); +static int parseMainTp(char *); +static int parseMacAddrCount(char *); +static int parseMacAddr(char *); +static int charIsHex(char ch); +static int parseGponSN(char *snStr); +static int parseGponPW(char *pwStr); +static int macNumToStr(unsigned char *, char *); +static void getGponBoardParam(void); +static int gponParamsInitialized(NVRAM_DATA *pNvramData); + +static int parseWpsDevicePin(char *pinStr); +static void getWpsDevicePinBoardParam(void); +#define PARAM_IDX_BOARD_NAME 0 +#define PARAM_IDX_NUM_MAC_ADDR 1 +#define PARAM_IDX_BASE_MAC_ADDR 2 +#define PARAM_IDX_PSI_SIZE 3 +#define PARAM_IDX_ENABLE_BACKUP_PSI 4 +#define PARAM_IDX_SYSLOG_SIZE 5 +#define PARAM_IDX_MAIN_THREAD_NUM 6 + +#define PARAM_IDX_GPON_SN 0 +#define PARAM_IDX_GPON_PW 1 + +#define PARAM_IDX_WPS_DEVICE_PIN 0 + +#define PARAM_IDX_VOICE_BOARD_NAME 0 + +static PARAMETER_SETTING gBoardParam[] = +{ + // prompt name Error Prompt Define Param Validation function + {"Board Id (0-# :", BOARDID_STR_PROMPT, "", "", 2, + parseBoardIdStr, TRUE}, + {"Number of MAC Addresses (1-32) :", MAC_CT_PROMPT, "", "", 2, + parseMacAddrCount, TRUE}, + {"Base MAC Address :", MAC_ADDR_PROMPT, "", "", 17, + parseMacAddr, TRUE}, + {"PSI Size (1-64) KBytes :", PSI_SIZE_PROMPT, "", "", 2, + parsePsiSize, TRUE}, + {"Enable Backup PSI [0|1] :", BACKUP_PSI_PROMPT, "", "", 1, + parseBackupPsi, TRUE}, + {"System Log Size (0-256) KBytes :", SYSLOG_SIZE_PROMPT, "", "", 3, + parseSyslogSize, TRUE}, + {"Main Thread Number [0|1] :", CPU_TP_PROMPT, "", "", 1, + parseMainTp, TRUE}, + {NULL} +}; + +static int gNumBoardParams = (sizeof(gBoardParam) / sizeof(PARAMETER_SETTING))-1; + +static PARAMETER_SETTING gGponBoardParam[] = +{ + // prompt name Error Prompt Define Param Validation function + {"GPON Serial Number :", GPON_SN_PROMPT, "", "", 12, + parseGponSN, TRUE}, + {"GPON Password :", GPON_PW_PROMPT, "", "", 10, + parseGponPW, TRUE}, + {NULL} +}; + +static int gNumGponBoardParams = (sizeof(gGponBoardParam) / sizeof(PARAMETER_SETTING))-1; +static int gGponParamsInitialized = 0; + + +static PARAMETER_SETTING gWpsDevicePinBoardParam[] = +{ + // prompt name Error Prompt Define Param Validation function + {"Device Pin :", WPS_DEVICE_PIN_PROMPT, "", "", 8, + parseWpsDevicePin, TRUE}, + {NULL} +}; + +static int gNumWpsDevicePinBoardParams = (sizeof(gWpsDevicePinBoardParam) / sizeof(PARAMETER_SETTING))-1; +static int gWpsDevicePinInitialized = 0; + +static PARAMETER_SETTING gVoiceBoardParam[] = +{ + // prompt name Error Prompt Define Param Validation function + {"Voice Board Configuration (0-# :", BOARDID_STR_PROMPT, "", "", 2, + parseVoiceBoardIdStr, FALSE}, + {NULL} +}; + +static int gNumVoiceBoardParams = (sizeof(gVoiceBoardParam) / sizeof(PARAMETER_SETTING))-1; +static int gVoiceParamsInitialized = 0; + + +static int parsehwaddr(char *str,uint8_t *hwaddr) +{ + int digit1,digit2; + int idx = 6; + + if (strlen(str) == (MAX_MAC_STR_LEN - 7)) { // no ':' mac input format ie. 021800100801 + while (*str && (idx > 0)) { + digit1 = parsexdigit(*str); + if (digit1 < 0) + return -1; + str++; + if (!*str) + return -1; + digit2 = parsexdigit(*str); + if (digit2 < 0) + return -1; + *hwaddr++ = (digit1 << 4) | digit2; + idx--; + str++; + } + return 0; + } + + if (strlen(str) != MAX_MAC_STR_LEN-2) + return -1; + if (*(str+2) != ':' || *(str+5) != ':' || *(str+8) != ':' || *(str+11) != ':' || *(str+14) != ':') + return -1; + + while (*str && (idx > 0)) { + digit1 = parsexdigit(*str); + if (digit1 < 0) + return -1; + str++; + if (!*str) + return -1; + + if (*str == ':') { + digit2 = digit1; + digit1 = 0; + } + else { + digit2 = parsexdigit(*str); + if (digit2 < 0) + return -1; + str++; + } + + *hwaddr++ = (digit1 << 4) | digit2; + idx--; + + if (*str == ':') + str++; + } + return 0; +} + + +static int parseMacAddr(char * macStr) +{ + unsigned char tmpBuf[MAX_PROMPT_LEN]; + + return (parsehwaddr(macStr, tmpBuf)); +} + + +static int parseBoardIdStr(char *boardIdStr) +{ + int ret = 1; + int boardId; + + if (strlen (boardIdStr) != 0) { + boardId = atoi(boardIdStr); + if (boardId >= 0 && boardId < g_numBoardIdNames) + ret = 0; + } + + return ret; +} + + +static int parseVoiceBoardIdStr(char *boardIdStr) +{ + int ret = 1; + int boardId; + + if (strlen (boardIdStr) != 0) { + boardId = atoi(boardIdStr); + if (boardId >= 0 && boardId < g_numVoiceBoardIdNames) + ret = 0; + } + + return ret; +} + + +static int parseMacAddrCount(char *ctStr) +{ + int count = atoi(ctStr); + + if (count >= 1 && count <= NVRAM_MAC_COUNT_MAX) + return 0; + else + return 1; +} + +static int parsePsiSize(char *tpStr) +{ + int psiSize = atoi(tpStr); + + if (psiSize >= 1 && psiSize <= NVRAM_MAX_PSI_SIZE) + return 0; + else + return 1; +} + +static int parseBackupPsi(char *tpStr) +{ + int enable = atoi(tpStr); + + if (enable == 0 || enable == 1) + return 0; + else + return 1; +} + +static int parseSyslogSize(char *tpStr) +{ + int syslogSize = atoi(tpStr); + + if (syslogSize >= 0 && syslogSize <= NVRAM_MAX_SYSLOG_SIZE) + return 0; + else + return 1; +} + + +static int parseMainTp(char *tpStr) +{ + int tpNum = atoi(tpStr); + + if (tpNum == 0 || tpNum == 1) + return 0; + else + return 1; +} + +static int charIsHex(char ch) +{ + if (((ch >= '0') && (ch <= '9')) || + ((ch >= 'a') && (ch <= 'f')) || + ((ch >= 'A') && (ch <= 'F'))) + return 1; + else + return 0; +} + +static int parseGponSN(char *snStr) +{ + int i; + int ret = 0; + + if(strlen(snStr) == NVRAM_GPON_SERIAL_NUMBER_LEN-1) { + for(i=4; i<NVRAM_GPON_SERIAL_NUMBER_LEN-1; ++i) { + if(!charIsHex(snStr[i])) { + ret = 1; + break; + } + } + } + else { + ret = 1; + } + + return ret; +} + +static int parseGponPW(char *pwStr) +{ + if(strlen(pwStr) == NVRAM_GPON_PASSWORD_LEN-1) + return 0; + else + return 1; +} + +static int parseWpsDevicePin(char *pinStr) +{ + unsigned char accum=0; + unsigned char factor[NVRAM_WPS_DEVICE_PIN_LEN]={3,1,3,1,3,1,3,1}; + int i =0; + + /*Check Length*/ + if(strlen(pinStr) != NVRAM_WPS_DEVICE_PIN_LEN) + return 1; + + /*valid checksum*/ + for ( i=0; i< NVRAM_WPS_DEVICE_PIN_LEN; i++ ) + accum += (pinStr[i]-'0')*factor[i]; + + if ( (accum%10) ==0 ) + return 0; + + return 1; +} + +int macNumToStr(unsigned char *macAddr, char *str) +{ + if (macAddr == NULL || str == NULL) + return 0; + + sprintf(str, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", + macAddr[0], macAddr[1], macAddr[2], + macAddr[3], macAddr[4], macAddr[5]); + return 1; +} + +static int gponParamsInitialized(NVRAM_DATA *pNvramData) +{ + int i; + int erased = 1; + + for(i=0; i<NVRAM_GPON_SERIAL_NUMBER_LEN-1; ++i) { + if((pNvramData->gponSerialNumber[i] != (char)0xFF) && + (pNvramData->gponSerialNumber[i] != '\0')) { + erased = 0; + break; + } + } + + if(erased) { + for(i=0; i<NVRAM_GPON_PASSWORD_LEN-1; ++i) { + if((pNvramData->gponPassword[i] != (char)0xFF) && + (pNvramData->gponPassword[i] != '\0')) { + erased = 0; + break; + } + } + } + + return (erased) ? 0 : 1; +} + +static void getGponBoardParam(void) +{ + NVRAM_DATA nvramData; + int erased; + int i; + int writeNvram = 0; + + readNvramData(&nvramData); + + erased = 1; + for(i=0; i<NVRAM_GPON_SERIAL_NUMBER_LEN-1; ++i) { + if((nvramData.gponSerialNumber[i] != (char)0xFF) && + (nvramData.gponSerialNumber[i] != '\0')) { + erased = 0; + break; + } + } + + if(erased) { + strcpy(nvramData.gponSerialNumber, DEFAULT_GPON_SN); + writeNvram = 1; + } + + erased = 1; + for(i=0; i<NVRAM_GPON_PASSWORD_LEN-1; ++i) { + if((nvramData.gponPassword[i] != (char)0xFF) && + (nvramData.gponPassword[i] != '\0')) { + erased = 0; + break; + } + } + + if(erased) { + strcpy(nvramData.gponPassword, DEFAULT_GPON_PW); + writeNvram = 1; + } + + if(writeNvram) { + writeNvramData(&nvramData); + } + + strcpy(gGponBoardParam[PARAM_IDX_GPON_SN].parameter, nvramData.gponSerialNumber); + strcpy(gGponBoardParam[PARAM_IDX_GPON_PW].parameter, nvramData.gponPassword); +} + +int setGponBoardParam(void) +{ + NVRAM_DATA nvramData; + int ret = 0; + + getGponBoardParam(); + + readNvramData(&nvramData); + + if (processPrompt(gGponBoardParam, gNumGponBoardParams)) { + + // At least one field was changed + strcpy(nvramData.gponSerialNumber, gGponBoardParam[PARAM_IDX_GPON_SN].parameter); + strcpy(nvramData.gponPassword, gGponBoardParam[PARAM_IDX_GPON_PW].parameter); + + // save the buf to nvram + writeNvramData(&nvramData); + ret = 1; + } + + return ret; +} + + + +static int gWpsDevicePinParamsInitialized(NVRAM_DATA *pNvramData) +{ + int i; + + for(i=0; i<NVRAM_WPS_DEVICE_PIN_LEN; ++i) { + if(( (unsigned char)(pNvramData->wpsDevicePin[i]) > 0x39) || + ( (unsigned char)(pNvramData->wpsDevicePin[i]) < 0x30) ) { + return 0; + } + } + + return 1; +} + +static void getWpsDevicePinBoardParam(void) +{ + NVRAM_DATA nvramData; + + readNvramData(&nvramData); + + if ( gWpsDevicePinParamsInitialized( &nvramData) ) { + memcpy(gWpsDevicePinBoardParam[PARAM_IDX_WPS_DEVICE_PIN].parameter, + nvramData.wpsDevicePin, NVRAM_WPS_DEVICE_PIN_LEN); + (gWpsDevicePinBoardParam[PARAM_IDX_WPS_DEVICE_PIN].parameter)[NVRAM_WPS_DEVICE_PIN_LEN] = + '\0'; + } + else { + /*Set Default Device Pin*/ + memcpy(nvramData.wpsDevicePin, DEFAULT_WPS_DEVICE_PIN, NVRAM_WPS_DEVICE_PIN_LEN); + writeNvramData(&nvramData); + + memcpy(gWpsDevicePinBoardParam[PARAM_IDX_WPS_DEVICE_PIN].parameter, + nvramData.wpsDevicePin, + NVRAM_WPS_DEVICE_PIN_LEN); + (gWpsDevicePinBoardParam[PARAM_IDX_WPS_DEVICE_PIN].parameter)[NVRAM_WPS_DEVICE_PIN_LEN] = + '\0'; + } + +} + +int setWpsDevicePinBoardParam(void) +{ + NVRAM_DATA nvramData; + int ret = 0; + + getWpsDevicePinBoardParam(); + + readNvramData(&nvramData); + + if (processPrompt(gWpsDevicePinBoardParam, gNumWpsDevicePinBoardParams)) { + memcpy(nvramData.wpsDevicePin, + gWpsDevicePinBoardParam[PARAM_IDX_WPS_DEVICE_PIN].parameter, + NVRAM_WPS_DEVICE_PIN_LEN); + // save the buf to nvram + writeNvramData(&nvramData); + ret = 1; + } + + return ret; +} + + +static int voiceParamsInitialized(NVRAM_DATA *pNvramData) +{ + int rc = 0; + NVRAM_DATA nvramData; + readNvramData(&nvramData); + + if ( BpSetBoardId(nvramData.szBoardId) == BP_SUCCESS ) { + if ( BpGetVoipDspConfig( 0 ) == NULL ) { + gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].enabled = FALSE; + } + else { + gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].enabled = TRUE; + rc = 1; + } + } + + return rc; +} + +static void getVoiceBoardParam(void) +{ + NVRAM_DATA nvramData; + char *ptr; + char tmp[10]; + + if (g_numVoiceBoardIdNames == 0) + g_numVoiceBoardIdNames = BpGetVoiceBoardIds(g_voiceBoardIdNames, MAX_VOICE_BOARD_ID_NAMES); + + ptr = strchr(gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].promptName, '#'); + if (ptr != NULL) { + sprintf(tmp, "%d)", g_numVoiceBoardIdNames - 1); + memcpy(ptr, tmp, strlen(tmp)); + } + + readNvramData(&nvramData); + + memcpy(gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].parameter, nvramData.szVoiceBoardId, NVRAM_BOARD_ID_STRING_LEN); + gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].parameter[NVRAM_BOARD_ID_STRING_LEN] = '\0'; +} + +int setVoiceBoardParam(void) +{ + NVRAM_DATA nvramData; + char voiceBoardIdPrompt[1000]; + int i; + char tmp[3]; + char *voiceBoardIdPromptPtr, *savedVoiceBoardIdPromptPtr; + int ret = 0; + + getVoiceBoardParam(); + + readNvramData(&nvramData); + + // Create prompt string with voice board ID name selection + voiceBoardIdPromptPtr = voiceBoardIdPrompt; + for (i = 0; i < g_numVoiceBoardIdNames; i++) { + sprintf (tmp, "%d", i); + sprintf (voiceBoardIdPromptPtr, "%-17s-- %2s\n", &g_voiceBoardIdNames[i * BP_BOARD_ID_LEN], tmp); + voiceBoardIdPromptPtr += strlen(voiceBoardIdPromptPtr); + } + strcpy (voiceBoardIdPromptPtr, gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].promptName); + + // Save existing prompt string + savedVoiceBoardIdPromptPtr = gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].promptName; + // Set newly created prompt string + gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].promptName = voiceBoardIdPrompt; + + // Convert board ID string to numeric value + for (i = 0; i < g_numVoiceBoardIdNames; i++) { + if (!strcmp(gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].parameter, &g_voiceBoardIdNames[i * BP_BOARD_ID_LEN])) { + sprintf(gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].parameter, "%d", i); + } + } + + if (processPrompt(gVoiceBoardParam, gNumVoiceBoardParams)) { + // At least one field was changed + i = atoi(gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].parameter); + strcpy(nvramData.szVoiceBoardId, &g_voiceBoardIdNames[i * BP_BOARD_ID_LEN]); + + // save the buf to nvram + writeNvramData(&nvramData); + ret = 1; + } + + // Convert numeric value of voice board ID to string + gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].promptName = savedVoiceBoardIdPromptPtr; + i = atoi(gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].parameter); + strcpy(gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].parameter, &g_voiceBoardIdNames[i * BP_BOARD_ID_LEN]); + + return ret; +} + + +// +// getBoardParam: convert the board param data and put them in the gBoardParam struct +// +int getBoardParam(void) +{ + NVRAM_DATA nvramData; + char *ptr; + char tmp[10]; + int ret = 0; + + if (g_numBoardIdNames == 0) + g_numBoardIdNames = BpGetBoardIds(g_boardIdNames, MAX_BOARD_ID_NAMES); + + ptr = strchr(gBoardParam[PARAM_IDX_BOARD_NAME].promptName, '#'); + if (ptr != NULL) { + sprintf(tmp, "%d)", g_numBoardIdNames - 1); + memcpy(ptr, tmp, strlen(tmp)); + } + + readNvramData(&nvramData); + + if(!gGponParamsInitialized) { + gGponParamsInitialized = gponParamsInitialized(&nvramData); + } + + /*WPS Device Pin Initialized?*/ + if(!gWpsDevicePinInitialized) { + gWpsDevicePinInitialized = gWpsDevicePinParamsInitialized(&nvramData); + } + + if (nvramData.ulVersion == -1) { + // Set default values + nvramData.ulVersion = NVRAM_VERSION_NUMBER; + nvramData.szBoardId[0] = '\0'; + nvramData.ulNumMacAddrs = DEFAULT_MAC_NUM; + parsehwaddr(DEFAULT_BOARD_MAC, nvramData.ucaBaseMacAddr); + nvramData.ulMainTpNum = DEFAULT_TP_NUM; + nvramData.szVoiceBoardId[0] = '\0'; + nvramData.ulPsiSize = DEFAULT_PSI_SIZE; + nvramData.backupPsi = 0; + nvramData.ulSyslogSize = 0; + writeNvramData(&nvramData); + } + else if (nvramData.ulVersion != NVRAM_VERSION_NUMBER) { + // When upgrading from older bootloader initialize new fields + printf("*** Upgrading NVRAM (version %d to version %d) ***\n\n", + nvramData.ulVersion, NVRAM_VERSION_NUMBER); + nvramData.ulVersion = NVRAM_VERSION_NUMBER; + if (nvramData.ulMainTpNum == -1) + nvramData.ulMainTpNum = DEFAULT_TP_NUM; + if ((nvramData.ulPsiSize == -1) || (nvramData.ulPsiSize == 0)) + nvramData.ulPsiSize = DEFAULT_PSI_SIZE; + nvramData.szVoiceBoardId[0] = '\0'; + if (nvramData.backupPsi == -1) + nvramData.backupPsi = 0; + if (nvramData.ulSyslogSize == -1) + nvramData.ulSyslogSize = 0; + writeNvramData(&nvramData); + ret = 1; + } + + gVoiceParamsInitialized = voiceParamsInitialized(&nvramData); + + // When backupPsi and syslog were introduced, the NVRAM version number + // was not bumped up. So convert -1 (unitialized) to 0 so it looks better. + if (nvramData.backupPsi == -1) + nvramData.backupPsi = 0; + if (nvramData.ulSyslogSize == -1) + nvramData.ulSyslogSize = 0; + + strcpy(gBoardParam[PARAM_IDX_BOARD_NAME].parameter, nvramData.szBoardId); + sprintf(gBoardParam[PARAM_IDX_NUM_MAC_ADDR].parameter, "%d", nvramData.ulNumMacAddrs); + macNumToStr(nvramData.ucaBaseMacAddr, gBoardParam[PARAM_IDX_BASE_MAC_ADDR].parameter); + sprintf(gBoardParam[PARAM_IDX_PSI_SIZE].parameter, "%d", nvramData.ulPsiSize); + sprintf(gBoardParam[PARAM_IDX_ENABLE_BACKUP_PSI].parameter, "%d", nvramData.backupPsi); + sprintf(gBoardParam[PARAM_IDX_SYSLOG_SIZE].parameter, "%d", nvramData.ulSyslogSize); + sprintf(gBoardParam[PARAM_IDX_MAIN_THREAD_NUM].parameter, "%d", nvramData.ulMainTpNum); + + return ret; +} + +/* Bob added start to set default board parameters, 11/01/2010 */ +int setDefaultBoardParam(void) +{ + NVRAM_DATA nvramData; + int ret = 0; + + if (getBoardParam()) { + /* New NVRAM version */ + return ret; + } + + readNvramData(&nvramData); + + { + // At least one field was changed + nvramData.ulVersion = NVRAM_VERSION_NUMBER; + strcpy(nvramData.szBoardId, "963281TAN"); + strcpy(nvramData.szFirmwareUpgradeBoardId, FOXCONN_BOARD_ID); + nvramData.ulNumMacAddrs = 10; + parsehwaddr("00:00:00:00:00:01", nvramData.ucaBaseMacAddr); + nvramData.ulPsiSize = 24; + nvramData.backupPsi = 0; + nvramData.ulSyslogSize = 0; + nvramData.ulMainTpNum = 0; + + // save the buf to nvram + writeNvramData(&nvramData); + ret = 1; + } + + return ret; +} +/* Bob added end to set default board parameters, 11/01/2010 */ + +// +// setBoardParam: Set the board Id string, mac addresses, psi size, etc... +// +int setBoardParam(void) +{ + char boardIdPrompt[1000]; + NVRAM_DATA nvramData; + int i; + char tmp[3]; + char *boardIdPromptPtr, *savedBoardIdPromptPtr; + int ret = 0; + + if (getBoardParam()) { + /* New NVRAM version */ + return ret; + } + + readNvramData(&nvramData); + + // Create prompt string with board ID name selection + boardIdPromptPtr = boardIdPrompt; + for (i = 0; i < g_numBoardIdNames; i++) { + sprintf (tmp, "%d", i); + sprintf (boardIdPromptPtr, "%-17s------- %2s\n", &g_boardIdNames[i * BP_BOARD_ID_LEN], tmp); + boardIdPromptPtr += strlen(boardIdPromptPtr); + } + strcpy (boardIdPromptPtr, gBoardParam[PARAM_IDX_BOARD_NAME].promptName); + + // Save existing prompt string + savedBoardIdPromptPtr = gBoardParam[PARAM_IDX_BOARD_NAME].promptName; + // Set newly created prompt string + gBoardParam[PARAM_IDX_BOARD_NAME].promptName = boardIdPrompt; + + // Convert board ID string to numeric value + for (i = 0; i < g_numBoardIdNames; i++) { + if (!strcmp(gBoardParam[PARAM_IDX_BOARD_NAME].parameter, &g_boardIdNames[i * BP_BOARD_ID_LEN])) { + sprintf(gBoardParam[PARAM_IDX_BOARD_NAME].parameter, "%d", i); + } + } + + if (processPrompt(gBoardParam, gNumBoardParams)) { + // At least one field was changed + nvramData.ulVersion = NVRAM_VERSION_NUMBER; + + // Convert numeric value of board ID to string + i = atoi(gBoardParam[PARAM_IDX_BOARD_NAME].parameter); + strcpy(nvramData.szBoardId, &g_boardIdNames[i * BP_BOARD_ID_LEN]); + + nvramData.ulNumMacAddrs = atoi(gBoardParam[PARAM_IDX_NUM_MAC_ADDR].parameter); + parsehwaddr(gBoardParam[PARAM_IDX_BASE_MAC_ADDR].parameter, nvramData.ucaBaseMacAddr); + nvramData.ulPsiSize = atoi(gBoardParam[PARAM_IDX_PSI_SIZE].parameter); + nvramData.backupPsi = atoi(gBoardParam[PARAM_IDX_ENABLE_BACKUP_PSI].parameter); + nvramData.ulSyslogSize = atoi(gBoardParam[PARAM_IDX_SYSLOG_SIZE].parameter); + nvramData.ulMainTpNum = atoi(gBoardParam[PARAM_IDX_MAIN_THREAD_NUM].parameter); + + // save the buf to nvram + writeNvramData(&nvramData); + ret = 1; + } + + // restore gBoardParam + // Convert numeric value of board ID to string + gBoardParam[PARAM_IDX_BOARD_NAME].promptName = savedBoardIdPromptPtr; + i = atoi(gBoardParam[PARAM_IDX_BOARD_NAME].parameter); + strcpy(gBoardParam[PARAM_IDX_BOARD_NAME].parameter, &g_boardIdNames[i * BP_BOARD_ID_LEN]); + + if(gGponParamsInitialized) { + printf("\n"); + ret += setGponBoardParam(); + } + + if(gWpsDevicePinInitialized) { + printf("\n"); + ret += setWpsDevicePinBoardParam(); + } + + gVoiceParamsInitialized = voiceParamsInitialized(&nvramData); + + if(gVoiceParamsInitialized) { + printf("\n"); + ret += setVoiceBoardParam(); + } + + return ret; +} + +void displayBoardParam(void) +{ + int i; + + getBoardParam(); + + for (i = 0; i < gNumBoardParams; i++) { + if( gBoardParam[i].enabled ) + printf("%s %s \n", gBoardParam[i].promptName, gBoardParam[i].parameter); + } + + if(gGponParamsInitialized) { + getGponBoardParam(); + + for (i = 0; i < gNumGponBoardParams; i++) + if( gGponBoardParam[i].enabled ) + printf("%s \"%s\" \n", gGponBoardParam[i].promptName, gGponBoardParam[i].parameter); + } + + /*Show WPS Device PIN */ + if(gWpsDevicePinInitialized) { + getWpsDevicePinBoardParam(); + if ( gWpsDevicePinBoardParam[PARAM_IDX_WPS_DEVICE_PIN].enabled) + printf("%s \"%s\" \n", gWpsDevicePinBoardParam[PARAM_IDX_WPS_DEVICE_PIN].promptName, \ + gWpsDevicePinBoardParam[PARAM_IDX_WPS_DEVICE_PIN].parameter); + } + + if(gVoiceParamsInitialized) { + getVoiceBoardParam(); + + for (i = 0; i < gNumVoiceBoardParams; i++) + if( gVoiceBoardParam[i].enabled ) + printf("%s %s \n", gVoiceBoardParam[i].promptName, gVoiceBoardParam[i].parameter); + } +} diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_cmd.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_cmd.c new file mode 100755 index 0000000..111e73f --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_cmd.c @@ -0,0 +1,1878 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * + * bcm63xx board specific routines and commands. + * + * by: seanl + * + * April 1, 2002 + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#include "bcm63xx_util.h" +#include "flash_api.h" +#include "jffs2.h" + +/* Foxconn add start by Cliff Wang, 03/23/2010 */ +#include "tftpd.h" + +#include "net_nmrp.h" + + +extern int nmrp_server_detected; +extern unsigned long cfe_sdramsize; +extern int ui_init_tftpdcmds(void); +int verify_checksum(char *buf, unsigned long buf_len, unsigned long chksum); +/* Foxconn add end by Cliff Wang, 03/23/2010 */ + +#define je16_to_cpu(x) ((x).v16) +#define je32_to_cpu(x) ((x).v32) +#define FLASH_STAGING_BUFFER BOARD_IMAGE_DOWNLOAD_ADDRESS +#define FLASH_STAGING_BUFFER_SIZE BOARD_IMAGE_DOWNLOAD_SIZE + +extern int decompressLZMA(unsigned char *in, unsigned insize, unsigned char *out, unsigned outsize); + +// global +int g_processing_cmd = 0; + +char fakeConsole[2] = " "; + +/* Foxconn add start by Jenny Zhao, 07/02/2008*/ +struct image_header +{ + unsigned long magic; /* magic */ + unsigned long header_len; /* Length of header */ + unsigned char reserved[8]; + unsigned long kernel_chksum; /* Kernel image chksum */ + unsigned long rootfs_chksum; /* rootfs image chksum */ + unsigned long kernel_len; /* Length of kernel */ + unsigned long rootfs_len; /* Length of rootfs */ + unsigned long image_chksum; /* checksum across length of image */ + unsigned long header_chksum; /* checksum across length of header */ +}; + +#define swap32(val) \ + ((unsigned int)( \ + (((unsigned int)(val) & (unsigned int)0x000000ffUL)) | \ + (((unsigned int)(val) & (unsigned int)0x0000ff00UL)) | \ + (((unsigned int)(val) & (unsigned int)0x00ff0000UL)) | \ + (((unsigned int)(val) & (unsigned int)0xff000000UL)) )) + +/* pling added 12/04/2008, define the Foxconn board ID length */ +#define FOXCONN_BOARD_ID_LEN 64 +/* Foxconn add end by Jenny Zhao, 07/02/2008*/ + +static int ui_cmd_set_board_param(ui_cmdline_t *cmd,int argc,char *argv[]) +{ + int ret = 0; + int i = 0; + int reset = 0; + + if(!argc) + { + reset += setBoardParam(); + } + + while(argc && !ret) + { + if(!strcmp(argv[i], "g")) + { + reset += setGponBoardParam(); + } + else { + /*Setup WPS Device Pin*/ + if(!strcmp(argv[i], "w")) + { + reset += setWpsDevicePinBoardParam(); + } + else + { + ret = -1; + } + } + + argc--; + i++; + } + + if(reset) + softReset(); + + return ret; +} + +static int ui_cmd_reset(ui_cmdline_t *cmd,int argc,char *argv[]) +{ + softReset(); + return 0; +} + +// return 0 if 'y' +int yesno(void) +{ + char ans[5]; + + printf(" (y/n):"); + console_readline ("", ans, sizeof (ans)); + if (ans[0] != 'y') + return -1; + + return 0; +} + +// erase Persistent sector +static int ui_cmd_erase_psi(ui_cmdline_t *cmd,int argc,char *argv[]) +{ + printf("Erase persisten storage data?"); + if (yesno()) + return -1; + + kerSysErasePsi(); + + return 0; +} + +static int ui_cmd_erase_nand(ui_cmdline_t *cmd,int argc,char *argv[]) +{ + +#if (INC_NAND_FLASH_DRIVER==1) + char *flag; + int i, blk_end; + + flag = cmd_getarg(cmd,0); + + if (!flag) + { + printf("'e b' to reinitialize NAND flash or 'e a' to erase kernel\n"); + return 0; + } + + switch (*flag) + { + case 'b': + printf("Reinitialize NAND flash?"); + if (yesno()) + return 0; + printf("\nNow think carefully. Do you really,\n" + "really want to reinitialize the NAND flag?"); + if (yesno()) + return 0; + flash_sector_erase_int(NAND_REINIT_FLASH); + break; + case 'a': + printf("Erase NAND flash? The modem will not be able to boot from " + "flash"); + if (yesno()) + return 0; + + blk_end = flash_get_numsectors(); + for (i = 1; i < blk_end; i++) + { + printf("."); + flash_sector_erase_int(i); + } + printf("\n"); + break; + case 's': + { + extern void dump_spare(void); + dump_spare(); + } + break; + + case 'r': + { + extern unsigned char *mem_topofmem; + unsigned char *buf = (unsigned char *) mem_topofmem + 1024; + char *pszLen = cmd_getarg(cmd, 2); + int len = (pszLen) ? atoi(pszLen) : 64; + char *pszBlk = cmd_getarg(cmd, 1); + if( flash_read_buf(atoi(pszBlk), 0, buf, 16 * 1024) > 0 ) + { + void ui_dumpaddr( unsigned char *pAddr, int nLen ); + printf("block read into buffer at 0x%8.8lx\n", (unsigned long)buf); + ui_dumpaddr(buf, len); /* dump first few bytes */ + } + else + printf("block NOT read into buffer at 0x%8.8lx\n",(unsigned long)buf); + /* Can break into JTAG now to view entire block contents. */ + } + break; + default: + printf("Erase [n]vram, [p]ersistent storage or [a]ll flash except bootrom\nusage: e [n/p/a]\n"); + return 0; + } +#elif (INC_SPI_PROG_NAND==1) + char *flag; + int i, blk_end; + + flash_change_flash_type(FLASH_IFC_NAND); + + flag = cmd_getarg(cmd,0); + + if (!flag) + { + printf("'n b' to reinitialize NAND flash or 'n a' to erase kernel on NAND\n"); + goto finish; + } + + switch (*flag) + { + case 'b': + printf("Reinitialize NAND flash?"); + if (yesno()) + goto finish; + printf("\nNow think carefully. Do you really,\n" + "really want to reinitialize the NAND flag?"); + if (yesno()) + goto finish; + flash_sector_erase_int(NAND_REINIT_FLASH); + break; + case 'a': + printf("Erase NAND flash? The modem will not be able to boot from " + "flash"); + if (yesno()) + goto finish; + + blk_end = flash_get_numsectors(); + for (i = 1; i < blk_end; i++) + { + printf("."); + flash_sector_erase_int(i); + } + printf("\n"); + break; + case 's': + { + extern void dump_spare(void); + dump_spare(); + } + break; + + case 'r': + { + extern unsigned char *mem_topofmem; + unsigned char *buf = (unsigned char *) mem_topofmem + 1024; + char *pszBlk = cmd_getarg(cmd, 1); + if( flash_read_buf(atoi(pszBlk), 0, buf, 16 * 1024) > 0 ) + { + void ui_dumpaddr( unsigned char *pAddr, int nLen ); + printf("block read into buffer at 0x%8.8lx\n", (unsigned long)buf); + ui_dumpaddr(buf, 64); /* dump first few bytes */ + } + else + printf("block NOT read into buffer at 0x%8.8lx\n",(unsigned long)buf); + /* Can break into JTAG now to view entire block contents. */ + } + break; + default: + printf("Erase [n]vram, [p]ersistent storage or [a]ll flash except bootrom on NAND\nusage: n [n/p/a]\n"); + } +finish: + flash_change_flash_type(FLASH_IFC_SPI); + +#endif + + return 0; +} + +// erase some sectors +static int ui_cmd_erase(ui_cmdline_t *cmd,int argc,char *argv[]) +{ + + //FILE_TAG cfeTag; + PFILE_TAG pTag; + char *flag; + int i, blk_start, blk_end; + + flag = cmd_getarg(cmd,0); + + if (!flag) + { + printf("Erase [n]vram, [p]ersistent storage or [a]ll flash except bootrom\nusage: e [n/p/a]\n"); + return 0; + } + + switch (*flag) + { + case 'b': + printf("Erase boot loader?"); + if (yesno()) + return 0; + printf("\nNow think carefully. Do you really,\n" + "really want to erase the boot loader?"); + if (yesno()) + return 0; + flash_sector_erase_int(0); + break; + case 'n': + printf("Erase nvram?"); + if (yesno()) + return 0; + kerSysEraseNvRam(); + softReset(); + break; + case 'a': + + printf("Erase all flash (except bootrom)?"); + if (yesno()) + return 0; + + blk_end = flash_get_numsectors(); + if ((pTag = getTagFromPartition(1)) != NULL) + blk_start = flash_get_blk(atoi(pTag->rootfsAddress) + BOOT_OFFSET); + else // just erase all after cfe + { + FLASH_ADDR_INFO flash_info; + + kerSysFlashAddrInfoGet(&flash_info); + for( blk_start = 0, i = 0; i<flash_info.flash_rootfs_start_offset && + blk_start < blk_end; blk_start++ ) + { + i += flash_get_sector_size(blk_start); + } + printf("No image tag found. Erase the blocks start at [%d]\n", + blk_start); + } + if( blk_start > 0 ) + { + for (i = blk_start; i < blk_end; i++) + { + printf("."); + flash_sector_erase_int(i); + } + printf("\n"); + } + + /* Preserve the NVRAM fields that are used in the 'b' command. */ + softReset(); + break; + case 'p': + ui_cmd_erase_psi(cmd,argc,argv); + break; + default: + printf("Erase [n]vram, [p]ersistent storage or [a]ll flash except bootrom\nusage: e [n/p/a]\n"); + return 0; + } + + return 0; +} + + +static int loadRaw(char *hostImageName, uint8_t *ptr) +{ + cfe_loadargs_t la; + int res; + + printf("Loading %s ...\n", hostImageName); + + // tftp only + la.la_filesys = "tftp"; + la.la_filename = hostImageName; + la.la_device = NULL; + la.la_address = (long)ptr; + la.la_options = NULL; + la.la_maxsize = FLASH_STAGING_BUFFER_SIZE; + la.la_flags = LOADFLG_SPECADDR; + + res = bcm63xx_cfe_rawload(&la); + if (res < 0) + { + ui_showerror(res, "Loading failed."); + return res; + } + printf("Finished loading %d bytes\n", res); + + return res; +} + +// flash the image +static int ui_cmd_flash_image(ui_cmdline_t *cmd,int argc,char *argv[]) +{ + char hostImageName[BOOT_FILENAME_LEN + BOOT_IP_LEN]; + char *imageName; + int res; + uint8_t *ptr = (uint8_t *) KERNADDR(FLASH_STAGING_BUFFER); + + g_processing_cmd = 1; + + imageName = cmd_getarg(cmd, 0); + + if (imageName) + { + if (strchr(imageName, ':')) + strcpy(hostImageName, imageName); + else + { + strcpy(hostImageName, bootInfo.hostIp); + strcat(hostImageName, ":"); + strcat(hostImageName, imageName); + } + } + else // use default flash file name + { + strcpy(hostImageName, bootInfo.hostIp); + strcat(hostImageName, ":"); + strcat(hostImageName, bootInfo.flashFileName); + } + + if ((res = loadRaw(hostImageName, ptr)) < 0) + { + g_processing_cmd = 0; + return res; + } + + // check and flash image + res = flashImage(ptr); + + if( res == 0 ) + { + char *p; + NVRAM_DATA nvramData; + + readNvramData(&nvramData); + + for( p = nvramData.szBootline; p[2] != '\0'; p++ ) { + if( p[0] == 'r' && p[1] == '=' && p[2] == 'h' ) + { + /* Change boot source to "boot from flash". */ + p[2] = 'f'; + writeNvramData(&nvramData); + break; + } + } + softReset(); + } + + g_processing_cmd = 0; + return( res ); +} + +static int ui_cmd_write_chk_image(ui_cmdline_t *cmd,int argc,char *argv[]) +{ + char hostImageName[BOOT_FILENAME_LEN + BOOT_IP_LEN]; + char *imageName; + uint8_t *ptr = (uint8_t *) KERNADDR(FLASH_STAGING_BUFFER); + int res; + struct image_header *header; + unsigned long image_len, image_chksum; + + unsigned long header_len = 0; + unsigned long board_id_len = 0; + char board_id[FOX_BOARD_ID_MAX_LEN]; + uint8_t *tmp; + + g_processing_cmd = 1; + + imageName = cmd_getarg(cmd, 0); + if (!imageName) + return ui_showusage(cmd); + + if (strchr(imageName, ':')) + strcpy(hostImageName, imageName); + else + { + strcpy(hostImageName, bootInfo.hostIp); + strcat(hostImageName, ":"); + strcat(hostImageName, imageName); + } + + if ((res = loadRaw(hostImageName, ptr)) < 0) + { + g_processing_cmd = 0; + return res; + } + + /* check chk file */ + header = (struct image_header *)ptr; + header_len = swap32(header->header_len); + image_len = swap32(header->kernel_len); + image_chksum = swap32(header->kernel_chksum); + board_id_len = header_len - sizeof(struct image_header); + + memset(board_id, 0, sizeof(board_id)); + memcpy(board_id, header+1, board_id_len); + + printf("total:%d header:%d kernel:%d \n", res, header_len, image_len); + + tmp = ptr; + ptr += header_len; + res -= header_len; + + if (verify_checksum((char*)ptr, image_len, image_chksum)) { + printf("fail to comapre checksum ... \n "); + return CFE_ERR_BADIMAGE; + } + + memcpy(tmp, ptr, res); + + // check and flash image + res = writeWholeImage(tmp, res); + + printf("Finished flashing image.\n"); +/* + if (res == 0) + { + softReset(); + } +*/ + g_processing_cmd = 0; + return( res ); +} + +// write the whole image +static int ui_cmd_write_whole_image(ui_cmdline_t *cmd,int argc,char *argv[]) +{ + char hostImageName[BOOT_FILENAME_LEN + BOOT_IP_LEN]; + char *imageName; + uint8_t *ptr = (uint8_t *) KERNADDR(FLASH_STAGING_BUFFER); + int res; + + g_processing_cmd = 1; + + imageName = cmd_getarg(cmd, 0); + if (!imageName) + return ui_showusage(cmd); + + if (strchr(imageName, ':')) + strcpy(hostImageName, imageName); + else + { + strcpy(hostImageName, bootInfo.hostIp); + strcat(hostImageName, ":"); + strcat(hostImageName, imageName); + } + + if ((res = loadRaw(hostImageName, ptr)) < 0) + { + g_processing_cmd = 0; + return res; + } + + // check and flash image + res = writeWholeImage(ptr, res); + + printf("Finished flashing image.\n"); + + if (res == 0) + { + softReset(); + } + + g_processing_cmd = 0; + return( res ); +} + + +static int ui_cmd_flash_router_image(ui_cmdline_t *cmd,int argc,char *argv[]) +{ + char hostImageName[BOOT_FILENAME_LEN + BOOT_IP_LEN]; + char *imageName; + uint8_t *ptr = (uint8_t *) KERNADDR(FLASH_STAGING_BUFFER); + +#if (INC_NAND_FLASH_DRIVER==1) + uint8_t *tmp; +#endif + + int res; + + char board_id[FOX_BOARD_ID_MAX_LEN]; //Silver + int update=0; + char board_id_test[PROJECT_ID_LEN]; + +#if (INC_NAND_FLASH_DRIVER==1) + NVRAM_DATA nvramData; +#endif + + imageName = cmd_getarg(cmd, 0); + if (!imageName) + return ui_showusage(cmd); + + if (strchr(imageName, ':')) + strcpy(hostImageName, imageName); + else + { + strcpy(hostImageName, ""); + strcat(hostImageName, ":"); + strcat(hostImageName, ""); + } + + set_tftpd_state(TFTPD_STATE_WAIT_IMAGE); + if ((res = loadRaw(hostImageName, ptr)) < 0) { + printf("fail to load raw file ... \n"); + return res; + } + + if ( nmrp_server_detected == 0) + { + set_tftpd_state(TFTPD_STATE_OFF); // Foxconn added to turn on RED. + setPowerOnLedOn(); // Foxconn added to turn on RED. + } + + /* Foxconn add start by Jenny Zhao, 07/02/2008*/ + if (1) { + struct image_header *header; + unsigned long image_len, image_chksum; + + unsigned long header_len = 0; + unsigned long board_id_len = 0; + + header = (struct image_header *)ptr; + header_len = swap32(header->header_len); + image_len = swap32(header->kernel_len); + image_chksum = swap32(header->kernel_chksum); + /* Check Board ID first */ + board_id_len = header_len - sizeof(struct image_header); + memset(board_id, 0, sizeof(board_id)); + //for(i=0;i<board_id_len;i++) + /* printf("copy board id ... \n"); */ + + //memcpy(board_id, board_id_test, board_id_len); +#if (INC_NAND_FLASH_DRIVER==1) + readNvramData(&nvramData); + if ( nvramData.szFirmwareUpgradeBoardId != NULL ) + memcpy(board_id_test, nvramData.szFirmwareUpgradeBoardId, PROJECT_ID_LEN); +#else + kerSysReadFromFlash(board_id_test, BOARD_DATA_ADDR, PROJECT_ID_LEN); +#endif + /* printf("bboard id is (%s)\n", board_id_test); */ + + memcpy(board_id, header+1, board_id_len); + + /* printf("iboard id is (%s)\n", board_id); */ + +/* disable board_id checking + if (verify_board_id(board_id)) { + printf("Check board id fail: (%s)\n", board_id); + return CFE_ERR_BADIMAGE; + } +*/ + /* Check image checksum */ +#ifdef _DEBUG + xprintf("len = 0x%08X\n", image_len); + xprintf("chksum = 0x%08X\n", image_chksum); + xprintf("header_len = 0x%08X\n", header_len); +#endif + +#if (INC_NAND_FLASH_DRIVER==1) + tmp = ptr; + res -= header_len; +#endif + + ptr += header_len; + + if (verify_checksum((char*)ptr, image_len, image_chksum)) { + printf("fail to comapre checksum ... \n "); + return CFE_ERR_BADIMAGE; + } + } + + /* Foxconn add end by Jenny Zhao, 07/02/2008*/ + if(nmrp_server_detected==1) // in NMRP mode + { + printf(">>> kerSysBcmImageSet= 0x%x\n", FLASH_IMAGE_START_ADDR); +#if (INC_NAND_FLASH_DRIVER==1) + memcpy(tmp, ptr, res); + if ((res = writeWholeImage(tmp, res) )!= 0) +#else + if ((res = kerSysBcmImageSet(FLASH_IMAGE_START_ADDR, ptr, res, 0)) != 0) +#endif + printf("Failed to flash image. Error: %d\n", res); + else + { + /* Foxconn added start, Silver Shih for burn board Id */ + if( strlen(board_id) < FOX_BOARD_ID_MAX_LEN) + { + if(strcmp(board_id_test, board_id) != 0) + //if (strcmp((char *)BOARD_DATA_ADDR, board_id) != 0) + { + //printf("board id not match, addr:0x%x\n", BOARD_DATA_ADDR); + //5 is indicated to burn board id +#if (INC_NAND_FLASH_DRIVER==0) + kerSysBcmImageSet(BOARD_DATA_ADDR, (unsigned char *)board_id, strlen(board_id)+1 , 5); +#endif + } + } + /* Foxconn added end, Silver Shih for burn board Id */ + + update=1; + printf("Finished flashing image in NMRP mode.\n"); + } + } + /* Foxconn added start pling 12/04/2008, for 'tftpd' */ +#if (INC_NAND_FLASH_DRIVER==0) + else if ((res = kerSysBcmImageSet(FLASH_IMAGE_START_ADDR, ptr, res, 0)) != 0) + printf("Failed to flash image. Error: %d\n", res); +#endif + else + printf("finishing flash image for flashimage command ... \n"); + + /* Foxconn added end pling 12/04/2008 */ + if (res == 0) + { + char *p; + NVRAM_DATA nvramData; + + readNvramData(&nvramData); + + memcpy(nvramData.szFirmwareUpgradeBoardId, board_id, strlen(board_id)); + + for( p = nvramData.szBootline; p[2] != '\0'; p++ ) { + if( p[0] == 'r' && p[1] == '=' && p[2] == 'h' ) + { + /* Change boot source to "boot from flash". */ + p[2] = 'f'; + //writeNvramData(&nvramData); + break; + } + } + writeNvramData(&nvramData); + // softReset(); //remove by EricHuang + } + + if (nmrp_server_detected==1 && update==1) //NMRP mode + { + // Restore to factory default. + printf("try to restore to default, addr=0x%x\n", BOARD_FOXNVRAM_ADDR); +#if (INC_NAND_FLASH_DRIVER==0) + kerSysBcmImageSet(BOARD_FOXNVRAM_ADDR, (unsigned char *)"", 0x10000 , 5); +#endif + } + + return( res ); +} + +/************************************************************************ + * cfe_go(la) + * + * Starts a previously loaded program. cfe_loadargs.la_entrypt + * must be set to the entry point of the program to be started + * + * Input parameters: + * la - loader args + * + * Return value: + * does not return + ********************************************************************* */ + +void cfe_go(cfe_loadargs_t *la) +{ + if (la->la_entrypt == 0) { + xprintf("No program has been loaded.\n"); + return; + } + + if (net_getparam(NET_DEVNAME)) { + xprintf("Closing network.\n"); + net_uninit(); + } + + xprintf("Starting program at 0x%p\n",la->la_entrypt); + + setPowerOnLedOn(); + + cfe_start(la->la_entrypt); +} + +static int bootImage(char *fileSys, char *device, int zflag, char *imageName) +{ + cfe_loadargs_t la; + int res; + + // elf only + la.la_filesys = fileSys; + la.la_filename = imageName; + la.la_device = device; + la.la_options = 0; + la.la_maxsize = 0; + la.la_address = 0; + la.la_flags = zflag; + + res = bcm63xx_cfe_elfload(&la); + if (res != 0) + return res; + + if (la.la_flags & LOADFLG_NOISY) + xprintf("Entry at 0x%p\n",la.la_entrypt); + if ((la.la_flags & LOADFLG_EXECUTE) && (la.la_entrypt != 0)) { + cfe_go(&la); + } + + return res; +} + +// Compressed image head format in Big Endia: +// 1) Text Start address: 4 bytes +// 2) Program Entry point: 4 bytes +// 3) Compress image Length: 4 bytes +// 4) Compress data starts: compressed data +static int bootCompressedImage(unsigned int *puiCmpImage, int retry) +{ + unsigned char *pucSrc; + unsigned char *pucDst; + unsigned char *pucEntry; + unsigned int dataLen; + int ret = 0; + cfe_loadargs_t la; + + if( (unsigned long) puiCmpImage > FLASH_BASE ) + { + /* Boot compressed image from flash. */ + unsigned int *puiOrigCmpImage = puiCmpImage; + unsigned int *puiNewCmpImage = NULL; + unsigned int *puiOldCmpImage = NULL; + unsigned int *puiFs = NULL; + PFILE_TAG pTag1 = getTagFromPartition(1); + PFILE_TAG pTag2 = getTagFromPartition(2); + PFILE_TAG pCurTag = NULL; + unsigned int *puiImg= NULL; + int nImgLen = 0; + unsigned long ulCrc, ulImgCrc; + + if( pTag1 && pTag2 ) + { + /* Two images are on flash. Determine which one is being booted. */ + PFILE_TAG pNewTag = NULL; + PFILE_TAG pOldTag = NULL; + int seq1 = atoi(pTag1->imageSequence); + int seq2 = atoi(pTag2->imageSequence); + + if( seq1 > seq2 ) + { + pNewTag = pTag1; + pOldTag = pTag2; + } + else + { + pNewTag = pTag2; + pOldTag = pTag1; + } + + puiNewCmpImage = (unsigned int *) + (atoi(pNewTag->kernelAddress) + BOOT_OFFSET); + puiOldCmpImage = (unsigned int *) + (atoi(pOldTag->kernelAddress) + BOOT_OFFSET); + + if( puiOrigCmpImage == puiOldCmpImage ) + { + printf("Booting from previous image (0x%8.8lx) ...\n", + (unsigned long) atoi(pOldTag->rootfsAddress) + + BOOT_OFFSET - TAG_LEN); + pCurTag = pOldTag; + } + else + { + printf("Booting from latest image (0x%8.8lx) ...\n", + (unsigned long) atoi(pNewTag->rootfsAddress) + + BOOT_OFFSET - TAG_LEN); + pCurTag = pNewTag; + } + } + else + if( pTag1 || pTag2 ) + { + /* Only one image on flash. */ + pCurTag = (pTag1) ? pTag1 : pTag2; + printf("Booting from only image (0x%8.8lx) ...\n", + (unsigned long) atoi(pCurTag->rootfsAddress) + + BOOT_OFFSET - TAG_LEN); + } + else + { + /* No image on flash. */ + printf("No valid boot image\n"); + ret = -1; + } + + if( ret == 0 ) + { + /* Copy compressed image to SDRAM. */ + extern unsigned char *mem_topofmem; + FLASH_ADDR_INFO info; + unsigned char *pDest = (unsigned char *) mem_topofmem + 1024; + unsigned char *pImgEnd; + + kerSysFlashAddrInfoGet( &info ); + pImgEnd = flash_get_memptr( info.flash_meta_start_blk ); + kerSysReadFromFlash( pDest, (unsigned long) puiCmpImage, + (unsigned long) pImgEnd - (unsigned long) puiCmpImage ); + + puiCmpImage = (unsigned int *) pDest; + + /* Copy file system to SDRAM. */ + pDest += (unsigned long) pImgEnd - (unsigned long) + puiOrigCmpImage + 1024; + kerSysReadFromFlash( pDest, (unsigned long) + atoi(pCurTag->rootfsAddress) + BOOT_OFFSET, + atoi(pCurTag->rootfsLen)); + + puiFs = (unsigned int *) pDest; + + pucDst = (unsigned char *) *puiCmpImage; + pucEntry = (unsigned char *) *(puiCmpImage + 1); + dataLen = (unsigned int) *(puiCmpImage + 2); + pucSrc = (unsigned char*) (puiCmpImage + 3); + + printf("Code Address: 0x%08X, Entry Address: 0x%08x\n", + (unsigned int) pucDst, (unsigned int) pucEntry); + + + /* Check Linux file system CRC */ + ulImgCrc = *(unsigned long *) (pCurTag->imageValidationToken + + CRC_LEN); + if( ulImgCrc ) + { + if( puiFs ) + puiImg = puiFs; + else + { + puiImg = (unsigned int *) (atoi(pCurTag->rootfsAddress) + + BOOT_OFFSET); + } + nImgLen = atoi(pCurTag->rootfsLen); + + ulCrc = CRC32_INIT_VALUE; + ulCrc = getCrc32((unsigned char *) puiImg, (UINT32) nImgLen, ulCrc); + if( ulCrc != ulImgCrc) + { + printf("Linux file system CRC error. Corrupted image?\n"); + ret = -1; + } + } + + /* Check Linux kernel CRC */ + ulImgCrc = *(unsigned long *) (pCurTag->imageValidationToken + + (CRC_LEN * 2)); + if( ulImgCrc ) + { + puiImg = (unsigned int *) puiCmpImage; + nImgLen = atoi(pCurTag->kernelLen); + + ulCrc = CRC32_INIT_VALUE; + ulCrc = getCrc32((unsigned char *) puiImg, (UINT32) nImgLen, ulCrc); + if( ulCrc != ulImgCrc) + { + printf("Linux kernel CRC error. Corrupted image?\n"); + ret = -1; + } + } + + if( ret == 0 ) + { + ret = decompressLZMA(pucSrc, dataLen, pucDst, 23*1024*1024); + if (ret != 0) + printf("Failed to decompress image. Corrupted image?\n"); + } + + if (ret != 0) + { + /* Try to boot from the other flash image, if one exists. */ + if( retry == TRUE && pTag1 && pTag2 ) + { + int blk = 0; + unsigned char *pBase = flash_get_memptr(0); + unsigned int *flash_addr_kernel; + FLASH_ADDR_INFO flash_info; + + /* The boot image is bad. Erase the sector with the tag so + * the image is not tried in subsequent boots. + */ + kerSysFlashAddrInfoGet(&flash_info); + if( pCurTag == pTag1 ) + { + blk = flash_get_blk((int)(pBase + + flash_info.flash_rootfs_start_offset)); + } + else + if( pCurTag == pTag2 ) + { + blk = flash_get_blk((int) (pBase + + (flash_get_total_size()/2))); + } + + if( blk ) + flash_sector_erase_int(blk); + + /* Boot from the other flash image. */ + if( puiOrigCmpImage == puiOldCmpImage ) + flash_addr_kernel = puiNewCmpImage; + else + flash_addr_kernel = puiOldCmpImage; + + ret = bootCompressedImage( flash_addr_kernel, FALSE ); + } + } + else + { + printf("Decompression OK!\n"); + la.la_entrypt = (long) pucEntry; + printf("Entry at 0x%p\n",la.la_entrypt); + cfe_go(&la); // never return... + } + + } + } + else + { + /* Boot compressed image that was downloaded to RAM. */ + pucDst = (unsigned char *) *puiCmpImage; + pucEntry = (unsigned char *) *(puiCmpImage + 1); + dataLen = (unsigned int) *(puiCmpImage + 2); + pucSrc = (unsigned char*) (puiCmpImage + 3); + + printf("Code Address: 0x%08X, Entry Address: 0x%08x\n", + (unsigned int) pucDst, (unsigned int) pucEntry); + + ret = decompressLZMA(pucSrc, dataLen, pucDst, 23*1024*1024); + if (ret == 0) + { + printf("Decompression OK!\n"); + la.la_entrypt = (long) pucEntry; + printf("Entry at 0x%p\n",la.la_entrypt); + cfe_go(&la); // never return... + } + else + printf("Failed on decompression. Corrupted image?\n"); + } + + return ret; +} + +static int bootNandImageFromRootfs(int start_blk, int end_blk) +{ + extern unsigned char *mem_topofmem; + char fname[] = NAND_FLASH_BOOT_IMAGE_NAME; + int fname_len = strlen(fname); + int len = flash_get_sector_size(0); + unsigned char *buf = (unsigned char *) mem_topofmem + 1024; + unsigned char *pDest = (unsigned char *) buf + len; + unsigned long *pulDest = (unsigned long *) pDest; + unsigned char *p; + unsigned long version = 0; + unsigned long ino = 0; + int i, done; + struct jffs2_raw_dirent *pdir; + struct jffs2_raw_inode *pino; + int ret = 0; + + /* Find the directory entry. */ + for( i = start_blk, done = 0; i < end_blk && done == 0; i++ ) + { + if( flash_read_buf(i, 0, buf, len) > 0 ) + { + p = buf; + while( p < buf + len ) + { + pdir = (struct jffs2_raw_dirent *) p; + if( je16_to_cpu(pdir->magic) == JFFS2_MAGIC_BITMASK ) + { + if( je16_to_cpu(pdir->nodetype) == JFFS2_NODETYPE_DIRENT && + fname_len == pdir->nsize && + !memcmp(fname, pdir->name, fname_len) ) + { + if( je32_to_cpu(pdir->version) > version ) + { + if( (ino = je32_to_cpu(pdir->ino)) != 0 ) + { + version = je32_to_cpu(pdir->version); + + /* Setting 'done = 1' assumes there is only one + * version of the directory entry. This may not + * be correct if the file is updated after it + * was initially flashed. + * + * TBD. Look for a higher version of the + * directory entry without searching the entire + * flash part. + */ + done = 1; + break; + } + } + } + + p += (je32_to_cpu(pdir->totlen) + 0x03) & ~0x03; + } + else + break; + } + } + } + + if( version ) + { + unsigned char *pucSrc; + unsigned char *pucDst; + unsigned char *pucEntry; + unsigned int dataLen; + unsigned long cur_isize = 0; + + /* Get the file contents. */ + for( i = start_blk, done = 0; i < end_blk && done == 0; i++ ) + { + if( flash_read_buf(i, 0, buf, len) > 0 ) + { + p = buf; + while( p < buf + len ) + { + pino = (struct jffs2_raw_inode *) p; + if( je16_to_cpu(pino->magic) == JFFS2_MAGIC_BITMASK ) + { + if(je16_to_cpu(pino->nodetype)==JFFS2_NODETYPE_INODE && + je32_to_cpu(pino->ino) == ino) + { + unsigned long size = je32_to_cpu(pino->dsize); + unsigned long ofs = je32_to_cpu(pino->offset); + unsigned long isize = je32_to_cpu(pino->isize); + + if( size ) + { + memcpy(pDest + ofs, pino->data, size); + if( (cur_isize += size) >= isize ) + { + done = 1; + break; + } + } + } + + p += (je32_to_cpu(pino->totlen) + 0x03) & ~0x03; + } + else + break; + } + } + } + + pucDst = (unsigned char *) *pulDest; + pucEntry = (unsigned char *) *(pulDest + 1); + dataLen = (unsigned int) *(pulDest + 2); + pucSrc = (unsigned char *) (pulDest + 3); + + ret = decompressLZMA(pucSrc, dataLen, pucDst, 23*1024*1024); + if (ret != 0) + printf("Failed to decompress image. Corrupted image?\n"); + else + { + cfe_loadargs_t la; + + /* Save the rootfs offset of the rootfs that the Linux image + * is loaded from at the memory location before the Linux load + * address. The Linux image uses this value to determine the + * the rootfs to use. + */ + *(unsigned long *) (pucDst - 4) = (start_blk * len) / 1024; + + printf("Decompression OK!\n"); + la.la_entrypt = (long) pucEntry; + printf("Entry at 0x%p\n",la.la_entrypt); + cfe_go(&la); // never return... + } + } + else + printf("ERROR: A JFFS2 directory entry for %s was not found.\n",fname); + + return( ret ); +} + +static int bootNandImage(void) +{ + int ret = -1; + char *msgA, *msgB; + PFILE_TAG pTag1 = getTagFromPartition(1); + PFILE_TAG pTag2 = getTagFromPartition(2); + int seq1 = (pTag1) ? atoi(pTag1->imageSequence) : -1; + int seq2 = (pTag2) ? atoi(pTag2->imageSequence) : -1; + int start_blk, end_blk, rootfsA, rootfsB; + int len = flash_get_sector_size(0) / 1024; + NVRAM_DATA nvramData; + + readNvramData(&nvramData); + validateNandPartTbl(&nvramData); + + if( pTag1 && pTag2 ) + { + if( bootInfo.bootPartition == BOOT_LATEST_IMAGE ) + { + msgA = "Booting from latest image (0x%8.8lx) ...\n"; + msgB = "Booting from previous image (0x%8.8lx) ...\n"; + rootfsA = (seq2 > seq1) ? NP_ROOTFS_2 : NP_ROOTFS_1; + } + else /* Boot from the previous image. */ + { + msgA = "Booting from previous image (0x%8.8lx) ...\n"; + msgB = "Booting from latest image (0x%8.8lx) ...\n"; + rootfsA = (seq2 <= seq1) ? NP_ROOTFS_2 : NP_ROOTFS_1; + } + + rootfsB = (rootfsA == NP_ROOTFS_2) ? NP_ROOTFS_1 : NP_ROOTFS_2; + start_blk = nvramData.ulNandPartOfsKb[rootfsA] / len; + end_blk = start_blk + + (nvramData.ulNandPartSizeKb[rootfsA] / len); + printf(msgA, FLASH_BASE + (nvramData.ulNandPartOfsKb[rootfsA] * 1024)); + if( (ret = bootNandImageFromRootfs(start_blk, end_blk)) != 0 ) + { + start_blk = nvramData.ulNandPartOfsKb[rootfsB] / len; + end_blk = start_blk + + (nvramData.ulNandPartSizeKb[rootfsB] / len); + printf(msgB, FLASH_BASE+(nvramData.ulNandPartOfsKb[rootfsB]*1024)); + if( (ret = bootNandImageFromRootfs(start_blk, end_blk)) != 0 ) + printf("Unable to boot image.\n"); + } + } + else + { + if( pTag1 ) + rootfsA = NP_ROOTFS_1; + else + if( pTag2 ) + rootfsA = NP_ROOTFS_2; + + if( pTag1 || pTag2 ) + { + start_blk = nvramData.ulNandPartOfsKb[rootfsA] / len; + end_blk = start_blk + + (nvramData.ulNandPartSizeKb[rootfsA] / len); + printf("Booting from only image (0x%8.8lx) ...\n", + FLASH_BASE + (nvramData.ulNandPartOfsKb[rootfsA] * 1024)); + if( (ret = bootNandImageFromRootfs(start_blk, end_blk)) != 0 ) + printf("Unable to boot image.\n"); + } + else + printf("No image found.\n"); + } + + return( ret ); +} + +static int autoRun(char *imageName) +{ + char ipImageName[BOOT_FILENAME_LEN + BOOT_IP_LEN]; + int ret; + + if (bootInfo.runFrom == 'f' && !imageName) + { + if (!imageName) + { + if( flash_get_flash_type() != FLASH_IFC_NAND ) + { + PFILE_TAG pTag = getBootImageTag(); + int flash_addr_kernel = atoi(pTag->kernelAddress) + BOOT_OFFSET; + + ret = bootCompressedImage((unsigned int *)flash_addr_kernel, TRUE); + } + else + ret = bootNandImage(); + } + else + printf("Image name not allowed for boot from flash.\n"); + } + else // loading from host + { + if (imageName) + { + if (strchr(imageName, ':')) + strcpy(ipImageName, imageName); + else + { + strcpy(ipImageName, bootInfo.hostIp); + strcat(ipImageName, ":"); + strcat(ipImageName, imageName); + } + } + else // use default host file name + { + strcpy(ipImageName, bootInfo.hostIp); + strcat(ipImageName, ":"); + strcat(ipImageName, bootInfo.hostFileName); + } + + // try uncompressed image first + ret = bootImage("tftp", "eth0", LOADFLG_EXECUTE | LOADFLG_NOISY, ipImageName); + + if( ret == CFE_ERR_NOTELF ) + { + uint8_t *ptr = (uint8_t *) KERNADDR(FLASH_STAGING_BUFFER); + // next try as a compressed image + printf("Retry loading it as a compressed image.\n"); + if ((ret = loadRaw(ipImageName, ptr)) > 0) + bootCompressedImage((unsigned int *) ptr, TRUE); + } + } + + return ret; +} + + +// run program from compressed image in flash or from tftped program from host +static int ui_cmd_run_program(ui_cmdline_t *cmd,int argc,char *argv[]) +{ + int ret; + + if( getBootImageTag() || bootInfo.runFrom == 'r' ) + { + char *imageName; + + imageName = cmd_getarg(cmd, 0); + g_processing_cmd = 1; + ret = autoRun(imageName); + } + else + { + printf("ERROR: There is not a valid image to boot from.\n"); + ret = CFE_ERR_FILENOTFOUND; + } + + return( ret ); +} + + +static int ui_cmd_print_system_info(ui_cmdline_t *cmd,int argc,char *argv[]) +{ + return printSysInfo(); +} + +static int ui_cmd_change_bootline(ui_cmdline_t *cmd,int argc,char *argv[]) +{ + return changeBootLine(); +} + +static int ui_cmd_set_afe_id(ui_cmdline_t *cmd,int argc,char *argv[]) +{ + return changeAfeId(); +} + +void ui_dumpaddr( unsigned char *pAddr, int nLen ); +void ui_dumpaddr( unsigned char *pAddr, int nLen ) +{ + static char szHexChars[] = "0123456789abcdef"; + char szLine[80]; + char *p = szLine; + unsigned char ch, *q; + int i = 0, j, size = 0; + unsigned long ul; + unsigned short us; + + if( ((unsigned long) pAddr & 0xff000000) == 0xff000000 || + ((unsigned long) pAddr & 0xff000000) == 0xb0000000 ) + { + if (nLen == 2) { + pAddr = (unsigned char *) ((unsigned long) pAddr & ~0x01); + } else if (nLen != 1) { + /* keeping the old logic as is. */ + if( ((unsigned long) pAddr & 0x03) != 0 ) + nLen += 4; + pAddr = (unsigned char *) ((unsigned long) pAddr & ~0x03); + } + } + while( nLen > 0 ) + { + sprintf( szLine, "%8.8lx: ", (unsigned long) pAddr ); + p = szLine + strlen(szLine); + + if( ((unsigned long) pAddr & 0xff000000) == 0xff000000 || + ((unsigned long) pAddr & 0xff000000) == 0xb0000000 ) + { + for(i = 0; i < 6 && nLen > 0; i += sizeof(long), nLen -= sizeof(long)) + { + if (nLen == 1) { + q = pAddr; + size = 1; + } else if (nLen == 2) { + us = *(unsigned short *)pAddr; + q = (unsigned char *) &us; + size = 2; + } else { + ul = *(unsigned long *) &pAddr[i]; + q = (unsigned char *) &ul; + size = sizeof(long); + } + for( j = 0; j < size; j++ ) + { + *p++ = szHexChars[q[j] >> 4]; + *p++ = szHexChars[q[j] & 0x0f]; + } + *p++ = ' '; + } + } + else + { + for(i = 0; i < 16 && nLen > 0; i++, nLen-- ) + { + ch = pAddr[i]; + + *p++ = szHexChars[ch >> 4]; + *p++ = szHexChars[ch & 0x0f]; + *p++ = ' '; + } + } + + for( j = 0; j < 16 - i; j++ ) + *p++ = ' ', *p++ = ' ', *p++ = ' '; + + *p++ = ' ', *p++ = ' ', *p++ = ' '; + + for( j = 0; j < i; j++ ) + { + ch = pAddr[j]; + *p++ = (ch >= ' ' && ch <= '~') ? ch : '.'; + } + + *p++ = '\0'; + printf( "%s\r\n", szLine ); + + pAddr += i; + } + printf( "\r\n" ); +} /* ui_dumpaddr */ + +static int ui_cmd_dump_mem(ui_cmdline_t *cmd,int argc,char *argv[]) +{ + char *pszAddr = cmd_getarg(cmd, 0); + char *pszLen = cmd_getarg(cmd, 1); + if( pszAddr && pszLen ) + ui_dumpaddr((unsigned char *) xtoi(pszAddr), atoi(pszLen)); + else + printf("dm address_in_hex length_in_decimal\n"); + + return( 0 ); +} + +static int ui_cmd_set_mem(ui_cmdline_t *cmd,int argc,char *argv[]) +{ + char *pszAddr = cmd_getarg(cmd, 0); + char *pszValue = cmd_getarg(cmd, 1); + char *pszSize = cmd_getarg(cmd, 2); + if( pszAddr && pszValue && pszSize ) + { + unsigned long ulAddr = (unsigned long) xtoi(pszAddr); + unsigned long ulValue = (unsigned long) atoi(pszValue); + int nSize = atoi(pszSize); + unsigned long *pul = (unsigned long *) ulAddr; + unsigned short *pus = (unsigned short *) ulAddr; + unsigned char *puc = (unsigned char *) ulAddr; + switch( nSize ) + { + case 4: + *pul = (unsigned long) ulValue; + break; + + case 2: + *pus = (unsigned short) ulValue; + break; + + case 1: + *puc = (unsigned char) ulValue; + break; + + default: + printf("sm address_in_hex value_in_hex size_4_2_or_1"); + break; + } + + ui_dumpaddr((unsigned char *) ulAddr, 4); + } + else + printf("sm address_in_hex value_in_hex size_4_2_or_1"); + + return( 0 ); +} + +static int ui_cmd_check_mem(ui_cmdline_t *cmd,int argc,char *argv[]) +{ + #define RAM_BASE_ADDRESS 0xa0000000 + #define BOOT_CODE_SIZE 256 * 1024 // 256KB + #define CFE_MEM_SPACE 0xa0400000 + #define CFE_MEM_SIZE 4*1024*1024 // 4MB + #define MEMORY_SIZE 32*1024*1024 // 32MB + #define MAGIC_NUMBER 0xacacacac + + #define NAND_SECTOR_SIZE (16*1024) // 16KB + #define NAND_TEST_SIZE (30*1024*1024) // 30MB + + unsigned char *addr = NULL; + int pass=1; + +#if 0 + unsigned int buf1[NAND_SECTOR_SIZE/4]; + unsigned int buf2[NAND_SECTOR_SIZE/4]; + int i, j; +#endif + + printf("Verifying DRAM access...\n"); + for(addr=(unsigned char *)(RAM_BASE_ADDRESS+BOOT_CODE_SIZE); addr< (unsigned char *)(RAM_BASE_ADDRESS+MEMORY_SIZE); addr+=4) + { + if( addr< (unsigned char *)CFE_MEM_SPACE || addr > (unsigned char *)CFE_MEM_SPACE+CFE_MEM_SIZE ) + { + *(unsigned long *)addr = MAGIC_NUMBER; + } + } + + for(addr=(unsigned char *)(RAM_BASE_ADDRESS+BOOT_CODE_SIZE); addr< (unsigned char *)(RAM_BASE_ADDRESS+MEMORY_SIZE); addr+=4) + { + if( addr< (unsigned char *)CFE_MEM_SPACE || addr > (unsigned char *)CFE_MEM_SPACE+CFE_MEM_SIZE ) + { + if( *(unsigned long *)addr != MAGIC_NUMBER ) + pass=0; + } + } + if(pass) + printf("DRAM check OK!!!!\n"); + else + printf("DRAM check NG!!!!\n"); + +#if 0 + //printf("Verifying NAND flash access...\n"); + pass=1; + + for(i=0; i<NAND_SECTOR_SIZE/4; i++) + { + buf1[i]=MAGIC_NUMBER; + } + + /* The CFE ROM boot loader saved the rootfs partition index at the + * memory location before CFE RAM load address. + */ + extern unsigned char _ftext; + int rootfs = (int) *(&_ftext - 1); + NVRAM_DATA nvramData; + int offset = 0; + int blk_start; + + readNvramData(&nvramData); + + if(rootfs == NP_ROOTFS_1 && nvramData.ulNandPartSizeKb[NP_ROOTFS_2]>0) + offset = nvramData.ulNandPartOfsKb[NP_ROOTFS_2] * 1024; + else + offset = nvramData.ulNandPartOfsKb[NP_ROOTFS_1] * 1024; + + printf("Verifying NAND flash access from 0x%08x...\n", FLASH_BASE+offset); + + for(i=0; i<NAND_TEST_SIZE/NAND_SECTOR_SIZE; i++, offset+=NAND_SECTOR_SIZE) + { + kerSysBcmImageSet(FLASH_BASE+offset, (unsigned char *)buf1, NAND_SECTOR_SIZE, 1); + kerSysReadFromFlash( buf2, FLASH_BASE+offset, NAND_SECTOR_SIZE ); + blk_start = flash_get_blk(FLASH_BASE+offset); + flash_sector_erase_int(blk_start); // erase blk before flash + if( memcmp(buf1, buf2, NAND_SECTOR_SIZE)) + { + printf("Failed address is 0x%08x\n", FLASH_BASE+offset); + for(j=0; j<NAND_SECTOR_SIZE/4; j++) + { + printf("buf2[%d]=%x\n", j, buf2[j]); + } + pass=0; + break; + } + } + + if(pass) + printf("NAND flash check OK!!!!\n"); + else + printf("NAND flash check NG!!!!\n"); +#endif + + return( 0 ); +} + +extern int ui_init_netcmds(void); + +int ui_cmd_nmrp(ui_cmdline_t *cmd,int argc,char *argv[]); + +int ui_cmd_nmrp(ui_cmdline_t *cmd,int argc,char *argv[]) +{ + _start_nmrp(); + return 0; +} + + +int ui_cmd_flash_read(ui_cmdline_t *cmd,int argc,char *argv[]); + +int ui_cmd_flash_read(ui_cmdline_t *cmd,int argc,char *argv[]) +{ + char str[10]; + + kerSysReadFromFlash(str, BOARD_DATA_ADDR, 7); + + printf("%s\n", str); + + return 0; +} + +int ui_cmd_write_boardid(ui_cmdline_t *cmd,int argc,char *argv[]); + +int ui_cmd_write_boardid(ui_cmdline_t *cmd,int argc,char *argv[]) +{ +#if (INC_NAND_FLASH_DRIVER==1) + NVRAM_DATA nvramData; + int len; +#endif + + if ( argv[0] != NULL ) { +#if (INC_NAND_FLASH_DRIVER==1) + len = strlen(argv[0]); + readNvramData(&nvramData); + memcpy(nvramData.szFirmwareUpgradeBoardId, argv[0], len); + writeNvramData(&nvramData); +#else + kerSysBcmImageSet(BOARD_DATA_ADDR, (unsigned char *)argv[0], strlen(argv[0])+1 , 5); +#endif + } +#if (INC_NAND_FLASH_DRIVER==1) + else { + readNvramData(&nvramData); + } + printf("read board id: %s \n", nvramData.szFirmwareUpgradeBoardId); +#endif + return 0; +} + +/* Foxconn add start by Cliff Wang, 03/23/2010 */ +extern int ui_init_netcmds(void); +/* Foxconn add end by Cliff Wang, 03/23/2010 */ + +static int ui_init_bcm63xx_cmds(void) +{ + console_name = fakeConsole; // for cfe_rawfs strcmp + // Used to flash an image that does not contain a FILE_TAG record. + + /* Foxconn add start by Cliff Wang, 03/23/2010 */ + cmd_addcmd("flashimage", + ui_cmd_flash_router_image, + NULL, + "Flashes a compressed image after the bootloader.", + "eg. flashimage [hostip:]compressed_image_file_name", + ""); + /* Foxconn add end by Cliff Wang, 03/23/2010 */ + cmd_addcmd("bid", + ui_cmd_write_boardid, + NULL, + "write board id to nand flash.", + "eg. bi str ", + ""); + + cmd_addcmd("reset", + ui_cmd_reset, + NULL, + "Reset the board", + "", + ""); + + cmd_addcmd("b", + ui_cmd_set_board_param, + NULL, + "Change board parameters", + "", + ""); + + cmd_addcmd("a", + ui_cmd_set_afe_id, + NULL, + "Change board AFE ID", + "", + ""); + + cmd_addcmd("i", + ui_cmd_erase_psi, + NULL, + "Erase persistent storage data", + "", + ""); + + if( flash_get_flash_type() != FLASH_IFC_NAND ) + cmd_addcmd("f", + ui_cmd_flash_image, + NULL, + "Write image to the flash ", + "eg. f [[hostip:]filename]<cr> -- if no filename, tftped from host with file name in 'Default host flash file name'", + ""); + + cmd_addcmd("c", + ui_cmd_change_bootline, + NULL, + "Change booline parameters", + "", + ""); + + cmd_addcmd("p", + ui_cmd_print_system_info, + NULL, + "Print boot line and board parameter info", + "", + ""); + + cmd_addcmd("r", + ui_cmd_run_program, + NULL, + "Run program from flash image or from host depend on [f/h] flag", + "eg. r [[hostip:]filenaem]<cr> if no filename, use the file name in 'Default host run file name'", + ""); + +#if (INC_SPI_PROG_NAND==1) + cmd_addcmd("n", + ui_cmd_erase_nand, + NULL, + "Erase NAND flash", + "e [a]", + ""); +#else + if( flash_get_flash_type() == FLASH_IFC_NAND ) + cmd_addcmd("e", + ui_cmd_erase_nand, + NULL, + "Erase NAND flash", + "e [a]", + ""); + else +#endif + cmd_addcmd("e", + ui_cmd_erase, + NULL, + "Erase [n]vram or [a]ll flash except bootrom", + "e [n/a]", + ""); + + cmd_addcmd("w", + ui_cmd_write_whole_image, + NULL, + "Write the whole image start from beginning of the flash", + "eg. w [hostip:]whole_image_file_name", + ""); + + cmd_addcmd("chw", + ui_cmd_write_chk_image, + NULL, + "Write chkw image start from beginning of the flash", + "eg. chkw [hostip:]whole_image_file_name", + ""); + + cmd_addcmd("dm", + ui_cmd_dump_mem, + NULL, + "Dump memory or registers.", + "eg. dm address_in_hex length_in_decimal", + ""); + + cmd_addcmd("sm", + ui_cmd_set_mem, + NULL, + "Set memory or registers.", + "eg. sm address_in_hex value_in_hex size_4_2_or_1", + ""); + + cmd_addcmd("nmrp", + ui_cmd_nmrp, + NULL, + "start memory or registers.", + "eg. nmrp ", + ""); + + cmd_addcmd("fr", + ui_cmd_flash_read, + NULL, + "read data from flash.", + "eg. fr addr ", + ""); + + /* Foxconn add start by Cliff Wang, 03/23/2010 */ + cmd_addcmd("checkmem", + ui_cmd_check_mem, + NULL, + "Check memory.", + "Check memory.", + ""); + + ui_init_tftpdcmds(); + /* Foxconn add end by Cliff Wang, 03/23/2010 */ + + return 0; +} + + +static int runDelay(int delayCount) +{ + int goAuto = 0; + + if (delayCount == 0) + return goAuto; + + printf("*** Press any key to stop auto run (%d seconds) ***\n", delayCount); + printf("Auto run second count down: %d", delayCount); + + cfe_sleep(CFE_HZ/8); // about 1/4 second + + while (1) + { + printf("\b%d", delayCount); + cfe_sleep(CFE_HZ); // about 1 second + if (console_status()) + break; + if (--delayCount == 0) + { + goAuto = 1; + break; + } + } + printf("\b%d\n", delayCount); + + return goAuto; +} + + +int bcm63xx_run(int breakIntoCfe) +{ + int goAuto; + + ui_init_bcm63xx_cmds(); + printSysInfo(); + enet_init(); + + goAuto = runDelay(bootInfo.bootDelay); + if (!breakIntoCfe && runDelay(bootInfo.bootDelay)) + { + /* Foxconn add start by Cliff Wang, 03/23/2010 */ + if(_start_nmrp() != 0) + autoRun(NULL); // never returns + /* Foxconn add end by Cliff Wang, 03/23/2010 */ + } + return goAuto; +} + + diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_devs.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_devs.c new file mode 100755 index 0000000..ac75083 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_devs.c @@ -0,0 +1,734 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Board device initialization File: bcm94710_devs.c + * + * This is the "C" part of the board support package. The + * routines to create and initialize the console, wire up + * device drivers, and do other customization live here. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * XX Copyright 2000,2001 + * Broadcom Corporation. All rights reserved. + * + * BROADCOM PROPRIETARY AND CONFIDENTIAL + * + * This software is furnished under license and may be used and + * copied only in accordance with the license. + ********************************************************************* */ + +#include "lib_types.h" +#include "lib_printf.h" + +/* Foxconn add start by Cliff Wang, 03/23/2010 */ +#include "lib_string.h" +/* Foxconn add end by Cliff Wang, 03/23/2010 */ + +#include "cfe_timer.h" +#include "cfe.h" +#include "bcm_map.h" +#include "bcm_hwdefs.h" +#include "bcmTag.h" +#include "dev_bcm63xx_flash.h" +#include "bcm63xx_util.h" +#include "flash_api.h" + +/* Foxconn add start by Cliff Wang, 03/23/2010 */ +#include "tftpd.h" +/* Foxconn add end by Cliff Wang, 03/23/2010 */ + +static int checkForResetToDefaultHold( unsigned short rstToDfltIrq ); + +/* Foxconn added start , 1/29/2010 */ +#include "gpio_drv.h" +#include "foxconnCfg.h" + +typedef enum +{ + kGpioInactive, + kGpioActive +} GPIO_STATE_t; +static int test_led_control(int on_off); +int power_led_toggle(int state); +int nmrp_led_toggle(void); +int verify_board_id(char *buf); +int verify_checksum(char *buf, unsigned long buf_len, unsigned long chksum); +#define NR_LED 24 +/* Foxconn added end , 1/29/2010 */ + +/* ********************************************************************* + * Devices we're importing + ********************************************************************* */ + +extern cfe_driver_t bcm63xx_uart; +extern cfe_driver_t bcm63xx_enet; + +/* ********************************************************************* + * board_console_init() + * + * Add the console device and set it to be the primary + * console. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +void board_console_init(void) +{ + /* Add the serial port driver. */ + cfe_add_device(&bcm63xx_uart,0,0,0); + + cfe_set_console( "uart0" ); +} + + +/* ********************************************************************* + * board_device_init() + * + * Initialize and add other devices. Add everything you need + * for bootstrap here, like disk drives, flash memory, UARTs, + * network controllers, etc. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +void board_device_init(void) +{ + unsigned short GPIOOverlays; + + kerSysFlashInit(); + +#if defined (_BCM96328_) + if( BpGetGPIOverlays(&GPIOOverlays) == BP_SUCCESS ) { + /* Start with all HW LEDs disabled */ + LED->ledHWDis |= 0xFFFFFF; + if (GPIOOverlays & BP_OVERLAY_SERIAL_LEDS) { + GPIO->PinMuxSel |= PINMUX_SERIAL_LED_DATA; + GPIO->PinMuxSel |= PINMUX_SERIAL_LED_CLK; + LED->ledInit |= LED_SERIAL_LED_EN; + } + /* Enable LED controller to drive GPIO */ + /* foxconn modified start to let hardware control only act LEDs, Bob, 08/04/2010 */ + if (GPIOOverlays & BP_OVERLAY_EPHY_LED_0) { + GPIO->PinMuxSel |= PINMUX_EPHY0_ACT_LED; + //GPIO->GPIOMode |= (1 << EPHY0_SPD_LED); + //LED->ledHWDis &= ~(1 << EPHY0_SPD_LED); + } + if (GPIOOverlays & BP_OVERLAY_EPHY_LED_1) { + GPIO->PinMuxSel |= PINMUX_EPHY1_ACT_LED; + //GPIO->GPIOMode |= (1 << EPHY1_SPD_LED); + //LED->ledHWDis &= ~(1 << EPHY1_SPD_LED); + } + if (GPIOOverlays & BP_OVERLAY_EPHY_LED_2) { + GPIO->PinMuxSel |= PINMUX_EPHY2_ACT_LED; + //GPIO->GPIOMode |= (1 << EPHY2_SPD_LED); + //LED->ledHWDis &= ~(1 << EPHY2_SPD_LED); + } + if (GPIOOverlays & BP_OVERLAY_EPHY_LED_3) { + GPIO->PinMuxSel |= PINMUX_EPHY3_ACT_LED; + //GPIO->GPIOMode |= (1 << EPHY3_SPD_LED); + //LED->ledHWDis &= ~(1 << EPHY3_SPD_LED); + } + /* foxconn modified end, Bob, 08/04/2010 */ + } +#endif + +#if defined (_BCM96362_) + if( BpGetGPIOverlays(&GPIOOverlays) == BP_SUCCESS ) { + /* Start with all HW LEDs disabled */ + LED->ledHWDis |= 0xFFFFFF; + if (GPIOOverlays & BP_OVERLAY_SERIAL_LEDS) { + GPIO->GPIOMode |= (GPIO_MODE_SERIAL_LED_CLK | GPIO_MODE_SERIAL_LED_DATA); + LED->ledInit |= LED_SERIAL_LED_EN; + } + /* Map HW LEDs to LED controller inputs and enable LED controller to drive GPIO */ + if (GPIOOverlays & BP_OVERLAY_EPHY_LED_0) { + LED->ledLinkActSelHigh |= ((1 << (LED_ENET0 - 4)) << LED_4_LINK_SHIFT); + GPIO->LEDCtrl |= (1 << LED_ENET0); + LED->ledHWDis &= ~(1 << LED_ENET0); + } + if (GPIOOverlays & BP_OVERLAY_EPHY_LED_1) { + LED->ledLinkActSelHigh |= ((1 << (LED_ENET1 - 4)) << LED_5_LINK_SHIFT); + GPIO->LEDCtrl |= (1 << LED_ENET1); + LED->ledHWDis &= ~(1 << LED_ENET1); + } + if (GPIOOverlays & BP_OVERLAY_EPHY_LED_2) { + LED->ledLinkActSelHigh |= ((1 << (LED_ENET2 - 4)) << LED_6_LINK_SHIFT); + GPIO->LEDCtrl |= (1 << LED_ENET2); + LED->ledHWDis &= ~(1 << LED_ENET2); + } + if (GPIOOverlays & BP_OVERLAY_EPHY_LED_3) { + LED->ledLinkActSelHigh |= ((1 << (LED_ENET3 - 4)) << LED_7_LINK_SHIFT); + GPIO->LEDCtrl |= (1 << LED_ENET3); + LED->ledHWDis &= ~(1 << LED_ENET3); + } + } +#endif + +#if defined (_BCM96368_) + TIMER->WDResetCount = 50000; // Assert reset for 1ms only. If reset asserted for too + // long chip reboots twice + if( BpGetGPIOverlays(&GPIOOverlays) == BP_SUCCESS ) { + if (GPIOOverlays & BP_OVERLAY_EPHY_LED_0) { + GPIO->GPIOMode |= GPIO_MODE_EPHY0_LED; + GPIO->GPIODir |= GPIO_MODE_EPHY0_LED; + } + + if (GPIOOverlays & BP_OVERLAY_EPHY_LED_1) { + GPIO->GPIOMode |= GPIO_MODE_EPHY1_LED; + GPIO->GPIODir |= GPIO_MODE_EPHY1_LED; + } + + if (GPIOOverlays & BP_OVERLAY_EPHY_LED_2) { + GPIO->GPIOMode |= GPIO_MODE_EPHY2_LED; + GPIO->GPIODir |= GPIO_MODE_EPHY2_LED; + } + + if (GPIOOverlays & BP_OVERLAY_EPHY_LED_3) { + GPIO->GPIOMode |= GPIO_MODE_EPHY3_LED; + GPIO->GPIODir |= GPIO_MODE_EPHY3_LED; + } + + if (GPIOOverlays & BP_OVERLAY_SERIAL_LEDS) { + GPIO->GPIOMode |= (GPIO_MODE_SERIAL_LED_CLK | GPIO_MODE_SERIAL_LED_DATA); + GPIO->GPIODir |= (GPIO_MODE_SERIAL_LED_CLK | GPIO_MODE_SERIAL_LED_DATA); + GPIO->SerialLed = 0xffffffff; + } + } + + /* These blocks will be enabled by the appropriate driver if they are + * compiled into a router image. + */ + PERF->blkEnables &= ~(USBH_CLK_EN | PCM_CLK_EN | SAR_CLK_EN | USBD_CLK_EN); +#endif + +#if defined (_BCM96816_) + TIMER->WDResetCount = 50000; // Assert reset for 1ms only. If reset asserted for too + // long chip reboots twice + + if( BpGetGPIOverlays(&GPIOOverlays) == BP_SUCCESS ) { + if (GPIOOverlays & BP_OVERLAY_GPHY_LED_0) { + GPIO->GPIOMode |= GPIO_MODE_GPHY0_LED; + GPIO->GPIODir |= GPIO_MODE_GPHY0_LED; + } + + if (GPIOOverlays & BP_OVERLAY_GPHY_LED_1) { + GPIO->GPIOMode |= GPIO_MODE_GPHY1_LED; + GPIO->GPIODir |= GPIO_MODE_GPHY1_LED; + } + + if (GPIOOverlays & BP_OVERLAY_SERIAL_LEDS) { + GPIO->GPIOMode |= (GPIO_MODE_SERIAL_LED_CLK | GPIO_MODE_SERIAL_LED_DATA); + GPIO->GPIODir |= (GPIO_MODE_SERIAL_LED_CLK | GPIO_MODE_SERIAL_LED_DATA); + GPIO->SerialLed = 0xffffffff; + } + + if (GPIOOverlays & BP_OVERLAY_MOCA_LED) { + GPIO->GPIOMode |= GPIO_MODE_MOCA_LED; + GPIO->GPIODir |= GPIO_MODE_MOCA_LED; + } + } + + MISC->miscMoCARst &= ~(MISC_MOCA_RST_REF_DIV2RST | MISC_MOCA_RST_REF_FBDIVRST); + MISC->miscMoCARst &= ~MISC_MOCA_RST_REF_VCRST; + MISC->miscMoCARst &= ~(MISC_MOCA_RST_REF_OUTDIV_RESET_M_MASK | MISC_MOCA_RST_REF_MDIV2RST); + MISC->miscMoCACtl |= (7 << MISC_MOCA_CTL_REF_QP_ICTRL_SHIFT); + MISC->miscMoCARst &= ~MISC_MOCA_RST_REF_LD_RESET_STRT; + PERF->softResetB &= ~(SOFT_RST_MOCA_CPU | SOFT_RST_MOCA_SYS | SOFT_RST_MOCA); +#endif + +#if defined (_BCM96328_) || defined (_BCM96362_) + LED->ledInit &= ~LED_FAST_INTV_MASK; + LED->ledInit |= (LED_INTERVAL_20MS * 4) << LED_FAST_INTV_SHIFT; +#else + /* Set blink rate for hardware LEDs. */ + GPIO->LEDCtrl &= ~LED_INTERVAL_SET_MASK; + GPIO->LEDCtrl |= LED_INTERVAL_SET_80MS; +#endif + + /* Add the ethernet driver. */ + cfe_add_device( &bcm63xx_enet, 0, 0, 0); +} + + +void setGpio (unsigned short led_gpio, unsigned short led_state) +{ +#if 0 + unsigned short gpio_state; + + if (((led_gpio & BP_ACTIVE_LOW) && (led_state == LED_ON)) || + (!(led_gpio & BP_ACTIVE_LOW) && (led_state == LED_OFF))) + gpio_state = 0; + else + gpio_state = 1; +#endif + + GPIO->GPIODir |= GPIO_NUM_TO_MASK(led_gpio); + if( led_state ) + GPIO->GPIOio |= GPIO_NUM_TO_MASK(led_gpio); + else + GPIO->GPIOio &= ~GPIO_NUM_TO_MASK(led_gpio); +} + + +/* ********************************************************************* + * board_final_init() + * + * Do any final initialization, such as adding commands to the + * user interface. + * + * If you don't want a user interface, put the startup code here. + * This routine is called just before CFE starts its user interface. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +void board_final_init(void) +{ + unsigned short rstToDfltIrq; + int breakIntoCfe = 0; + + /* Foxconn add start by Cliff Wang, 03/23/2010 */ + int goAuto; + /* Foxconn add end by Cliff Wang, 03/23/2010 */ + + setAllLedsOff(); + setPowerOnLedOn(); + setGpio(GPIO_POWER_RED_LED, GPIO_POWER_RED_LED_ON); +#if (INC_SPI_PROG_NAND==1) + rstToDfltIrq = 1 ; + breakIntoCfe = rstToDfltIrq; +#else + if( (bootInfo.runFrom == 'f') && getBootImageTag() == NULL ) { + setBreakIntoCfeLed(); + printf("** Flash image not found. **\n\n"); + kerSysErasePsi(); + breakIntoCfe = 1; + } + + if( BpGetResetToDefaultExtIntr( &rstToDfltIrq ) == BP_SUCCESS ) { + if (checkForResetToDefaultHold( rstToDfltIrq )) { + kerSysErasePsi(); + /* Reset the default bootline if the board IP address has changed. */ + if (strcmp(bootInfo.boardIp, DEFAULT_BOARD_IP) != 0) { + setDefaultBootline(); + } + /* Foxconn modified start pling 09/09/2008 */ + /* just load default, don't break into console */ + //breakIntoCfe = 1; + printf("\n** Load default! **\n\n"); + /* Foxconn modified end pling 09/09/2008 */ + } + } +#endif + /* Foxconn add start by Cliff Wang, 03/23/2010 */ + goAuto = bcm63xx_run(breakIntoCfe); + setBreakIntoCfeLed(); + if(goAuto) + { + ui_docommand("tftpd"); + } + /* Foxconn add end by Cliff Wang, 03/23/2010 */ +} + +/* ********************************************************************* + * Miscellaneous Board Functions + ********************************************************************* */ + +/* ********************************************************************* + * checkForResetToDefaultHold() + * + * Determines if the user is holding the reset to default button. + * + * Input parameters: + * Reset to default irq# + * + * Return value: + * 1 - break into the CFE, 0 - continue boot sequence + ********************************************************************* */ +#if (INC_SPI_PROG_NAND==0) +static int checkForResetToDefaultHold( unsigned short rstToDfltIrq ) +{ + const int nBreakIntoCfeDelay = 5; + int ret = 0; + int i; + uint32 irqBit; + volatile uint32 *extIrqReg; + + extIrqReg = &PERF->ExtIrqCfg; + irqBit = 1 << (rstToDfltIrq + EI_STATUS_SHFT); + +#if defined(_BCM96368_) + if (rstToDfltIrq >= BP_EXT_INTR_4 && rstToDfltIrq <= BP_EXT_INTR_5) { + extIrqReg = &PERF->ExtIrqCfg1; + irqBit = 1 << (rstToDfltIrq - BP_EXT_INTR_4 + EI_STATUS_SHFT); + } +#endif + + /* Loop while the reset to default button is depressed. */ + for(i = 0; !(*extIrqReg & irqBit); i++) { + if (i == nBreakIntoCfeDelay) { + setBreakIntoCfeLed(); + printf("\n*** Break into CFE console ***\n\n"); + ret = 1; + break; + } + cfe_sleep(CFE_HZ); + } + + return( ret ); +} +#endif +/* ********************************************************************* + * setLed(led_gpio, led_state) + * + * Turns on an LED. + * + * Input parameters: + * LED purpose + * LED State + * + * Return value: + * nothing + ********************************************************************* */ + +void setLed (unsigned short led_gpio, unsigned short led_state) +{ + unsigned short gpio_state; + + if (((led_gpio & BP_ACTIVE_LOW) && (led_state == LED_ON)) || + (!(led_gpio & BP_ACTIVE_LOW) && (led_state == LED_OFF))) + gpio_state = 0; + else + gpio_state = 1; + +#if defined(_BCM96328_) + /* Enable LED controller to drive this GPIO */ + if (!(led_gpio & BP_GPIO_SERIAL)) + GPIO->GPIOMode |= GPIO_NUM_TO_MASK(led_gpio); +#endif + +#if defined(_BCM96362_) + /* Enable LED controller to drive this GPIO */ + if (!(led_gpio & BP_GPIO_SERIAL)) + GPIO->LEDCtrl |= GPIO_NUM_TO_MASK(led_gpio); +#endif + +#if defined(_BCM96328_) || defined(_BCM96362_) + LED->ledMode &= ~(LED_MODE_MASK << GPIO_NUM_TO_LED_MODE_SHIFT(led_gpio)); + if( gpio_state ) + LED->ledMode |= (LED_MODE_OFF << GPIO_NUM_TO_LED_MODE_SHIFT(led_gpio)); + else + LED->ledMode |= (LED_MODE_ON << GPIO_NUM_TO_LED_MODE_SHIFT(led_gpio)); + +#else + if (led_gpio & BP_GPIO_SERIAL) { + while (GPIO->SerialLedCtrl & SER_LED_BUSY); + if( gpio_state ) + GPIO->SerialLed |= GPIO_NUM_TO_MASK(led_gpio); + else + GPIO->SerialLed &= ~GPIO_NUM_TO_MASK(led_gpio); + } + else { + GPIO->GPIODir |= GPIO_NUM_TO_MASK(led_gpio); + if( gpio_state ) + GPIO->GPIOio |= GPIO_NUM_TO_MASK(led_gpio); + else + GPIO->GPIOio &= ~GPIO_NUM_TO_MASK(led_gpio); + } +#endif +} + +/* ********************************************************************* + * setAllLedsOff() + * + * Turns off all board LEDs on init + * + * Input parameters: + * LED purpose + * + * Return value: + * nothing + ********************************************************************* */ + +void setAllLedsOff(void) +{ + unsigned short gpio; + + if( BpGetAdslLedGpio( &gpio ) == BP_SUCCESS ) + setLed( gpio, LED_OFF ); + if( BpGetAdslFailLedGpio( &gpio ) == BP_SUCCESS ) + setLed( gpio, LED_OFF ); + if( BpGetSecAdslLedGpio( &gpio ) == BP_SUCCESS ) + setLed( gpio, LED_OFF ); + if( BpGetSecAdslFailLedGpio( &gpio ) == BP_SUCCESS ) + setLed( gpio, LED_OFF ); + if( BpGetWirelessSesLedGpio( &gpio ) == BP_SUCCESS ) + setLed( gpio, LED_OFF ); + if( BpGetHpnaLedGpio( &gpio ) == BP_SUCCESS ) + setLed( gpio, LED_OFF ); + if( BpGetWanDataLedGpio( &gpio ) == BP_SUCCESS ) + setLed( gpio, LED_OFF ); + if( BpGetWanErrorLedGpio( &gpio ) == BP_SUCCESS ) + setLed( gpio, LED_OFF ); + if( BpGetBootloaderPowerOnLedGpio( &gpio ) == BP_SUCCESS ) + setLed( gpio, LED_OFF ); + if( BpGetBootloaderStopLedGpio( &gpio ) == BP_SUCCESS ) + setLed( gpio, LED_OFF ); + if( BpGetVoipLedGpio( &gpio ) == BP_SUCCESS ) + setLed( gpio, LED_OFF ); + if( BpGetVoip1LedGpio( &gpio ) == BP_SUCCESS ) + setLed( gpio, LED_OFF ); + if( BpGetVoip2LedGpio( &gpio ) == BP_SUCCESS ) + setLed( gpio, LED_OFF ); + if( BpGetPotsLedGpio( &gpio ) == BP_SUCCESS ) + setLed( gpio, LED_OFF ); + if( BpGetGponLedGpio( &gpio ) == BP_SUCCESS ) + setLed( gpio, LED_OFF ); + if( BpGetMoCALedGpio( &gpio ) == BP_SUCCESS ) + setLed( gpio, LED_OFF ); + if( BpGetGponFailLedGpio( &gpio ) == BP_SUCCESS ) + setLed( gpio, LED_OFF ); + if( BpGetMoCAFailLedGpio( &gpio ) == BP_SUCCESS ) + setLed( gpio, LED_OFF ); +} + +/* ********************************************************************* + * setPowerOnLedOn() + * + * Turns on the Power LED. + * + * Input parameters: + * LED purpose + * + * Return value: + * nothing + ********************************************************************* */ + +void setPowerOnLedOn(void) +{ + unsigned short gpio; + if( BpGetBootloaderStopLedGpio( &gpio ) == BP_SUCCESS ) + setLed( gpio, LED_OFF ); + if( BpGetBootloaderPowerOnLedGpio( &gpio ) == BP_SUCCESS ) + setLed( gpio, LED_ON ); +} + + +/* ********************************************************************* + * setBreakIntoCfeLed() + * + * Turns on the alarm LED. + * + * Input parameters: + * LED purpose + * + * Return value: + * nothing + ********************************************************************* */ + +void setBreakIntoCfeLed(void) +{ + unsigned short gpio; + if( BpGetBootloaderStopLedGpio( &gpio ) == BP_SUCCESS ) { + setLed( gpio, LED_ON ); + if( BpGetBootloaderPowerOnLedGpio( &gpio ) == BP_SUCCESS ) + setLed( gpio, LED_OFF ); + } +} + +/* ********************************************************************* + * softReset() + * + * Resets the board. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +void softReset(void) +{ + printf( "\nResetting board...\n" ); +#if defined (_BCM96816_) + /* Work around reset issues */ + HVG->reg_hvg_cha_misc |= HVG_SOFT_INIT_0; + HVG->reg_hvg_chb_misc |= HVG_SOFT_INIT_0; +#endif + +#if defined(_BCM96328_) + TIMER->SoftRst |= SOFT_RESET; +#else + PERF->pll_control |= SOFT_RESET; // soft reset mips +#if defined(_BCM96368_) || defined(_BCM96816_) + PERF->pll_control = 0; +#endif +#endif + while (1); +} + +/* Foxconn added start , 1/29/2010 */ +extern int nmrp_server_detected; + +int test_led_control(int on_off) +{ + // unsigned short gpio; + int tftpd_state = get_tftpd_state(); + + if (tftpd_state == TFTPD_STATE_OFF) + { + setGpio(GPIO_POWER_RED_LED, GPIO_POWER_RED_LED_ON); //turn red power led + } + else if ( (tftpd_state == TFTPD_STATE_WAIT_IMAGE) || (tftpd_state == TFTPD_STATE_WRITE_IMAGE) ) + { + if (on_off==1) + { + setGpio(GPIO_POWER_RED_LED, GPIO_POWER_RED_LED_ON); + } + else + { + setGpio(GPIO_POWER_RED_LED, GPIO_POWER_RED_LED_OFF); + } + } + + return 0; +} + +int power_led_toggle(int state) +{ + test_led_control(state); + return 0; +} + +int nmrp_led_toggle(void) +{ + static int led_state = 0; + + /* Foxconn added end for U12H154 */ + + if (led_state == 0) + { + led_state = 1; + setGpio(18, 1); + } + else + { + led_state = 0; + setGpio(18, 0); + } + + return 0; +} + + +static unsigned long calculate_checksum (int action, char *s, int size) +{ + static unsigned long c0, c1; + unsigned long checksum, b; + int i; + switch (action) + { + case 0: + c0 = c1 = 0; + break; + + case 1: + for (i = 0; i < size; i++) + { + c0 += s[i] & 0xff; + c1 += c0; + /* check the lan/wan ports status, Foxconn added by EricHuang, 10/24/2006 */ + if ((i % 90000) == 0) + { + printf("."); +// bcm_robo_check_link_status(); + } + } + break; + + case 2: + b = (c0 & 65535) + ((c0 >> 16) & 65535); + c0 = ((b >> 16) + b) & 65535; + + b = (c1 & 65535) + ((c1 >> 16) & 65535); + c1 = ((b >> 16) + b) & 65535; + + checksum = ((c1 << 16) | c0); + + return checksum; + } + return 0; +} + +int verify_checksum(char *buf, unsigned long buf_len, unsigned long chksum) +{ + unsigned long cal_chksum = 0; + + xprintf("Loading ."); + calculate_checksum (0, NULL, 0); + calculate_checksum (1, buf, buf_len); + cal_chksum = calculate_checksum (2, NULL, 0); + printf("\n"); + + + if (cal_chksum != chksum) { + xprintf("Image chksum: 0x%08X\n", chksum); + xprintf("Calc chksum: 0x%08X\n", cal_chksum); + return -1; + } + +#ifdef _DEBUG + //printf("verify_checksum calculate_checksum = 0x%08X\n", cal_chksum); + //printf("verify_checksum image_chksum = 0x%08X\n", chksum); +#endif + + return 0; +} + +int verify_board_id(char *buf) +{ + /* char *board_id = ( char *)BOARD_DATA_ADDR; */ + char board_id[PROJECT_ID_LEN]; + + kerSysReadFromFlash(board_id, BOARD_DATA_ADDR, PROJECT_ID_LEN); + + if(nmrp_server_detected==1) // in NMRP mode + { + if (strncmp(buf, board_id, PROJECT_ID_LEN) != 0) + { + printf("verify_board_id failed: (%s)\n", buf); + return -1; + } + } + else + { + if (strcmp(buf, board_id) != 0) + { + /* Foxconn removed start pling 12/10/2008 */ + /* Don't check board ID in 'tftpd' mode */ + printf("verify_board_id failed: (%s)\n", buf); + //return -1; + /* Foxconn removed end pling 12/10/2008 */ + } + } + return 0; +} + +/* Foxconn added end , 1/29/2010 */ + diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_env_subr.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_env_subr.c new file mode 100755 index 0000000..3ce3a28 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_env_subr.c @@ -0,0 +1,277 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Environment variable subroutines File: env_subr.c + * + * This module contains routines to muck with environment variables + * (manage the list, read/write to nvram, etc.) + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + +#include "lib_types.h" +#include "lib_string.h" +#include "lib_queue.h" +#include "lib_malloc.h" +#include "lib_printf.h" + +#include "env_subr.h" +///#include "nvram_subr.h" + +#include "cfe_error.h" +#include "cfe.h" + +/* ********************************************************************* + * Types + ********************************************************************* */ + +typedef struct cfe_envvar_s { + queue_t qb; + int flags; + char *name; + char *value; + /* name and value go here */ +} cfe_envvar_t; + +/* ********************************************************************* + * Globals + ********************************************************************* */ + +queue_t env_envvars = {&env_envvars,&env_envvars}; +extern unsigned int cfe_startflags; + +/* ********************************************************************* + * env_findenv(name) + * + * Locate an environment variable in the in-memory list + * + * Input parameters: + * name - name of env var to find + * + * Return value: + * cfe_envvar_t pointer, or NULL if not found + ********************************************************************* */ + +static cfe_envvar_t *env_findenv(const char *name) +{ + queue_t *qb; + cfe_envvar_t *env; + + for (qb = env_envvars.q_next; qb != &env_envvars; qb = qb->q_next) { + env = (cfe_envvar_t *) qb; + if (strcmp(env->name,name) == 0) break; + } + + if (qb == &env_envvars) return NULL; + + return (cfe_envvar_t *) qb; + +} + +/* ********************************************************************* + * env_enum(idx,name,namelen,val,vallen) + * + * Enumerate environment variables. This routine locates + * the nth environment variable and copies its name and value + * to user buffers. + * + * The namelen and vallen variables must be preinitialized to + * the maximum size of the output buffer. + * + * Input parameters: + * idx - variable index to find (starting with zero) + * name,namelen - name buffer and length + * val,vallen - value buffer and length + * + * Return value: + * 0 if ok + * else error code + ********************************************************************* */ + +int env_enum(int idx,char *name,int *namelen,char *val,int *vallen) +{ + queue_t *qb; + cfe_envvar_t *env; + + for (qb = env_envvars.q_next; qb != &env_envvars; qb = qb->q_next) { + if (idx == 0) break; + idx--; + } + + if (qb == &env_envvars) return CFE_ERR_ENVNOTFOUND; + env = (cfe_envvar_t *) qb; + + *namelen = xstrncpy(name,env->name,*namelen); + *vallen = xstrncpy(val,env->value,*vallen); + + return 0; + +} + +/* ********************************************************************* + * env_envtype(name) + * + * Return the type of the environment variable + * + * Input parameters: + * name - name of environment variable + * + * Return value: + * flags, or <0 if error occured + ********************************************************************* */ +int env_envtype(const char *name) +{ + cfe_envvar_t *env; + + env = env_findenv(name); + + if (env) { + return env->flags; + } + + return CFE_ERR_ENVNOTFOUND; +} + + + +/* ********************************************************************* + * env_delenv(name) + * + * Delete an environment variable + * + * Input parameters: + * name - environment variable to delete + * + * Return value: + * 0 if ok + * else error code + ********************************************************************* */ + +int env_delenv(const char *name) +{ + cfe_envvar_t *env; + + env = env_findenv(name); + + if (!env) return 0; + + if (!(env->flags & ENV_FLG_READONLY)) { + q_dequeue((queue_t *) env); + KFREE(env); + return 0; + } + + return CFE_ERR_ENVNOTFOUND; +} + +/* ********************************************************************* + * env_getenv(name) + * + * Retrieve the value of an environment variable + * + * Input parameters: + * name - name of environment variable to find + * + * Return value: + * value, or NULL if variable is not found + ********************************************************************* */ + +char *env_getenv(const char *name) +{ + cfe_envvar_t *env; + + env = env_findenv(name); + + if (env) { + return env->value; + } + + return NULL; +} + + +/* ********************************************************************* + * env_setenv(name,value,flags) + * + * Set the value of an environment variable + * + * Input parameters: + * name - name of variable + * value - value of variable + * flags - flags for variable (ENV_FLG_xxx) + * + * Return value: + * 0 if ok + * else error code + ********************************************************************* */ + +int env_setenv(const char *name,char *value,int flags) +{ + cfe_envvar_t *env; + int namelen; + + env = env_findenv(name); + if (env) { + if (!(flags & ENV_FLG_ADMIN)) { + if (env->flags & ENV_FLG_READONLY) return CFE_ERR_ENVREADONLY; + } + q_dequeue((queue_t *) env); + KFREE(env); + } + + namelen = strlen(name); + + env = KMALLOC(sizeof(cfe_envvar_t) + namelen + 1 + strlen(value) + 1,0); + if (!env) return CFE_ERR_NOMEM; + + env->name = (char *) (env+1); + env->value = env->name + namelen + 1; + env->flags = (flags & ENV_FLG_MASK); + + strcpy(env->name,name); + strcpy(env->value,value); + + q_enqueue(&env_envvars,(queue_t *) env); + + return 0; +} +int env_save(void) +{ + return 0; +} diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_httpd.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_httpd.c new file mode 100755 index 0000000..dcd5b0a --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_httpd.c @@ -0,0 +1,1031 @@ +/* milli_httpd - pretty small HTTP server +** A combination of +** micro_httpd - really small HTTP server +** and +** mini_httpd - small HTTP server +** +** Copyright 1999,2000 by Jef Poskanzer <jef@acme.com>. +** All rights reserved. +** +** 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. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. +*/ + +#if (CFG_WEB_SERVER==1) + +/** Includes. **/ + +#include "lib_types.h" +#include "lib_string.h" +#include "lib_queue.h" +#include "lib_malloc.h" +#include "lib_printf.h" + +#include "cfe_timer.h" +#include "cfe_error.h" +#include "cfe.h" +#include "cfe_iocb.h" +#include "cfe_devfuncs.h" + +#include "bsp_config.h" + +#include "bcmTag.h" +#include "bcm63xx_util.h" + + +/** Externs. **/ + +extern char ul_html[]; +extern char ulinfo_html[]; +extern int ul_html_size; +extern int ulinfo_html_size; + +extern int g_console_abort; +extern int g_processing_cmd; + +/** Defines. **/ + +#define SERVER_NAME "micro_httpd" +#define SERVER_URL "http://www.acme.com/software/micro_httpd/" +#define SERVER_PORT 80 +#define PROTOCOL "HTTP/1.0" +#define POST_DATA_START (unsigned char *) \ + BOARD_IMAGE_DOWNLOAD_ADDRESS +#define SOCKET_CLOSED -100 +#define NUM_SOCKETS 4 + +/* Return codes from cfe_web_gets. */ +#define WEB_GETS_DONE 1 +#define WEB_GETS_PENDING 2 +#define WEB_GETS_ERROR 3 + +/* HTTP states. */ +#define HTTP_INITIAL 0 +#define HTTP_READ_FIRST_HDR 1 +#define HTTP_READ_REMAINING_HDRS 2 +#define HTTP_READ_POST_DATA 3 + +/* HTTP POST status */ +#define UPLOAD_OK '0' +#define UPLOAD_FAIL_NO_MEM '1' +#define UPLOAD_FAIL_NO_FILENAME '2' +#define UPLOAD_FAIL_ILLEGAL_IMAGE '3' +#define UPLOAD_FAIL_IMAGE_TOOBIG '4' +#define UPLOAD_FAIL_CORRUPT_IMAGE '5' +#define UPLOAD_FAIL_FLASH '6' +#define UPLOAD_FATAL '7' +#define UPLOAD_PENDING '8' +#define UPLOAD_TCP_ERROR '9' + +/* HTTP upload image formats. */ +#define NO_IMAGE_FORMAT 0 +#define BROADCOM_IMAGE_FORMAT 1 +#define FLASH_IMAGE_FORMAT 2 + + +/** Structs. **/ + +typedef struct +{ + int s; + int state; + int web_buf_idx; + int post_content_length; + char web_first_buf[128]; + char web_buf[256]; +} SOCKET_INFO, *PSOCKET_INFO; + +typedef struct +{ + char *wp_name; + char *wp_content_buf; + int *wp_content_size; + char *wp_mime_type; +} WEB_PAGE_MAP, *PWEB_PAGE_MAP; + + +/** Globals. **/ + +static int g_listen_idx = 0; +static unsigned char *g_image_start = NULL; +static int g_image_len = 0; +static int g_image_format = NO_IMAGE_FORMAT; +static int g_post_data_in_progress = 0; +static int g_post_data_idx = 0; + +static SOCKET_INFO g_socket_info[NUM_SOCKETS]; + +static WEB_PAGE_MAP g_web_page_map[] = + { + {"/", ul_html, &ul_html_size, "text/html"}, + {"/upload.html", ul_html, &ul_html_size, "text/html"}, + {"/uploadinfo.html", ulinfo_html, &ulinfo_html_size, "text/html"}, + {NULL, NULL, 0, NULL} + }; + + +/** Prototypes. **/ + +int cfe_web_check(void); +void cfe_web_fg_process(void); +void cfe_web_poll(void *x); +static void cfe_web_listen( int *listen_idx_ptr ); +static void cfe_web_bg_process(PSOCKET_INFO si); +static int cfe_web_gets( char *web_buf, int web_buf_size, + int *web_buf_idx_ptr, int s ); +static int read_first_hdr(int s, char *web_buf, int web_buf_size, + int *web_buf_idx_ptr, int *close_tcp_ptr); +static int read_remaining_hdrs(int s, char *web_buf, int web_buf_size, + int *web_buf_idx_ptr, int *close_tcp_ptr, int *content_length_ptr); +static char read_post_data( int s, unsigned char *post_data_start, + int content_length, int *post_data_idx_ptr ); +static char parse_post_data( int s, unsigned char *post_data_start, + int post_data_length, unsigned char **image_start_ptr, int *image_len_ptr, + int *image_format_ptr ); +static void send_error( int s, int status, char* title, char* extra_header, + char* text ); +static void send_error( int s, int status, char* title, char* extra_header, + char* text ); +static void send_headers( int s, int status, char* title, char* extra_header, + char* mime_type ); +static void send_page( int s, char *path, int send_headers_flag, + char **substs, int num_substs ); +static int cfe_web_tcp_send( int s, char *buf, int size ); +void * memmove(void * dest,const void *src,size_t count); + + +/*************************************************************************** + * Function Name: cfe_web_check + * Description : Checks if an image has been downloaded through an HTTP POST + * request and is ready to be written to flash memory. + * Returns : 1 - image is ready to be flashed, 0 - nothing to do + ***************************************************************************/ +int cfe_web_check(void) +{ + return( (g_image_format != NO_IMAGE_FORMAT) ? 1 : 0 ); +} /* cfe_web_check */ + + +/*************************************************************************** + * Function Name: cfe_web_process + * Description : Calls the appropriate functions to write an image to + * flash memory. + * Returns : None. + ***************************************************************************/ +void cfe_web_fg_process(void) +{ + /* Wait so the uploadinfo web page can be displayed on the browser. */ + cfe_sleep(CFE_HZ * 2); + if( g_image_format == BROADCOM_IMAGE_FORMAT ) + flashImage( g_image_start ); + else + if( g_image_format == FLASH_IMAGE_FORMAT ) + writeWholeImage( g_image_start, g_image_len ); + + if( g_image_format != NO_IMAGE_FORMAT ) + softReset(); + +} /* cfe_web_process */ + + +/*************************************************************************** + * Function Name: cfe_web_poll + * Description : The entry point function that is called in the background + * at polled intervals. It listens for and processes HTTP + * requests. + * Returns : None. + ***************************************************************************/ +void cfe_web_poll(void *x) +{ + static int first_time = 1; + static int in_cfe_web_poll = 0; + + PSOCKET_INFO si; + int i; + + if( in_cfe_web_poll == 0 ) + { + in_cfe_web_poll = 1; + + /* If this is the first time that this function was called, initialize + * the socket info data array. + */ + if( first_time == 1 ) + { + first_time = 0; + for( i = 0, si = g_socket_info; i < NUM_SOCKETS; i++, si++ ) + { + si->s = SOCKET_CLOSED; + si->state = HTTP_READ_FIRST_HDR; + si->web_buf_idx = 0; + si->post_content_length = 0; + } + } + + /* Check the connection state of each socket. */ + for( i = 0, si = g_socket_info; i < NUM_SOCKETS; i++, si++ ) + { + cfe_web_listen( &g_listen_idx ); + if( si->s >= 0 ) + { + unsigned int connflag; + tcp_status( si->s, &connflag, NULL, NULL ); + if( connflag == TCPSTATUS_CONNECTED ) + { + cfe_web_bg_process( si ); + POLL(); + } + else + if( connflag == TCPSTATUS_NOTCONN ) + { + console_log("web warning: Unexpected TCP disconnect."); + tcp_close(si->s); + si->s = SOCKET_CLOSED; + si->state = HTTP_READ_FIRST_HDR; + si->web_buf_idx = 0; + } + } + } + + in_cfe_web_poll = 0; + } +} /* cfe_web_poll */ + + +/*************************************************************************** + * Function Name: cfe_web_listen + * Description : This function checks to see if TCP listen can be issued + * on the HTTP port and issues the listen if it can. + * Returns : None. + ***************************************************************************/ +static void cfe_web_listen( int *listen_idx_ptr ) +{ + static int port = SERVER_PORT; + + int listen_idx = *listen_idx_ptr; + PSOCKET_INFO si = &g_socket_info[listen_idx]; + + /* If a TCP socket has been opened, check its connection status. */ + if( si->s >= 0 ) + { + unsigned int connflag; + tcp_status( si->s, &connflag, NULL, NULL ); + + /* If the socket is connection, set the next socket index to listen for + * a TCP connection. + */ + if( connflag == TCPSTATUS_CONNECTED ) + { + listen_idx = (listen_idx + 1) % NUM_SOCKETS; + si = &g_socket_info[listen_idx]; + } + } + + /* If the TCP socket has not been opened, open it and listen for a TCP + * connection. + */ + if( si->s == SOCKET_CLOSED ) + { + /* Open the socket in non-blocking mode. */ + POLL(); + if( (si->s = tcp_socket()) >= 0 ) + { + console_log("web info: Waiting for connection on socket %d.", si->s); + if( tcp_listen(si->s, port) != 0 ) + console_log("web error: listen error on %d.", si->s); + } + else + { + console_log("web error %d: Could not create TCP socket.", si->s); + si->s = SOCKET_CLOSED; + } + } + + *listen_idx_ptr = listen_idx; +} /* cfe_web_listen */ + + +/*************************************************************************** + * Function Name: cfe_web_bg_process + * Description : This function processes an HTTP request on a socket. + * Returns : None. + ***************************************************************************/ +static void cfe_web_bg_process(PSOCKET_INFO si) +{ + char post_subst[] = {UPLOAD_FATAL, '\0'}; + char *post_substs[] = {post_subst}; + int close_tcp = 0; + + switch( si->state ) + { + case HTTP_READ_FIRST_HDR: + if( read_first_hdr( si->s, si->web_first_buf, + sizeof(si->web_first_buf), &si->web_buf_idx, &close_tcp ) == 0 ) + { + /* Not all of the first header has been read yet. Try again later.*/ + break; + } + + /* The first header has been read. */ + si->state = HTTP_READ_REMAINING_HDRS; + + /* fall thru */ + + case HTTP_READ_REMAINING_HDRS: + if( read_remaining_hdrs( si->s, si->web_buf, sizeof(si->web_buf), + &si->web_buf_idx, &close_tcp, &si->post_content_length ) ) + { + if( g_processing_cmd == 0 ) + { + char *method = NULL; + char *path = NULL; + char *ptr = (char *) si->web_first_buf; + + method = gettoken(&ptr); + if( method ) + path = gettoken(&ptr); + + /* Process the HTTP request. Only GET and POST are supported. */ + if( method && path ) + { + if( !strcmpi( method, "get" ) ) + { + send_page( si->s, path, 1, NULL, 0 ); + close_tcp = 1; + } + else + { + if( !strcmpi( method, "post" ) ) + { + if( g_post_data_in_progress == 0 ) + { + g_post_data_in_progress = 1; + si->state = HTTP_READ_POST_DATA; + } + else + { + send_error( si->s, 501, "Upload Busy", + (char*) 0, + "An image is already being uploaded." ); + close_tcp = 1; + } + } + else + { + send_error( si->s, 501, "Not Implemented", + (char*) 0, + "That method is not implemented." ); + close_tcp = 1; + } + } + } + else + { + send_error( si->s, 400, "Bad Request", (char *) 0, + "Can't parse request." ); + close_tcp = 1; + } + } + else + { + /* A download and flash image command is being executed from + * the serial port console. + */ + send_error( si->s, 400, "Bad Request", (char *) 0, + "Console command is in progress." ); + close_tcp = 1; + } + } + + if( si->state != HTTP_READ_POST_DATA ) + break; + + case HTTP_READ_POST_DATA: + /* Read the post data, which contains an image to flash, into low + * memory. + */ + if( (post_subst[0] = read_post_data( si->s, POST_DATA_START, + si->post_content_length, &g_post_data_idx )) == UPLOAD_OK ) + { + /* Verify that the post data is a valid image to flash. */ + post_subst[0] = parse_post_data( si->s, POST_DATA_START, + g_post_data_idx, (unsigned char **) &g_image_start, &g_image_len, + &g_image_format ); + } + + switch( post_subst[0] ) + { + case UPLOAD_PENDING: + break; + + case UPLOAD_TCP_ERROR: + close_tcp = 1; + g_post_data_in_progress = 0; + g_post_data_idx = 0; + break; + + case UPLOAD_OK: + /* Notify foreground to abort the console input so it can + * write the image to flash memory. + */ + g_console_abort = 1; + + send_page(si->s, "/uploadinfo.html", 0, post_substs, 1); + close_tcp = 1; + g_post_data_idx = 0; + break; + + default: + /* The image was downloaded OK but there was a problem with it + * so it could not be written to flash memory. + */ + send_page(si->s, "/uploadinfo.html", 0, post_substs, 1); + close_tcp = 1; + g_post_data_in_progress = 0; + g_post_data_idx = 0; + break; + } + break; + } + + /* Close the socket if the HTTP transaction is done. */ + if( close_tcp ) + { + POLL(); + tcp_close(si->s); + si->s = SOCKET_CLOSED; + si->state = HTTP_READ_FIRST_HDR; + si->web_buf_idx = 0; + si->post_content_length = 0; + } +} /* cfe_web_poll */ + + +/*************************************************************************** + * Function Name: cfe_web_gets + * Description : Reads from a socket up to a <CR><LF> or <LF>. The socket + * is non-blocking. + * Returns : WEB_GETS_DONE - Complete line was read. + * WEB_GETS_PENDING - Line partially read. + * WEB_GETS_ERROR - Socket error. + ***************************************************************************/ +static int cfe_web_gets( char *web_buf, int web_buf_size, + int *web_buf_idx_ptr, int s ) +{ + int ret = WEB_GETS_PENDING; + unsigned char ch; + int web_buf_idx = *web_buf_idx_ptr; + char *p = web_buf + web_buf_idx; + int continue_reading = 1; + + while( web_buf_idx < web_buf_size && continue_reading ) + { + switch( tcp_recv( s, &ch, 1 ) ) + { + case 0: /* no characters are available to receive */ + continue_reading = 0; + break; + + case 1: /* character was read */ + if( ch == '\n' ) + { + *p = '\0'; + continue_reading = 0; + ret = WEB_GETS_DONE; + } + else + if( ch != '\r' ) + { + *p++ = ch; + web_buf_idx++; + } + break; + + default: + continue_reading = 0; + ret = WEB_GETS_ERROR; + break; + } + } + + if( web_buf_idx == web_buf_size ) + { + web_buf[web_buf_idx - 1] = '\0'; + ret = WEB_GETS_DONE; + } + + *web_buf_idx_ptr = web_buf_idx; + + return( ret ); +} /* cfe_web_gets */ + + +/*************************************************************************** + * Function Name: read_first_hdr + * Description : This function reads the first HTTP header which contains + * the method (GET, POST), path and protocol. For example, + * GET /upload.html HTTP/1.1 + * Returns : 1 - First header was read, 0 - was not read. + ***************************************************************************/ +static int read_first_hdr(int s, char *web_buf, int web_buf_size, + int *web_buf_idx_ptr, int *close_tcp_ptr) +{ + int ret = 0; + int sts = cfe_web_gets( web_buf, web_buf_size, web_buf_idx_ptr, s ); + + switch( sts ) + { + case WEB_GETS_DONE: + /* The first HTTP header has been read into web_buf. */ + *web_buf_idx_ptr = 0; + ret = 1; + break; + + case WEB_GETS_ERROR: + console_log("web error: TCP read error."); + *close_tcp_ptr = 1; + break; + } + + return( ret ); +} /* read_first_hdr */ + + +/*************************************************************************** + * Function Name: read_remaining_hdrs + * Description : This function reads the remaining HTTP headers. + * Returns : 1 - Remaining headers were read, 0 - were not read. + ***************************************************************************/ +static int read_remaining_hdrs(int s, char *web_buf, int web_buf_size, + int *web_buf_idx_ptr, int *close_tcp_ptr, int *content_length_ptr) +{ + int ret = 0; + int sts = WEB_GETS_DONE; + + while( sts == WEB_GETS_DONE ) + { + sts = cfe_web_gets( web_buf, web_buf_size, web_buf_idx_ptr, s ); + switch( sts ) + { + case WEB_GETS_DONE: + if( *web_buf_idx_ptr == 0 ) + { + /* The remaining HTTP headers have been read. */ + ret = 1; + sts = WEB_GETS_PENDING; + } + else + { + char *p2 = web_buf; + char *p1 = gettoken(&p2); + if( !strcmpi( p1, "Content-Length:" ) ) + *content_length_ptr=atoi(p2); + *web_buf_idx_ptr = 0; + } + break; + + case WEB_GETS_ERROR: + console_log("web error: TCP read error."); + *close_tcp_ptr = 1; + break; + } + } + + return( ret ); +} /* read_remaining_hdrs */ + + +/*************************************************************************** + * Function Name: read_post_data + * Description : This function reads HTTP POST data which is the contents of + * a new image to write to flash memory. + * Returns : UPLOAD_OK - all data read + * UPLOAD_PENDING - not all data read + * UPLOAD_TCP_ERROR - TCP error + ***************************************************************************/ +static char read_post_data( int s, unsigned char *post_data_start, + int content_length, int *post_data_idx_ptr ) +{ + char ret = UPLOAD_PENDING; + int post_data_idx = *post_data_idx_ptr; + int len; + + do + { + len = tcp_recv( s, (unsigned char*)(post_data_start + post_data_idx), + content_length - post_data_idx ); + post_data_idx += len; + POLL(); + cfe_web_listen( &g_listen_idx ); + } while( len > 0 && post_data_idx < content_length ); + + *post_data_idx_ptr = post_data_idx; + + if( len < 0 ) + { + console_log("web error: TCP read error receiving post data."); + ret = UPLOAD_TCP_ERROR; + } + else + if( post_data_idx == content_length ) + ret = UPLOAD_OK; + + return( ret ); +} /* read_post_data */ + + +/*************************************************************************** + * Function Name: parse_post_data + * Description : This function parses HTTP POST data which is the contents of + * a new image to write to flash memory. + * Returns : UPLOAD_OK or UPLOAD_xxx error + ***************************************************************************/ +static char parse_post_data( int s, unsigned char *post_data_start, + int post_data_length, unsigned char **image_start_ptr, int *image_len_ptr, + int *image_format_ptr ) +{ + char ret = UPLOAD_OK; + unsigned char *p = post_data_start; + int boundary_size = 0; + + /* Convert the start boundary field into a string. It will be compared + * against the end boundary field below. + */ + while( *p != '\r' && *p != '\n' && + ((int) p - (int) post_data_start) < post_data_length ) + { + p++; + } + + if( *p == '\r' || *p == '\n' ) + { + *p++ = '\0'; + boundary_size = strlen((char*)post_data_start); + } + else + { + console_log("web error: HTTP POST start bound field not found."); + ret = UPLOAD_FATAL; + } + + /* Verify that a filename has been entered. */ + if( ret == UPLOAD_OK ) + { + unsigned char *fname = NULL; + while( memcmp( p, "\r\n\r\n", strlen("\r\n\r\n") ) ) + { + if( *p == 'f' && !memcmp( p, "filename=", strlen("filename=" ) ) ) + { + p += strlen("filename="); + fname = p + 1; + if( p[0] == '"' && p[1] != '"' ) + { + p++; + while( *p != '"' && *p != '\r' && *p != '\n' ) + p++; + *p = '\0'; + } + else + { + console_log("web error: HTTP POST filename not specified."); + ret = UPLOAD_FAIL_NO_FILENAME; + } + break; + } + + p++; + } + + if( fname == NULL ) + { + console_log("web error: HTTP POST filename field not found."); + ret = UPLOAD_FATAL; + } + } + + /* Find the start of the image which starts after two consecutive + * carriage return, linefeed pairs. + */ + if( ret == UPLOAD_OK ) + { + while( memcmp( p, "\r\n\r\n", strlen("\r\n\r\n") ) ) + p++; + + p += strlen("\r\n\r\n"); + if( p[0] != '\r' || p[1] != '\n' || + memcmp(p + 2, post_data_start, boundary_size ) ) + { + *image_start_ptr = p; + } + else + { + console_log("web error: HTTP POST no image data."); + ret = UPLOAD_FAIL_ILLEGAL_IMAGE; + } + } + + /* Find the end of the image which contains the same boundary field as + * at the start of the buffer. + */ + if( ret == UPLOAD_OK ) + { + p = post_data_start + post_data_length - 1; + while( *p == '\r' || *p == '\n' || *p == '-' ) + p--; + p[1] = '\0'; + p -= boundary_size + 1; + if( !memcmp( p + strlen("\r\n"), post_data_start, boundary_size ) ) + *image_len_ptr = (int) p - (int) *image_start_ptr; + else + { + console_log("web error: HTTP POST end bound field not found."); + ret = UPLOAD_FATAL; + } + } + + /* Verify that the image is (or should be) a Broadcom flash format file or + * a flash image format. + */ + if( ret == UPLOAD_OK ) + { + /* Align the image on a 16 byte boundary */ + if( ((unsigned long) *image_start_ptr & 0x0f) != 0 ) + { + unsigned char *dest = (unsigned char *) + ((unsigned long) *image_start_ptr & ~0x0f); + unsigned char *src = *image_start_ptr; + memmove( dest, src, *image_len_ptr ); + *image_start_ptr = dest; + } + + /* Check if the first part of the image is the Broadcom defined TAG + * record. + */ + if( verifyTag( (FILE_TAG *) *image_start_ptr, 0 ) == -1 ) + { + /* It is not a Broadcom flash format file. Now check if it is a + * flash image format file. A flash image format file must have a + * CRC at the end of the image. + */ + unsigned char *image_ptr = *image_start_ptr; + unsigned long image_len = (unsigned long) *image_len_ptr - TOKEN_LEN; + unsigned long crc = CRC32_INIT_VALUE; + + crc = getCrc32(image_ptr, image_len, crc); + if (memcmp(&crc, image_ptr + image_len, CRC_LEN) == 0) + { + console_log("web info: Upload %lu bytes, flash image format.", + *image_len_ptr); + *image_format_ptr = FLASH_IMAGE_FORMAT; + } + else + { + console_log("web info: Upload %lu bytes, invalid image format.", + *image_len_ptr); + ret = UPLOAD_FAIL_ILLEGAL_IMAGE; + } + } + else + { + console_log("web info: Upload %lu bytes, Broadcom image format.", + *image_len_ptr); + *image_format_ptr = BROADCOM_IMAGE_FORMAT; + } + } + + return( ret ); +} /* parse_post_data */ + + +/*************************************************************************** + * Function Name: send_error + * Description : This function sends an HTTP error response to the browser. + * Returns : None. + ***************************************************************************/ +static void send_error( int s, int status, char* title, char* extra_header, + char* text ) +{ + int tcpret = 0; + char buf[128]; + send_headers( s, status, title, extra_header, "text/html" ); + sprintf( (char *) buf, "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\n" + "<BODY BGCOLOR=\"#cc9999\"><H4>%d %s</H4>\n", status, title, status, + title ); + tcpret = tcp_send( s, (unsigned char*)buf, strlen(buf) ); + sprintf( (char *) buf, "%s\n", text ); + tcpret = tcp_send( s, (unsigned char*)buf, strlen(buf) ); + sprintf( (char *) buf, "<HR>\n<ADDRESS><A HREF=\"%s\">%s</A></ADDRESS>\n" + "</BODY></HTML>\n", SERVER_URL, SERVER_NAME ); + tcpret = tcp_send( s, (unsigned char*)buf, strlen(buf) ); + + if( tcpret < 0 ) + console_log("web error: TCP write error sending error response."); +} /* send_error */ + + +/*************************************************************************** + * Function Name: send_headers + * Description : This function sends an HTTP response to the browser. + * Returns : None. + ***************************************************************************/ +static void send_headers( int s, int status, char* title, char* extra_header, + char* mime_type ) +{ + int tcpret = 0; + char buf[128]; + unsigned long secs = (unsigned long) cfe_ticks / CFE_HZ; + + sprintf( buf, "%s %d %s\r\n", PROTOCOL, status, title ); + tcpret = tcp_send( s, (unsigned char*)buf, strlen(buf) ); + sprintf( buf, "Server: %s\r\n", SERVER_NAME ); + tcpret = tcp_send( s, (unsigned char*)buf, strlen(buf) ); + sprintf( buf, "Date: Thu, 01 Jan 1970 %2.2d:%2.2d:%2.2d GMT\r\n", + secs / 3600, (secs % 3600) / 60, secs % 60 ); + tcpret = tcp_send( s, (unsigned char*)buf, strlen(buf) ); + if ( extra_header != (char*) 0 ) + { + sprintf( buf, "%s\r\n", extra_header ); + tcpret = tcp_send( s, (unsigned char*)buf, strlen(buf) ); + } + if ( mime_type != (char*) 0 ) + { + sprintf( buf, "Content-Type: %s\r\n", mime_type ); + tcpret = tcp_send( s, (unsigned char*)buf, strlen(buf) ); + } + sprintf( buf, "Connection: close\r\n\r\n" ); + tcpret = tcp_send( s, (unsigned char*)buf, strlen(buf) ); + + if( tcpret < 0 ) + console_log("web error: TCP write error sending header."); +} /* send_headers */ + + +/*************************************************************************** + * Function Name: send_page + * Description : This function sends a web page to the browser. + * Returns : None. + ***************************************************************************/ +static void send_page( int s, char *path, int send_headers_flag, + char **substs, int num_substs ) +{ + PWEB_PAGE_MAP map; + + /* Find the specified web page. */ + for( map = g_web_page_map; map->wp_name; map++ ) + { + if( !strcmp( map->wp_name, path ) ) + { + /* Found the web page. */ + char *p2 = NULL; + char *p = (char *) map->wp_content_buf; + int size = *map->wp_content_size; + int i = 0; + + if( send_headers_flag ) + send_headers( s, 200, "Ok", (char *) 0, map->wp_mime_type ); + + /* Make substitutions. */ + while( i < num_substs && (p2 = strnchr( p, '<', size )) != NULL ) + { + if( p2[1] == '%' ) + { + /* Found a substituion pattern. Send up to that point. */ + if( cfe_web_tcp_send( s, p, (int) (p2 - p) ) < 0 ) + break; + + /* Send substitution value. */ + if( cfe_web_tcp_send( s, substs[i], strlen(substs[i]) ) < 0 ) + break; + + i++; + + /* Skip to end of substitution pattern. */ + p = p2 + 2; /* skip '<%' */ + while( p[0] != '%' || p[1] != '>' ) + p++; + p += 2; /* skip '%.' */ + } + else + { + /* Was not a substitution pattern. Send up that point. */ + p2++; + if( cfe_web_tcp_send( s, p, (int) (p2 - p) ) < 0 ) + break; + + p = p2; + } + + size = *map->wp_content_size - ((int)p-(int)map->wp_content_buf); + } + + /* Send remaining part of web page after the last substitution. */ + cfe_web_tcp_send( s, p, size ); + + break; /* for loop */ + } + } + + if( map->wp_name == NULL ) + send_error( s, 404, "Not Found", (char*) 0, "File not found." ); +} /* send_page */ + + +/*************************************************************************** + * Function Name: cfe_web_tcp_send + * Description : Sends data on a TCP non blocking connection and waits for + * it to finish. + * Returns : > 0 - bytes send, < 0 - TCP error + ***************************************************************************/ +static int cfe_web_tcp_send( int s, char *buf, int size ) +{ + int i, len = 0; + + for( i = 0; i < size; i += len ) + { + POLL(); + cfe_web_listen( &g_listen_idx ); + len = tcp_send( s, (unsigned char*)(buf + i), size - i ); + if( len < 0 ) + { + console_log("web error: TCP write error sending a web page."); + break; + } + } + + return( len ); +} /* cfe_web_tcp_send */ + + +/** + * memmove - Copy one area of memory to another + * @dest: Where to copy to + * @src: Where to copy from + * @count: The size of the area. + * + * Unlike memcpy(), memmove() copes with overlapping areas. + */ +void * memmove(void * dest,const void *src,size_t count) +{ + char *tmp, *s; + + if (dest <= src) { + tmp = (char *) dest; + s = (char *) src; + while (count--) + *tmp++ = *s++; + } + else { + tmp = (char *) dest + count; + s = (char *) src + count; + while (count--) + *--tmp = *--s; + } + + return dest; +} + +#else + +/*************************************************************************** + * Function Name: Functions stubs. + * Description : Used when the web server is not compiled into the CFE. + * Returns : None. + ***************************************************************************/ + +int cfe_web_check(void); +void cfe_web_fg_process(void); +void cfe_web_poll(void *x); + +int cfe_web_check(void) +{ + return(0); +} + +void cfe_web_fg_process(void) +{ +} + +void cfe_web_poll(void *x) +{ +} + +#endif + diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ldr_elf.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ldr_elf.c new file mode 100755 index 0000000..fb3f122 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ldr_elf.c @@ -0,0 +1,388 @@ + +//********** for boot -elf thing from cfe_ldr_elf.c +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * ELF Program Loader File: cfe_ldr_elf.c + * + * This program parses ELF executables and loads them into memory. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#include "lib_types.h" +#include "lib_string.h" +#include "lib_queue.h" +#include "lib_malloc.h" +#include "lib_printf.h" + +#include "cfe_iocb.h" +#include "cfe_device.h" +#include "cfe_console.h" +#include "cfe_error.h" +#include "cfe_devfuncs.h" +#include "cfe_timer.h" +#include "cfe_mem.h" + +#include "cfe.h" +#include "cfe_loader.h" +#include "cfe_fileops.h" +#include "elf.h" + +#include "cfe_boot.h" + +/* ********************************************************************* + * Externs + ********************************************************************* */ + +int bcm63xx_cfe_elfload(cfe_loadargs_t *la); + +const cfe_loader_t elfloader = { + "elf", + bcm63xx_cfe_elfload, + 0}; + +/* ********************************************************************* + * readprogsegment(fsctx,ref,addr,size) + * + * Read a program segment, generally corresponding to one + * section of the file. + * + * Input parameters: + * fsctx - file I/O dispatch + * ref - reference data for open file handle + * addr - target virtual address + * size - size of region to read + * + * Return value: + * Number of bytes copied or <0 if error occured + ********************************************************************* */ + +static int readprogsegment(fileio_ctx_t *fsctx,void *ref, + void *addr,int size,int flags) +{ + int res; + +#ifdef __long64 + if (flags & LOADFLG_NOISY) xprintf("0x%016llx/%d ",addr,size); +#else + if (flags & LOADFLG_NOISY) xprintf("0x%x/%d ",addr,size); +#endif + + res = fs_read(fsctx,ref,addr,size); + + if (res < 0) return CFE_ERR_IOERR; + if (res != size) return CFE_ERR_BADELFFMT; + + return size; +} + + +/* ********************************************************************* + * readclearbss(addr,size) + * + * Process a BSS section, zeroing memory corresponding to + * the BSS. + * + * Input parameters: + * addr - address to zero + * size - length of area to zero + * + * Return value: + * number of zeroed bytes or <0 if error occured + ********************************************************************* */ + +static int readclearbss(void *addr,int size,int flags) +{ + +#ifdef __long64 + if (flags & LOADFLG_NOISY) xprintf("0x%016llx/%d ",addr,size); +#else + if (flags & LOADFLG_NOISY) xprintf("0x%x/%d ",addr,size); +#endif + + if (size > 0) memset(addr,0,size); + return size; +} + + +/* ********************************************************************* + * elfgetshdr(ops,ref,ep) + * + * Get a section header from the ELF file + * + * Input parameters: + * ops - file I/O dispatch + * ref - reference data for open file + * ep - extended header info + * + * Return value: + * copy of section header (malloc'd) or NULL if no memory + ********************************************************************* */ + +static Elf32_Shdr *elfgetshdr(fileio_ctx_t *fsctx,void *ref,Elf32_Ehdr *ep) +{ + Elf32_Shdr *shtab; + unsigned size = ep->e_shnum * sizeof(Elf32_Shdr); + + shtab = (Elf32_Shdr *) KMALLOC(size,0); + if (!shtab) { + return NULL; + } + + if (fs_seek(fsctx,ref,ep->e_shoff,FILE_SEEK_BEGINNING) != ep->e_shoff || + fs_read(fsctx,ref,(uint8_t *)shtab,size) != size) { + KFREE(shtab); + return NULL; + } + + return (shtab); +} + +/* ********************************************************************* + * elfload_internal(ops,ref,entrypt,flags) + * + * Read an ELF file (main routine) + * + * Input parameters: + * ops - file I/O dispatch + * ref - open file handle + * entrypt - filled in with entry vector + * flags - generic boot flags + * + * Return value: + * 0 if ok + * else error code + ********************************************************************* */ + +static int elfload_internal(fileio_ctx_t *fsctx,void *ref, + long *entrypt,int flags) +{ + Elf32_Ehdr *ep; + Elf32_Phdr *phtab = 0; + Elf32_Shdr *shtab = 0; + unsigned int nbytes; + int i; + int res; + Elf32_Ehdr ehdr; + + ep = &ehdr; + if (fs_read(fsctx,ref,(uint8_t *) ep,sizeof(*ep)) != sizeof(*ep)) { + return CFE_ERR_IOERR; + } + + /* check header validity */ + if (ep->e_ident[EI_MAG0] != ELFMAG0 || + ep->e_ident[EI_MAG1] != ELFMAG1 || + ep->e_ident[EI_MAG2] != ELFMAG2 || + ep->e_ident[EI_MAG3] != ELFMAG3) { + return CFE_ERR_NOTELF; + } + + if (ep->e_ident[EI_CLASS] != ELFCLASS32) return CFE_ERR_NOT32BIT; + +#ifdef __MIPSEB + if (ep->e_ident[EI_DATA] != ELFDATA2MSB) return CFE_ERR_WRONGENDIAN; /* big endian */ +#endif +#ifdef __MIPSEL + if (ep->e_ident[EI_DATA] != ELFDATA2LSB) return CFE_ERR_WRONGENDIAN; /* little endian */ +#endif + + if (ep->e_ident[EI_VERSION] != EV_CURRENT) return CFE_ERR_BADELFVERS; + if (ep->e_machine != EM_MIPS) return CFE_ERR_NOTMIPS; + + /* Is there a program header? */ + if (ep->e_phoff == 0 || ep->e_phnum == 0 || + ep->e_phentsize != sizeof(Elf32_Phdr)) { + return CFE_ERR_BADELFFMT; + } + + /* Load program header */ + nbytes = ep->e_phnum * sizeof(Elf32_Phdr); + phtab = (Elf32_Phdr *) KMALLOC(nbytes,0); + if (!phtab) { + return CFE_ERR_NOMEM; + } + + if (fs_seek(fsctx,ref,ep->e_phoff,FILE_SEEK_BEGINNING) != ep->e_phoff || + fs_read(fsctx,ref,(uint8_t *)phtab,nbytes) != nbytes) { + KFREE(phtab); + return CFE_ERR_IOERR; + } + + /* + * From now on we've got no guarantee about the file order, + * even where the section header is. Hopefully most linkers + * will put the section header after the program header, when + * they know that the executable is not demand paged. We assume + * that the symbol and string tables always follow the program + * segments. + */ + + /* read section table (if before first program segment) */ + if (ep->e_shoff < phtab[0].p_offset) { + shtab = elfgetshdr(fsctx,ref,ep); + } + + /* load program segments */ + /* We cope with a badly sorted program header, as produced by + * older versions of the GNU linker, by loading the segments + * in file offset order, not in program header order. */ + + while (1) { + Elf32_Off lowest_offset = ~0; + Elf32_Phdr *ph = 0; + + /* find nearest loadable segment */ + for (i = 0; i < ep->e_phnum; i++) + if ((phtab[i].p_type == PT_LOAD) && (phtab[i].p_offset < lowest_offset)) { + ph = &phtab[i]; + lowest_offset = ph->p_offset; + } + if (!ph) { + break; /* none found, finished */ + } + /* load the segment */ + if (ph->p_filesz) { + if (fs_seek(fsctx,ref,ph->p_offset,FILE_SEEK_BEGINNING) != ph->p_offset) { + if (shtab) KFREE(shtab); + KFREE(phtab); + return CFE_ERR_BADELFFMT; + } + res = readprogsegment(fsctx,ref, + (void *)(intptr_t)(signed)ph->p_vaddr, + ph->p_filesz,flags); + if (res != ph->p_filesz) { + if (shtab) KFREE(shtab); + KFREE(phtab); + return res; + } + } + if (ph->p_filesz < ph->p_memsz) { + res = readclearbss((void *)(intptr_t)(signed)ph->p_vaddr + ph->p_filesz, + ph->p_memsz - ph->p_filesz,flags); + if (res < 0) { + if (shtab) KFREE(shtab); + KFREE(phtab); + return res; + } + } + + ph->p_type = PT_NULL; /* remove from consideration */ + } + + KFREE(phtab); + + *entrypt = (intptr_t)ep->e_entry; /* return entry point */ + return 0; +} + + + +/* ********************************************************************* + * cfe_elfload(ops,file,flags) + * + * Read an ELF file (main entry point) + * + * Input parameters: + * ops - fileio dispatch + * file - name of file to read + * ept - where to put entry point + * flags - load flags + * + * Return value: + * 0 if ok, else error code + ********************************************************************* */ + +int bcm63xx_cfe_elfload(cfe_loadargs_t *la) +{ + fileio_ctx_t *fsctx; + void *ref; + int res; + + /* + * Look up the file system type and get a context + */ + + + res = fs_init(la->la_filesys,&fsctx,la->la_device); + if (res != 0) { + return res; + } + + /* + * Turn on compression if we're doing that. + */ + + if (la->la_flags & LOADFLG_COMPRESSED) { + res = fs_hook(fsctx,"z"); + if (res != 0) { + return res; + } + } + + /* + * Open the remote file + */ + + res = fs_open(fsctx,&ref,la->la_filename,FILE_MODE_READ); + if (res != 0) { + fs_uninit(fsctx); + return CFE_ERR_FILENOTFOUND; + } + + /* + * Load the image. + */ + + la->la_entrypt = 0; + res = elfload_internal(fsctx,ref,&(la->la_entrypt),la->la_flags); + + /* + * All done, release resources + */ + + fs_close(fsctx,ref); + fs_uninit(fsctx); + + return res; +} + + diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ldr_raw.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ldr_raw.c new file mode 100755 index 0000000..eaabf14 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ldr_raw.c @@ -0,0 +1,368 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * RAW Program Loader File: cfe_ldr_raw.c + * + * This program reads raw binaries into memory. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + +#include "lib_types.h" +#include "lib_string.h" +#include "lib_queue.h" +#include "lib_malloc.h" +#include "lib_printf.h" + +#include "cfe_iocb.h" +#include "cfe_device.h" +#include "cfe_error.h" +#include "cfe_devfuncs.h" + +#include "cfe.h" +#include "cfe_fileops.h" + +#include "cfe_boot.h" +#include "cfe_bootblock.h" + +#include "cfe_loader.h" + +/* ********************************************************************* + * Externs + ********************************************************************* */ + +int bcm63xx_cfe_rawload(cfe_loadargs_t *la); + +const cfe_loader_t rawloader = { + "raw", + bcm63xx_cfe_rawload, + 0}; + +/* ********************************************************************* + * cfe_findbootblock(la,fsctx,ref) + * + * Find the boot block on the specified device. + * + * Input parameters: + * la - loader args (to be filled in) + * ops - file operations + * ref - reference for open file handle + * + * Return value: + * 0 if ok + * else error code + ********************************************************************* */ +static int cfe_findbootblock(cfe_loadargs_t *la, + fileio_ctx_t *fsctx, + void *ref, + struct boot_block *bootblock) +{ + uint32_t checksum = 0; + uint32_t calcsum = 0; + uint32_t secsize = 0; + uint64_t secoffset = 0; + int res; + int curblk; + + /* + * Search for the boot block. Stop when we find + * something with a matching checksum and magic + * number. + */ + + fs_seek(fsctx,ref,0,FILE_SEEK_BEGINNING); + + for (curblk = 0; curblk < BOOT_BLOCK_MAXLOC; curblk++) { + + + /* Read a block */ + + res = fs_read(fsctx,ref, + (unsigned char *) bootblock, + sizeof(struct boot_block)); + + if (res != sizeof(struct boot_block)) { + return CFE_ERR_IOERR; + } + + /* Verify magic number */ + +#if defined(CONFIG_MIPS_BRCM) + continue; +#else + if (bootblock->bb_magic != BOOT_MAGIC_NUMBER) { + continue; + } +#endif + + /* Extract fields from block */ + + checksum = ((uint32_t) (bootblock->bb_hdrinfo & BOOT_HDR_CHECKSUM_MASK)); + bootblock->bb_hdrinfo &= ~BOOT_HDR_CHECKSUM_MASK; + secsize = ((uint32_t) (bootblock->bb_secsize & BOOT_SECSIZE_MASK)); + secoffset = bootblock->bb_secstart; + + /* Verify block's checksum */ + + CHECKSUM_BOOT_DATA(&(bootblock->bb_magic),BOOT_BLOCK_SIZE,&calcsum); + + if (checksum == calcsum) { + break; + } + } + + /* + * Okay, determine if we were successful. + */ + +#if !defined(CONFIG_MIPS_BRCM) + if (bootblock->bb_magic != BOOT_MAGIC_NUMBER) { + return CFE_ERR_INVBOOTBLOCK; + } +#endif + + if (checksum != calcsum) { + return CFE_ERR_BBCHECKSUM; + } + + /* + * If we get here, we had a valid boot block. + */ + + return 0; +} + + +/* ********************************************************************* + * cfe_rawload(la) + * + * Read a raw (unformatted) boot file + * + * Input parameters: + * la - loader args + * + * Return value: + * 0 if ok, else error code + ********************************************************************* */ +int bcm63xx_cfe_rawload(cfe_loadargs_t *la) +{ + int res; + fileio_ctx_t *fsctx; + const fileio_dispatch_t *ops; + void *ref; + int ttlcopy = 0; + int findbb; + int devinfo; + struct boot_block bootblock; + uint8_t *ptr; + uint8_t *bootcode; +#if !defined(CONFIG_MIPS_BRCM) + uint32_t checksum,calcsum; +#endif + uint64_t secoffset = 0; + int32_t maxsize; + int amtcopy; + int thisamt; + uint32_t loadflags; + int onedot; + + loadflags = la->la_flags; + + /* + * Set starting address and maximum size. You can either + * explicitly set this (with LOADFLG_SPECADDR) or + * let CFE decide. If CFE decides, the load address + * will be BOOT_START_ADDRESS in all cases. + * The size is dependant on the device type: block and flash + * devices will get this info from the boot block, + * and network devices will get the info by reaching EOF + * on reads, up to the maximum size of the boot area. + */ + + if (loadflags & LOADFLG_SPECADDR) { + bootcode = (uint8_t *) la->la_address; + maxsize = la->la_maxsize; + findbb = FALSE; /* don't find a boot block */ + } + else { + bootcode = (uint8_t *) BOOT_START_ADDRESS; + maxsize = BOOT_AREA_SIZE; + findbb = FALSE; + devinfo = la->la_device ? cfe_getdevinfo(la->la_device) : 0; + + /* + * If the device is either a disk or a flash device, + * we will expect to find a boot block. + * Serial and network devices do not have boot blocks. + */ + if ((devinfo >= 0) && + ( ((devinfo & CFE_DEV_MASK) == CFE_DEV_DISK) || + ((devinfo & CFE_DEV_MASK) == CFE_DEV_FLASH) )) { + findbb = TRUE; + } + } + + + /* + * merge in any filesystem-specific flags + */ + + ops = cfe_findfilesys(la->la_filesys); + if (!ops) return CFE_ERR_FSNOTAVAIL; + loadflags |= ops->loadflags; + + /* + * turn off the boot block if requested. + */ + + if (loadflags & LOADFLG_NOBB) findbb = FALSE; + + /* + * Create a file system context + */ + + res = fs_init(la->la_filesys,&fsctx,la->la_device); + if (res != 0) { + return res; + } + + /* + * Turn on compression if we're doing that. + */ + + if (!findbb && (la->la_flags & LOADFLG_COMPRESSED)) { + res = fs_hook(fsctx,"z"); + if (res != 0) { + return res; + } + } + + /* + * Open the boot device + */ + + res = fs_open(fsctx,&ref,la->la_filename,FILE_MODE_READ); + if (res != 0) { + fs_uninit(fsctx); + return res; + } + + /* + * If we need to find a boot block, do it now. + */ + + if (findbb) { + res = cfe_findbootblock(la,fsctx,ref,&bootblock); + + /* + * If we found the boot block, seek to the part of the + * disk where the boot code is. + * Otherwise, get out now, since the disk has no boot block. + */ + + if (res == 0) { + maxsize = (int) ((uint32_t) (bootblock.bb_secsize & BOOT_SECSIZE_MASK)); + secoffset = bootblock.bb_secstart; + fs_seek(fsctx,ref,secoffset,FILE_SEEK_BEGINNING); + } + else { + fs_close(fsctx,ref); + fs_uninit(fsctx); + return res; + } + + } + + /* + * Okay, go load the boot file. + */ + + ptr = bootcode; + amtcopy = maxsize; + ttlcopy = 0; + + onedot = amtcopy / 10; /* ten dots for entire load */ + if (onedot < 4096) onedot = 4096; /* but minimum 4096 bytes per dot */ + onedot = (onedot + 1) & ~4095; /* round to multiple of 4096 */ + + while (amtcopy > 0) { + thisamt = onedot; + if (thisamt > amtcopy) thisamt = amtcopy; + + res = fs_read(fsctx,ref,ptr,thisamt); + if (la->la_flags & LOADFLG_NOISY) { + xprintf("."); + } + if (res <= 0) break; + ptr += res; + amtcopy -= res; + ttlcopy += res; + } + + /* + * We're done with the file. + */ + + fs_close(fsctx,ref); + fs_uninit(fsctx); + + /* + * Verify the boot loader checksum if we were reading + * the disk. + */ + +#if !defined(CONFIG_MIPS_BRCM) + if (findbb) { + CHECKSUM_BOOT_DATA(bootcode,maxsize,&calcsum); + checksum = (uint32_t) ((bootblock.bb_secsize & BOOT_DATA_CHECKSUM_MASK) + >> BOOT_DATA_CHECKSUM_SHIFT); + + if (checksum != calcsum) { + return CFE_ERR_BOOTPROGCHKSUM; + } + } +#endif + + la->la_entrypt = (uintptr_t) bootcode; + + if (la->la_flags & LOADFLG_NOISY) xprintf(" %d bytes read\n",ttlcopy); + + return (res < 0) ? res : ttlcopy; + +} diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_main.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_main.c new file mode 100755 index 0000000..2cf2546 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_main.c @@ -0,0 +1,611 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Main Module File: cfe_main.c + * + * This module contains the main "C" routine for CFE and + * the main processing loop. There should not be any board-specific + * stuff in here. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#include "lib_types.h" +#include "lib_string.h" +#include "lib_malloc.h" +#include "lib_printf.h" + +#include "cfe_iocb.h" +#include "cfe_device.h" +#include "cfe_console.h" +#include "cfe_timer.h" + +#include "env_subr.h" +#include "cfe_mem.h" +#include "cfe.h" + +#include "exception.h" + +#include "bsp_config.h" +#include "bcm_hwdefs.h" +#include "boardparms.h" +#include "bcm_map.h" +#include "bcm_cpu.h" +#include "bcm63xx_util.h" + +#include "segtable.h" +#include "initdata.h" + +/* ********************************************************************* + * Constants + ********************************************************************* */ + +#ifndef CFG_STACK_SIZE +#define STACK_SIZE 8192 +#else +#define STACK_SIZE ((CFG_STACK_SIZE+1023) & ~1023) +#endif + +/* ********************************************************************* + * Externs + ********************************************************************* */ + +void cfe_main(int,int); +void cfe_command_restart(uint64_t status); + +extern void cfe_device_poll(void *x); + +extern int cfe_web_check(void); +extern void cfe_web_fg_process(void); +extern void cfe_web_poll(void *x); + +extern const char *builddate; +extern const char *builduser; + +/* Foxconn add start by Cliff Wang, 03/23/2010 */ +extern int ui_init_netcmds(void); +/* Foxconn add end by Cliff Wang, 03/23/2010 */ + +/* ********************************************************************* + * Globals + ********************************************************************* */ + +const char *cfe_boardname = CFG_BOARDNAME; +unsigned int cfe_startflags = 0; +#if defined (_BCM96368_) +static int cfe_bus_speed = 0; +static int cfe_ref_speed = 0; +#endif +#if defined (_BCM96328_) || defined (_BCM96362_) || defined (_BCM96816_) +static int cfe_bus_speed = 0; +static int cfe_ddr_speed = 0; +#endif +unsigned long cfe_sdramsize = 8 * 1024 * 1024; + +static void calculateCpuSpeed(void); + +#if defined (_BCM96328_) +const uint32 cpu_speed_table[0x20] = { + 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, + 0, 320, 160, 200, 160, 200, 400, 320, 320, 160, 384, 320, 192, 320, 320, 320 +}; +const uint32 ddr_speed_table[0x20] = { + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 0, 80, 100, 100, 160, 200, 400, 400, 80, 160, 160, 160, 192, 192, 240, 320 +}; +const uint32 bus_speed_table[0x20] = { + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 0, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160 +}; +#endif + +#if defined (_BCM96362_) +const uint32 cpu_speed_table[0x20] = { + 320, 320, 320, 240, 160, 400, 440, 384, 320, 320, 320, 240, 160, 320, 400, 320, + 320, 320, 320, 240, 160, 200, 400, 384, 320, 320, 320, 240, 160, 200, 400, 400 +}; +const uint32 ddr_speed_table[0x20] = { + 320, 400, 192, 320, 200, 400, 367, 320, 320, 400, 192, 320, 200, 400, 400, 320, + 320, 400, 192, 320, 200, 267, 400, 320, 320, 320, 192, 320, 200, 200, 400, 333 +}; +const uint32 bus_speed_table[0x20] = { + 160, 200, 96, 160, 100, 160, 183, 160, 160, 200, 96, 160, 100, 160, 200, 160, + 160, 200, 96, 160, 100, 100, 200, 160, 160, 160, 96, 160, 100, 100, 200, 166 +}; +#endif + +#if defined (_BCM96816_) +const uint32 cpu_speed_table[0x20] = { + 200, 400, 400, 320, 200, 400, 333, 333, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 400, 400, 200, 360, 400, 400, 300, 300, 320, 320, 400, 400 +}; +const uint32 ddr_speed_table[0x20] = { + 200, 333, 200, 200, 200, 333, 333, 333, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 400, 200, 200, 300, 300, 300, 300, 300, 400, 400, 400, 400 +}; +const uint32 bus_speed_table[0x20] = { + 200, 200, 200, 160, 100, 167, 200, 167, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 200, 200, 160, 180, 171, 200, 171, 200, 160, 200, 160, 200 +}; +#endif + +static unsigned long cfe_get_sdram_size(void); + +/* ********************************************************************* + * cfe_setup_default_env() + * + * Initialize the default environment for CFE. These are all + * the temporary variables that do not get stored in the NVRAM + * but are available to other programs and command-line macros. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +static void cfe_setup_default_env(void) +{ + char buffer[80]; + + xsprintf(buffer,"%d.%d.%d",CFE_VER_MAJOR,CFE_VER_MINOR,CFE_VER_BUILD); + env_setenv("CFE_VERSION",buffer,ENV_FLG_BUILTIN | ENV_FLG_READONLY); + + if (cfe_boardname) { + env_setenv("CFE_BOARDNAME",(char *) cfe_boardname, + ENV_FLG_BUILTIN | ENV_FLG_READONLY); + } +} + + +/* ********************************************************************* + * cfe_ledstr(leds) + * + * Display a string on the board's LED display, if it has one. + * This routine depends on the board-support package to + * include a "driver" to write to the actual LED, if the board + * does not have one this routine will do nothing. + * + * The LEDs are written at various places in the initialization + * sequence, to debug board problems. + * + * Input parameters: + * leds - pointer to four-character ASCII string + * + * Return value: + * nothing + ********************************************************************* */ + +void cfe_ledstr(const char *leds) +{ +#if 0 + unsigned int val; + + val = ((((unsigned int) leds[0]) << 24) | + (((unsigned int) leds[1]) << 16) | + (((unsigned int) leds[2]) << 8) | + ((unsigned int) leds[3])); + + cfe_leds(val); +#endif +} + + +/* ********************************************************************* + * cfe_say_hello() + * + * Print out the CFE startup message and copyright notice + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +void cfe_command_restart(uint64_t status) +{ +} + +static void cfe_say_hello(void) +{ + xprintf("\n\n"); + xprintf("CFE version 2.0.3" +#ifdef CFE_VER_RELEASE + ".%d" +#endif + " for DGN2200v2 (%s)\n", + //CFE_VER_MAJOR,CFE_VER_MINOR,CFE_VER_BUILD, BCM63XX_MAJOR, BCM63XX_MINOR, +#ifdef CFE_VER_RELEASE + CFE_VER_RELEASE, +#endif + //cfe_boardname, +#ifdef __long64 + "64bit," +#else + "32bit," +#endif +#if CFG_MULTI_CPUS + "MP," +#else + "SP," +#endif +#ifdef __MIPSEL + "LE" +#endif +#ifdef __MIPSEB + "BE" +#endif +#if CFG_VAPI + ",VAPI" +#endif + ); + + xprintf("Build Date: %s (%s)\n",builddate,builduser); + xprintf("Copyright (C) 2000-2009 Broadcom Corporation.\n"); + xprintf("\n"); +} + + +/* ********************************************************************* + * cfe_restart() + * + * Restart CFE from scratch, jumping back to the boot vector. + * + * Input parameters: + * nothing + * + * Return value: + * does not return + ********************************************************************* */ + +void cfe_restart(void) +{ + _exc_restart(); +} + + +/* ********************************************************************* + * cfe_start(ept) + * + * Start a user program + * + * Input parameters: + * ept - entry point + * + * Return value: + * nothing + ********************************************************************* */ +void cfe_start(unsigned long ept) +{ + cfe_launch(ept); +} + +/* ********************************************************************* + * cfe_startup_info() + * + * Display startup memory configuration messages + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +static void cfe_startup_info(void) +{ + xprintf("Chip ID: BCM%X%X, ", (PERF->RevID & 0xFFFF0000) >> 16, PERF->RevID & 0xFF); + xprintf("MIPS: %dMHz",cfe_cpu_speed/1000000); +#if defined (_BCM96328_) || defined (_BCM96362_) || defined (_BCM96816_) + xprintf(", DDR: %dMHz, Bus: %dMHz\n", cfe_ddr_speed/1000000, cfe_bus_speed/1000000); +#else + xprintf("\n"); +#endif + { + unsigned long tp; + __asm __volatile( + "mfc0 $9, $22, 3;" + "move %0, $9" + :"=r" (tp)); + tp = ((tp & CP0_CMT_TPID) == CP0_CMT_TPID) ? 1 : 0; + xprintf("Main Thread: TP%d\n", tp); + } +#if defined (_BCM96328_) || defined (_BCM96362_) || defined (_BCM96816_) + if (DDR->TEST_CFG1 & 0x2) { /* Memory Test is finished */ + xprintf("Memory Test "); + if (DDR->TEST_CFG1 & 0x4) { + xprintf("Failed\n"); + } + else { + xprintf("Passed\n"); + } + } +#endif + cfe_sdramsize = cfe_get_sdram_size(); + xprintf("Total Memory: %lu bytes (%luMB)\n", cfe_sdramsize, cfe_sdramsize >> 20); + xprintf("Boot Address: 0x%x\n\n", FLASH_BASE); +} + +#if defined (_BCM96816_) +/* ********************************************************************* + * apm_hvg_init() + * + * Work around 6816-specific reset logic + * + * Input parameters: + * nothing + * + * Return value: + * does not return + ********************************************************************* */ + +static void apm_hvg_init(void) +{ + HVG->reg_hvg_cha_misc ^= HVG_SOFT_INIT_0; + HVG->reg_hvg_chb_misc ^= HVG_SOFT_INIT_0; +} +#endif + +/* ********************************************************************* + * cfe_main(a,b) + * + * It's gotta start somewhere. + * + * Input parameters: + * a,b - not used + * + * Return value: + * does not return + ********************************************************************* */ + +void cfe_main(int a,int b) +{ + /* + * By the time this routine is called, the following things have + * already been done: + * + * 1. The processor(s) is(are) initialized. + * 2. The caches are initialized. + * 3. The memory controller is initialized. + * 4. BSS has been zeroed. + * 5. The data has been moved to R/W space. + * 6. The "C" Stack has been initialized. + */ + + cfe_bg_init(); /* init background processing */ + cfe_attach_init(); + calculateCpuSpeed(); + cfe_timer_init(); /* Timer process */ + cfe_bg_add(cfe_device_poll,NULL); + + /* + * Initialize the memory allocator + */ + KMEMINIT((unsigned char *) (uintptr_t) mem_heapstart, + ((CFG_HEAP_SIZE)*1024)); + + /* + * Initialize the console. It is done before the other devices + * get turned on. + */ + + board_console_init(); + cfe_setup_exceptions(); + cfe_say_hello(); + +#if defined(CONFIG_BRCM_IKOS) + { + /*0x694b6f32 (iKo2) is replaced with actual addr during the build process*/ + static unsigned long linuxStartAddr=0x694b6f32; + printf("IKOS Build: Jump to Linux start address 0x%8.8lx.\n\n", + linuxStartAddr); + cfe_launch(linuxStartAddr); + } +#endif + + cfe_arena_init(); + board_device_init(); + cfe_startup_info(); + cfe_setup_default_env(); + ui_init_cmddisp(); + getBootLine(); + getBoardParam(); +#if defined (_BCM96816_) + apm_hvg_init(); +#endif + + /* Foxconn add start by Cliff Wang, 03/23/2010 */ + ui_init_netcmds(); + /* Foxconn add end by Cliff Wang, 03/23/2010 */ + + board_final_init(); + cfe_command_loop(); + + +} + + +/* ********************************************************************* + * cfe_command_loop() + * + * This routine reads and processes user commands + * + * Input parameters: + * nothing + * + * Return value: + * does not return + ********************************************************************* */ + +void cfe_command_loop() +{ + char buffer[300]; + int status; + char *prompt; + + /* Start Web interface. */ + cfe_bg_add(cfe_web_poll,NULL); + + for (;;) { + prompt = env_getenv("PROMPT"); + if (!prompt) prompt = "CFE> "; + console_readline(prompt,buffer,sizeof(buffer)); + + if (cfe_web_check()) + cfe_web_fg_process(); + else { + status = ui_docommands(buffer); + if (status != CMD_ERR_BLANK) { + xprintf("*** command status = %d\n", status); + } + } + } +} + +/* ********************************************************************* + * cfe_errortext(err) + * + * Returns an error message with a number in it. The number can be + * looked up in cfe_error.h. + * + * Input parameters: + * err - error code + * + * Return value: + * string description of error + ********************************************************************* */ + +const char *cfe_errortext(int err) +{ + static char err_buf[20]; + + sprintf(err_buf, "CFE error %d", err); + return (const char *) err_buf; +} + +#if defined (_BCM96368_) +/* ********************************************************************* + * calculateCpuSpeed() + * Calculate BCM6368 CPU speed by reading the PLL Config register + * and applying the following formula: + * Fref_clk = (64 * (P2/P1) * (MIPSDDR_NDIV / REF_MDIV) + * Fbus_clk = (64 * (P2/P1) * (MIPSDDR_NDIV / DDR_MDIV) + * Fcpu_clk = (64 * (P2/P1) * (MIPSDDR_NDIV / CPU_MDIV) + * Input parameters: + * none + * Return value: + * none + ********************************************************************* */ +void static calculateCpuSpeed(void) +{ + UINT32 numerator; + UINT32 pllConfig = DDR->MIPSDDRPLLConfig; + UINT32 pllMDiv = DDR->MIPSDDRPLLMDiv; + + numerator = 64000000 / ((pllConfig & MIPSDDR_P1_MASK) >> MIPSDDR_P1_SHFT) * + ((pllConfig & MIPSDDR_P2_MASK) >> MIPSDDR_P2_SHFT) * + ((pllConfig & MIPSDDR_NDIV_MASK) >> MIPSDDR_NDIV_SHFT); + + cfe_cpu_speed = numerator / ((pllMDiv & MIPS_MDIV_MASK) >> MIPS_MDIV_SHFT); + cfe_bus_speed = numerator / ((pllMDiv & DDR_MDIV_MASK) >> DDR_MDIV_SHFT); + cfe_ref_speed = numerator / ((pllConfig & REF_MDIV_MASK) >> REF_MDIV_SHFT); +} +#endif + +#if defined (_BCM96328_) || defined (_BCM96362_) || (_BCM96816_) +/* ********************************************************************* + * calculateCpuSpeed() + * Calculate CPU speed by reading strap register + * Input parameters: + * none + * Return value: + * none + ********************************************************************* */ +void static calculateCpuSpeed(void) +{ + uint32 mips_pll_fvco; + + mips_pll_fvco = MISC->miscStrapBus & MISC_STRAP_BUS_MIPS_PLL_FVCO_MASK; + mips_pll_fvco >>= MISC_STRAP_BUS_MIPS_PLL_FVCO_SHIFT; + cfe_cpu_speed = cpu_speed_table[mips_pll_fvco] * 1000000; + cfe_ddr_speed = ddr_speed_table[mips_pll_fvco] * 1000000; + cfe_bus_speed = bus_speed_table[mips_pll_fvco] * 1000000; +} +#endif + +/* ********************************************************************* + * cfe_get_sdram_size(void) + * + * Return amount of SDRAM on the board. + * + * Input parameters: + * None. + * + * Return value: + * Amount of SDRAM on the board. + ********************************************************************* */ +static unsigned long cfe_get_sdram_size(void) +{ +#if defined (_BCM96368_) + uint32 size; + uint32 memCfg; + + size = 1; + memCfg = MEMC->Config; + /* Number of column bits */ + size <<= (((memCfg & MEMC_COL_MASK) >> MEMC_COL_SHFT) + 8); + /* Plus number of row bits */ + size <<= (((memCfg & MEMC_ROW_MASK) >> MEMC_ROW_SHFT) + 11); + /* Plus bus width */ + if (((memCfg & MEMC_WIDTH_MASK) >> MEMC_WIDTH_SHFT) == MEMC_32BIT_BUS) + size <<= 2; + else + size <<= 1; + + /* Plus number of banks */ + size <<= 2; + + return( size ); +#else + return (DDR->CSEND << 24); +#endif +} diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_net_icmp.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_net_icmp.c new file mode 100755 index 0000000..89802f8 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_net_icmp.c @@ -0,0 +1,199 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * ICMP Protocol File: net_icmp.c + * + * This module implements portions of the ICMP protocol. Note + * that it is not a complete implementation, just enough to + * generate and respond to ICMP echo requests. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#include "lib_types.h" +#include "lib_string.h" +#include "lib_queue.h" +#include "lib_malloc.h" +#include "lib_printf.h" + +#include "cfe_timer.h" + +#include "net_ebuf.h" +#include "net_ether.h" + +#include "net_ip.h" + +/* ********************************************************************* + * Constants + ********************************************************************* */ + +#define ICMP_CODE_ECHO 0 +#define ICMP_TYPE_ECHOREPLY 0 +#define ICMP_TYPE_ECHOREQ 8 + +#define ICMPMSG(type,code) (((type)<<8)|(code)) + +/* ********************************************************************* + * Structures + ********************************************************************* */ + +struct icmp_info_s { + ip_info_t *icmp_ipinfo; + queue_t icmp_echoreplies; + int icmp_maxreplies; +}; + +/* ********************************************************************* + * ICMP_RX_CALLBACK(ref,buf,dst,src) + * + * This routine is called by the IP layer when we receive + * ICMP protocol messages. + * + * Input parameters: + * ref - reference data (an icmp_info_t) + * buf - the ebuf containing the buffer + * dst - destination IP address (us, usually) + * src - source IP address + * + * Return value: + * ETH_KEEP to keep packet, ETH_DROP to cause packet to be freed + ********************************************************************* */ + +static int icmp_rx_callback(void *ref,ebuf_t *buf,uint8_t *dst,uint8_t *src) +{ + icmp_info_t *icmp = (icmp_info_t *)ref; + ip_info_t *ipi = icmp->icmp_ipinfo; + uint16_t imsg; + uint16_t cksum; + ebuf_t *txbuf; + uint8_t *icmphdr; + int res; + + imsg = ICMPMSG(buf->eb_ptr[0],buf->eb_ptr[1]); + + res = ETH_DROP; /* assume we're dropping the pkt */ + + switch (imsg) { + case ICMPMSG(ICMP_TYPE_ECHOREQ,ICMP_CODE_ECHO): + txbuf = _ip_alloc(ipi); + if (txbuf) { + /* Construct reply from the original packet. */ + icmphdr = txbuf->eb_ptr; + ebuf_append_bytes(txbuf,buf->eb_ptr,buf->eb_length); + icmphdr[0] = ICMP_TYPE_ECHOREPLY; + icmphdr[1] = ICMP_CODE_ECHO; + icmphdr[2] = 0; icmphdr[3] = 0; + cksum = ~ip_chksum(0,icmphdr,ebuf_length(txbuf)); + icmphdr[2] = (cksum >> 8) & 0xFF; + icmphdr[3] = (cksum & 0xFF); + if (_ip_send(ipi,txbuf,src,IPPROTO_ICMP) < 0) { + _ip_free(ipi,txbuf); + } + } + break; + + case ICMPMSG(ICMP_TYPE_ECHOREPLY,ICMP_CODE_ECHO): + if (q_count(&(icmp->icmp_echoreplies)) < icmp->icmp_maxreplies) { + /* We're keeping this packet, put it on the queue and don't + free it in the driver. */ + q_enqueue(&(icmp->icmp_echoreplies),(queue_t *) buf); + res = ETH_KEEP; + } + break; + + default: + res = ETH_DROP; + } + + return res; +} + + +/* ********************************************************************* + * _ICMP_INIT(ipi) + * + * Initialize the ICMP layer. + * + * Input parameters: + * ipi - ipinfo structure of IP layer to attach to + * + * Return value: + * icmp_info_t structure or NULL if error occurs + ********************************************************************* */ + +icmp_info_t *_icmp_init(ip_info_t *ipi) +{ + icmp_info_t *icmp; + + icmp = (icmp_info_t *) KMALLOC(sizeof(icmp_info_t),0); + if (!icmp) return NULL; + + icmp->icmp_ipinfo = ipi; + q_init(&(icmp->icmp_echoreplies)); + icmp->icmp_maxreplies = 0; + + _ip_register(ipi,IPPROTO_ICMP,icmp_rx_callback,icmp); + + return icmp; +} + +/* ********************************************************************* + * _ICMP_UNINIT(icmp) + * + * Un-initialize the ICMP layer. + * + * Input parameters: + * icmp - icmp_info_t structure + * + * Return value: + * nothing + ********************************************************************* */ + +void _icmp_uninit(icmp_info_t *icmp) +{ + _ip_deregister(icmp->icmp_ipinfo,IPPROTO_ICMP); + + KFREE(icmp); +} + +int _icmp_ping(icmp_info_t *icmp,uint8_t *dest,int seq,int len) +{ + return 0; +} diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ram_boot.S b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ram_boot.S new file mode 100755 index 0000000..cf48de0 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ram_boot.S @@ -0,0 +1,88 @@ +#include "sbmips.h" + +/* ********************************************************************* + * BOARD_EARLYINIT() + * + * Initialize board registers. This is the earliest + * time the BSP gets control. This routine cannot assume that + * memory is operational, and therefore all code in this routine + * must run from registers only. The $ra register must not + * be modified, as it contains the return address. + * + * This routine will be called from uncached space, before + * the caches are initialized. If you want to make + * subroutine calls from here, you must use the CALLKSEG1 macro. + * + * Among other things, this is where the GPIO registers get + * programmed to make on-board LEDs function, or other startup + * that has to be done before anything will work. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ +LEAF(board_earlyinit) + j ra +END(board_earlyinit) + +/* ********************************************************************* + * BOARD_DRAMINFO + * + * Return the address of the DRAM information table + * + * Input parameters: + * nothing + * + * Return value: + * v0 - DRAM info table, return 0 to use default table + ********************************************************************* */ +LEAF(board_draminfo) + j ra +END(board_draminfo) + +/* ********************************************************************* + * BOARD_DRAMINIT + * + * This routine should activate memory. + * + * Input parameters: + * a0 - points to configuration table returned by board_draminfo + * or 0 to use an automatic table + * + * Return value: + * v0 - total memory installed + * + * Registers used: + * can use all registers. + ********************************************************************* */ +LEAF(board_draminit) + j ra +END(board_draminit) + +/* ********************************************************************* + * BOARD_SETLEDS(x) + * + * Set LEDs for boot-time progress indication. Not used if + * the board does not have progress LEDs. This routine + * must not call any other routines, since it may be invoked + * either from KSEG0 or KSEG1 and it may be invoked + * whether or not the icache is operational. + * + * Input parameters: + * a0 - LED value (8 bits per character, 4 characters) + * + * Return value: + * nothing + * + * Registers used: + * t0,t1,t2,t3 + ********************************************************************* */ +LEAF(board_setleds) + j ra +END(board_setleds) + +LEAF(bcmcore_tp1_switch) + j ra +END(bcmcore_tp1_switch) diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_util.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_util.c new file mode 100755 index 0000000..91e1ad0 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_util.c @@ -0,0 +1,1375 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * bcm63xx utility functions + * + * Created on : 04/18/2002 seanl + * + ********************************************************************* + +<:copyright-broadcom + + Copyright (c) 2002 Broadcom Corporation + All Rights Reserved + No portions of this material may be reproduced in any form without the + written permission of: + Broadcom Corporation + 16215 Alton Parkway + Irvine, California 92619 + All information contained in this document is Broadcom Corporation + company private, proprietary, and trade secret. + +:> +*/ + +#define BCMTAG_EXE_USE +#include "bcm63xx_util.h" +#include "flash_api.h" +#include "jffs2.h" + +#define je16_to_cpu(x) ((x).v16) +#define je32_to_cpu(x) ((x).v32) + +static void convertBootInfo(void); +static int checkChipId(int tagChipId, char *sig2); +static void UpdateImageSequenceNumber( char *imageSequence ); + +BOOT_INFO bootInfo; + +static int parseFilename(char *fn) +{ + if (strlen(fn) < BOOT_FILENAME_LEN) + return 0; + else + return 1; +} + +static int parseChoiceFh(char *choice) +{ + + if (*choice == 'f' || *choice == 'h') + return 0; + else + return 1; +} + + +static int parseBootPartition(char *choice) +{ + return( (*choice == BOOT_LATEST_IMAGE || *choice == BOOT_PREVIOUS_IMAGE) + ? 0 : 1 ); +} + +static int parseChoice09(char *choice) +{ + int bChoice = *choice - '0'; + + if (bChoice >= 0 && bChoice <= 9) + return 0; + else + return 1; +} + +static int parseIpAddr(char *ipStr); +static int parseGwIpAddr(char *ipStr); +static int parseAfeId(char *afeIdStr); + +#define PARAM_IDX_BOARD_IPADDR 0 +#define PARAM_IDX_HOST_IPADDR 1 +#define PARAM_IDX_GW_IPADDR 2 +#define PARAM_IDX_RUN_FROM 3 +#define PARAM_IDX_RUN_FILENAME 4 +#define PARAM_IDX_FLASH_FILENAME 5 +#define PARAM_IDX_BOOT_DELAY 6 +#define PARAM_IDX_BOOT_IMAGE 7 + +static PARAMETER_SETTING gBootParam[] = +{ + // prompt name Error Prompt Boot Define Boot Param Validation function + {"Board IP address :", IP_PROMPT , "e=", + "", 24, parseIpAddr, TRUE}, // index 0 + {"Host IP address :", IP_PROMPT , "h=", + "", 15, parseIpAddr, TRUE}, // index 1 + {"Gateway IP address :", IP_PROMPT , "g=", + "", 15, parseGwIpAddr, TRUE}, // index 2 + {"Run from flash/host (f/h) :", RUN_FROM_PROMPT , "r=", + "", 1, parseChoiceFh, TRUE}, // index 3 + {"Default host run file name :", HOST_FN_PROMPT , "f=", + "", MAX_PROMPT_LEN - 1, parseFilename, TRUE}, // index 4 + {"Default host flash file name :", FLASH_FN_PROMPT , "i=", + "", MAX_PROMPT_LEN - 1, parseFilename, TRUE}, // index 5 + {"Boot delay (0-9 seconds) :", BOOT_DELAY_PROMPT, "d=", + "", 1, parseChoice09, TRUE}, // index 6 + {"Boot image (0=latest, 1=previous) :", BOOT_PARTITION_PROMPT, "p=", + "", 1, parseBootPartition, TRUE}, // index 7 + {NULL}, +}; + +static int gNumBootParams = (sizeof(gBootParam) / sizeof(PARAMETER_SETTING))-1; + +static PARAMETER_SETTING gAfeId[] = +{ + // prompt name Error Prompt Boot Define Boot Param Validation function + {"Primary AFE ID :", AFE_PROMPT, "", "", 12, parseAfeId, TRUE}, // index 0 + {"Bonding AFE ID :", AFE_PROMPT, "", "", 12, parseAfeId, TRUE}, // index 1 + {NULL}, +}; +static int gAfeIdParams = (sizeof(gAfeId) / sizeof(PARAMETER_SETTING))-1; + +// move from lib_misc.c +int parseipaddr(const char *ipaddr,uint8_t *dest) +{ + int a,b,c,d; + char *x; + + /* make sure it's all digits and dots. */ + x = (char *) ipaddr; + while (*x) { + if ((*x == '.') || ((*x >= '0') && (*x <= '9'))) { + x++; + continue; + } + return -1; + } + + x = (char *) ipaddr; + a = lib_atoi(ipaddr); + x = lib_strchr(x,'.'); + if (!x) return -1; + b = lib_atoi(x+1); + x = lib_strchr(x+1,'.'); + if (!x) return -1; + c = lib_atoi(x+1); + x = lib_strchr(x+1,'.'); + if (!x) return -1; + d = lib_atoi(x+1); + + if ((a < 0) || (a > 255)) return -1; + if ((b < 0) || (b > 255)) return -1; + if ((c < 0) || (c > 255)) return -1; + if ((d < 0) || (d > 255)) return -1; + + dest[0] = (uint8_t) a; + dest[1] = (uint8_t) b; + dest[2] = (uint8_t) c; + dest[3] = (uint8_t) d; + + return 0; +} + +#if 0 +static const char hextable[16] = "0123456789ABCDEF"; +void dumpHex(unsigned char *start, int len) +{ + unsigned char *ptr = start, + *end = start + len; + + while (ptr < end) + { + long offset = ptr - start; + unsigned char text[120], + *p = text; + while (ptr < end && p < &text[16 * 3]) + { + *p++ = hextable[*ptr >> 4]; + *p++ = hextable[*ptr++ & 0xF]; + *p++ = ' '; + } + p[-1] = 0; + printf("%4lX %s\n", offset, text); + } +} + +#endif + +int parsexdigit(char str) +{ + int digit; + + if ((str >= '0') && (str <= '9')) + digit = str - '0'; + else if ((str >= 'a') && (str <= 'f')) + digit = str - 'a' + 10; + else if ((str >= 'A') && (str <= 'F')) + digit = str - 'A' + 10; + else + return -1; + + return digit; +} + + +// convert in = fffffff00 to out=255.255.255.0 +// return 0 = OK, 1 failed. +static int convertMaskStr(char *in, char *out) +{ + int i; + char twoHex[4]; + uint8_t dest[4]; + char mask[BOOT_IP_LEN]; + + if (strlen(in) != MASK_LEN) // mask len has to 8 + return 1; + + memset(twoHex, 0, sizeof(twoHex)); + for (i = 0; i < 4; i++) + { + twoHex[0] = (uint8_t)*in++; + twoHex[1] = (uint8_t)*in++; + if (parsexdigit(*twoHex) == -1) + return 1; + dest[i] = (uint8_t) xtoi(twoHex); + } + sprintf(mask, "%d.%d.%d.%d", dest[0], dest[1], dest[2], dest[3]); + strcpy(out, mask); + return 0; +} + +// return 0 - OK, !0 - Bad ip +static int parseIpAddr(char *ipStr) +{ + char *x; + uint8_t dest[4]; + char mask[BOOT_IP_LEN]; + char ipMaskStr[2*BOOT_IP_LEN]; + + strcpy(ipMaskStr, ipStr); + + x = strchr(ipMaskStr,':'); + if (!x) // no mask + return parseipaddr(ipMaskStr, dest); + + *x = '\0'; + + if (parseipaddr(ipMaskStr, dest)) // ipStr is not ok + return 1; + + x++; + return convertMaskStr(x, mask); // mask is not used here + +} + +// return 0 - OK, !0 - Bad ip +static int parseGwIpAddr(char *ipStr) +{ + int ret = 0; + if( *ipStr ) + ret = parseIpAddr(ipStr); + return(ret); +} + +// return 0 - OK, !0 - Bad ip +static int parseAfeId(char *afeIdStr) +{ + return 0; +} + +// port from ifconfig command in ui_netcmds.c +void enet_init(void) +{ + char devname[] = "eth0"; + uint8_t addr[IP_ADDR_LEN]; + int res; + NVRAM_DATA nvramData; + + readNvramData(&nvramData); + + if (net_getparam(NET_DEVNAME) == NULL) { + res = net_init(devname); /* turn interface on */ + if (res < 0) { + ui_showerror(res, "Could not activate network interface '%s'", devname); + return; + } + } + + net_setparam(NET_HWADDR, nvramData.ucaBaseMacAddr); + + parseipaddr(bootInfo.boardIp, addr); + net_setparam(NET_IPADDR, addr); + + if (strlen(bootInfo.boardMask) > 0) { + parseipaddr(bootInfo.boardMask, addr); + net_setparam(NET_NETMASK, addr); + } + + if (strlen(bootInfo.gatewayIp) > 0) { + parseipaddr(bootInfo.gatewayIp, addr); + net_setparam(NET_GATEWAY, addr); + } + + net_setnetvars(); +} + +/*************************************************************************** +// Function Name: getCrc32 +// Description : caculate the CRC 32 of the given data. +// Parameters : pdata - array of data. +// size - number of input data bytes. +// crc - either CRC32_INIT_VALUE or previous return value. +// Returns : crc. +****************************************************************************/ +UINT32 getCrc32(byte *pdata, UINT32 size, UINT32 crc) +{ + while (size-- > 0) + crc = (crc >> 8) ^ Crc32_table[(crc ^ *pdata++) & 0xff]; + + return crc; +} + + +// return 0, ok. return -1 = wrong chip +static int checkChipId(int tagChipId, char *sig2) +{ + unsigned int chipId = (PERF->RevID & 0xFFFE0000) >> 16; + int result = 0; + + /* Force BCM681x variants to be be BCM6816) */ + if( (chipId & 0xfff0) == 0x6810 ) + chipId = 0x6816; + + if (tagChipId == chipId) + result = 0; + else { + printf("Chip Id error. Image Chip Id = %04x, Board Chip Id = %04x.\n", tagChipId, chipId); + result = -1; + } + + return result; +} + +// return -1: fail. +// 0: OK. +int verifyTag( PFILE_TAG pTag, int verbose ) +{ + UINT32 crc; + FLASH_ADDR_INFO info; + int tagVer, curVer; + + kerSysFlashAddrInfoGet( &info ); + + tagVer = atoi(pTag->tagVersion); + curVer = atoi(BCM_TAG_VER); + + if (tagVer != curVer) + { + if( verbose ) + { + printf("Firmware tag version [%d] is not compatible with the current Tag version [%d].\n", \ + tagVer, curVer); + } + return -1; + } + + if (checkChipId(xtoi(pTag->chipId), pTag->signiture_2) != 0) + return -1; + + // check tag validate token first + crc = CRC32_INIT_VALUE; + crc = getCrc32((byte *) pTag, (UINT32)TAG_LEN-TOKEN_LEN, crc); + + if (crc != (UINT32)(*(UINT32*)(pTag->tagValidationToken))) + { + if( verbose ) + printf("Illegal image ! Tag crc failed.\n"); + return -1; + } + return 0; +} + +#if (INC_NAND_FLASH_DRIVER==0) +PFILE_TAG getTagFromPartition(int imageNumber) +{ + static unsigned char sectAddr1[sizeof(FILE_TAG)]; + static unsigned char sectAddr2[sizeof(FILE_TAG)]; + int blk = 0; + UINT32 crc; + PFILE_TAG pTag = NULL; + unsigned char *pBase = flash_get_memptr(0); + unsigned char *pSectAddr = NULL; + + /* The image tag for the first image is always after the boot loader. + * The image tag for the second image, if it exists, is at one half + * of the flash size. + */ + if( imageNumber == 1 ) + { + + FLASH_ADDR_INFO flash_info; + + kerSysFlashAddrInfoGet(&flash_info); + blk = flash_get_blk((int)(pBase+flash_info.flash_rootfs_start_offset)); + pSectAddr = sectAddr1; + } + else + if( imageNumber == 2 ) + { + blk = flash_get_blk((int) (pBase + (flash_get_total_size() / 2))); + pSectAddr = sectAddr2; + } + + if( blk ) + { + memset(pSectAddr, 0x00, sizeof(FILE_TAG)); + flash_read_buf((unsigned short) blk, 0, pSectAddr, sizeof(FILE_TAG)); + crc = CRC32_INIT_VALUE; + crc = getCrc32(pSectAddr, (UINT32)TAG_LEN-TOKEN_LEN, crc); + pTag = (PFILE_TAG) pSectAddr; + if (crc != (UINT32)(*(UINT32*)(pTag->tagValidationToken))) + pTag = NULL; + } + + return( pTag ); +} +#else +#define tag_not_searched 0 +#define tag_not_found 1 +#define tag_found 2 +PFILE_TAG getTagFromPartition(int imageNumber) +{ + extern unsigned char *mem_topofmem; + static FILE_TAG Tag1 = {{tag_not_searched}}; + static FILE_TAG Tag2 = {{tag_not_searched}}; + PFILE_TAG pTag = (imageNumber == 2) ? &Tag2 : &Tag1; + PFILE_TAG ret = NULL; + + switch( pTag->tagVersion[0] ) + { + case tag_not_searched: + { + int rootfs = (imageNumber == 2) ? NP_ROOTFS_2 : NP_ROOTFS_1; + char fname[] = NAND_CFE_RAM_NAME; + int fname_actual_len = strlen(fname); + int fname_cmp_len = strlen(fname) - 3; /* last three are digits */ + unsigned char *buf = (unsigned char *) mem_topofmem + 1024; + unsigned char *p; + int len = flash_get_sector_size(0); + int num_blks = flash_get_numsectors(); + int i, done, start_blk, end_blk; + struct jffs2_raw_dirent *pdir; + unsigned long version = 0; + NVRAM_DATA nvramData; + + pTag->tagVersion[0] = tag_not_found; + readNvramData(&nvramData); + validateNandPartTbl(&nvramData); + + if( nvramData.ulNandPartOfsKb[rootfs] > 0 && + nvramData.ulNandPartOfsKb[rootfs] < ((num_blks * len) / 1024) && + nvramData.ulNandPartSizeKb[rootfs] > 0 && + nvramData.ulNandPartSizeKb[rootfs] < ((num_blks * len) / 1024) ) + { + const int max_not_jffs2 = 10; + int not_jffs2 = 0; + + start_blk = nvramData.ulNandPartOfsKb[rootfs] / (len / 1024); + end_blk = + start_blk + (nvramData.ulNandPartSizeKb[rootfs] / (len / 1024)); + + /* Find the directory entry. */ + for( i = start_blk, done = 0; i < end_blk && done == 0; i++ ) + { + if( flash_read_buf(i, 0, buf, len) > 0 ) + { + p = buf; + while( p < buf + len ) + { + pdir = (struct jffs2_raw_dirent *) p; + if( je16_to_cpu(pdir->magic) == JFFS2_MAGIC_BITMASK ) + { + if( je16_to_cpu(pdir->nodetype) == + JFFS2_NODETYPE_DIRENT && + fname_actual_len == pdir->nsize && + !memcmp(fname, pdir->name, fname_cmp_len) ) + { + if( je32_to_cpu(pdir->version) > version ) + { + if( je32_to_cpu(pdir->ino) != 0 ) + { + unsigned char *seq = + pdir->name + fname_cmp_len; + pTag->imageSequence[0] = seq[0]; + pTag->imageSequence[1] = seq[1]; + pTag->imageSequence[2] = seq[2]; + pTag->imageSequence[3] = '\0'; + pTag->tagVersion[0] = tag_found; + + version = je32_to_cpu(pdir->version); + + /* Setting 'done = 1' assumes there is + * only one version of the directory + * entry. + */ + done = 1; + ret = pTag; + break; + } + } + } + + p += (je32_to_cpu(pdir->totlen) + 0x03) & ~0x03; + not_jffs2 = 0; + } + else + { + if( not_jffs2++ > max_not_jffs2 ) + done = 1; + break; + } + } + } + } + } + } + break; + + case tag_found: + ret = pTag; + break; + + case tag_not_found: + ret = NULL; + break; + } + + return(ret); +} +#endif + + +int getPartitionFromTag( PFILE_TAG pTag ) +{ + int ret = 0; + + if( pTag ) + { + PFILE_TAG pTag1 = getTagFromPartition(1); + PFILE_TAG pTag2 = getTagFromPartition(2); + int sequence = atoi(pTag->imageSequence); + int sequence1 = (pTag1) ? atoi(pTag1->imageSequence) : -1; + int sequence2 = (pTag2) ? atoi(pTag2->imageSequence) : -1; + + if( pTag1 && sequence == sequence1 ) + ret = 1; + else + if( pTag2 && sequence == sequence2 ) + ret = 2; + } + + return( ret ); +} + +PFILE_TAG getBootImageTag(void) +{ + PFILE_TAG pTag = NULL; + + if( flash_get_flash_type() != FLASH_IFC_NAND ) + { + PFILE_TAG pTag1 = getTagFromPartition(1); + + /* Foxconn modified end pling 10/13/2008 */ + PFILE_TAG pTag2 = NULL; + // PFILE_TAG pTag2 = getTagFromPartition(2); + //* Foxconn modified end pling 10/13/2008 */ + + if( pTag1 && pTag2 ) + { + /* Two images are flashed. */ + int sequence1 = atoi(pTag1->imageSequence); + int sequence2 = atoi(pTag2->imageSequence); + + if( bootInfo.bootPartition == BOOT_LATEST_IMAGE ) + pTag = (sequence2 > sequence1) ? pTag2 : pTag1; + else /* Boot from the previous image. */ + pTag = (sequence2 < sequence1) ? pTag2 : pTag1; + } + else + /* One image is flashed. */ + pTag = (pTag2) ? pTag2 : pTag1; + } + else + { + /* TBD. Verify that linux is on the file system. */ + /* pTag pointer is only compared to NULL for NAND flash boot. */ + pTag = (PFILE_TAG) 1; + } + + return( pTag ); +} + +static void UpdateImageSequenceNumber( char *imageSequence ) +{ + int newImageSequence = 0; + PFILE_TAG pTag = getTagFromPartition(1); + + if( pTag ) + newImageSequence = atoi(pTag->imageSequence); + + pTag = getTagFromPartition(2); + if( pTag && atoi(pTag->imageSequence) > newImageSequence ) + newImageSequence = atoi(pTag->imageSequence); + + newImageSequence++; + sprintf(imageSequence, "%d", newImageSequence); +} + +// return -1: fail. +// 0: OK. +int flashImage(uint8_t *imagePtr) +{ + UINT32 crc; + FLASH_ADDR_INFO info; + int totalImageSize = 0; + int cfeSize; + int cfeAddr, rootfsAddr, kernelAddr; + int status = 0; + PFILE_TAG pTag = (PFILE_TAG) imagePtr; + NVRAM_DATA nvramData, tmpNvramData; + + if( flash_get_flash_type() == FLASH_IFC_NAND ) + { + printf("ERROR: Image is not a valid NAND flash image.\n"); + return -1; + } + + // save existing NVRAM data into a local structure + readNvramData(&nvramData); + + if( verifyTag( pTag, 1 ) == -1 ) + return -1; + + kerSysFlashAddrInfoGet( &info ); + + // check imageCrc + totalImageSize = atoi(pTag->totalImageLen); + crc = CRC32_INIT_VALUE; + crc = getCrc32((imagePtr+TAG_LEN), (UINT32) totalImageSize, crc); + + if (crc != (UINT32) (*(UINT32*)(pTag->imageValidationToken))) + { + printf(" Illegal image ! Image crc failed.\n"); + return -1; + } + + cfeSize = cfeAddr = rootfsAddr = kernelAddr = 0; + + // check cfe's existence + cfeAddr = atoi(pTag->cfeAddress); + if (cfeAddr) + { + cfeSize = atoi(pTag->cfeLen); + if( (cfeSize <= 0) ) + { + printf("Illegal cfe size [%d].\n", cfeSize ); + return -1; + } + + printf("\nFlashing CFE: "); + if ((status = kerSysBcmImageSet(cfeAddr+BOOT_OFFSET, imagePtr+TAG_LEN, + cfeSize, 0)) != 0) + { + printf("Failed to flash CFE. Error: %d\n", status); + return status; + } + + // Check if the new image has valid NVRAM + if ((readNvramData(&tmpNvramData) != 0) || (BpSetBoardId(tmpNvramData.szBoardId) != BP_SUCCESS) || (BpSetVoiceBoardId(tmpNvramData.szBoardId) != BP_SUCCESS)) + writeNvramData(&nvramData); + } + + // check root filesystem and kernel existence + rootfsAddr = atoi(pTag->rootfsAddress); + kernelAddr = atoi(pTag->kernelAddress); + + if( rootfsAddr && kernelAddr ) + { + char *p; + unsigned char *tagFs = imagePtr; + unsigned int baseAddr = (unsigned int) flash_get_memptr(0); + unsigned int totalSize = (unsigned int) flash_get_total_size(); + unsigned int reservedBytesAtEnd; + unsigned int availableSizeOneImg; + unsigned int reserveForTwoImages; + unsigned int availableSizeTwoImgs; + unsigned int newImgSize = atoi(pTag->rootfsLen)+atoi(pTag->kernelLen); + PFILE_TAG pCurTag = getBootImageTag(); + UINT32 crc; + unsigned int curImgSize = 0; + unsigned int rootfsOffset = (unsigned int)rootfsAddr-IMAGE_BASE-TAG_LEN; + FLASH_ADDR_INFO flash_info; + + kerSysFlashAddrInfoGet(&flash_info); + if( rootfsOffset < flash_info.flash_rootfs_start_offset ) + { + // Increase rootfs and kernel addresses by the difference between + // rootfs offset and what it needs to be. + rootfsAddr += flash_info.flash_rootfs_start_offset - rootfsOffset; + kernelAddr += flash_info.flash_rootfs_start_offset - rootfsOffset; + sprintf(pTag->rootfsAddress,"%lu", (unsigned long) rootfsAddr); + sprintf(pTag->kernelAddress,"%lu", (unsigned long) kernelAddr); + crc = CRC32_INIT_VALUE; + crc = getCrc32((unsigned char *)pTag,(UINT32)TAG_LEN-TOKEN_LEN,crc); + *(unsigned long *) &pTag->tagValidationToken[0] = crc; + } + + rootfsAddr += BOOT_OFFSET; + kernelAddr += BOOT_OFFSET; + + reservedBytesAtEnd = flash_get_reserved_bytes_at_end(&flash_info); + availableSizeOneImg = totalSize - ((unsigned int)rootfsAddr-baseAddr) - + reservedBytesAtEnd; + reserveForTwoImages = + (flash_info.flash_rootfs_start_offset > reservedBytesAtEnd) + ? flash_info.flash_rootfs_start_offset : reservedBytesAtEnd; + availableSizeTwoImgs = (totalSize / 2) - reserveForTwoImages; + +// printf("availableSizeOneImage=%dKB availableSizeTwoImgs=%dKB reserve=%dKB\n", +// availableSizeOneImg/1024, availableSizeTwoImgs/1024, reserveForTwoImages/1024); + + if( pCurTag ) + curImgSize = atoi(pCurTag->rootfsLen) + atoi(pCurTag->kernelLen); + + if( newImgSize > availableSizeOneImg) + { + printf("Illegal image size %d. Image size must not be greater " + "than %d.\n", newImgSize, availableSizeOneImg); + return -1; + } + + // tag is alway at the sector start of fs + if (cfeAddr) + { + // will trash cfe memory, but cfe is already flashed + tagFs = imagePtr + cfeSize; + memcpy(tagFs, imagePtr, TAG_LEN); + } + + // If the current image fits in half the flash space and the new + // image to flash also fits in half the flash space, then flash it + // in the partition that is not currently being used to boot from. + if( curImgSize <= availableSizeTwoImgs && + newImgSize <= availableSizeTwoImgs && + getPartitionFromTag( pCurTag ) == 1 ) + { + // Update rootfsAddr to point to the second boot partition. + int offset = (totalSize / 2) + TAG_LEN; + + sprintf(((PFILE_TAG) tagFs)->kernelAddress, "%lu", + (unsigned long) IMAGE_BASE + offset + (kernelAddr-rootfsAddr)); + kernelAddr = baseAddr + offset + (kernelAddr - rootfsAddr); + + sprintf(((PFILE_TAG) tagFs)->rootfsAddress, "%lu", + (unsigned long) IMAGE_BASE + offset); + rootfsAddr = baseAddr + offset; + } + + UpdateImageSequenceNumber( ((PFILE_TAG) tagFs)->imageSequence ); + crc = CRC32_INIT_VALUE; + crc = getCrc32((unsigned char *)tagFs, (UINT32)TAG_LEN-TOKEN_LEN, crc); + *(unsigned long *) &((PFILE_TAG) tagFs)->tagValidationToken[0] = crc; + + printf("\nFlashing root file system and kernel at 0x%8.8lx: ", + rootfsAddr - TAG_LEN); + if( (status = kerSysBcmImageSet((rootfsAddr-TAG_LEN), tagFs, + TAG_LEN + newImgSize, 0)) != 0 ) + { + printf("Failed to flash root file system. Error: %d\n", status); + return status; + } + + for( p = nvramData.szBootline; p[2] != '\0'; p++ ) + { + if( p[0] == 'p' && p[1] == '=' && p[2] != BOOT_LATEST_IMAGE ) + { + // Change boot partition to boot from new image. + p[2] = BOOT_LATEST_IMAGE; + writeNvramData(&nvramData); + break; + } + } + } + + printf(".\n*** Image flash done *** !\n"); + + return status; +} + +static int nandUpdateImageSequenceNumber( uint8_t *imagePtr, int imageSize ) +{ + unsigned char *buf, *p; + char fname[] = NAND_CFE_RAM_NAME; + int fname_actual_len = strlen(fname); + int fname_cmp_len = strlen(fname) - 3; /* last three are digits */ + int len = flash_get_sector_size(0); + struct jffs2_raw_dirent *pdir; + unsigned long version = 0; + PFILE_TAG pTag1 = getTagFromPartition(1); + PFILE_TAG pTag2 = getTagFromPartition(2); + int seq = (pTag1) ? atoi(pTag1->imageSequence) : -1; + int seq2 = (pTag2) ? atoi(pTag2->imageSequence) : -1; + int ret = 0; + + if( seq2 > seq ) + seq = seq2; + + if( seq != -1 ) + { + int done = 0; + + /* Increment the new highest sequence number. Add it to the CFE RAM + * file name. + */ + seq++; + + for(buf = imagePtr; buf < imagePtr+imageSize && done == 0; buf += len) + { + p = buf; + while( p < buf + len ) + { + pdir = (struct jffs2_raw_dirent *) p; + if( je16_to_cpu(pdir->magic) == JFFS2_MAGIC_BITMASK ) + { + if( je16_to_cpu(pdir->nodetype) == JFFS2_NODETYPE_DIRENT && + fname_actual_len == pdir->nsize && + !memcmp(fname, pdir->name, fname_cmp_len) && + je32_to_cpu(pdir->version) > version && + je32_to_cpu(pdir->ino) != 0 ) + { + p = pdir->name + fname_cmp_len; + p[0] = (seq / 100) + '0'; + p[1] = ((seq % 100) / 10) + '0'; + p[2] = ((seq % 100) % 10) + '0'; + p[3] = '\0'; + + je32_to_cpu(pdir->name_crc) = getCrc32(pdir->name, + (unsigned long) fname_actual_len, 0); + + version = je32_to_cpu(pdir->version); + + /* Setting 'done = 1' assumes there is only one version + * of the directory entry. + */ + done = 1; + ret = (buf - imagePtr) / len; /* block number */ + break; + } + + p += (je32_to_cpu(pdir->totlen) + 0x03) & ~0x03; + } + else + break; + } + } + } + + return(ret); +} + +// return -1: fail. +// 0: OK. +int writeWholeImage(uint8_t *imagePtr, int wholeImageSize) +{ + UINT32 crc; + int status = 0; + int offset = 0; + int imageSize = wholeImageSize - TOKEN_LEN; + unsigned char crcBuf[CRC_LEN]; + NVRAM_DATA nvramData, tmpNvramData; + WFI_TAG wfiTag; +#if (INC_SPI_PROG_NAND==1) + if( flash_get_flash_type() != FLASH_IFC_NAND && wholeImageSize > FLASH_LENGTH_BOOT_ROM) + flash_change_flash_type(FLASH_IFC_NAND); +#endif + + // if whole image size (plus TOKEN_LEN of crc) is greater than total flash size, return error + if (wholeImageSize > (flash_get_total_size() + TOKEN_LEN)) + { + printf("Image size too big\n"); + return -1; + } + + memcpy(&wfiTag, imagePtr + imageSize, sizeof(wfiTag)); + if( (wfiTag.wfiVersion & WFI_ANY_VERS_MASK) == WFI_ANY_VERS && + checkChipId(wfiTag.wfiChipId, NULL) != 0 ) + return -1; + + // check tag validate token first + crc = CRC32_INIT_VALUE; + crc = getCrc32(imagePtr, (UINT32)imageSize, crc); + memcpy(crcBuf, imagePtr+imageSize, CRC_LEN); + if (memcmp(&crc, crcBuf, CRC_LEN) != 0) + { + printf("Illegal whole flash image\n"); + return -1; + } + + // save existing NVRAM data into a local structure + readNvramData(&nvramData); + + if( flash_get_flash_type() == FLASH_IFC_NAND ) + { + /* The CFE ROM boot loader saved the rootfs partition index at the + * memory location before CFE RAM load address. + */ + extern unsigned char _ftext; + + /* Allow addition blocks to flash cfram block that has sequence number + * and is flashed last. + */ + const int overhead_blocks = 8; + + int rootfs = (int) *(&_ftext - 1); + int blksize = flash_get_sector_size(0) / 1024; + int sectsize = flash_get_sector_size(0); + int i, cferam_blk, after_cferam, cferam_overhead; + + if( (wfiTag.wfiVersion & WFI_ANY_VERS_MASK) == WFI_ANY_VERS && + ((blksize == 16 && wfiTag.wfiFlashType != WFI_NAND16_FLASH) || + (blksize == 128 && wfiTag.wfiFlashType != WFI_NAND128_FLASH)) ) + { + printf("\nERROR: NAND flash block size does not match image " + "block size\n\n"); + return -1; + } + + if( *(unsigned short *) imagePtr != JFFS2_MAGIC_BITMASK ) + { + /* Flash block 0 (cferom). */ + PNVRAM_DATA pnd = (PNVRAM_DATA) (imagePtr + NVRAM_DATA_OFFSET); + char *p; + + /* Copy NVRAM data to block to be flashed so it is preserved. */ + memcpy((unsigned char *) pnd, (unsigned char *) &nvramData, + sizeof(NVRAM_DATA)); + for( p = pnd->szBootline; p[2] != '\0'; p++ ) + { + if( p[0] == 'p' && p[1] == '=' && p[2] != BOOT_LATEST_IMAGE ) + { + // Change boot partition to boot from new image. + p[2] = BOOT_LATEST_IMAGE; + break; + } + } + + /* Recalculate the nvramData CRC. */ + pnd->ulCheckSum = 0; + pnd->ulCheckSum = getCrc32((unsigned char *) pnd, + sizeof(NVRAM_DATA), CRC32_INIT_VALUE); + + if((status = kerSysBcmImageSet(FLASH_BASE,imagePtr,sectsize,0)) != 0) + printf("Failed to flash block 0. Error: %d\n", status); + imagePtr += sectsize; + imageSize -= sectsize; + } + + validateNandPartTbl(&nvramData); + cferam_blk = nandUpdateImageSequenceNumber(imagePtr, imageSize); + + /* rootfs is the partition that the CFE RAM booted from. Write the + * image to the other rootfs partition. + */ + if(rootfs == NP_ROOTFS_1 && nvramData.ulNandPartSizeKb[NP_ROOTFS_2]>0) + offset = nvramData.ulNandPartOfsKb[NP_ROOTFS_2] * 1024; + else + offset = nvramData.ulNandPartOfsKb[NP_ROOTFS_1] * 1024; + + after_cferam = (cferam_blk + 1) * sectsize; + cferam_overhead = overhead_blocks * sectsize; + + /* Erase block with cferam JFFS2 directory entry so if flashing this + * image does not finish, the partition will not be valid. + */ + for( i = 0; i < (cferam_blk + 1 + overhead_blocks); i++ ) + flash_sector_erase_int((offset / sectsize) + i); + + /* Flash image after cferam directory entry. */ + printf("\nFlashing root file system at 0x%8.8lx: ", FLASH_BASE+offset); + if((status = kerSysBcmImageSet(FLASH_BASE + offset + after_cferam + + cferam_overhead, imagePtr + after_cferam, imageSize - after_cferam, + 1)) != 0) + { + printf("Failed to flash whole image. Error: %d\n", status); + return status; + } + + /* Flash block(s) up to and including the block with cferam JFFS2 + * directory entry. + */ + if((status = kerSysBcmImageSet(FLASH_BASE + offset, imagePtr, + after_cferam, 0)) != 0) + { + printf("Failed to flash whole image. Error: %d\n", status); + return status; + } + } + else /* NOR FLASH */ + { + printf("\nFlashing root file system and kernel at 0x%8.8lx\n", + FLASH_BASE+offset); + + if( (wfiTag.wfiVersion & WFI_ANY_VERS_MASK) == WFI_ANY_VERS && + wfiTag.wfiFlashType != WFI_NOR_FLASH ) + { + printf("\nERROR: Image does not support a NOR flash device.\n\n"); + return -1; + } + + if((status = kerSysBcmImageSet(FLASH_BASE+offset, imagePtr, imageSize, + 1)) != 0) + { + printf("Failed to flash whole image. Error: %d\n", status); + return status; + } + } + + // Check if the new image has valid NVRAM + // Also check if the new image still supports currently configured board ID + if( (readNvramData(&tmpNvramData) != 0) || + (BpSetBoardId(tmpNvramData.szBoardId) != BP_SUCCESS) || + (BpSetVoiceBoardId(tmpNvramData.szVoiceBoardId) != BP_SUCCESS) ) + { + // Don't write NVRAM area if we are flashing tiny bridge image. + // unlike cfe.w, the tiny bridge .w image will not have NVRAM_DATA_ID set + if (*(unsigned long *) &tmpNvramData == NVRAM_DATA_ID) + writeNvramData(&nvramData); + } + + return status; +} + +int processPrompt(PPARAMETER_SETTING promptPtr, int promptCt) +{ + char tmpBuf[MAX_PROMPT_LEN]; + int i = 0; + int bChange = FALSE; + + printf("Press: <enter> to use current value\r\n"); + printf(" '-' to go previous parameter\r\n"); + printf(" '.' to clear the current value\r\n"); + printf(" 'x' to exit this command\r\n"); + + memset(tmpBuf, 0, MAX_PROMPT_LEN); + while (i < promptCt) + { + if( (promptPtr+i)->enabled == FALSE ) + { + if( tmpBuf[0] == '-' ) + { + if( i > 0 ) + { + i--; + continue; + } + } + else + { + i++; + continue; + } + } + + if (strlen((promptPtr+i)->parameter) > 0) + printf("%s %s ", (promptPtr+i)->promptName, (promptPtr+i)->parameter); + else + printf("%s %s", (promptPtr+i)->promptName, (promptPtr+i)->parameter); + + memset(tmpBuf, 0, MAX_PROMPT_LEN); + console_readline ("", tmpBuf, (promptPtr+i)->maxValueLength + 1); + + switch (tmpBuf[0]) + { + case '-': // go back one parameter + if (i > 0) + i--; + break; + case 'x': // get out the b command + if ((promptPtr+i)->func != 0) // validate function is supplied, do a check + { + if ((promptPtr+i)->func((promptPtr+i)->parameter)) + { + printf("\n%s; Try again!\n", (promptPtr+i)->errorPrompt); + break; + } + } + i = promptCt; + break; + case '.': // clear the current parameter and advance + if ((promptPtr+i)->func != 0) // validate function is supplied, do a check + { + if ((promptPtr+i)->func("")) + { + printf("\n%s; Try again!\n", (promptPtr+i)->errorPrompt); + break; + } + } + memset((promptPtr+i)->parameter, 0, MAX_PROMPT_LEN); + i++; + bChange = TRUE; + break; + case 0: // no input; use default if it is OK + if ((promptPtr+i)->func != 0) // validate function is supplied, do a check + { + if ((promptPtr+i)->func((promptPtr+i)->parameter)) + { + printf("\n%s; Try again!\n", (promptPtr+i)->errorPrompt); + break; + } + } + i++; + break; + default: // new parameter + if ((promptPtr+i)->func != 0) // validate function is supplied, do a check + { + if ((promptPtr+i)->func(tmpBuf)) + { + printf("\n%s; Try again!\n", (promptPtr+i)->errorPrompt); + break; + } + } + memset((promptPtr+i)->parameter, 0, MAX_PROMPT_LEN); + memcpy((promptPtr+i)->parameter, tmpBuf, strlen(tmpBuf)); + i++; + bChange = TRUE; + } + } + + return bChange; + +} // processPrompt + +// write the nvramData struct to nvram after CRC is calculated +void writeNvramData(PNVRAM_DATA pNvramData) +{ + UINT32 crc = CRC32_INIT_VALUE; + + pNvramData->ulCheckSum = 0; + crc = getCrc32((unsigned char *)pNvramData, sizeof(NVRAM_DATA), crc); + pNvramData->ulCheckSum = crc; + kerSysNvRamSet((unsigned char *)pNvramData, sizeof(NVRAM_DATA), 0); +} + +// read the nvramData struct from nvram +// return -1: crc fail, 0 ok +int readNvramData(PNVRAM_DATA pNvramData) +{ + UINT32 crc = CRC32_INIT_VALUE, savedCrc; + + kerSysNvRamGet((unsigned char *)pNvramData, sizeof(NVRAM_DATA), 0); + savedCrc = pNvramData->ulCheckSum; + pNvramData->ulCheckSum = 0; + crc = getCrc32((unsigned char *)pNvramData, sizeof(NVRAM_DATA), crc); + if (savedCrc != crc) + return -1; + + return 0; +} + +static void convertBootInfo(void) +{ + char *x; + + memset(&bootInfo, 0, sizeof(BOOT_INFO)); + strcpy(bootInfo.boardIp, gBootParam[PARAM_IDX_BOARD_IPADDR].parameter); + + if ((x = strchr(bootInfo.boardIp, ':'))) // has mask + { + *x = '\0'; + convertMaskStr((x+1), bootInfo.boardMask); + } + strcpy(bootInfo.hostIp, gBootParam[PARAM_IDX_HOST_IPADDR].parameter); + if ((x = strchr(bootInfo.hostIp, ':'))) // ignore host mask + *x = '\0'; + strcpy(bootInfo.gatewayIp, gBootParam[PARAM_IDX_GW_IPADDR].parameter); + if ((x = strchr(bootInfo.gatewayIp, ':'))) // ignore gw mask + *x = '\0'; + bootInfo.runFrom = gBootParam[PARAM_IDX_RUN_FROM].parameter[0]; + strcpy(bootInfo.hostFileName, gBootParam[PARAM_IDX_RUN_FILENAME].parameter); + strcpy(bootInfo.flashFileName, gBootParam[PARAM_IDX_FLASH_FILENAME].parameter); + bootInfo.bootDelay = (int)(gBootParam[PARAM_IDX_BOOT_DELAY].parameter[0] - '0'); + bootInfo.bootPartition = gBootParam[PARAM_IDX_BOOT_IMAGE].parameter[0]; +} + +void getBootLine(void) +{ + int i; + char *curPtr; + char *dPtr; + NVRAM_DATA nvramData; + + readNvramData(&nvramData); + + if ((nvramData.szBootline[0] == (char)0xff) || + (nvramData.szBootline[0] == (char)0)) + { + setDefaultBootline(); + return; + } + + curPtr = nvramData.szBootline; + for (i = 0; (i < gNumBootParams) && (curPtr != 0); i++) + { + curPtr = strchr(curPtr, '='); + if (curPtr) // found '=' and get the param. + { + dPtr = strchr(curPtr, ' '); // find param. deliminator ' ' + memset(gBootParam[i].parameter, 0, MAX_PROMPT_LEN); + memcpy(gBootParam[i].parameter, curPtr+1, dPtr-curPtr-1); + // move to next param. + curPtr = dPtr; + } + } // for loop + + if (i < gNumBootParams) { + setDefaultBootline(); + return; + } + + convertBootInfo(); +} + +// print the bootline and board parameter info and fill in the struct for later use +// +int printSysInfo(void) +{ + int i; + ETHERNET_MAC_INFO EnetInfos[BP_MAX_ENET_MACS]; + + // display the bootline info + + if( getTagFromPartition(1) == NULL || getTagFromPartition(2) == NULL ) + gBootParam[PARAM_IDX_BOOT_IMAGE].enabled = FALSE; + + for (i = 0; i < gNumBootParams; i++) + if( gBootParam[i].enabled ) + printf("%s %s \n", gBootParam[i].promptName, gBootParam[i].parameter); + + // display the board param + displayBoardParam(); + + if( BpGetEthernetMacInfo( EnetInfos, BP_MAX_ENET_MACS ) == BP_SUCCESS ) + { + // Here we should print whether EMAC1 or EMAC2 is selected + } + + printf("\n"); + + return 0; +} + + +//************************************************************************** +// Function Name: changeBootLine +// Description : Use vxWorks bootrom style parameter input method: +// Press <enter> to use default, '-' to go to previous parameter +// Note: Parameter is set to current value in the menu. +// Returns : None. +//************************************************************************** +int changeBootLine(void) +{ + int i; + char boardIpSaved[BOOT_IP_LEN]; + NVRAM_DATA nvramData; + + readNvramData(&nvramData); + + strcpy(boardIpSaved, bootInfo.boardIp); + + if (processPrompt(gBootParam, gNumBootParams)) + { + char *blPtr = nvramData.szBootline; + int paramLen; + + memset(blPtr, 0, NVRAM_BOOTLINE_LEN); + for (i = 0; i < gNumBootParams; i++) + { + memcpy(blPtr, gBootParam[i].promptDefine, PROMPT_DEFINE_LEN); + blPtr += PROMPT_DEFINE_LEN; + paramLen = strlen(gBootParam[i].parameter); + memcpy(blPtr, gBootParam[i].parameter, paramLen); + blPtr += paramLen; + if (!(gBootParam[i].parameter[0] == ' ')) + { + memcpy(blPtr, " ", 1); + blPtr += 1; + } + } + writeNvramData(&nvramData); + } + + getBootLine(); + + // if board ip differs, do enet init + if (strcmp(boardIpSaved, bootInfo.boardIp) != 0) + enet_init(); + + return 0; + +} + +void setDefaultBootline(void) +{ + char boardIpSaved[BOOT_IP_LEN]; + NVRAM_DATA nvramData; + + readNvramData(&nvramData); + strcpy(boardIpSaved, bootInfo.boardIp); + + memset(nvramData.szBootline, 0, NVRAM_BOOTLINE_LEN); + strncpy(nvramData.szBootline, DEFAULT_BOOTLINE, strlen(DEFAULT_BOOTLINE)); + printf("Use default boot line parameters: %s\n", DEFAULT_BOOTLINE); + writeNvramData(&nvramData); + + getBootLine(); + + // if board ip differs, do enet init + if (strcmp(boardIpSaved, bootInfo.boardIp) != 0) + enet_init(); +} + +//************************************************************************** +// Function Name: changeAfeId +// Description : Use vxWorks bootrom style parameter input method: +// Press <enter> to use default, '-' to go to previous parameter +// Note: Parameter is set to current value in the menu. +// Returns : None. +//************************************************************************** +static void hex2Str(unsigned long num, char *str) +{ + static const char hextable[16] = "0123456789ABCDEF"; + unsigned long i, n; + str[0] = '0'; + str[1] = 'x'; + if (0 == num) { + str[2] = '0'; + str[3] = 0; + return; + } + str +=2; + n = num >> 28; + i = 0; + while (0 == n) { + num <<= 4; + n = num >> 28; + i++; + } + for (; i < 8; i++) { + *str++ = hextable[num >> 28]; + num <<= 4; + } + *str = 0; +} + +int changeAfeId(void) +{ + NVRAM_DATA nvramData; + + readNvramData(&nvramData); + hex2Str(nvramData.afeId[0], gAfeId[0].parameter); + hex2Str(nvramData.afeId[1], gAfeId[1].parameter); + if (processPrompt(gAfeId, gAfeIdParams)) + { + nvramData.afeId[0] = lib_atoi(gAfeId[0].parameter); + nvramData.afeId[1] = lib_atoi(gAfeId[1].parameter); + writeNvramData(&nvramData); + } + return 0; +} diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/dev_bcm63xx_eth.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/dev_bcm63xx_eth.c new file mode 100755 index 0000000..c4ea465 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/dev_bcm63xx_eth.c @@ -0,0 +1,547 @@ +/* +<:copyright-broadcom + + Copyright (c) 2002 Broadcom Corporation + All Rights Reserved + No portions of this material may be reproduced in any form without the + written permission of: + Broadcom Corporation + 16215 Alton Parkway + Irvine, California 92619 + All information contained in this document is Broadcom Corporation + company private, proprietary, and trade secret. + +:> +*/ + +/** Includes. **/ +#include "lib_types.h" +#include "lib_malloc.h" +#include "lib_string.h" +#include "lib_printf.h" + +#include "cfe_iocb.h" +#include "cfe_ioctl.h" +#include "cfe_device.h" +#include "cfe_devfuncs.h" +#include "sbmips.h" +#include "cfe_timer.h" +#include "dev_bcm63xx_eth.h" +#include "dev_bcm63xx_flash.h" +#include "mii.h" +#include "robosw_reg.h" + +#define DMA_RX_CHAN (softc->dmaPort * 2) +#define DMA_TX_CHAN (softc->dmaPort * 2 + 1) + +#define CACHE_ALIGN 16 +extern void _cfe_flushcache(int, uint8_t *, uint8_t *); +#define INVAL_RANGE(s,l) _cfe_flushcache(CFE_CACHE_INVAL_RANGE,((uint8_t *) (s)),((uint8_t *) (s))+(l)) +#define FLUSH_RANGE(s,l) _cfe_flushcache(CFE_CACHE_FLUSH_RANGE,((uint8_t *) (s)),((uint8_t *) (s))+(l)) + +/** Externs. **/ +extern unsigned long sysGetEnetModeFlag(void); + +/** Prototypes. **/ +static void bcm63xx_ether_probe( cfe_driver_t * drv, unsigned long probe_a, + unsigned long probe_b, void * probe_ptr ); +static int bcm63xx_ether_open(cfe_devctx_t *ctx); +static int bcm63xx_ether_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer); +static int bcm63xx_ether_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat); +static int bcm63xx_ether_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer); +static int bcm63xx_ether_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer); +static int bcm63xx_ether_close(cfe_devctx_t *ctx); +static int internal_open(bcmenet_softc * softc); + +/** Variables. **/ +const static cfe_devdisp_t bcm63xx_ether_dispatch = { + bcm63xx_ether_open, + bcm63xx_ether_read, + bcm63xx_ether_inpstat, + bcm63xx_ether_write, + bcm63xx_ether_ioctl, + bcm63xx_ether_close, + NULL, + NULL +}; + +const cfe_driver_t bcm63xx_enet = { + "BCM63xx Ethernet", + "eth", + CFE_DEV_NETWORK, + &bcm63xx_ether_dispatch, + bcm63xx_ether_probe +}; + +/** Functions. **/ +static void bcm63xx_ether_probe( cfe_driver_t * drv, unsigned long probe_a, + unsigned long probe_b, void * probe_ptr ) +{ + bcmenet_softc * softc; + char descr[100]; + + softc = (bcmenet_softc *) KMALLOC( sizeof(bcmenet_softc), CACHE_ALIGN ); + if( softc == NULL ) { + xprintf( "BCM63xx : Failed to allocate softc memory.\n" ); + } else { + memset( softc, 0, sizeof(bcmenet_softc) ); + + if (internal_open( softc ) == -1) + xprintf("Failed initializing enet hardware\n"); + else + { + cfe_attach( drv, softc, NULL, descr ); + } + } +} + +static int bcm63xx_ether_open(cfe_devctx_t *ctx) +{ + /* FIXME -- See if this can be returned to its normal place. */ + return 0; +} + +/* + * init_dma: Initialize DMA control register + */ +static void init_dma(bcmenet_softc *softc) +{ + uint32 *StateRam; + int i; + + /* + * clear State RAM + */ + StateRam = (UINT32 *)&softc->dmaCtrl->stram.s[0]; + for (i = 0; i < sizeof(DmaStateRam) / sizeof(UINT32) * NUM_PORTS * 2; i++) + StateRam[i] = 0; + + /* + * initialize IUDMA controller register + */ + softc->dmaCtrl->controller_cfg = DMA_FLOWC_CH1_EN; + softc->dmaCtrl->flowctl_ch1_thresh_lo = DMA_FC_THRESH_LO; + softc->dmaCtrl->flowctl_ch1_thresh_hi = DMA_FC_THRESH_HI; + softc->dmaCtrl->flowctl_ch1_alloc = 0; + + // transmit + softc->txDma->cfg = 0; /* initialize first (will enable later) */ + softc->txDma->maxBurst = DMA_MAX_BURST_LENGTH; + softc->txDma->intMask = 0; /* mask all ints */ + /* clr any pending interrupts on channel */ + softc->txDma->intStat = DMA_DONE|DMA_NO_DESC|DMA_BUFF_DONE; + softc->txDma->intMask = DMA_DONE; + softc->dmaCtrl->stram.s[DMA_TX_CHAN].baseDescPtr = (uint32)K1_TO_PHYS((uint32_t)(softc->txFirstBdPtr)); + + // receive + softc->rxDma->cfg = 0; // initialize first (will enable later) + softc->rxDma->maxBurst = DMA_MAX_BURST_LENGTH; + softc->rxDma->intMask = 0; /* mask all ints */ + /* clr any pending interrupts on channel */ + softc->rxDma->intStat = DMA_DONE|DMA_NO_DESC|DMA_BUFF_DONE; + softc->rxDma->intMask = DMA_DONE; + softc->dmaCtrl->stram.s[DMA_RX_CHAN].baseDescPtr = (uint32)K1_TO_PHYS((uint32_t)(softc->rxFirstBdPtr)); +} + + +static int internal_open(bcmenet_softc * softc) +{ + int i; + void *p; + + robosw_init(); + softc->dmaCtrl = (DmaRegs *)(SWITCH_DMA_BASE); + + softc->rxDma = &softc->dmaCtrl->chcfg[DMA_RX_CHAN]; + softc->txDma = &softc->dmaCtrl->chcfg[DMA_TX_CHAN]; + + // If doing SW reboot in EPI the controller can still be active + softc->rxDma->cfg = 0; + softc->txDma->cfg = 0; + softc->dmaCtrl->controller_cfg &= ~DMA_MASTER_EN; + + p = KMALLOC( NR_TX_BDS * sizeof(DmaDesc), CACHE_ALIGN ); + if( p == NULL ) { + xprintf( "BCM63xx : Failed to allocate txBds memory.\n" ); + return -1; + } + INVAL_RANGE(p, NR_TX_BDS * sizeof(DmaDesc)); + softc->txBds = (DmaDesc *)K0_TO_K1((uint32) p); + + p = KMALLOC( NR_RX_BDS * sizeof(DmaDesc), CACHE_ALIGN ); + if( p== NULL ) { + xprintf( "BCM63xx : Failed to allocate rxBds memory.\n" ); + KFREE( (void *)(softc->txBds) ); + softc->txBds = NULL; + return -1; + } + INVAL_RANGE(p, NR_RX_BDS * sizeof(DmaDesc)); + softc->rxBds = (DmaDesc *)K0_TO_K1((uint32) p); + + softc->rxBuffers = (uint32_t)KMALLOC( NR_RX_BDS * ENET_BUF_SIZE, CACHE_ALIGN ); + if( softc->rxBuffers == NULL ) { + xprintf( "BCM63xx : Failed to allocate RxBuffer memory.\n" ); + KFREE( (void *)(softc->txBds) ); + softc->txBds = NULL; + KFREE( (void *)(softc->rxBds) ); + softc->rxBds = NULL; + return -1; + } + INVAL_RANGE(softc->rxBuffers, NR_RX_BDS * ENET_BUF_SIZE); + + softc->txBuffers = (uint32_t)KMALLOC( NR_TX_BDS * ENET_BUF_SIZE, CACHE_ALIGN ); + if( softc->txBuffers == NULL ) { + xprintf( "BCM63xx : Failed to allocate txBuffer memory.\n" ); + KFREE( (void *)(softc->rxBuffers) ); + softc->rxBuffers = NULL; + KFREE( (void *)(softc->txBds) ); + softc->txBds = NULL; + KFREE( (void *)(softc->rxBds) ); + softc->rxBds = NULL; + return -1; + } + INVAL_RANGE(softc->txBuffers, NR_TX_BDS * ENET_BUF_SIZE); + + /* Init the Receive Buffer Descriptor Ring. */ + softc->rxFirstBdPtr = softc->rxBdReadPtr = softc->rxBds; + softc->rxLastBdPtr = softc->rxBds + NR_RX_BDS - 1; + + for(i = 0; i < NR_RX_BDS; i++) { + (softc->rxBds + i)->status = DMA_OWN; + (softc->rxBds + i)->length = ENET_BUF_SIZE; + (softc->rxBds + i)->address = softc->rxBuffers + i * ENET_BUF_SIZE; + (softc->rxBds + i)->address = K1_TO_PHYS( (softc->rxBds + i)->address ); + softc->dmaCtrl->flowctl_ch1_alloc = 1; + } + softc->rxLastBdPtr->status |= DMA_WRAP; + + /* Init Transmit Buffer Descriptor Ring. */ + softc->txFirstBdPtr = softc->txNextBdPtr = softc->txBds; + softc->txLastBdPtr = softc->txBds + NR_TX_BDS - 1; + + for(i = 0; i < NR_TX_BDS; i++) { + (softc->txBds + i)->status = 0; + (softc->txBds + i)->length = 0; + (softc->txBds + i)->address = softc->txBuffers + i * ENET_BUF_SIZE; + (softc->txBds + i)->address = K1_TO_PHYS( (softc->txBds + i)->address ); + } + softc->txLastBdPtr->status = DMA_WRAP; + + /* init dma registers */ + init_dma(softc); + + robosw_configure_ports(); + + softc->dmaCtrl->controller_cfg |= DMA_MASTER_EN; + + softc->rxDma->cfg |= DMA_ENABLE; + + softc->linkCheck = 0; + + return 0; +} + +static int bcm63xx_ether_read( cfe_devctx_t * ctx, iocb_buffer_t * buffer ) +{ + unsigned char * dstptr; + unsigned char * srcptr; + volatile DmaDesc * CurrentBdPtr; + bcmenet_softc * softc = (bcmenet_softc *) ctx->dev_softc; + uint16 dmaFlag; + + if( ctx == NULL ) { + xprintf( "No context\n" ); + return -1; + } + + if( buffer == NULL ) { + xprintf( "No dst buffer\n" ); + return -1; + } + + if( softc == NULL ) { + xprintf( "softc has not been initialized.\n" ); + return -1; + } + + dmaFlag = (uint16) softc->rxBdReadPtr->status; + if (!(dmaFlag & DMA_EOP)) + { + xprintf("dmaFlag (return -1)[%04x]\n", dmaFlag); + return -1; + } + + dstptr = buffer->buf_ptr; + CurrentBdPtr = softc->rxBdReadPtr; + + srcptr = (unsigned char *)( PHYS_TO_K1(CurrentBdPtr->address) ); + + buffer->buf_retlen = ((CurrentBdPtr->length < buffer->buf_length) ? CurrentBdPtr->length : buffer->buf_length); + + memcpy( dstptr, srcptr, buffer->buf_retlen ); + + CurrentBdPtr->length = ENET_BUF_SIZE; + CurrentBdPtr->status &= DMA_WRAP; + CurrentBdPtr->status |= DMA_OWN; + + IncRxBdPtr( CurrentBdPtr, softc ); + softc->rxBdReadPtr = CurrentBdPtr; + softc->dmaCtrl->flowctl_ch1_alloc = 1; + + // enable rx dma + softc->rxDma->cfg = DMA_ENABLE; + return 0; +} + + +static int bcm63xx_ether_inpstat( cfe_devctx_t * ctx, iocb_inpstat_t * inpstat ) +{ + bcmenet_softc * softc; + volatile DmaDesc * CurrentBdPtr; + + /* ============================= ASSERTIONS ============================= */ + + if( ctx == NULL ) { + xprintf( "No context\n" ); + return -1; + } + + if( inpstat == NULL ) { + xprintf( "No inpstat buffer\n" ); + return -1; + } + + softc = (bcmenet_softc *)ctx->dev_softc; + if( softc == NULL ) { + xprintf( "softc has not been initialized.\n" ); + return -1; + } + + /* ====================================================================== */ + + + CurrentBdPtr = softc->rxBdReadPtr; + + // inp_status == 1 -> data available + inpstat->inp_status = (CurrentBdPtr->status & DMA_OWN) ? 0 : 1; + + if (!inpstat->inp_status || (++softc->linkCheck > 100)) { + // Don't check link state too often when receiving data + softc->linkCheck = 0; + robosw_check_ports(); + } + + return 0; +} + + +static int bcm63xx_ether_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer) +{ + uint32_t status; + unsigned char * dstptr; + bcmenet_softc * softc; + volatile DmaDesc * CurrentBdPtr; + volatile uint32 txEvents = 0; + + /* ============================= ASSERTIONS ============================= */ + + if( ctx == NULL ) { + xprintf( "No context\n" ); + return -1; + } + + if( buffer == NULL ) { + xprintf( "No dst buffer\n" ); + return -1; + } + + if( buffer->buf_length > ENET_MAX_MTU_SIZE ) { + xprintf( "src buffer too large.\n" ); + xprintf( "size is %d\n", buffer->buf_length ); + return -1; + } + + softc = (bcmenet_softc *) ctx->dev_softc; + if( softc == NULL ) { + xprintf( "softc has not been initialized.\n" ); + return -1; + } + + /* ====================================================================== */ + + CurrentBdPtr = softc->txNextBdPtr; + + /* Find out if the next BD is available. */ + if( CurrentBdPtr->status & DMA_OWN ) { + xprintf( "No tx BD available ?!\n" ); + return -1; + } + + dstptr = (unsigned char *)PHYS_TO_K1( CurrentBdPtr->address ); + memcpy( dstptr, buffer->buf_ptr, buffer->buf_length ); + + /* Set status of DMA BD to be transmitted. */ + status = DMA_SOP | DMA_EOP | DMA_APPEND_CRC | DMA_OWN; + if( CurrentBdPtr == softc->txLastBdPtr ) { + status |= DMA_WRAP; + } + + CurrentBdPtr->length = ((buffer->buf_length < ETH_ZLEN) ? ETH_ZLEN : buffer->buf_length); + CurrentBdPtr->status = status; + + // Enable DMA for this channel + softc->txDma->cfg |= DMA_ENABLE; + + // poll the dma status until done + do + { + txEvents = CurrentBdPtr->status; + } while (txEvents & DMA_OWN); + + + //Advance BD pointer to next in the chain. + InctxBdPtr( CurrentBdPtr, softc ); + softc->txNextBdPtr = CurrentBdPtr; + + return 0; +} + +static int bcm63xx_ether_ioctl(cfe_devctx_t *ctx, iocb_buffer_t *buffer) +{ + bcmenet_softc *softc = (bcmenet_softc *) ctx->dev_softc; + + switch ((int)buffer->buf_ioctlcmd) { + case IOCTL_ETHER_GETHWADDR: + memcpy(buffer->buf_ptr, softc->hwaddr, sizeof(softc->hwaddr)); + return 0; + + case IOCTL_ETHER_SETHWADDR: + memcpy(softc->hwaddr, buffer->buf_ptr, sizeof(softc->hwaddr)); + return 0; + + default: + return -1; + } + + return 0; +} + +/* + * bcm63xx_ether_flush: Flushes packets from the DMA receive ring + */ +static int bcm63xx_ether_flush(bcmenet_softc * softc) +{ + volatile DmaDesc * CurrentBdPtr; + uint16 dmaFlag; + unsigned char * srcptr; + uint16 len; + uint32 rxBdsCount = 0; + int i; + + if( softc == NULL ) { + xprintf( "softc has not been initialized.\n" ); + return -1; + } + + xprintf("Disabling Switch ports.\n"); + + /* disable forwarding */ + SWITCH->SwitchMode &= ~SwitchMode_FwdgEn; + + /* Bring the link down on all switch ports */ + for(i=0; i<8; ++i) { + SWITCH->PortOverride[i] &= ~PortOverride_Linkup; + /* disable Rx and Tx */ + SWITCH->PortCtrl[i] = PortCtrl_DisableTx | PortCtrl_DisableRx; + } + + for(i=0; i<1000; ++i) { + cfe_usleep(1000); + } + + xprintf("Flushing Receive Buffers...\n"); + + while(!((dmaFlag = (uint16) softc->rxBdReadPtr->status) & DMA_OWN)) { + + if (!(dmaFlag & DMA_EOP)) + { + xprintf("dmaFlag (return -1)[%04x]\n", dmaFlag); + return -1; + } + + CurrentBdPtr = softc->rxBdReadPtr; + + srcptr = (unsigned char *)( PHYS_TO_K1(CurrentBdPtr->address) ); + + len = CurrentBdPtr->length; + + ++rxBdsCount; + + CurrentBdPtr->length = ENET_BUF_SIZE; + CurrentBdPtr->status &= DMA_WRAP; + CurrentBdPtr->status |= DMA_OWN; + + IncRxBdPtr( CurrentBdPtr, softc ); + softc->rxBdReadPtr = CurrentBdPtr; + softc->dmaCtrl->flowctl_ch1_alloc = 1; + + // enable rx dma + softc->rxDma->cfg = DMA_ENABLE; + } + + xprintf("%d buffers found.\n", rxBdsCount); + + return 0; +} + +static int bcm63xx_ether_close(cfe_devctx_t *ctx) +{ + int i; + bcmenet_softc * softc = (bcmenet_softc *) ctx->dev_softc; + unsigned long sts; + + /* flush Rx DMA Channel */ + bcm63xx_ether_flush(softc); + + xprintf("Closing DMA Channels.\n"); + + sts = softc->rxDma->intStat; + softc->rxDma->intStat = sts; + softc->rxDma->intMask = 0; + softc->rxDma->cfg = 0; + // wait the current packet to complete before turning off EMAC, otherwise memory corruption can occur. + for(i=0; softc->rxDma->cfg & DMA_ENABLE; i++) { + // put the line below inside - it seems the signal can be lost and DMA never stops + softc->rxDma->cfg = 0; + if (i >= 20) { + xprintf("Rx Timeout !!!\n"); + break; + } + cfe_usleep(100); + } + + sts = softc->txDma->intStat; + softc->txDma->intStat = sts; + softc->txDma->intMask = 0; + softc->txDma->cfg = 0; + for(i=0; softc->txDma->cfg & DMA_ENABLE; i++) { + // put the line below inside - it seems the signal can be lost and DMA never stops + softc->txDma->cfg = 0; + if (i >= 20) { + xprintf("Tx Timeout !!!\n"); + break; + } + cfe_usleep(100); + } + + /* return buffer allocation register internal count to 0 */ + softc->dmaCtrl->flowctl_ch1_alloc = (DMA_BUF_ALLOC_FORCE | 0); + + softc->dmaCtrl->controller_cfg &= ~DMA_MASTER_EN; + + KFREE( (void *)(softc->txBuffers) ); + KFREE( (void *)(softc->rxBuffers) ); + KFREE( (void *)(softc->txBds) ); + KFREE( (void *)(softc->rxBds) ); + return 0; +} diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/dev_bcm63xx_flash.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/dev_bcm63xx_flash.c new file mode 100755 index 0000000..cf38104 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/dev_bcm63xx_flash.c @@ -0,0 +1,629 @@ +/*************************************************************************** + * Broadcom Corp. Confidential + * Copyright 2001 Broadcom Corp. All Rights Reserved. + * + * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED + * SOFTWARE LICENSE AGREEMENT BETWEEN THE USER AND BROADCOM. + * YOU HAVE NO RIGHT TO USE OR EXPLOIT THIS MATERIAL EXCEPT + * SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. + * + *************************************************************************** + * File Name : bcm63xx_flash.c + * + * Description: This file contains the flash device driver for bcm63xx board. Very similar to + * board.c in linux development. + * + * Created on : 4/18/2002 seanl + * + ***************************************************************************/ + + +/* Includes. */ +#include "lib_types.h" +#include "lib_malloc.h" +#include "lib_string.h" +#include "lib_printf.h" + +#include "bcm_map.h" +#include "bcm_hwdefs.h" +#include "dev_bcm63xx_flash.h" +#include "flash_api.h" +#include "boardparms.h" +#include "boardparms_voice.h" +#include "bcm63xx_util.h" + +//#define DEBUG_FLASH + +/* This driver determines the NVRAM and persistent storage flash address and + * length. + */ +/* Foxconn start jenny add for timeout */ +extern int NMRPKeepAlive(void); +extern int NMRPTFTPWaiting(void); +extern int g_nmrp_keepalive; +extern int nmrp_server_detected; +/* Foxconn end jenny add for timeout*/ + +static FLASH_ADDR_INFO fInfo; + +//************************************************************************************** +// Flash read/write and image downloading.. +//************************************************************************************** + +void kerSysFlashInit( void ) +{ + NVRAM_DATA nvramData; + + flash_init(); + + while ((readNvramData(&nvramData) != 0) || (BpSetBoardId(nvramData.szBoardId) != BP_SUCCESS)) + { + printf("\n*** Board is not initialized properly ***\n\n"); + //setBoardParam(); /* Bob removed to set default board parameters, 11/01/2010 */ + setDefaultBoardParam(); /* Bob added to set default board parameters, 11/01/2010 */ + } + + fInfo.flash_rootfs_start_offset = flash_get_sector_size(0); + if( fInfo.flash_rootfs_start_offset < FLASH_LENGTH_BOOT_ROM ) + fInfo.flash_rootfs_start_offset = FLASH_LENGTH_BOOT_ROM; + + flash_init_info(&nvramData, &fInfo); + +#if (INC_NAND_FLASH_DRIVER==1) + validateNandPartTbl(&nvramData); + + /* Check if spare area data contains non 0xff values after JFFS2 clean + * marker. Early version of this CFE driver filled bytes 8 - 11 with + * 0 which Linux does not like. + */ + { + extern int read_spare_data(int blk, unsigned char *buf, int bufsize); + + int blk_size = flash_get_sector_size(0) / 1024; + int blk_start = nvramData.ulNandPartOfsKb[NP_DATA] / blk_size; + unsigned char spare[64]; + + memset(spare, 0xff, sizeof(spare)); + if( read_spare_data(blk_start, spare, sizeof(spare)) == FLASH_API_OK ) + { + const int spare_len = 8; /* Linux JFFS2 spare area is 8 bytes */ + int i; + + for( i = spare_len; i < sizeof(spare); i++ ) + { + if( spare[i] != 0xff ) + { + printf("Data spare area is not correct, erasing psi\n"); + printf("%8.8lx %8.8lx %8.8lx %8.8lx\n", + *(unsigned long *) &spare[0],*(unsigned long *)&spare[4], + *(unsigned long *) &spare[8],*(unsigned long *)&spare[12]); + kerSysErasePsi(); + break; + } + } + } + } +#endif +} + +#if (INC_NAND_FLASH_DRIVER==1) || (INC_SPI_PROG_NAND==1) +/*********************************************************************** + * Function Name: validateNandPartTbl + * Description : Checks the NAND partition table fields in NVRAM data. + * If nay of the fields are not valid, new values are set. + * Returns : None. + ***********************************************************************/ +void validateNandPartTbl(PNVRAM_DATA pNvramData) +{ + unsigned long ulBlockSizeKb = (unsigned long)flash_get_sector_size(0)/1024; + unsigned long ulTotalSizeKb = (unsigned long)flash_get_total_size() / 1024; + +#if (INC_SPI_PROG_NAND==1) + if( flash_get_flash_type() != FLASH_IFC_NAND ) + return; +#endif + if( pNvramData->ulNandPartSizeKb[NP_BOOT] != ulBlockSizeKb || + pNvramData->ulNandPartSizeKb[NP_DATA] != NAND_DATA_SIZE_KB || + (pNvramData->ulNandPartSizeKb[NP_BBT] != NAND_BBT_SMALL_SIZE_KB && + pNvramData->ulNandPartSizeKb[NP_BBT] != NAND_BBT_BIG_SIZE_KB) ) + { + /* Initialize NAND flash partition table. */ + unsigned long ulRootfsSizeKb; + unsigned long ulBbtSizeKb = (ulTotalSizeKb > NAND_BBT_THRESHOLD_KB) + ? NAND_BBT_BIG_SIZE_KB : NAND_BBT_SMALL_SIZE_KB; + + /* The Boot partition is first and is one block in size. */ + pNvramData->ulNandPartOfsKb[NP_BOOT] = 0; + pNvramData->ulNandPartSizeKb[NP_BOOT] = ulBlockSizeKb; + + /* The Bad Block Table partition is last and is a constant size. */ + pNvramData->ulNandPartOfsKb[NP_BBT] = ulTotalSizeKb - ulBbtSizeKb; + pNvramData->ulNandPartSizeKb[NP_BBT] = ulBbtSizeKb; + + /* The Data partition is before the BBT and is a constant size. */ + pNvramData->ulNandPartOfsKb[NP_DATA] = + pNvramData->ulNandPartOfsKb[NP_BBT] - NAND_DATA_SIZE_KB; + pNvramData->ulNandPartSizeKb[NP_DATA] = NAND_DATA_SIZE_KB; + + /* The first rootfs partition starts at the second sector. */ + pNvramData->ulNandPartOfsKb[NP_ROOTFS_1] = ulBlockSizeKb; + + /* The size of the two root file system partitions is whatever is left + * after the Boot, Data and BBT paritions divided by 2 and evenly + * divisible by the NAND flash block size. + */ + ulRootfsSizeKb = ((pNvramData->ulNandPartOfsKb[NP_DATA] - + pNvramData->ulNandPartOfsKb[NP_ROOTFS_1]) / 2); + ulRootfsSizeKb = (ulRootfsSizeKb / ulBlockSizeKb) * ulBlockSizeKb; + +#if 1 /* support two file system partitions */ + pNvramData->ulNandPartSizeKb[NP_ROOTFS_1] = ulRootfsSizeKb; + + pNvramData->ulNandPartOfsKb[NP_ROOTFS_2] = + pNvramData->ulNandPartOfsKb[NP_ROOTFS_1] + ulRootfsSizeKb; + pNvramData->ulNandPartSizeKb[NP_ROOTFS_2] = ulRootfsSizeKb; +#else /* support one file system partition */ + pNvramData->ulNandPartSizeKb[NP_ROOTFS_1] = ulRootfsSizeKb * 2; + + pNvramData->ulNandPartOfsKb[NP_ROOTFS_2] = ulTotalSizeKb; + pNvramData->ulNandPartSizeKb[NP_ROOTFS_2] = 0; +#endif + + writeNvramData(pNvramData); + +#if defined(DEBUG_FLASH) + printf("boot offset=0x%8.8lx, size=0x%8.8lx\n", + pNvramData->ulNandPartOfsKb[NP_BOOT], + pNvramData->ulNandPartSizeKb[NP_BOOT]); + printf("rootfs1 offset=0x%8.8lx, size=0x%8.8lx\n", + pNvramData->ulNandPartOfsKb[NP_ROOTFS_1], + pNvramData->ulNandPartSizeKb[NP_ROOTFS_1]); + printf("rootfs2 offset=0x%8.8lx, size=0x%8.8lx\n", + pNvramData->ulNandPartOfsKb[NP_ROOTFS_2], + pNvramData->ulNandPartSizeKb[NP_ROOTFS_2]); + printf("data offset=0x%8.8lx, size=0x%8.8lx\n", + pNvramData->ulNandPartOfsKb[NP_DATA], + pNvramData->ulNandPartSizeKb[NP_DATA]); + printf("bbt offset=0x%8.8lx, size=0x%8.8lx\n", + pNvramData->ulNandPartOfsKb[NP_BBT], + pNvramData->ulNandPartSizeKb[NP_BBT]); +#endif + } +} +#else +void validateNandPartTbl(PNVRAM_DATA pNvramData) +{ +} +#endif + + +/*********************************************************************** + * Function Name: kerSysFlashAddrInfoGet + * Description : Fills in a structure with information about the NVRAM + * and persistent storage sections of flash memory. + * Returns : None. + ***********************************************************************/ +void kerSysFlashAddrInfoGet(PFLASH_ADDR_INFO pflash_addr_info) +{ + memcpy(pflash_addr_info, &fInfo, sizeof(FLASH_ADDR_INFO)); +} + +// get shared blks into *** pTempBuf *** which has to be released bye the caller! +// return: if pTempBuf != NULL, poits to the data with the dataSize of the buffer +// !NULL -- ok +// NULL -- fail +static unsigned char *getSharedBlks(int start_blk, int num_blks) +{ + int i = 0; + int usedBlkSize = 0; + int sect_size = 0; + unsigned char *pTempBuf = NULL; + unsigned char *pBuf = NULL; + + for (i = start_blk; i < (start_blk + num_blks); i++) + usedBlkSize += flash_get_sector_size((unsigned short) i); + + if ((pTempBuf = (unsigned char *) KMALLOC(usedBlkSize, sizeof(long))) == NULL) + { + printf("failed to allocate memory with size: %d\n", usedBlkSize); + return pTempBuf; + } + + pBuf = pTempBuf; + for (i = start_blk; i < (start_blk + num_blks); i++) + { + sect_size = flash_get_sector_size((unsigned short) i); +#if defined(DEBUG_FLASH) + printf("getShareBlks: blk=%d, sect_size=%d\n", i, sect_size); +#endif + flash_read_buf((unsigned short)i, 0, pBuf, sect_size); + pBuf += sect_size; + } + + return pTempBuf; +} + + + +// Set the pTempBuf to flash from start_blk for num_blks +// return: +// 0 -- ok +// -1 -- fail +static int setSharedBlks(int start_blk, int num_blks, unsigned char *pTempBuf) +{ + int i = 0; + int sect_size = 0; + int sts = 0; + unsigned char *pBuf = pTempBuf; + + for (i = start_blk; i < (start_blk + num_blks); i++) + { + sect_size = flash_get_sector_size((unsigned short) i); + flash_sector_erase_int(i); + if (flash_write_buf(i, 0, pBuf, sect_size) != sect_size) + { + printf("Error writing flash sector %d.", i); + sts = -1; + break; + } + +#if defined(DEBUG_FLASH) + printf("setShareBlks: blk=%d, sect_size=%d\n", i, sect_size); +#endif + + pBuf += sect_size; + } + + return sts; +} + + + +/******************************************************************************* + * NVRAM functions + *******************************************************************************/ + +// get nvram data +// return: +// 0 - ok +// -1 - fail +int kerSysNvRamGet(unsigned char *string, int strLen, int offset) +{ + unsigned char *pBuf = NULL; + + if ((pBuf = getSharedBlks(NVRAM_SECTOR, 1)) == NULL) + return -1; + + // get string off the memory buffer + memcpy(string, (pBuf + NVRAM_DATA_OFFSET + offset), strLen); + + KFREE(pBuf); + + return 0; +} + + +// set nvram +// return: +// 0 - ok +// -1 - fail +int kerSysNvRamSet(unsigned char *string, int strLen, int offset) +{ + int sts = 0; + unsigned char *pBuf = NULL; + + if ((pBuf = getSharedBlks(NVRAM_SECTOR, 1)) == NULL) + return -1; + + // set string to the memory buffer + memcpy((pBuf + NVRAM_DATA_OFFSET + offset), string, strLen); + + if (setSharedBlks(NVRAM_SECTOR, 1, pBuf) != 0) + sts = -1; + + KFREE(pBuf); + + return sts; +} + +/*********************************************************************** + * Function Name: kerSysEraseNvRam + * Description : Erase the NVRAM storage section of flash memory. + * Returns : 1 -- ok, 0 -- fail + ***********************************************************************/ +int kerSysEraseNvRam(void) +{ + int sts = 1; + unsigned char *tempStorage = KMALLOC(NVRAM_LENGTH, sizeof(long)); + + // just write the whole buf with '0xff' to the flash + if (!tempStorage) + sts = 0; + else + { + memset(tempStorage, 0xff, NVRAM_LENGTH); + if (kerSysNvRamSet(tempStorage, NVRAM_LENGTH, 0) != 0) + sts = 0; + KFREE(tempStorage); + } + + return sts; +} + + +/******************************************************************************* + * PSI functions + *******************************************************************************/ + +#if (INC_NAND_FLASH_DRIVER!=1) +/** set psi while preserving any other data that might be sharing sectors with + * the psi, e.g. scratch pad. + * + * @param string (IN) buffer that holds the data to be written. + * @param strLen (IN) length of buffer. + * + * @return 0 if OK, -1 on failure. + */ +static int kerSysPsiSet(const unsigned char *string, int strLen) +{ + int sts = 0; + unsigned char *pBuf = NULL; + + if ((pBuf = getSharedBlks(fInfo.flash_persistent_start_blk, + fInfo.flash_persistent_number_blk)) == NULL) + return -1; + + // set string to the memory buffer + memcpy((pBuf + fInfo.flash_persistent_blk_offset), string, strLen); + + if (setSharedBlks(fInfo.flash_persistent_start_blk, + fInfo.flash_persistent_number_blk, pBuf) != 0) + sts = -1; + + KFREE(pBuf); + + return sts; +} + +/** set backup psi + * + * Backup PSI does not share its sectors with anything else, so this + * function does not need to read first and write. Just write. + * This function expects the length of the buffer to be exactly the + * length of the entire PSI. + * + * @param string (IN) buffer that holds the data to be written. + * + * @return 0 if OK, -1 on failure. + */ +static int kerSysBackupPsiSet(const unsigned char *string) +{ + int sts = 0; + + if (setSharedBlks(fInfo.flash_backup_psi_start_blk, + fInfo.flash_backup_psi_number_blk, + (unsigned char *) string) != 0) + sts = -1; + + return sts; +} + +/*********************************************************************** + * Function Name: kerSysErasePsi + * Description : Erase the Psi storage section of flash memory. + * Returns : 1 -- ok, 0 -- fail + ***********************************************************************/ +int kerSysErasePsi(void) +{ + int sts = 1; + unsigned char *tempStorage; + + if (fInfo.flash_persistent_start_blk == 0) { + sts = 0; + } + else { + tempStorage = KMALLOC(fInfo.flash_persistent_length, sizeof(long)); + // just write the whole buf with '0xff' to the flash + if (!tempStorage) + sts = 0; + else + { + memset(tempStorage, 0xff, fInfo.flash_persistent_length); + if (kerSysPsiSet(tempStorage, fInfo.flash_persistent_length) != 0) + sts = 0; + + // Also erase backup psi if it is there + if (fInfo.flash_backup_psi_number_blk > 0) + { + if (kerSysBackupPsiSet(tempStorage) != 0) + sts = 0; + } + + KFREE(tempStorage); + } + } + return sts; +} +#else +int kerSysErasePsi(void) +{ + int sts = 1; + NVRAM_DATA nvramData; + + if( readNvramData(&nvramData) == 0 ) + { + int blk_size = flash_get_sector_size(0) / 1024; + int blk_start = nvramData.ulNandPartOfsKb[NP_DATA] / blk_size; + int total_blks = + blk_start + (nvramData.ulNandPartSizeKb[NP_DATA]) / blk_size; + + while( blk_start < total_blks ) + { + flash_sector_erase_int(blk_start); + blk_start++; + } + sts = 0; + } + + return(sts); +} +#endif + +// flash bcm image +// return: +// 0 - ok +// !0 - the sector number fail to be flashed (should not be 0) +int kerSysBcmImageSet( int flash_start_addr, unsigned char *string, int size, int fWholeImage) +{ + int sts; + int sect_size; + int blk_start; + // int savedSize = size; + int total_blks = flash_get_numsectors(); + + /* Foxconn add by Cliff Wang, 03/23/2010 */ + unsigned char *pTempBuf = NULL; + int savedBlkStart; + /* Foxconn add end by Cliff Wang, 03/23/2010 */ + + if( flash_get_flash_type() == FLASH_IFC_NAND ) + { + if( flash_start_addr == FLASH_BASE ) + total_blks = 1; + else + { + NVRAM_DATA nvramData; + + if( readNvramData(&nvramData) == 0 ) + { + sect_size = flash_get_sector_size(0); + int rootfs = + ((flash_start_addr - FLASH_BASE) / 1024 == + nvramData.ulNandPartOfsKb[NP_ROOTFS_2]) + ? NP_ROOTFS_2 : NP_ROOTFS_1; + + total_blks = (nvramData.ulNandPartOfsKb[rootfs] + + nvramData.ulNandPartSizeKb[rootfs]) / (sect_size/ 1024); + } + } + } + +#if defined(DEBUG_FLASH) + printf("kerSysBcmImageSet: flash_start_addr=0x%x string=%p len=%d wholeImage=%d\n", + flash_start_addr, string, size, fWholeImage); +#endif + + blk_start = flash_get_blk(flash_start_addr); + /* Foxconn add start by Cliff Wang, 03/23/2010 */ + savedBlkStart = blk_start; + if( blk_start < 0 ) + return( -1 ); + /* Foxconn add end by Cliff Wang, 03/23/2010 */ + + /* write image to flash memory */ + do + { + g_nmrp_keepalive = 1; /* Foxconn add by Cliff Wang, 03/23/2010 */ + + sect_size = flash_get_sector_size(blk_start); + +#if defined(DEBUG_FLASH) + printf("Image flashing on block: %d\n", blk_start); +#endif + + // share the blk with psi only when fWholeImage == 0 + // Foxconn modified by Silver Shih for burn board Id + if ((!fWholeImage && blk_start == fInfo.flash_persistent_start_blk) || (fWholeImage == 5)) + { + +#if 0 + if (size > (sect_size - fInfo.flash_persistent_length)) + { + printf("Image is too big\n"); + break; // image is too big. Can not overwrite to psi + } +#endif + + if ((pTempBuf = (unsigned char *) KMALLOC(sect_size, sizeof(long))) == NULL) + { + printf("Failed to allocate memory with size: %d\n", sect_size); + break; + } + flash_read_buf((unsigned short)blk_start, 0, pTempBuf, sect_size); + memcpy(pTempBuf, string, size); + flash_sector_erase_int(blk_start); // erase blk before flash + + + if (flash_write_buf(blk_start, 0, pTempBuf, sect_size) == sect_size) + size = 0; // break out and say all is ok + break; + } + + flash_sector_erase_int(blk_start); // erase blk before flash + + if (sect_size > size) + { + if (size & 1) + size++; + sect_size = size; + } + if (flash_write_buf(blk_start, 0, string, sect_size) != sect_size) { + if( flash_get_flash_type() != FLASH_IFC_NAND ) + break; + blk_start++; + } + else { + printf("."); + blk_start++; + string += sect_size; + size -= sect_size; + + /* Foxconn added start by jenny @NMRP */ + if(nmrp_server_detected==1) // in NMRP mode + { + if(blk_start - savedBlkStart == 30) + { + savedBlkStart = blk_start; + printf("\n"); + NMRPKeepAlive(); + } + } + /* Foxconn added end by jenny @NMRP */ + } + } while (size > 0); + g_nmrp_keepalive = 0; /* Foxconn added by jenny add for timeout */ + +#if 0 /* Foxconn removed by EricHuang */ + if (size == 0 && fWholeImage && savedSize > FLASH_LENGTH_BOOT_ROM) + { + // If flashing a whole image, erase to end of flash. + while( blk_start < total_blks ) + { + flash_sector_erase_int(blk_start); + printf("."); + blk_start++; + } + } +#endif + + printf("\n\n"); + + if( size == 0 ) + sts = 0; // ok + else + sts = blk_start; // failed to flash this sector + + g_nmrp_keepalive = 0; /* Foxconn jenny add for timeout */ + return sts; +} + +unsigned long kerSysReadFromFlash( void *toaddr, unsigned long fromaddr, + unsigned long len ) +{ + int sect = flash_get_blk((int) fromaddr); + unsigned char *start = flash_get_memptr(sect); + flash_read_buf( sect, (int) fromaddr - (int) start, toaddr, len ); + + return(len); +} + diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/dev_bcm63xx_uart.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/dev_bcm63xx_uart.c new file mode 100755 index 0000000..3b2ce63 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/dev_bcm63xx_uart.c @@ -0,0 +1,211 @@ +#include "cfe.h" +#include "lib_types.h" +#include "lib_malloc.h" +#include "lib_printf.h" +#include "cfe_iocb.h" +#include "cfe_device.h" +#include "cfe_ioctl.h" + +#include "sbmips.h" +#include "bsp_config.h" + +#include "bcm_hwdefs.h" +#include "bcm_map.h" + +static void bcm63xx_uart_probe(cfe_driver_t *drv, + unsigned long probe_a, unsigned long probe_b, + void *probe_ptr); + +static int bcm63xx_uart_open(cfe_devctx_t *ctx); +static int bcm63xx_uart_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer); +static int bcm63xx_uart_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat); +static int bcm63xx_uart_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer); +static int bcm63xx_uart_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer); +static int bcm63xx_uart_close(cfe_devctx_t *ctx); + +const static cfe_devdisp_t bcm63xx_uart_dispatch = { + bcm63xx_uart_open, + bcm63xx_uart_read, + bcm63xx_uart_inpstat, + bcm63xx_uart_write, + bcm63xx_uart_ioctl, + bcm63xx_uart_close, + NULL, + NULL +}; + + +const cfe_driver_t bcm63xx_uart = { + "BCM63xx DUART", + "uart", + CFE_DEV_SERIAL, + &bcm63xx_uart_dispatch, + bcm63xx_uart_probe +}; + + +typedef struct bcm63xx_uart_s { + int baudrate; +} bcm63xx_uart_t; + + +static void bcm63xx_set_baudrate( bcm63xx_uart_t * softc ) +{ + uint32_t baudwd; + + baudwd = (FPERIPH / softc->baudrate) / 16; + if( baudwd & 0x1 ) { + baudwd = baudwd / 2; + } else { + baudwd = baudwd / 2 - 1; + } + UART->baudword = baudwd; +} + + +static void bcm63xx_uart_probe(cfe_driver_t *drv, + unsigned long probe_a, unsigned long probe_b, + void *probe_ptr) +{ + bcm63xx_uart_t * softc; + char descr[80]; + + /* enable the transmitter interrupt? */ + + /* + * probe_a is the DUART base address. + * probe_b is the channel-number-within-duart (0 or 1) + * probe_ptr is unused. + */ + softc = (bcm63xx_uart_t *) KMALLOC(sizeof(bcm63xx_uart_t),0); + if (softc) { + xsprintf( descr, "%s channel %d", drv->drv_description, probe_b ); + cfe_attach( drv, softc, NULL, descr ); + } +} + +static int bcm63xx_uart_open(cfe_devctx_t *ctx) +{ + bcm63xx_uart_t * softc = ctx->dev_softc; + + /* Enable the UART clock */ + softc->baudrate = CFG_SERIAL_BAUD_RATE; + bcm63xx_set_baudrate( softc ); + + UART->control = BRGEN | TXEN | RXEN; + UART->config = BITS8SYM | ONESTOP; + UART->fifoctl = RSTTXFIFOS | RSTRXFIFOS; + UART->intMask = 0; + + return 0; +} + + +static int bcm63xx_uart_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer) +{ + unsigned char * bptr; + int blen; + uint32_t status; + char inval; + + bptr = buffer->buf_ptr; + blen = buffer->buf_length; + + while (blen > 0) { + status = UART->intStatus; + if(status & (RXOVFERR | RXPARERR | RXFRAMERR | RXBRK)) { + /* RX over flow */ + if(status & RXOVFERR) { + /* reset RX FIFO to clr interrupt */ + UART->fifoctl |= RSTRXFIFOS; + } + + /* other errors just read the bad character to clear the bit */ + inval = UART->Data; + } + else if(status & RXFIFONE) { + *bptr++ = UART->Data; + blen--; + } + else + break; + } + + buffer->buf_retlen = buffer->buf_length - blen; + return 0; +} + + +static int bcm63xx_uart_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat) +{ + inpstat->inp_status = UART->intStatus & RXFIFONE; + return 0; +} + + +static int bcm63xx_uart_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer) +{ + unsigned char * bptr; + int blen; + uint32_t status; + + bptr = buffer->buf_ptr; + blen = buffer->buf_length; + + status = 0; + while( (blen > 0) && !status ) { + /* Wait for the buffer to empty before we write the next character */ + /* FIXME - The serial port should be able to accept more than one */ + /* character at a time. Why doesn't it work though? */ + do { + status = UART->intStatus & TXFIFOEMT; + } while( !status ); + UART->Data = *bptr; + bptr++; + blen--; + + status = UART->intStatus & (TXOVFERR|TXUNDERR); + } + + if( status ) { + /* Reset TX FIFO */ + UART->fifoctl |= RSTTXFIFOS; + blen++; + } + + buffer->buf_retlen = buffer->buf_length - blen; + return 0; +} + + +static int bcm63xx_uart_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer) +{ + bcm63xx_uart_t * softc = ctx->dev_softc; + unsigned int * info = (unsigned int *) buffer->buf_ptr; + + switch ((int)buffer->buf_ioctlcmd) { + case IOCTL_SERIAL_GETSPEED: + *info = softc->baudrate; + break; + case IOCTL_SERIAL_SETSPEED: + softc->baudrate = *info; + bcm63xx_set_baudrate( softc ); + break; + case IOCTL_SERIAL_GETFLOW: + *info = SERIAL_FLOW_NONE; + break; + case IOCTL_SERIAL_SETFLOW: + break; + default: + return -1; + } + + return 0; +} + + +static int bcm63xx_uart_close(cfe_devctx_t *ctx) +{ + /* Turn off the UART clock. */ + return 0; +} diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/html/ul.html b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/html/ul.html new file mode 100755 index 0000000..a663a35 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/html/ul.html @@ -0,0 +1,48 @@ +<html> + <head> + <meta HTTP-EQUIV='Pragma' CONTENT='no-cache'> + <script language="javascript"> +<!-- hide + +var progress = 0; + +function isInProgress() { + if ( progress == 0 ) { + progress = 1; + return true; + } + alert('Upload software is in progress. Please wait for a minute.'); + return false; +} + +// done hiding --> +</script> + </head> + <body> + <blockquote> + <form method='post' ENCTYPE='multipart/form-data' action='upload.cgi' onSubmit='return isInProgress();'> + <b>Update Software</b><br> + <br> + <b>Step 1:</b> Obtain an updated software image file from your ISP.<br> + <br> + <b>Step 2:</b> Enter the path to the image file location in the box below or + click the "Browse" button to locate the image file.<br> + <br> + <b>Step 3:</b> Click the "Update Software" button once to upload the new image + file.<br> + <br> + NOTE: The update process takes about 2 minutes to complete, and your DSL Router + will reboot.<br> + <br> + <table border="0" cellpadding="0" cellspacing="0"> + <tr> + <td>Software File Name: + </td> + <td><input type='file' name='filename' size='15'></td> + </tr> + </table> + <p align="center"><input type='submit' value='Update Software'></p> + </form> + </blockquote> + </body> +</html> diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/html/ulinfo.html b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/html/ulinfo.html new file mode 100755 index 0000000..1edb2ae --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/html/ulinfo.html @@ -0,0 +1,60 @@ +<html> + <head> + <meta HTTP-EQUIV='Pragma' CONTENT='no-cache'> + <script language="javascript"> +<!-- hide +var msg = new Array(); +msg[0] = 'New software is being programmed to the flash memory. The DSL Router will reboot upon completion. This process will take about 2 minutes.'; +msg[1] = 'Image uploading failed. The system is out of memory. The DSL Router is rebooting.'; +msg[2] = 'Image uploading failed. No image file was selected.'; +msg[3] = 'Image uploading failed. The selected file contains an illegal image.'; +msg[4] = 'Image uploading failed. The selected file contains an illegal image.'; +msg[5] = 'Image uploading failed. The selected file contains an illegal image.'; +msg[6] = ' '; +msg[7] = 'Image uploading failed. The selected file contains an illegal image.'; + +var idxStr = '<%%>'; + +function getMsgIndex() { + var idxNum = parseInt(idxStr); + if ( isNaN(idxNum) || idxNum < 0 || idxNum > 7 ) + idxNum = 7; + + return idxNum; +} + +function reboot() { + var loc = 'upload.html'; + + var code = 'location.assign("' + loc + '")'; + eval(code); +} + +function frmLoad() { + setTimeout('reboot()', 40000); +} + +function btnBack() { + var code = 'location.assign("' + 'upload.html' + '")'; + eval(code); +} + +// done hiding --> +</script> + </head> + <body onLoad='frmLoad()'> + <blockquote> <b>DSL Router Software Upgrade</b><br> + <br> + <script language="javascript"> +<!-- hide +document.write(msg[getMsgIndex()]); +// done hiding --> +</script> + <br> + <br> + <center> + <input type='button' onClick='btnBack()' value='Back'> + </center> + </blockquote> + </body> +</html> diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/ram_cfe.mk b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/ram_cfe.mk new file mode 100755 index 0000000..a540170 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/ram_cfe.mk @@ -0,0 +1,378 @@ + +# +# CFE's version number +# + +include ${TOP}/main/cfe_version.mk + +# +# Default values for certain parameters +# + +CFG_MLONG64 ?= 0 +CFG_LITTLE ?= 0 +CFG_RELOC ?= 0 +CFG_UNCACHED ?= 0 +CFG_NEWRELOC ?= 0 +CFG_BOOTRAM ?= 0 +CFG_VGACONSOLE ?= 0 +CFG_PCI ?= 1 +CFG_LDT_REV_017 ?= 0 +CFG_ZLIB ?= 0 +CFG_BIENDIAN ?= 0 +CFG_DOWNLOAD ?= 0 +CFG_RAMAPP ?= 0 +CFG_USB ?= 0 + +# +# Paths to other parts of the firmware. Everything's relative to ${TOP} +# so that you can actually do a build anywhere you want. +# + +ARCH_TOP = ${TOP}/arch/${ARCH} +ARCH_SRC = ${ARCH_TOP}/common/src +ARCH_INC = ${ARCH_TOP}/common/include +CPU_SRC = ${ARCH_TOP}/cpu/${CPU}/src +CPU_INC = ${ARCH_TOP}/cpu/${CPU}/include + +# +# It's actually optional to have a 'board' +# directory. If you don't specify BOARD, +# don't include the files. +# + +ifneq ("$(strip ${BOARD})","") +BOARD_SRC = ${ARCH_TOP}/board/${BOARD}/src +BOARD_INC = ${ARCH_TOP}/board/${BOARD}/include +endif + +# +# Preprocessor defines for CFE's version number +# + +VDEF = -DCFE_VER_MAJ=${CFE_VER_MAJ} -DCFE_VER_MIN=${CFE_VER_MIN} -DCFE_VER_ECO=${CFE_VER_ECO} + +# +# Construct the list of paths that will eventually become the include +# paths and VPATH +# + +SRCDIRS = ${ARCH_SRC} ${CPU_SRC} ${LZMZ_SRC} ${BOARD_SRC} ${TOP}/main ${TOP}/vendor ${TOP}/include ${TOP}/net ${TOP}/dev ${TOP}/pci ${TOP}/ui ${TOP}/lib ${TOP}/common ${TOP}/verif ${TOP}/lzma + +CFE_INC = ${TOP}/include ${TOP}/pci ${TOP}/net + +ifeq ($(strip ${CFG_VGACONSOLE}),1) +SRCDIRS += ${TOP}/x86emu ${TOP}/pccons +CFE_INC += ${TOP}/x86emu ${TOP}/pccons +endif + +ifeq ($(strip ${CFG_VAPI}),1) +SRCDIRS += ${TOP}/verif +CFE_INC += ${TOP}/verif +endif + +ifeq ($(strip ${CFG_ZLIB}),1) +SRCDIRS += ${TOP}/zlib +CFE_INC += ${TOP}/zlib +endif + + +INCDIRS = $(patsubst %,-I%,$(subst :, ,$(ARCH_INC) $(CPU_INC) $(BOARD_INC) $(CFE_INC))) + +VPATH = $(SRCDIRS) + +# +# Bi-endian support: If we're building the little-endian +# version, use a different linker script so we can locate the +# ROM at a higher address. You'd think we could do this with +# normal linker command line switches, but there appears to be no +# command-line way to override the 'AT' qualifier in the linker script. +# + +CFG_TEXTAT1MB=0 +ifeq ($(strip ${CFG_BIENDIAN}),1) + ifeq ($(strip ${CFG_LITTLE}),1) + CFG_TEXTAT1MB=1 + endif +endif + + +# +# Configure tools and basic tools flags. This include sets up +# macros for calling the C compiler, basic flags, +# and linker scripts. +# + +include ${ARCH_SRC}/tools.mk + +# +# Add some common flags that are used on any architecture. +# + +CFLAGS += -I. $(INCDIRS) +CFLAGS += -D_CFE_ ${VDEF} -DCFG_BOARDNAME=\"${CFG_BOARDNAME}\" -DCONFIG_MIPS_BRCM + +# +# Add flash driver support. +# +# INC_xxx_FLASH_DRIVER is exported from rom_cfe.mk + +CFLAGS += -DINC_CFI_FLASH_DRIVER=$(INC_CFI_FLASH_DRIVER) +CFLAGS += -DINC_SPI_FLASH_DRIVER=$(INC_SPI_FLASH_DRIVER) +CFLAGS += -DINC_NAND_FLASH_DRIVER=$(INC_NAND_FLASH_DRIVER) +CFLAGS += -DINC_SPI_PROG_NAND=$(INC_SPI_PROG_NAND) + +# +# Set CFG_TCP=0 to not include the TCP protocol. +# + +CFG_TCP=1 +ifeq ($(strip ${CFG_TCP}),1) +CFLAGS += -DCFG_TCP +endif + +# +# Set CFG_WEB_SERVER=0 to not include the web server. +# + +CFG_WEB_SERVER=1 +CFLAGS += -DCFG_WEB_SERVER=${CFG_WEB_SERVER} + +# +# Gross - allow more options to be supplied from command line +# + +ifdef CFG_OPTIONS +OPTFLAGS = $(patsubst %,-D%,$(subst :, ,$(CFG_OPTIONS))) +CFLAGS += ${OPTFLAGS} +endif + + +# +# IKOS Build +# + +ifeq ($(strip $(BRCM_IKOS)),y) +CFLAGS += -DCONFIG_BRCM_IKOS +endif + +# +# This is the makefile's main target. Note that we actually +# do most of the work in 'ALL' not 'all', since we include +# other makefiles after this point. +# + +all : build_date.c ALL + +# +# Macros that expand to the list of arch-independent files +# + +LZMAOBJS = LzmaDecode.o dcapi.o +DEVOBJS = +## dev_newflash.o dev_null.o dev_promice.o dev_ide_common.o dev_ns16550.o dev_ds17887clock.o dev_flash.o +LIBOBJS = lib_malloc.o lib_printf.o lib_queue.o lib_string.o lib_string2.o \ + lib_setjmp.o lib_arena.o +##lib_hssubr.o lib_physio.o lib_misc.o lib_qsort.o + +## Foxconn add start by Cliff Wang, 03/23/2010 ## +#NETOBJS = net_ether.o net_tftp.o net_ip.o net_udp.o net_dns.o net_arp.o \ + net_api.o net_tcp.o net_tcpbuf.o +NETOBJS = net_ether.o net_tftp.o net_ip.o net_udp.o net_dns.o net_arp.o \ + net_api.o net_tcp.o net_tcpbuf.o net_nmrp.o +## Foxconn add end by Cliff Wang, 03/23/2010 + +## dev_tcpconsole.o net_dhcp.o net_icmp.o +CFEOBJS = cfe_attach.o cfe_iocb_dispatch.o cfe_devfuncs.o \ + cfe_console.o cfe_mem.o cfe_timer.o \ + cfe_background.o build_date.o \ + cfe_xreq.o cfe_filesys.o +## cfe_error.o cfe_rawfs.o cfe_fatfs.o cfe_httpfs.o cfe_ldr_srec.o cfe_autoboot.o cfe_boot.o cfe_ldr_elf.o cfe_ldr_raw.o cfe_loader.o +## cfe_main.o nvram_subr.o url.o cfe_savedata.o env_subr.o cfe_zlibfs.o + +#UIOBJS = ui_command.o ui_cmddisp.o +# Foxconn add start by Cliff Wang, 03/23/2010 +UIOBJS = ui_command.o ui_cmddisp.o ui_tftpd.o ui_netcmds.o + +## ui_pcicmds.o \ui_tcpcmds.o ui_memcmds.o ui_loadcmds.o ui_flash.o ui_envcmds.o ui_devcmds.o ui_netcmds.o +## ui_examcmds.o ui_misccmds.o \ +## ui_test_disk.o ui_test_ether.o ui_test_flash.o ui_test_uart.o + +# +# Add more object files if we're supporting PCI +# + +ifeq ($(strip ${CFG_PCI}),1) +PCIOBJS = pciconf.o ldtinit.o pci_subr.o +PCIOBJS += pci_devs.o +DEVOBJS += dev_sp1011.o dev_ht7520.o +DEVOBJS += dev_ide_pci.o dev_ns16550_pci.o +DEVOBJS += dev_tulip.o dev_dp83815.o +CFLAGS += -DCFG_PCI=1 +ifeq ($(strip ${CFG_LDT_REV_017}),1) +CFLAGS += -DCFG_LDT_REV_017=1 +endif +ifeq ($(strip ${CFG_DOWNLOAD}),1) +DEVOBJS += dev_bcm1250.o download.data +CFLAGS += -DCFG_DOWNLOAD=1 +endif +endif + +# +# If doing bi-endian, add the compiler switch to change +# the way the vectors are generated. These switches are +# only added to the big-endian portion of the ROM, +# which is located at the real boot vector. +# + +ifeq ($(strip ${CFG_BIENDIAN}),1) + ifeq ($(strip ${CFG_LITTLE}),0) + CFLAGS += -DCFG_BIENDIAN=1 + endif +endif + +# +# Include the makefiles for the architecture-common, cpu-specific, +# and board-specific directories. Each of these will supply +# some files to "ALLOBJS". The BOARD directory is optional +# as some ports are so simple they don't need boad-specific stuff. +# + +include ${ARCH_SRC}/Makefile +include ${CPU_SRC}/Makefile + +ifneq ("$(strip ${BOARD})","") +include ${BOARD_SRC}/Makefile +endif + +# +# Add the common object files here. +# + +ALLOBJS += $(LIBOBJS) $(DEVOBJS) $(CFEOBJS) $(VENOBJS) $(UIOBJS) $(NETOBJS) $(LZMAOBJS) +#$(PCIOBJS) + +# +# VAPI continues to be a special case. +# + +ifeq ($(strip ${CFG_VAPI}),1) +include ${TOP}/verif/Makefile +endif + +# +# USB support +# + +ifeq ($(strip ${CFG_USB}),1) +SRCDIRS += ${TOP}/usb +CFE_INC += ${TOP}/usb +include ${TOP}/usb/Makefile +endif + +# +# If we're doing the VGA console thing, pull in the x86 emulator +# and the pcconsole subsystem +# + +ifeq ($(strip ${CFG_VGACONSOLE}),1) +include ${TOP}/x86emu/Makefile +include ${TOP}/pccons/Makefile +endif + +# +# If we're including ZLIB, then add its makefile. +# + +ifeq ($(strip ${CFG_ZLIB}),1) +include ${TOP}/zlib/Makefile +CFLAGS += -DCFG_ZLIB=1 -DMY_ZCALLOC -DNO_MEMCPY +endif + +# +# Vendor extensions come next - they live in their own directory. +# + +include ${TOP}/vendor/Makefile + +.PHONY : all +.PHONY : ALL +.PHONY : build_date.c + +# +# Build the local tools that we use to construct other source files +# + +mkpcidb : ${TOP}/hosttools/mkpcidb.c + gcc -o mkpcidb ${TOP}/hosttools/mkpcidb.c + +memconfig : ${TOP}/hosttools/memconfig.c + gcc -o memconfig -D_MCSTANDALONE_ -D_MCSTANDALONE_NOISY_ -I${TOP}/arch/mips/cpu/sb1250/include ${TOP}/hosttools/memconfig.c ${TOP}/arch/${ARCH}/cpu/${CPU}/src/sb1250_draminit.c + +pcidevs_data2.h : mkpcidb ${TOP}/pci/pcidevs_data.h + ./mkpcidb > pcidevs_data2.h + +mkflashimage : ${TOP}/hosttools/mkflashimage.c + gcc -o mkflashimage -I${TOP}/include ${TOP}/hosttools/mkflashimage.c + +pci_subr.o : ${TOP}/pci/pci_subr.c pcidevs_data2.h + +build_date.c : + echo "const char *builddate = \"`date`\";" > build_date.c + echo "const char *builduser = \"`whoami`@`hostname`\";" >> build_date.c + +# +# Make a define for the board name +# + +CFLAGS += -D_$(patsubst "%",%,${CFG_BOARDNAME})_ + +LIBCFE = libcfe.a + +%.o : %.c + $(GCC) $(CFLAGS) -o $@ $< + +%.o : %.S + $(GCC) $(CFLAGS) -o $@ $< + +%.o : %.html + echo unsigned char $*_html[] = { > $*.c + hexdump -v -e '" " 12/1 "0x%2.2x, " "\n"' $< | sed -e "s/ 0x .*$\//" -e "\$$s/, *$$//" >> $*.c + echo ' };' >> $*.c + echo 'int $*_html_size = sizeof($*_html);' >> $*.c + echo >> $*.c + $(GCC) $(CFLAGS) -o $@ $*.c + rm -f $*.c + +%.o : %.css + echo unsigned char $*_css[] = { > $*.c + hexdump -v -e '" " 12/1 "0x%2.2x, " "\n"' $< | sed -e "s/ 0x .*$\//" -e "\$$s/, *$$//" >> $*.c + echo ' };' >> $*.c + echo 'int $*_css_size = sizeof($*_css);' >> $*.c + echo >> $*.c + $(GCC) $(CFLAGS) -o $@ $*.c + rm -f $*.c + +%.o : %.gif + echo unsigned char $*_gif[] = { > $*.c + hexdump -v -e '" " 12/1 "0x%2.2x, " "\n"' $< | sed -e "s/ 0x .*$\//" -e "\$$s/, *$$//" >> $*.c + echo ' };' >> $*.c + echo 'int $*_gif_size = sizeof($*_gif);' >> $*.c + echo >> $*.c + $(GCC) $(CFLAGS) -o $@ $*.c + rm -f $*.c + +# +# This rule constructs "libcfe.a" which contains most of the object +# files. +# + +$(LIBCFE) : $(ALLOBJS) + rm -f $(LIBCFE) + $(AR) cr $(LIBCFE) $(ALLOBJS) + $(RANLIB) $(LIBCFE) + + + + + diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/robosw_reg.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/robosw_reg.c new file mode 100755 index 0000000..15dad53 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/robosw_reg.c @@ -0,0 +1,615 @@ +/* +<:copyright-broadcom + + Copyright (c) 2007 Broadcom Corporation + All Rights Reserved + No portions of this material may be reproduced in any form without the + written permission of: + Broadcom Corporation + 16215 Alton Parkway + Irvine, California 92619 + All information contained in this document is Broadcom Corporation + company private, proprietary, and trade secret. + +:> +*/ + +#include "bcm_map.h" +#include "lib_types.h" +#include "lib_malloc.h" +#include "lib_string.h" +#include "lib_printf.h" +#include "mii.h" +#include "bcmmii.h" +#include "sbmips.h" +#include "cfe_iocb.h" +#include "cfe_timer.h" +#include "robosw_reg.h" +#include "dev_bcm63xx_eth.h" +#include "bcmSpiRes.h" + +static uint32 mii_read(uint32 uPhyAddr, uint32 uRegAddr); +static void mii_write(uint32 uPhyAddr, uint32 uRegAddr, uint32 data); + +static int ext_switch_init(void); +static int ethsw_spi_ss_id(void); +static void ethsw_spi_select(int page); +static void ethsw_spi_rreg(int page, int reg, uint8 *data, int len); +static void ethsw_spi_wreg(int page, int reg, uint8 *data, int len); + +void ethsw_rreg_ext(int access_type, int page, int reg, uint8 *data, int len); +void ethsw_wreg_ext(int access_type, int page, int reg, uint8 *data, int len); + + +static ETHERNET_MAC_INFO EnetInfo[BP_MAX_ENET_MACS]; +static uint16 PortLinkState[BP_MAX_SWITCH_PORTS]; + +#define MDIO_BUS 0 +#define SPI_BUS 1 +#define TX_BDS 3 +#define RX_BDS 16 +#define CACHE_ALIGN 16 +#define BUF_LENGTH 160 +extern void _cfe_flushcache(int, uint8_t *, uint8_t *); +#define INVAL_RANGE(s,l) _cfe_flushcache(CFE_CACHE_INVAL_RANGE,((uint8_t *) (s)),((uint8_t *) (s))+(l)) + +/* read a value from the MII */ +static uint32 mii_read(uint32 uPhyAddr, uint32 uRegAddr) +{ + SWITCH->MdioCtrl = 0x0; + SWITCH->MdioCtrl = MdioCtrl_Read | (IsExtPhyId(uPhyAddr) ? MdioCtrl_Ext : 0) | + ((uPhyAddr << MdioCtrl_ID_Shift) & MdioCtrl_ID_Mask) | + (uRegAddr << MdioCtrl_Addr_Shift); + cfe_usleep(100); + return SWITCH->MdioData; +} + +/* write a value to the MII */ +static void mii_write(uint32 uPhyAddr, uint32 uRegAddr, uint32 data) +{ + SWITCH->MdioCtrl = 0x0; + SWITCH->MdioCtrl = MdioCtrl_Write | (IsExtPhyId(uPhyAddr) ? MdioCtrl_Ext : 0) | + ((uPhyAddr << MdioCtrl_ID_Shift) & MdioCtrl_ID_Mask) | + (uRegAddr << MdioCtrl_Addr_Shift) | data; + cfe_usleep(100); +} + +static int clkHz = 781000; +#if !defined(_BCM96328_) +static int clk781k = 2; +#endif +static int ethsw_spi_ss_id() +{ + int slave_select; + + switch(EnetInfo[1].usConfigType) { + case BP_ENET_CONFIG_SPI_SSB_0: + slave_select = 0; + break; + case BP_ENET_CONFIG_SPI_SSB_1: + slave_select = 1; + break; + case BP_ENET_CONFIG_SPI_SSB_2: + slave_select = 2; + break; + case BP_ENET_CONFIG_SPI_SSB_3: + slave_select = 3; + break; + default: + slave_select = 1; + xprintf("Invalid SPI_SS in usConfigType, Assuming 1\n"); + break; + } + return slave_select; +} + +static void ethsw_spi_select(int page) +{ + unsigned char buf[3]; + int spi_ss, cid = 0; + + spi_ss = ethsw_spi_ss_id(); + /* Select new chip */ + buf[0] = BCM5325_SPI_CMD_NORMAL | BCM5325_SPI_CMD_WRITE | + ((cid & BCM5325_SPI_CHIPID_MASK) << BCM5325_SPI_CHIPID_SHIFT); + + /* Select new page */ + buf[1] = PAGE_SELECT; + buf[2] = (char)page; +#if defined(_BCM96328_) + BcmSpi_Write(buf, sizeof(buf), HS_SPI_BUS_NUM, spi_ss, clkHz); +#else + BcmSpi_Write(buf, sizeof(buf), LEG_SPI_BUS_NUM, spi_ss, clkHz); +#endif + +} + +static void ethsw_spi_rreg(int page, int reg, uint8 *data, int len) +{ + unsigned char buf[64]; + int rc; + int i; + int max_check_spi_sts; + int prependCnt = BCM5325_SPI_PREPENDCNT, spi_ss, cid = 0; + + spi_ss = ethsw_spi_ss_id(); + + ethsw_spi_select(page); + + /* write command byte and register address */ + buf[0] = BCM5325_SPI_CMD_NORMAL | BCM5325_SPI_CMD_READ | + ((cid & BCM5325_SPI_CHIPID_MASK) << BCM5325_SPI_CHIPID_SHIFT); + buf[1] = (unsigned char)reg; +#if defined(_BCM96328_) + rc = BcmSpi_Read(buf, prependCnt, 1, HS_SPI_BUS_NUM, spi_ss, clkHz); +#else + rc = BcmSpi_Read(buf, prependCnt, 1, LEG_SPI_BUS_NUM, spi_ss, clkHz); +#endif + + if (rc == SPI_STATUS_OK) { + max_check_spi_sts = 0; + do { + /* write command byte and read spi_sts address */ + buf[0] = BCM5325_SPI_CMD_NORMAL | BCM5325_SPI_CMD_READ | + ((cid & BCM5325_SPI_CHIPID_MASK) << BCM5325_SPI_CHIPID_SHIFT); + buf[1] = (unsigned char)BCM5325_SPI_STS; +#if defined(_BCM96328_) + rc = BcmSpi_Read(buf, prependCnt, 1, HS_SPI_BUS_NUM, spi_ss, clkHz); +#else + rc = BcmSpi_Read(buf, prependCnt, 1, LEG_SPI_BUS_NUM, spi_ss, clkHz); +#endif + if (rc == SPI_STATUS_OK) { + /* check the bit 0 RACK bit is set */ + if (buf[0] & BCM5325_SPI_CMD_RACK) { + break; + } + cfe_usleep(10000); + } else { + break; + } + } while (max_check_spi_sts++ < 10); + + if (rc == SPI_STATUS_OK) { + for (i = 0; i < len; i++) { + buf[0] = BCM5325_SPI_CMD_NORMAL | BCM5325_SPI_CMD_READ | + ((cid & BCM5325_SPI_CHIPID_MASK) << BCM5325_SPI_CHIPID_SHIFT); + buf[1] = (unsigned char)0xf0; +#if defined(_BCM96328_) + rc = BcmSpi_Read(buf, prependCnt, 1, HS_SPI_BUS_NUM, spi_ss, clkHz); +#else + rc = BcmSpi_Read(buf, prependCnt, 1, LEG_SPI_BUS_NUM, spi_ss, clkHz); +#endif + if (rc == SPI_STATUS_OK) { + *(data + (len - i - 1)) = buf[0]; + } + } + } + } +} + +static void ethsw_spi_wreg(int page, int reg, uint8 *data, int len) +{ + unsigned char buf[64]; + int i; + int spi_ss, cid = 0; + + ethsw_spi_select(page); + + spi_ss = ethsw_spi_ss_id(); + buf[0] = BCM5325_SPI_CMD_NORMAL | BCM5325_SPI_CMD_WRITE | + ((cid & BCM5325_SPI_CHIPID_MASK) << BCM5325_SPI_CHIPID_SHIFT); + + buf[1] = (char)reg; + for (i = 0; i < len; i++) { + /* Write the data out in LE format to the switch */ + buf[BCM5325_SPI_PREPENDCNT+i] = *(data + (len - i - 1)); + } + BcmSpi_Write(buf, len+BCM5325_SPI_PREPENDCNT, LEG_SPI_BUS_NUM, spi_ss, clkHz); +} + +/* External switch register access through MDC/MDIO */ +static void ethsw_mdio_rreg(int page, int reg, uint8 *data, int len) +{ + uint32 cmd, res, ret; + int max_retry = 0; + + cmd = (page << REG_PPM_REG16_SWITCH_PAGE_NUMBER_SHIFT) | REG_PPM_REG16_MDIO_ENABLE; + mii_write(PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG16, cmd); + + cmd = (reg << REG_PPM_REG17_REG_NUMBER_SHIFT) | REG_PPM_REG17_OP_READ; + mii_write(PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG17, cmd); + + do { + res = mii_read(PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG17); + cfe_usleep(10); + } while (((res & (REG_PPM_REG17_OP_WRITE|REG_PPM_REG17_OP_READ)) != REG_PPM_REG17_OP_DONE) && + (max_retry++ < 5)); + + ret = 0; + ret |= mii_read(PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG24) << 0; + ret |= mii_read(PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG25) << 16; + switch (len) { + case 1: + *data = (uint8)ret; + break; + case 2: + *(uint16 *)data = (uint16)ret; + break; + case 4: + *(uint32 *)data = ret; + break; + } +} + +static void ethsw_mdio_wreg(int page, int reg, uint8 *data, int len) +{ + uint32 cmd, res; + uint32 val = 0; + int max_retry = 0; + + switch (len) { + case 1: + val = *data; + break; + case 2: + val = *(uint16 *)data; + break; + case 4: + val = *(uint32 *)data; + break; + } + cmd = (page << REG_PPM_REG16_SWITCH_PAGE_NUMBER_SHIFT) | REG_PPM_REG16_MDIO_ENABLE; + mii_write(PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG16, cmd); + + cmd = val>>0 & 0xffff; + mii_write(PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG24, cmd); + cmd = val>>16 & 0xffff; + mii_write(PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG25, cmd); + cmd = 0; + mii_write(PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG26, cmd); + cmd = 0; + mii_write(PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG27, cmd); + + cmd = (reg << REG_PPM_REG17_REG_NUMBER_SHIFT) | REG_PPM_REG17_OP_WRITE; + mii_write(PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG17, cmd); + + do { + res = mii_read(PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG17); + cfe_usleep(10); + } while (((res & (REG_PPM_REG17_OP_WRITE|REG_PPM_REG17_OP_READ)) != REG_PPM_REG17_OP_DONE) && + (max_retry++ < 5)); +} + +void ethsw_rreg_ext(int access_type, int page, int reg, uint8 *data, int len) +{ + if (access_type == MDIO_BUS) { + ethsw_mdio_rreg(page, reg, data, len); + + } else { + ethsw_spi_rreg(page, reg, data, len); + } +} + +void ethsw_wreg_ext(int access_type, int page, int reg, uint8 *data, int len) +{ + if (access_type == MDIO_BUS) { + ethsw_mdio_wreg(page, reg, data, len); + } else { + ethsw_spi_wreg(page, reg, data, len); + } +} + +int ext_switch_init(void) +{ + uint8 data8; + uint32 data32, access_type; +#if !defined(_BCM96328_) + uint32 clkSave; +#endif + + switch (EnetInfo[1].usConfigType) { + case BP_ENET_CONFIG_SPI_SSB_0: + case BP_ENET_CONFIG_SPI_SSB_1: + case BP_ENET_CONFIG_SPI_SSB_2: + case BP_ENET_CONFIG_SPI_SSB_3: + access_type = SPI_BUS; +#if !defined(_BCM96328_) + clkSave = SPI->spiClkCfg & SPI_CLK_MASK; + xprintf("spiClkCfg = %x; clkSave = %d \n", SPI->spiClkCfg, clkSave); + SPI->spiClkCfg = (SPI->spiClkCfg & ~SPI_CLK_MASK) | clk781k; +#endif + break; + + case BP_ENET_CONFIG_MDIO_PSEUDO_PHY: + access_type = MDIO_BUS; + break; + + default: + xprintf("Unknown PHY configuration type\n"); + return -1; + } + + ethsw_rreg_ext(access_type, PAGE_MANAGEMENT, REG_DEVICE_ID, (uint8 *)&data32, sizeof(data32)); + xprintf("External switch id = %x \n", data32); + + if (data32 == 0x53115) + { + /* setup Switch MII1 port state override */ + data8 = (REG_CONTROL_MPSO_MII_SW_OVERRIDE | + REG_CONTROL_MPSO_SPEED1000 | + REG_CONTROL_MPSO_FDX | + REG_CONTROL_MPSO_LINKPASS); + ethsw_wreg_ext(access_type, PAGE_CONTROL, + REG_CONTROL_MII1_PORT_STATE_OVERRIDE, &data8, sizeof(data8)); + /* management mode, enable forwarding */ + data8 = REG_SWITCH_MODE_FRAME_MANAGE_MODE | REG_SWITCH_MODE_SW_FWDG_EN; + ethsw_wreg_ext(access_type, PAGE_CONTROL, + REG_SWITCH_MODE, &data8, sizeof(data8)); + /* Enable IMP Port */ + data8 = ENABLE_MII_PORT; + ethsw_wreg_ext(access_type, PAGE_MANAGEMENT, + REG_GLOBAL_CONFIG, &data8, sizeof(data8)); + /* Disable BRCM Tag for IMP */ + data8 = ~REG_BRCM_HDR_ENABLE; + ethsw_wreg_ext(access_type, PAGE_MANAGEMENT, + REG_BRCM_HDR_CTRL, &data8, sizeof(data8)); + /* enable rx bcast, ucast and mcast of imp port */ + data8 = (REG_MII_PORT_CONTROL_RX_UCST_EN | + REG_MII_PORT_CONTROL_RX_MCST_EN | + REG_MII_PORT_CONTROL_RX_BCST_EN); + ethsw_wreg_ext(access_type, PAGE_CONTROL, REG_MII_PORT_CONTROL, &data8, sizeof(data8)); + } + +#if !defined(_BCM96328_) + if (access_type == SPI_BUS) + SPI->spiClkCfg = (SPI->spiClkCfg & ~SPI_CLK_MASK) | clkSave; +#endif + return 0; +} + + +void robosw_init(void) +{ + int port; + + BpGetEthernetMacInfo(EnetInfo, BP_MAX_ENET_MACS); + + // Power up and reset EPHYs + GPIO->RoboswEphyCtrl = 0; + cfe_usleep(1000); + + // Take EPHYs out of reset + GPIO->RoboswEphyCtrl = + EPHY_RST_4 | + EPHY_RST_3 | + EPHY_RST_2 | + EPHY_RST_1; + cfe_usleep(1000); + +#if defined(_BCM96328_) || defined(_BCM96362_) + GPIO->RoboswSwitchCtrl |= (RSW_MII_DUMB_FWDG_EN | RSW_HW_FWDG_EN); +#endif +#if defined(_BCM96368_) || defined(_BCM96816_) + GPIO->RoboswEphyCtrl |= (RSW_MII_DUMB_FWDG_EN | RSW_HW_FWDG_EN); +#endif + + // Enable Switch clock + PERF->blkEnables |= ROBOSW_CLK_EN; +#if defined(_BCM96368_) + PERF->blkEnables |= SWPKT_SAR_CLK_EN | SWPKT_USB_CLK_EN; +#endif +#if defined(_BCM96816_) + PERF->blkEnables |= SWPKT_GPON_CLK_EN | SWPKT_USB_CLK_EN; +#endif + + cfe_usleep(1000); + + PERF->softResetB &= ~SOFT_RST_SWITCH; + cfe_usleep(1000); + PERF->softResetB |= SOFT_RST_SWITCH; + cfe_usleep(1000); + + /* Disable Rx and Tx on all Ethernet Ports */ + for (port = 0; port < EPHY_PORTS; port++) { + SWITCH->PortCtrl[port] = 0x03; + } + + if (EnetInfo[1].ucPhyType == BP_ENET_EXTERNAL_SWITCH) { + ext_switch_init(); + } + +} + +void robosw_configure_ports() +{ + uint16 data; + int i; + + for (i = 0; i < 6; i++) { + if ((EnetInfo[0].sw.port_map & (1 << i)) != 0) { + if (EnetInfo[0].sw.phy_id[i] == 0xff) { +#if defined(_BCM96368_) + if (i == 4) + GPIO->GPIOBaseMode |= (EN_GMII1); + if (i == 5) + GPIO->GPIOBaseMode |= (EN_GMII2); +#endif + continue; + } + if (IsWanPort(EnetInfo[0].sw.phy_id[i])) { + *(SWITCH_PBVLAN + i) = PBMAP_MIPS; + SWITCH->DisableLearn |= (1 << i); + } + // Reset + mii_write(EnetInfo[0].sw.phy_id[i], MII_BMCR, BMCR_RESET); + PortLinkState[i] = 0; + if (!IsExtPhyId(EnetInfo[0].sw.phy_id[i])) { + // Configure PHY link/act LED +#if defined(_BCM96368_) + // Enable status change notification */ + mii_write(EnetInfo[0].sw.phy_id[i], MII_INTERRUPT, MII_INTR_ENABLE); + // Configure LEDs + data = mii_read(EnetInfo[0].sw.phy_id[i], MII_RESERVED_1B); + mii_write(EnetInfo[0].sw.phy_id[i], MII_RESERVED_1B, data | MII_RESERVED_1B_ACT_LED); +#elif defined(_BCM96816_) + // Configure LEDs + mii_write(EnetInfo[0].sw.phy_id[i], 0x1c, 0xa410); +#elif defined(_BCM96328_) || defined(_BCM96362_) + // Configure LEDs + // Enable Shadow register 2 + data = mii_read(EnetInfo[0].sw.phy_id[i], MII_BRCM_TEST); + mii_write(EnetInfo[0].sw.phy_id[i], MII_BRCM_TEST, (data | MII_BRCM_TEST_SHADOW2_ENABLE)); + // Set LED0 to speed. Set LED1 to blinky link + mii_write(EnetInfo[0].sw.phy_id[i], 0x15, 0x71); + // Disable Shadow register 2 + mii_write(EnetInfo[0].sw.phy_id[i], MII_BRCM_TEST, (data & ~MII_BRCM_TEST_SHADOW2_ENABLE)); +#endif + } else { +#if defined(_BCM96368_) + if (i == 4) + GPIO->GPIOBaseMode |= (EN_GMII1); + if (i == 5) + GPIO->GPIOBaseMode |= (EN_GMII2); +#endif +#if defined(_BCM96816_) + if (i == 2) + GPIO->GPIOBaseMode |= (EN_GMII1); + if (i == 3) + GPIO->GPIOBaseMode |= (EN_GMII2); +#endif +#if defined(_BCM96362_) + if (i == 4) + GPIO->RoboswSwitchCtrl |= (RSW_MII_SEL_2P5V << RSW_MII_SEL_SHIFT); + if (i == 5) + GPIO->RoboswSwitchCtrl |= (RSW_MII_2_IFC_EN | (RSW_MII_SEL_2P5V << RSW_MII_2_SEL_SHIFT)); +#endif +#if defined(_BCM96328_) + if (i == 4) + MISC->miscPadCtrlHigh |= (MISC_MII_SEL_2P5V << MISC_MII_SEL_SHIFT); +#endif + // Reset + mii_write(EnetInfo[0].sw.phy_id[i], MII_BMCR, BMCR_RESET); + // Enable auto-negotiation + mii_write(EnetInfo[0].sw.phy_id[i], MII_ANAR, ANAR_TXFD | ANAR_TXHD | ANAR_10FD | ANAR_10HD | PSB_802_3); + + // Configure LED for link/activity + data = MII_1C_SHADOW_LED_CONTROL << MII_1C_SHADOW_REG_SEL_S; + mii_write(EnetInfo[0].sw.phy_id[i], MII_REGISTER_1C, data); + data = mii_read(EnetInfo[0].sw.phy_id[i], MII_REGISTER_1C); + data |= ACT_LINK_LED_ENABLE; + data |= MII_1C_WRITE_ENABLE; + mii_write(EnetInfo[0].sw.phy_id[i], MII_REGISTER_1C, data); + + data = mii_read(EnetInfo[0].sw.phy_id[i], MII_PHYIDR2); + if ((data & BCM_PHYID_M) == (BCM54610_PHYID2 & BCM_PHYID_M)) { + // Configure RGMII timing for 54610 GPHY + data = MII_1C_SHADOW_CLK_ALIGN_CTRL << MII_1C_SHADOW_REG_SEL_S; + mii_write(EnetInfo[0].sw.phy_id[i], MII_REGISTER_1C, data); + data = mii_read(EnetInfo[0].sw.phy_id[i], MII_REGISTER_1C); + data &= (~GTXCLK_DELAY_BYPASS_DISABLE); + data |= MII_1C_WRITE_ENABLE; + mii_write(EnetInfo[0].sw.phy_id[i], MII_REGISTER_1C, data); + + // Configure LOM LED Mode + data = MII_1C_EXTERNAL_CONTROL_1 << MII_1C_SHADOW_REG_SEL_S; + mii_write(EnetInfo[0].sw.phy_id[i], MII_REGISTER_1C, data); + data = mii_read(EnetInfo[0].sw.phy_id[i], MII_REGISTER_1C); + data |= LOM_LED_MODE; + data |= MII_1C_WRITE_ENABLE; + mii_write(EnetInfo[0].sw.phy_id[i], MII_REGISTER_1C, data); + } + } + // Restart auto-negotiation + data = mii_read(EnetInfo[0].sw.phy_id[i], MII_BMCR); + mii_write(EnetInfo[0].sw.phy_id[i], MII_BMCR, data | BMCR_RESTARTAN); + } + } + +#if defined(_BCM96816_) + // Disable SERDES, MoCA, USB and GPON port + SWITCH->PortOverride[SERDES_PORT_ID] = PortOverride_Enable; + SWITCH->PortOverride[MOCA_PORT_ID] = PortOverride_Enable; + SWITCH->PortOverride[USB_PORT_ID] = PortOverride_Enable; + SWITCH->PortOverride[GPON_PORT_ID] = PortOverride_Enable; +#endif + +#if defined(_BCM96328_) || defined(_BCM96362_) + // Ports 6 and 7 are not used on 6328 and 6362 + SWITCH->PortOverride[PORT_6_PORT_ID] = PortOverride_Enable; + SWITCH->PortOverride[PORT_7_PORT_ID] = PortOverride_Enable; +#endif + +#if defined(_BCM96368_) + // Disable SAR and USB port + SWITCH->PortOverride[USB_PORT_ID] = PortOverride_Enable; + SWITCH->PortOverride[SAR_PORT_ID] = PortOverride_Enable; +#endif + + // Enable the GMII clocks. + SWITCH->ImpRgmiiCtrlP4 |= ImpRgmiiCtrl_GMII_En; + /* RGMII Delay Programming. Enable ID mode */ + SWITCH->ImpRgmiiCtrlP4 |= ImpRgmiiCtrl_Timing_Sel; + +#if !defined(_BCM96328_) + SWITCH->ImpRgmiiCtrlP5 |= ImpRgmiiCtrl_GMII_En; + SWITCH->ImpRgmiiCtrlP5 |= ImpRgmiiCtrl_Timing_Sel; +#endif + + // Reset MIB counters + SWITCH->GlbMgmt = GlbMgmt_ResetMib; + cfe_usleep(100); + SWITCH->GlbMgmt = 0; + + SWITCH->ImpOverride |= ImpOverride_Force | ImpOverride_Linkup; + +} + +void robosw_check_ports() +{ + uint16 data; + uint8 PortOverride; + int i; + + for (i = 0; i < EPHY_PORTS; i++) { + if ((EnetInfo[0].sw.port_map & (1 << i)) != 0) { + if (EnetInfo[0].sw.phy_id[i] == 0xff) { + PortOverride = PortOverride_Enable | PortOverride_1000Mbs | + PortOverride_Fdx | PortOverride_Linkup; + if ((SWITCH->PortOverride[i] & PortOverride) != PortOverride) { + SWITCH->PortOverride[i] = PortOverride; + SWITCH->PortCtrl[i] = 0; + PortLinkState[i] = 1; + } + continue; + } + PortOverride = PortOverride_Enable; + data = mii_read(EnetInfo[0].sw.phy_id[i], MII_ASR); + if (PortLinkState[i] != MII_ASR_LINK(data)) { + + if (MII_ASR_LINK(data)) + PortOverride |= PortOverride_Linkup; + + if (MII_ASR_DONE(data)) { + if (MII_ASR_FDX(data)) + PortOverride |= PortOverride_Fdx; + if (MII_ASR_1000(data)) + PortOverride |= PortOverride_1000Mbs; + else if (MII_ASR_100(data)) + PortOverride |= PortOverride_100Mbs; + else + PortOverride |= PortOverride_10Mbs; + } + + SWITCH->PortOverride[i] = PortOverride; + + if(PortOverride & PortOverride_Linkup) { + /* Enable Rx and Tx */ + SWITCH->PortCtrl[i] = 0; + } + + PortLinkState[i] = MII_ASR_LINK(data); + } + } + } +} + diff --git a/cfe/cfe/arch/mips/board/bcm63xx_rom/src/Makefile b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/Makefile new file mode 100755 index 0000000..808ddc2 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/Makefile @@ -0,0 +1,23 @@ +ifeq ($(strip ${CFG_BOARDNAME}),"BCM96328") +BSPOBJS += \ + bcm63xx_impl1_rom_boot.o +endif +ifeq ($(strip ${CFG_BOARDNAME}),"BCM96362") +BSPOBJS += \ + bcm63xx_impl1_rom_boot.o +endif +ifeq ($(strip ${CFG_BOARDNAME}),"BCM96368") +BSPOBJS += \ + bcm6368_rom_boot.o \ + bcm6368_sdramDqs.o +endif +ifeq ($(strip ${CFG_BOARDNAME}),"BCM96816") +BSPOBJS += \ + bcm63xx_impl1_rom_boot.o +endif +ifeq ($(strip ${INC_NAND_FLASH_DRIVER}),1) +BSPOBJS += \ + nandflash.o +endif +BSPOBJS += \ + bcm63xx_main.o diff --git a/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm6368_rom_boot.S b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm6368_rom_boot.S new file mode 100755 index 0000000..f1cba19 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm6368_rom_boot.S @@ -0,0 +1,548 @@ +#include "sbmips.h" +#include "bsp_config.h" + +#include "6368_cpu.h" +#include "6368_common.h" +#include "bcm_hwdefs.h" +#include "boardparms.h" +#include "mipsmacros.h" + +#define SETLEDS1(a,b,c,d) \ + li a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ; \ + bal board_setleds + +/* ********************************************************************* + * BOARD_EARLYINIT() + * + * Initialize board registers. This is the earliest + * time the BSP gets control. This routine cannot assume that + * memory is operational, and therefore all code in this routine + * must run from registers only. The $ra register must not + * be modified, as it contains the return address. + * + * This routine will be called from uncached space, before + * the caches are initialized. If you want to make + * subroutine calls from here, you must use the CALLKSEG1 macro. + * + * Among other things, this is where the GPIO registers get + * programmed to make on-board LEDs function, or other startup + * that has to be done before anything will work. + * + * Input parameters: + * a0 - Flash base address (address of MIPS reset) + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(board_earlyinit) + + .set noreorder + + mfc0 t1, C0_BCM_CONFIG, 3 + li t2, CP0_CMT_TPID + and t1, t2 + bnez t1, 2f # if we are running on thread 1, skip init + nop + +#if 0 + /* wait for a while to allow catch by jtag debugger */ + li t8, -(200000000*3) /* we will count up to 0 to delay a couple of seconds */ + /* and give the emulator a chance to catch us */ + mtc0 t8, C0_COUNT +catchloop: + bltz t8, catchloop + mfc0 t8, C0_COUNT +#endif + + /**--------------------------------------------------------------**/ + /** platform specific code **/ + /**--------------------------------------------------------------**/ + /**----- Enable I Cache -----------------------------------------**/ + mfc0 t1, C0_BCM_CONFIG + or t1, (CP0_BCM_CFG_ICSHEN | CP0_BCM_CFG_DCSHEN) + mtc0 t1, C0_BCM_CONFIG # Enable I Cache + + // In the begining MIPS core registers are mapped to 0xbfax_xxxx + li t1, 0x1FA0000C # Set up CBR to 1FAx_xxxx + mtc0 t1, C0_BCM_CONFIG, 6 + + li t1, MIPS_BASE_BOOT + lw t2, MIPS_LMB_CR(t1) + or t2, 0xC0000000 # enable ffxx_xxxx space + sw t2, MIPS_LMB_CR(t1) + li t2, 0xFFF80001 # SBR FFF8_xxxx and enable + sw t2, MIPS_SBR(t1) + + // Now map MIPS core registers to 0xFF4x_xxxx space + li t1, 0xFF40000C # CBR FF4x_xxxx (and reserved bits 0xc). + mtc0 t1, C0_BCM_CONFIG, 6 + + /**----- Initialize EBI -----------------------------------------**/ + li t1, MPI_BASE + li t2, EBI_SIZE_32M + or t2, a0 + sw t2, CS0BASE(t1) # CS[0] Base + li t2, THREEWT|EBI_WORD_WIDE|EBI_ENABLE + sw t2, CS0CNTL(t1) # CS[0] Control + + /**----- Initialize Serial --------------------------------------**/ + li t3, ((FPERIPH / 115200) / 16) + /* + # Baudword = (FPeriph)/Baud/32-1. We have to perform rounding + # and subtraction. Above we divided by 16 (instead of 32). If + # bit0 is set, we round up. However, we then subtract 1, so final + # result should be t3/2. If bit0 is 0, then we truncate and subtract + # 1, t3=t3/2-1. + */ + andi t0, t3, 0x1 + bne t0,zero,1f # do shift only (in delay slot) + # and jump to apply + srl t3,1 # do divide by 2 + addiu t3, -1 # subtract 1 +1: + + # t3 contains the UART BAUDWORD + li t0, UART_BASE + sw t3, UART0BAUD(t0) # Store BaudRate + li t1, BITS8SYM|ONESTOP + sb t1, UART0CONFIG(t0) # 8 Bits/1 Stop + li t1, TXEN|RXEN|BRGEN + sb t1, UART0CONTROL(t0) # Enable, No Parity + move t1, zero + sh t1, UART0INTMASK(t0) + + .set reorder +2: + j ra +END(board_earlyinit) + +/* ********************************************************************* + * BOARD_DRAMINFO + * + * Return the address of the DRAM information table + * + * Input parameters: + * nothing + * + * Return value: + * v0 - DRAM info table, return 0 to use default table + ********************************************************************* */ +LEAF(board_draminfo) + j ra +END(board_draminfo) + +/* ********************************************************************* + * BOARD_DRAMINIT + * + * This routine should activate memory. + * + * Input parameters: + * None + * + * Return value: + * None + * + * Registers used: + * can use all registers. + ********************************************************************* */ +LEAF(board_draminit) + .set noreorder + + li t0, MEMC_BASE + li t1, DDR_BASE + + li t4, (7 << 28) | (7 << 24) | (1 << 20) | (7 << 16) # UBUS_CNTR_CYCLES = 7, LLMB_CNTR_CYCLES = 7, PH_CNTR_EN = 1, PH_CNTR_CYCLES = 7 + sw t4, DDR_MIPS_PHASE_CNTL(t1) + + # Calculate a value for a 90 degree phase shift. + + lw t2, DDR_MIPSDDR_PLL_MDIV(t1) + srl t2, 8 # Shift and mask off DDR_MDIV + and t2, 0xff + sll t2, 2 # PI_steps = (90deg * 16 * MBUS(t2) + 2)/360 ~= MBUS * 4 + or t2, (1 << 14) # set the count direction + + lw t3, DDR_DDR3_4_PHASE_CNTL(t1) # Get current DDR3/4 value. + ori t3, 0x7fff # Clear low 15 bits (DDR3 value). + xori t3, 0x7fff + or t3, t2 # Set new DDR3 value, preserving existing DDR4 value. + sw t3, DDR_DDR3_4_PHASE_CNTL(t1) + + li t4, (1 << 28) | (7 << 24) | (1 << 23) | (1 << 20) | (7 << 16) # UBUS_CNTR_CYCLES = 1, LLMB_CNTR_CYCLES = 7, UBUS_CNTR_EN = 1, PH_CNTR_EN = 1, PH_CNTR_CYCLES = 7 + sw t4, DDR_MIPS_PHASE_CNTL(t1) + + li t4, 0x103e + sw t4, DDR_UBUS_PI_DSK1(t1) + li t4, 0x40000000 + sw t4, DDR_UBUS_PI_DSK0(t1) + + ## Set PI mask, and frequnecy of updates + # bit[5:0] 1 to 31, controls how often feedback is send back to PI + # bit[7] update register in sampling logic to take the new value in bit[5:0] + # bit[14:8] masking bits for the sampling result + + li t2, 0x00000010 # 0x8 for 8 DDR cycles, 0x10 for 16 DDR cycles, 0x4 for 4 DDR cycles, can take values from 1 to 31 + sw t2, DDR_UBUS_PI_DSK0(t1) # set PI update to 16 ddr cycles + li t2, 0x00000090 # update value + sw t2, DDR_UBUS_PI_DSK0(t1) + li t2, 0x00000c90 # set mask to 0001100; 0x1890 will set mask to 0011000 + sw t2, DDR_UBUS_PI_DSK0(t1) + + ###### Check to see if we found the edge... + ###### Ideally we want to loop here until we find an edge.... + + li t3, 0 + li t2, 10000 + +1: + # Looking for a rising edge. + lw t4, DDR_UBUS_PI_DSK0(t1) # Read a sample value. + srl t4, 16 # The sample is in the upper 16 bits. + andi t4, 0x41 # Look at the 2 outermost bits; if the LSB is 0 and the MSB is 1, + beq t4, 0x40, 2f # then there is an edge somewhere in the sample. + + addi t3, 1 + bne t2, t3, 1b + nop + +2: + + /**----- Configure DDR controller ------------------------------------**/ + li v0, 16 + li t2, ((MEMC_12BIT_ROW << MEMC_ROW_SHFT) | (MEMC_9BIT_COL << MEMC_COL_SHFT)) + or t2, (MEMC_16BIT_BUS << MEMC_WIDTH_SHFT) + or t2, (MEMC_SEL_PRIORITY) + or t2, (2 << MEMC_EARLY_HDR_CNT_SHFT) + or t2, (MEMC_USE_HDR_CNT) +// or t2, (MEMC_EN_FAST_REPLY) + or t2, (MEMC_RR_ARB) + or t2, (MEMC_DQS_GATE_EN | MEMC_MEMTYPE_DDR) + sw t2, MEMC_CONFIG(t0) # Enable DDR Mem & SEQ EN, 16MB + + li t2, 0x7 # Reduce drive strength for command pins (per John Lorek) + sw t2, DDR_CMD_PAD_CNTL(t1) + + li t2, 0x00A778DD + sw t2, MEMC_DRAM_TIM(t0) # DDR Timing Set Latency 2.5 Latency,tRAS period =7,tRFC period=12, tWR=3 + li t2, 0x00000003 + sw t2, MEMC_CONTROL(t0) # Turn on CKE + li t2, 0x0000000B + sw t2, MEMC_CONTROL(t0) # PreCharge + li t2, 0x00004002 + sw t2, MEMC_M_EM_BUF(t0) # Value for Extended Mode Register, DDR Reduced Drive Strength On + li t2, 0x00000013 + sw t2, MEMC_CONTROL(t0) # MRS command + li t2, 0x00000163 + sw t2, MEMC_M_EM_BUF(t0) # Reset DLL, Burst Length = 8, Burst Type Sequential 2.5 Latency + li t2, 0x00000013 + sw t2, MEMC_CONTROL(t0) # MRS command + nop # Delay 200 DDR clock cycles (~1.5 uS) + nop + nop + li t2, 0x0000000B + sw t2, MEMC_CONTROL(t0) # Precharge + li t2, 0x0000840f + sw t2, MEMC_REF_PD_CONTROL(t0) # Enable auto refresh + li t2, 0x00000007 + sw t2, MEMC_CONTROL(t0) # Set Auto Refresh Mode + li t2, 0x00000007 + sw t2, MEMC_CONTROL(t0) # Set Auto Refresh Mode + li t2, 0x00000063 + sw t2, MEMC_M_EM_BUF(t0) # Reset DLL, Burst Length = 8, Burst Type Sequential 2.5 Latency + li t2, 0x00000013 + sw t2, MEMC_CONTROL(t0) # MRS + + .set reorder + + li sp, 0x80001000 + sub sp, 8 + sw ra, 0(sp) + sw v0, 4(sp) + bal sdramDqsPhaseSet + lw v0, 4(sp) + lw ra, 0(sp) + add sp, 8 + + /**----- switch to sync -----------------------------------------**/ + li t0, 0xff410000 + li t1, DDR_BASE + li t2, 4048 + li t3, 1 + +1: + lw t4, 0x40(t0) # Read a sample value. + srl t4, 16 # The sample is in the upper 16 bits. + + andi t4, t4, 0x41 # Look at the 2 outermost bits; if the LSB is 0 and the MSB is 1, + beq t4, 0x40, 2f # then there is an edge somewhere in the sample. + + lw t5, DDR_MIPS_PHASE_CNTL(t1) + and t5, 0xffff0000 + or t5, t3 + or t5, (1<<14) + sw t5, DDR_MIPS_PHASE_CNTL(t1) + + lw t5, 0x40(t0) # Delay before reading another sample. + add t3, 1 + bne t2, t3, 1b + b 3f + +2: + # Success + lw t2, DDR_MIPS_PHASE_CNTL(t1) # Turn on auto-PI mode. + and t2, 0xf0ffffff + or t2, (1 << 24) | (1 << 21) # LLMB_CNTR_CYCLES_CNTL = 1, LLMB_CNTR_EN = 1 + sw t2, DDR_MIPS_PHASE_CNTL(t1) + + li t2, 0x0010 # Set PI mask to 0000110, and check new value every 16 MIPS cycles. + sw t2, 0x40(t0) # set PI update to 16 ddr cycles + li t2, 0x80000090 # Enable MIPS auto-PI | Enable update period | Set 16 clock update + sw t2, 0x40(t0) + li t2, 0x80000c90 # Enable MIPS auto-PI | Enable comparator | Enable update period | Set 16 clock update + sw t2, 0x40(t0) + + lw t2, 0x40(t0) # Do a few reads to wait till the edge is stable... + lw t2, 0x40(t0) + lw t2, 0x40(t0) + lw t2, 0x40(t0) + lw t2, 0x40(t0) + + mfc0 t1, C0_BCM_CONFIG, 5 + and t1, ~(0x1 << 28) + mtc0 t1, C0_BCM_CONFIG, 5 + + /**----- Enable RAC and LMB -------------------------------------**/ + li t1, MIPS_BASE + lw t2, MIPS_LMB_CR(t1) + or t2, LMB_EN # Enable LMB + sw t2, MIPS_LMB_CR(t1) + + li t2, 0xFFF << RAC_UPB_SHFT # Enable prefetch for RAM address range up to 256MB + sw t2, MIPS_RAC_ARR(t1) + + lw t2, MIPS_RAC_CR0(t1) + or t2, (RAC_C_INV | RAC_I | RAC_PF_I) + sw t2, MIPS_RAC_CR0(t1) + + lw t2, MIPS_RAC_CR1(t1) + or t2, (RAC_C_INV | RAC_I | RAC_PF_I) + sw t2, MIPS_RAC_CR1(t1) + +3: + /**----- Enable branch prediction and non-blocking data cache ---**/ + mfc0 t1, C0_BCM_CONFIG + and t1, ~CP0_BCM_CFG_BTHD + or t1, CP0_BCM_CFG_NBK + or t1, CP0_BCM_CFG_CLF + mtc0 t1, C0_BCM_CONFIG + + /* Test whether memory is 16 or 32 bit wide */ + li t0, MEMC_BASE + lw t2, MEMC_CONFIG(t0) + and t2, ~MEMC_WIDTH_MASK + or t2, (MEMC_32BIT_BUS << MEMC_WIDTH_SHFT) + sw t2, MEMC_CONFIG(t0) + + li t3, DRAM_BASE_NOCACHE + li t4, 0x12345678 + sw t4, 0(t3) + li t4, 0x87654321 + sw t4, 4(t3) + nop + nop + nop + nop + nop + nop + li t4, 0x12345678 + lw t5, 0(t3) + beq t4, t5, 4f + + /* 16 bit wide memory */ + lw t2, MEMC_CONFIG(t0) + and t2, ~MEMC_WIDTH_MASK + or t2, (MEMC_16BIT_BUS << MEMC_WIDTH_SHFT) + sw t2, MEMC_CONFIG(t0) +4: + j ra + +END(board_draminit) + +/* ********************************************************************* + * BOARD_SETLEDS(x) + * + * Set LEDs for boot-time progress indication. Not used if + * the board does not have progress LEDs. This routine + * must not call any other routines, since it may be invoked + * either from KSEG0 or KSEG1 and it may be invoked + * whether or not the icache is operational. + * + * Input parameters: + * a0 - LED value (8 bits per character, 4 characters) + * + * Return value: + * nothing + * + * Registers used: + * t0,t1,t2,t3 + ********************************************************************* */ +LEAF(board_setleds) +#if 0 + li t0, UART_BASE + li t2, TXFIFOEMT + +1: lh t1, UART0INTSTAT(t0) + and t1, t2 + bne t1, t2, 1b + + srl t3, a0, 24 + sb t3, UART0DATA(t0) + srl t3, a0, 16 + sb t3, UART0DATA(t0) + srl t3, a0, 8 + sb t3, UART0DATA(t0) + sb a0, UART0DATA(t0) + li a0, '\r' + sb a0, UART0DATA(t0) + li a0, '\n' + sb a0, UART0DATA(t0) +#endif + j ra +END(board_setleds) + +/* ********************************************************************* + * BCMCORE_TP1_SWITCH() + * + * Check if the thread switch is required. If we are already + * running on thread 1 this function will do nothing and just return + * If we are running on thread 0 this function will take thread 1 + * out of reset and put thread 0 to sleep waiting for singnal from + * thread 1. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ +LEAF(bcmcore_tp1_switch) + + mfc0 t1, C0_BCM_CONFIG, 3 + li t2, CP0_CMT_TPID + and t1, t2 + bnez t1, tp1 # Already running on thread 1 + +# Start TP1 +# Set boot address for TP1 + li t1, MIPS_BASE + li t2, 0x98000000 | ENABLE_ALT_BV + sw t2, MIPS_TP1_ALT_BV(t1) + +# Set a flag so we can wait for TP1 to catch up + li t1, 0x0 + mtc0 t1, $31 # CO_DESAVE + +# Take TP1 out of reset + mfc0 t1, C0_BCM_CONFIG, 2 + or t1, CP0_CMT_RSTSE + mtc0 t1, C0_BCM_CONFIG, 2 + + /* wait until second thread catches up with the first */ +waittp1: + mfc0 t0, $31 # CO_DESAVE + beqz t0, waittp1 + + li t0, THREAD_NUM_ADDRESS + FIXUP(t0) + lw t0, 0(t0) + li t1, 1 + bne t0, t1, return # Linux will run on TP0, continue running bootloader + +# Voice will run on TP0. Set it up and put it to sleep + + # enable interrupts and enable SW IRQ 0 + li t0, M_SR_IE | M_SR_IBIT1 + mtc0 t0, C0_SR + + # Set up to use alternate exception vector 0x80000200 + li t0, M_CAUSE_IV + mtc0 t0, C0_CAUSE + + mfc0 t1, C0_BCM_CONFIG, 1 + # set all ints except IRQ1 to TP1 and cross over SW IRQ 0 + or t1, (CP0_CMT_XIR_4 | CP0_CMT_XIR_3 | CP0_CMT_XIR_2 | CP0_CMT_XIR_0 | CP0_CMT_SIR_0 | CP0_CMT_NMIR_TP1) + mtc0 t1, C0_BCM_CONFIG, 1 + + mfc0 t1, C0_BCM_CONFIG, 2 + # Set debug on TP1, give priority to TP0, and + # set TLB exception serialization to ignore SCNT value in CP0 reg22 sel 4 + and t1, ~CP0_CMT_TPS_MASK; + or t1, (CP0_CMT_DSU_TP1 | CP0_CMT_PRIO_TP0 | (1 << CP0_CMT_TPS_SHFT)) + mtc0 t1, C0_BCM_CONFIG, 2 + + # Enable Data RAC on TP0 + li t1, MIPS_BASE + lw t2, MIPS_RAC_CR0(t1) + or t2, (RAC_D | RAC_PF_D) + sw t2, MIPS_RAC_CR0(t1) + +2: + li t8, 0 + b wait_for_wake + +tp1: +# Running on TP1.... +# First signal to TP0 that TP1 is up + li t1, 0x1 + mtc0 t1, $31 # CO_DESAVE + + li t0, THREAD_NUM_ADDRESS + FIXUP(t0) + lw t0, 0(t0) + li t1, 1 + beq t0, t1, return # Linux will run on TP1, continue running bootloader + +# Voice will run on TP1. Set it up and put it to sleep + + # enable interrupts and enable SW IRQ 0 + li t0, M_SR_IE | M_SR_IBIT1 + mtc0 t0, C0_SR + + # Set up to use alternate exception vector 0x80000200 + li t0, M_CAUSE_IV + mtc0 t0, C0_CAUSE + + mfc0 t1, C0_BCM_CONFIG, 1 + # set IRQ1 to TP1 and cross over SW IRQ 0 + or t1, (CP0_CMT_XIR_1 | CP0_CMT_SIR_0 | CP0_CMT_NMIR_TP0) + mtc0 t1, C0_BCM_CONFIG, 1 + + mfc0 t1, C0_BCM_CONFIG, 2 + # Set debug on TP0, give priority to TP1, and + # set TLB exception serialization to ignore SCNT value in CP0 reg22 sel 4 + and t1, ~CP0_CMT_TPS_MASK; + or t1, (CP0_CMT_PRIO_TP1 | (1 << CP0_CMT_TPS_SHFT)) + mtc0 t1, C0_BCM_CONFIG, 2 + + # Enable Data RAC on TP1 + li t1, MIPS_BASE + lw t2, MIPS_RAC_CR1(t1) + or t2, (RAC_D | RAC_PF_D) + sw t2, MIPS_RAC_CR1(t1) + b 2b + +return: + j ra + +END(bcmcore_tp1_switch) + +# align this code to cache line. NAND flash is not memory mapped after system boots +# so when we are signaling to the second TP to wake we need +# jal instruction to be in cache + .align 4 +LEAF(wait_for_wake) + sync + wait # wait for interrupt + jal t8 # jump to entry point +END(wait_for_wake) diff --git a/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm6368_sdramDqs.c b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm6368_sdramDqs.c new file mode 100755 index 0000000..96d5000 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm6368_sdramDqs.c @@ -0,0 +1,439 @@ +/*************************************************************************** +* +* Copyright (c) 2004 Broadcom Corporation, All Rights Reserved. +* Contains proprietary and confidential information. +* +* No portions of this material may be reproduced in any form without the +* written permission of: +* +* Broadcom Corporation +* 16215 Alton Parkway +* P.O. Box 57013 +* Irvine, California 92619-7013 +* +* All information contained in this document is Broadcom Corporation +* company private, proprietary, and trade secret. +* +****************************************************************************/ +#include "lib_types.h" +#include "bcm_map.h" + +// Uncomment out the below line to use MemoryTestSuite() +// #define EXTENDED_MEMORY_TESTS + +/* ---- Private Constants and Types -------------------------------------- */ +#define VCDL_PHASE_DEFAULT 16 +#define VCDL_PHASE_MAX 47 /* 154.69 degree */ +#define VCDL_PHASE_MIN 0 /* 22.5 degree */ + +typedef unsigned long u; + +#define N 32*1024 // Size of the copy operation + // Must be at least equal to the L2 cache size +#define S (1*sizeof(u)) + +/* ---- Private Function Prototypes -------------------------------------- */ +inline static int MemoryTest(void) __attribute__((always_inline)); +inline static void PI_upper_set(volatile uint32 *, int bitOffset, int shift) __attribute__((always_inline)); +inline static void PI_shmoo(volatile uint32 *PI_reg, int bitOffset, int minValue, int maxValue, int increment) __attribute__((always_inline)); +inline static void shmooVcdl(int minValue, int maxValue, int increment) __attribute__((always_inline)); + +// #define DEBUG_SHMOO 1 +#if DEBUG_SHMOO +inline static void dumpChar(uint8 c) __attribute__((always_inline)); +inline static void dumpChar(uint8 c) +{ + //wait till tx fifo below threshold + while (UART->txf_levl > 14); + UART->Data = c; +} + +#else +#define dumpChar(c) +#endif + +#if defined(EXTENDED_MEMORY_TESTS) +#include "memtest.c"/* Suite memory tests SCAN, MARCH, SLIDING, SHIFT ADDRESS */ +inline static int MemoryTestSuite(void) __attribute__((always_inline)); +#endif + +/* ==== Public Functions ================================================= */ +void sdramDqsPhaseSet(void); +void vcdlCalibration(void); + +/*******************************************************************************/ +void sdramDqsPhaseSet(void) +{ + int dqOutPhaseMax; + int delay; + int ubusPhase, mipsPhase; + int equalCount = 0; + + // Reset VCDL + DDR->Spare1 |= 0x1; + delay = 1000; + while(delay--); + DDR->Spare1 &= ~0x1; + + // Calculate max phase offset from PLL config register. + dqOutPhaseMax = ((DDR->MIPSDDRPLLMDiv & DDR_MDIV_MASK) >> DDR_MDIV_SHFT) * 8; + + dumpChar('\n'); + dumpChar('\r'); + + // Start by setting VCDL to the default. This almost always works. + // Enable squelch + DDR->WSliceCntl |= (0x1<<20) | (0x1<<4); + DDR->VCDLPhaseCntl0 = (VCDL_PHASE_DEFAULT << 22) | (VCDL_PHASE_DEFAULT << 16) | (VCDL_PHASE_DEFAULT << 6) | VCDL_PHASE_DEFAULT; + DDR->VCDLPhaseCntl1 = (VCDL_PHASE_DEFAULT << 22) | (VCDL_PHASE_DEFAULT << 16) | (VCDL_PHASE_DEFAULT << 6) | VCDL_PHASE_DEFAULT; + DDR->WSliceCntl &= ~((0x1<<20) | (0x1<<4)); + + // Now shmoo over DQ phase to find an optimum value. + dumpChar('D');dumpChar('D');dumpChar('R');dumpChar('2'); + dumpChar('\n'); + dumpChar('\r'); + PI_shmoo(&DDR->DDR1_2PhaseCntl0, 16, -dqOutPhaseMax, dqOutPhaseMax, 1); + + dumpChar('V');dumpChar('C');dumpChar('D');dumpChar('L'); + dumpChar('\n'); + dumpChar('\r'); + shmooVcdl(VCDL_PHASE_MIN, VCDL_PHASE_MAX, 1); + + // Now setup the UBUS clock + dumpChar('U');dumpChar('B');dumpChar('U');dumpChar('S'); + dumpChar('\n'); + dumpChar('\r'); + + MEMC->RefreshPdControl &= ~MEMC_REFRESH_ENABLE; // Turn off refresh while messing with UBus clock + + DDR->MIPSPhaseCntl &= ~(0x1<<23); // turn off ubus PI auto mode + + mipsPhase = DDR->MIPSPhaseCntl; + do { + if (DDR->MIPSPhaseCntl == mipsPhase) + equalCount++; + else { + equalCount = 0; + mipsPhase = DDR->MIPSPhaseCntl; + } + } while (equalCount < 3); + + ubusPhase = ((DDR->UBUSPhaseCntl) & 0x3ffe); // make it even and decrease count + DDR->UBUSPhaseCntl = ubusPhase; + + // Wait until we match several times in a row, to be sure we wait long enough + do { + if (DDR->UBUSPhaseCntl == ubusPhase) + equalCount++; + else + equalCount = 0; + } while (equalCount < 3); + + MEMC->RefreshPdControl |= MEMC_REFRESH_ENABLE; +} + + +/* ==== Private Functions ================================================ */ + +inline static void PI_upper_set(volatile uint32 *PI_reg, int bitOffset, int shift) +{ + uint32 oldVal; + uint32 newVal; + int32 oldPhase; + int32 newPhase; + int equalCount = 0; + + oldVal = *PI_reg; // get the phase config (may have other controls in other 16 bits) + + oldPhase = ( oldVal >> bitOffset ) & 0x3fff; + if ( oldPhase & (0x1<<13) ) { + oldPhase |= ~0x3fff; // sign extend + } + + newPhase = shift & 0x3fff; // set up phase shift value[13:0] + if (shift > oldPhase) { // set up up/down [14], shift is signed value + newPhase |= 0x1<<14; + } + + newPhase = newPhase << bitOffset; + oldVal = oldVal & (0xffff << (16-bitOffset)); // Keep the other control bits + newVal = newPhase | oldVal; + *PI_reg = newVal; + + // Wait until we match several times in a row, to be sure we wait long enough + do { + if (*PI_reg == newVal) + equalCount++; + else + equalCount = 0; + } while (equalCount < 3); +} + + +inline static void PI_shmoo(volatile uint32 *PI_reg, int bitOffset, int minValue, int maxValue, int increment) +{ + int piPhase, piPhaseCnt, passStatus; + int pass1Start, pass1Fail, pass2Start, pass2Fail; + int pass1Cnt, pass2Cnt; + + PI_upper_set(PI_reg, bitOffset, minValue); + + passStatus = 0; + pass1Start = maxValue; + pass1Fail = minValue; + pass2Start = minValue; + pass2Fail = minValue; + + for (piPhase = minValue; piPhase <= maxValue; piPhase += increment) { + + // if (MemoryTestSuite()) + if (MemoryTest()) + { + if (passStatus == 0x0) { // first_pass start + passStatus = 0x1; + pass1Start = piPhase; + } + else if (passStatus == 0x2) { // second_pass start + passStatus = 0x3; + pass2Start = piPhase; + } + dumpChar('p'); + } + else { + if (passStatus == 0x1) { // fisrt_pass end + passStatus = 0x2; + pass1Fail = piPhase; + } + else if (passStatus == 0x3) { // second_pass end + passStatus = 0x4; + pass2Fail = piPhase; + } + dumpChar('.'); + } + + piPhaseCnt = ( piPhase + 0x01) & 0x3fff; + if (increment) { + piPhaseCnt |= (0x01<<14); + } + + *PI_reg = (*PI_reg & (0xffff << (16-bitOffset))) | (piPhaseCnt<<bitOffset); + + } + + // Figure out the middle point of the pass window + // valid window 1 -- .......PPPPPPPPPPPPPP....... + // valid window 2 -- PPPPPPP........PPPPPPPPPPPPP + + if ((pass1Start != maxValue) && (pass2Start == minValue)) { // valid window 1 + if (pass1Fail == minValue) { + piPhaseCnt = (pass1Start + maxValue) >> 1; // mid-point of the pass window + } else { + piPhaseCnt = (pass1Start + pass1Fail - 0x1) >> 1; // mid-point of the pass window + } + } + else if ((pass1Start == minValue) && (pass2Start != minValue) && (pass2Fail == minValue)) { // valid window 2 + pass1Cnt = pass1Fail - minValue; + pass2Cnt = maxValue - pass2Start + 1; + passStatus= (pass1Cnt + pass2Cnt) >> 1; + if (passStatus < pass1Cnt) { // mid-point of the overall pass window is in sub-window 1 + piPhaseCnt = minValue + ( pass1Cnt - passStatus ); + } + else { + piPhaseCnt = pass2Start - 0x1 + passStatus; + } + } + else { + piPhaseCnt = 0x0; // shmoo failed. + } + + piPhaseCnt &= ~0x01; // make it even number + + PI_upper_set(PI_reg, bitOffset, piPhaseCnt); // set the final phase value + + dumpChar('\n'); + dumpChar('\r'); +} + + +inline static void shmooVcdl(int minValue, int maxValue, int increment) +{ + UINT32 dqsInPhase; + UINT32 dqsInSum = 0; + UINT32 passCnt = 0; + volatile int delay; + + for (dqsInPhase = minValue; dqsInPhase <= maxValue; dqsInPhase += increment) { + delay = 1000; + while(delay--); + // Enable squelch + DDR->WSliceCntl |= (0x1<<20) | (0x1<<4); + DDR->VCDLPhaseCntl0 = (dqsInPhase << 22) | (dqsInPhase << 16) | (dqsInPhase << 6) | dqsInPhase; + DDR->VCDLPhaseCntl1 = (dqsInPhase << 22) | (dqsInPhase << 16) | (dqsInPhase << 6) | dqsInPhase; + DDR->WSliceCntl &= ~((0x1<<20) | (0x1<<4)); + + delay = 1000; + while(delay--); + +#if defined(EXTENDED_MEMORY_TESTS) + if (MemoryTestSuite() == MEMTEST_SUCCESS ) +#else + if (MemoryTest()) +#endif + { + dqsInSum += dqsInPhase; + passCnt++; + dumpChar('p'); + } + else { + dumpChar('.'); + } + } + delay = 1000; + while(delay--); + // Enable squelch + DDR->WSliceCntl |= (0x1<<20) | (0x1<<4); + if (passCnt > 0) { + dqsInPhase = dqsInSum / passCnt; + DDR->VCDLPhaseCntl0 = (dqsInPhase << 22) | (dqsInPhase << 16) | (dqsInPhase << 6) | dqsInPhase; + DDR->VCDLPhaseCntl1 = (dqsInPhase << 22) | (dqsInPhase << 16) | (dqsInPhase << 6) | dqsInPhase; + } + else { + DDR->VCDLPhaseCntl0 = (VCDL_PHASE_DEFAULT << 22) | (VCDL_PHASE_DEFAULT << 16) | (VCDL_PHASE_DEFAULT << 6) | VCDL_PHASE_DEFAULT; + DDR->VCDLPhaseCntl1 = (VCDL_PHASE_DEFAULT << 22) | (VCDL_PHASE_DEFAULT << 16) | (VCDL_PHASE_DEFAULT << 6) | VCDL_PHASE_DEFAULT; + } + DDR->WSliceCntl &= ~((0x1<<20) | (0x1<<4)); + dumpChar('\n'); + dumpChar('\r'); +} + +#if defined(EXTENDED_MEMORY_TESTS) + +// Define the memory size for use by the memory test suite +#define MEMORY_SIZE (2 * 1024) + +int MemoryTestSuite(void) +{ + int test = 1; + uint32_t * memory = (uint32_t*) (0xa0000000); + Pattern_t pat32, patIx; + + for (patIx = PATTERN_0x00000000; patIx < PATTERN_MAX; patIx++ ) + { + pat32 = pattern[ patIx ]; + + fill_memory( memory, MEMORY_SIZE, 0x0 ); + if ( scanWordValue( memory, MEMORY_SIZE, pat32 ) == MEMTEST_FAILURE ) + goto exit_tests; + + test++; + + fill_memory( memory, MEMORY_SIZE, 0x0 ); + if ( scanBulkValue( memory, MEMORY_SIZE, pat32 ) == MEMTEST_FAILURE ) + goto exit_tests; + + test++; + + fill_memory( memory, MEMORY_SIZE, 0x0 ); + if ( scanBulkAltInv( memory, MEMORY_SIZE, pat32 ) == MEMTEST_FAILURE ) + goto exit_tests; + + test++; + + fill_memory( memory, MEMORY_SIZE, 0x0 ); + if ( slidingAltInv( memory, MEMORY_SIZE, pat32 ) == MEMTEST_FAILURE ) + goto exit_tests; + + test++; + + fill_memory( memory, MEMORY_SIZE, 0x0 ); + if ( slidingDiag( memory, MEMORY_SIZE, pat32 ) == MEMTEST_FAILURE ) + goto exit_tests; + + test++; + } + + fill_memory( memory, MEMORY_SIZE, 0x0 ); + if ( scanWordSelf( memory, MEMORY_SIZE ) == MEMTEST_FAILURE ) + goto exit_tests; + + test++; + + fill_memory( memory, MEMORY_SIZE, 0x0 ); + if ( scanBulkSelf( memory, MEMORY_SIZE ) == MEMTEST_FAILURE ) + goto exit_tests; + + test++; + + fill_alt_memory( memory, MEMORY_SIZE, 0XAAAAAAAA, 0x55555555 ); + if ( memoryBulkCopy( memory, (memory + ((MEMORY_SIZE/2)/sizeof(uint32_t))), + MEMORY_SIZE/2 ) == MEMTEST_FAILURE ) + goto exit_tests; + + // return tests; + return MEMTEST_SUCCESS; + +exit_tests: + return MEMTEST_FAILURE; + +} +#endif /* defined(EXTENDED_MEMORY_TESTS) */ + +// +// Returns: 0=FAILURE, 1=SUCCESS +inline static int MemoryTest(void) +{ + // Test 32-bit write/read + volatile uint32 *memAddr; + uint32 memBase; + uint32 testValue; + int i; + int j; + int k; + + memBase = 0xa0000000; + for (i = 2; i < 24; i++) { + memAddr = (void *) (memBase + (1 << i)); + for (k = 0; k < 2; k++) { + /* walking one */ + testValue = 1; + for (j = 0; j < 32; j++) { + *memAddr = testValue; + if (*memAddr != testValue) + return 0; + + testValue <<= 1; + } + /* walking zero */ + testValue = ~1; + for (j = 0; j < 32; j++) { + *memAddr = testValue; + if (*memAddr != testValue) + return 0; + + testValue = (testValue << 1) | 1; + } + /* shift in zeroes */ + testValue = -1; + for (j = 0; j < 32; j++) { + *memAddr = testValue; + *(uint32*)memBase = 0; + if (*memAddr != testValue) + return 0; + + testValue <<= 1; + } + /* shift in ones */ + testValue = 1; + for (j = 0; j < 32; j++) { + *memAddr = testValue; + *(uint32*)memBase = 0; + if (*memAddr != testValue) + return 0; + + testValue = (testValue << 1) | 1; + } + } + } + return 1; +} + diff --git a/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_impl1_rom_boot.S b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_impl1_rom_boot.S new file mode 100755 index 0000000..b3986ed --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_impl1_rom_boot.S @@ -0,0 +1,1818 @@ +#include "sbmips.h" +#include "bsp_config.h" + +#include "bcm_cpu.h" +#include "bcm_common.h" + +#include "bcm_hwdefs.h" +#include "boardparms.h" +#include "mipsmacros.h" + +#define DDR_TEST 1 +#define UBUS_SYNC_ENABLE 1 +#define LMB_SYNC_ENABLE 1 +#define MIPS_SYNC_ENABLE 1 +#define LMB_ENABLE 1 + +/* Memory mapping table for different size DRAMs (256Mb, 512Mb, 1Gb, 2Gb) */ + .globl dram_map_table_x8 +dram_map_table_x8: + // 128Mb 64B Interleaving (x8 Mode) 32MB + // This is just a place holder. This memory does not exist + _LONG_ 0x0F0E0D0C, 0x13121110, 0x17161514, 0x00000018 // Row00_0 Row00_1 Row01_0 Row01_1 + _LONG_ 0x04000000, 0x0A090805, 0x0000000B, 0x00000000 // Col00_0 Col00_1 Col01_0 Col01_1 + _LONG_ 0x00080706, 0x00000002, 0x00000055 // Bank CS_End Dramsize + + // 256Mb 64B Interleaving (x8 Mode) 64MB + _LONG_ 0x100F0E0D, 0x14131211, 0x18171615, 0x00000019 // Row00_0 Row00_1 Row01_0 Row01_1 + _LONG_ 0x04000000, 0x0A090805, 0x00000C0B, 0x00000000 // Col00_0 Col00_1 Col01_0 Col01_1 + _LONG_ 0x00000706, 0x00000004, 0x00000066 // Bank CS_End Dramsize + + // 512Mb 64B Interleaving (x8 Mode) 128MB + _LONG_ 0x100F0E0D, 0x14131211, 0x18171615, 0x00001A19 // Row00_0 Row00_1 Row01_0 Row01_1 + _LONG_ 0x04000000, 0x0A090805, 0x00000C0B, 0x00000000 // Col00_0 Col00_1 Col01_0 Col01_1 + _LONG_ 0x00000706, 0x00000008, 0x00000077 // Bank CS_End Dramsize + + // 1Gb 64B Interleaving (x8 Mode) 256MB + _LONG_ 0x11100F0E, 0x15141312, 0x19181716, 0x00001B1A // Row00_0 Row00_1 Row01_0 Row01_1 + _LONG_ 0x04000000, 0x0B0A0905, 0x00000D0C, 0x00000000 // Col00_0 Col00_1 Col01_0 Col01_1 + _LONG_ 0x00080706, 0x00000010, 0x00000088 // Bank CS_End Dramsize + + .globl dram_map_table_x16 +dram_map_table_x16: + // 256Mb 64B Interleaving (x16 Mode) 32MB + _LONG_ 0x0F0E0D0C, 0x13121110, 0x17161514, 0x00000018 // Row00_0 Row00_1 Row01_0 Row01_1 + _LONG_ 0x04000000, 0x0A090805, 0x0000000B, 0x00000000 // Col00_0 Col00_1 Col01_0 Col01_1 + _LONG_ 0x00000706, 0x00000002, 0x00000055 // Bank CS_End Dramsize + + // 512Mb 64B Interleaving (x16 Mode) 64MB + _LONG_ 0x100F0E0D, 0x14131211, 0x18171615, 0x00000019 // Row00_0 Row00_1 Row01_0 Row01_1 + _LONG_ 0x04000000, 0x0A090805, 0x00000C0B, 0x00000000 // Col00_0 Col00_1 Col01_0 Col01_1 + _LONG_ 0x00000706, 0x00000004, 0x00000066 // Bank CS_End Dramsize + + // 1Gb 64B Interleaving (x16 Mode) 128MB + _LONG_ 0x11100F0E, 0x15141312, 0x19181716, 0x0000001A // Row00_0 Row00_1 Row01_0 Row01_1 + _LONG_ 0x04000000, 0x0B0A0905, 0x00000D0C, 0x00000000 // Col00_0 Col00_1 Col01_0 Col01_1 + _LONG_ 0x00080706, 0x00000008, 0x00000077 // Bank CS_End Dramsize + + // 2Gb 64B Interleaving (x16 Mode) 256MB + _LONG_ 0x11100F0E, 0x15141312, 0x19181716, 0x00001B1A // Row00_0 Row00_1 Row01_0 Row01_1 + _LONG_ 0x04000000, 0x0B0A0905, 0x00000D0C, 0x00000000 // Col00_0 Col00_1 Col01_0 Col01_1 + _LONG_ 0x00080706, 0x00000010, 0x00000088 // Bank CS_End Dramsize + + .globl dram_tRefi_table +dram_tRefi_table: /* Refresh Interval table for different Speed DRAMs (100-200, 300-333, 400) */ + _LONG_ 0x16, 0x49, 0x5D // 100-200 300-333 400 (MHz) + + .globl dram_tRFC_table +dram_tRFC_table: /* tRFC table for different size & Speed DRAMs (256Mb, 512Mb, 1Gb)/(200, 333, 400) */ +// 200 333 400 (MHz) + _LONG_ 0xF, 0x19, 0x1E // 256Mb + _LONG_ 0x15, 0x23, 0x2A // 512Mb + _LONG_ 0x1A, 0x2B, 0x33 // 1Gb + _LONG_ 0x28, 0x42, 0x4F // 2Gb + + .globl dram_timing_table +dram_timing_table: /* */ +// tRCD tCL tWR tWL tRP tRRD tRC tFAW tW2R tR2W tR2R tAL tRTP tW2W +// --------------------------------------------------------------------- + .byte 0x03,0x04,0x03,0x03,0x03,0x02,0x11,0x00,0x01,0x01,0x00,0x02,0x02,0x00,0x00,0x00 // 200MHz + .byte 0x05,0x05,0x05,0x04,0x05,0x04,0x13,0x00,0x02,0x01,0x00,0x04,0x03,0x00,0x00,0x00 // 300MHz + .byte 0x05,0x05,0x06,0x04,0x06,0x05,0x18,0x00,0x02,0x01,0x00,0x04,0x03,0x00,0x00,0x00 // 400MHz + + .globl dram_sync_table +dram_sync_table: /* Bit vector table for Ubus sync modes and Lmb sync modes */ +#if defined(_BCM96328_) + _LONG_ 0x8E10FFFF, 0x8A10FFFF, 0xEDC2FFFF // UBUS Sync , LMB Sync, Mips Sync +#elif defined(_BCM96362_) + _LONG_ 0xFFBFBFBF, 0x6341C101, 0xE7E5E5E5 // UBUS Sync , LMB Sync, Mips Sync +#elif defined(_BCM96816_) + _LONG_ 0xC03033B5, 0x80303095, 0xFF90FFFF // UBUS Sync , LMB Sync, Mips Sync +#endif + .globl dram_speed_table +dram_speed_table: /* Memory Speed Table for different clock strap values */ + /* 0=200Mhz 1=333MHz 2=400MHz */ +#if defined(_BCM96328_) + .byte 0 // 0x0 + .byte 0 // 0x1 + .byte 0 // 0x2 + .byte 0 // 0x3 + .byte 0 // 0x4 + .byte 0 // 0x5 + .byte 0 // 0x6 + .byte 0 // 0x7 + .byte 0 // 0x8 + .byte 0 // 0x9 + .byte 0 // 0xa + .byte 0 // 0xb + .byte 0 // 0xc + .byte 0 // 0xd + .byte 0 // 0xe + .byte 0 // 0xf + .byte 0 // 0x10 + .byte 0 // 0x11 + .byte 0 // 0x12 + .byte 0 // 0x13 + .byte 0 // 0x14 + .byte 0 // 0x15 + .byte 2 // 0x16 + .byte 2 // 0x17 + .byte 0 // 0x18 + .byte 0 // 0x19 + .byte 0 // 0x1a + .byte 0 // 0x1b + .byte 0 // 0x1c + .byte 0 // 0x1d + .byte 0 // 0x1e + .byte 1 // 0x1f +#elif defined(_BCM96362_) + .byte 1 // 0x0 + .byte 2 // 0x1 + .byte 0 // 0x2 + .byte 1 // 0x3 + .byte 0 // 0x4 + .byte 2 // 0x5 + .byte 2 // 0x6 + .byte 1 // 0x7 + .byte 1 // 0x8 + .byte 2 // 0x9 + .byte 0 // 0xa + .byte 1 // 0xb + .byte 0 // 0xc + .byte 2 // 0xd + .byte 2 // 0xe + .byte 1 // 0xf + .byte 1 // 0x10 + .byte 2 // 0x11 + .byte 0 // 0x12 + .byte 1 // 0x13 + .byte 0 // 0x14 + .byte 1 // 0x15 // 267MHz. Need to change tREFI if this is used. + .byte 2 // 0x16 + .byte 1 // 0x17 + .byte 1 // 0x18 + .byte 1 // 0x19 + .byte 0 // 0x1a + .byte 1 // 0x1b + .byte 0 // 0x1c + .byte 0 // 0x1d + .byte 2 // 0x1e + .byte 1 // 0x1f +#elif defined(_BCM96816_) + .byte 0 // 0x0 + .byte 1 // 0x1 + .byte 0 // 0x2 + .byte 0 // 0x3 + .byte 0 // 0x4 + .byte 1 // 0x5 + .byte 1 // 0x6 + .byte 1 // 0x7 + .byte 1 // 0x8 + .byte 1 // 0x9 + .byte 1 // 0xa + .byte 2 // 0xb + .byte 2 // 0xc + .byte 2 // 0xd + .byte 2 // 0xe + .byte 2 // 0xf + .byte 2 // 0x10 + .byte 2 // 0x11 + .byte 2 // 0x12 + .byte 2 // 0x13 + .byte 2 // 0x14 + .byte 0 // 0x15 + .byte 0 // 0x16 + .byte 1 // 0x17 + .byte 1 // 0x18 + .byte 1 // 0x19 + .byte 1 // 0x1a + .byte 1 // 0x1b + .byte 2 // 0x1c + .byte 2 // 0x1d + .byte 2 // 0x1e + .byte 2 // 0x1f +#endif + + .globl memc_ubus_ratio_table +memc_ubus_ratio_table: /* Memory Speed Table for different clock strap values */ +#if defined(_BCM96328_) +// 6328 Clock Speed Table + .byte 3 // 0x0 + .byte 3 // 0x1 + .byte 3 // 0x2 + .byte 3 // 0x3 + .byte 3 // 0x4 + .byte 3 // 0x5 + .byte 3 // 0x6 + .byte 3 // 0x7 + .byte 3 // 0x8 + .byte 3 // 0x9 + .byte 3 // 0xa + .byte 3 // 0xb + .byte 3 // 0xc + .byte 3 // 0xd + .byte 3 // 0xe + .byte 3 // 0xf + .byte 3 // 0x10 + .byte 3 // 0x11 + .byte 0xf // 0x12 + .byte 0xf // 0x13 + .byte 3 // 0x14 + .byte 9 // 0x15 + .byte 9 // 0x16 + .byte 9 // 0x17 + .byte 3 // 0x18 + .byte 3 // 0x19 + .byte 3 // 0x1a + .byte 3 // 0x1b + .byte 0xb // 0x1c + .byte 0xb // 0x1d + .byte 0xb // 0x1e + .byte 3 // 0x1f +#elif defined(_BCM96362_) +// 6362 Clock Speed Table + .byte 3 // 0x0 + .byte 3 // 0x1 + .byte 3 // 0x2 + .byte 3 // 0x3 + .byte 3 // 0x4 + .byte 3 // 0x5 + .byte 3 // 0x6 + .byte 3 // 0x7 + .byte 3 // 0x8 + .byte 3 // 0x9 + .byte 3 // 0xa + .byte 3 // 0xb + .byte 3 // 0xc + .byte 3 // 0xd + .byte 3 // 0xe + .byte 3 // 0xf + .byte 3 // 0x10 + .byte 3 // 0x11 + .byte 3 // 0x12 + .byte 3 // 0x13 + .byte 4 // 0x14 + .byte 4 // 0x15 + .byte 15 // 0x16 + .byte 3 // 0x17 + .byte 3 // 0x18 + .byte 3 // 0x19 + .byte 3 // 0x1a + .byte 3 // 0x1b + .byte 3 // 0x1c + .byte 3 // 0x1d + .byte 3 // 0x1e + .byte 3 // 0x1f +#elif defined(_BCM96816_) +// 6816 Clock Speed Table + .byte 3 // 0x0 + .byte 9 // 0x1 + .byte 3 // 0x2 + .byte 4 // 0x3 + .byte 3 // 0x4 + .byte 3 // 0x5 + .byte 9 // 0x6 + .byte 3 // 0x7 + .byte 3 // 0x8 + .byte 3 // 0x9 + .byte 2 // 0xa + .byte 4 // 0xb + .byte 2 // 0xc + .byte 3 // 0xd + .byte 4 // 0xe + .byte 9 // 0xf + .byte 1 // 0x10 + .byte 1 // 0x11 + .byte 1 // 0x12 + .byte 1 // 0x13 + .byte 3 // 0x14 + .byte 3 // 0x15 + .byte 4 // 0x16 + .byte 9 // 0x17 + .byte 6 // 0x18 + .byte 2 // 0x19 + .byte 6 // 0x1a + .byte 2 // 0x1b + .byte 4 // 0x1c + .byte 3 // 0x1d + .byte 4 // 0x1e + .byte 3 // 0x1f +#endif + +#if defined(_BCM96816_) + .globl periph_fix_table +periph_fix_table: // Periph Clock fix vector for different clock strap values + _LONG_ 0xAA30A047 +#endif + +#define SETLEDS1(a,b,c,d) \ + li a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ; \ + bal board_setleds; \ + nop + +/* ********************************************************************* + * BOARD_EARLYINIT() + * + * Initialize board registers. This is the earliest + * time the BSP gets control. This routine cannot assume that + * memory is operational, and therefore all code in this routine + * must run from registers only. The $ra register must not + * be modified, as it contains the return address. + * + * This routine will be called from uncached space, before + * the caches are initialized. If you want to make + * subroutine calls from here, you must use the CALLKSEG1 macro. + * + * Among other things, this is where the GPIO registers get + * programmed to make on-board LEDs function, or other startup + * that has to be done before anything will work. + * + * Input parameters: + * a0 - Flash base address (address of MIPS reset) + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(board_earlyinit) + + .set noreorder + + mfc0 t1, C0_BCM_CONFIG, 3 + li t2, CP0_CMT_TPID + and t1, t2 + bnez t1, 3f # if we are running on thread 1, skip init + nop + + /**-------------------------------------------------------------**/ + /** platform specific code **/ + /**-------------------------------------------------------------**/ + +#if defined(_BCM96816_) + /**----- Offset UBUS Clock 180 degrees -------------------------**/ + li t2, MISC_BASE + lw t1, MISC_STRAP_BUS(t2) + + srl t1, MISC_STRAP_BUS_MIPS_PLL_FVCO_SHIFT + andi t1, 0x1f // Mask out strap bits + + move s0,ra + LOADREL(t2, periph_fix_table) + lw t2, 0(t2) + srl t2, t1 + andi t2, 1 + move ra,s0 + + beq t2, zero, 2f + nop + + li t0, DDR_BASE + li t1, 0x00070000 // send new phase value to PLL every 8 cycles + sw t1, DDR_CTL_PI_UBUS_CTL(t0) + ori t1, 0x4080 // shift 128 steps in the positive direction to be 180 degree's offset VCO 1.6GHz + sw t1, DDR_CTL_PI_UBUS_CTL(t0) + li t1, 0x00000001 + sw t1, DDR_CTL_PI_GCF(t0) + + li t1, 0x10000 // delay +1: + bnez t1, 1b + addi t1, -1 + +2: + /**----- Set 1.2V and 2.5V Voltage regulators ------------------**/ + li t1, GPIO_BASE + lw t2, GPIO_SWREG_CONFIG(t1) + and t2, ~GPIO_SW_VREG_SEL_MASK + or t2, (0x0 << GPIO_SW_VREG_SEL_SHIFT) + and t2, ~GPIO_LIN_VREG_ADJ_MASK + or t2, (0x0 << GPIO_LIN_VREG_ADJ_SHIFT) + sw t2, GPIO_SWREG_CONFIG(t1) + + li t1, 0x10000 +1: + bnez t1, 1b + addi t1, -1 +#endif + +#if defined (_BCM96328_) || defined (_BCM96362_) + /* slow down mips clk (div 4) to unlock memory */ + mfc0 t1, C0_BCM_CONFIG, 5 + or t2, t1, 0x40000000 + mtc0 t2, C0_BCM_CONFIG, 5 + nop + + mtc0 t1, C0_BCM_CONFIG, 5 + nop +#endif + +#if defined (_BCM96362_) + /* Adjust VREG frequency up by 50% to improve DSL performance */ + li t2, MISC_BASE + + /* First set ramp control */ + lw t1, MISC_VREG_CONTROL0(t2) + or t1, (0x2 << MISC_VREG_CONTROL0_VREG_RAMP1P8_SHIFT) | (0x2 << MISC_VREG_CONTROL0_VREG_RAMP1P2_SHIFT) + sw t1, MISC_VREG_CONTROL0(t2) + + /* wait 10ms for the setting to take effect */ + li t8, -2000000 + mtc0 t8, C0_COUNT +1: + bltz t8, 1b + mfc0 t8, C0_COUNT + + and t1, ~((0x7 << MISC_VREG_CONTROL0_VREG_RAMP1P8_SHIFT) | (0x7 << MISC_VREG_CONTROL0_VREG_RAMP1P2_SHIFT)) + or t1, (0x3 << MISC_VREG_CONTROL0_VREG_ADJ_SHIFT) + sw t1, MISC_VREG_CONTROL0(t2) + + /* Increase 2.5V regulator to provide increased range for 1.8V */ + lw t1, MISC_VREG_CONTROL1(t2) + and t1, ~MISC_VREG_CONTROL1_VREG_ISEL2P5_MASK + or t1, (MISC_VREG_LDO_2P61 << MISC_VREG_CONTROL1_VREG_ISEL2P5_SHIFT) + sw t1, MISC_VREG_CONTROL1(t2) +#endif + +#if 0 + /* wait for a while to allow catch by jtag debugger */ + li t8, -(200000000*3) /* we will count up to 0 to delay a couple of seconds */ + /* and give the emulator a chance to catch us */ + mtc0 t8, C0_COUNT +catchloop: + bltz t8, catchloop + mfc0 t8, C0_COUNT +#endif + + /**----- Enable I Cache -----------------------------------------**/ + mfc0 t1, C0_BCM_CONFIG + or t1, (CP0_BCM_CFG_ICSHEN | CP0_BCM_CFG_DCSHEN) + mtc0 t1, C0_BCM_CONFIG # Enable I Cache + + // In the begining MIPS core registers are mapped to 0xbfax_xxxx + li t1, 0x1FA0000C # Set up CBR to 1FAx_xxxx + mtc0 t1, C0_BCM_CONFIG, 6 + + li t1, MIPS_BASE_BOOT + lw t2, MIPS_LMB_CR(t1) + or t2, 0xC0000000 # enable ffxx_xxxx space + sw t2, MIPS_LMB_CR(t1) + li t2, 0xFFF80001 # SBR FFF8_xxxx and enable + sw t2, MIPS_SBR(t1) + + // Now map MIPS core registers to 0xFF4x_xxxx space + li t1, 0xFF40000C # CBR FF4x_xxxx (and reserved bits 0xc). + mtc0 t1, C0_BCM_CONFIG, 6 + +#if defined(_BCM96816_) + /**----- Initialize EBI -----------------------------------------**/ + li t1, MPI_BASE + li t2, EBI_SIZE_32M + or t2, a0 + sw t2, CS0BASE(t1) # CS[0] Base + li t2, THREEWT|EBI_WORD_WIDE|EBI_ENABLE + sw t2, CS0CNTL(t1) # CS[0] Control +#endif + + /**----- Initialize Serial --------------------------------------**/ + li t3, ((FPERIPH / 115200) / 16) + /* + # Baudword = (FPeriph)/Baud/32-1. We have to perform rounding + # and subtraction. Above we divided by 16 (instead of 32). If + # bit0 is set, we round up. However, we then subtract 1, so final + # result should be t3/2. If bit0 is 0, then we truncate and subtract + # 1, t3=t3/2-1. + */ + andi t0, t3, 0x1 + bne t0,zero,1f # do shift only (in delay slot) + # and jump to apply + srl t3,1 # do divide by 2 + addiu t3, -1 # subtract 1 +1: + + // t3 contains the UART BAUDWORD + li t0, UART_BASE + sw t3, UART0BAUD(t0) # Store BaudRate + li t1, BITS8SYM|ONESTOP + sb t1, UART0CONFIG(t0) # 8 Bits/1 Stop + li t1, TXEN|RXEN|BRGEN + sb t1, UART0CONTROL(t0) # Enable, No Parity + move t1, zero + sh t1, UART0INTMASK(t0) + + .set reorder +3: + j ra +END(board_earlyinit) + +/* ********************************************************************* + * BOARD_DRAMINFO + * + * Return the address of the DRAM information table + * + * Input parameters: + * nothing + * + * Return value: + * v0 - DRAM info table, return 0 to use default table + ********************************************************************* */ +LEAF(board_draminfo) + j ra +END(board_draminfo) + +/* ********************************************************************* + * BOARD_DRAMINIT + * + * This routine should activate memory. + * + * Input parameters: + * None + * + * Return value: + * None + * + * Registers used: + * can use all registers. + ********************************************************************* */ +LEAF(board_draminit) + .set noreorder + + move s0,ra + +/***** Load DDR Base *************************************/ + li t0, DDR_BASE + +/***** Disable Auto refresh ******************************/ + li t1, 0x10000 + sw t1, DDR_CTL_CLKS(t0) + SETLEDS1('-','-','-', '-') + SETLEDS1('P','H','Y','S') + + li t1, 0x10 // Loop count value + li t3, 1 + +zq_loop: + sub t1, t3 // Decrement count by 1 + beq t1, zero, zq_error + nop + + sw zero, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Reset the calibration engine + li t4, (1 << 26) + sw t4, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Start the calibration + + li t2, 0x100 // Timeout value + +wait_zq1: + beq t2, zero, zq_timeout + nop + + lw t4, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Read the calibration result + move t5, t4 // Save calibration result1 + and t4, (1 << 28) + beq t4, zero, wait_zq1 + sub t2, t3 + + sw zero, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Reset the calibration engine + li t4, (1 << 26) + sw t4, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Start the calibration + + li t2, 0x100 // Timeout value + +wait_zq2: + beq t2, zero, zq_timeout + nop + + lw t4, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Read the calibration result + move t6, t4 // Save calibration result1 + and t4, (1 << 28) + beq t4, zero, wait_zq2 + sub t2, t3 + + sw zero, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Reset the calibration engine + li t4, (1 << 26) + sw t4, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Start the calibration + + li t2, 0x100 // Timeout value + +wait_zq3: + beq t2, zero, zq_timeout + nop + + lw t4, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Read the calibration result + move t7, t4 // Save calibration result1 + and t4, (1 << 28) + beq t4, zero, wait_zq3 + sub t2, t3 + + bne t5, t6, zq_loop + nop + bne t5, t7, zq_loop + nop + bne t6, t7, zq_loop + nop + + b zq_done; + nop + +zq_error: + SETLEDS1('Z','Q','E','R') + b zq_done + nop + +zq_timeout: + SETLEDS1('Z','Q','T','O') + nop +zq_done: + sw zero, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Reset the calibration engine + + SETLEDS1('Z','Q','D','N') + nop + +/****** Set control pad strength to half ********/ + lw t2, PHY_CONTROL_REGS_DRIVE_PAD_CTL(t0) + or t2, 0x4 + sw t2, PHY_CONTROL_REGS_DRIVE_PAD_CTL(t0) + +#if defined(_BCM96816_) +/****** Disable byte lanes 2 and 3 ********/ + li t1, 0x800fffff + sw t1, PHY_BYTE_LANE_2_IDLE_PAD_CONTROL(t0) + sw t1, PHY_BYTE_LANE_3_IDLE_PAD_CONTROL(t0) +#endif + +/****** Disable byte lane 1 clock ********/ + li t1, 1 + sw t1, PHY_BYTE_LANE_1_CLOCK_PAD_DISABLE(t0) + +ddr_x8: + +/****** Change the slew and receiver power to full strength in the byte lanes ********/ + li t1, 0xFFFFFFFC + lw t2, PHY_BYTE_LANE_0_DRIVE_PAD_CTL(t0) + and t2, t2, t1 + sw t2, PHY_BYTE_LANE_0_DRIVE_PAD_CTL(t0) + lw t2, PHY_BYTE_LANE_1_DRIVE_PAD_CTL(t0) + and t2, t2, t1 + sw t2, PHY_BYTE_LANE_1_DRIVE_PAD_CTL(t0) + +/****** Hardware calibrate VDL *******/ + li t1, 3 + sw t1, PHY_BYTE_LANE_0_VDL_CALIBRATE(t0) + sw t1, PHY_BYTE_LANE_1_VDL_CALIBRATE(t0) + + li t1, 0x1000 +1: + bnez t1, 1b + addi t1, -1 + +/****** Check strap value to figure out 400MHz or 200Mhz DDR ******/ + li t2, MISC_BASE + lw t1, MISC_STRAP_BUS(t2) + + srl t1, MISC_STRAP_BUS_MIPS_PLL_FVCO_SHIFT + andi t1, 0x1f // Mask out strap bits + + LOADREL(t2, dram_speed_table) + + add t2, t1 + lb t1, 0x00(t2) + beq t1, zero, ddr_clk_200 + li t2, 1 + beq t1, t2, ddr_clk_300 + nop + +/****** Software override rd_en VDL and ADDRESS VDL ********/ +ddr_clk_450: +ddr_clk_400: + li a1, 2 // Set speed to 400MHz (2) + b 1f + nop +ddr_clk_300: + li a1, 1 // Set speed to 300MHz (1) + +/* At higher frequencies set Read_en VDL value to calibrated VDL value + 10 */ +1: li t2, 0x10000 + lw t1, PHY_BYTE_LANE_0_VDL_STATUS(t0) + srl t1, 8 + addi t1, 0xA + or t1, t1, t2 + sw t1, PHY_BYTE_LANE_0_VDL_OVERRIDE_2(t0) + lw t1, PHY_BYTE_LANE_1_VDL_STATUS(t0) + srl t1, 8 + addi t1, 0xA + or t1, t1, t2 + sw t1, PHY_BYTE_LANE_1_VDL_OVERRIDE_2(t0) + b vdl_override_cont + nop + +ddr_clk_200: + li a1, 0 // Set speed to 200MHz (0) + li t3, 0x1f // Set maximum VDL step size for 200MHz + b 1f + nop + +vdl_override_cont: + lw t2, PHY_BYTE_LANE_0_VDL_STATUS(t0) + andi t3, t2, 0x1f00 + srl t3, 8 + addi t3, t3, 0x4 // Add Stepsize 4 + +1: li t1, 0x110000 // Enable & Force Override + or t1, t3 // Fine rise and fine fall are set to 0 + + sw t1, PHY_CONTROL_REGS_STATIC_VDL_OVERRIDE(t0) + li t1, 0x0c + sw t1, DDR_CTL_DCMD(t0) // Set VDL + + SETLEDS1('P','H','Y','E') + +/* Program MC Timing Registers + + Read each timing parameter based on the speed and then create the + timing registers and program them. +*/ + LOADREL(t2, dram_timing_table) + + li t1, 0x10 // size of dram_timing_table element + mult t1, a1 + mflo t1 // dram_timing_table offset + add t2, t1 + + move t3, zero + lb t1, 0x00(t2) // tRCD + andi t1, 0xf + move t3, t1 + lb t1, 0x01(t2) // tCL + andi t1, 0xf + + move t4, t1 + and t4, 0x7 // Make sure that only 3 bits are written to DRAM's tCL field + sll t4, 20 + sw t4, DDR_CTL_DMODE_0 (t0) // Write tCL to the MRS register holder + + sll t1, 4 + or t3, t1 + lb t1, 0x02(t2) // tWR + andi t1, 0xf + + // Here we create the MRS register values + move t4, t1 + li t5, 1 + subu t4, t5 // tWR written to DRAM is 1 less than real tWR value + andi t4, 0x7 + sll t4, 25 + li t5, 0x01030000 // Sequential burst mode, burst of 8, reset DLL + or t4, t5 + lw t5, DDR_CTL_DMODE_0 (t0) + or t5, t4 + sw t5, DDR_CTL_DMODE_0 (t0) // Add tWR to the MRS register holder + + sll t1, 9 + or t3, t1 + lb t1, 0x03(t2) // tWL + andi t1, 0xf + sll t1, 12 + or t3, t1 + lb t1, 0x04(t2) // tRP + andi t1, 0xf + sll t1, 16 + or t3, t1 + lb t1, 0x05(t2) // tRRD + andi t1, 0xf + sll t1, 20 + or t3, t1 + lb t1, 0x06(t2) // tRC + andi t1, 0x1f + sll t1, 24 // tRCw + or t3, t1 + sw t3, DDR_CTL_TIM1_0(t0) // Program TIM1_0 register + + move t3, zero + lb t1, 0x06(t2) // tRC + andi t1, 0x1f + or t3, t1 // tRCr + lb t1, 0x07(t2) // tFAW + andi t1, 0x3f + sll t1, 8 + or t3, t1 + li t1, 0xff // tRFC = 0xff (Set to max value first. + sll t1, 16 // We'll fix it after we determine dram size) + or t3, t1 + + // We skip tFIFO since it needs to be 0 + + lb t1, 0x08(t2) // tW2R + andi t1, 0x3 + sll t1, 26 + or t3, t1 + lb t1, 0x09(t2) // tR2W + andi t1, 0x3 + sll t1, 28 + or t3, t1 + lb t1, 0x0a(t2) // tR2R + andi t1, 0x1 + sll t1, 30 + or t3, t1 + sw t3, DDR_CTL_TIM1_1(t0) // Program TIM1_1 register + + move t3, zero + lb t1, 0x0b(t2) // tAL + andi t1, 0xf + + // Here we create the EMRS register values + move t4, t1 + andi t4, 0x7 + sll t4, 3 + li t5, 0x384 // RTT=75ohm, OCD Enter + or t4, t5 + lw t5, DDR_CTL_DMODE_0 (t0) + or t5, t4 + sw t5, DDR_CTL_DMODE_0 (t0) // Store required values in EMRS holding register + + or t3, t1 + lb t1, 0x0c(t2) // tRTP + andi t1, 0x7 + sll t1, 4 + or t3, t1 + lb t1, 0x0d(t2) // tW2W + andi t1, 0x3 + sll t1, 8 + or t3, t1 + sw t3, DDR_CTL_TIM2(t0) // Program TIM2 register + +/* +// (tRRD is incremented by 1 due to tFAW bug for >=1Gb devices) + li t1, 0x18564c55 // tRCD=5,tWR=6,tCL=5,tWL=4,tRP=6,tRRD=5,tRCw=0x18 +// li t1, 0x13554a55 // tRCD=5,tWR=5,tCL=5,tWL=4,tRP=5,tRRD=5,tRCw=0x13 + sw t1, DDR_CTL_TIM1_0(t0) + li t1, 0x18330018 // tR2W=1,tR2R=0,tW2R=2,tFIFO=0,tRFC=0x33,tFAW=0,tRCr=0x18 +// li t1, 0x182b0013 // tR2W=1,tR2R=0,tW2R=2,tFIFO=0,tRFC=0x2b,tFAW=0,tRCr=0x13 + sw t1, DDR_CTL_TIM1_1(t0) + li t1, 0x00000034 // tAL=4 (tRCD-1), tRTP=3, tW2W=0 + sw t1, DDR_CTL_TIM2(t0) +*/ + +// Set x16 mode and Page policy + li t1, 0x100 + sw t1, DDR_CTL_DMODE_1(t0) + +// Enable ODT for writes + li t1, 0x104 + sw t1, DDR_CTL_ODT(t0) + +/***** Turn on CKE ***************/ + li t1, 0x35 + sw t1, DDR_CTL_DCMD(t0) + + li t1, 0x200 +2: + bnez t1, 2b + addi t1, -1 + +/***** Set arbitor for Burst Round Robin Mode ***/ + lw t1, DDR_CTL_ARB(t0) + or t1, 4 << 16 + sw t1, DDR_CTL_ARB(t0) + +/***** Issue Precharge All Banks Command ***/ + li t1, 0x32 + sw t1, DDR_CTL_DCMD(t0) + +/***** Issue EMRS2 Command ***/ + li t1, 0x0 + lw t2, DDR_CTL_DMODE_0 (t0) // Load previous value to t2 to preserve it + nop + sw t1, DDR_CTL_DMODE_0 (t0) + li t1, 0x38 + sw t1, DDR_CTL_DCMD(t0) + +/***** Issue EMRS3 Command***/ + li t1, 0x0 + sw t1, DDR_CTL_DMODE_0 (t0) + li t1, 0x39 + sw t1, DDR_CTL_DCMD(t0) + +// Enable DLL by issuing EMRS Command +// li t1, 0x0 +// sw t1, DDR_CTL_DMODE_0 (t0) + sw t2, DDR_CTL_DMODE_0 (t0) // Use the saved value back to DMODE_0 register + li t1, 0x30 + sw t1, DDR_CTL_DCMD(t0) + +/* +// Issue MRS Command tCL=5 tWL=4 + li t1, 0x0b530000 +// li t1, 0x07530000 // tCL=5 tWR=5, Reset DLL, Sequential Mode, Burst Length = 8 + sw t1, DDR_CTL_DMODE_0 (t0) + li t1, 0x31 + sw t1, DDR_CTL_DCMD(t0) +*/ +// Issue MRS Command. Set Reset DLL bit + li t1, 0x31 + sw t1, DDR_CTL_DCMD(t0) + +// Issue Precharge All Banks Command + li t1, 0x32 + sw t1, DDR_CTL_DCMD(t0) + +// Issue Autorefresh Command + li t1, 0x33 + sw t1, DDR_CTL_DCMD(t0) + li t1, 0x33 + sw t1, DDR_CTL_DCMD(t0) + + li t1, 0x200 +3: + bnez t1, 3b + addi t1, -1 + +/* +// Clear DLL Reset by Issuing MRS Command, tCL=5 tWL=4 + li t1, 0x0a530000 + sw t1, DDR_CTL_DMODE_0 (t0) + li t1, 0x31 + sw t1, DDR_CTL_DCMD(t0) +*/ + +// Issue MRS Command w/ DLL Reset bit set to 0 + lw t1, DDR_CTL_DMODE_0 (t0) + li t2, 0xFEFFFFFF // Reset DLL reset bit + and t1, t2 + sw t1, DDR_CTL_DMODE_0 (t0) + li t1, 0x31 + sw t1, DDR_CTL_DCMD(t0) + +/* +// Issue EMRS Command (Enter OCD Calibration) + li t1, 0x380 + sw t1, DDR_CTL_DMODE_0 (t0) + li t1, 0x30 + sw t1, DDR_CTL_DCMD(t0) +*/ + +// Issue EMRS Command (Enter OCD Calibration) 75 Ohm, Full strength Drive, tAL=tRCD-1 + li t1, 0x30 + sw t1, DDR_CTL_DCMD(t0) + +// Issue EMRS Command (Exit OCD Calibration) + lw t1, DDR_CTL_DMODE_0 (t0) + li t2, 0xFC7F // Reset OCD field for exit mode + and t1, t2 + sw t1, DDR_CTL_DMODE_0 (t0) + li t1, 0x30 + sw t1, DDR_CTL_DCMD(t0) + +// Check x8 or x16 DDR + li t1, 0x12345678 + li t3, 0xA0000000 + sw zero, 0(t3) + sw t1, 0(t3) + lw t2, 0(t3) + bne t1, t2, 3f // Failed + nop +// Do the test twice. Just in case random values match... + li t1, 0x87654321 + sw t1, 0(t3) + lw t2, 0(t3) + beq t1, t2, 1f // Clock lines are enabled as needed + nop + +3: +// Memory test failed. Need to re-enable byte lane 1 clock + sw zero, PHY_BYTE_LANE_1_CLOCK_PAD_DISABLE(t0) + li t1, 0x200 +2: + bnez t1, 2b // Delay after enabling clocks + addi t1, -1 + b ddr_x8 + nop + +1: +// Find memory size. a3 keeps the size: 0=256Mb, 1=512Mb, 2=1Gb, 3=2Gb +// Start from 2Gb device + LOADREL(t7, dram_map_table_x8) + lw t1, PHY_BYTE_LANE_1_CLOCK_PAD_DISABLE(t0) + beqz t1, 1f + nop + LOADREL(t7, dram_map_table_x16) + +1: + li a3, 4 +ddr_size: + addi a3, -1 + + li t1, 0x2c // size of dram_map_table element + mult t1, a3 + mflo t2 // dram_map_table offset + add t2, t7 + + lw t1, 0x00(t2) // Row00_0 + sw t1, DDR_CTL_ROW00_0(t0) + + lw t1, 0x04(t2) // Row00_1 + sw t1, DDR_CTL_ROW00_1(t0) + + lw t1, 0x08(t2) // Row01_0 + sw t1, DDR_CTL_ROW01_0(t0) + + lw t1, 0x0C(t2) // Row01_1 + sw t1, DDR_CTL_ROW01_1(t0) + + lw t1, 0x10(t2) // Col00_0 + sw t1, DDR_CTL_COL00_0(t0) + + lw t1, 0x14(t2) // Col00_1 + sw t1, DDR_CTL_COL00_1(t0) + + lw t1, 0x18(t2) // Col01_0 + sw t1, DDR_CTL_COL01_0(t0) + + lw t1, 0x1C(t2) // Col01_1 + sw t1, DDR_CTL_COL01_1(t0) + + lw t1, 0x20(t2) // Bank + sw t1, DDR_CTL_BNK10(t0) + + li t1, 0x0 // CS_Start + sw t1, DDR_CTL_CSST(t0) + + lw t1, 0x24(t2) // CS_End + sw t1, DDR_CTL_CSEND(t0) + + li t1, 0x0 // CS Interleaving CFG + sw t1, DDR_CTL_CNFG(t0) + + lw t3, 0x28(t2) // Dram Size + lw t1, DDR_CTL_GCFG(t0) // GCFG + li t2, 0xFFFFFF00 + and t1, t1, t2 // Mask out Dram Size Fields + or t1, t3, t1 // insert new DRAM Size value + sw t1, DDR_CTL_GCFG(t0) + beqz a3, ddr_speed + nop + +// Check for memory aliasing +// This assumes that the bank interleaving is below address bits 8. + li t1, 8 + li t2, 24 + add t2, a3 // Scan up to maximum memory size + li t3, 0xA0000000 + +check_alias: + li t4, 1 + sll t4, t1 + add t4, t3 + + sw zero, 0(t3) + li t5, -1 + sw t5, 0(t4) + lw t6, 0(t3) + + beq t5, t6, ddr_size + nop + + bne t1, t2, check_alias + addi t1, 1 + +ddr_speed: + li t1, 3 + lw t2, PHY_BYTE_LANE_1_CLOCK_PAD_DISABLE(t0) + beqz t2, 1f + nop + li t1, 2 +1: + blt a3, t1, tRefi_update // If smaller than 1Gb device, keep tRRD same + nop + + lw t1, DDR_CTL_TIM1_0(t0) // Load DDR_CTL_TIM1_0 register + move t2, t1 + srl t2, 20 + andi t2, 0xf + addi t2, 1 // Increment ttRRD by one (software work around for a bug) + sll t2, 20 + li t3, 0xFF0FFFFF + and t1, t3 // Clear tRRD field + or t1, t2 // Insert the new tRRD value + sw t1, DDR_CTL_TIM1_0(t0) // Store DDR_CTL_TIM1_0 register + nop + +tRefi_update: + LOADREL(t2, dram_tRefi_table) + + li t1, 0x4 // size of dram_tRefi_table entry + mult t1, a1 + mflo t1 // dram_tRefi_table offset + add t2, t1 + + lw t1, 0x0(t2) // tRefi + sll t1, 8 + sw t1, DDR_CTL_CLKS(t0) + + LOADREL(t2, dram_tRFC_table) + + li t1, 0x4 // size of dram_tRFC_table entry + mult t1, a1 + mflo t1 // dram_tRefi_table offset + add t2, t1 // Calculate address in the row + + li t1, 0xc // size of dram_tRFC_table row + mult t1, a3 + mflo t1 // dram_tRefi_table offset + add t2, t1 // Calculate address in the column + + lw t3, 0x0(t2) // Load tRFC value + andi t3, 0xFF // Mask tRFC to 8-bits + sll t3, 16 // Move it to bit location [23:16] + + lw t1, DDR_CTL_TIM1_1(t0) // Load DDR_CTL_TIM1_1 register + li t2, 0xFF00FFFF + and t1, t1, t2 // Mask out tRFC Field + or t1, t3, t1 // insert new tRFC value + sw t1, DDR_CTL_TIM1_1(t0) // Write to TIM1_1 register + + SETLEDS1('D','I','N','T') + +/***** UBUS align to MEMC *****/ +align_memc: + +/*** check MEMC clk ratio to set sampling freq *****/ + li t2, MISC_BASE + lw t1, MISC_STRAP_BUS(t2) + + srl t1, MISC_STRAP_BUS_MIPS_PLL_FVCO_SHIFT + andi t1, 0x1f // Mask out strap bits + +#if defined(_BCM96816_) + LOADREL(t2, periph_fix_table) + lw t2, 0(t2) + srl t2, t1 + andi t2, 1 + bne t2, zero, 2f +#endif + + LOADREL(t2, memc_ubus_ratio_table) + + add t2, t1 + lb t1, 0x00(t2) + sll t4,t1,28 // Update Sampling Period Field + +pi_ubus: + li t2, 4048 + li t3, 1 + + sw zero, DDR_CTL_PI_GCF(t0) + li t1, 0x00001c0b // send feedback command every 11 cycles + or t1, t1, t4 + sw t1, DDR_CTL_PI_UBUS_SMPL(t0) + ori t1, 0x80 // trigger stoke signal to latch in new counter value + sw t1, DDR_CTL_PI_UBUS_SMPL(t0) + li t1, 0x00040000 // send new phase value to PLL every 5 cycles + sw t1, DDR_CTL_PI_UBUS_CTL(t0) + li t1, 0x00000001 // enable enable counter that change PLL phase + sw t1, DDR_CTL_PI_GCF(t0) + nop + +#if defined (_BCM96328_) || defined(_BCM96362_) +// Enable PHY MIPS PI + li t1, 0x00130000 + sw t1, DDR_CTL_PI_DSL_MIPS_CTL(t0) + nop +#endif + +1: + lw t4, DDR_CTL_PI_UBUS_SMPL(t0) // Read a sample value. + srl t4, 16 // The sample is in the upper 16 bits. + + andi t4, t4, 0x22 // Look at the 2 outermost bits; if the LSB is 0 and the MSB is 1, + beq t4, 0x20, 2f // then there is an edge somewhere in the sample. + nop + lw t5, DDR_CTL_PI_UBUS_CTL(t0) + and t5, 0xffff0000 + or t5, t3 + or t5, (1<<14) // move phase in positive direction + sw t5, DDR_CTL_PI_UBUS_CTL(t0) + nop + lw t5, DDR_CTL_PI_UBUS_CTL(t0) // Delay before reading another sample. + add t3, 1 + bne t2, t3, 1b + nop + + SETLEDS1('U','A','S','Y') + SETLEDS1('L','A','S','Y') + SETLEDS1('M','A','S','Y') + b run_async // failed to set sync mode + nop + +2: +/*** check MIPS clk ratio *****/ + li t4, 0xff410010 + li t2, MISC_BASE + lw t1, MISC_STRAP_BUS(t2) + + srl t1, MISC_STRAP_BUS_MIPS_PLL_FVCO_SHIFT + andi t1, 0x1f // Mask out strap bits + + b _mips_align_2_ubus // none of the above means it is either 1/1 or 2/1 + nop + + +_mips_align_2_ubus: + +/***** MIPS align to UBUS *****/ + li t1, 0xff410000 + + li t2, 0x00040000 // update PLL phase value every 5 MC cycles + sw t2, DDR_CTL_PI_MIPS_CTL(t0) + + li t2, 0xc0001c03 // force update on mclk_period + sw t2, 0x40(t1) + li t2, 0x80001c83 + sw t2, 0x40(t1) + + lw t2, DDR_CTL_PI_MIPS_CTL(t0) // add delay + li t3, 1 + +1: lw t4, 0x40(t1) // Read a sample value. + srl t4, 16 // The sample is in the upper 16 bits. + + andi t4, t4, 0x22 // Look at the 2 outermost bits, if the LSB is 0 and the MSB is 1, + beq t4, 0x20, 2f // then there is an edge somewhere in the sample. + nop + lw t5, DDR_CTL_PI_MIPS_CTL(t0) + and t5, 0xffff0000 + or t5, t3 + or t5, (1<<14) // move phase in positive direction + sw t5, DDR_CTL_PI_MIPS_CTL(t0) + nop + lw t5, DDR_CTL_PI_MIPS_CTL(t0) // Delay before reading another sample. + add t3, 1 + bne t2, t3, 1b + nop + + SETLEDS1('U','A','S','Y') + SETLEDS1('L','A','S','Y') + SETLEDS1('M','A','S','Y') + b run_async // failed to set sync mode + nop +2: + // Success + lw t2, DDR_CTL_PI_MIPS_CTL(t0) // Turn on auto-PI mode. + or t2, (1 << 20) // PI_UBUS_CTL_Hw_Cntr_En = 1 + sw t2, DDR_CTL_PI_MIPS_CTL(t0) + + /**----- Enable DDR/UBUS and DDR/LMB sync mode ------------------**/ + /*** only MIPS in sync mode for these strap options */ + + li t2, MISC_BASE + lw t1, MISC_STRAP_BUS(t2) + + srl t1, MISC_STRAP_BUS_MIPS_PLL_FVCO_SHIFT + andi t1, 0x1f // Mask out strap bits + + li t3, 0 // Used to keep MC/MIPS and MC/UBUS sync/async mode + + LOADREL(t2, dram_sync_table) + + lw t4, 0x0(t2) // Ubus Sync vector + lw t5, 0x4(t2) // Lmb Sync vector + +#if defined (_96816_) + move t4, t6 +#endif + lw t6, 0x8(t2) // Mips Sync vector + + srl t4, t1 // Get the ubus sync flag + srl t5, t1 // Get the lmb sync flag + srl t6, t1 // Get the mips sync flag + andi t4, 1 // Mask out other bits + andi t5, 1 // Mask out other bits + andi t6, 1 // Mask out other bits + + li t2, 1 + bne t4, t2, ubus_async // 1f below. If ubus is not sync, lmb can't be in sync + nop // Go to ubus_async (1f) + + // Ubus Sync Mode. Turn on Ubus Clock tracking + lw t2, DDR_CTL_PI_UBUS_CTL(t0) // Turn on auto-PI mode. + or t2, (1 << 20) // PI_UBUS_CTL_Hw_Cntr_En = 1 + sw t2, DDR_CTL_PI_UBUS_CTL(t0) + + // Is LMB Sync as well? + li t2, 1 + beq t5, t2, memc_all_sync // If both ubus and lmb are sync, go to memc_all_sync + nop + +memc_ubus_sync: +#if UBUS_SYNC_ENABLE +// set MC/UBUS to SYNC + li t3, 0x4 + SETLEDS1('L','A','S','Y') + SETLEDS1('U','S','Y','N') +#else +// set MC/UBUS to ASYNC + li t3, 0xc + SETLEDS1('L','A','S','Y') + SETLEDS1('U','A','S','Y') +#endif + + b update_sync_mode + nop + +memc_all_sync: +#if LMB_SYNC_ENABLE +// set MC/MIPS to SYNC + nop + SETLEDS1('L','S','Y','N') +#else +// set MC/MIPS to ASYNC + li t1, 0x4 + or t3, t1 + SETLEDS1('L','A','S','Y') +#endif +#if UBUS_SYNC_ENABLE +// set MC/UBUS to SYNC + nop + SETLEDS1('U','S','Y','N') +#else +// set MC/UBUS to ASYNC + li t1, 0x8 + or t3, t1 + SETLEDS1('U','A','S','Y') +#endif + +update_sync_mode: + li t1, MISC_BASE + sw t3, MISC_MEMC_CONTROL(t1) + b 2f + nop +1: +ubus_async: + SETLEDS1('L','A','S','Y') + SETLEDS1('U','A','S','Y') + +2: + // Can Mips run in sync mode? If not, skip all below + beq t6, zero, run_async + nop + +#if MIPS_SYNC_ENABLE + /**----- Clear MIPS Async mode bit ------------------------------**/ + mfc0 t1, C0_BCM_CONFIG, 5 + and t1, ~(0x1 << 28) + mtc0 t1, C0_BCM_CONFIG, 5 + + SETLEDS1('M','S','Y','N') +#else + SETLEDS1('M','A','S','Y') +#endif + +3: + /**----- Enable RAC and LMB -------------------------------------**/ + li t0, MIPS_BASE + lw t2, MIPS_LMB_CR(t0) +#if LMB_ENABLE + or t2, LMB_EN // Enable LMB + SETLEDS1('L','M','B','E') +#else + SETLEDS1('L','M','B','D') +#endif + sw t2, MIPS_LMB_CR(t0) + + li t2, 0xFFF << RAC_UPB_SHFT // Enable prefetch for RAM address range up to 256MB + sw t2, MIPS_RAC_ARR(t0) + + lw t2, MIPS_RAC_CR0(t0) + or t2, (RAC_C_INV | RAC_I | RAC_PF_I) + sw t2, MIPS_RAC_CR0(t0) + + lw t2, MIPS_RAC_CR1(t0) + or t2, (RAC_C_INV | RAC_I | RAC_PF_I) + sw t2, MIPS_RAC_CR1(t0) + +run_async: + /**----- Enable branch prediction and non-blocking data cache ---**/ + mfc0 t1, C0_BCM_CONFIG + and t1, ~CP0_BCM_CFG_BTHD + or t1, CP0_BCM_CFG_NBK + or t1, CP0_BCM_CFG_CLF + mtc0 t1, C0_BCM_CONFIG + +#if DDR_TEST +####################################### +# Run test on DRAM using Test Engine # +####################################### +#define BACKGND_MODE_DATA 0x0 +#define BACKGND_MODE_LFSR 0x400 +#define BACKGND_MODE_PRBS 0x800 +#define BACKGND_MODE_NOT_PRBS 0xc00 +#define BACKGND_MODE_PAT 0x1000 +#define BACKGND_MODE_NOT_PAT 0x1400 + +#define VICT_MODE_PRBS 0 +#define VICT_MODE_NOT_PRBS 0x100 +#define VICT_MODE_PAT 0x200 +#define VICT_MODE_NOT_PAT 0x300 + +#define VICT_ENABLE 0x8000 +#define VICT_SWEEP_ENABLE 0x10000 +#define VICT_COUNT 0x0 + +#define PRBS_ORDER(x) ((x & 0x3) << 13) + +#define TEST_COUNT 0x1000 +#define TEST_ADDR 0x0 +#define TEST_ADDR_UPDT 0x1 +#define TEST_PATTERN0 0x5555 +#define TEST_PATTERN1 0xaaaa +#define TEST_PATTERN (TEST_PATTERN1 << 16 | TEST_PATTERN0) + +#define TEST_ENABLE 0x1 +#define TEST_DONE 0x2 +#define TEST_ERROR 0x4 +#define TEST_WRITE 0x10 +#define TEST_READ 0x0 + +#define BACKGND_DATA0 0xa5a5a5a5 +#define BACKGND_DATA1 0x5a5a5a5a +#define BACKGND_DATA2 0xa5a5a5a5 +#define BACKGND_DATA3 0x5a5a5a5a + +#define TEST_DATA0 0x02468ace +#define TEST_DATA1 0x13579bdf +#define TEST_DATA2 0x33cccc33 +#define TEST_DATA3 0x55aaaa55 + +/***** Load DDR Base *************************************/ + li t0, DDR_BASE + li t1, BACKGND_DATA0 + sw t1, DDR_CTL_TEST_DATA0(t0) + li t1, BACKGND_DATA1 + sw t1, DDR_CTL_TEST_DATA1(t0) + li t1, BACKGND_DATA2 + sw t1, DDR_CTL_TEST_DATA2(t0) + li t1, BACKGND_DATA3 + sw t1, DDR_CTL_TEST_DATA3(t0) + li t1, TEST_COUNT + li t2, VICT_COUNT + or t1, t2 # add victim count value + sw t1, DDR_CTL_TEST_COUNT(t0) + li t1, TEST_ADDR + sw t1, DDR_CTL_TEST_ADDR(t0) + li t1, TEST_ADDR_UPDT + sw t1, DDR_CTL_TEST_ADDR_UPDT(t0) + li t1, TEST_PATTERN + sw t1, DDR_CTL_TEST_PAT(t0) + +# Write a background pattern first + li t1, BACKGND_MODE_DATA + li t2, TEST_WRITE + or t1, t2 + li t2, TEST_ENABLE + or t1, t2 + sw t1, DDR_CTL_TEST_CFG1(t0) + + li t2, 0x2 + li t3, MISC_BASE + + li t5, 0x10000 +2: li t1, 0x100 +1: addiu t1, -1 + bnez t1, 1b + nop + + lw t4, MISC_MEMC_CONTROL(t3) + and t4, 0x2 + beq t4, t2, backgnd_write_done + nop + addiu t5, -1 + bnez t5, 2b + nop + +# Background write operation is finished + +backgnd_write_done: + li t1, TEST_DATA0 + sw t1, DDR_CTL_TEST_DATA0(t0) + li t1, TEST_DATA1 + sw t1, DDR_CTL_TEST_DATA1(t0) + li t1, TEST_DATA2 + sw t1, DDR_CTL_TEST_DATA2(t0) + li t1, TEST_DATA3 + sw t1, DDR_CTL_TEST_DATA3(t0) + li t1, TEST_COUNT + li t2, VICT_COUNT + or t1, t2 # add victim count value + sw t1, DDR_CTL_TEST_COUNT(t0) + li t1, TEST_ADDR + sw t1, DDR_CTL_TEST_ADDR(t0) + li t1, TEST_ADDR_UPDT + sw t1, DDR_CTL_TEST_ADDR_UPDT(t0) + li t1, TEST_PATTERN + sw t1, DDR_CTL_TEST_PAT(t0) + +# li t1, BACKGND_MODE_DATA +# li t1, BACKGND_MODE_PAT +# li t2, VICT_MODE_NOT_PAT + li t1, BACKGND_MODE_PRBS + li t2, VICT_MODE_NOT_PRBS + + or t1, t2 + li t2, VICT_ENABLE + or t1, t2 + li t2, VICT_SWEEP_ENABLE + or t1, t2 + li t2, PRBS_ORDER(0) + or t1, t2 + li t2, TEST_WRITE + or t1, t2 + li t2, TEST_ENABLE + or t1, t2 + sw t1, DDR_CTL_TEST_CFG1(t0) + + li t2, 0x2 + li t3, MISC_BASE + + li t5, 0x10000 +2: li t1, 0x100 +1: addiu t1, -1 + bnez t1, 1b + nop + + lw t4, MISC_MEMC_CONTROL(t3) + and t4, 0x2 + beq t4, t2, test_write_done + nop + addiu t5, -1 + bnez t5, 2b + nop + +# Test write operation is finished + +test_write_done: + li t1, TEST_DATA0 + sw t1, DDR_CTL_TEST_DATA0(t0) + li t1, TEST_DATA1 + sw t1, DDR_CTL_TEST_DATA1(t0) + li t1, TEST_DATA2 + sw t1, DDR_CTL_TEST_DATA2(t0) + li t1, TEST_DATA3 + sw t1, DDR_CTL_TEST_DATA3(t0) + li t1, TEST_COUNT + li t2, VICT_COUNT + or t1, t2 # add victim count value + sw t1, DDR_CTL_TEST_COUNT(t0) + li t1, TEST_ADDR + sw t1, DDR_CTL_TEST_ADDR(t0) + li t1, TEST_ADDR_UPDT + sw t1, DDR_CTL_TEST_ADDR_UPDT(t0) + li t1, TEST_PATTERN + sw t1, DDR_CTL_TEST_PAT(t0) + +# li t1, BACKGND_MODE_DATA +# li t1, BACKGND_MODE_PAT +# li t2, VICT_MODE_NOT_PAT + li t1, BACKGND_MODE_PRBS + li t2, VICT_MODE_NOT_PRBS + + or t1, t2 + li t2, VICT_ENABLE + or t1, t2 + li t2, VICT_SWEEP_ENABLE + or t1, t2 + li t2, PRBS_ORDER(0) + or t1, t2 + li t2, TEST_READ + or t1, t2 + li t2, TEST_ENABLE + or t1, t2 + sw t1, DDR_CTL_TEST_CFG1(t0) + + li t3, MISC_BASE + li t2, 0x2 + + li t5, 0x10000 +2: li t1, 0x100 +1: addiu t1, -1 + bnez t1, 1b + nop + + lw t4, MISC_MEMC_CONTROL(t3) + and t4, 0x2 + beq t4, t2, test_read_done + nop + addiu t5, -1 + bnez t5, 2b + nop + +# Test read operation is finished + +test_read_done: + lw t1, DDR_CTL_TEST_CFG1(t0) + srl t1, 2 + and t1, 1 + beq t1, zero, test_passed + nop + +test_failed: + SETLEDS1('F','A','I','L') + b 1f + nop +test_passed: + SETLEDS1('P','A','S','S') +1: + SETLEDS1('-','-','-', '-') +#endif + + move ra,s0 + j ra + nop + + .set reorder + +END(board_draminit) + +/* ********************************************************************* + * BOARD_SETLEDS(x) + * + * Set LEDs for boot-time progress indication. Not used if + * the board does not have progress LEDs. This routine + * must not call any other routines, since it may be invoked + * either from KSEG0 or KSEG1 and it may be invoked + * whether or not the icache is operational. + * + * Input parameters: + * a0 - LED value (8 bits per character, 4 characters) + * + * Return value: + * nothing + * + * Registers used: + * t7,t8,t9 + ********************************************************************* */ +LEAF(board_setleds) +#if 1 + li t7, UART_BASE + li t8, TXFIFOEMT + +1: lh t9, UART0INTSTAT(t7) + and t9, t8 + bne t9, t8, 1b + + srl t8, a0, 24 + sb t8, UART0DATA(t7) + srl t8, a0, 16 + sb t8, UART0DATA(t7) + srl t8, a0, 8 + sb t8, UART0DATA(t7) + sb a0, UART0DATA(t7) + li a0, '\r' + sb a0, UART0DATA(t7) + li a0, '\n' + sb a0, UART0DATA(t7) +#endif + j ra +END(board_setleds) + +/* ********************************************************************* + * BCMCORE_TP1_SWITCH() + * + * Check if the thread switch is required. If we are already + * running on thread 1 this function will do nothing and just return + * If we are running on thread 0 this function will take thread 1 + * out of reset and put thread 0 to sleep waiting for singnal from + * thread 1. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ +LEAF(bcmcore_tp1_switch) + +#if defined(_BCM96328_) + li t1, OTP_BASE + addi t1, OTP_USER_BITS + addi t1, 0xc - ((OTP_TP1_DISABLE_BIT / 8) & ~3) + lw t0, 0(t1) + andi t0, 1 << (OTP_TP1_DISABLE_BIT % 32) + beqz t0, 1f + j ra +1: +#endif + mfc0 t1, C0_BCM_CONFIG, 3 + li t2, CP0_CMT_TPID + and t1, t2 + bnez t1, tp1 # Already running on thread 1 + +# Start TP1 +# Set boot address for TP1 + li t1, MIPS_BASE + li t2, 0x98000000 | ENABLE_ALT_BV + sw t2, MIPS_TP1_ALT_BV(t1) + +# Set a flag so we can wait for TP1 to catch up + li t1, 0x0 + mtc0 t1, $31 # CO_DESAVE + +# Take TP1 out of reset + mfc0 t1, C0_BCM_CONFIG, 2 + or t1, CP0_CMT_RSTSE + mtc0 t1, C0_BCM_CONFIG, 2 + + /* wait until second thread catches up with the first */ +waittp1: + mfc0 t0, $31 # CO_DESAVE + beqz t0, waittp1 + + li t0, THREAD_NUM_ADDRESS + FIXUP(t0) + lw t0, 0(t0) + li t1, 1 + bne t0, t1, return # Linux will run on TP0, continue running bootloader + +# Voice will run on TP0. Set it up and put it to sleep + + # enable interrupts and enable SW IRQ 0 + li t0, M_SR_IE | M_SR_IBIT1 + mtc0 t0, C0_SR + + # Set up to use alternate exception vector 0x80000200 + li t0, M_CAUSE_IV + mtc0 t0, C0_CAUSE + + mfc0 t1, C0_BCM_CONFIG, 1 + # set all ints except IRQ1 to TP1 and cross over SW IRQ 0 + or t1, (CP0_CMT_XIR_4 | CP0_CMT_XIR_3 | CP0_CMT_XIR_2 | CP0_CMT_XIR_0 | CP0_CMT_SIR_0 | CP0_CMT_NMIR_TP1) + mtc0 t1, C0_BCM_CONFIG, 1 + + mfc0 t1, C0_BCM_CONFIG, 2 + # Set debug on TP1, give priority to TP0, and + # set TLB exception serialization to ignore SCNT value in CP0 reg22 sel 4 + and t1, ~CP0_CMT_TPS_MASK; + or t1, (CP0_CMT_DSU_TP1 | CP0_CMT_PRIO_TP0 | (1 << CP0_CMT_TPS_SHFT)) + mtc0 t1, C0_BCM_CONFIG, 2 + + # Enable Data RAC on TP0 + li t1, MIPS_BASE + lw t2, MIPS_RAC_CR0(t1) + or t2, (RAC_D | RAC_PF_D) + sw t2, MIPS_RAC_CR0(t1) + +2: + b wait_for_wake + +tp1: +# Running on TP1.... +# First signal to TP0 that TP1 is up + li t1, 0x1 + mtc0 t1, $31 # CO_DESAVE + + li t0, THREAD_NUM_ADDRESS + FIXUP(t0) + lw t0, 0(t0) + li t1, 1 + beq t0, t1, return # Linux will run on TP1, continue running bootloader + +# Voice will run on TP1. Set it up and put it to sleep + + # enable interrupts and enable SW IRQ 0 + li t0, M_SR_IE | M_SR_IBIT1 + mtc0 t0, C0_SR + + # Set up to use alternate exception vector 0x80000200 + li t0, M_CAUSE_IV + mtc0 t0, C0_CAUSE + + mfc0 t1, C0_BCM_CONFIG, 1 + # set IRQ1 to TP1 and cross over SW IRQ 0 + or t1, (CP0_CMT_XIR_1 | CP0_CMT_SIR_0 | CP0_CMT_NMIR_TP0) + mtc0 t1, C0_BCM_CONFIG, 1 + + mfc0 t1, C0_BCM_CONFIG, 2 + # Set debug on TP0, give priority to TP1, and + # set TLB exception serialization to ignore SCNT value in CP0 reg22 sel 4 + and t1, ~CP0_CMT_TPS_MASK; + or t1, (CP0_CMT_PRIO_TP1 | (1 << CP0_CMT_TPS_SHFT)) + mtc0 t1, C0_BCM_CONFIG, 2 + + # Enable Data RAC on TP1 + li t1, MIPS_BASE + lw t2, MIPS_RAC_CR1(t1) + or t2, (RAC_D | RAC_PF_D) + sw t2, MIPS_RAC_CR1(t1) + b 2b + +return: + j ra + +END(bcmcore_tp1_switch) + +# align this code to cache line. NAND flash is not memory mapped after system boots +# so when we are signaling to the second TP to wake we need +# jal instruction to be in cache + .align 4 +LEAF(wait_for_wake) + sync + wait # wait for interrupt + jal t8 # jump to entry point +END(wait_for_wake) diff --git a/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_main.c b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_main.c new file mode 100755 index 0000000..201d6d8 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_main.c @@ -0,0 +1,649 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Main Module File: bcm63xxBoot_main.c + * + * This module contains the main "C" routine for CFE bootstrap loader + * and decompressor to decompress the real CFE to ram and jump over. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * Revised: seanl + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#include "lib_types.h" +#include "lib_string.h" +#include "lib_malloc.h" +#include "lib_printf.h" + +#include "cfe_iocb.h" +#include "cfe_device.h" +#include "cfe_console.h" +#include "cfe_timer.h" + +#include "env_subr.h" +#include "ui_command.h" +#include "cfe_mem.h" +#include "cfe.h" + +#include "bsp_config.h" +#include "bcm_hwdefs.h" +#include "bcm_map.h" + +#include "exception.h" + +#include "segtable.h" + +#include "initdata.h" + +#if defined(_BCM96368_) || defined(_BCM96362_) || defined(_BCM96328_) || defined(_BCM96816_) +#include "flash_api.h" +#include "jffs2.h" +#endif + +#if CFG_PCI +#include "pcivar.h" +#endif + + + +int cfe_size_ram(void); +inline static int is_aliased(int max_bits) __attribute__((always_inline)); + +/* ********************************************************************* + * Constants + ********************************************************************* */ + +#ifndef CFG_STACK_SIZE +#define STACK_SIZE 8192 +#else +#define STACK_SIZE ((CFG_STACK_SIZE+1023) & ~1023) +#endif + +inline static int is_aliased(int max_bits) +{ + volatile uint32 *mem_base; + volatile uint32 *test_ptr; + uint32 tmp; + int bit; + int res = 0; + + mem_base = (uint32*)DRAM_BASE_NOCACHE; + + *mem_base = 0; + + for (bit = 8; bit < max_bits; bit++) { + test_ptr = (uint32*)((uint32)mem_base | 1 << bit); + /* ram may contain useful data, save location before modifying */ + tmp = *test_ptr; + *test_ptr = -1; + if (*mem_base == *test_ptr) { + *test_ptr = tmp; + res = 1; + break; + } + *test_ptr = tmp; + } + return res; +} + +#define MEMC_MAX_ROWS 14 + +int cfe_size_ram(void) +{ +#if !(defined(_BCM96328_) || defined (_BCM96362_) || defined(_BCM96816_)) + uint32 col_bits, row_bits, bus_bits, bank_bits; + uint32 size; + + /* Bus width is configured during early boot */ + if (((MEMC->Config & MEMC_WIDTH_MASK) >> MEMC_WIDTH_SHFT) == MEMC_32BIT_BUS) + bus_bits = 2; + else + bus_bits = 1; + + bank_bits = 2; + /* Start from setting to the lowest possible configuration */ + col_bits = 8; + row_bits = 11; + + MEMC->Config &= ~MEMC_COL_MASK; + MEMC->Config |= ((col_bits - 8) << MEMC_COL_SHFT); + + MEMC->Config &= ~MEMC_ROW_MASK; + MEMC->Config |= ((row_bits - 11) << MEMC_ROW_SHFT); + + /* Determine number of rows */ + for (row_bits = 12; row_bits <= MEMC_MAX_ROWS; row_bits++) { + MEMC->Config &= ~MEMC_ROW_MASK; + MEMC->Config |= ((row_bits - 11) << MEMC_ROW_SHFT); + /* check if this address bit is valid */ + if (is_aliased (col_bits + row_bits + bus_bits + bank_bits)) + break; + } + row_bits -= 1; + MEMC->Config &= ~MEMC_ROW_MASK; + MEMC->Config |= ((row_bits - 11) << MEMC_ROW_SHFT); + + /* Determine number of columns */ + for (col_bits = 9; col_bits <= 11; col_bits++) { + MEMC->Config &= ~MEMC_COL_MASK; + MEMC->Config |= ((col_bits - 8) << MEMC_COL_SHFT); + /* check if this address bit is valid */ + if (is_aliased (col_bits + row_bits + bus_bits + bank_bits)) + break; + } + col_bits -= 1; + MEMC->Config &= ~MEMC_COL_MASK; + MEMC->Config |= ((col_bits - 8) << MEMC_COL_SHFT); + + /* Compute memory size in MB */ + size = 1 << (bus_bits + col_bits + row_bits + bank_bits - 20); + + return size; +#else + return (DDR->CSEND << 24); +#endif +} + +// fake functions for not to modifying init_mips.S +void _exc_entry(void); +void cfe_command_restart(void); +void cfe_doxreq(void); + +void _exc_entry(void) +{ +} + +void cfe_command_restart(void) +{ +} +void cfe_doxreq(void) +{ +} + +/* ********************************************************************* + * Externs + ********************************************************************* */ + +void cfe_main(int,int); + +/* ********************************************************************* + * Globals + ********************************************************************* */ + +void cfe_ledstr(const char *leds) +{ +} + +#if !defined(CONFIG_BRCM_IKOS) +extern void _binArrayStart(void); +extern void _binArrayEnd(void); +extern int decompressLZMA(unsigned char *in, unsigned insize, unsigned char *out, unsigned outsize); + +#if (INC_NAND_FLASH_DRIVER==1) || (INC_SPI_PROG_NAND==1) +#define je16_to_cpu(x) ((x).v16) +#define je32_to_cpu(x) ((x).v32) +extern void rom_nand_flash_init(void); +extern int nand_flash_get_sector_size(unsigned short sector); +extern int nand_flash_get_numsectors(void); +extern int nand_flash_read_buf(unsigned short blk, int offset, + unsigned char *buffer, int len); +extern void board_setleds(unsigned long); + +void *lib_memcpy(void *dest,const void *src,size_t cnt) +{ + unsigned char *d; + const unsigned char *s; + + d = (unsigned char *) dest; + s = (const unsigned char *) src; + + while (cnt) { + *d++ = *s++; + cnt--; + } + + return dest; +} + +int lib_memcmp(const void *dest,const void *src,size_t cnt) +{ + const unsigned char *d; + const unsigned char *s; + + d = (const unsigned char *) dest; + s = (const unsigned char *) src; + + while (cnt) { + if (*d < *s) return -1; + if (*d > *s) return 1; + d++; s++; cnt--; + } + + return 0; +} + +#if (INC_NAND_FLASH_DRIVER==1) +/* Find uncompressed file cferam.bin on the JFFS2 file system, load it into + * memory and jump to its entry point function. + */ +char g_fname[] = NAND_CFE_RAM_NAME; +int g_fname_actual_len = sizeof(g_fname) - 1; +int g_fname_cmp_len = sizeof(g_fname) - 4; /* last three are digits */ +static void bootImageFromNand(void) +{ + const unsigned long bv_invalid = 0xfffffff; + const int max_not_jffs2 = 10; + + struct rootfs_info + { + int rootfs; + int start_blk; + int end_blk; + unsigned long boot_val; + unsigned long ino; + } rfs_info[2], *prfs_info[2], *rfsi; + + unsigned char *buf = (unsigned char *) mem_heapstart; + unsigned long version = 0; + struct jffs2_raw_dirent *pdir; + struct jffs2_raw_inode *pino; + unsigned char *p; + int i, j, k, done, not_jffs2; + int num_blks; + int len; + int boot_prev; + PNVRAM_DATA nd; + static int err0=0, err1=1; + + rom_nand_flash_init(); + num_blks = nand_flash_get_numsectors(); + len = nand_flash_get_sector_size(0); + nd = (PNVRAM_DATA) (buf + len); + + NAND->NandNandBootConfig = NBC_AUTO_DEV_ID_CFG | 0x101; + NAND->NandCsNandXor = 1; + + memcpy((unsigned char *) nd, (unsigned char *) + FLASH_BASE + NVRAM_DATA_OFFSET, sizeof(NVRAM_DATA)); + + NAND->NandNandBootConfig = NBC_AUTO_DEV_ID_CFG | 0x2; + NAND->NandCsNandXor = 0; + + /* Look at config to determine whether to boot current or previous image.*/ + for( i = 0, p = (unsigned char *) nd->szBootline, boot_prev = 0; + i < NVRAM_BOOTLINE_LEN; i++, p++ ) + { + if( p[0] == ' ' && p[1] == 'p' && p[2] == '=' ) + { + boot_prev = p[3] - '0'; + if( boot_prev != 0 && boot_prev != 1 ) + boot_prev = '0'; + break; + } + } + + /* Find the CFE ram inode entry point for both root file systems. */ + board_setleds((boot_prev == 0) ? 0x4e414e30 : 0x4e414e31); + for( k = 0, rfsi = rfs_info; k < 2; k++, rfsi++ ) + { + version = 0; + not_jffs2 = 0; + rfsi->rootfs = k + NP_ROOTFS_1; + rfsi->boot_val = bv_invalid; + if( nd->ulNandPartOfsKb[rfsi->rootfs] > 0 && + nd->ulNandPartOfsKb[rfsi->rootfs] < ((num_blks * len) / 1024)) + { + rfsi->start_blk = nd->ulNandPartOfsKb[rfsi->rootfs] / (len/1024); + rfsi->end_blk = rfsi->start_blk + + (nd->ulNandPartSizeKb[rfsi->rootfs] / (len / 1024)); + } + else + rfsi->start_blk = rfsi->end_blk = 0; + + if( rfsi->start_blk == 0 || rfsi->start_blk >= rfsi->end_blk || + rfsi->start_blk >= num_blks || rfsi->end_blk >= num_blks ) + { + /* NVRAM_DATA fields for this rootfs are not valid. */ + if( k == 0 ) + { + /* Skip this rootfs. */ + board_setleds(0x4e414e36); + continue; + } + + if( rfs_info[0].boot_val == bv_invalid ) + { + /* File system info cannot be found for either rootfs. + * NVRAM_DATA may not be set. Use default values. + */ + board_setleds(0x4e414e37); + rfsi = rfs_info; + rfsi->start_blk = 1; + rfsi->end_blk = num_blks; + } + } + + /* Find the directory entry. */ + for( i = rfsi->start_blk, done = 0; i < rfsi->end_blk && done == 0; i++ ) + { + /* This loop sequentially reads a NAND flash block into memory and + * processes it. + */ + if( nand_flash_read_buf(i, 0, buf, len) > 0 ) + { + /* This loop reads inodes in a block. */ + p = buf; + while( p < buf + len ) + { + pdir = (struct jffs2_raw_dirent *) p; + if( je16_to_cpu(pdir->magic) == JFFS2_MAGIC_BITMASK ) + { + if( je16_to_cpu(pdir->nodetype) == + JFFS2_NODETYPE_DIRENT && + g_fname_actual_len == pdir->nsize && + !memcmp(g_fname, pdir->name, g_fname_cmp_len) ) + { + /* The desired directory was found. */ + if( je32_to_cpu(pdir->version) > version ) + { + if( (rfsi->ino = je32_to_cpu(pdir->ino)) != 0 ) + { + unsigned char *fname = + pdir->name + g_fname_cmp_len; + rfsi->boot_val = + ((fname[0] - '0') * 100) + + ((fname[1] - '0') * 10) + + ((fname[2] - '0') * 1); + version = je32_to_cpu(pdir->version); + + board_setleds(0x42540000 + + ((unsigned long) fname[1] << 8) + + (unsigned long) fname[2]); + + /* Setting 'done = 1' assumes there is only + * one version of the directory entry. This + * may not be correct if the file is + * updated after it was initially flashed. + * + * TBD. Look for a higher version of the + * directory entry without searching the + * entire flash part. + */ + done = 1; + break; + } + } + } + + p += (je32_to_cpu(pdir->totlen) + 0x03) & ~0x03; + not_jffs2 = 0; + } + else + { + if( not_jffs2++ > max_not_jffs2 ) + { + /* No JFFS2 magic bitmask for consecutive blocks. + * Assume this partion does not have a file system + * on it. + */ + board_setleds(0x53544F50); + done = 1; + } + break; + } + } + } + else + { + if(!err0) + { + err0=1; + board_setleds(0x45525230); + } + } + } + board_setleds(0x4e414e39); + } + + /* Set the rfs_info to the index to boot from. */ + if( (boot_prev == 0 && rfs_info[0].boot_val > rfs_info[1].boot_val) || + (boot_prev == 1 && rfs_info[0].boot_val < rfs_info[1].boot_val) || + rfs_info[1].boot_val == bv_invalid ) + { + /* Boot from the most recent image. */ + prfs_info[0] = &rfs_info[0]; + prfs_info[1] = &rfs_info[1]; + } + else + { + /* Boot from the previous image. */ + prfs_info[0] = &rfs_info[1]; + prfs_info[1] = &rfs_info[0]; + } + + /* If the directory entry for the desired file, which is the CFE RAM image, + * is found, read it into memory and jump to its entry point function. + * This loop checks for CFE RAM image in two possible rootfs file sytems. + */ + for( k = 0; k < 2; k++ ) + { + unsigned char *pucDest = NULL; + unsigned char *pucEntry = NULL; + long isize = 0; + + board_setleds(0x4e414e33); + rfsi = prfs_info[k]; + if( rfsi->boot_val == bv_invalid ) + continue; + + /* When j == 0, get the first inode to find the entry point address. + * When j == 1, read the file contents into memory. + */ + for( j = 0; j < 2; j++ ) + { + /* This loop sequentially reads a NAND flash block into memory and + * processes it. + */ + for(i = rfsi->start_blk, done = 0; i<rfsi->end_blk && done==0; i++) + { + if( nand_flash_read_buf(i, 0, buf, len) > 0 ) + { + /* This loop reads inodes in a block. */ + p = buf; + while( p < buf + len ) + { + /* Verify the first short word is the JFFS2 magic + * number. + */ + pino = (struct jffs2_raw_inode *) p; + if( je16_to_cpu(pino->magic) == JFFS2_MAGIC_BITMASK ) + { + if( je16_to_cpu(pino->nodetype) == + JFFS2_NODETYPE_INODE && + je32_to_cpu(pino->ino) == rfsi->ino ) + { + unsigned long size = je32_to_cpu(pino->dsize); + unsigned long ofs = je32_to_cpu(pino->offset); + + if( size ) + { + /* A node of the CFE RAM file was found + * with data. */ + if( pucDest == NULL ) + { + /* The entry point and copy destination + * addresses have not been obtained. + * If this is the first node of the CFE + * RAM file, obtain this information. + */ + if( ofs == 0 ) + { + /* The first 12 bytes contain a + * header. The first word is the + * entry point address. + */ + pucEntry = (unsigned char *) + *(unsigned long *) pino->data; + pucDest = pucEntry - 12; + isize = je32_to_cpu(pino->isize); + done = 1; + board_setleds(0x52465330 | + rfsi->rootfs); + break; + } + } + else + { + /* Copy the image to memory. Stop when + * the entire image has been copied. + */ + memcpy(pucDest+ofs, pino->data, size); + if( (isize -= size) <= 0 ) + { + done = 1; + break; + } + } + } + } + + /* Skip to the next inode entry. */ + p += (je32_to_cpu(pino->totlen) + 0x03) & ~0x03; + } + else + break; + } + } + else + { + if(!err1) + { + err1=1; + board_setleds(0x45525231); + } + } + } + } + + if( pucEntry && isize <= 0 ) + { + board_setleds(0x4e414e35); + + /* Save the rootfs partition that the CFE RAM image boots from + * at the memory location before the CFE RAM load address. The + * CFE RAM image uses this value to determine the partition to + * flash a new rootfs to. + */ + *(pucEntry - 1) = (unsigned char) rfsi->rootfs; + + cfe_launch((unsigned long) pucEntry); // never return... + } + board_setleds(0x4e414e38); + } + + /* Error occurred. */ + board_setleds(0x44494530); + while(1); +} +#endif +#endif + +/* ********************************************************************* + * cfe_main(a,b) + * + * It's gotta start somewhere. + * Input parameters: + * a,b - not used + * + * Return value: + * does not return + ********************************************************************* */ + +void cfe_main(int a,int b) +{ + unsigned char *pucSrc; + unsigned char *pucDst; + unsigned int *entryPoint; + unsigned int binArrayStart = (unsigned int) _binArrayStart; + unsigned int binArrayEnd = (unsigned int) _binArrayEnd; + unsigned int dataLen = binArrayEnd - binArrayStart - 4; + int ret; + + KMEMINIT((unsigned char *) (uint32_t) mem_heapstart, + ((CFG_HEAP_SIZE)*1024)); + +#if (INC_NAND_FLASH_DRIVER==1) && (defined(_BCM96816_) || defined(_BCM96362_) || defined(_BCM96328_)) + if( ((MISC->miscStrapBus & MISC_STRAP_BUS_BOOT_SEL_MASK) >> + MISC_STRAP_BUS_BOOT_SEL_SHIFT) == MISC_STRAP_BUS_BOOT_NAND ) + { + bootImageFromNand(); /* Will not return. */ + } +#elif (INC_NAND_FLASH_DRIVER==1) && defined(_BCM96368_) + if( ((GPIO->StrapBus & MISC_STRAP_BUS_BOOT_SEL_MASK) >> + MISC_STRAP_BUS_BOOT_SEL_SHIFT) == MISC_STRAP_BUS_BOOT_NAND ) + { + bootImageFromNand(); /* Will not return. */ + } +#endif + + entryPoint = (unsigned int*) binArrayStart; + pucSrc = (unsigned char *) (binArrayStart + 4); + + pucDst = (unsigned char *) *entryPoint; + ret = decompressLZMA((unsigned char*)pucSrc, + (unsigned int)dataLen, + (unsigned char *) pucDst, + 23*1024*1024); + + if (ret != 0) + while (1); // if not decompressed ok, loop for EJTAG + + cfe_launch((unsigned long) pucDst); // never return... +} +#else +/* 0x694b6f31 (iKo1) is replaced with actual address during the build process.*/ +unsigned long cfeRamStartAddr=0x694b6f31; +void cfe_main(int a,int b) +{ + cfe_size_ram(); + cfe_launch(cfeRamStartAddr); // never return... +} +#endif + diff --git a/cfe/cfe/arch/mips/board/bcm63xx_rom/src/memtest.c b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/memtest.c new file mode 100755 index 0000000..310fb40 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/memtest.c @@ -0,0 +1,1031 @@ +/* + *----------------------------------------------------------------------------* + * Collection of Memory Tests. + *----------------------------------------------------------------------------* + */ + +// +// NOTE: Blatant inlining ... (not sure whether caller supports EABI calls). +// WARNING CFE: Must NOT use function calls !!! +// +#define _ALWAYS_INLINE_ __attribute__((always_inline)) +#define _INLINE_ inline static + +typedef enum memTestResult { + MEMTEST_FAILURE = 0, + MEMTEST_SUCCESS, + MEMTEST_ERROR, +} MemTestResult_t; + +/* ------------------------------------------------------------------------- */ + +#undef PATTERN +#define PATTERN(x) PATTERN_##x, + +/* + * For each pattern listed, the inverse pattern is also automatically used. + * E.g. 0x55555555, the inverse of defined 0xAAAAAAAA is covered. + */ +typedef enum pattern { + PATTERN(0x00000000) + PATTERN(0xAAAAAAAA) + PATTERN(0xCCCCCCCC) + PATTERN(0x77777777) + PATTERN(0xF0F0F0F0) + PATTERN(0xFF00FF00) + PATTERN(0xFFFF0000) + PATTERN(0x01234567) + PATTERN(0x89ABCDEF) + PATTERN_MAX, +} Pattern_t; + +#undef PATTERN +#define PATTERN(x) x, +const uint32_t pattern[] = { + PATTERN(0x00000000) + PATTERN(0xAAAAAAAA) + PATTERN(0xCCCCCCCC) + PATTERN(0x77777777) + PATTERN(0xF0F0F0F0) + PATTERN(0xFF00FF00) + PATTERN(0xFFFF0000) + PATTERN(0x01234567) + PATTERN(0x89ABCDEF) + PATTERN_MAX, +}; + +/* ------------------------------------------------------------------------- */ + +#ifndef NBBY +#define NBBY 8 /* FreeBSD style: Number Bits per BYte */ +#endif + +/* ------------------------------------------------------------------------- */ + +#define NBITS(type) (sizeof(type) * NBBY) +#define NBITVAL(nbits) (1 << (nbits)) +#define MAXBITVAL(nbits) ( NBITVAL(nbits) - 1) +#define NBITMASK(nbits) MAXBITVAL(nbits) +#define MAXNBVAL(nbyte) MAXBITVAL((nbyte) * NBBY) + +#define DIVBY(val32,by) ((val32)>>(by)) +#define MODBY(val32,by) ((val32) & ((1 <<(by)) - 1) ) + +#define IS_POWEROF2(val32) ( (((val32)-1) & (val32)) == 0 ) + +#define ROUNDDN(addr, align) ( (addr) & ~((align) - 1) ) +#define ROUNDUP(addr, align) ( ((addr) + (align) - 1) & ~((align) - 1) ) +//#define ROUNDUP(x,y) ((((x)+((y)-1))/(y))*(y)) +#define ALIGN_ADDR(addr, bytes) (void *)( ((uint32_t *)(addr) + (bytes) - 1) \ + & ~((bytes) - 1) ) +#define IS_ALIGNED(addr, bytes) (((uint32_t)(addr) & ((bytes)-1)) == 0) + +#define OFFSET_OF(stype,member) ((uint32_t) &((struct stype *)0)->member) +#define RELOC(base,stype,member) ((base) + OFFSET_OF(stype, member)) + +#define RROTATE32(val32) (((val32) << 31) | ((val32) >> 1)) +#define LROTATE32(val32) (((val32) << 1) | ((val32) >> 31)) + +/* ------------------------------------------------------------------------- */ + +/* Aligned (32bit register) read/write access */ +#define RD16(addr16) (*(volatile uint32_t *)(addr16)) +#define WR16(addr16,val16) (*(volatile uint32_t *)(addr16))=(val16) +#define RD32(addr32) (*(volatile uint32_t *)(addr32)) +#define WR32(addr32,val32) (*(volatile uint32_t *)(addr32))=(val32) + +/*---------------------------------------------------------------------------*/ + +/* Forward declaration */ +_INLINE_ void fill_memory( uint32_t * addr, uint32_t bytes, uint32_t fill32) + _ALWAYS_INLINE_; +_INLINE_ void fill_alt_memory(uint32_t * addr, uint32_t bytes, + uint32_t fillA32, uint32_t fillB32) _ALWAYS_INLINE_; + +void fill_memory( uint32_t * addr, uint32_t bytes, uint32_t fill32) +{ + uint32_t * at, * end_p; + uint32_t words; + words = bytes / sizeof(uint32_t); + if ( words == 0 ) return; + + end_p = addr + words; + for ( at = addr; at < end_p; at++ ) + WR32( at, fill32 ); +} + +void fill_alt_memory( uint32_t * addr, uint32_t bytes, + uint32_t fillA32, uint32_t fillB32) +{ + uint32_t * at, * end_p; + uint32_t words; + words = bytes / sizeof(uint32_t); + words = ROUNDDN( words, 2 ); + if ( words == 0 ) return; + + end_p = addr + words; + for ( at = addr; at < end_p; at+=2 ) + { + WR32( at+0, fillA32 ); + WR32( at+1, fillB32 ); + } +} + +/* Forward declaration */ +_INLINE_ MemTestResult_t scanWordValue( uint32_t * addr, uint32_t bytes, + uint32_t pat32 ) _ALWAYS_INLINE_; +_INLINE_ MemTestResult_t scanBulkValue( uint32_t * addr, uint32_t bytes, + uint32_t pat32 ) _ALWAYS_INLINE_; +_INLINE_ MemTestResult_t scanBulkAltInv( uint32_t * addr, uint32_t bytes, + uint32_t pat32 ) _ALWAYS_INLINE_; +_INLINE_ MemTestResult_t scanWordSelf( uint32_t * addr, uint32_t bytes ) + _ALWAYS_INLINE_; +_INLINE_ MemTestResult_t scanBulkSelf( uint32_t * addr, uint32_t bytes ) + _ALWAYS_INLINE_; +_INLINE_ MemTestResult_t slidingAltInv( uint32_t * addr, uint32_t bytes, + uint32_t pat32 ) _ALWAYS_INLINE_; +_INLINE_ MemTestResult_t slidingDiag( uint32_t * addr, uint32_t bytes, + uint32_t pat32 ) _ALWAYS_INLINE_; +_INLINE_ MemTestResult_t memoryBulkCopy( uint32_t * saddr, uint32_t * daddr, + uint32_t bytes ) _ALWAYS_INLINE_; + +/* + *----------------------------------------------------------------------------- + * Function: scanWordValue + * + * Description: + * 4 Passes are conducted on the memory region. + * Pass 1. In INcreasing memory address, write a word with value and verify. + * Pass 2. In DEcreasing memory address, write a word with value and verify. + * Pass 3. In INcreasing memory address, write a word with INVERSE and verify. + * Pass 4. In DEcreasing memory address, write a word with INVERSE and verify. + * Pass 5. In INcreasing shifted memory address, write word with value verify. + * Pass 6. In INcreasing shifted memory address, write word with INVERSE verify. + * + * Parameters: + * addr: word aligned pointer to memory region + * bytes: size in bytes of memory region to test + * pat32: 32bit pattern, e.g. 0x0U, 0xAAAAAAAA, 0xFF00FF00, 0xFFFF0000, + * 0xF0F0F0F0, 0xC3C3C3C3, 0x87878787 + *----------------------------------------------------------------------------- + */ +MemTestResult_t scanWordValue( uint32_t * addr, uint32_t bytes, uint32_t pat32 ) +{ + volatile uint32_t * at, * end_p; + uint32_t expected, read, words; + uint32_t shift; + + if ( ! IS_ALIGNED(addr,4) ) return MEMTEST_ERROR; + + words = bytes / sizeof(uint32_t); /* in whole words (4byte multiple) */ + if ( words == 0 ) + return MEMTEST_ERROR; + + expected = pat32; /* ORIGINAL value */ + + /* INCREASING traversal */ + end_p = addr + words; + for ( at = addr; at < end_p; at++ ) + { + WR32( at, expected ); + read = RD32(at); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + } + + /* DECREASING traversal */ + end_p = addr; + for ( at = addr + words - 1; at >= end_p; at-- ) + { + WR32( at, expected ); + read = RD32(at); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + } + + expected = ~pat32; /* INVERSE value */ + + /* INCREASING traversal */ + end_p = addr + words; + for ( at = addr; at < end_p; at++ ) + { + WR32( at, expected ); + read = RD32(at); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + } + + /* DECREASING traversal */ + end_p = addr; + for ( at = addr + words - 1; at >= end_p; at-- ) + { + WR32( at, expected ); + read = RD32(at); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + } + + /* PASS 5: Shifting address walk, ORIGINAL */ + expected = pat32; /* ORIGINAL value */ + + end_p = addr + words; + shift = sizeof(uint32_t); + for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift ) + { + WR32( at, expected ); + WR32( addr, ~expected ); /* noise at base addr */ + read = RD32(at); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + } + + expected = ~pat32; /* INVERSE value */ + + /* PASS 6: Shifting address walk, INVERSE */ + end_p = addr + words; + shift = sizeof(uint32_t); + for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift ) + { + WR32( at, expected ); + WR32( addr, ~expected ); /* noise at base addr */ + read = RD32(at); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + } + + return MEMTEST_SUCCESS; +} + +/* + *----------------------------------------------------------------------------- + * Function: scanBulkValue + * + * Description: + * Pass 1. Fill entire memory in INcreasing memory address with value + * then in INcreasing memory address read and verify. + * Pass 2. Fill entire memory in DEcreasing memory address with value + * then in DEcreasing memory address read and verify. + * Pass 3. Fill entire memory in INcreasing memory address with inverse value + * then in INcreasing memory address read and verify. + * Pass 4. Fill entire memory in DEcreasing memory address with inverse value + * then in DEcreasing memory address read and verify. + * Pass 5. INcreasing shifted, ORIGINAL + * Pass 6. INcreasing shifted, INVERSE + * + * Parameters: + * addr: word aligned pointer to memory region + * bytes: size in bytes of memory region to test + * pat32: 32bit pattern, e.g. 0x0U, 0xAAAAAAAA, 0xFF00FF00, 0xFFFF0000, + * 0xF0F0F0F0, 0xC3C3C3C3, 0x87878787 + *----------------------------------------------------------------------------- + */ +MemTestResult_t scanBulkValue( uint32_t * addr, uint32_t bytes, uint32_t pat32 ) +{ + volatile uint32_t * at, * end_p; + uint32_t expected, read, words; + uint32_t shift; + + if ( ! IS_ALIGNED(addr,4) ) return MEMTEST_ERROR; + + words = bytes / sizeof(uint32_t); /* in whole words (4byte multiple) */ + if ( words == 0 ) return MEMTEST_ERROR; + + expected = pat32; /* ORIGINAL value */ + + /* INCREASING traversal */ + end_p = addr + words; + for ( at = addr; at < end_p; at++ ) + { + WR32( at, expected ); + } + for ( at = addr; at < end_p; at++ ) + { + read = RD32(at); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + } + + /* DECREASING traversal */ + end_p = addr; + for ( at = addr + words - 1; at >= end_p; at-- ) + { + WR32( at, expected ); + } + for ( at = addr + words - 1; at >= end_p; at-- ) + { + read = RD32(at); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + } + + expected = ~pat32; /* INVERSE value */ + + /* INCREASING traversal */ + end_p = addr + words; + for ( at = addr; at < end_p; at++ ) + { + WR32( at, expected ); + } + for ( at = addr; at < end_p; at++ ) + { + read = RD32(at); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + } + + /* DECREASING traversal */ + end_p = addr; + for ( at = addr + words - 1; at >= end_p; at-- ) + { + WR32( at, expected ); + } + for ( at = addr + words - 1; at >= end_p; at-- ) + { + read = RD32(at); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + } + + /* Pass 5. INCREASING Shifted traversal */ + expected = pat32; /* ORIGINAL value */ + end_p = addr + words; + shift = sizeof(uint32_t); + for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift ) + { + WR32( at, expected ); + WR32( addr, ~expected ); /* noise at base addr */ + } + shift = sizeof(uint32_t); + for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift ) + { + read = RD32(at); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + } + + expected = ~pat32; /* INVERSE value */ + end_p = addr + words; + shift = sizeof(uint32_t); + for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift ) + { + WR32( at, expected ); + WR32( addr, ~expected ); /* noise at base addr */ + } + shift = sizeof(uint32_t); + for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift ) + { + read = RD32(at); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + } + + return MEMTEST_SUCCESS; +} + +/* + *----------------------------------------------------------------------------- + * Function: scanBulkAltInv + * + * Description: + * Pass 1. Fill entire memory in INcreasing memory address with alternating + * value, then in INcreasing memory address read and verify. + * Pass 2. Fill entire memory in DEcreasing memory address with alternating + * value, then in DEcreasing memory address read and verify. + * Pass 3. Same as one but with shifted address. + * + * Parameters: + * addr: word aligned pointer to memory region + * bytes: size in bytes of memory region to test + * pat32: 32bit pattern, e.g. 0x0U, 0xAAAAAAAA, 0xFF00FF00, 0xFFFF0000, + * 0xF0F0F0F0, 0xC3C3C3C3, 0x87878787 + *----------------------------------------------------------------------------- + */ +MemTestResult_t scanBulkAltInv( uint32_t * addr, uint32_t bytes, uint32_t pat32 ) +{ + volatile uint32_t * at, * end_p; + uint32_t read, words; + uint32_t shift; + + if ( ! IS_ALIGNED(addr,4) ) return MEMTEST_ERROR; + + words = bytes / sizeof(uint32_t); /* in whole words (4byte multiple) */ + words = ROUNDDN( words, 2 ); + if ( words == 0 ) return MEMTEST_ERROR; + + /* INCREASING traversal */ + end_p = addr + words; + for ( at = addr; at < end_p; at+=2 ) + { + WR32( at+0, pat32 ); + WR32( at+1, ~pat32 ); + } + for ( at = addr; at < end_p; at+=2 ) + { + read = RD32( at+0 ); + if ( read != pat32 ) + { + return MEMTEST_FAILURE; + } + read = RD32( at+1 ); + if ( read != ~pat32 ) + { + return MEMTEST_FAILURE; + } + } + + /* DECREASING traversal */ + end_p = addr; + for ( at = addr + words - 1; at >= end_p; at-=2 ) + { + WR32( at+0, pat32 ); + WR32( at+1, ~pat32 ); + } + for ( at = addr + words - 1; at >= end_p; at-=2 ) + { + read = RD32( at+0 ); + if ( read != pat32 ) + { + return MEMTEST_FAILURE; + } + read = RD32( at+1 ); + if ( read != ~pat32 ) + { + return MEMTEST_FAILURE; + } + } + + /* INCREASING SHIFTED traversal */ + end_p = addr + words; + shift = sizeof(uint32_t); + for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift ) + { + WR32( at+0, pat32 ); + WR32( addr, 0 ); + WR32( at+1, ~pat32 ); + WR32( addr, 0 ); + } + shift = sizeof(uint32_t); + for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift ) + { + read = RD32( at+0 ); + if ( read != pat32 ) + { + return MEMTEST_FAILURE; + } + read = RD32( at+1 ); + if ( read != ~pat32 ) + { + return MEMTEST_FAILURE; + } + } + + return MEMTEST_SUCCESS; +} + + +/* + *----------------------------------------------------------------------------- + * Function: scanWordSelf + * + * Description: + * 4 Passes are conducted on the memory region. + * Pass 1. In INcreasing memory address, write a word with selfaddr and verify. + * Pass 2. In DEcreasing memory address, write a word with INVERSE and verify. + * Pass 3. In INcreasing memory address, write a word with INVERSE and verify. + * Pass 4. In DEcreasing memory address, write a word with selfaddr and verify. + * Pass 5. value = ORIGINAL address, INCREASING SHIFTED traversal. + * Pass 6. value = INVERSE address, INCREASING SHIFTED traversal. + * + * In Pass 2 Read+Modify+Write, and in Pass 3, Read+Write is used + * + * Parameters: + * addr: word aligned pointer to memory region + * bytes: size in bytes of memory region to test + * + *----------------------------------------------------------------------------- + */ +MemTestResult_t scanWordSelf( uint32_t * addr, uint32_t bytes ) +{ + volatile uint32_t * at, * end_p; + uint32_t expected, read, words; + uint32_t shift; + + if ( ! IS_ALIGNED(addr,4) ) return MEMTEST_FAILURE; + + words = bytes / sizeof(uint32_t); /* in whole words (4byte multiple) */ + if ( words == 0 ) return MEMTEST_ERROR; + + /* ORIGINAL value */ + + /* INCREASING traversal */ + end_p = addr + words; + for ( at = addr; at < end_p; at++ ) + { + expected = (uint32_t)at; + WR32( at, expected ); + read = RD32(at); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + } + + /* DECREASING traversal */ + end_p = addr; + for ( at = addr + words - 1; at >= end_p; at-- ) + { + expected = ~( (uint32_t)RD32(at) ); + WR32( at, expected ); + read = RD32(at); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + } + + /* INCREASING traversal */ + end_p = addr + words; + for ( at = addr; at < end_p; at++ ) + { + expected = ((uint32_t)RD32(at)); + WR32( at, expected ); + read = RD32(at); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + } + + /* DECREASING traversal */ + end_p = addr; + for ( at = addr + words - 1; at >= end_p; at-- ) + { + expected = ~((uint32_t)at); + WR32( at, expected ); + read = RD32(at); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + } + + /* value = ORIGINAL address, INCREASING SHIFTED traversal */ + end_p = addr + words; + shift = sizeof(uint32_t); + for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift ) + { + expected = (uint32_t)at; /* Not read modify write */ + WR32( at, expected ); + WR32( addr, ~expected ); + read = RD32(at); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + } + + /* value = INVERSE address, INCREASING SHIFTED traversal */ + end_p = addr + words; + shift = sizeof(uint32_t); + for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift ) + { + expected = ~(uint32_t)(at); /* Not read modify write */ + WR32( at, expected ); + WR32( addr, ~expected ); + read = RD32(at); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + } + + return MEMTEST_SUCCESS; +} + +/* + *----------------------------------------------------------------------------- + * Function: scanBulkSelf + * + * Description: + * Pass 1. Fill entire memory in INcreasing memory address with self address + * then in INcreasing memory address read and verify. + * Pass 2. Fill entire memory in DEcreasing memory address with self address + * then in DEcreasing memory address read and verify. + * Pass 3. Fill entire memory in INcreasing memory address with inverse addr + * then in INcreasing memory address read and verify. + * Pass 4. Fill entire memory in DEcreasing memory address with inverse addr + * then in DEcreasing memory address read and verify. + * Pass 5. Same as Pass 1 but with shifted address + * Pass 6. Same as Pass 3 but with shifted address + * + * Parameters: + * addr: word aligned pointer to memory region + * bytes: size in bytes of memory region to test + *----------------------------------------------------------------------------- + */ +MemTestResult_t scanBulkSelf( uint32_t * addr, uint32_t bytes ) +{ + volatile uint32_t * at, * end_p; + uint32_t read, words; + uint32_t shift; + + if ( ! IS_ALIGNED(addr,4) ) return MEMTEST_ERROR; + + words = bytes / sizeof(uint32_t); /* in whole words (4byte multiple) */ + if ( words == 0 ) return MEMTEST_ERROR; + + /* INCREASING traversal */ + end_p = addr + words; + for ( at = addr; at < end_p; at++ ) + { + WR32( at, (uint32_t)at ); + } + for ( at = addr; at < end_p; at++ ) + { + read = RD32(at); + if ( read != (uint32_t)at ) + { + return MEMTEST_FAILURE; + } + } + + /* DECREASING traversal */ + end_p = addr; + for ( at = addr + words - 1; at >= end_p; at-- ) + { + WR32( at, (uint32_t)at ); + } + for ( at = addr + words - 1; at >= end_p; at-- ) + { + read = RD32(at); + if ( read != (uint32_t)at ) + { + return MEMTEST_FAILURE; + } + } + + /* INCREASING traversal */ + end_p = addr + words; + for ( at = addr; at < end_p; at++ ) + { + WR32( at, ~((uint32_t)at) ); + } + for ( at = addr; at < end_p; at++ ) + { + read = RD32(at); + if ( read != ~((uint32_t)at) ) + { + return MEMTEST_FAILURE; + } + } + + /* DECREASING traversal */ + end_p = addr; + for ( at = addr + words - 1; at >= end_p; at-- ) + { + WR32( at, ~((uint32_t)at) ); + } + for ( at = addr + words - 1; at >= end_p; at-- ) + { + read = RD32(at); + if ( read != ~((uint32_t)at) ) + { + return MEMTEST_FAILURE; + } + } + + /* INCREASING traversal */ + end_p = addr + words; + shift = sizeof(uint32_t); + for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift ) + { + WR32( at, (uint32_t)at ); + WR32( addr, ~((uint32_t)at) ); + } + shift = sizeof(uint32_t); + for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift ) + { + read = RD32(at); + if ( read != (uint32_t)at ) + { + return MEMTEST_FAILURE; + } + } + + /* INCREASING traversal */ + end_p = addr + words; + shift = sizeof(uint32_t); + for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift ) + { + WR32( at, ~((uint32_t)at) ); + WR32( addr, ((uint32_t)at) ); + } + shift = sizeof(uint32_t); + for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift ) + { + read = RD32(at); + if ( read != ~((uint32_t)at) ) + { + return MEMTEST_FAILURE; + } + } + + return MEMTEST_SUCCESS; +} + + +/* + *----------------------------------------------------------------------------- + * Function: slidingAltInv + * + * Description: + * This is the same as scanBulkAltInv, where in each invocation the value is + * rotated to the right. The starting value is usedefined. + * + * Parameters: + * addr: word aligned pointer to memory region + * bytes: size in bytes of memory region to test + * pat32: pattern to slide per pass + *----------------------------------------------------------------------------- + */ +MemTestResult_t slidingAltInv( uint32_t * addr, uint32_t bytes, uint32_t pat32 ) +{ + uint32_t sliding_pat32, i; + + if ( pat32 == 0x0 ) pat32 = 0x80000000; + if ( pat32 == ~0x0 ) pat32 = 0x7FFFFFFF; + + sliding_pat32 = pat32; + + for ( i=0; i<32; i++ ) + { + if ( scanBulkAltInv( addr, bytes, sliding_pat32 ) + == MEMTEST_FAILURE ) + { + return MEMTEST_FAILURE; + } + + sliding_pat32 = RROTATE32( sliding_pat32 ); + } + + sliding_pat32 = pat32; + for (i=0; i<32; i++) + { + if ( scanBulkAltInv( addr, bytes, sliding_pat32 ) + == MEMTEST_FAILURE ) + { + return MEMTEST_FAILURE; + } + + sliding_pat32 = LROTATE32( sliding_pat32 ); + } + + return MEMTEST_SUCCESS; +} + +/* + *----------------------------------------------------------------------------- + * Function: slidingDiag + * + * Description: + * Pass 1. Fill entire memory in INcreasing memory address with pattern right + * shifted. Then read in INcreasing order and verify. + * Pass 2. Fill entire memory in DEcreasing memory address with inverse of + * read value. Then read in DEcreasing order and verify. + * Pass 3. Fill entire memory in DEcreasing memory address with pattern right + * shifted. Then read in DEcreasing order and verify. + * Pass 4. Fill entire memory in INcreasing memory address with inverse of + * read value. Then read in INcreasing order and verify. + * + * Parameters: + * addr: word aligned pointer to memory region + * bytes: size in bytes of memory region to test + * pat32: pattern to be filled shifted each write + *----------------------------------------------------------------------------- + */ +MemTestResult_t slidingDiag( uint32_t * addr, uint32_t bytes, uint32_t pat32 ) +{ + volatile uint32_t * at, * end_p; + uint32_t expected, read = 0, words, last; + + if ( ! IS_ALIGNED(addr,4) ) return MEMTEST_ERROR; + + words = bytes / sizeof(uint32_t); /* in whole words (4byte multiple) */ + if ( words == 0 ) return MEMTEST_ERROR; + + + /* INCREASING traversal */ + expected = pat32; /* ORIGINAL value */ + end_p = addr + words; + for ( at = addr; at < end_p; at++ ) + { + WR32( at, expected ); + expected = RROTATE32( expected ); /* next expected */ + } + expected = pat32; /* ORIGINAL value */ + for ( at = addr; at < end_p; at++ ) + { + read = RD32(at); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + expected = RROTATE32( expected ); /* next expected */ + } + + last = ~( read ); /* Starting value for decreasing traversal, next */ + + /* DECREASING traversal */ + end_p = addr; + for ( at = addr + words - 1; at >= end_p; at-- ) + { + expected = ~( RD32(at) ); + WR32( at, expected ); + } + expected = last; + for ( at = addr + words - 1; at >= end_p; at-- ) + { + read = RD32(at); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + expected = LROTATE32( expected ); + } + + /* DECREASING traversal */ + expected = pat32; /* ORIGINAL value */ + end_p = addr; + for ( at = addr + words - 1; at >= end_p; at-- ) + { + WR32( at, expected ); + expected = RROTATE32( expected ); /* next expected */ + } + expected = pat32; /* ORIGINAL value */ + for ( at = addr + words - 1; at >= end_p; at-- ) + { + read = RD32(at); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + expected = RROTATE32( expected ); /* next expected */ + } + + last = ~( read ); + + /* INCREASING traversal */ + end_p = addr + words; + for ( at = addr; at < end_p; at++ ) + { + expected = ~( RD32(at) ); + WR32( at, expected ); + } + expected = last; + for ( at = addr; at < end_p; at++ ) + { + read = RD32(at); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + expected = LROTATE32( expected ); + } + + return MEMTEST_SUCCESS; +} + +/* + *----------------------------------------------------------------------------- + * Function: memoryBulkCopy + * + * Description: + * Pass 1. Copy entire ORIGINAL memory in INcreasing memory address, then verify + * Pass 2. Copy entire ORIGINAL memory in DEcreasing memory address, then verify + * Pass 3. Copy entire INVERSE memory in INcreasing memory address, then verify + * Pass 4. Copy entire INVERSE memory in DEcreasing memory address, then verify + *----------------------------------------------------------------------------- + */ +MemTestResult_t memoryBulkCopy( uint32_t * saddr, uint32_t * daddr, + uint32_t bytes ) +{ + volatile uint32_t * src_p, * dst_p, * end_p; + uint32_t expected, read, words; + + if ( ! IS_ALIGNED(saddr,4) ) return MEMTEST_ERROR; + if ( ! IS_ALIGNED(daddr,4) ) return MEMTEST_ERROR; + + words = bytes / sizeof(uint32_t); /* in whole words (4byte multiple) */ + if ( words == 0 ) return MEMTEST_ERROR; + + if ( (uint32_t)saddr < (uint32_t)daddr ) + { + if ( (uint32_t)(saddr + words) > (uint32_t)daddr ) + return MEMTEST_ERROR; + } + else if ( (uint32_t)daddr < (uint32_t)saddr ) + { + if ( (uint32_t)(daddr + words) > (uint32_t)saddr ) + return MEMTEST_ERROR; + } + + /* INCREASING traversal ORIGINAL */ + end_p = saddr + words; + for ( src_p = saddr, dst_p = daddr; src_p < end_p; src_p++, dst_p++ ) + { + expected = RD32( dst_p ); + WR32( src_p, expected ); + } + for ( src_p = saddr, dst_p = daddr; src_p < end_p; src_p++, dst_p++ ) + { + expected = RD32( dst_p ); + read = RD32( src_p ); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + } + + /* DECREASING traversal ORIGINAL */ + end_p = saddr; + for ( src_p = saddr + words - 1, dst_p = daddr + words - 1; + src_p >= end_p; src_p--, dst_p-- ) + { + expected = RD32( dst_p ); + WR32( src_p, expected ); + } + for ( src_p = saddr + words - 1, dst_p = daddr + words - 1; + src_p >= end_p; src_p--, dst_p-- ) + { + expected = RD32( dst_p ); + read = RD32( src_p ); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + } + + /* INCREASING traversal INVERSE */ + end_p = saddr + words; + for ( src_p = saddr, dst_p = daddr; src_p < end_p; src_p++, dst_p++ ) + { + expected = ~( RD32( dst_p ) ); + WR32( src_p, expected ); + } + for ( src_p = saddr, dst_p = daddr; src_p < end_p; src_p++, dst_p++ ) + { + expected = ~( RD32( dst_p ) ); + read = RD32( src_p ); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + } + + /* DECREASING traversal INVERSE */ + end_p = saddr; + for ( src_p = saddr + words - 1, dst_p = daddr + words - 1; + src_p >= end_p; src_p--, dst_p-- ) + { + expected = ~( RD32( dst_p ) ); + WR32( src_p, expected ); + } + for ( src_p = saddr + words - 1, dst_p = daddr + words - 1; + src_p >= end_p; src_p--, dst_p-- ) + { + expected = ~( RD32( dst_p ) ); + read = RD32( src_p ); + if ( read != expected ) + { + return MEMTEST_FAILURE; + } + } + + return MEMTEST_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ diff --git a/cfe/cfe/arch/mips/board/bcm63xx_rom/src/rom_cfe.mk b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/rom_cfe.mk new file mode 100755 index 0000000..c45aea7 --- /dev/null +++ b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/rom_cfe.mk @@ -0,0 +1,370 @@ + +# +# CFE's version number +# + +include ${TOP}/main/cfe_version.mk + +# +# Default values for certain parameters +# + +CFG_MLONG64 ?= 0 +CFG_LITTLE ?= 0 +CFG_RELOC ?= 0 +CFG_UNCACHED ?= 0 +CFG_NEWRELOC ?= 0 +CFG_BOOTRAM ?= 0 +CFG_VGACONSOLE ?= 0 +CFG_PCI ?= 1 +CFG_LDT_REV_017 ?= 0 +CFG_ZLIB ?= 0 +CFG_BIENDIAN ?= 0 +CFG_DOWNLOAD ?= 0 +CFG_RAMAPP ?= 0 +CFG_USB ?= 0 + +# +# Paths to other parts of the firmware. Everything's relative to ${TOP} +# so that you can actually do a build anywhere you want. +# + +ARCH_TOP = ${TOP}/arch/${ARCH} +ARCH_SRC = ${ARCH_TOP}/common/src +ARCH_INC = ${ARCH_TOP}/common/include +CPU_SRC = ${ARCH_TOP}/cpu/${CPU}/src +CPU_INC = ${ARCH_TOP}/cpu/${CPU}/include +# +# It's actually optional to have a 'board' +# directory. If you don't specify BOARD, +# don't include the files. +# + +ifneq ("$(strip ${BOARD})","") +BOARD_SRC = ${ARCH_TOP}/board/${BOARD}/src +BOARD_INC = ${ARCH_TOP}/board/${BOARD}/include +endif + +# +# Preprocessor defines for CFE's version number +# + +VDEF = -DCFE_VER_MAJ=${CFE_VER_MAJ} -DCFE_VER_MIN=${CFE_VER_MIN} -DCFE_VER_ECO=${CFE_VER_ECO} + +# +# Construct the list of paths that will eventually become the include +# paths and VPATH +# + +SRCDIRS = ${ARCH_SRC} ${CPU_SRC} ${BOARD_SRC} ${TOP}/main ${TOP}/vendor ${TOP}/include ${TOP}/net ${TOP}/dev ${TOP}/pci ${TOP}/ui ${TOP}/lib ${TOP}/common ${TOP}/verif ${TOP}/lzma + +CFE_INC = ${TOP}/include ${TOP}/pci ${TOP}/net + +ifeq ($(strip ${CFG_VGACONSOLE}),1) +SRCDIRS += ${TOP}/x86emu ${TOP}/pccons +CFE_INC += ${TOP}/x86emu ${TOP}/pccons +endif + +ifeq ($(strip ${CFG_VAPI}),1) +SRCDIRS += ${TOP}/verif +CFE_INC += ${TOP}/verif +endif + +ifeq ($(strip ${CFG_ZLIB}),1) +SRCDIRS += ${TOP}/zlib +CFE_INC += ${TOP}/zlib +endif + + +INCDIRS = $(patsubst %,-I%,$(subst :, ,$(ARCH_INC) $(CPU_INC) $(BOARD_INC) $(CFE_INC))) + +VPATH = $(SRCDIRS) + +# +# Bi-endian support: If we're building the little-endian +# version, use a different linker script so we can locate the +# ROM at a higher address. You'd think we could do this with +# normal linker command line switches, but there appears to be no +# command-line way to override the 'AT' qualifier in the linker script. +# + +CFG_TEXTAT1MB=0 +ifeq ($(strip ${CFG_BIENDIAN}),1) + ifeq ($(strip ${CFG_LITTLE}),1) + CFG_TEXTAT1MB=1 + endif +endif + + +# +# Configure tools and basic tools flags. This include sets up +# macros for calling the C compiler, basic flags, +# and linker scripts. +# + +include ${ARCH_SRC}/tools.mk + +# +# Add some common flags that are used on any architecture. +# + +CFLAGS += -I. $(INCDIRS) +CFLAGS += -D_CFE_ ${VDEF} -DCFG_BOARDNAME=\"${CFG_BOARDNAME}\" + +# +# Gross - allow more options to be supplied from command line +# + +ifdef CFG_OPTIONS +OPTFLAGS = $(patsubst %,-D%,$(subst :, ,$(CFG_OPTIONS))) +CFLAGS += ${OPTFLAGS} +endif + +ifeq ($(strip $(BRCM_IKOS)),y) +CFLAGS += -DCONFIG_BRCM_IKOS +endif + +# +# Add flash driver support. +# + +ifeq ($(strip $(BLD_NAND)),1) +# BUILD NAND flash boot loader +ifeq ($(strip $(BRCM_CHIP)),6328) +INC_CFI_FLASH_DRIVER=0 +INC_SPI_FLASH_DRIVER=0 +INC_NAND_FLASH_DRIVER=1 +endif +ifeq ($(strip $(BRCM_CHIP)),6362) +INC_CFI_FLASH_DRIVER=0 +INC_SPI_FLASH_DRIVER=0 +INC_NAND_FLASH_DRIVER=1 +endif +ifeq ($(strip $(BRCM_CHIP)),6368) +INC_CFI_FLASH_DRIVER=0 +INC_SPI_FLASH_DRIVER=0 +INC_NAND_FLASH_DRIVER=1 +endif +ifeq ($(strip $(BRCM_CHIP)),6816) +INC_CFI_FLASH_DRIVER=0 +INC_SPI_FLASH_DRIVER=0 +INC_NAND_FLASH_DRIVER=1 +endif + +else +# BUILD NOR flash boot loader +ifeq ($(strip $(BRCM_CHIP)),6328) +INC_CFI_FLASH_DRIVER=0 +INC_SPI_FLASH_DRIVER=1 +INC_NAND_FLASH_DRIVER=0 +endif +ifeq ($(strip $(BRCM_CHIP)),6362) +INC_CFI_FLASH_DRIVER=0 +INC_SPI_FLASH_DRIVER=1 +INC_NAND_FLASH_DRIVER=0 +endif +ifeq ($(strip $(BRCM_CHIP)),6368) +INC_CFI_FLASH_DRIVER=1 +INC_SPI_FLASH_DRIVER=1 +INC_NAND_FLASH_DRIVER=0 +endif +ifeq ($(strip $(BRCM_CHIP)),6816) +INC_CFI_FLASH_DRIVER=1 +INC_SPI_FLASH_DRIVER=1 +INC_NAND_FLASH_DRIVER=0 +endif +endif + +ifeq ($(strip $(BLD_SPI_NAND)),1) +INC_CFI_FLASH_DRIVER=0 +INC_SPI_FLASH_DRIVER=1 +INC_NAND_FLASH_DRIVER=0 +INC_SPI_PROG_NAND=1 +else +INC_SPI_PROG_NAND=0 +endif + +CFLAGS += -DINC_CFI_FLASH_DRIVER=$(INC_CFI_FLASH_DRIVER) +CFLAGS += -DINC_SPI_FLASH_DRIVER=$(INC_SPI_FLASH_DRIVER) +CFLAGS += -DINC_NAND_FLASH_DRIVER=$(INC_NAND_FLASH_DRIVER) +CFLAGS += -DINC_SPI_PROG_NAND=$(INC_SPI_PROG_NAND) + +# +# This is the makefile's main target. Note that we actually +# do most of the work in 'ALL' not 'all', since we include +# other makefiles after this point. +# + +all : build_date.c ALL + +# +# Macros that expand to the list of arch-independent files +# + +LZMAOBJS = LzmaDecode.o dcapi.o +DEVOBJS = lib_malloc.o +## dev_newflash.o dev_null.o dev_promice.o dev_ide_common.o dev_ns16550.o dev_ds17887clock.o dev_flash.o + +##lib_hssubr.o lib_physio.o lib_printf.o lib_misc.o \ lib_arena.o lib_queue.o +## lib_qsort.o lib_string.o lib_string2.o + +NETOBJS = +## net_tcp.o net_tcpbuf.o dev_tcpconsole.o net_dhcp.o net_icmp.o net_ether.o net_tftp.o net_ip.o net_udp.o net_dns.o net_arp.o net_api.o + +CFEOBJS = +## cfe_iocb_dispatch.o cfe_devfuncs.o \ cfe_console.o cfe_timer.o cfe_attach.o cfe_background.o cfe_zlibfs.o +## cfe_mem.o +## cfe_error.o build_date.o \ +## cfe_rawfs.o cfe_xreq.o cfe_filesys.o +## cfe_fatfs.o cfe_httpfs.o cfe_ldr_srec.o cfe_autoboot.o cfe_boot.o cfe_ldr_elf.o cfe_ldr_raw.o cfe_loader.o +## cfe_main.o nvram_subr.o url.o cfe_savedata.o env_subr.o +UIOBJS = +##ui_command.o ui_cmddisp.o +## ui_pcicmds.o \ui_tcpcmds.o ui_memcmds.o ui_loadcmds.o ui_flash.o ui_netcmds.o ui_envcmds.o ui_devcmds.o +## ui_examcmds.o ui_misccmds.o \ +## ui_test_disk.o ui_test_ether.o ui_test_flash.o ui_test_uart.o + +# +# Add more object files if we're supporting PCI +# + +ifeq ($(strip ${CFG_PCI}),1) +PCIOBJS = pciconf.o ldtinit.o pci_subr.o +PCIOBJS += pci_devs.o +DEVOBJS += dev_sp1011.o dev_ht7520.o +DEVOBJS += dev_ide_pci.o dev_ns16550_pci.o +DEVOBJS += dev_tulip.o dev_dp83815.o +CFLAGS += -DCFG_PCI=1 +ifeq ($(strip ${CFG_LDT_REV_017}),1) +CFLAGS += -DCFG_LDT_REV_017=1 +endif +ifeq ($(strip ${CFG_DOWNLOAD}),1) +DEVOBJS += dev_bcm1250.o download.data +CFLAGS += -DCFG_DOWNLOAD=1 +endif +endif + +# +# If doing bi-endian, add the compiler switch to change +# the way the vectors are generated. These switches are +# only added to the big-endian portion of the ROM, +# which is located at the real boot vector. +# + +ifeq ($(strip ${CFG_BIENDIAN}),1) + ifeq ($(strip ${CFG_LITTLE}),0) + CFLAGS += -DCFG_BIENDIAN=1 + endif +endif + +# +# Include the makefiles for the architecture-common, cpu-specific, +# and board-specific directories. Each of these will supply +# some files to "ALLOBJS". The BOARD directory is optional +# as some ports are so simple they don't need boad-specific stuff. +# + +include ${ARCH_SRC}/Makefile +include ${CPU_SRC}/Makefile + +ifneq ("$(strip ${BOARD})","") +include ${BOARD_SRC}/Makefile +endif + +# +# Add the common object files here. +# + +ALLOBJS += $(LIBOBJS) $(DEVOBJS) $(CFEOBJS) $(VENOBJS) $(UIOBJS) $(NETOBJS) +#$(PCIOBJS) + +# +# VAPI continues to be a special case. +# + +ifeq ($(strip ${CFG_VAPI}),1) +include ${TOP}/verif/Makefile +endif + +# +# USB support +# + +ifeq ($(strip ${CFG_USB}),1) +SRCDIRS += ${TOP}/usb +CFE_INC += ${TOP}/usb +include ${TOP}/usb/Makefile +endif + +# +# If we're doing the VGA console thing, pull in the x86 emulator +# and the pcconsole subsystem +# + +ifeq ($(strip ${CFG_VGACONSOLE}),1) +include ${TOP}/x86emu/Makefile +include ${TOP}/pccons/Makefile +endif + +# +# If we're including ZLIB, then add its makefile. +# + +##ifeq ($(strip ${CFG_ZLIB}),1) +##include ${TOP}/zlib/Makefile +CFLAGS += -DCFG_ZLIB=1 -DMY_ZCALLOC -DNO_MEMCPY +##endif + +.PHONY : all +.PHONY : ALL +.PHONY : build_date.c + +# +# Build the local tools that we use to construct other source files +# + +mkpcidb : ${TOP}/hosttools/mkpcidb.c + gcc -o mkpcidb ${TOP}/hosttools/mkpcidb.c + +memconfig : ${TOP}/hosttools/memconfig.c + gcc -o memconfig -D_MCSTANDALONE_ -D_MCSTANDALONE_NOISY_ -I${TOP}/arch/mips/cpu/sb1250/include ${TOP}/hosttools/memconfig.c ${TOP}/arch/${ARCH}/cpu/${CPU}/src/sb1250_draminit.c + +pcidevs_data2.h : mkpcidb ${TOP}/pci/pcidevs_data.h + ./mkpcidb > pcidevs_data2.h + +mkflashimage : ${TOP}/hosttools/mkflashimage.c + gcc -o mkflashimage -I${TOP}/include ${TOP}/hosttools/mkflashimage.c + +pci_subr.o : ${TOP}/pci/pci_subr.c pcidevs_data2.h + +##build_date.c : +## echo "const char *builddate = \"`date`\";" > build_date.c +## echo "const char *builduser = \"`whoami`@`hostname`\";" >> build_date.c + +# +# Make a define for the board name +# + +CFLAGS += -D_$(patsubst "%",%,${CFG_BOARDNAME})_ + +LIBCFE = libcfe.a + +%.o : %.c + $(GCC) $(CFLAGS) -o $@ $< + +%.o : %.S + $(GCC) $(CFLAGS) -o $@ $< + +# +# This rule constructs "libcfe.a" which contains most of the object +# files. +# + +$(LIBCFE) : $(ALLOBJS) + rm -f $(LIBCFE) + $(AR) cr $(LIBCFE) $(ALLOBJS) + $(RANLIB) $(LIBCFE) + + + + |