diff options
Diffstat (limited to 'cfe/cfe/arch/mips')
79 files changed, 26528 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) + + + + diff --git a/cfe/cfe/arch/mips/common/include/addrspace.h b/cfe/cfe/arch/mips/common/include/addrspace.h new file mode 100644 index 0000000..6330851 --- /dev/null +++ b/cfe/cfe/arch/mips/common/include/addrspace.h @@ -0,0 +1,63 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Address space macros File: addrspace.h + * + * Macros to deal with physical, virtual, and uncached addresses. + * for MIPS, these map to the appropriate KSEG0/KSEG1 macros + * + * 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 "sbmips.h" + +#define PHYSADDR(x) K0_TO_PHYS(x) + +/* If running uncached, force all kernel addresses to be uncached */ +#if CFG_RUNFROMKSEG0 +#define KERNADDR(x) PHYS_TO_K0(x) +#else +#define KERNADDR(x) PHYS_TO_K1(x) +#endif + +#define UNCADDR(x) PHYS_TO_K1(x) + + + diff --git a/cfe/cfe/arch/mips/common/include/disasm.h b/cfe/cfe/arch/mips/common/include/disasm.h new file mode 100644 index 0000000..8a8e7b7 --- /dev/null +++ b/cfe/cfe/arch/mips/common/include/disasm.h @@ -0,0 +1,61 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * MIPS disassembler File: disasm.h + * + * MIPS disassembler (used by ui_examcmds.c) + * + * Author: Justin Carlson (carlson@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. + ********************************************************************* */ + +#ifndef DISASM_H +#define DISASM_H + +/* Returns a pointer to a read-only string containing the intstruction name */ +char *disasm_inst_name(uint32_t inst); + +/* Copies a disassembled version of the instruction into buf, null terminating the +string. Will not exceed buf_size bytes written; if the disassembled string is +longer than buf_size, buf_size-1 bytes of the string will be written and that string +will be null-terminated */ +void disasm_inst(char *buf, int buf_size, uint32_t inst, uint64_t pc); +#endif + + + diff --git a/cfe/cfe/arch/mips/common/include/exception.h b/cfe/cfe/arch/mips/common/include/exception.h new file mode 100644 index 0000000..70e87c2 --- /dev/null +++ b/cfe/cfe/arch/mips/common/include/exception.h @@ -0,0 +1,223 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Exception/trap handler defs File: exception.h + * + * This module describes the exception handlers, exception + * trap frames, and dispatch. + * + * 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. + ********************************************************************* */ + +#ifdef __ASSEMBLER__ +#define _XAIDX(x) (8*(x)) +#else +#define _XAIDX(x) (x) +#endif + + +/* ********************************************************************* + * Exception vectors from the MIPS specification + ********************************************************************* */ + +#define MIPS_ROM_VEC_RESET 0x0000 +#define MIPS_ROM_VEC_TLBFILL 0x0200 +#define MIPS_ROM_VEC_XTLBFILL 0x0280 +#define MIPS_ROM_VEC_CACHEERR 0x0300 +#define MIPS_ROM_VEC_EXCEPTION 0x0380 +#define MIPS_ROM_VEC_INTERRUPT 0x0400 +#define MIPS_ROM_VEC_EJTAG 0x0480 + +#define MIPS_RAM_VEC_TLBFILL 0x0000 +#define MIPS_RAM_VEC_XTLBFILL 0x0080 +#define MIPS_RAM_VEC_EXCEPTION 0x0180 +#define MIPS_RAM_VEC_INTERRUPT 0x0200 +#define MIPS_RAM_VEC_CACHEERR 0x0100 +#define MIPS_RAM_VEC_END 0x0300 + +#define MIPS_RAM_EXL_VEC_TLBFILL 0x0100 +#define MIPS_RAM_EXL_VEC_XTLBFILL 0x0180 + + +/* ********************************************************************* + * Fixed locations of other low-memory objects. We stuff some + * important data in the spaces between the vectors. + ********************************************************************* */ + +#define CFE_LOCORE_GLOBAL_GP 0x0040 /* our "handle" */ +#define CFE_LOCORE_GLOBAL_SP 0x0048 /* Stack pointer for exceptions */ +#define CFE_LOCORE_GLOBAL_K0TMP 0x0050 /* Used by cache error handler */ +#define CFE_LOCORE_GLOBAL_K1TMP 0x0058 /* Used by cache error handler */ +#define CFE_LOCORE_GLOBAL_RATMP 0x0060 /* Used by cache error handler */ +#define CFE_LOCORE_GLOBAL_GPTMP 0x0068 /* Used by cache error handler */ +#define CFE_LOCORE_GLOBAL_CERRH 0x0070 /* Pointer to cache error handler */ + +#define CFE_LOCORE_GLOBAL_T0TMP 0x0240 /* used by cache error handler */ +#define CFE_LOCORE_GLOBAL_T1TMP 0x0248 /* used by cache error handler */ +#define CFE_LOCORE_GLOBAL_T2TMP 0x0250 /* used by cache error handler */ +#define CFE_LOCORE_GLOBAL_T3TMP 0x0258 /* used by cache error handler */ + +/* ********************************************************************* + * Offsets into our exception handler table. + ********************************************************************* */ + +#define XTYPE_RESET 0 +#define XTYPE_TLBFILL 8 +#define XTYPE_XTLBFILL 16 +#define XTYPE_CACHEERR 24 +#define XTYPE_EXCEPTION 32 +#define XTYPE_INTERRUPT 40 +#define XTYPE_EJTAG 48 + +/* ********************************************************************* + * Exception frame definitions. + ********************************************************************* */ + +/* + * The exception frame is divided up into pieces, representing the different + * parts of the processor that the data comes from: + * + * CP0: Words 0..7 + * Int Regs: Words 8..41 + * FP Regs: Words 42..73 + * Total size: 74 words + */ + +#define EXCEPTION_SIZE _XAIDX(74) + +#define XCP0_BASE 0 +#define XGR_BASE 8 +#define XFR_BASE 42 + +#define _XCP0IDX(x) _XAIDX((x)+XCP0_BASE) +#define XCP0_SR _XCP0IDX(0) +#define XCP0_CAUSE _XCP0IDX(1) +#define XCP0_EPC _XCP0IDX(2) +#define XCP0_VADDR _XCP0IDX(3) +#define XCP0_PRID _XCP0IDX(4) + +#define _XGRIDX(x) _XAIDX((x)+XGR_BASE) +#define XGR_ZERO _XGRIDX(0) +#define XGR_AT _XGRIDX(1) +#define XGR_V0 _XGRIDX(2) +#define XGR_V1 _XGRIDX(3) +#define XGR_A0 _XGRIDX(4) +#define XGR_A1 _XGRIDX(5) +#define XGR_A2 _XGRIDX(6) +#define XGR_A3 _XGRIDX(7) +#define XGR_T0 _XGRIDX(8) +#define XGR_T1 _XGRIDX(9) +#define XGR_T2 _XGRIDX(10) +#define XGR_T3 _XGRIDX(11) +#define XGR_T4 _XGRIDX(12) +#define XGR_T5 _XGRIDX(13) +#define XGR_T6 _XGRIDX(14) +#define XGR_T7 _XGRIDX(15) +#define XGR_S0 _XGRIDX(16) +#define XGR_S1 _XGRIDX(17) +#define XGR_S2 _XGRIDX(18) +#define XGR_S3 _XGRIDX(19) +#define XGR_S4 _XGRIDX(20) +#define XGR_S5 _XGRIDX(21) +#define XGR_S6 _XGRIDX(22) +#define XGR_S7 _XGRIDX(23) +#define XGR_T8 _XGRIDX(24) +#define XGR_T9 _XGRIDX(25) +#define XGR_K0 _XGRIDX(26) +#define XGR_K1 _XGRIDX(27) +#define XGR_GP _XGRIDX(28) +#define XGR_SP _XGRIDX(29) +#define XGR_FP _XGRIDX(30) +#define XGR_RA _XGRIDX(31) +#define XGR_LO _XGRIDX(32) +#define XGR_HI _XGRIDX(33) + + +#define _XFRIDX(x) _XAIDX((x)+XFR_BASE) +#define XR_F0 _XFRIDX(0) +#define XR_F1 _XFRIDX(1) +#define XR_F2 _XFRIDX(2) +#define XR_F3 _XFRIDX(3) +#define XR_F4 _XFRIDX(4) +#define XR_F5 _XFRIDX(5) +#define XR_F6 _XFRIDX(6) +#define XR_F7 _XFRIDX(7) +#define XR_F8 _XFRIDX(8) +#define XR_F9 _XFRIDX(9) +#define XR_F10 _XFRIDX(10) +#define XR_F11 _XFRIDX(11) +#define XR_F12 _XFRIDX(12) +#define XR_F13 _XFRIDX(13) +#define XR_F14 _XFRIDX(14) +#define XR_F15 _XFRIDX(15) +#define XR_F16 _XFRIDX(16) +#define XR_F17 _XFRIDX(17) +#define XR_F18 _XFRIDX(18) +#define XR_F19 _XFRIDX(19) +#define XR_F20 _XFRIDX(20) +#define XR_F21 _XFRIDX(21) +#define XR_F22 _XFRIDX(22) +#define XR_F23 _XFRIDX(23) +#define XR_F24 _XFRIDX(24) +#define XR_F25 _XFRIDX(25) +#define XR_F26 _XFRIDX(26) +#define XR_F27 _XFRIDX(27) +#define XR_F28 _XFRIDX(28) +#define XR_F29 _XFRIDX(29) +#define XR_F30 _XFRIDX(30) +#define XR_F31 _XFRIDX(31) +#define XR_FCR _XFRIDX(32) +#define XR_FID _XFRIDX(33) + + +#ifndef __ASSEMBLER__ +extern void _exc_setvector(int vectype, void *vecaddr); +extern void _exc_crash_sim(void); +extern void _exc_cache_crash_sim(void); +extern void _exc_restart(void); +extern void _exc_clear_sr_exl(void); +extern void _exc_clear_sr_erl(void); +void cfe_exception(int code,uint64_t *info); +void cfe_setup_exceptions(void); +#endif + + + + + diff --git a/cfe/cfe/arch/mips/common/include/exchandler.h b/cfe/cfe/arch/mips/common/include/exchandler.h new file mode 100644 index 0000000..af268f1 --- /dev/null +++ b/cfe/cfe/arch/mips/common/include/exchandler.h @@ -0,0 +1,85 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Exception Handler definitions File: exchandler.h + * + * Exception handler functions and constants + * + * Author: Binh Vo (binh@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. + ********************************************************************* */ + + +#ifndef _LIB_SETJMP_H +#include "lib_setjmp.h" +#endif + +#ifndef _LIB_QUEUE_H +#include "lib_queue.h" +#endif + +#define MEM_BYTE 1 +#define MEM_HALFWORD 2 +#define MEM_WORD 3 +#define MEM_QUADWORD 4 + +#define EXC_NORMAL_RETURN 0 +#define EXC_CHAIN_EXC 1 + +typedef struct jmpbuf_s { + queue_t stack; + jmp_buf jmpbuf; +} jmpbuf_t; + +typedef struct exc_handler_s { + int catch_exc; + int chain_exc; + queue_t jmpbuf_stack; +} exc_handler_t; + +extern exc_handler_t exc_handler; + +jmpbuf_t *exc_initialize_block(void); +void exc_cleanup_block(jmpbuf_t *); +void exc_cleanup_handler(jmpbuf_t *, int); +void exc_longjmp_handler(void); +int mem_peek(void*, long, int); +int mem_poke(long, uint64_t, int); + + +#define exc_try(jb) (lib_setjmp(((jb)->jmpbuf))) diff --git a/cfe/cfe/arch/mips/common/include/initdata.h b/cfe/cfe/arch/mips/common/include/initdata.h new file mode 100644 index 0000000..c5fc0d8 --- /dev/null +++ b/cfe/cfe/arch/mips/common/include/initdata.h @@ -0,0 +1,68 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Data stored in initialization module File: initdata.h + * + * This file contains data declared by the init module. It also + * contains externs for that data so we can keep the types straight. + * + * 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. + ********************************************************************* */ + + +#if defined(__ASSEMBLER__) +#define DECLARE_INITVAR(x) \ + .globl x ; \ +x: _LONG_ 0 +#else +#define DECLARE_INITVAR(x) \ + extern long x; +#endif + +DECLARE_INITVAR(mem_textreloc) +DECLARE_INITVAR(mem_textbase) +DECLARE_INITVAR(mem_textsize) +DECLARE_INITVAR(mem_totalsize) +DECLARE_INITVAR(mem_topofmem) +DECLARE_INITVAR(mem_heapstart) +DECLARE_INITVAR(mem_bottomofmem) +DECLARE_INITVAR(mem_datareloc) +DECLARE_INITVAR(cpu_prid) + + diff --git a/cfe/cfe/arch/mips/common/include/lib_hssubr.h b/cfe/cfe/arch/mips/common/include/lib_hssubr.h new file mode 100644 index 0000000..b4df439 --- /dev/null +++ b/cfe/cfe/arch/mips/common/include/lib_hssubr.h @@ -0,0 +1,84 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * "Hyperspace" access routines File: lib_hssubr.h + * + * Constants, macros, and definitions for routines to deal with + * hyperspace (beyond 256MB) on MIPS processors. + * + * 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. + ********************************************************************* */ + + +#ifndef _LIB_HSSUBR_H +#define _LIB_HSSUBR_H + +/* + * If __long64 we can do this via macros. Otherwise, call + * the magic functions. + */ + +#if __long64 + +typedef long hsaddr_t; + +#define hs_write8(a,b) *((volatile uint8_t *) (a)) = (b) +#define hs_write16(a,b) *((volatile uint16_t *) (a)) = (b) +#define hs_write32(a,b) *((volatile uint32_t *) (a)) = (b) +#define hs_write64(a,b) *((volatile uint32_t *) (a)) = (b) +#define hs_read8(a) *((volatile uint8_t *) (a)) +#define hs_read16(a) *((volatile uint16_t *) (a)) +#define hs_read32(a) *((volatile uint32_t *) (a)) +#define hs_read64(a) *((volatile uint64_t *) (a)) + +#else /* not __long64 */ + +typedef long long hsaddr_t; + +extern void hs_write8(hsaddr_t a,uint8_t b); +extern void hs_write16(hsaddr_t a,uint16_t b); +extern void hs_write32(hsaddr_t a,uint32_t b); +extern void hs_write64(hsaddr_t a,uint64_t b); +extern uint8_t hs_read8(hsaddr_t a); +extern uint16_t hs_read16(hsaddr_t a); +extern uint32_t hs_read32(hsaddr_t a); +extern uint64_t hs_read64(hsaddr_t a); +#endif + +#endif diff --git a/cfe/cfe/arch/mips/common/include/lib_physio.h b/cfe/cfe/arch/mips/common/include/lib_physio.h new file mode 100644 index 0000000..00d0093 --- /dev/null +++ b/cfe/cfe/arch/mips/common/include/lib_physio.h @@ -0,0 +1,100 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Physical memory peek/poke routines File: lib_physio.h + * + * Little stub routines to allow access to arbitrary physical + * addresses. In most cases this should not be needed, as + * many physical addresses are within kseg1, but this handles + * the cases that are not automagically, so we don't need + * to mess up the code with icky macros and such. + * + * 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. + ********************************************************************* */ + + +#ifndef _LIB_PHYSIO_H +#define _LIB_PHYSIO_H + +//#ifndef _SB_MIPS_H +//#include "sbmips.h" +//#endif + +/* + * If __long64 we can do this via macros. Otherwise, call + * the magic functions. + */ + +#if __long64 + +typedef long physaddr_t; +#define _PHYSADDR_T_DEFINED_ + +/*#define __UNCADDRX(x) PHYS_TO_XKSEG_UNCACHED(x)*/ +#define __UNCADDRX(x) (((physaddr_t)(x))|0x9000000000000000) + + +#define phys_write8(a,b) *((volatile uint8_t *) __UNCADDRX(a)) = (b) +#define phys_write16(a,b) *((volatile uint16_t *) __UNCADDRX(a)) = (b) +#define phys_write32(a,b) *((volatile uint32_t *) __UNCADDRX(a)) = (b) +#define phys_write64(a,b) *((volatile uint64_t *) __UNCADDRX(a)) = (b) +#define phys_read8(a) *((volatile uint8_t *) __UNCADDRX(a)) +#define phys_read16(a) *((volatile uint16_t *) __UNCADDRX(a)) +#define phys_read32(a) *((volatile uint32_t *) __UNCADDRX(a)) +#define phys_read64(a) *((volatile uint64_t *) __UNCADDRX(a)) + +#else /* not __long64 */ + +#ifdef _MIPSREGS32_ +typedef long physaddr_t; /* 32-bit-only processors can't have >32bit pa's */ +#else +typedef long long physaddr_t; /* Otherwise, they might. */ +#endif + +extern void phys_write8(physaddr_t a,uint8_t b); +extern void phys_write16(physaddr_t a,uint16_t b); +extern void phys_write32(physaddr_t a,uint32_t b); +extern void phys_write64(physaddr_t a,uint64_t b); +extern uint8_t phys_read8(physaddr_t a); +extern uint16_t phys_read16(physaddr_t a); +extern uint32_t phys_read32(physaddr_t a); +extern uint64_t phys_read64(physaddr_t a); +#endif + +#endif diff --git a/cfe/cfe/arch/mips/common/include/lib_setjmp.h b/cfe/cfe/arch/mips/common/include/lib_setjmp.h new file mode 100644 index 0000000..b673222 --- /dev/null +++ b/cfe/cfe/arch/mips/common/include/lib_setjmp.h @@ -0,0 +1,81 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * setjmp/longjmp defs File: lib_setjmp.h + * + * Description of the jmp_buf structure for setjmp and longjmp + * + * 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. + ********************************************************************* */ + + +/* + * Note that while lib_setjmp() and lib_longjmp() behave like setjmp() + * and longjmp() normally do, gcc 3.1.x (and later) assumes things about + * how setjmp() and longjmp() should work (even with -fno-builtins). We + * don't want it to do those, so these functions must be named differently. + */ + +#ifdef __ASSEMBLER__ +#define _JBIDX(x) (8*(x)) +#else +#define _JBIDX(x) (x) +#endif + + +#define JMPB_S0 _JBIDX(0) +#define JMPB_S1 _JBIDX(1) +#define JMPB_S2 _JBIDX(2) +#define JMPB_S3 _JBIDX(3) +#define JMPB_S4 _JBIDX(4) +#define JMPB_S5 _JBIDX(5) +#define JMPB_S6 _JBIDX(6) +#define JMPB_S7 _JBIDX(7) +#define JMPB_FP _JBIDX(8) +#define JMPB_SP _JBIDX(9) +#define JMPB_RA _JBIDX(10) + +#define JMPB_SIZE _JBIDX(11) + +#ifndef __ASSEMBLER__ +typedef long long jmp_buf[JMPB_SIZE]; +extern int lib_setjmp(jmp_buf); +extern void lib_longjmp(jmp_buf,int val); +#endif + diff --git a/cfe/cfe/arch/mips/common/include/mipsmacros.h b/cfe/cfe/arch/mips/common/include/mipsmacros.h new file mode 100755 index 0000000..072a5e6 --- /dev/null +++ b/cfe/cfe/arch/mips/common/include/mipsmacros.h @@ -0,0 +1,376 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * MIPS Macros File: mipsmacros.h + * + * Macros to deal with various mips-related things. + * + * 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. + ********************************************************************* */ + +/* ********************************************************************* + * 32/64-bit macros + ********************************************************************* */ + +#ifdef __long64 +#define _VECT_ .dword +#define _LONG_ .dword +#define SR sd +#define LR ld +#define ADD dadd +#define SUB dsub +#define MFC0 dmfc0 +#define MTC0 dmtc0 +#define REGSIZE 8 +#define BPWSIZE 3 /* bits per word size */ +#define _TBLIDX(x) ((x)*REGSIZE) +#else +#define _VECT_ .word +#define _LONG_ .word +#define SR sw +#define LR lw +#define ADD add +#define SUB sub +#define MFC0 mfc0 +#define MTC0 mtc0 +#define REGSIZE 4 +#define BPWSIZE 2 +#define _TBLIDX(x) ((x)*REGSIZE) +#endif + + +/* ********************************************************************* + * NORMAL_VECTOR(addr,vecname,vecdest) + * NORMAL_XVECTOR(addr,vecname,vecdest,code) + * + * Declare a trap or dispatch vector. There are two flavors, + * DECLARE_XVECTOR sets up an indentifying code in k0 before + * jumping to the dispatch routine. + * + * Input parameters: + * addr - vector address + * vecname - for label at that address + * vecdest - destination (place vector jumps to) + * code - code to place in k0 before jumping + * + * Return value: + * nothing + ********************************************************************* */ + + +#define NORMAL_VECTOR(addr,vecname,vecdest) \ + .globl vecname ; \ + .org addr ; \ +vecname: b vecdest ; \ + nop; + +#define NORMAL_XVECTOR(addr,vecname,vecdest,code) \ + .globl vecname ; \ + .org addr ; \ +vecname: b vecdest ; \ + li k0,code ; \ + nop; + + +/* ********************************************************************* + * Evil macros for bi-endian support. + * + * The magic here is in the instruction encoded as 0x10000014. + * + * This instruction in big-endian is: "b .+0x54" + * this instruction in little-endian is: "bne zero,zero,.+0x44" + * + * So, depending on what the system endianness is, it will either + * branch to .+0x54 or not branch at all. + * + * the instructions that follow are: + * + * 0x10000014 "magic branch" (either-endian) + * 0x00000000 nop (bds) (either-endian) + * 0xD0BF1A3C lui k0,0xBFD0 (little-endian) + * 0xxxxx5A27 addu k0,vector (little-endian) + * 0x08004003 jr k0 (little-endian) + * 0x00000000 nop (bds) (little-endian) + * ... space up to offset 0x54 + * ......... b vecaddr (big-endian) + * + * The idea is that the big-endian firmware is first, from 0..1MB + * in the flash, and the little-endian firmware is second, + * from 1..2MB in the flash. The little-endian firmware is + * set to load at BFD00000, so that its initial routines will + * work until relocation is completed. + * + * the instructions at the vectors will either jump to the + * big-endian or little-endian code based on system endianness. + * + * The ROM is built by compiling CFE twice, first with + * CFG_BIENDIAN=1 and CFG_LITTLE=0 (big-endian) and again + * with CFG_BIENDIAN=1 and CFG_LITTLE=1. The resulting + * cfe.bin files are located at 0xBFC00000 and 0xBFD00000 + * for big and little-endian versions, respectively. + * + * More information about how this works can be found in the + * CFE Manual. + ********************************************************************* */ + +#define __SWAPW(x) ((((x) & 0xFF) << 8) | (((x) & 0xFF00) >> 8)) + +#define BIENDIAN_VECTOR(addr,vecname,vecdest) \ + .globl vecname ; \ + .org addr ; \ +vecname: .word 0x10000014 ; \ + .word 0 ; \ + .word ((__SWAPW(BIENDIAN_LE_BASE >> 16)) << 16) | 0x1A3C ; \ + .word (0x00005A27 | (((addr) & 0xFF) << 24) | (((addr) & 0xFF00) << 8)) ; \ + .word 0x08004003 ; \ + .word 0 ; \ + .org ((addr) + 0x54) ; \ + b vecdest ; \ + nop; + +#define BIENDIAN_XVECTOR(addr,vecname,vecdest,code) \ + .globl vecname ; \ + .org addr ; \ +vecname: .word 0x10000014 ; \ + .word 0 ; \ + .word ((__SWAPW(BIENDIAN_LE_BASE >> 16)) << 16) | 0x1A3C ; \ + .word (0x00005A27 | (((addr) & 0xFF) << 24) | (((addr) & 0xFF00) << 8)) ; \ + .word 0x08004003 ; \ + .word 0 ; \ + .org ((addr) + 0x54) ; \ + b vecdest ; \ + li k0,code ; \ + nop; + + + +/* ********************************************************************* + * Declare the right versions of DECLARE_VECTOR and + * DECLARE_XVECTOR depending on how we're building stuff. + * Generally, we only use the biendian version if we're building + * as CFG_BIENDIAN=1 and we're doing the big-endian MIPS version. + ********************************************************************* */ + +#if (CFG_BIENDIAN) && defined(__MIPSEB) +#define DECLARE_VECTOR BIENDIAN_VECTOR +#define DECLARE_XVECTOR BIENDIAN_XVECTOR +#else +#define DECLARE_VECTOR NORMAL_VECTOR +#define DECLARE_XVECTOR NORMAL_XVECTOR +#endif + + + +/* ********************************************************************* + * LOADREL(reg,label) + * + * Load the address of a label, but do it in a position-independent + * way. + * + * Input parameters: + * reg - register to load + * label - label whose address to load + * + * Return value: + * ra is trashed! + ********************************************************************* */ + +#if (!(CFG_RAMAPP)) +#define LOADREL(reg,label) \ + la reg, label ; \ + la ra, 100f ; \ + sub reg, ra ; \ + .set push ; \ + .set noreorder ; \ + bal 100f ; \ + nop ; \ + .set pop ; \ +100: ; \ + addu reg, ra +#else +#define LOADREL(reg,label) \ + la reg,label +#endif + +#if (CFG_RAMAPP) +#define FIXUP(addr) +#else +#define FIXUP(addr) \ + addu addr, s6 +#endif + + + +/* ********************************************************************* + * CALLINIT_KSEG1(label,table,offset) + * CALLINIT_KSEG0(label,table,offset) + * + * Call an initialization routine (usually in another module). + * If initialization routine lives in KSEG1 it may need + * special fixing if using the cached version of CFE (this is + * the default case). CFE is linked at a KSEG0 address. + * + * Embedded PIC is especially tricky, since the "la" + * instruction expands to calculations involving GP. + * In that case, use our table of offsets to + * load the routine address from a table in memory. + * + * Input parameters: + * label - routine to call if we can call directly + * table - symbol name of table containing routine addresses + * offset - offset within the above table + * + * Return value: + * k1,ra is trashed. + ********************************************************************* */ + + +#if CFG_RUNFROMKSEG0 +/* Cached PIC code - call indirect through table */ +#define CALLINIT_KSEG1(table,tableoffset) \ + LOADREL(k1,table) ; \ + or k1,K1BASE ; \ + LR k1,tableoffset(k1) ; \ + FIXUP (k1); \ + or k1,K1BASE ; \ + jal k1 +#define CALLINIT_KSEG0(table,tableoffset) \ + LOADREL(k1,table) ; \ + LR k1,tableoffset(k1) ; \ + FIXUP (k1); \ + jal k1 +#else +/* Uncached PIC code - call indirect through table, always same KSEG */ +#define CALLINIT_KSEG1(table,tableoffset) \ + LOADREL(k1,table) ; \ + LR k1,tableoffset(k1) ; \ + FIXUP (k1); \ + jal k1 +#define CALLINIT_KSEG0 CALLINIT_KSEG1 +#endif + +/* + * CALLINIT_RELOC is used once CFE's relocation is complete and + * the "mem_textreloc" variable is set up. (yes, this is nasty.) + * If 'gp' is set, we can presume that we've relocated + * and it's safe to read "mem_textreloc", otherwise use the + * address as-is from the table. + */ + +#define CALLINIT_RELOC CALLINIT_KSEG0 + +/* ********************************************************************* + * SPIN_LOCK(lock,reg1,reg2) + * + * Acquire a spin lock. + * + * Input parameters: + * lock - symbol (address) of lock to acquire + * reg1,reg2 - registers we can use to acquire lock + * + * Return value: + * nothing (lock acquired) + ********************************************************************* */ + +#define SPIN_LOCK(lock,reg1,reg2) \ + la reg1,lock ; \ +1: sync ; \ + ll reg2,0(reg1) ; \ + bne reg2,zero,1b ; \ + li reg2,1 ; \ + sc reg2,0(reg1) ; \ + beq reg2,zero,1b ; \ + nop + +/* ********************************************************************* + * SPIN_UNLOCK(lock,reg1) + * + * Release a spin lock. + * + * Input parameters: + * lock - symbol (address) of lock to release + * reg1 - a register we can use + * + * Return value: + * nothing (lock released) + ********************************************************************* */ + + +#define SPIN_UNLOCK(lock,reg1) \ + la reg1,lock ; \ + sw zero,0(reg1) + + +/* ********************************************************************* + * SETCCAMODE(treg,mode) + * + * Set cacheability mode. For some of the pass1 workarounds we + * do this alot, so here's a handy macro. + * + * Input parameters: + * treg - temporary register we can use + * mode - new mode (K_CFG_K0COH_xxx) + * + * Return value: + * nothing + ********************************************************************* */ + +#define SETCCAMODE(treg,mode) \ + mfc0 treg,C0_CONFIG ; \ + srl treg,treg,3 ; \ + sll treg,treg,3 ; \ + or treg,treg,mode ; \ + mtc0 treg,C0_CONFIG ; \ + HAZARD + + +/* ********************************************************************* + * Declare variables + ********************************************************************* */ + +#define DECLARE_LONG(x) \ + .global x ; \ +x: _LONG_ 0 + + + + +/* + * end + */ diff --git a/cfe/cfe/arch/mips/common/include/segtable.h b/cfe/cfe/arch/mips/common/include/segtable.h new file mode 100755 index 0000000..8a003f0 --- /dev/null +++ b/cfe/cfe/arch/mips/common/include/segtable.h @@ -0,0 +1,97 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Segment Table definitions File: segtable.h + * + * The 'segment table' (bad name) is just a list of addresses + * of important stuff used during initialization. We use these + * indirections to make life less complicated during code + * relocation. + * + * 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. + ********************************************************************* */ + + +#if !defined(__ASSEMBLER__) +#define _TBLIDX(x) (x) /* C handles indexing for us */ +typedef long segtable_t; /* 32 for long32, 64 for long64 */ +#endif + +/* + * Definitions for the segment_table + */ + +#define R_SEG_ETEXT _TBLIDX(0) /* end of text segment */ +#define R_SEG_FDATA _TBLIDX(1) /* Beginning of data segment */ +#define R_SEG_EDATA _TBLIDX(2) /* end of data segment */ +#define R_SEG_END _TBLIDX(3) /* End of BSS */ +#define R_SEG_FTEXT _TBLIDX(4) /* Beginning of text segment */ +#define R_SEG_FBSS _TBLIDX(5) /* Beginning of BSS */ +#define R_SEG_GP _TBLIDX(6) /* Global Pointer */ +#define R_SEG_RELOCSTART _TBLIDX(7) /* Start of reloc table */ +#define R_SEG_RELOCEND _TBLIDX(8) /* End of reloc table */ +#define R_SEG_APIENTRY _TBLIDX(9) /* API Entry address */ + +/* + * Definitions for the init_table + */ + +#define R_INIT_EARLYINIT _TBLIDX(0) /* pointer to board_earlyinit */ +#define R_INIT_SETLEDS _TBLIDX(1) /* pointer to board_setleds */ +#define R_INIT_DRAMINFO _TBLIDX(2) /* pointer to board_draminfo */ +#define R_INIT_CPUINIT _TBLIDX(3) /* pointer tp cpuinit */ +#define R_INIT_ALTCPU_START1 _TBLIDX(4) /* pointer to altcpu_start1 */ +#define R_INIT_ALTCPU_START2 _TBLIDX(5) /* pointer to altcpu_start2 */ +#define R_INIT_ALTCPU_RESET _TBLIDX(6) /* pointer to altcpu_reset */ +#define R_INIT_CPURESTART _TBLIDX(7) /* pointer to cpurestart */ +#define R_INIT_DRAMINIT _TBLIDX(8) /* pointer to draminit */ +#define R_INIT_CACHEOPS _TBLIDX(9) /* pointer to cacheops */ +#define R_INIT_TLBHANDLER _TBLIDX(10) /* pointer to TLB fault handler */ +#define R_INIT_CMDSTART _TBLIDX(11) /* pointer to cfe_main */ +#define R_INIT_CMDRESTART _TBLIDX(12) /* pointer to cfe_cmd_restart */ +#define R_INIT_DOXREQ _TBLIDX(13) /* pointer to cfe_doxreq */ +#define R_INIT_TP1_SWITCH _TBLIDX(14) /* pointer to tp1_switch */ +#define R_INIT_SIZERAM _TBLIDX(15) /* pointer to board_sizeram */ + +/* + * Definitions for the diag_table + */ + +#define R_DIAG_TEST1 _TBLIDX(0) /* after CPU and cache init, before DRAM init */ +#define R_DIAG_TEST2 _TBLIDX(1) /* after DRAM init, before main */ diff --git a/cfe/cfe/arch/mips/common/src/Makefile b/cfe/cfe/arch/mips/common/src/Makefile new file mode 100755 index 0000000..638113d --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/Makefile @@ -0,0 +1,38 @@ + +# +# This is just a Makefile fragment -- it is included by the master +# makefile, cfe.mk +# +# This file should just append object file names to "ALLOBJS", +# but since it is mean to be linked *first*, it will append +# modules to "CRT0OBJS" +# + +ifndef INIT_MIPS +INIT_MIPS = init_mips.o +endif + +ifeq ($(strip ${CFG_RAMAPP}),1) +CRT0OBJS += init_ram.o exception.o +else +CRT0OBJS += $(INIT_MIPS) +endif + +ifeq ($(strip ${CFG_RAMAPP}),1) +ALLOBJS += lib_hssubr.o lib_setjmp.o mips_arena.o exchandler.o +ALLOBJS += dev_flash_all.o dev_flashop_engine.o +ALLOBJS += ui_memtest.o +endif + +makereg : ${TOP}/hosttools/makereg.c + gcc -o makereg ${TOP}/hosttools/makereg.c + +%.inc : %.regdef makereg + ./makereg $< $@ + +ui_soccmds.o : ${CPU_SRC}/ui_soccmds.c ${CPU}_socregs.inc + +vapi.o : ${TOP}/verif/vapi.S sb1250_socregs.inc + + + diff --git a/cfe/cfe/arch/mips/common/src/cfe_ram_cached.lds b/cfe/cfe/arch/mips/common/src/cfe_ram_cached.lds new file mode 100644 index 0000000..4b8ce87 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/cfe_ram_cached.lds @@ -0,0 +1,40 @@ +OUTPUT_ARCH(mips) +ENTRY(vec_reset) +SECTIONS +{ + . = 0x9fc00000; /* was 0x9fc00000 */ + .text : +/* AT ( 0xBFC00000 ) */ /* was 0xbfc00000 */ + { + _ftext = . ; + *(.init) + eprol = .; + *(.text) + *(.fini) + *(.rodata) + _etext = .; + } + + .data : + { + _fdata = ALIGN(16) ; + *(.data) + CONSTRUCTORS + . = ALIGN(16); + _gp = . + 0x8000; + *(.sdata) + } + . = ALIGN(16); + _edata = .; + _fbss = .; + .sbss : { + *(.sbss) + *(.scommon) + } + .bss : { + *(.bss) + *(COMMON) + } + . = ALIGN(16); + _end = .; +} diff --git a/cfe/cfe/arch/mips/common/src/cfe_ram_uncached.lds b/cfe/cfe/arch/mips/common/src/cfe_ram_uncached.lds new file mode 100644 index 0000000..4295fe4 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/cfe_ram_uncached.lds @@ -0,0 +1,40 @@ +OUTPUT_ARCH(mips) +ENTRY(vec_reset) +SECTIONS +{ + . = 0xbfc00000; /* was 0x9fc00000 */ + .text : +/* AT ( 0xBFC00000 ) */ /* was 0xbfc00000 */ + { + _ftext = . ; + *(.init) + eprol = .; + *(.text) + *(.fini) + *(.rodata) + _etext = .; + } + + .data : + { + _fdata = ALIGN(16) ; + *(.data) + CONSTRUCTORS + . = ALIGN(16); + _gp = . + 0x8000; + *(.sdata) + } + . = ALIGN(16); + _edata = .; + _fbss = .; + .sbss : { + *(.sbss) + *(.scommon) + } + .bss : { + *(.bss) + *(COMMON) + } + . = ALIGN(16); + _end = .; +} diff --git a/cfe/cfe/arch/mips/common/src/cfe_ramapp.lds b/cfe/cfe/arch/mips/common/src/cfe_ramapp.lds new file mode 100755 index 0000000..5a7a377 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/cfe_ramapp.lds @@ -0,0 +1,41 @@ +OUTPUT_ARCH(mips) +ENTRY(vec_reset) +SECTIONS +{ + . = 0x80601000; + .text : + { + _ftext = . ; + *(.init) + eprol = .; + *(.text) + *(.fini) + *(.rodata) + *(.rodata.str1.4) + *(.gnu.linkonce.r.*) + _etext = .; + } + + .data : + { + _fdata = ALIGN(16) ; + *(.data) + CONSTRUCTORS + . = ALIGN(16); + _gp = . + 0x8000; + *(.sdata) + } + . = ALIGN(16); + _edata = .; + _fbss = .; + .sbss : { + *(.sbss) + *(.scommon) + } + .bss : { + *(.bss) + *(COMMON) + } + . = ALIGN(16); + _end = .; +} diff --git a/cfe/cfe/arch/mips/common/src/cfe_rom_cached.lds b/cfe/cfe/arch/mips/common/src/cfe_rom_cached.lds new file mode 100755 index 0000000..2ca1353 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/cfe_rom_cached.lds @@ -0,0 +1,40 @@ +OUTPUT_ARCH(mips) +ENTRY(vec_reset) +SECTIONS +{ + . = 0x80000000; + .text : + { + _ftext = . ; + *(.init) + eprol = .; + *(.text) + *(.fini) + *(.rodata) + _etext = .; + } + + .data : + { + _fdata = ALIGN(16) ; + *(.data) + CONSTRUCTORS + . = ALIGN(16); + _gp = . + 0x8000; + *(.sdata) + } + . = ALIGN(16); + _edata = .; + .reginfo : {} + _fbss = .; + .sbss : { + *(.sbss) + *(.scommon) + } + .bss : { + *(.bss) + *(COMMON) + } + . = ALIGN(16); + _end = .; +} diff --git a/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_cached.lds b/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_cached.lds new file mode 100644 index 0000000..ee94831 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_cached.lds @@ -0,0 +1,43 @@ +OUTPUT_ARCH(mips) +ENTRY(vec_reset) +SECTIONS +{ + . = 0x9FC00000; + .text : + AT ( 0xBFC00000 ) + { + _ftext = . ; + *(.init) + eprol = .; + *(.text) + PROVIDE (__runtime_reloc_start = .); + *(.rel.sdata) + PROVIDE (__runtime_reloc_stop = .); + *(.fini) + *(.rodata) + _etext = .; + } + .data 0x80001000 : + AT ( ((ADDR(.text)|0xB0000000) + SIZEOF ( .text ) + 15) & 0xFFFFFFF0) + { + _gp = ALIGN(16) + 0x8000; + _fdata = .; + *(.rdata) + *(.data) + CONSTRUCTORS + *(.sdata) + } + . = ALIGN(16); + _edata = .; + _fbss = .; + .sbss : { + *(.sbss) + *(.scommon) + } + .bss : { + *(.bss) + *(COMMON) + } + . = ALIGN(16); + _end = .; +} diff --git a/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_cached_biendian.lds b/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_cached_biendian.lds new file mode 100644 index 0000000..78421a4 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_cached_biendian.lds @@ -0,0 +1,49 @@ +/* + * This linker script is exactly the same as cfe_rom_reloc_cached.lds + * except our start address is at BFD00000, 1MB into the + * ROM. We locate the little-endian version of CFE at this address + * in bi-endian ROM support. + */ +OUTPUT_ARCH(mips) +ENTRY(vec_reset) +SECTIONS +{ + . = 0x9FD00000; + .text : + AT ( 0xBFD00000 ) + { + _ftext = . ; + *(.init) + eprol = .; + *(.text) + PROVIDE (__runtime_reloc_start = .); + *(.rel.sdata) + PROVIDE (__runtime_reloc_stop = .); + *(.fini) + *(.rodata) + _etext = .; + } + .data 0x80001000 : + AT ( ((ADDR(.text)|0xB0000000) + SIZEOF ( .text ) + 15) & 0xFFFFFFF0) + { + _gp = ALIGN(16) + 0x8000; + _fdata = .; + *(.rdata) + *(.data) + CONSTRUCTORS + *(.sdata) + } + . = ALIGN(16); + _edata = .; + _fbss = .; + .sbss : { + *(.sbss) + *(.scommon) + } + .bss : { + *(.bss) + *(COMMON) + } + . = ALIGN(16); + _end = .; +} diff --git a/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_uncached.lds b/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_uncached.lds new file mode 100644 index 0000000..0c62889 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_uncached.lds @@ -0,0 +1,41 @@ +OUTPUT_ARCH(mips) +ENTRY(vec_reset) +SECTIONS +{ + . = 0xBFC00000; + .text : { + _ftext = . ; + *(.init) + eprol = .; + *(.text) + PROVIDE (__runtime_reloc_start = .); + *(.rel.sdata) + PROVIDE (__runtime_reloc_stop = .); + *(.fini) + *(.rodata) + _etext = .; + } + .data 0xA0001000 : + AT ( ((ADDR(.text)|0xB0000000) + SIZEOF ( .text ) + 15) & 0xFFFFFFF0) + { + _gp = ALIGN(16) + 0x8000; + _fdata = .; + *(.rdata) + *(.data) + CONSTRUCTORS + *(.sdata) + } + . = ALIGN(16); + _edata = .; + _fbss = .; + .sbss : { + *(.sbss) + *(.scommon) + } + .bss : { + *(.bss) + *(COMMON) + } + . = ALIGN(16); + _end = .; +} diff --git a/cfe/cfe/arch/mips/common/src/cfe_rom_uncached.lds b/cfe/cfe/arch/mips/common/src/cfe_rom_uncached.lds new file mode 100644 index 0000000..a0362ba --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/cfe_rom_uncached.lds @@ -0,0 +1,39 @@ +OUTPUT_ARCH(mips) +ENTRY(vec_reset) +SECTIONS +{ + . = 0xBFC00000; + .text : { + _ftext = . ; + *(.init) + eprol = .; + *(.text) + *(.fini) + *(.rodata) + _etext = .; + } + + .data 0xA1F00000 : + AT ( ((ADDR(.text)|0xB0000000) + SIZEOF ( .text ) + 15) & 0xFFFFFFF0) + { + _fdata = ALIGN(16) ; + *(.data) + CONSTRUCTORS + . = ALIGN(16); + _gp = . + 0x8000; + *(.sdata) + } + . = ALIGN(16); + _edata = .; + _fbss = .; + .sbss : { + *(.sbss) + *(.scommon) + } + .bss : { + *(.bss) + *(COMMON) + } + . = ALIGN(16); + _end = .; +} diff --git a/cfe/cfe/arch/mips/common/src/dev_flash_all.S b/cfe/cfe/arch/mips/common/src/dev_flash_all.S new file mode 100644 index 0000000..6dbb581 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/dev_flash_all.S @@ -0,0 +1,220 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Flash "self-write" module File: flash_write_all.S + * + * This module takes care of the case of writing to the flash + * memory that CFE is currently reading its code from. It is + * assumed that you'll be doing a complete flash update, + * so this code erases the affected sectors, reprograms them, + * and jumps to the boot sector. + * + * Note: this code is written to be position-independent, even + * for non-PIC versions of CFE! It will be copied (with memcpy) + * into the heap for execution. + * + * 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 "sbmips.h" +#include "dev_flash.h" +#include "mipsmacros.h" + +#define WRITEFLASH(base,offset,value) \ + li t0,value ; \ + sb t0,offset(base) + + +/* ********************************************************************* + * flash_write_all(data,flashbase,size,secsize) + * + * Write bytes to flash, erasing affected sectors first. + * + * Input parameters: + * a0 - data - pointer to data to write + * a1 - flashbase - base (phys addr) of flash area + * a2 - size - number of bytes to write + * a3 - secsize - flash sector size + * + * Return value: + * does not return + ********************************************************************* */ + +#define data a0 +#define flashbase a1 +#define datasize a2 +#define secsize a3 + +#define secidx t4 +#define secptr t5 + +LEAF(flash_write_all) + + /* + * Mask all interrupts. An exception with BEV set would be very bad. + */ + + mfc0 v0,C0_SR # Get current interrupt flag + li v1,M_SR_IE # master interrupt control + not v1 # disable interrupts + and v0,v1 # SR now has IE=0 + mtc0 v0,C0_SR # put back into CP0 + + /* + * Get KSEG1 addr of flash + */ + + or flashbase,K1BASE + + + /* + * Do an "unlock write" sequence (cycles 1-2) + */ + + WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + + /* + * send the erase command (cycle 3) + */ + + WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_ERASE_3) + + /* + * Do an "unlock write" sequence (cycles 4-5) + */ + + WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + + /* + * Send the "erase all" qualifier (cycle 6) + */ + + WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_ERASE_ALL_6) + + /* + * Wait for the erase to complete + */ + +1: lb t0,0(secptr) # get byte + and t0,0xFF # test hi byte + bne t0,0xFF,1b # go till bit is set + + + /* + * Okay, now loop through the bytes and write them to the + * flash. + */ + + move secptr,flashbase + move secidx,datasize + +proglp: + + /* + * Do an "unlock write" sequence + */ + + WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + + /* + * Send a program command + */ + WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_PROGRAM) + + /* + * Write a byte + */ + + lbu t0,0(data) + sb t0,0(secptr) # t0 = byte written to flash + + + /* + * Wait for write to complete + */ + +1: lbu t2,0(secptr) # t2 = byte from flash + + and t1,t2,0x80 # done if bit7 of flash + and t0,t0,0x80 # is same as bit7 of data + beq t1,t0,2f + + and t1,t2,0x20 # not done if bit5 + bne t1,0x20,1b # is still set +2: + + /* + * next byte... + */ + + add a0,1 # next source byte + add secptr,1 # next dest byte + sub datasize,1 # one less count + bgt datasize,0,proglp + + /* + * All done, reboot system + */ + + li v0,0xBFC00000 + j v0 + +flash_write_all_end: + nop + +END(flash_write_all) + +/* ********************************************************************* + * Data + ********************************************************************* */ + + .sdata + + .globl flash_write_all_ptr + .globl flash_write_all_len + +flash_write_all_ptr: + _VECT_ flash_write_all +flash_write_all_len: + .word flash_write_all_end-flash_write_all + + diff --git a/cfe/cfe/arch/mips/common/src/dev_flashop_engine.S b/cfe/cfe/arch/mips/common/src/dev_flashop_engine.S new file mode 100644 index 0000000..29ade6a --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/dev_flashop_engine.S @@ -0,0 +1,695 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Flash "self-write" module File: dev_flashop_engine.S + * + * This module takes care of the case of writing to the flash + * memory that CFE is currently reading its code from. + * + * Note: this code is written to be position-independent, even + * for non-PIC versions of CFE! It will be copied (with memcpy) + * into the heap for execution. + * + * 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 "sbmips.h" +#include "mipsmacros.h" + +#include "bsp_config.h" +#include "dev_newflash.h" + +/* ********************************************************************* + * Macros + ********************************************************************* */ + +#define FLASHCMD_8(base,offset,value) \ + li t0,value ; \ + sb t0,offset(base) + +#define FLASHCMD_16(base,offset,value) \ + li t0,value ; \ + sh t0,((offset)<<1)(base) + +#define FLASHCMD_16B(base,offset,value) \ + li t0,value ; \ + sb t0,((offset)<<1)(base) + + +/* ********************************************************************* + * flashop_engine + * + * This routine is written in a PIC method to allow us to do + * flash operations without any help from CFE. We need to do + * this when we're not relocated and want to muck with the + * flash we're running from. + * + * This routine follows some simple instructions in a table, + * so you can batch up the operations in one place. + * + * Input parameters: + * a0 - pointer to instruction list + * + * Return value: + * v0 - 0 if all instructions succeeded + * else less than zero, # of failing instructions + ********************************************************************* */ + + .text + +#define reg_op t3 +#define reg_base t4 +#define reg_dest t5 +#define reg_src t6 +#define reg_cnt t7 + +LEAF(flashop_engine) + +instloop: LR reg_op,FEINST_OP(a0) /* Load instruction */ + LR reg_base,FEINST_BASE(a0) + LR reg_dest,FEINST_DEST(a0) + LR reg_src,FEINST_SRC(a0) + LR reg_cnt,FEINST_CNT(a0) + li v0,0 /* total of result values */ + li v1,0 /* result for this function */ + +#ifdef __long64 + dli t0,0x9000000000000000 /* uncached - XKPHYS */ + or reg_base,t0 /* so we can access flash beyond KSEG */ +#else + or reg_base,K1BASE /* 32-bit, regular KSEG */ +#endif + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + bne reg_op,FEOP_RETURN,99f /* Return to main prog */ + + j ra +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_REBOOT,99f /* restart system */ + + li t0,0xBFC00000 /* jump to boot vector */ + j t0 +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_READ8,99f /* Read, 8-bit mode */ + + ADD reg_src,reg_src,reg_base + +1: lbu t0,0(reg_src) /* Copy user data */ + sb t0,0(reg_dest) + ADD reg_src,1 + add reg_dest,1 + sub reg_cnt,1 + bgt reg_cnt,zero,1b + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_READ16,99f /* Read, 16-bit mode */ + + ADD reg_src,reg_src,reg_base + + li t0,1 /* test bottom bit */ + and t0,t0,reg_src /* t0 == 1 if odd */ + beq t0,zero,1f /* no odd byte to worry about */ + + SUB reg_src,reg_src,t0 /* make even value */ + lh t0,0(reg_src) /* interesting byte is odd */ +#ifdef __MIPSEB + sb t0,0(reg_dest) /* interesting byte in low 8 bits */ +#else + srl t0,t0,8 /* little endian */ + sb t0,0(reg_dest) /* interesting byte is high 8 bits */ +#endif + + ADD reg_src,2 /* advance one word (we made addr even above) */ + add reg_dest,1 /* dest always written by bytes */ + sub reg_cnt,1 + +1: beq reg_cnt,zero,nextinst + + lh t0,0(reg_src) /* Copy user data */ + +#ifdef __MIPSEB + sb t0,1(reg_dest) /* Big endian to memory */ + srl t0,t0,8 /* t0 = 0x1234 -> 0x12 0x34 */ + sb t0,0(reg_dest) +#else + sb t0,0(reg_dest) /* little endian */ + srl t0,t0,8 /* t0 = 0x1234 -> 0x34 0x12 */ + sb t0,1(reg_dest) +#endif + + ADD reg_src,2 + add reg_dest,2 + sub reg_cnt,2 + bgt reg_cnt,1,1b + + beq reg_cnt,zero,nextinst /* no straggler */ + + lh t0,0(reg_src) /* interesting byte is odd */ +#ifdef __MIPSEB + srl t0,t0,8 /* little endian */ + sb t0,0(reg_dest) /* interesting byte in high 8 bits */ +#else + sb t0,0(reg_dest) /* interesting byte is low 8 bits */ +#endif + + b nextinst +/* CFI - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +#if (FLASH_DRIVERS & FLASH_DRIVER_CFI) +99: bne reg_op,FEOP_CFIQUERY8,99f /* CFI Query 8-bit */ + + ADD reg_src,reg_src,reg_base + + FLASHCMD_8(reg_base,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_MODE) + +1: lbu t0,0(reg_src) /* Copy CFI data */ + sb t0,0(reg_dest) + ADD reg_src,1 + add reg_dest,1 + sub reg_cnt,1 + bgt reg_cnt,zero,1b + + FLASHCMD_8(reg_base,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_EXIT) + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_CFIQUERY16,99f /* CFI Query 16-bit in word mode */ + + ADD reg_src,reg_src,reg_base + + FLASHCMD_16(reg_base,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_MODE) + +1: lh t0,0(reg_src) /* Copy CFI data */ + sh t0,0(reg_dest) + ADD reg_src,2 + add reg_dest,2 + sub reg_cnt,2 + bgt reg_cnt,zero,1b + + FLASHCMD_16(reg_base,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_EXIT) + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_CFIQUERY16B,99f /* CFI Query 16-bit in byte mode */ + + ADD reg_src,reg_src,reg_base + + FLASHCMD_16B(reg_base,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_MODE) + +1: lb t0,0(reg_src) /* Copy CFI data */ + sb t0,0(reg_dest) + ADD reg_src,1 + add reg_dest,1 + sub reg_cnt,1 + bgt reg_cnt,zero,1b + + FLASHCMD_16B(reg_base,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_EXIT) + + b nextinst +#endif + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_MEMCPY,99f /* Generic memcpy */ + +1: lbu t0,0(reg_src) + sb t0,0(reg_dest) + add reg_src,1 + add reg_dest,1 + sub reg_cnt,1 + bgt reg_cnt,zero,1b + + b nextinst + + +/* AMD - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +#if (FLASH_DRIVERS & FLASH_DRIVER_AMD) +99: bne reg_op,FEOP_AMD_ERASE8,99f /* AMD erase (8-bit) */ + + ADD reg_dest,reg_dest,reg_base + + /* Do an "unlock write" sequence (cycles 1-2) */ + + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + + /* send the erase command (cycle 3) */ + + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_ERASE_3) + + /* Do an "unlock write" sequence (cycles 4-5) */ + + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + + /* Send the "erase sector" qualifier (cycle 6) */ + + FLASHCMD_8(reg_dest,0,AMD_FLASH_ERASE_SEC_6) + + /* Wait for the erase to complete */ + +1: lb t0,0(reg_dest) # get byte + and t0,0xFF # test hi byte + bne t0,0xFF,1b # go till bit is set + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_AMD_ERASE16,99f /* AMD erase (16-bit in word mode) */ + + ADD reg_dest,reg_dest,reg_base + + /* Do an "unlock write" sequence (cycles 1-2) */ + + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + + /* send the erase command (cycle 3) */ + + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_ERASE_3) + + /* Do an "unlock write" sequence (cycles 4-5) */ + + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + + /* Send the "erase sector" qualifier (cycle 6) */ + + FLASHCMD_16(reg_dest,0,AMD_FLASH_ERASE_SEC_6) + + /* Wait for the erase to complete */ + +1: lh t0,0(reg_dest) # get word + and t0,0xFF # test byte + bne t0,0xFF,1b # go till erased + + b nextinst + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_AMD_ERASE16B,99f /* AMD erase (16-bit in byte mode) */ + + ADD reg_dest,reg_dest,reg_base + + /* Do an "unlock write" sequence (cycles 1-2) */ + + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + + /* send the erase command (cycle 3) */ + + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_ERASE_3) + + /* Do an "unlock write" sequence (cycles 4-5) */ + + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + + /* Send the "erase sector" qualifier (cycle 6) */ + + FLASHCMD_16B(reg_dest,0,AMD_FLASH_ERASE_SEC_6) + + /* Wait for the erase to complete */ + +1: lh t0,0(reg_dest) # get word + and t0,0xFF # test byte + bne t0,0xFF,1b # go till erased + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_AMD_PGM8,99f /* AMD 8-bit program */ + + ADD reg_dest,reg_dest,reg_base + + /* Do an "unlock write" sequence (cycles 1-2) */ +11: + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + + /* Send a program command (cycle 3) */ + + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_PROGRAM) + + /* Write a byte (cycle 4) */ + + lbu t0,0(reg_src) + sb t0,0(reg_dest) # t0 = byte written to flash + + /* Wait for write to complete */ + +1: lbu t2,0(reg_dest) # t2 = byte from flash + + and t1,t2,0x80 # done if bit7 of flash + and t0,t0,0x80 # is same as bit7 of data + beq t1,t0,2f + + and t1,t2,0x20 # not done if bit5 + bne t1,0x20,1b # is still set +2: + + /* next byte... */ + + add reg_src,1 # next source byte + ADD reg_dest,1 # next dest byte + sub reg_cnt,1 # one less count + bgt reg_cnt,0,11b + + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_AMD_PGM16,99f /* AMD 16-bit program */ + + ADD reg_dest,reg_dest,reg_base + + /* Do an "unlock write" sequence (cycles 1-2) */ +11: + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + + /* Send a program command (cycle 3) */ + + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_PROGRAM) + + /* Write a byte (cycle 4) */ + + lh t0,0(reg_src) + sh t0,0(reg_dest) # t0 = byte written to flash + + /* Wait for write to complete */ + +1: lh t2,0(reg_dest) # t2 = byte from flash + + and t1,t2,0x80 # done if bit7 of flash + and t0,t0,0x80 # is same as bit7 of data + beq t1,t0,2f + + and t1,t2,0x20 # not done if bit5 + bne t1,0x20,1b # is still set +2: + + /* next byte... */ + + add reg_src,2 # next source word + ADD reg_dest,2 # next dest word + sub reg_cnt,2 # one less count + bgt reg_cnt,0,11b + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_AMD_PGM16B,99f /* AMD 16-bit pgm in 8-bit mode */ + + ADD reg_dest,reg_dest,reg_base + + /* Do an "unlock write" sequence (cycles 1-2) */ +11: + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + + /* Send a program command (cycle 3) */ + + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_PROGRAM) + + /* Write a byte (cycle 4) */ + + lb t0,0(reg_src) + sb t0,0(reg_dest) # t0 = byte written to flash + + /* Wait for write to complete */ + +1: lb t2,0(reg_dest) # t2 = byte from flash + + and t1,t2,0x80 # done if bit7 of flash + and t0,t0,0x80 # is same as bit7 of data + beq t1,t0,2f + + and t1,t2,0x20 # not done if bit5 + bne t1,0x20,1b # is still set +2: + + /* next byte... */ + + add reg_src,1 # next source word + ADD reg_dest,1 # next dest word + sub reg_cnt,1 # one less count + bgt reg_cnt,0,11b + + b nextinst + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_AMD_DEVCODE8,99f /* AMD 8-bit - Boot Block Location */ + + ADD reg_src,reg_src,reg_base + + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL) + + lbu t0,AMD_FLASH_DEVCODE8(reg_src) + sb t0,0(reg_dest) + li t0,AMD_FLASH_RESET + sb t0,0(reg_src) + + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_AMD_DEVCODE16,99f /* AMD 8-bit - Boot Block Location */ + + ADD reg_src,reg_src,reg_base + + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL) + + lw t0,0(reg_src) +#ifdef __MIPSEB + srl t0,t0,8 /* ((3-AMD_FLASH_DEVCODE16)*8) */ +#else + srl t0,t0,16 /* (AMD_FLASH_DEVCODE16*8) */ +#endif + sb t0,0(reg_dest) + li t0,AMD_FLASH_RESET + sb t0,0(reg_src) + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_AMD_DEVCODE16B,99f /* AMD 8-bit - Boot Block Location */ + + ADD reg_src,reg_src,reg_base + + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL) + + lw t0,0(reg_src) +#ifdef __MIPSEB +#else + srl t0,t0,16 /* (AMD_FLASH_DEVCODE16B*8)*/ +#endif + + sb t0,0(reg_dest) + li t0,AMD_FLASH_RESET + sb t0,0(reg_src) + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_AMD_MANID8,99f /* AMD 8-bit - Boot Block Location */ + + ADD reg_src,reg_src,reg_base + + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL) + + lbu t0,AMD_FLASH_MANID(reg_src) + sb t0,0(reg_dest) + li t0,AMD_FLASH_RESET + sb t0,0(reg_src) + + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_AMD_MANID16,99f /* AMD 8-bit - Boot Block Location */ + + ADD reg_src,reg_src,reg_base + + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL) + + lw t0,0(reg_src) +#ifdef __MIPSEB + srl t0,t0,((3-AMD_FLASH_MANID)*8) +#else + srl t0,t0,(AMD_FLASH_MANID*8) +#endif + sb t0,0(reg_dest) + li t0,AMD_FLASH_RESET + sb t0,0(reg_src) + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_AMD_MANID16B,99f /* AMD 8-bit - Boot Block Location */ + + ADD reg_src,reg_src,reg_base + + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL) + + lbu t0,AMD_FLASH_MANID(reg_src) + + sb t0,0(reg_dest) + li t0,AMD_FLASH_RESET + sb t0,0(reg_src) + + b nextinst + +#endif + +/* INTEL - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +#if (FLASH_DRIVERS & FLASH_DRIVER_INTEL) +99: bne reg_op,FEOP_INTEL_ERASE8,99f /* Intel erase 8-bit */ + + ADD reg_dest,reg_dest,reg_base + + FLASHCMD_8(reg_dest,0,INTEL_FLASH_ERASE_BLOCK) + FLASHCMD_8(reg_dest,0,INTEL_FLASH_ERASE_CONFIRM) + +1: lbu t0,0(reg_dest) /* loop till bit 7 is set */ + andi t0,0x80 + beq t0,zero,1b + + FLASHCMD_8(reg_dest,0,INTEL_FLASH_READ_MODE) + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_INTEL_ERASE16,99f /* Intel erase 16-bit */ + + ADD reg_dest,reg_dest,reg_base + +/* XXX copy of 8-bit erase, is this right? */ + + FLASHCMD_8(reg_dest,0,INTEL_FLASH_ERASE_BLOCK) + FLASHCMD_8(reg_dest,0,INTEL_FLASH_ERASE_CONFIRM) + +1: lbu t0,0(reg_dest) /* loop till bit 7 is set */ + andi t0,0x80 + beq t0,zero,1b + + FLASHCMD_8(reg_dest,0,INTEL_FLASH_READ_MODE) + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_INTEL_PGM8,99f /* Intel 8-bit program */ + + ADD reg_dest,reg_dest,reg_base + +11: FLASHCMD_8(reg_dest,0,INTEL_FLASH_PROGRAM) + + lbu t0,0(reg_src) + sb t0,0(reg_dest) + +1: lbu t0,0(reg_dest) /* loop till bit 7 is set */ + andi t0,0x80 + beq t0,zero,1b + + lbu t0,0(reg_dest) /* contains final result */ + /* If good, bits 1, 3, 4 will not be set */ + + add reg_src,1 + ADD reg_dest,1 + sub reg_cnt,1 + bgt reg_cnt,zero,11b + + FLASHCMD_8(reg_dest,0,INTEL_FLASH_READ_MODE) + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_INTEL_PGM16,99f /* Intel 16-bit prog */ + + ADD reg_dest,reg_dest,reg_base + +11: FLASHCMD_16(reg_dest,0,INTEL_FLASH_PROGRAM) + + lh t0,0(reg_src) + sh t0,0(reg_dest) + +1: lh t0,0(reg_dest) /* loop till bit 7 is set */ + andi t0,0x80 + beq t0,zero,1b + + lh t0,0(reg_dest) /* contains final result */ + /* If good, bits 1, 3, 4 will not be set */ + + add reg_src,2 + ADD reg_dest,2 + sub reg_cnt,2 + bgt reg_cnt,zero,11b + + FLASHCMD_16(reg_dest,0,INTEL_FLASH_READ_MODE) + + b nextinst +#endif +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: li v1,-1 /* invalid command */ + +nextinst: SR v1,FEINST_RESULT(a0) /* store result of instruction */ + ADD v0,v0,v1 /* add to total */ + ADD a0,FEINST_SIZE /* advance to next instr. */ + b instloop + +flashop_engine_end: + nop + +END(flashop_engine) + + .sdata + + .globl flashop_engine_ptr + .globl flashop_engine_len + +flashop_engine_ptr: + _VECT_ flashop_engine +flashop_engine_len: + .word flashop_engine_end-flashop_engine + + + +/* ********************************************************************* + * end + ********************************************************************* */ + + diff --git a/cfe/cfe/arch/mips/common/src/disasm.c b/cfe/cfe/arch/mips/common/src/disasm.c new file mode 100644 index 0000000..1b76fee --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/disasm.c @@ -0,0 +1,2111 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * MIPS disassembler File: disasm.c + * + * MIPS disassembler (used by ui_examcmds.c) + * + * Author: Justin Carlson (carlson@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 "disasm.h" +#include "lib_printf.h" + +#define UINT64_T(x) ((uint64_t) (x)) +#define PF_64 "ll" +#define PF_32 "" +/* These aren't guaranteed to be portable, either */ +#define SEXT_32(bit, val) \ + ((((int32_t)(val))<<(31-(bit)))>>(31-(bit))) +#define SEXT_64(bit, val) \ + ((((int64_t)(val))<<(63-(bit)))>>(63-(bit))) + +#define DATASEG __attribute__ ((section(".text"))) + + +#define REGNAME(r) (&_regnames[(r)*5]) +static const char * const _regnames = + "zero\0" + "AT\0 " + "v0\0 " + "v1\0 " + "a0\0 " + "a1\0 " + "a2\0 " + "a3\0 " + "t0\0 " + "t1\0 " + "t2\0 " + "t3\0 " + "t4\0 " + "t5\0 " + "t6\0 " + "t7\0 " + "s0\0 " + "s1\0 " + "s2\0 " + "s3\0 " + "s4\0 " + "s5\0 " + "s6\0 " + "s7\0 " + "t8\0 " + "t9\0 " + "k0\0 " + "k1\0 " + "gp\0 " + "sp\0 " + "fp\0 " + "ra\0 "; + +#define CP0REGNAME(r) (&_cp0names[(r)*12]) +static const char * const _cp0names = + "C0_INX\0 " + "C0_RAND\0 " + "C0_TLBLO0\0 " + "C0_TLBLO1\0 " + + "C0_CTEXT\0 " + "C0_PGMASK\0 " + "C0_WIRED\0 " + "C0_reserved\0" + + "C0_BADVADDR\0" + "C0_COUNT\0 " + "C0_TLBHI\0 " + "C0_COMPARE\0 " + + "C0_SR\0 " + "C0_CAUSE\0 " + "C0_EPC\0 " + "C0_PRID\0 " + + "C0_CONFIG\0 " + "C0_LLADDR\0 " + "C0_WATCHLO\0 " + "C0_WATCHHI\0 " + + "C0_XCTEXT\0 " + "C0_reserved\0" + "C0_reserved\0" + "C0_reserved\0" + + "C0_reserved\0" + "C0_reserved\0" + "C0_reserved\0" + "C0_reserved\0" + + "C0_TAGLO\0 " + "C0_TAGHI\0 " + "C0_ERREPC\0 " + "C0_reserved\0"; + + + +/* + * MIPS instruction set disassembly module. + */ + +typedef enum { + DC_RD_RS_RT, + DC_RD_RT_RS, + DC_RT_RS_SIMM, + DC_RT_RS_XIMM, + DC_RS_RT_OFS, + DC_RS_OFS, + DC_RD_RT_SA, + DC_RT_UIMM, + DC_RD, + DC_J, + DC_RD_RS, + DC_RS_RT, + DC_RT_RS, + DC_RT_RD_SEL, + DC_RT_CR_SEL, + DC_RS, + DC_RS_SIMM, + DC_RT_OFS_BASE, + DC_FT_OFS_BASE, + DC_FD_IDX_BASE, + DC_FS_IDX_BASE, + DC_FD_FS_FT, + DC_FD_FS_RT, + DC_FD_FS, + DC_PREF_OFS, + DC_PREF_IDX, + DC_CC_OFS, + DC_FD_FS_CC, + DC_RD_RS_CC, + DC_FD_FR_FS_FT, + DC_FD_FS_FT_RS, + DC_CC_FS_FT, + DC_BARE, + DC_RT_FS, + DC_SYSCALL, + DC_BREAK, + DC_VD_VS_VT_VEC, + DC_VD_VS_VT, + DC_VS_VT, + DC_VS_VT_VEC, + DC_VD_VS_VT_RS, + DC_VD_VS_VT_IMM, + DC_VD_VT, + DC_VD, + DC_VS, + DC_DEREF, + DC_OOPS +} DISASM_CLASS; + + + + +/* We're pulling some trickery here. Most of the time, this structure operates + exactly as one would expect. The special case, when type == DC_DREF, + means name points to a byte that is an index into a dereferencing array. */ + +/* + * To make matters worse, the whole module has been coded to reduce the + * number of relocations present, so we don't actually store pointers + * in the dereferencing array. Instead, we store fixed-width strings + * and use digits to represent indicies into the deref array. + * + * This is all to make more things fit in the relocatable version, + * since every initialized pointer goes into our small data segment. + */ + +typedef struct { + char name[15]; + char type; +} disasm_t; + +typedef struct { + const disasm_t *ptr; + int shift; + uint32_t mask; +} disasm_deref_t; + +/* Forward declaration of deref array, we need this for the disasm_t definitions */ + + +extern const disasm_deref_t disasm_deref[]; + +static const disasm_t disasm_normal[64] DATASEG = +{{"$1" , DC_DEREF }, + {"$2" , DC_DEREF }, + {"j" , DC_J }, + {"jal" , DC_J }, + {"beq" , DC_RS_RT_OFS }, + {"bne" , DC_RS_RT_OFS }, + {"blez" , DC_RS_OFS }, + {"bgtz" , DC_RS_OFS }, + {"addi" , DC_RT_RS_SIMM }, + {"addiu" , DC_RT_RS_SIMM }, + {"slti" , DC_RT_RS_SIMM }, + {"sltiu" , DC_RT_RS_SIMM }, + {"andi" , DC_RT_RS_XIMM }, + {"ori" , DC_RT_RS_XIMM }, + {"xori" , DC_RT_RS_XIMM }, + {"lui" , DC_RT_UIMM }, + {"$4" , DC_DEREF }, + {"$6" , DC_DEREF }, + {"invalid" , DC_BARE }, + {"$15" , DC_DEREF }, + {"beql" , DC_RS_RT_OFS }, + {"bnel" , DC_RS_RT_OFS }, + {"blezl" , DC_RS_OFS }, + {"bgtzl" , DC_RS_OFS }, + {"daddi" , DC_RT_RS_SIMM }, + {"daddiu" , DC_RT_RS_SIMM }, + {"ldl" , DC_RT_OFS_BASE }, + {"ldr" , DC_RT_OFS_BASE }, + {"$3" , DC_DEREF }, + {"invalid" , DC_BARE }, + {"$18" , DC_DEREF }, + {"invalid" , DC_BARE }, + {"lb" , DC_RT_OFS_BASE }, + {"lh" , DC_RT_OFS_BASE }, + {"lwl" , DC_RT_OFS_BASE }, + {"lw" , DC_RT_OFS_BASE }, + {"lbu" , DC_RT_OFS_BASE }, + {"lhu" , DC_RT_OFS_BASE }, + {"lwr" , DC_RT_OFS_BASE }, + {"lwu" , DC_RT_OFS_BASE }, + {"sb" , DC_RT_OFS_BASE }, + {"sh" , DC_RT_OFS_BASE }, + {"swl" , DC_RT_OFS_BASE }, + {"sw" , DC_RT_OFS_BASE }, + {"sdl" , DC_RT_OFS_BASE }, + {"sdr" , DC_RT_OFS_BASE }, + {"swr" , DC_RT_OFS_BASE }, + {"cache" , DC_BARE }, + {"ll" , DC_RT_OFS_BASE }, + {"lwc1" , DC_FT_OFS_BASE }, + {"invalid" , DC_BARE }, + {"pref" , DC_PREF_OFS }, + {"lld" , DC_RT_OFS_BASE }, + {"ldc1" , DC_FT_OFS_BASE }, + {"invalid" , DC_BARE }, + {"ld" , DC_RT_OFS_BASE }, + {"sc" , DC_RT_OFS_BASE }, + {"swc1" , DC_FT_OFS_BASE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"scd" , DC_RT_OFS_BASE }, + {"sdc1" , DC_FT_OFS_BASE }, + {"invalid" , DC_BARE }, + {"sd" , DC_RT_OFS_BASE }}; + +static const disasm_t disasm_special[64] DATASEG = +{{"sll" , DC_RD_RT_SA }, + {"$16" , DC_DEREF }, + {"srl" , DC_RD_RT_SA }, + {"sra" , DC_RD_RT_SA }, + {"sllv" , DC_RD_RT_RS }, + {"invalid" , DC_BARE }, + {"srlv" , DC_RD_RT_RS }, + {"srav" , DC_RD_RT_RS }, + {"jr" , DC_RS }, + {"jalr" , DC_RD_RS }, + {"movz" , DC_RD_RS_RT }, + {"movn" , DC_RD_RS_RT }, + {"syscall" , DC_SYSCALL }, + {"break" , DC_BREAK }, + {"invalid" , DC_BARE }, + {"sync" , DC_BARE }, + {"mfhi" , DC_RD }, + {"mthi" , DC_RS }, + {"mflo" , DC_RD }, + {"mtlo" , DC_RS }, + {"dsllv" , DC_RD_RT_RS }, + {"invalid" , DC_BARE }, + {"dsrlv" , DC_RD_RT_RS }, + {"dsrav" , DC_RD_RT_RS }, + {"mult" , DC_RS_RT }, + {"multu" , DC_RS_RT }, + {"div" , DC_RS_RT }, + {"divu" , DC_RS_RT }, + {"dmult" , DC_RS_RT }, + {"dmultu" , DC_RS_RT }, + {"ddiv" , DC_RS_RT }, + {"ddivu" , DC_RS_RT }, + {"add" , DC_RD_RS_RT }, + {"addu" , DC_RD_RS_RT }, + {"sub" , DC_RD_RS_RT }, + {"subu" , DC_RD_RS_RT }, + {"and" , DC_RD_RS_RT }, + {"or" , DC_RD_RS_RT }, + {"xor" , DC_RD_RS_RT }, + {"nor" , DC_RD_RS_RT }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"slt" , DC_RD_RS_RT }, + {"sltu" , DC_RD_RS_RT }, + {"dadd" , DC_RD_RS_RT }, + {"daddu" , DC_RD_RS_RT }, + {"dsub" , DC_RD_RS_RT }, + {"dsubu" , DC_RD_RS_RT }, + {"tge" , DC_RS_RT }, + {"tgeu" , DC_RS_RT }, + {"tlt" , DC_RS_RT }, + {"tltu" , DC_RS_RT }, + {"teq" , DC_RS_RT }, + {"invalid" , DC_BARE }, + {"tne" , DC_RS_RT }, + {"invalid" , DC_BARE }, + {"dsll" , DC_RD_RT_SA }, + {"invalid" , DC_BARE }, + {"dsrl" , DC_RD_RT_SA }, + {"dsra" , DC_RD_RT_SA }, + {"dsll32" , DC_RD_RT_SA }, + {"invalid" , DC_BARE }, + {"dsrl32" , DC_RD_RT_SA }, + {"dsra32" , DC_RD_RT_SA }}; + +static const disasm_t disasm_movci[2] DATASEG = +{{"movf" , DC_RD_RS_CC }, + {"movt" , DC_RD_RS_CC }}; + +static const disasm_t disasm_regimm[32] DATASEG = +{{"bltz" , DC_RS_OFS }, + {"bgez" , DC_RS_OFS }, + {"bltzl" , DC_RS_OFS }, + {"bgezl" , DC_RS_OFS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"tgei" , DC_RS_SIMM }, + {"tgeiu" , DC_RS_SIMM }, + {"tlti" , DC_RS_SIMM }, + {"tltiu" , DC_RS_SIMM }, + {"teqi" , DC_RS_SIMM }, + {"invalid" , DC_BARE }, + {"tnei" , DC_RS_SIMM }, + {"invalid" , DC_BARE }, + {"bltzal" , DC_RS_OFS }, + {"bgezal" , DC_RS_OFS }, + {"bltzall" , DC_RS_OFS }, + {"bgezall" , DC_RS_OFS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }}; + +static const disasm_t disasm_spec2[64] DATASEG = +{{"madd" , DC_RS_RT }, + {"maddu" , DC_RS_RT }, + {"mul" , DC_RD_RS_RT }, + {"invalid" , DC_BARE }, + {"msub" , DC_RS_RT }, + {"msubu" , DC_RS_RT }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"clz" , DC_RT_RS }, + {"clo" , DC_RT_RS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"dclz" , DC_RT_RS }, + {"dclo" , DC_RT_RS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"sdbbp" , DC_BARE }}; + +static const disasm_t disasm_cop0[32] DATASEG = +{{"mfc0@1" , DC_RT_CR_SEL }, + {"dmfc0@1" , DC_RT_CR_SEL }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"mtc0@1" , DC_RT_CR_SEL }, + {"dmtc0@1" , DC_RT_CR_SEL }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }}; + +static const disasm_t disasm_cop0_c0[64] DATASEG = +{{"invalid" , DC_BARE }, + {"tlbr" , DC_BARE }, + {"tlbwi" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"tlbwr" , DC_BARE }, + {"invalid" , DC_BARE }, + {"tlbp" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"eret" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"deret" , DC_BARE }, + {"wait" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }}; + +static const disasm_t disasm_cop1[32] DATASEG = +{{"mfc1" , DC_RT_FS }, + {"dmfc1" , DC_RT_FS }, + {"cfc1" , DC_RT_FS }, + {"invalid" , DC_BARE }, + {"mtc1" , DC_RT_FS }, + {"dmtc1" , DC_RT_FS }, + {"ctc1" , DC_RT_FS }, + {"invalid" , DC_BARE }, + {"$17" , DC_DEREF }, + {"$36" , DC_DEREF }, + {"$37" , DC_DEREF }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"$7" , DC_DEREF }, + {"$9" , DC_DEREF }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"$11" , DC_DEREF }, + {"$12" , DC_DEREF }, + {"$13" , DC_DEREF }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }}; + +static const disasm_t disasm_cop1_bc1[4] DATASEG = +{{"bc1f" , DC_CC_OFS }, + {"bc1t" , DC_CC_OFS }, + {"bc1fl" , DC_CC_OFS }, + {"bc1tl" , DC_CC_OFS }, +}; + +static const disasm_t disasm_cop1_bc1any2[2] DATASEG = +{{"bc1any2f" , DC_CC_OFS }, + {"bc1any2t" , DC_CC_OFS }, +}; + +static const disasm_t disasm_cop1_bc1any4[2] DATASEG = +{{"bc1any4f" , DC_CC_OFS }, + {"bc1any4t" , DC_CC_OFS }, +}; + +static const disasm_t disasm_cop1_s[64] DATASEG = +{{"add.s" , DC_FD_FS_FT }, + {"sub.s" , DC_FD_FS_FT }, + {"mul.s" , DC_FD_FS_FT }, + {"div.s" , DC_FD_FS_FT }, + {"sqrt.s" , DC_FD_FS }, + {"abs.s" , DC_FD_FS }, + {"mov.s" , DC_FD_FS }, + {"neg.s" , DC_FD_FS }, + {"round.l.s" , DC_FD_FS }, + {"trunc.l.s" , DC_FD_FS }, + {"ceil.l.s" , DC_FD_FS }, + {"floor.l.s" , DC_FD_FS }, + {"round.w.s" , DC_FD_FS }, + {"trunc.w.s" , DC_FD_FS }, + {"ceil.w.s" , DC_FD_FS }, + {"floor.w.s" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"$8" , DC_DEREF }, + {"movz.s" , DC_FD_FS_RT }, + {"movn.s" , DC_FD_FS_RT }, + {"invalid" , DC_BARE }, + {"recip.s" , DC_FD_FS }, + {"rsqrt.s" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"recip2.s" , DC_FD_FS_FT }, + {"recip1.s" , DC_FD_FS }, + {"rsqrt1.s" , DC_FD_FS }, + {"rsqrt2.s" , DC_FD_FS_FT }, + {"invalid" , DC_BARE }, + {"cvt.d.s" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"cvt.w.s" , DC_FD_FS }, + {"cvt.l.s" , DC_FD_FS }, + {"cvt.ps.s" , DC_FD_FS_FT }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"$38" , DC_DEREF }, + {"$39" , DC_DEREF }, + {"$40" , DC_DEREF }, + {"$41" , DC_DEREF }, + {"$42" , DC_DEREF }, + {"$43" , DC_DEREF }, + {"$44" , DC_DEREF }, + {"$45" , DC_DEREF }, + {"$46" , DC_DEREF }, + {"$47" , DC_DEREF }, + {"$48" , DC_DEREF }, + {"$49" , DC_DEREF }, + {"$50" , DC_DEREF }, + {"$51" , DC_DEREF }, + {"$52" , DC_DEREF }, + {"$53" , DC_DEREF }}; + +static const disasm_t disasm_cop1_s_mvcf[2] DATASEG = +{{"movf.s" , DC_FD_FS_CC }, + {"movt.s" , DC_FD_FS_CC }}; + +static const disasm_t disasm_cop1_d[64] DATASEG = +{{"add.d" , DC_FD_FS_FT }, + {"sub.d" , DC_FD_FS_FT }, + {"mul.d" , DC_FD_FS_FT }, + {"div.d" , DC_FD_FS_FT }, + {"sqrt.d" , DC_FD_FS }, + {"abs.d" , DC_FD_FS }, + {"mov.d" , DC_FD_FS }, + {"neg.d" , DC_FD_FS }, + {"round.l.d" , DC_FD_FS }, + {"trunc.l.d" , DC_FD_FS }, + {"ceil.l.d" , DC_FD_FS }, + {"floor.l.d" , DC_FD_FS }, + {"round.w.d" , DC_FD_FS }, + {"trunc.w.d" , DC_FD_FS }, + {"ceil.w.d" , DC_FD_FS }, + {"floor.w.d" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"$10" , DC_DEREF }, + {"movz.d" , DC_FD_FS_RT }, + {"movn.d" , DC_FD_FS_RT }, + {"invalid" , DC_BARE }, + {"recip.d" , DC_FD_FS }, + {"rsqrt.d" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"recip2.d" , DC_FD_FS_FT }, + {"recip1.d" , DC_FD_FS }, + {"rsqrt1.d" , DC_FD_FS }, + {"rsqrt2.d" , DC_FD_FS_FT }, + {"cvt.s.d" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"cvt.w.d" , DC_FD_FS }, + {"cvt.l.d" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"$54" , DC_DEREF }, + {"$55" , DC_DEREF }, + {"$56" , DC_DEREF }, + {"$57" , DC_DEREF }, + {"$58" , DC_DEREF }, + {"$59" , DC_DEREF }, + {"$60" , DC_DEREF }, + {"$61" , DC_DEREF }, + {"$62" , DC_DEREF }, + {"$63" , DC_DEREF }, + {"$64" , DC_DEREF }, + {"$65" , DC_DEREF }, + {"$66" , DC_DEREF }, + {"$67" , DC_DEREF }, + {"$68" , DC_DEREF }, + {"$69" , DC_DEREF }}; + +static const disasm_t disasm_cop1_d_mvcf[2] DATASEG = +{{"movf.d" , DC_FD_FS_CC }, + {"movt.d" , DC_FD_FS_CC }}; + +static const disasm_t disasm_cop1_w[64] DATASEG = +{{"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"cvt.s.w" , DC_FD_FS }, + {"cvt.d.w" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"cvt.ps.pw" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }}; + +static const disasm_t disasm_cop1_l[64] DATASEG = +{{"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"cvt.s.l" , DC_FD_FS }, + {"cvt.d.l" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }}; + +static const disasm_t disasm_cop1_ps[64] DATASEG = +{{"add.ps" , DC_FD_FS_FT }, + {"sub.ps" , DC_FD_FS_FT }, + {"mul.ps" , DC_FD_FS_FT }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"abs.ps" , DC_FD_FS }, + {"mov.ps" , DC_FD_FS }, + {"neg.ps" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"$14" , DC_DEREF }, + {"movz.ps" , DC_FD_FS_RT }, + {"movn.ps" , DC_FD_FS_RT }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"addr.ps" , DC_FD_FS_FT }, + {"invalid" , DC_BARE }, + {"mulr.ps" , DC_FD_FS_FT }, + {"invalid" , DC_BARE }, + {"recip2.ps" , DC_FD_FS_FT }, + {"recip1.ps" , DC_FD_FS }, + {"rsqrt1.ps" , DC_FD_FS }, + {"rsqrt2.ps" , DC_FD_FS_FT }, + {"cvt.s.pu" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"cvt.pw.ps" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"cvt.s.pl" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"pll.ps" , DC_FD_FS_FT }, + {"plu.ps" , DC_FD_FS_FT }, + {"pul.ps" , DC_FD_FS_FT }, + {"puu.ps" , DC_FD_FS_FT }, + {"$70" , DC_DEREF }, + {"$71" , DC_DEREF }, + {"$72" , DC_DEREF }, + {"$73" , DC_DEREF }, + {"$74" , DC_DEREF }, + {"$75" , DC_DEREF }, + {"$76" , DC_DEREF }, + {"$77" , DC_DEREF }, + {"$78" , DC_DEREF }, + {"$79" , DC_DEREF }, + {"$80" , DC_DEREF }, + {"$81" , DC_DEREF }, + {"$82" , DC_DEREF }, + {"$83" , DC_DEREF }, + {"$84" , DC_DEREF }, + {"$85" , DC_DEREF }}; + +static const disasm_t disasm_cop1_c_f_s[2] DATASEG = +{{"c.f.s" , DC_CC_FS_FT }, + {"cabs.f.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_un_s[2] DATASEG = +{{"c.un.s" , DC_CC_FS_FT }, + {"cabs.un.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_eq_s[2] DATASEG = +{{"c.eq.s" , DC_CC_FS_FT }, + {"cabs.eq.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ueq_s[2] DATASEG = +{{"c.ueq.s" , DC_CC_FS_FT }, + {"cabs.ueq.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_olt_s[2] DATASEG = +{{"c.olt.s" , DC_CC_FS_FT }, + {"cabs.olt.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ult_s[2] DATASEG = +{{"c.ult.s" , DC_CC_FS_FT }, + {"cabs.ult.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ole_s[2] DATASEG = +{{"c.ole.s" , DC_CC_FS_FT }, + {"cabs.ole.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ule_s[2] DATASEG = +{{"c.ule.s" , DC_CC_FS_FT }, + {"cabs.ule.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_sf_s[2] DATASEG = +{{"c.sf.s" , DC_CC_FS_FT }, + {"cabs.sf.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ngle_s[2] DATASEG = +{{"c.ngle.s" , DC_CC_FS_FT }, + {"cabs.ngle.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_seq_s[2] DATASEG = +{{"c.seq.s" , DC_CC_FS_FT }, + {"cabs.seq.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ngl_s[2] DATASEG = +{{"c.ngl.s" , DC_CC_FS_FT }, + {"cabs.ngl.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_lt_s[2] DATASEG = +{{"c.lt.s" , DC_CC_FS_FT }, + {"cabs.lt.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_nge_s[2] DATASEG = +{{"c.nge.s" , DC_CC_FS_FT }, + {"cabs.nge.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_le_s[2] DATASEG = +{{"c.le.s" , DC_CC_FS_FT }, + {"cabs.le.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ngt_s[2] DATASEG = +{{"c.ngt.s" , DC_CC_FS_FT }, + {"cabs.ngt.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_f_d[2] DATASEG = +{{"c.f.d" , DC_CC_FS_FT }, + {"cabs.f.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_un_d[2] DATASEG = +{{"c.un.d" , DC_CC_FS_FT }, + {"cabs.un.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_eq_d[2] DATASEG = +{{"c.eq.d" , DC_CC_FS_FT }, + {"cabs.eq.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ueq_d[2] DATASEG = +{{"c.ueq.d" , DC_CC_FS_FT }, + {"cabs.ueq.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_olt_d[2] DATASEG = +{{"c.olt.d" , DC_CC_FS_FT }, + {"cabs.olt.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ult_d[2] DATASEG = +{{"c.ult.d" , DC_CC_FS_FT }, + {"cabs.ult.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ole_d[2] DATASEG = +{{"c.ole.d" , DC_CC_FS_FT }, + {"cabs.ole.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ule_d[2] DATASEG = +{{"c.ule.d" , DC_CC_FS_FT }, + {"cabs.ule.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_sf_d[2] DATASEG = +{{"c.sf.d" , DC_CC_FS_FT }, + {"cabs.sf.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ngle_d[2] DATASEG = +{{"c.ngle.d" , DC_CC_FS_FT }, + {"cabs.ngle.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_seq_d[2] DATASEG = +{{"c.seq.d" , DC_CC_FS_FT }, + {"cabs.seq.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ngl_d[2] DATASEG = +{{"c.ngl.d" , DC_CC_FS_FT }, + {"cabs.ngl.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_lt_d[2] DATASEG = +{{"c.lt.d" , DC_CC_FS_FT }, + {"cabs.lt.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_nge_d[2] DATASEG = +{{"c.nge.d" , DC_CC_FS_FT }, + {"cabs.nge.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_le_d[2] DATASEG = +{{"c.le.d" , DC_CC_FS_FT }, + {"cabs.le.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ngt_d[2] DATASEG = +{{"c.ngt.d" , DC_CC_FS_FT }, + {"cabs.ngt.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_f_ps[2] DATASEG = +{{"c.f.ps" , DC_CC_FS_FT }, + {"cabs.f.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_un_ps[2] DATASEG = +{{"c.un.ps" , DC_CC_FS_FT }, + {"cabs.un.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_eq_ps[2] DATASEG = +{{"c.eq.ps" , DC_CC_FS_FT }, + {"cabs.eq.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ueq_ps[2] DATASEG = +{{"c.ueq.ps" , DC_CC_FS_FT }, + {"cabs.ueq.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_olt_ps[2] DATASEG = +{{"c.olt.ps" , DC_CC_FS_FT }, + {"cabs.olt.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ult_ps[2] DATASEG = +{{"c.ult.ps" , DC_CC_FS_FT }, + {"cabs.ult.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ole_ps[2] DATASEG = +{{"c.ole.ps" , DC_CC_FS_FT }, + {"cabs.ole.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ule_ps[2] DATASEG = +{{"c.ule.ps" , DC_CC_FS_FT }, + {"cabs.ule.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_sf_ps[2] DATASEG = +{{"c.sf.ps" , DC_CC_FS_FT }, + {"cabs.sf.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ngle_ps[2] DATASEG = +{{"c.ngle.ps" , DC_CC_FS_FT }, + {"cabs.ngle.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_seq_ps[2] DATASEG = +{{"c.seq.ps" , DC_CC_FS_FT }, + {"cabs.seq.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ngl_ps[2] DATASEG = +{{"c.ngl.ps" , DC_CC_FS_FT }, + {"cabs.ngl.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_lt_ps[2] DATASEG = +{{"c.lt.ps" , DC_CC_FS_FT }, + {"cabs.lt.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_nge_ps[2] DATASEG = +{{"c.nge.ps" , DC_CC_FS_FT }, + {"cabs.nge.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_le_ps[2] DATASEG = +{{"c.le.ps" , DC_CC_FS_FT }, + {"cabs.le.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ngt_ps[2] DATASEG = +{{"c.ngt.ps" , DC_CC_FS_FT }, + {"cabs.ngt.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_ps_mvcf[2] DATASEG = +{{"movf.ps" , DC_FD_FS_CC }, + {"movt.ps" , DC_FD_FS_CC }}; + +static const disasm_t disasm_cop1x[64] DATASEG = +{{"lwxc1" , DC_FD_IDX_BASE }, + {"ldxc1" , DC_FD_IDX_BASE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"luxc1" , DC_FD_IDX_BASE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"swxc1" , DC_FS_IDX_BASE }, + {"sdxc1" , DC_FS_IDX_BASE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"suxc1" , DC_FS_IDX_BASE }, + {"invalid" , DC_BARE }, + {"prefx" , DC_PREF_IDX }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"alnv.ps" , DC_FD_FS_FT_RS }, + {"invalid" , DC_BARE }, + {"madd.s" , DC_FD_FR_FS_FT }, + {"madd.d" , DC_FD_FR_FS_FT }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"madd.ps" , DC_FD_FR_FS_FT }, + {"invalid" , DC_BARE }, + {"msub.s" , DC_FD_FR_FS_FT }, + {"msub.d" , DC_FD_FR_FS_FT }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"msub.ps" , DC_FD_FR_FS_FT }, + {"invalid" , DC_BARE }, + {"nmadd.s" , DC_FD_FR_FS_FT }, + {"nmadd.d" , DC_FD_FR_FS_FT }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"nmadd.ps" , DC_FD_FR_FS_FT }, + {"invalid" , DC_BARE }, + {"nmsub.s" , DC_FD_FR_FS_FT }, + {"nmsub.d" , DC_FD_FR_FS_FT }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"nmsub.ps" , DC_FD_FR_FS_FT }, + {"invalid" , DC_BARE }}; + +static const disasm_t disasm_mdmx[8] DATASEG = +{{ "$20" , DC_DEREF }, + { "$19" , DC_DEREF }, + { "$20" , DC_DEREF }, + { "$33" , DC_DEREF }, + { "$20" , DC_DEREF }, + { "$19" , DC_DEREF }, + { "$20" , DC_DEREF }, + { "$33" , DC_DEREF }, +}; + +static const disasm_t disasm_mdmx_qh[64] DATASEG = +{{ "msgn.qh" , DC_VD_VS_VT_VEC}, + { "c.eq.qh" , DC_VS_VT_VEC }, + { "pickf.qh" , DC_VD_VS_VT_VEC}, + { "pickt.qh" , DC_VD_VS_VT_VEC}, + { "c.lt.qh" , DC_VS_VT_VEC }, + { "c.le.qh" , DC_VS_VT_VEC }, + { "min.qh" , DC_VD_VS_VT_VEC}, + { "max.qh" , DC_VD_VS_VT_VEC}, + + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "sub.qh" , DC_VD_VS_VT_VEC}, + { "add.qh" , DC_VD_VS_VT_VEC}, + { "and.qh" , DC_VD_VS_VT_VEC}, + { "xor.qh" , DC_VD_VS_VT_VEC}, + { "or.qh" , DC_VD_VS_VT_VEC}, + { "nor.qh" , DC_VD_VS_VT_VEC}, + + { "sll.qh" , DC_VD_VS_VT_VEC}, + { "invalid" , DC_BARE }, + { "srl.qh" , DC_VD_VS_VT_VEC}, + { "sra.qh" , DC_VD_VS_VT_VEC}, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + + { "alni.ob" , DC_VD_VS_VT_IMM}, + { "alnv.ob" , DC_VD_VS_VT_RS }, + { "alni.qh" , DC_VD_VS_VT_IMM}, + { "alnv.qh" , DC_VD_VS_VT_RS }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "$34" , DC_DEREF }, + + { "rzu.qh" , DC_VD_VT }, + { "rnau.qh" , DC_VD_VT }, + { "rneu.qh" , DC_VD_VT }, + { "invalid" , DC_BARE }, + { "rzs.qh" , DC_VD_VT }, + { "rnas.qh" , DC_VD_VT }, + { "rnes.qh" , DC_VD_VT }, + { "invalid" , DC_BARE }, + + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + + { "mul.qh" , DC_VD_VS_VT_VEC}, + { "invalid" , DC_BARE }, + { "$21" , DC_DEREF }, + { "$22" , DC_DEREF }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "$23" , DC_DEREF }, + { "$24" , DC_DEREF }, + + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "$25" , DC_DEREF }, + { "$26" , DC_DEREF }, +}; + +static const disasm_t disasm_mdmx_ob[64] DATASEG = +{{ "invalid" , DC_BARE }, + { "c.eq.ob" , DC_VS_VT_VEC }, + { "pickf.ob" , DC_VD_VS_VT_VEC}, + { "pickt.ob" , DC_VD_VS_VT_VEC}, + { "c.lt.ob" , DC_VS_VT_VEC }, + { "c.le.ob" , DC_VS_VT_VEC }, + { "min.ob" , DC_VD_VS_VT_VEC}, + { "max.ob" , DC_VD_VS_VT_VEC}, + + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "sub.ob" , DC_VD_VS_VT_VEC}, + { "add.ob" , DC_VD_VS_VT_VEC}, + { "and.ob" , DC_VD_VS_VT_VEC}, + { "xor.ob" , DC_VD_VS_VT_VEC}, + { "or.ob" , DC_VD_VS_VT_VEC}, + { "nor.ob" , DC_VD_VS_VT_VEC}, + + { "sll.ob" , DC_VD_VS_VT_VEC}, + { "invalid" , DC_BARE }, + { "srl.ob" , DC_VD_VS_VT_VEC}, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + + { "alni.ob" , DC_VD_VS_VT_IMM}, + { "alnv.ob" , DC_VD_VS_VT_RS }, + { "alni.qh" , DC_VD_VS_VT_IMM}, + { "alnv.qh" , DC_VD_VS_VT_RS }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "$35" , DC_DEREF }, + + { "rzu.ob" , DC_VD_VT }, + { "rnau.ob" , DC_VD_VT }, + { "rneu.ob" , DC_VD_VT }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + + { "mul.ob" , DC_VD_VS_VT_VEC}, + { "invalid" , DC_BARE }, + { "$27" , DC_DEREF }, + { "$28" , DC_DEREF }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "$29" , DC_DEREF }, + { "$30" , DC_DEREF }, + + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "$31" , DC_DEREF }, + { "$32" , DC_DEREF }, +}; + +static const disasm_t disasm_mdmx_alni[64] DATASEG = +{{ "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + + { "alni.ob" , DC_VD_VS_VT_IMM}, + { "alnv.ob" , DC_VD_VS_VT_RS }, + { "alni.qh" , DC_VD_VS_VT_IMM}, + { "alnv.qh" , DC_VD_VS_VT_RS }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, +}; + +static const disasm_t disasm_mdmx_muls_qh[2] DATASEG = +{{ "muls.qh" , DC_VS_VT_VEC }, + { "mulsl.qh" , DC_VS_VT_VEC }, +}; + +static const disasm_t disasm_mdmx_mul_qh[2] DATASEG = +{{ "mula.qh" , DC_VS_VT_VEC }, + { "mull.qh" , DC_VS_VT_VEC }, +}; + +static const disasm_t disasm_mdmx_sub_qh[2] DATASEG = +{{ "suba.qh" , DC_VS_VT_VEC }, + { "subl.qh" , DC_VS_VT_VEC }, +}; + +static const disasm_t disasm_mdmx_add_qh[2] DATASEG = +{{ "adda.qh" , DC_VS_VT_VEC }, + { "addl.qh" , DC_VS_VT_VEC }, +}; + +static const disasm_t disasm_mdmx_wac_qh[4] DATASEG = +{{ "wacl.qh" , DC_VS_VT }, + { "invalid" , DC_BARE }, + { "wach.qh" , DC_VS }, + { "invalid" , DC_BARE }, +}; + +static const disasm_t disasm_mdmx_rac_qh[4] DATASEG = +{{ "racl.qh" , DC_VD }, + { "racm.qh" , DC_VD }, + { "rach.qh" , DC_VD }, + { "invalid" , DC_BARE }, +}; + +static const disasm_t disasm_mdmx_muls_ob[2] DATASEG = +{{ "muls.ob" , DC_VS_VT_VEC }, + { "mulsl.ob" , DC_VS_VT_VEC }, +}; + +static const disasm_t disasm_mdmx_mul_ob[2] DATASEG = +{{ "mula.ob" , DC_VS_VT_VEC }, + { "mull.ob" , DC_VS_VT_VEC }, +}; + +static const disasm_t disasm_mdmx_sub_ob[2] DATASEG = +{{ "suba.ob" , DC_VS_VT_VEC }, + { "subl.ob" , DC_VS_VT_VEC }, +}; + +static const disasm_t disasm_mdmx_add_ob[2] DATASEG = +{{ "adda.ob" , DC_VS_VT_VEC }, + { "addl.ob" , DC_VS_VT_VEC }, +}; + +static const disasm_t disasm_mdmx_wac_ob[4] DATASEG = +{{ "wacl.ob" , DC_VS_VT }, + { "invalid" , DC_BARE }, + { "wach.ob" , DC_VS }, + { "invalid" , DC_BARE }, +}; + +static const disasm_t disasm_mdmx_rac_ob[4] DATASEG = +{{ "racl.ob" , DC_VD }, + { "racm.ob" , DC_VD }, + { "rach.ob" , DC_VD }, + { "invalid" , DC_BARE }, +}; + +static const disasm_t disasm_mdmx_shfl_ob[16] DATASEG = +{{ "shfl.upsl.ob" , DC_VD_VS_VT }, + { "shfl.pach.ob" , DC_VD_VS_VT }, + { "shfl.mixh.ob" , DC_VD_VS_VT }, + { "shfl.mixl.ob" , DC_VD_VS_VT }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, +}; + +static const disasm_t disasm_mdmx_shfl_qh[8] DATASEG = +{{ "shfl.bfla.qh" , DC_VD_VS_VT }, + { "shfl.pach.qh" , DC_VD_VS_VT }, + { "shfl.mixh.qh" , DC_VD_VS_VT }, + { "shfl.mixl.qh" , DC_VD_VS_VT }, + { "shfl.repa.qh" , DC_VD_VS_VT }, + { "shfl.repb.qh" , DC_VD_VS_VT }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, +}; + + + +const disasm_deref_t disasm_deref[] = +/* Disasm array shft msk */ +{{ disasm_normal , 26, 0x3f }, /* 0 */ + { disasm_special , 0, 0x3f }, /* 1 */ + { disasm_regimm , 16, 0x1f }, /* 2 */ + { disasm_spec2 , 0, 0x3f }, /* 3 */ + { disasm_cop0 , 21, 0x1f }, /* 4 */ + { disasm_cop0_c0 , 0, 0x3f }, /* 5 */ + { disasm_cop1 , 21, 0x1f }, /* 6 */ + { disasm_cop1_s , 0, 0x3f }, /* 7 */ + { disasm_cop1_s_mvcf , 16, 0x1 }, /* 8 */ + { disasm_cop1_d , 0, 0x3f }, /* 9 */ + { disasm_cop1_d_mvcf , 16, 0x1 }, /* 10 */ + { disasm_cop1_w , 0, 0x3f }, /* 11 */ + { disasm_cop1_l , 0, 0x3f }, /* 12 */ + { disasm_cop1_ps , 0, 0x3f }, /* 13 */ + { disasm_cop1_ps_mvcf, 16, 0x1 }, /* 14 */ + { disasm_cop1x , 0, 0x3f }, /* 15 */ + { disasm_movci , 16, 0x1 }, /* 16 */ + { disasm_cop1_bc1 , 16, 0x3 }, /* 17 */ + { disasm_mdmx , 21, 0x7 }, /* 18 */ + { disasm_mdmx_qh , 0, 0x3f }, /* 19 */ + { disasm_mdmx_ob , 0, 0x3f }, /* 20 */ + { disasm_mdmx_muls_qh, 10, 0x1 }, /* 21 */ + { disasm_mdmx_mul_qh , 10, 0x1 }, /* 22 */ + { disasm_mdmx_sub_qh , 10, 0x1 }, /* 23 */ + { disasm_mdmx_add_qh , 10, 0x1 }, /* 24 */ + { disasm_mdmx_wac_qh , 24, 0x3 }, /* 25 */ + { disasm_mdmx_rac_qh , 24, 0x3 }, /* 26 */ + { disasm_mdmx_muls_ob, 10, 0x1 }, /* 27 */ + { disasm_mdmx_mul_ob , 10, 0x1 }, /* 28 */ + { disasm_mdmx_sub_ob , 10, 0x1 }, /* 29 */ + { disasm_mdmx_add_ob , 10, 0x1 }, /* 30 */ + { disasm_mdmx_wac_ob , 24, 0x3 }, /* 31 */ + { disasm_mdmx_rac_ob , 24, 0x3 }, /* 32 */ + { disasm_mdmx_alni , 0, 0x3f }, /* 33 */ + { disasm_mdmx_shfl_ob, 22, 0xf }, /* 34 */ + { disasm_mdmx_shfl_qh, 23, 0x7 }, /* 35 */ + { disasm_cop1_bc1any2, 16, 0x1 }, /* 36 */ + { disasm_cop1_bc1any4, 16, 0x1 }, /* 37 */ + { disasm_cop1_c_f_s , 6, 0x1 }, /* 38 */ + { disasm_cop1_c_un_s , 6, 0x1 }, /* 39 */ + { disasm_cop1_c_eq_s , 6, 0x1 }, /* 40 */ + { disasm_cop1_c_ueq_s, 6, 0x1 }, /* 41 */ + { disasm_cop1_c_olt_s, 6, 0x1 }, /* 42 */ + { disasm_cop1_c_ult_s, 6, 0x1 }, /* 43 */ + { disasm_cop1_c_ole_s, 6, 0x1 }, /* 44 */ + { disasm_cop1_c_ule_s, 6, 0x1 }, /* 45 */ + { disasm_cop1_c_sf_s , 6, 0x1 }, /* 46 */ + { disasm_cop1_c_ngle_s, 6, 0x1 }, /* 47 */ + { disasm_cop1_c_seq_s, 6, 0x1 }, /* 48 */ + { disasm_cop1_c_ngl_s, 6, 0x1 }, /* 49 */ + { disasm_cop1_c_lt_s , 6, 0x1 }, /* 50 */ + { disasm_cop1_c_nge_s, 6, 0x1 }, /* 51 */ + { disasm_cop1_c_le_s , 6, 0x1 }, /* 52 */ + { disasm_cop1_c_ngt_s, 6, 0x1 }, /* 53 */ + { disasm_cop1_c_f_d , 6, 0x1 }, /* 54 */ + { disasm_cop1_c_un_d , 6, 0x1 }, /* 55 */ + { disasm_cop1_c_eq_d , 6, 0x1 }, /* 56 */ + { disasm_cop1_c_ueq_d, 6, 0x1 }, /* 57 */ + { disasm_cop1_c_olt_d, 6, 0x1 }, /* 58 */ + { disasm_cop1_c_ult_d, 6, 0x1 }, /* 59 */ + { disasm_cop1_c_ole_d, 6, 0x1 }, /* 60 */ + { disasm_cop1_c_ule_d, 6, 0x1 }, /* 61 */ + { disasm_cop1_c_sf_d , 6, 0x1 }, /* 62 */ + { disasm_cop1_c_ngle_d, 6, 0x1 }, /* 63 */ + { disasm_cop1_c_seq_d, 6, 0x1 }, /* 64 */ + { disasm_cop1_c_ngl_d, 6, 0x1 }, /* 65 */ + { disasm_cop1_c_lt_d , 6, 0x1 }, /* 66 */ + { disasm_cop1_c_nge_d, 6, 0x1 }, /* 67 */ + { disasm_cop1_c_le_d , 6, 0x1 }, /* 68 */ + { disasm_cop1_c_ngt_d, 6, 0x1 }, /* 69 */ + { disasm_cop1_c_f_ps , 6, 0x1 }, /* 70 */ + { disasm_cop1_c_un_ps, 6, 0x1 }, /* 71 */ + { disasm_cop1_c_eq_ps, 6, 0x1 }, /* 72 */ + { disasm_cop1_c_ueq_ps, 6, 0x1 }, /* 73 */ + { disasm_cop1_c_olt_ps, 6, 0x1 }, /* 74 */ + { disasm_cop1_c_ult_ps, 6, 0x1 }, /* 75 */ + { disasm_cop1_c_ole_ps, 6, 0x1 }, /* 76 */ + { disasm_cop1_c_ule_ps, 6, 0x1 }, /* 77 */ + { disasm_cop1_c_sf_ps, 6, 0x1 }, /* 78 */ + { disasm_cop1_c_ngle_ps, 6, 0x1 }, /* 79 */ + { disasm_cop1_c_seq_ps, 6, 0x1 }, /* 80 */ + { disasm_cop1_c_ngl_ps, 6, 0x1 }, /* 81 */ + { disasm_cop1_c_lt_ps, 6, 0x1 }, /* 82 */ + { disasm_cop1_c_nge_ps, 6, 0x1 }, /* 83 */ + { disasm_cop1_c_le_ps, 6, 0x1 }, /* 84 */ + { disasm_cop1_c_ngt_ps, 6, 0x1 }, /* 85 */ +}; + +#define PREFHINT(x) (&pref_hints[(x)*9]) +static char *pref_hints = + "load \0" + "store \0" + "reserved\0" + "reserved\0" + + "ld_strm \0" + "st_strm \0" + "ld_retn \0" + "st_retn \0" + + "reserved\0" + "reserved\0" + "reserved\0" + "reserved\0" + + "reserved\0" + "reserved\0" + "reserved\0" + "reserved\0" + + "reserved\0" + "reserved\0" + "reserved\0" + "reserved\0" + + "reserved\0" + "reserved\0" + "reserved\0" + "reserved\0" + + "reserved\0" + "wb_inval\0" + "reserved\0" + "reserved\0" + + "reserved\0" + "reserved\0" + "reserved\0" + "reserved\0"; + + +static int snprintf(char *buf,int len,const char *templat,...) +{ + va_list marker; + int count; + + va_start(marker,templat); + count = xvsprintf(buf,templat,marker); + va_end(marker); + + return count; +} + +static const disasm_t *get_disasm_field(uint32_t inst) +{ + const disasm_deref_t *tmp = &disasm_deref[0]; + const disasm_t *rec; + do { + rec = &(tmp->ptr[(inst>>tmp->shift) & tmp->mask]); + tmp = &disasm_deref[atoi(&(rec->name[1]))]; + } while (rec->type == DC_DEREF); + return rec; +} + +char *disasm_inst_name(uint32_t inst) +{ + return (char *)(get_disasm_field(inst)->name); +} + +void disasm_inst(char *buf, int buf_size, uint32_t inst, uint64_t pc) +{ + const disasm_t *tmp; + char instname[32]; + int commentmode = 0; + char *x; + + tmp = get_disasm_field(inst); + + strcpy(instname,(char *) tmp->name); + + if ((x = strchr(instname,'@'))) { + *x++ = 0; + commentmode = atoi(x); + } + + switch (tmp->type) { + case DC_RD_RS_RT: + snprintf(buf, buf_size, "%-8s %s,%s,%s", + instname, + REGNAME((inst>>11) & 0x1f), + REGNAME((inst>>21) & 0x1f), + REGNAME((inst>>16) & 0x1f)); + break; + case DC_RD_RT_RS: + snprintf(buf, buf_size, "%-8s %s,%s,%s", + instname, + REGNAME((inst>>11) & 0x1f), + REGNAME((inst>>16) & 0x1f), + REGNAME((inst>>21) & 0x1f)); + break; + case DC_RT_RS_SIMM: + snprintf(buf, buf_size, "%-8s %s,%s,#%" PF_32 "d", + instname, + REGNAME((inst>>16) & 0x1f), + REGNAME((inst>>21) & 0x1f), + SEXT_32(15, inst & 0xffff)); + break; + case DC_RT_RS_XIMM: + snprintf(buf, buf_size, "%-8s %s,%s,#0x%" PF_32 "x", + instname, + REGNAME((inst>>16) & 0x1f), + REGNAME((inst>>21) & 0x1f), + inst & 0xffff); + break; + case DC_RS_RT_OFS: + snprintf(buf, buf_size, "%-8s %s,%s,0x%" PF_64 "x", + instname, + REGNAME((inst>>21) & 0x1f), + REGNAME((inst>>16) & 0x1f), + pc + 4 + (SEXT_64(15, inst & 0xffff)<<2)); + break; + case DC_RS_OFS: + snprintf(buf, buf_size, "%-8s %s,0x%" PF_64 "x", + instname, + REGNAME((inst>>21) & 0x1f), + pc + 4 + (SEXT_64(16, inst & 0xffff)<<2)); + break; + case DC_RD_RT_SA: + snprintf(buf, buf_size, "%-8s %s,%s,#%d", + instname, + REGNAME((inst>>11) & 0x1f), + REGNAME((inst>>16) & 0x1f), + (inst>>6) & 0x1f); + break; + case DC_RT_UIMM: + snprintf(buf, buf_size, "%-8s %s,#%d", + instname, + REGNAME((inst>>16) & 0x1f), + inst & 0xffff); + break; + case DC_RD: + snprintf(buf, buf_size, "%-8s %s", + instname, + REGNAME((inst>>11) & 0x1f)); + break; + case DC_J: + snprintf(buf, buf_size, "%-8s 0x%" PF_64 "x", + instname, + (pc & UINT64_T(0xfffffffff0000000)) | ((inst & 0x3ffffff)<<2)); + break; + case DC_RD_RS: + snprintf(buf, buf_size, "%-8s %s,%s", + instname, + REGNAME((inst>>11) & 0x1f), + REGNAME((inst>>21) & 0x1f)); + break; + case DC_RS_RT: + snprintf(buf, buf_size, "%-8s %s,%s", + instname, + REGNAME((inst>>21) & 0x1f), + REGNAME((inst>>16) & 0x1f)); + break; + case DC_RT_RS: + snprintf(buf, buf_size, "%-8s %s,%s", + instname, + REGNAME((inst>>16) & 0x1f), + REGNAME((inst>>21) & 0x1f)); + break; + case DC_RT_RD_SEL: + snprintf(buf, buf_size, "%-8s %s,%s,#%d", + instname, + REGNAME((inst>>16) & 0x1f), + REGNAME((inst>>11) & 0x1f), + inst & 0x3); + break; + case DC_RT_CR_SEL: + snprintf(buf, buf_size, "%-8s %s,%d,#%d", + instname, + REGNAME((inst>>16) & 0x1f), + (inst>>11) & 0x1f, + inst & 0x3); + break; + case DC_RS: + snprintf(buf, buf_size, "%-8s %s", + instname, + REGNAME((inst>>21) & 0x1f)); + break; + case DC_RS_SIMM: + snprintf(buf, buf_size, "%-8s %s,#%" PF_32 "d", + instname, + REGNAME((inst>>21) & 0x1f), + SEXT_32(15, inst & 0xffff)); + break; + case DC_RT_OFS_BASE: + snprintf(buf, buf_size, "%-8s %s,#%" PF_32 "d(%s)", + instname, + REGNAME((inst>>16) & 0x1f), + SEXT_32(15, inst), + REGNAME((inst>>21) & 0x1f)); + break; + case DC_FT_OFS_BASE: + snprintf(buf, buf_size, "%-8s f%d,#%" PF_32 "d(%s)", + instname, + (inst>>16) & 0x1f, + SEXT_32(15, inst), + REGNAME((inst>>21) & 0x1f)); + break; + case DC_FD_IDX_BASE: + snprintf(buf, buf_size, "%-8s f%d,%s(%s)", + instname, + (inst>>6) & 0x1f, + REGNAME((inst>>16) & 0x1f), + REGNAME((inst>>21) & 0x1f)); + break; + case DC_FS_IDX_BASE: + snprintf(buf, buf_size, "%-8s f%d,%s(%s)", + instname, + (inst>>11) & 0x1f, + REGNAME((inst>>16) & 0x1f), + REGNAME((inst>>21) & 0x1f)); + break; + case DC_FD_FS_FT: + snprintf(buf, buf_size, "%-8s f%d,f%d,f%d", + instname, + (inst>>6) & 0x1f, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f); + break; + case DC_FD_FS_RT: + snprintf(buf, buf_size, "%-8s f%d,f%d,%s", + instname, + (inst>>6) & 0x1f, + (inst>>11) & 0x1f, + REGNAME((inst>>16) & 0x1f)); + break; + case DC_FD_FS: + snprintf(buf, buf_size, "%-8s f%d,f%d", + instname, + (inst>>6)&0x1f, + (inst>>11)&0x1f); + break; + case DC_PREF_OFS: + snprintf(buf, buf_size, "%-8s #%" PF_32 "d(%s) /* %s */", + instname, + SEXT_32(15, inst & 0xffff), + REGNAME((inst>>21) & 0x1f), + PREFHINT((inst>>16) & 0x1f)); + break; + case DC_PREF_IDX: + snprintf(buf, buf_size, "%-8s %s(%s) /* %s */", + instname, + REGNAME((inst>>16) & 0x1f), + REGNAME((inst>>21) & 0x1f), + PREFHINT((inst>>16) & 0x1f)); + break; + case DC_CC_OFS: + snprintf(buf, buf_size, "%-8s %d,0x%" PF_64 "x", + instname, + (inst>>18) & 0x7, + pc + 4 + (SEXT_64(15, inst & 0xffff)<<2)); + break; + case DC_RD_RS_CC: + snprintf(buf, buf_size, "%-8s %s,%s,%d", + instname, + REGNAME((inst>>11) & 0x1f), + REGNAME((inst>>21) & 0x1f), + (inst>>18) & 0x7); + break; + case DC_FD_FS_CC: + snprintf(buf, buf_size, "%-8s f%d,f%d,%d", + instname, + (inst>>6) & 0x1f, + (inst>>11) & 0x1f, + (inst>>18) & 0x7); + break; + case DC_FD_FR_FS_FT: + snprintf(buf, buf_size, "%-8s f%d,f%d,f%d,f%d", + instname, + (inst>>6) & 0x1f, + (inst>>21) & 0x1f, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f); + break; + case DC_FD_FS_FT_RS: + snprintf(buf, buf_size, "%-8s f%d,f%d,f%d,%s", + instname, + (inst>>6) & 0x1f, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f, + REGNAME((inst>>21) & 0x1f)); + break; + case DC_CC_FS_FT: + snprintf(buf, buf_size, "%-8s %d,f%d,f%d", + instname, + (inst>>8) & 0x7, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f); + break; + case DC_BARE: + snprintf(buf, buf_size, "%-8s", instname); + break; + case DC_RT_FS: + snprintf(buf, buf_size, "%-8s %s,f%d", + instname, + REGNAME((inst>>16) & 0x1f), + (inst>>11) & 0x1f); + break; + case DC_VS: + snprintf(buf, buf_size, "%-8s $v%d", + instname, + (inst>>11) & 0x1f); + break; + case DC_VD: + snprintf(buf, buf_size, "%-8s $v%d", + instname, + (inst>>6) & 0x1f); + break; + case DC_VD_VT: + snprintf(buf, buf_size, "%-8s $v%d,$v%d", + instname, + (inst>>6) & 0x1f, + (inst>>16) & 0x1f); + break; + case DC_VD_VS_VT_IMM: + snprintf(buf, buf_size, "%-8s $v%d,$v%d,$v%d,#%d", + instname, + (inst>>6) & 0x1f, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f, + (inst>>21) & 0x7); + break; + case DC_VD_VS_VT_RS: + snprintf(buf, buf_size, "%-8s $v%d,$v%d,$v%d,%s", + instname, + (inst>>6) & 0x1f, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f, + REGNAME((inst>>21) & 0x1f)); + break; + case DC_VD_VS_VT: + snprintf(buf, buf_size, "%-8s $v%d,$v%d,$v%d", + instname, + (inst>>6) & 0x1f, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f); + break; + case DC_VS_VT: + snprintf(buf, buf_size, "%-8s $v%d,$v%d", + instname, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f); + break; + case DC_VS_VT_VEC: + switch((inst>>24) & 0x3) { + case 0: + case 1: + /* element select */ + if ((inst>>21) & 1) { + /* QH */ + snprintf(buf, buf_size, "%-8s $v%d,$v%d[%d]", + instname, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f, + (inst>>23) & 0x3); + } else { + /* OB */ + snprintf(buf, buf_size, "%-8s $v%d,$v%d[%d]", + instname, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f, + (inst>>22) & 0x7); + + } + break; + case 2: + /* Vector select */ + snprintf(buf, buf_size, "%-8s $v%d,$v%d", + instname, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f); + break; + case 3: + /* immediate select */ + snprintf(buf, buf_size, "%-8s $v%d,$#%d", + instname, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f); + break; + } + break; + + case DC_VD_VS_VT_VEC: + switch((inst>>24) & 0x3) { + case 0: + case 1: + /* element select */ + if ((inst>>21) & 1) { + /* QH */ + snprintf(buf, buf_size, "%-8s $v%d,$v%d,$v%d[%d]", + instname, + (inst>>6) & 0x1f, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f, + (inst>>23) & 0x3); + } else { + /* OB */ + snprintf(buf, buf_size, "%-8s $v%d,$v%d,$v%d[%d]", + instname, + (inst>>6) & 0x1f, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f, + (inst>>22) & 0x7); + + } + break; + case 2: + /* Vector select */ + snprintf(buf, buf_size, "%-8s $v%d,$v%d,$v%d", + instname, + (inst>>6) & 0x1f, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f); + break; + case 3: + /* immediate select */ + snprintf(buf, buf_size, "%-8s $v%d,$v%d,$#%d", + instname, + (inst>>6) & 0x1f, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f); + break; + } + break; + + case DC_SYSCALL: + snprintf(buf, buf_size, "%-8s #%d", + instname, + (inst>>6) & 0xfffff); + break; + case DC_BREAK: + snprintf(buf, buf_size, "%-8s %d", instname, (inst>>6)&0xfffff); + break; + case DC_OOPS: + snprintf(buf, buf_size, "%s OOPS! FIXME!", instname); + break; + default: + /* Hit something we don't know about...Shouldn't happen. */ + break; + } + + /* + * Handle comment field + */ + + + switch (commentmode) { + case 1: /* CP0 ops */ + if ((inst & 3) == 0) { /* select 0 */ + snprintf(buf + strlen(buf),buf_size-strlen(buf)," /* %s */", + CP0REGNAME((inst >> 11) & 0x1f)); + } + break; + default: + break; + } + + buf[buf_size-1] = 0; + +} diff --git a/cfe/cfe/arch/mips/common/src/exception.S b/cfe/cfe/arch/mips/common/src/exception.S new file mode 100644 index 0000000..8036b35 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/exception.S @@ -0,0 +1,546 @@ +/* ********************************************************************* + * SB1250 Board Support Package + * + * Exception Handler File: exception.S + * + * 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 "sbmips.h" +#include "exception.h" +#include "mipsmacros.h" +#include "cpu_config.h" /* for definition of HAZARD and ERET */ +#include "bsp_config.h" + +/* ********************************************************************* + * Macros + ********************************************************************* */ + +#ifdef _MIPSREGS32_ +#define LREG lw +#define SREG sw +#define SRL srl +#define SLL sll +#else +#define LREG ld +#define SREG sd +#define SRL dsrl +#define SLL dsll +#endif + + +/* ********************************************************************* + * Data + ********************************************************************* */ + + .sdata + + .globl _exc_vectab +_exc_vectab: _LONG_ 0 # XTYPE_RESET + _LONG_ 0 # XTYPE_TLBFILL (not used) + _LONG_ 0 # XTYPE_XTLBFILL + _LONG_ 0 # XTYPE_CACHEERR (not used) + _LONG_ 0 # XTYPE_EXCEPTION + _LONG_ 0 # XTYPE_INTERRUPT + _LONG_ 0 # XTYPE_EJTAG + +/* ********************************************************************* + * Common Data + ********************************************************************* */ + + .bss + + +/* ********************************************************************* + * Code + ********************************************************************* */ + + .text + +#define R_EXC_CERR_TEMPLATE _TBLIDX(0) +#define R_EXC_CERR_TEMPLATE_END _TBLIDX(1) + + .globl _exc_cerr_htable +_exc_cerr_htable: + _LONG_ _exc_cerr_template + _LONG_ _exc_cerr_template_end + + +/* ********************************************************************* + * _exc_cerr_template + * + * This is a template routine for our cache error handler. + * We save a couple of registers in our magic save area, then + * dispatch to code elsewhere in CFE. + * + * This code is copied right to the vector address, so it has + * to be kept tiny! + * + * Input parameters: + * nothing - running uncached, all registers trashed + * + * Return value: + * might return, might not + ********************************************************************* */ + +LEAF(_exc_cerr_template) + + /* + * Magic! When the cache error handler is running, + * we are in a very special state, running uncached + * and with translations turned off. We can use offsets + * from r0(zero) to store registers we need to use + * during the error handler. + */ + + .set push ; .set noreorder + + SR k0,CFE_LOCORE_GLOBAL_K0TMP(zero) + SR k1,CFE_LOCORE_GLOBAL_K1TMP(zero) + SR ra,CFE_LOCORE_GLOBAL_RATMP(zero) + SR gp,CFE_LOCORE_GLOBAL_GPTMP(zero) + + LR k0,CFE_LOCORE_GLOBAL_CERRH(zero) + jal k0 + nop + + LR k0,CFE_LOCORE_GLOBAL_K0TMP(zero) + LR k1,CFE_LOCORE_GLOBAL_K1TMP(zero) + LR ra,CFE_LOCORE_GLOBAL_RATMP(zero) + LR gp,CFE_LOCORE_GLOBAL_GPTMP(zero) + ERET + + .set pop + + /* + * Note: make sure this routine does not exceed 128 bytes + */ + +_exc_cerr_template_end: + +END(_exc_cerr_template) + +/* ********************************************************************* + * _exc_setup_locore(cerrh) + * + * Set global data into the low-memory region. We do this in + * assembly language so it's easier to deal with the 32-bit/64-bit + * issues that arise in the "C" code. + * + * Input parameters: + * a0 - cache error handler + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(_exc_setup_locore) + + move t4,ra + + /* + * Save GP for easy re-use, using uncached writes. + */ + + li t0,PHYS_TO_K1(CFE_LOCORE_GLOBAL_GP) + SR gp,0(t0) + + /* + * Initialize cache error handler pointer. Make it + * uncached, since cache error handlers should not + * touch the cache. + */ + + li t1,(K0SIZE-1) + and a0,a0,t1 # keep just physical part + li t1,K1BASE + or a0,a0,t1 # make into an uncached address + + li t0,PHYS_TO_K1(CFE_LOCORE_GLOBAL_CERRH) + SR a0,0(t0) + + /* + * Move the cache error handler into low RAM. + */ + + li t0,PHYS_TO_K1(MIPS_RAM_VEC_CACHEERR) + + LOADREL(t1,_exc_cerr_htable) + LR t2,R_EXC_CERR_TEMPLATE_END(t1) + LR t1,R_EXC_CERR_TEMPLATE(t1) + +1: lw t3,0(t1) # get a word + sw t3,0(t0) # write a word + ADD t0,4 # next word... + ADD t1,4 + blt t1,t2,1b # till done + + /* + * Now do the whole thing again, but with cached writes. + * Writing uncached makes sure the data is actually in memory, + * and writing cached makes sure we write the same + * stuff again when the cache is evicted. + * This way we don't have to bother with cacheops, + * a bonus on the BCM1250 with its funky L2. + */ + + li t0,PHYS_TO_K0(CFE_LOCORE_GLOBAL_GP) + SR gp,0(t0) + + li t0,PHYS_TO_K0(CFE_LOCORE_GLOBAL_CERRH) + SR a0,0(t0) + + li t0,PHYS_TO_K0(MIPS_RAM_VEC_CACHEERR) + + LOADREL(t1,_exc_cerr_htable) + LR t2,R_EXC_CERR_TEMPLATE_END(t1) + LR t1,R_EXC_CERR_TEMPLATE(t1) + +1: lw t3,0(t1) # get a word + sw t3,0(t0) # write a word + ADD t0,4 # next word... + ADD t1,4 + blt t1,t2,1b # till done + + + /* + * done! + */ + + move ra,t4 + j ra + +END(_exc_setup_locore) + + + + +/* ********************************************************************* + * _exc_setvector(xtype,addr) + * + * Set an exception vector address + * + * Input parameters: + * xtype - exception vector type + * addr - routine address + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(_exc_setvector) + + la v0,_exc_vectab + srl a0,3 /* convert 8-byte index to array index */ + sll a0,BPWSIZE /* convert back to index appropriate for word size */ + add v0,a0 + SR a1,(v0) + j ra + +END(_exc_setvector) + + +/* ********************************************************************* + * _exc_crash_sim() + * + * Crash the GDB simulator, causing it to exit. + * + * Input parameters: + * nothing + * + * Return value: + * nothing - does not return + ********************************************************************* */ + + +LEAF(_exc_crash_sim) + + li $2,1 + li $3,0xdead + li $4,0 + syscall 0xca +1: b 1b + +END(_exc_crash_sim) + + +/* ********************************************************************* + * _exc_cache_crash_sim() + * + * As _exc_crash_sim, but distinguish cache error exception. + * + * Input parameters: + * nothing + * + * Return value: + * nothing - does not return + ********************************************************************* */ + + +LEAF(_exc_cache_crash_sim) + + li $2,1 + li $3,0xbadc + li $4,0 + syscall 0xca +1: b 1b + +END(_exc_cache_crash_sim) + + +/* ********************************************************************* + * _exc_restart() + * + * Restart the firmware at the boot address + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(_exc_restart) + + li t0,0xBFC00000 # ROM restart vector + jr t0 + +END(_exc_restart) + +/* ********************************************************************* + * _exc_entry(k0) + * + * Main exception entry point. + * + * Input parameters: + * k0 - exception type + * + * Return value: + * ... + ********************************************************************* */ + +LEAF(_exc_entry) + + .set noreorder + .set noat + + subu k1,sp,EXCEPTION_SIZE + SRL k1,3 + SLL k1,3 + + SREG zero,XGR_ZERO(k1) + SREG AT,XGR_AT(k1) + + SREG v0,XGR_V0(k1) + SREG v1,XGR_V1(k1) + + SREG a0,XGR_A0(k1) + SREG a1,XGR_A1(k1) + SREG a2,XGR_A2(k1) + SREG a3,XGR_A3(k1) + + SREG t0,XGR_T0(k1) + SREG t1,XGR_T1(k1) + SREG t2,XGR_T2(k1) + SREG t3,XGR_T3(k1) + SREG t4,XGR_T4(k1) + SREG t5,XGR_T5(k1) + SREG t6,XGR_T6(k1) + SREG t7,XGR_T7(k1) + + SREG s0,XGR_S0(k1) + SREG s1,XGR_S1(k1) + SREG s2,XGR_S2(k1) + SREG s3,XGR_S3(k1) + SREG s4,XGR_S4(k1) + SREG s5,XGR_S5(k1) + SREG s6,XGR_S6(k1) + SREG s7,XGR_S7(k1) + + SREG t8,XGR_T8(k1) + SREG t9,XGR_T9(k1) + + SREG gp,XGR_GP(k1) + SREG sp,XGR_SP(k1) + SREG fp,XGR_FP(k1) + SREG ra,XGR_RA(k1) + + mfc0 t0,C0_CAUSE + mfc0 t1,C0_SR + MFC0 t2,C0_BADVADDR + MFC0 t3,C0_EPC + mfc0 t4,C0_PRID + mflo t5 + mfhi t6 + SREG t0,XCP0_CAUSE(k1) + SREG t1,XCP0_SR(k1) + SREG t2,XCP0_VADDR(k1) + SREG t3,XCP0_EPC(k1) + SREG t4,XCP0_PRID(k1) + SREG t5,XGR_LO(k1) + SREG t6,XGR_HI(k1) + +#if CFG_EMBEDDED_PIC + la gp,PHYS_TO_K0(CFE_LOCORE_GLOBAL_GP) + LR gp,0(gp) # get our GP handle from low memory vector +#else + la gp,_gp # Load up GP, not relocated so it's easy +#endif + + move a0,k0 # Pass exception type + move a1,k1 # Pass frame to exception handler + la t0,_exc_vectab # get base of exception vectors + srl k0,3 # convert 8-byte index to array index + sll k0,BPWSIZE # convert back to index appropriate for word size + addu t0,k0 # get vector address + LR t0,(t0) # to call handler + + move sp,k1 # "C" gets fresh stack area + + jalr t0 # Call exception handler + nop + + move k1, sp + LREG AT,XGR_AT(k1) + + LREG t0,XGR_LO(k1) + LREG t1,XGR_HI(k1) + mtlo t0 + mthi t1 + + LREG a0,XGR_A0(k1) + LREG a1,XGR_A1(k1) + LREG a2,XGR_A2(k1) + LREG a3,XGR_A3(k1) + + LREG t0,XGR_T0(k1) + LREG t1,XGR_T1(k1) + LREG t2,XGR_T2(k1) + LREG t3,XGR_T3(k1) + LREG t4,XGR_T4(k1) + LREG t5,XGR_T5(k1) + LREG t6,XGR_T6(k1) + LREG t7,XGR_T7(k1) + + LREG s0,XGR_S0(k1) + LREG s1,XGR_S1(k1) + LREG s2,XGR_S2(k1) + LREG s3,XGR_S3(k1) + LREG s4,XGR_S4(k1) + LREG s5,XGR_S5(k1) + LREG s6,XGR_S6(k1) + LREG s7,XGR_S7(k1) + + LREG t8,XGR_T8(k1) + LREG t9,XGR_T9(k1) + + LREG gp,XGR_GP(k1) + LREG sp,XGR_SP(k1) + LREG fp,XGR_FP(k1) + LREG ra,XGR_RA(k1) + +/* do any CP0 cleanup here */ + + LREG v0,XGR_V0(k1) + LREG v1,XGR_V1(k1) + + ERET + + .set at + .set reorder + + +END(_exc_entry) + + +/* ********************************************************************* + * _exc_clear_sr_exl() + * + * Clear SR(EXL) and return to caller. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(_exc_clear_sr_exl) + + mfc0 t0,C0_SR + and t0,t0,~(0x02) # clear SR(EXL). Bit 1 + mtc0 t0,C0_SR + + HAZARD + + j ra + +END(_exc_clear_sr_exl) + +/* ********************************************************************* + * _exc_clear_sr_erl() + * + * Clear SR(ERL) and return to caller. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(_exc_clear_sr_erl) + + mfc0 t0,C0_SR + and t0,t0,~(0x04) # clear SR(ERL). Bit 2 + mtc0 t0,C0_SR + + HAZARD + + j ra + +END(_exc_clear_sr_erl) + + +/* ********************************************************************* + * End + ********************************************************************* */ + + diff --git a/cfe/cfe/arch/mips/common/src/exchandler.c b/cfe/cfe/arch/mips/common/src/exchandler.c new file mode 100644 index 0000000..d69b980 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/exchandler.c @@ -0,0 +1,580 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Exception Handler File: exchandler.c + * + * This is the "C" part of the exception handler and the + * associated setup routines. We call these routines from + * the assembly-language exception handler. + * + * 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 "sbmips.h" +#include "lib_types.h" +#include "lib_string.h" +#include "lib_printf.h" +#include "lib_queue.h" +#include "lib_malloc.h" +#include "exception.h" +#include "cfe.h" +#include "cfe_error.h" +#include "cfe_iocb.h" +#include "exchandler.h" +#include "cpu_config.h" +#include "bsp_config.h" + +/* ********************************************************************* + * Constants + ********************************************************************* */ + +/* + * Temporary until all our CPU packages support a cache error handler + */ + +#ifndef CPUCFG_CERRHANDLER +#define CPUCFG_CERRHANDLER 0xBFC00000 +#else +extern void CPUCFG_CERRHANDLER(void); +#endif + +/* ********************************************************************* + * Globals + ********************************************************************* */ + +exc_handler_t exc_handler; +extern void _exc_entry(void); +extern void _exc_setup_locore(long); +extern void CPUCFG_TLBHANDLER(void); +extern void cfe_flushcache(uint32_t,long,long); +extern uint32_t _getstatus(void); +extern void _setstatus(uint32_t); + +static const char *regnames = "0 ATv0v1a0a1a2a3t0t1t2t3t4t5t6t7" + "s0s1s2s3s4s5s6s7t8t9k0k1gpspfpra"; +static const char *excnames = + "Interrupt" /* 0 */ + "TLBMod " /* 1 */ + "TLBMissRd" /* 2 */ + "TLBMissWr" /* 3 */ + "AddrErrRd" /* 4 */ + "AddrErrWr" /* 5 */ + "BusErrRd " /* 6 */ + "BusErrWr " /* 7 */ + "Syscall " /* 8 */ + "Breakpt " /* 9 */ + "InvOpcode" /* 10 */ + "CoProcUnu" /* 11 */ + "ArithOvfl" /* 12 */ + "TrapExc " /* 13 */ + "VCEI " /* 14 */ + "FPUExc " /* 15 */ + "CP2Exc " /* 16 */ + "Exc17 " /* 17 */ + "Exc18 " /* 18 */ + "Exc19 " /* 19 */ + "Exc20 " /* 20 */ + "Exc21 " /* 21 */ + "Exc22 " /* 22 */ + "Watchpt " /* 23 */ + "Exc24 " /* 24 */ + "Exc25 " /* 25 */ + "Exc26 " /* 26 */ + "Exc27 " /* 27 */ + "Exc28 " /* 28 */ + "Exc29 " /* 29 */ + "Exc30 " /* 30 */ + "VCED "; /* 31 */ + + + +/* ********************************************************************* + * cfe_exception(code,info) + * + * Exception handler. This routine is called when any CPU + * exception that is handled by the assembly-language + * vectors is reached. The usual thing to do here is just to + * reboot. + * + * Input parameters: + * code - exception type + * info - exception stack frame + * + * Return value: + * usually reboots + ********************************************************************* */ + +void cfe_exception(int code,uint64_t *info) +{ + int idx; + + SETLEDS("EXC!"); + + if(exc_handler.catch_exc == 1) { + /*Deal with exception without restarting CFE.*/ + + /*Clear relevant SR bits*/ + _exc_clear_sr_exl(); + _exc_clear_sr_erl(); + + /*Reset flag*/ + exc_handler.catch_exc = 0; + + exc_longjmp_handler(); + } + + +#ifdef _MIPSREGS32_ + xprintf("**Exception %d: EPC=%08X, Cause=%08X (%9s)\n", + code,(uint32_t)info[XCP0_EPC], + (uint32_t)info[XCP0_CAUSE], + excnames + G_CAUSE_EXC((uint32_t)info[XCP0_CAUSE])*9); + xprintf(" RA=%08X, VAddr=%08X\n", + (uint32_t)info[XGR_RA],(uint32_t)info[XCP0_VADDR]); + xprintf("\n"); + for (idx = 0;idx < 32; idx+= 2) { + xprintf(" %2s ($%2d) = %08X %2s ($%2d) = %08X\n", + regnames+(idx*2), + idx,(uint32_t)info[XGR_ZERO+idx], + regnames+((idx+1)*2), + idx+1,(uint32_t)info[XGR_ZERO+idx+1]); + } +#else + xprintf("**Exception %d: EPC=%016llX, Cause=%08X (%9s)\n", + code,info[XCP0_EPC],info[XCP0_CAUSE], + excnames + G_CAUSE_EXC((uint32_t)info[XCP0_CAUSE])*9); + xprintf(" RA=%016llX, VAddr=%016llX\n", + info[XGR_RA],info[XCP0_VADDR]); + xprintf("\n"); + for (idx = 0;idx < 32; idx+= 2) { + xprintf(" %2s ($%2d) = %016llX %2s ($%2d) = %016llX\n", + regnames+(idx*2), + idx,info[XGR_ZERO+idx], + regnames+((idx+1)*2), + idx+1,info[XGR_ZERO+idx+1]); + } +#endif + + xprintf("\n"); + _exc_restart(); +} + +#if (!CFG_BOOTRAM) && (CFG_RUNFROMKSEG0) +/* ********************************************************************* + * exc_setup_hw_vector(vecoffset,target,k0code) + * + * Install a patch of code at the specified offset in low + * KSEG0 memory that will jump to 'target' and load k0 + * with the specified code value. This is used when we + * run with RAM vectors. + * + * Input parameters: + * vecoffset - offset into KSEG0 + * target - location where we should branch when vector is called + * k0code - value to load into K0 before branching + * + * Return value: + * nothing + ********************************************************************* */ + +static void exc_setup_hw_vector(uint32_t vecoffset, + void *target, + uint32_t k0code) +{ + uint32_t *vec; + uint32_t new; + uint32_t lower,upper; + + new = (uint32_t) (intptr_t) target; /* warning: assumes compatibility addresses! */ + + lower = new & 0xffff; + upper = (new >> 16) & 0xffff; + if ((lower & 0x8000) != 0) { + upper++; + } + + /* + * Get a KSEG0 version of the vector offset. + */ + vec = (uint32_t *) PHYS_TO_K0(vecoffset); + + /* + * Patch in the vector. Note that we have to flush + * the L1 Dcache and invalidate the L1 Icache before + * we can use this. + */ + + vec[0] = 0x3c1b0000 | upper; /* lui k1, HIGH(new) */ + vec[1] = 0x277b0000 | lower; /* addiu k1, k1, LOW(new) */ + vec[2] = 0x03600008; /* jr k1 */ + vec[3] = 0x241a0000 | k0code; /* li k0, code */ + +} + + +/* ********************************************************************* + * exc_install_ram_vectors() + * + * Install all of the hardware vectors into low memory, + * flush the cache, and clear the BEV bit so we can start + * using them. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +static void exc_install_ram_vectors(void) +{ + uint32_t *ptr; + int idx; + + /* Debug: blow away the vector area so we can see what we did */ + ptr = (uint32_t *) PHYS_TO_K0(0); + for (idx = 0; idx < 0x1000/sizeof(uint32_t); idx++) *ptr++ = 0; + + /* + * Set up the vectors. The cache error handler is set up + * specially. + */ + + exc_setup_hw_vector(MIPS_RAM_VEC_TLBFILL, CPUCFG_TLBHANDLER,XTYPE_TLBFILL); + exc_setup_hw_vector(MIPS_RAM_VEC_XTLBFILL, _exc_entry,XTYPE_XTLBFILL); + exc_setup_hw_vector(MIPS_RAM_VEC_CACHEERR, _exc_entry,XTYPE_CACHEERR); + exc_setup_hw_vector(MIPS_RAM_VEC_EXCEPTION,_exc_entry,XTYPE_EXCEPTION); + exc_setup_hw_vector(MIPS_RAM_VEC_INTERRUPT,_exc_entry,XTYPE_INTERRUPT); + + /* + * Flush the D-cache and invalidate the I-cache so we can start + * using these vectors. + */ + + cfe_flushcache(CFE_CACHE_FLUSH_D | CFE_CACHE_INVAL_I,0,0); + + /* + * Write the handle into our low memory space. If we need to save + * other stuff down there, this is a good place to do it. + * This call uses uncached writes - we have not touched the + * memory in the handlers just yet, so they should not be + * in our caches. + */ + + _exc_setup_locore((intptr_t) CPUCFG_CERRHANDLER); + + /* + * Finally, clear BEV so we'll use the vectors in RAM. + */ + + _setstatus(_getstatus() & ~M_SR_BEV); + + /* + * XXX There's a hazard here, but we're not going to worry about + * XXX it. It is unlikely we'll use the vectors any time soon. + */ +} +#endif + +/* ********************************************************************* + * cfe_setup_exceptions() + * + * Set up the exception handlers. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ +void cfe_setup_exceptions(void) +{ + _exc_setvector(XTYPE_TLBFILL, (void *) cfe_exception); + _exc_setvector(XTYPE_XTLBFILL, (void *) cfe_exception); + _exc_setvector(XTYPE_CACHEERR, (void *) _exc_cache_crash_sim); + _exc_setvector(XTYPE_EXCEPTION,(void *) cfe_exception); + _exc_setvector(XTYPE_INTERRUPT,(void *) cfe_exception); + _exc_setvector(XTYPE_EJTAG, (void *) cfe_exception); + + exc_handler.catch_exc = 0; + q_init( &(exc_handler.jmpbuf_stack)); + +#if (!CFG_BOOTRAM) && (CFG_RUNFROMKSEG0) + /* + * Install RAM vectors, and clear the BEV bit in the status + * register. Don't do this if we're running from PromICE RAM + */ + exc_install_ram_vectors(); +#endif +} + + + +/* ********************************************************************* + * exc_initialize_block() + * + * Set up the exception handler. Allow exceptions to be caught. + * Allocate memory for jmpbuf and store it away. + * + * Returns NULL if error in memory allocation. + * + * Input parameters: + * nothing + * + * Return value: + * jmpbuf_t structure, or NULL if no memory + ********************************************************************* */ +jmpbuf_t *exc_initialize_block(void) +{ + jmpbuf_t *jmpbuf_local; + + exc_handler.catch_exc = 1; + + /* Create the jmpbuf_t object */ + jmpbuf_local = (jmpbuf_t *) KMALLOC((sizeof(jmpbuf_t)),0); + + if (jmpbuf_local == NULL) { + return NULL; + } + + q_enqueue( &(exc_handler.jmpbuf_stack), &((*jmpbuf_local).stack)); + + return jmpbuf_local; +} + +/* ********************************************************************* + * exc_cleanup_block(dq_jmpbuf) + * + * Remove dq_jmpbuf from the exception handler stack and free + * the memory. + * + * Input parameters: + * dq_jmpbuf - block to deallocate + * + * Return value: + * nothing + ********************************************************************* */ + +void exc_cleanup_block(jmpbuf_t *dq_jmpbuf) +{ + int count; + + if (dq_jmpbuf == NULL) { + return; + } + + count = q_count( &(exc_handler.jmpbuf_stack)); + + if( count > 0 ) { + q_dequeue( &(*dq_jmpbuf).stack ); + KFREE(dq_jmpbuf); + } +} + +/* ********************************************************************* + * exc_cleanup_handler(dq_jmpbuf,chain_exc) + * + * Clean a block, then chain to the next exception if required. + * + * Input parameters: + * dq_jmpbuf - current exception + * chain_exc - true if we should chain to the next handler + * + * Return value: + * nothing + ********************************************************************* */ + +void exc_cleanup_handler(jmpbuf_t *dq_jmpbuf, int chain_exc) +{ + exc_cleanup_block(dq_jmpbuf); + + if( chain_exc == EXC_CHAIN_EXC ) { + /*Go to next exception on stack */ + exc_longjmp_handler(); + } +} + + + +/* ********************************************************************* + * exc_longjmp_handler() + * + * This routine long jumps to the exception handler on the top + * of the exception stack. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ +void exc_longjmp_handler(void) +{ + int count; + jmpbuf_t *jmpbuf_local; + + count = q_count( &(exc_handler.jmpbuf_stack)); + + if( count > 0 ) { + jmpbuf_local = (jmpbuf_t *) q_getlast(&(exc_handler.jmpbuf_stack)); + + SETLEDS("CFE "); + + lib_longjmp( (*jmpbuf_local).jmpbuf, -1); + } +} + + +/* ********************************************************************* + * mem_peek(d,addr,type) + * + * Read memory of the specified type at the specified address. + * Exceptions are caught in the case of a bad memory reference. + * + * Input parameters: + * d - pointer to where data should be placed + * addr - address to read + * type - type of read to do (MEM_BYTE, etc.) + * + * Return value: + * 0 if ok + * else error code + ********************************************************************* */ + +int mem_peek(void *d, long addr, int type) +{ + + jmpbuf_t *jb; + + jb = exc_initialize_block(); + if( jb == NULL ) { + return CFE_ERR_NOMEM; + } + + if (exc_try(jb) == 0) { + + switch (type) { + case MEM_BYTE: + *(uint8_t *)d = *((volatile uint8_t *) addr); + break; + case MEM_HALFWORD: + *(uint16_t *)d = *((volatile uint16_t *) addr); + break; + case MEM_WORD: + *(uint32_t *)d = *((volatile uint32_t *) addr); + break; + case MEM_QUADWORD: + *(uint64_t *)d = *((volatile uint64_t *) addr); + break; + default: + return CFE_ERR_INV_PARAM; + } + + exc_cleanup_block(jb); + } + else { + /*Exception handler*/ + + exc_cleanup_handler(jb, EXC_NORMAL_RETURN); + return CFE_ERR_GETMEM; + } + + return 0; +} + +/* ********************************************************************* + * Write memory of type at address addr with value val. + * Exceptions are caught, handled (error message) and function + * returns with 0. + * + * 1 success + * 0 failure + ********************************************************************* */ + +int mem_poke(long addr, uint64_t val, int type) +{ + + jmpbuf_t *jb; + + jb = exc_initialize_block(); + if( jb == NULL ) { + return CFE_ERR_NOMEM; + } + + if (exc_try(jb) == 0) { + + switch (type) { + case MEM_BYTE: + *((volatile uint8_t *) addr) = (uint8_t) val; + break; + case MEM_HALFWORD: + *((volatile uint16_t *) addr) = (uint16_t) val; + break; + case MEM_WORD: + *((volatile uint32_t *) addr) = (uint32_t) val; + break; + case MEM_QUADWORD: + *((volatile uint64_t *) addr) = (uint64_t) val; + break; + default: + return CFE_ERR_INV_PARAM; + } + + exc_cleanup_block(jb); + } + else { + /*Exception handler*/ + + exc_cleanup_handler(jb, EXC_NORMAL_RETURN); + return CFE_ERR_SETMEM; + } + + return 0; +} + + + + + + + + + + diff --git a/cfe/cfe/arch/mips/common/src/init_mips.S b/cfe/cfe/arch/mips/common/src/init_mips.S new file mode 100755 index 0000000..3f59539 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/init_mips.S @@ -0,0 +1,683 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * CPU init module File: init_mips.S + * + * This module contains the vectors and lowest-level CPU startup + * functions for 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. + ********************************************************************* */ + + +#include "sbmips.h" +#include "exception.h" + +#include "bsp_config.h" +#include "cpu_config.h" + +#ifdef _CFE_ +#include "cfe_devfuncs.h" +#else + +#define cfe_command_restart 0 +#endif + +/* BCM63XX specific change. */ +#include "bcm_hwdefs.h" + +/* ********************************************************************* + * Macros + ********************************************************************* */ + +#include "mipsmacros.h" + + +/* ********************************************************************* + * SETLEDS(a,b,c,d) + * SETLEDS1(a,b,c,d) + * + * Sets the on-board LED display (if present). Two variants + * of this routine are provided. If you're running KSEG1, + * call the SETLEDS1 variant, else call SETLEDS. + * + * Input parameters: + * a,b,c,d - four ASCII characters (literal constants) + * + * Return value: + * a0,k1,ra trashed + ********************************************************************* */ + +#define SETLEDS(a,b,c,d) \ + li a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ; \ + CALLINIT_KSEG0(init_table,R_INIT_SETLEDS) + +#define SETLEDS1(a,b,c,d) \ + li a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ; \ + CALLINIT_KSEG1(init_table,R_INIT_SETLEDS) + + +/* ********************************************************************* + * Other constants + ********************************************************************* */ + +/* + * This is the size of the stack, rounded to KByte boundaries. + */ + +#ifndef CFG_STACK_SIZE +#error "CFG_STACK_SIZE not defined" +#else +#define STACK_SIZE ((CFG_STACK_SIZE+1023) & ~1023) +#endif + +#ifdef __MIPSEB +#define TEXTSECTION 0x2e746578 # ".tex", big-endian +#else +#define TEXTSECTION 0x7865742e # ".tex", little-endian +#endif + +/* + * Duplicates from cfe_iocb.h -- warning! + */ + +#define CFE_CACHE_FLUSH_D 1 +#define CFE_CACHE_INVAL_I 2 +#define CFE_CACHE_INVAL_D 4 +#define CFE_CACHE_INVAL_L2 8 +#define CFE_CACHE_FLUSH_L2 16 +#define CFE_CACHE_INVAL_RANGE 32 +#define CFE_CACHE_FLUSH_RANGE 64 + + +/* + * To make life easier reading this code, define "KSEGBASE" + * to either K0BASE or K1BASE depending on whether we're running + * uncached. + */ + +#if CFG_RUNFROMKSEG0 +#define KSEGBASE K0BASE +#else +#define KSEGBASE K1BASE +#endif + + +/* ********************************************************************* + * Names of registers used in this module + ********************************************************************* */ + +#define RELOCOFFSET s8 /* $30 (fp) */ +#define TEXTOFFSET t9 /* $25 (t9) */ +#define MEMTOP t8 /* $24 (t8) */ +#define TEXTBASE s7 /* $23 (s7) */ +#undef BOOT_OFFSET +#define BOOT_OFFSET s6 /* $22 (s6) */ + + .sdata + +#include "initdata.h" /* declare variables we use here */ + +#if CFG_MULTI_CPUS + .globl cfe_spinlock +cfe_spinlock: .word 0 +#endif + + .extern _fdata + .extern _edata + .extern _etext + +/* ********************************************************************* + * uninitialized data + ********************************************************************* */ + + .bss + + .comm __junk,4 + +/* ********************************************************************* + * Exception Vectors + ********************************************************************* */ + + .text + + .set noreorder + +/* + * Declare the actual vectors. This expands to code that + * must be at the very beginning of the text segment. + */ + +DECLARE_VECTOR(0x0000,vec_reset,cpu_reset) + + .set reorder + +/* ********************************************************************* + * Some offsets depend on our current configuration + ********************************************************************* */ + +#define RUNTIME_RELOC_START 0 +#define RUNTIME_RELOC_STOP 0 + +/* ********************************************************************* + * Segment Table. + * + * Addresses of data segments and of certain routines we're going + * to call from KSEG1. These are here mostly for the embedded + * PIC case, since we can't count on the 'la' instruction to + * do the expected thing (the assembler expands it into a macro + * for doing GP-relative stuff, and the code is NOT GP-relative. + * So, we (relocatably) get the offset of this table and then + * index within it. + * + * Pointer values in this segment will be relative to KSEG0 for + * cached versions of CFE, so we need to OR in K1BASE in the + * case of calling to a uncached address. + * + * The LOADREL macro handles most of the nastiness here. + ********************************************************************* */ + +#include "segtable.h" +#include "cfe.h" + + .org 0x570 + .byte 'c','f','e','-','v',CFE_VER_MAJOR,CFE_VER_MINOR,CFE_VER_BUILD,BCM63XX_MAJOR,BCM63XX_MINOR # CFE version info for applications + .org 0x580 # move past exception vectors + + /* + * BCM963XX NVRAM Data Storage + */ + + .globl nvram_data_storage +nvram_data_storage: + .word NVRAM_DATA_ID + .space 0x400 + + .globl segment_table +segment_table: + _LONG_ _etext # [ 0] End of text (R_SEG_ETEXT) + _LONG_ _fdata # [ 1] Beginning of data (R_SEG_FDATA) + _LONG_ _edata # [ 2] End of data (R_SEG_EDATA) + _LONG_ _end # [ 3] End of BSS (R_SEG_END) + _LONG_ _ftext # [ 4] Beginning of text (R_SEG_FTEXT) + _LONG_ _fbss # [ 5] Beginning of BSS (R_SEG_FBSS) + _LONG_ _gp # [ 6] Global Pointer (R_SEG_GP) + _LONG_ 0 # [ 7] Beginning of reloc entries + _LONG_ 0 # [ 8] End of reloc entries + _LONG_ 0 # [ 9] R_SEG_APIENTRY + +/* ********************************************************************* + * Init Table. + * + * This is like segment_table except it contains pointers to + * routines used during initialization. It serves both as a + * table for doing PIC stuff and also to separate out + * machine-specific init routines. + * + * The CALLINIT_xxx macros are used to call routines in this table. + ********************************************************************* */ + + + .globl init_table +init_table: + _LONG_ board_earlyinit # [ 0] R_INIT_EARLYINIT + _LONG_ board_setleds # [ 1] R_INIT_SETLEDS + _LONG_ board_draminfo # [ 2] R_INIT_DRAMINFO + _LONG_ CPUCFG_CPUINIT # [ 3] R_INIT_CPUINIT + _LONG_ CPUCFG_ALTCPU_START1 # [ 4] R_INIT_ALTCPU_START1 + _LONG_ CPUCFG_ALTCPU_START2 # [ 5] R_INIT_ALTCPU_START2 + _LONG_ CPUCFG_ALTCPU_RESET # [ 6] R_INIT_ALTCPU_RESET + _LONG_ CPUCFG_CPURESTART # [ 7] R_INIT_CPURESTART + _LONG_ CPUCFG_DRAMINIT # [ 8] R_INIT_DRAMINIT + _LONG_ CPUCFG_CACHEOPS # [ 9] R_INIT_CACHEOPS + _LONG_ CPUCFG_TLBHANDLER # [ 10] R_INIT_TLBHANDLER + _LONG_ cfe_main # [ 11] R_INIT_CMDSTART + _LONG_ cfe_command_restart # [ 12] R_INIT_CMDRESTART + _LONG_ cfe_doxreq # [ 13] R_INIT_DOXREQ + _LONG_ CPUCFG_TP1_SWITCH # [ 14] R_INIT_TP1_SWITCH + _LONG_ cfe_size_ram # [ 15] R_INIT_SIZERAM + +/* ********************************************************************* + * CPU Startup Code + ********************************************************************* */ + +cpu_reset: + + /* + * Start with GP as zero. Nobody should touch + * this or set it to any other value until we're ready + * to use it. This is used to tell when we should start + * using relocated references in the init table, + * so beware! (see CALLINIT_RELOC in mipsmacros.h) + */ + + move gp,zero # start with no GP. + + .set noreorder + bal 1f + nop +1: nop + .set reorder + li BOOT_OFFSET, 0x1fff0000 + and BOOT_OFFSET, ra + +#------------------------------------------------------------------------------ + + /* + * Do low-level board initialization. This is our first + * chance to customize the startup sequence. + */ + move a0, BOOT_OFFSET + + CALLINIT_KSEG1(init_table,R_INIT_EARLYINIT) + + SETLEDS1('H','E','L','O') + + CALLINIT_KSEG1(init_table,R_INIT_CPUINIT) + +#------------------------------------------------------------------------------ + + /* + * Now, switch from KSEG1 to KSEG0 + */ + +#if CFG_RUNFROMKSEG0 + bal cpu_kseg0_switch +#endif + +#------------------------------------------------------------------------------ + /* + * Now running on cpu0 in K0SEG. + */ + +#if CFG_CMT + /* + * 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. + */ + CALLINIT_KSEG0(init_table,R_INIT_TP1_SWITCH) +#endif + +#if CFG_INIT_DRAM + SETLEDS('D','R','A','M') + + CALLINIT_KSEG0(init_table,R_INIT_DRAMINFO) + + move a0,v0 # pass these params + CALLINIT_KSEG0(init_table,R_INIT_DRAMINIT) + CALLINIT_KSEG0(init_table,R_INIT_SIZERAM) + move k0,v0 # Save in k0 for now +#else + li k0,(CFG_DRAM_SIZE * 1024) +#endif + +#------------------------------------------------------------------------------ + +#if CFG_BOOTRAM + b have_ram # No RAM is ok if using emulator RAM +#endif + + bne k0,zero,have_ram + + SETLEDS('R','A','M','X') # die here if no ram + +die1: b die1 + +have_ram: + + /* + * If this is the 64-bit version, turn on the KX bit + * to allow 64-bit accesses. + */ + +#ifdef __long64 + mfc0 t0,C0_SR + or t0,t0,M_SR_KX + mtc0 t0,C0_SR +#endif + +#------------------------------------------------------------------------------ + /* + * K0 contains the RAM size (and therefore the top of RAM + * offset). Start there, and subtract the amount of memory + * we expect to use. If we have more than 256MB of + * physical memory, work backwards from the 256MB + * boundary. + */ + +__CalcMemTop: li MEMTOP,256 # 256MB boundary + bgt k0,MEMTOP,1f # use 256MB if k0 is greater + move MEMTOP,k0 # otherwise keep top +1: sll MEMTOP,20 # make into byte amount + + li RELOCOFFSET,0 # not relocating, no offset + li TEXTOFFSET,0 + + /* + * DRAM is now running, and we're alive in cacheable memory + * on cpu0 in K0SEG. Set up GP. + */ + + LOADREL(a0,segment_table) + LR gp,R_SEG_GP(a0) + add gp,RELOCOFFSET + +#------------------------------------------------------------------------------ + /* + * Zero BSS + */ + + SETLEDS('Z','B','S','S') + + LOADREL(a0,segment_table) +__ZeroBss: + + LR v0,R_SEG_FBSS(a0) + LR v1,R_SEG_END(a0) + ADD v0,RELOCOFFSET # Relocate to actual data segment + ADD v1,RELOCOFFSET + +1: SR zero,0(v0) # Zero one cacheline at a time + SR zero,(REGSIZE*1)(v0) + SR zero,(REGSIZE*2)(v0) + SR zero,(REGSIZE*3)(v0) + add v0,REGSIZE*4 + blt v0,v1,1b + +#------------------------------------------------------------------------------ + /* + * Copy code + */ + + SETLEDS('C','O','D','E') + + LOADREL(a0,segment_table) +__CopyCode: + + LR t1,R_SEG_FTEXT(a0) # destination address + move TEXTBASE,t1 + + LR t2,R_SEG_FTEXT(a0) # Source address + FIXUP (t2); + LR t3,R_SEG_ETEXT(a0) + FIXUP (t3); + +1: LR t4,0(t2) # read one cache line + LR t5,(REGSIZE*1)(t2) + LR t6,(REGSIZE*2)(t2) + LR t7,(REGSIZE*3)(t2) + SR t4,0(t1) # write one cache line + SR t5,(REGSIZE*1)(t1) + SR t6,(REGSIZE*2)(t1) + SR t7,(REGSIZE*3)(t1) + add t1,REGSIZE*4 + add t2,REGSIZE*4 + bltu t2,t3,1b + +#------------------------------------------------------------------------------ + /* + * Copy initialized data + */ + +#if (CFG_BOOTRAM == 0) + + SETLEDS('D','A','T','A') + + LOADREL(a0,segment_table) + +__CopyData: + LR t1,R_SEG_FDATA(a0) + FIXUP (t1); + li t0,15 + add t1,t0 + not t0 + and t1,t0 # t1 = _etext rounded up to 16-byte boundary + + LR t2,R_SEG_FDATA(a0) + LR t3,R_SEG_EDATA(a0) + ADD t2,RELOCOFFSET # Relocate to actual data segment + ADD t3,RELOCOFFSET + +1: LR t4,0(t1) # read one cache line + LR t5,(REGSIZE*1)(t1) + LR t6,(REGSIZE*2)(t1) + LR t7,(REGSIZE*3)(t1) + SR t4,0(t2) # write one cache line + SR t5,(REGSIZE*1)(t2) + SR t6,(REGSIZE*2)(t2) + SR t7,(REGSIZE*3)(t2) + add t1,(REGSIZE*4) + add t2,(REGSIZE*4) + bltu t2,t3,1b + +#endif + +#------------------------------------------------------------------------------ + + /* + * Flush the cache, then switch to relocated code + * We need to flush the cache since we just moved the code and + * it may still live in our L1 DCache. We also need to + * flush L2, since there are some rare times we run + * uncached from DRAM, like when we start/stop a CPU. + * + * In the case of running completely uncached, don't flush the + * cache. It should not have any dirty lines in it, but you + * never know... + */ + +__GoRelo: + +#if CFG_RUNFROMKSEG0 + SETLEDS('L','1','2','F') + + li a0,CFE_CACHE_FLUSH_D | CFE_CACHE_FLUSH_L2 + CALLINIT_KSEG0(init_table,R_INIT_CACHEOPS) + li a0,CFE_CACHE_INVAL_I + CALLINIT_KSEG0(init_table,R_INIT_CACHEOPS) +#endif /* CFG_RUNFROMKSEG0 */ + + la t0,gorelo # Now jump to an address code was compiled for + j t0 # and go there +gorelo: nop + li BOOT_OFFSET, 0 # no longer running at offset + + /* + * Remember total amount of memory. This is *still* in k0 + * after all this time. Hopefully. + */ + +__MemVars: + SR k0,mem_totalsize + SR RELOCOFFSET,mem_datareloc + + move v0,zero + + LOADREL(a0,segment_table) # trashed by l2 cache flush + LR v0,R_SEG_FDATA(a0) + ADD v0,RELOCOFFSET + LR v1,R_SEG_END(a0) + ADD v1,RELOCOFFSET + + SR v0,mem_bottomofmem + SR v1,mem_heapstart + + add v1,(CFG_HEAP_SIZE*1024) # Otherwise + add v1,STACK_SIZE + SR v1,mem_topofmem + + SR TEXTOFFSET,mem_textreloc + + /* At this point it's safe to use the CALLINIT_RELOC macro */ + + LR t1,R_SEG_FTEXT(a0) + FIXUP (t1); + LR t0,R_SEG_ETEXT(a0) + FIXUP (t0); + sub t0,t0,t1 + SR t0,mem_textsize + add t1,TEXTOFFSET + SR t1,mem_textbase + + +#------------------------------------------------------------------------------ + + /* + * Stash away some config register stuff + */ + + mfc0 v0,C0_PRID + SR v0,cpu_prid + + +#------------------------------------------------------------------------------ + + /* + * Set up the "C" stack and jump to the main routine. + */ + + SETLEDS('M','A','I','N') + + LR sp,mem_heapstart + ADD sp,((CFG_HEAP_SIZE*1024)+STACK_SIZE - 8) + li a0,0 # call as "cfe_main(0,0)" + li a1,0 + + CALLINIT_RELOC(init_table,R_INIT_CMDSTART) # should not return + +/* ********************************************************************* + * CFE_LAUNCH + * + * Start the user program. The program is passed a handle + * that must be passed back when calling the firmware. + * + * Parameters passed to the called program are as follows: + * + * a0 - CFE handle + * a1 - entry vector + * a2 - reserved, will be 0 + * a3 - entrypoint signature. + * + * Input parameters: + * a0 - entry vector + * + * Return value: + * does not return + ********************************************************************* */ + +LEAF(cfe_launch) + + sub sp,8 + SR a0,0(sp) + + /* + * This function runs in RAM so BOOT_OFFSET is 0. It is called from + * C which could have modified the BOOT_OFFSET register, s6. + */ + li BOOT_OFFSET, 0 + + + /* + * Mask all interrupts. + */ + mfc0 v0,C0_SR # Get current interrupt flag + li v1,M_SR_IE # master interrupt control + not v1 # disable interrupts + and v0,v1 # SR now has IE=0 + mtc0 v0,C0_SR # put back into CP0 + + + /* + * Flush the D-Cache, since the program we loaded is "data". + * Invalidate the I-Cache, so that addresses in the program + * region will miss and need to be filled from the data we + * just flushed above. + */ + + li a0,CFE_CACHE_FLUSH_D|CFE_CACHE_INVAL_I + CALLINIT_RELOC(init_table,R_INIT_CACHEOPS) + + + /* + * Set things up for launching the program. Pass the + * handle in A0 - apps need to remember that and pass it + * back. + */ + + j RunProgram + +END(cfe_launch) + + /* + * This is a nice place to set a breakpoint. + */ +LEAF(RunProgram) + LR t0,0(sp) # entry point + + j t0 # go for it. +END(RunProgram) + +/* ********************************************************************* + * CPU_KSEG0_SWITCH + * + * Hack the return address so we will come back in KSEG0 + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(cpu_kseg0_switch) + + and ra,(K0SIZE-1) + or ra,K0BASE + jr ra + +END(cpu_kseg0_switch) + +/* ********************************************************************* + * End + ********************************************************************* */ + + diff --git a/cfe/cfe/arch/mips/common/src/init_ram.S b/cfe/cfe/arch/mips/common/src/init_ram.S new file mode 100755 index 0000000..2531700 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/init_ram.S @@ -0,0 +1,889 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * CPU init module File: init_ram.S + * + * This module contains the vectors and lowest-level CPU startup + * functions for CFE. + * + * This is very similar to "init_mips.S" but is used when + * you want to locate CFE in DRAM, loading it like an + * application program. + * + * 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 "sbmips.h" +#include "exception.h" + +#include "bsp_config.h" +#include "cpu_config.h" + +#include "cfe_devfuncs.h" + +/* ********************************************************************* + * Check some stuff + ********************************************************************* */ + +#if CFG_RELOC +#error "RAM version is not compatible with relocation." +#endif +#if !(CFG_RUNFROMKSEG0) +#error "RAM version should be run cached" +#endif + +#if CFG_MULTI_CPUS +#error "Multiple CPUs not compatible with RAM version" +#endif + + +/* ********************************************************************* + * Macros + ********************************************************************* */ + +#include "mipsmacros.h" + + +/* ********************************************************************* + * SETLEDS(a,b,c,d) + * + * Sets the on-board LED display (if present). + * + * Input parameters: + * a,b,c,d - four ASCII characters (literal constants) + * + * Return value: + * a0,k1,ra trashed + ********************************************************************* */ + + +#define SETLEDS(a,b,c,d) \ + li a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ; \ + jal board_setleds ; + + +/* ********************************************************************* + * Other constants + ********************************************************************* */ + +/* + * This is the size of the stack, rounded to KByte boundaries. + */ + +#ifndef CFG_STACK_SIZE +#error "CFG_STACK_SIZE not defined" +#else +#define STACK_SIZE ((CFG_STACK_SIZE+1023) & ~1023) +#endif + +/* + * Duplicates from cfe_iocb.h -- warning! + */ + +#define CFE_CACHE_FLUSH_D 1 +#define CFE_CACHE_INVAL_I 2 +#define CFE_CACHE_INVAL_D 4 +#define CFE_CACHE_INVAL_L2 8 +#define CFE_CACHE_FLUSH_L2 16 +#define CFE_CACHE_INVAL_RANGE 32 +#define CFE_CACHE_FLUSH_RANGE 64 + + +/* + * To make life easier reading this code, define "KSEGBASE" + * to either K0BASE or K1BASE depending on whether we're running + * uncached. + */ + +#define KSEGBASE K0BASE /* RAM version always cached */ + + +/* ********************************************************************* + * Names of registers used in this module + ********************************************************************* */ + + .sdata + +#include "initdata.h" /* declare variables we use here */ + +#if CFG_MULTI_CPUS + .globl cfe_spinlock +cfe_spinlock: .word 0 +#endif + + .extern _fdata + .extern _edata + .extern _etext + +/* ********************************************************************* + * uninitialized data + ********************************************************************* */ + + .bss + + .comm __junk,4 + + .text + + .set noreorder + + +/* ********************************************************************* + * CFE Entry Point (used by OS boot loaders and such) + ********************************************************************* */ + + .set noreorder + + .globl vec_reset + +vec_reset: b cpu_reset + nop + + +vec_apientry: b cpu_apientry + nop + .word CFE_EPTSEAL + .word CFE_EPTSEAL + + .set reorder + + +/* ********************************************************************* + * Segment Table. + * + * Addresses of data segments and of certain routines we're going + * to call from KSEG1. These are here mostly for the embedded + * PIC case, since we can't count on the 'la' instruction to + * do the expected thing (the assembler expands it into a macro + * for doing GP-relative stuff, and the code is NOT GP-relative. + * So, we (relocatably) get the offset of this table and then + * index within it. + * + * Pointer values in this segment will be relative to KSEG0 for + * cached versions of CFE, so we need to OR in K1BASE in the + * case of calling to a uncached address. + * + * The LOADREL macro handles most of the nastiness here. + ********************************************************************* */ + + +#include "segtable.h" + + .globl segment_table +segment_table: + _LONG_ _etext # [ 0] End of text (R_SEG_ETEXT) + _LONG_ _fdata # [ 1] Beginning of data (R_SEG_FDATA) + _LONG_ _edata # [ 2] End of data (R_SEG_EDATA) + _LONG_ _end # [ 3] End of BSS (R_SEG_END) + _LONG_ _ftext # [ 4] Beginning of text (R_SEG_FTEXT) + _LONG_ _fbss # [ 5] Beginning of BSS (R_SEG_FBSS) + _LONG_ _gp # [ 6] Global Pointer (R_SEG_GP) + _LONG_ 0 # [ 7] Beginning of reloc entries + _LONG_ 0 # [ 8] End of reloc entries + _LONG_ cpu_apientry # [ 9] R_SEG_APIENTRY + + +/* ********************************************************************* + * Init Table. + * + * This is like segment_table except it contains pointers to + * routines used during initialization. It serves both as a + * table for doing PIC stuff and also to separate out + * machine-specific init routines. + * + * The CALLINIT_xxx macros are used to call routines in this table. + ********************************************************************* */ + + + .globl init_table +init_table: + _LONG_ board_earlyinit # [ 0] R_INIT_EARLYINIT + _LONG_ board_setleds # [ 1] R_INIT_SETLEDS + _LONG_ board_draminfo # [ 2] R_INIT_DRAMINFO + _LONG_ CPUCFG_CPUINIT # [ 3] R_INIT_CPUINIT + _LONG_ CPUCFG_ALTCPU_START1 # [ 4] R_INIT_ALTCPU_START1 + _LONG_ CPUCFG_ALTCPU_START2 # [ 5] R_INIT_ALTCPU_START2 + _LONG_ CPUCFG_ALTCPU_RESET # [ 6] R_INIT_ALTCPU_RESET + _LONG_ CPUCFG_CPURESTART # [ 7] R_INIT_CPURESTART + _LONG_ CPUCFG_DRAMINIT # [ 8] R_INIT_DRAMINIT + _LONG_ CPUCFG_CACHEOPS # [ 9] R_INIT_CACHEOPS + _LONG_ CPUCFG_TLBHANDLER # [ 10] R_INIT_TLBHANDLER + _LONG_ cfe_main # [ 11] R_INIT_CMDSTART + _LONG_ cfe_command_restart # [ 12] R_INIT_CMDRESTART + _LONG_ cfe_doxreq # [ 13] R_INIT_DOXREQ + _LONG_ CPUCFG_TP1_SWITCH # [ 14] R_INIT_TP1_SWITCH + _LONG_ bcmcore_null # [ 15] R_INIT_SIZERAM + +/* ********************************************************************* + * CPU Startup Code + ********************************************************************* */ + + +cpu_reset: + +#------------------------------------------------------------------------------ + + /* + * Do low-level board initialization. This is our first + * chance to customize the startup sequence. + */ + + CALLINIT_KSEG0(init_table,R_INIT_EARLYINIT) + + SETLEDS('H','E','L','O') + +#------------------------------------------------------------------------------ + + /* + * DRAM is now running, and we're alive in cacheable memory + * on cpu0 in K0SEG. Set up GP. + */ + + LOADREL(a0,segment_table) + LR gp,R_SEG_GP(a0) + +#------------------------------------------------------------------------------ + /* + * Zero BSS + */ + + SETLEDS('Z','B','S','S') + + LOADREL(a0,segment_table) +__ZeroBss: + + LR v0,R_SEG_FBSS(a0) + LR v1,R_SEG_END(a0) + +1: SR zero,0(v0) # Zero one cacheline at a time + SR zero,(REGSIZE*1)(v0) + SR zero,(REGSIZE*2)(v0) + SR zero,(REGSIZE*3)(v0) + add v0,REGSIZE*4 + blt v0,v1,1b + + +#------------------------------------------------------------------------------ + + li k0,256 # memory size in megabytes + + +#ifdef __long64 + mfc0 t0,C0_SR + or t0,t0,M_SR_KX + mtc0 t0,C0_SR +#endif + +#------------------------------------------------------------------------------ + + /* + * Remember total amount of memory. This is *still* in k0 + * after all this time. Hopefully. + */ + +__MemVars: + SR k0,mem_totalsize + SR zero,mem_datareloc + + move v0,zero + + LOADREL(a0,segment_table) # trashed by l2 cache flush + LR v0,R_SEG_FTEXT(a0) # bottom = beginning of text + LR v1,R_SEG_END(a0) + + SR v0,mem_bottomofmem + SR v1,mem_heapstart + + add v1,(CFG_HEAP_SIZE*1024) # Otherwise + add v1,STACK_SIZE + SR v1,mem_topofmem + + SR zero,mem_textreloc + + + LR t1,R_SEG_FTEXT(a0) + LR t0,R_SEG_ETEXT(a0) + sub t0,t0,t1 + SR t0,mem_textsize + SR t1,mem_textbase + + +#------------------------------------------------------------------------------ + +#if CFG_MULTI_CPUS + /* + * Let secondary CPU(s) run their idle loops. Set the + * mailbox register to our relocation factor so we can read + * it out of the mailbox register and relocate GP properly. + */ + + move a0,zero + CALLINIT_KSEG0(init_table,R_INIT_ALTCPU_START2) +#endif + + /* + * Stash away some config register stuff + */ + + mfc0 v0,C0_PRID + SR v0,cpu_prid + + +#------------------------------------------------------------------------------ + + /* + * Set up the "C" stack and jump to the main routine. + */ + + SETLEDS('M','A','I','N') + + LR sp,mem_heapstart + ADD sp,((CFG_HEAP_SIZE*1024)+STACK_SIZE - 8) + li a0,0 # call as "cfe_main(0,0)" + li a1,0 + + CALLINIT_KSEG0(init_table,R_INIT_CMDSTART) # should not return + + + /* + * Terminate the simulator. + */ + +crash_sim: li $2,1 + li $4,0 + syscall 0xCA + b cpu_reset + + + +/* ********************************************************************* + * CFE_WARMSTART + * + * Restart the command interpreter + * + * Input parameters: + * A0 - command status + * nothing (GP has already been set up for us) + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(cfe_warmstart) + + SR a0,0(sp) # store on old stack + LOADREL(v0,init_table) + LR v0,R_INIT_CPURESTART(v0) + jal v0 # had better not trash GP or K1 + LR a0,0(sp) + + LR sp,mem_heapstart + ADD sp,((CFG_HEAP_SIZE*1024)+STACK_SIZE - 8) + + /* + * If someone called the API to do a warm start, clear the + * spin lock, since the call will never return. + */ + +#if CFG_MULTI_CPUS + SPIN_UNLOCK(cfe_spinlock,t0) +#endif + + CALLINIT_KSEG0(init_table,R_INIT_CMDRESTART) # should not return + +END(cfe_warmstart) + +/* ********************************************************************* + * CFE_FLUSHCACHE + * + * Perform certain cache operations + * + * Input parameters: + * a0 - flags (CFE_CACHE_xxx flags, or zero for a default) + * a1,a2 - start/end of range for "range invalidate" operations + * (not used otherwise) + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(_cfe_flushcache) + + sub sp,32 + SR ra,0(sp) + SR a0,8(sp) + SR s0,16(sp) + SR v1,24(sp) + + + CALLINIT_KSEG0(init_table,R_INIT_CACHEOPS) + + LR v1,24(sp) + LR s0,16(sp) + LR a0,8(sp) + LR ra,0(sp) + add sp,32 + j ra + +END(_cfe_flushcache) + + +/* ********************************************************************* + * CFE_LAUNCH + * + * Start the user program. The program is passed a handle + * that must be passed back when calling the firmware. + * + * Parameters passed to the called program are as follows: + * + * a0 - CFE handle + * a1 - entry vector + * a2 - reserved, will be 0 + * a3 - entrypoint signature. + * + * Input parameters: + * a0 - entry vector + * + * Return value: + * does not return + ********************************************************************* */ + +LEAF(cfe_launch) + + sub sp,8 + SR a0,0(sp) + + /* + * Mask all interrupts. + */ + mfc0 v0,C0_SR # Get current interrupt flag + li v1,M_SR_IE # master interrupt control + not v1 # disable interrupts + and v0,v1 # SR now has IE=0 + mtc0 v0,C0_SR # put back into CP0 + + /* + * Flush the D-Cache, since the program we loaded is "data". + * Invalidate the I-Cache, so that addresses in the program + * region will miss and need to be filled from the data we + * just flushed above. + */ + + li a0,CFE_CACHE_FLUSH_D|CFE_CACHE_INVAL_I + CALLINIT_KSEG0(init_table,R_INIT_CACHEOPS) + + /* + * Set things up for launching the program. Pass the + * handle in A0 - apps need to remember that and pass it + * back. + */ + + j RunProgram + +END(cfe_launch) + + /* + * This is a nice place to set a breakpoint. + */ +LEAF(RunProgram) + + LOADREL(a2,segment_table) + LR a2,R_SEG_APIENTRY(a2) # A2 = code entry + move t0,a0 # + move a1,zero # A1 = 0 + move a0,gp # A0 = handle + li a3,CFE_EPTSEAL # A3 = entrypoint signature + LR t0,0(sp) # entry point + j t0 # go for it. +END(RunProgram) + + + + +/* ********************************************************************* + * CFE_LEDS + * + * Set the on-board LEDs. + * + * Input parameters: + * a0 - LEDs + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(cfe_leds) + + j board_setleds # jump to BSP routine + +END(cfe_leds) + +/* ********************************************************************* + * TLB Fill Exeption Handler + ********************************************************************* */ + +cpu_tlbfill: + move k0,ra # Save, we're about to trash + LOADREL(k1,init_table) # Load offset of init table + LR k1,R_INIT_TLBHANDLER(k1) # Get entry from table + move ra,k0 # restore trashed ra + j k1 # Dispatch to handler + +/* ********************************************************************* + * XTLB Fill Exception Handler + ********************************************************************* */ + +cpu_xtlbfill: + j _exc_entry + +/* ********************************************************************* + * Cache Error Exception Handler + ********************************************************************* */ + +cpu_cacheerr: + j _exc_entry + + +/* ********************************************************************* + * General Exception Handler + ********************************************************************* */ + +cpu_exception: + j _exc_entry + + +/* ********************************************************************* + * General Interrupt Handler + ********************************************************************* */ + +cpu_interrupt: + j _exc_entry + + +/* ********************************************************************* + * EJTAG Debug Exception Handler + ********************************************************************* */ + +cpu_ejtag: + j cpu_reset + +/* ********************************************************************* + * cpu_apientry(handle,iocb) + * + * API entry point for external apps. + * + * Input parameters: + * a0 - firmware handle (used to determine the location of + * our relocated data) + * a1 - pointer to IOCB to execute + * + * Return value: + * v0 - return code, 0 if ok + ********************************************************************* */ + +#define _regidx(x) ((x)*8) + +#define CAE_SRSAVE _regidx(0) +#define CAE_GPSAVE _regidx(1) +#define CAE_RASAVE _regidx(2) +#define CAE_S0SAVE _regidx(3) +#define CAE_S1SAVE _regidx(4) +#define CAE_S2SAVE _regidx(5) +#define CAE_S3SAVE _regidx(6) +#define CAE_S4SAVE _regidx(7) +#define CAE_S5SAVE _regidx(8) +#define CAE_S6SAVE _regidx(9) +#define CAE_S7SAVE _regidx(10) + +#define CAE_STKSIZE _regidx(11) + +LEAF(cpu_apientry) + + sub sp,CAE_STKSIZE # Make room for our stuff + + mfc0 v0,C0_SR # Get current interrupt flag + SR v0,CAE_SRSAVE(sp) # save on stack + li t0,M_SR_IE # master interrupt control + not t0 # disable interrupts + and v0,t0 # SR now has IE=0 + mtc0 v0,C0_SR # put back into CP0 + + SR gp,CAE_GPSAVE(sp) # save GP + SR ra,CAE_RASAVE(sp) # and old RA + + SR s0,CAE_S0SAVE(sp) + SR s1,CAE_S1SAVE(sp) + SR s2,CAE_S2SAVE(sp) + SR s3,CAE_S3SAVE(sp) + SR s4,CAE_S4SAVE(sp) + SR s5,CAE_S5SAVE(sp) + SR s6,CAE_S6SAVE(sp) + SR s7,CAE_S7SAVE(sp) + + move gp,a0 # set up new GP + move a0,a1 # A0 points at IOCB + + +#if CFG_MULTI_CPUS + SPIN_LOCK(cfe_spinlock,t0,t1) +#endif + + CALLINIT_KSEG0(init_table,R_INIT_DOXREQ) # should not return + +#if CFG_MULTI_CPUS + SPIN_UNLOCK(cfe_spinlock,t0) +#endif + + # + # Restore the saved registers. + # + + LR s7,CAE_S7SAVE(sp) + LR s6,CAE_S6SAVE(sp) + LR s5,CAE_S5SAVE(sp) + LR s4,CAE_S4SAVE(sp) + LR s3,CAE_S3SAVE(sp) + LR s2,CAE_S2SAVE(sp) + LR s1,CAE_S1SAVE(sp) + LR s0,CAE_S0SAVE(sp) + + LR ra,CAE_RASAVE(sp) # unwind the stack + LR gp,CAE_GPSAVE(sp) + + LR t0,CAE_SRSAVE(sp) # old interrupt mask + + add sp,CAE_STKSIZE # restore old stack pointer + + mtc0 t0,C0_SR # restore interrupts + j ra + nop + +END(cpu_apientry) + + +/* ********************************************************************* + * CPU_KSEG0_SWITCH + * + * Hack the return address so we will come back in KSEG0 + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(cpu_kseg0_switch) + + and ra,(K0SIZE-1) + or ra,K0BASE + jr ra + +END(cpu_kseg0_switch) + + + + +/* ********************************************************************* + * _GETSTATUS() + * + * Read the STATUS register into v0 + * + * Input parameters: + * nothing + * + * Return value: + * v0 - Status register + ********************************************************************* */ + +LEAF(_getstatus) + + mfc0 v0,C0_SR + j ra +END(_getstatus) + + +/* ********************************************************************* + * _SETSTATUS() + * + * Set the STATUS register to the value in a0 + * + * Input parameters: + * nothing + * + * Return value: + * v0 - Status register + ********************************************************************* */ + +LEAF(_setstatus) + + mtc0 a0,C0_SR + j ra +END(_setstatus) + +/* ********************************************************************* + * _GETCAUSE() + * + * Read the CAUSE register into v0 + * + * Input parameters: + * nothing + * + * Return value: + * v0 - Cause register + ********************************************************************* */ + +LEAF(_getcause) + + mfc0 v0,C0_CAUSE + j ra +END(_getcause) + + +/* ********************************************************************* + * _GETTICKS() + * + * Read the COUNT register into v0 + * + * Input parameters: + * nothing + * + * Return value: + * v0 - count register + ********************************************************************* */ + +LEAF(_getticks) + + mfc0 v0,C0_COUNT + j ra +END(_getticks) + + +/* ********************************************************************* + * _SETALARM(ticks) + * + * Set the C0_Compare register from a0 + * + * Input parameters: + * a0 - compare register + * + * Return value: + * none + ********************************************************************* */ + +LEAF(_setalarm) + + mtc0 a0,C0_COMPARE + j ra +END(_setalarm) + + +/* ********************************************************************* + * _SETCONTEXT() + * + * Set the CONTEXT register. + * + * Input parameters: + * a0 - context + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(_setcontext) + + mtc0 a0,C0_CTEXT + j ra +END(_setcontext) + +/* ********************************************************************* + * _GETSEGTBL() + * + * Return the address of the segment table. We use this + * to display the startup messages. + * + * You can't just address the table from C because it lives + * in the text segment. + * + * Input parameters: + * nothing + * + * Return value: + * address of table + ********************************************************************* */ + + +LEAF(_getsegtbl) + move t0,ra + LOADREL(v0,segment_table) + move ra,t0 + j ra +END(_getsegtbl) + + +/* ********************************************************************* + * _wbflush() + * + * Flush the write buffer. This is probably not necessary + * on SiByte CPUs, but we have it for completeness. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(_wbflush) + + sync /* drain the buffers */ + la t0,__junk /* do an uncached read to force it out */ + or t0,K1BASE + lw zero,0(t0) + j ra + +END(_wbflush) + + +/* ********************************************************************* + * End + ********************************************************************* */ + + diff --git a/cfe/cfe/arch/mips/common/src/lib_hssubr.S b/cfe/cfe/arch/mips/common/src/lib_hssubr.S new file mode 100644 index 0000000..07085e3 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/lib_hssubr.S @@ -0,0 +1,194 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Hyperspace Subroutines File: lib_hssubr.S + * + * Little stub routines to allow access to KXSEG from 32-bit progs. + * + * Author: Mitch Lichtenberg (mitch@sibyte.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 "sbmips.h" +#include "mipsmacros.h" +#include "cpu_config.h" /* for definition of HAZARD */ + + +/* ********************************************************************* + * hs_read8 - read 8-bit bytes + ********************************************************************* */ + + +LEAF(hs_read8) + mfc0 t2,C0_SR + or t1,t2,M_SR_KX + mtc0 t1,C0_SR + HAZARD + + lbu v0,(a0) + + mtc0 t2,C0_SR + HAZARD + j ra +END(hs_read8) + +/* ********************************************************************* + * hs_read16 - read 16-bit shorts + ********************************************************************* */ + +LEAF(hs_read16) + mfc0 t2,C0_SR + or t1,t2,M_SR_KX + mtc0 t1,C0_SR + HAZARD + + lhu v0,(a0) + + mtc0 t2,C0_SR + HAZARD + j ra +END(hs_read16) + +/* ********************************************************************* + * hs_read32 - read 32-bit ints + ********************************************************************* */ + +LEAF(hs_read32) + mfc0 t2,C0_SR + or t1,t2,M_SR_KX + mtc0 t1,C0_SR + HAZARD + + lw v0,(a0) + + mtc0 t2,C0_SR + HAZARD + j ra +END(hs_read32) + +/* ********************************************************************* + * hs_read64 - read 64-bit longs + ********************************************************************* */ + +LEAF(hs_read64) + mfc0 t2,C0_SR + or t1,t2,M_SR_KX + mtc0 t1,C0_SR + HAZARD + + ld v0,(a0) + + mtc0 t2,C0_SR + HAZARD + j ra +END(hs_read64) + +/* ********************************************************************* + * hs_write8 - write 8-bit bytes + ********************************************************************* */ + +LEAF(hs_write8) + mfc0 t2,C0_SR + or t1,t2,M_SR_KX + mtc0 t1,C0_SR + HAZARD + + sb a1,(a0) + + mtc0 t2,C0_SR + HAZARD + j ra +END(hs_write8) + +/* ********************************************************************* + * hs_write16 - write 16-bit shorts + ********************************************************************* */ + +LEAF(hs_write16) + mfc0 t2,C0_SR + or t1,t2,M_SR_KX + mtc0 t1,C0_SR + HAZARD + + sh a1,(a0) + + mtc0 t2,C0_SR + HAZARD + j ra +END(hs_write16) + +/* ********************************************************************* + * hs_write32 - write 32-bit longs + ********************************************************************* */ + +LEAF(hs_write32) + mfc0 t2,C0_SR + or t1,t2,M_SR_KX + mtc0 t1,C0_SR + HAZARD + + sw a1,(a0) + + mtc0 t2,C0_SR + HAZARD + j ra +END(hs_write32) + +/* ********************************************************************* + * hs_write64 - write 64-bit longs + ********************************************************************* */ + +LEAF(hs_write64) + mfc0 t2,C0_SR + or t1,t2,M_SR_KX + mtc0 t1,C0_SR + HAZARD + + sd a1,(a0) + + mtc0 t2,C0_SR + HAZARD + j ra +END(hs_write64) + + +/* ********************************************************************* + * End + ********************************************************************* */ + diff --git a/cfe/cfe/arch/mips/common/src/lib_physio.S b/cfe/cfe/arch/mips/common/src/lib_physio.S new file mode 100644 index 0000000..7f57fea --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/lib_physio.S @@ -0,0 +1,173 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Physical memory peek/poke routines File: lib_physio.S + * + * Little stub routines to allow access to arbitrary physical + * addresses. In most cases this should not be needed, as + * many physical addresses are within kseg1, but this handles + * the cases that are not automagically, so we don't need + * to mess up the code with icky macros and such. + * + * 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 "sbmips.h" +#include "mipsmacros.h" +#include "cpu_config.h" /* for definition of HAZARD */ + + +/* ********************************************************************* + * PHYSOP(inst,a) + * + * Macro to construct code for doing the physical I/O + * We try to avoid messing with KX or doing 64-bit stuff + * unless necessary. + * + * Input parameters: + * INST - instruction name to run + * A - register containing arg or return value + * + * Return value: + * nothing + ********************************************************************* */ + + + +#ifdef _MIPSREGS32_ +#define PHYSOP(INST,A) \ + or a0,a0,K1BASE ; \ + INST A,0(a0) ; \ + j ra ; +#else +#define PHYSOP(INST,A) \ + lui t0,0x2000 ; \ + bgeu a0,t0,1f ; \ + or a0,a0,K1BASE ; \ + INST A,0(a0) ; \ + j ra ; \ +1: lui t0,0x9000 ; \ + dsll t0,t0,32 ; \ + or a0,a0,t0 ; \ + mfc0 t1,C0_SR ; \ + and t0,t1,M_SR_KX ; \ + beq t0,zero,1f ; \ + INST A,0(a0) ; \ + j ra ; \ +1: or t0,t1,M_SR_KX ; \ + mtc0 t0,C0_SR ; \ + HAZARD ; \ + INST A,0(a0) ; \ + mtc0 t1,C0_SR ; \ + HAZARD ; \ + j ra ; +#endif + + +/* ********************************************************************* + * phys_read8 - read 8-bit bytes + ********************************************************************* */ + + +LEAF(phys_read8) +PHYSOP(lbu,v0) +END(phys_read8) + +/* ********************************************************************* + * phys_read16 - read 16-bit shorts + ********************************************************************* */ + +LEAF(phys_read16) +PHYSOP(lh,v0) +END(phys_read16) + +/* ********************************************************************* + * phys_read32 - read 32-bit ints + ********************************************************************* */ + +LEAF(phys_read32) +PHYSOP(lw,v0) +END(phys_read32) + +/* ********************************************************************* + * phys_read64 - read 64-bit longs + ********************************************************************* */ + +LEAF(phys_read64) +PHYSOP(ld,v0) +END(phys_read64) + +/* ********************************************************************* + * phys_write8 - write 8-bit bytes + ********************************************************************* */ + +LEAF(phys_write8) +PHYSOP(sb,a1) +END(phys_write8) + +/* ********************************************************************* + * phys_write16 - write 16-bit shorts + ********************************************************************* */ + +LEAF(phys_write16) +PHYSOP(sh,a1) +END(phys_write16) + +/* ********************************************************************* + * phys_write32 - write 32-bit longs + ********************************************************************* */ + +LEAF(phys_write32) +PHYSOP(sw,a1) +END(phys_write32) + +/* ********************************************************************* + * phys_write64 - write 64-bit longs + ********************************************************************* */ + +LEAF(phys_write64) +PHYSOP(sd,a1) +END(phys_write64) + + +/* ********************************************************************* + * End + ********************************************************************* */ + diff --git a/cfe/cfe/arch/mips/common/src/lib_setjmp.S b/cfe/cfe/arch/mips/common/src/lib_setjmp.S new file mode 100644 index 0000000..b8c82b3 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/lib_setjmp.S @@ -0,0 +1,94 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Simple setjmp/longjmp File: lib_setjmp.S + * + * A very simple SETJMP and LONGJMP + * + * 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 "sbmips.h" +#include "lib_setjmp.h" + +#ifdef _MIPSREGS32_ +#define SREG sw +#define LREG lw +#else +#define SREG sd +#define LREG ld +#endif + +LEAF(lib_setjmp) + + SREG s0,JMPB_S0(a0) + SREG s1,JMPB_S1(a0) + SREG s2,JMPB_S2(a0) + SREG s3,JMPB_S3(a0) + SREG s4,JMPB_S4(a0) + SREG s5,JMPB_S5(a0) + SREG s6,JMPB_S6(a0) + SREG s7,JMPB_S7(a0) + SREG fp,JMPB_FP(a0) + SREG sp,JMPB_SP(a0) + SREG ra,JMPB_RA(a0) + move v0,zero + j ra + +END(lib_setjmp) + +LEAF(lib_longjmp) + LREG s0,JMPB_S0(a0) + LREG s1,JMPB_S1(a0) + LREG s2,JMPB_S2(a0) + LREG s3,JMPB_S3(a0) + LREG s4,JMPB_S4(a0) + LREG s5,JMPB_S5(a0) + LREG s6,JMPB_S6(a0) + LREG s7,JMPB_S7(a0) + LREG fp,JMPB_FP(a0) + LREG sp,JMPB_SP(a0) + LREG ra,JMPB_RA(a0) + move v0,a1 + jr ra +END(lib_longjmp) + diff --git a/cfe/cfe/arch/mips/common/src/mips_arena.c b/cfe/cfe/arch/mips/common/src/mips_arena.c new file mode 100644 index 0000000..d96fee6 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/mips_arena.c @@ -0,0 +1,186 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Physical Memory (arena) manager File: sb1250_arena.c + * + * This module describes the physical memory available to the + * firmware. + * + * 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 "lib_arena.h" + +#include "cfe_error.h" + +#include "cfe.h" +#include "cfe_mem.h" + +#include "initdata.h" + +#define _NOPROTOS_ +#include "cfe_boot.h" +#undef _NOPROTOS_ + +#include "cpu_config.h" + +#include "addrspace.h" + +/* ********************************************************************* + * Constants + ********************************************************************* */ + + +#define MEG (1024*1024) +#define KB 1024 +#define PAGESIZE 4096 +#define CFE_BOOTAREA_SIZE (256*KB) +#define CFE_BOOTAREA_ADDR 0x20000000 + + +/* ********************************************************************* + * Globals + ********************************************************************* */ + +extern arena_t cfe_arena; +uint64_t *cfe_pagetable = NULL; + +extern void CPUCFG_PAGETBLINIT(uint64_t *ptaddr,unsigned int ptstart); + +void cfe_bootarea_init(void); +extern void _setcontext(int64_t); + + +/* ********************************************************************* + * CFE_BOOTAREA_INIT() + * + * Initialize the page table and map our boot program area. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +void cfe_bootarea_init(void) +{ + unsigned char *pte; + int64_t pte_int; + unsigned int addr = 16*MEG; + unsigned int topmem; + unsigned int topcfe; + unsigned int botcfe; + unsigned int beforecfe; + unsigned int aftercfe; + + /* + * Calculate the location where the boot area will + * live. It lives either above or below the + * firmware, depending on where there's more space. + */ + + /* + * The firmware will always be loaded in the first + * 256M. Calculate the top of that region. The bottom + * of that region is always the beginning of our + * data segment. + */ + if (mem_totalsize > (uint64_t)256) { + topmem = 256*MEG; + } + else { + topmem = (unsigned int) (mem_totalsize << 20); + } + botcfe = (unsigned int) K1_TO_PHYS(mem_bottomofmem); + topcfe = (unsigned int) K1_TO_PHYS(mem_topofmem); + + beforecfe = botcfe; + aftercfe = topmem-topcfe; + + if (beforecfe > aftercfe) { + botcfe -= (PAGESIZE-1); + botcfe &= ~(PAGESIZE-1); /* round down to page boundary */ + addr = botcfe - CFE_BOOTAREA_SIZE; /* this is the address */ + } + else { + topcfe += (PAGESIZE-1); /* round *up* to a page address */ + topcfe &= ~(PAGESIZE-1); + addr = topcfe; + } + + mem_bootarea_start = addr; + mem_bootarea_size = CFE_BOOTAREA_SIZE; + + /* + * Allocate the page table + */ + + pte = KMALLOC(1024,1024); + +#ifdef __long64 + pte_int = (int64_t) pte; +#else + pte_int = (int64_t) ((int) pte); +#endif + + /* + * Set the CP0 CONTEXT register to point at the page table + */ + + pte_int <<= 13; + cfe_pagetable = (uint64_t *) pte; + + _setcontext(pte_int); + + + /* + * Initialize page table entries + */ + + CPUCFG_PAGETBLINIT(cfe_pagetable,addr); + + +} + diff --git a/cfe/cfe/arch/mips/common/src/tools.mk b/cfe/cfe/arch/mips/common/src/tools.mk new file mode 100755 index 0000000..d195de9 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/tools.mk @@ -0,0 +1,83 @@ +# +# Basic compiler options and preprocessor flags +# + +CFLAGS += -g -c -ffreestanding +CFLAGS += -O1 -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes + +# +# Tools locations +# + +ifndef TOOLS +TOOLS=/opt/toolchains/uclibc-crosstools-gcc-4.4.2-1/usr/bin/mips-linux- +endif + +GCC ?= $(TOOLS)gcc +GLD ?= $(TOOLS)ld +AR ?= $(TOOLS)ar +OBJDUMP ?= $(TOOLS)objdump +OBJCOPY ?= $(TOOLS)objcopy +RANLIB ?= $(TOOLS)ranlib + +# +# Check for 64-bit mode +# + +ifeq ($(strip ${CFG_MLONG64}),1) + CFLAGS += -mlong64 -D__long64 +endif + +# +# Figure out which linker script to use +# + +ifeq ($(strip ${CFG_RAMAPP}),1) + CFLAGS += -DCFG_RAMAPP=1 + LDFLAGS = -g --script ${ARCH_SRC}/cfe_ramapp.lds + CFLAGS += -DCFG_RUNFROMKSEG0=1 +else + ifeq ($(strip ${CFG_RELOC}),0) + ifeq ($(strip ${CFG_BOOTRAM}),1) + CFLAGS += -DCFG_BOOTRAM=1 + ROMRAM = ram + else + CFLAGS += -DCFG_BOOTRAM=0 + ROMRAM = rom + endif + ifeq ($(strip ${CFG_UNCACHED}),1) + CFLAGS += -DCFG_RUNFROMKSEG0=0 + LDFLAGS = -g --script ${ARCH_SRC}/cfe_${ROMRAM}_uncached.lds + else + CFLAGS += -DCFG_RUNFROMKSEG0=1 + LDFLAGS = -g --script ${ARCH_SRC}/cfe_${ROMRAM}_cached.lds + endif + else + CFLAGS += -membedded-pic -mlong-calls -DCFG_EMBEDDED_PIC=1 + ifeq ($(strip ${CFG_UNCACHED}),1) + CFLAGS += -DCFG_RUNFROMKSEG0=0 + LDFLAGS = -g --script ${ARCH_SRC}/cfe_rom_reloc_uncached.lds --embedded-relocs + else + CFLAGS += -DCFG_RUNFROMKSEG0=1 + ifeq ($(strip ${CFG_TEXTAT1MB}),1) + LDFLAGS = -g --script ${ARCH_SRC}/cfe_rom_reloc_cached_biendian.lds --embedded-relocs + else + LDFLAGS = -g --script ${ARCH_SRC}/cfe_rom_reloc_cached.lds --embedded-relocs + endif + endif + endif +endif +# +# Determine target endianness +# + +ifeq ($(strip ${CFG_LITTLE}),1) + ENDIAN = -EL + CFLAGS += -EL + LDFLAGS += -EL +else + ENDIAN = -EB + CFLAGS += -EB + LDFLAGS += -EB +endif + diff --git a/cfe/cfe/arch/mips/common/src/ui_memtest.c b/cfe/cfe/arch/mips/common/src/ui_memtest.c new file mode 100644 index 0000000..5388fd8 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/ui_memtest.c @@ -0,0 +1,282 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Test commands File: ui_memtest.c + * + * A simple memory test + * + * 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 "sbmips.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_error.h" + +#include "ui_command.h" +#include "cfe.h" + +#include "bsp_config.h" + +#include "cfe_mem.h" + + +#ifdef __long64 +static int ui_cmd_memorytest(ui_cmdline_t *cmd,int argc,char *argv[]); +#endif + +#ifndef _SB_MAKE64 +#define _SB_MAKE64(x) ((uint64_t)(x)) +#endif +#ifndef _SB_MAKEMASK +#define _SB_MAKEMASK(v,n) (_SB_MAKE64((_SB_MAKE64(1)<<(v))-1) << _SB_MAKE64(n)) +#endif +#ifndef _SB_MAKEMASK1 +#define _SB_MAKEMASK1(n) (_SB_MAKE64(1) << _SB_MAKE64(n)) +#endif + + +int ui_init_memtestcmds(void); + +int ui_init_memtestcmds(void) +{ +#ifdef __long64 + cmd_addcmd("memorytest", + ui_cmd_memorytest, + NULL, + "Tests all available memory", + "", + "-loop;Loop forever or until keypress|" + "-stoponerror;Stop if error occurs while looping|" + "-cca=*;Use specified cacheability attribute|" + "-arena=*;Test only specified arena index"); +#endif + return 0; +} + + +#ifdef __long64 +/* extensive memory tests */ + +static void inline uacwrite(volatile long *srcadr,long *dstadr) +{ +__asm __volatile ("ld $8, 0(%0) ; " + "ld $9, 8(%0) ; " + "ld $10, 16(%0) ; " + "ld $11, 24(%0) ; " + "sync ; " + "sd $8, 0(%1) ; " + "sd $9, 8(%1) ; " + "sd $10, 16(%1) ; " + "sd $11, 24(%1) ; " + "sync" :: "r"(srcadr),"r"(dstadr) : "$8","$9","$10","$11"); +} + + +#define TEST_DATA_LEN 4 +#define CACHE_LINE_LEN 32 + +static int ui_cmd_memorytest(ui_cmdline_t *cmd,int argc,char *argv[]) +{ + + static volatile long test_data[TEST_DATA_LEN] = { + 0xaaaaaaaaaaaaaaaa, 0x5555555555555555, 0xcccccccccccccccc, 0x3333333333333333, /* one cache line */ + }; + int arena, exitLoop; + int error; + int arena_type; + uint64_t arena_start, arena_size; + long phys_addr, offset, mem_base, cache_mem_base, i; + long *dst_adr, *cache_dst_adr; + long cda,tda; + int forever; + int passcnt; + int stoponerr = 0; + int cca = K_CALG_UNCACHED_ACCEL; + int arenanum = -1; + char *x; + + arena = 0; + exitLoop = 0; + offset = 0; + mem_base = 0; + passcnt = 0; + error = 0; + + forever = cmd_sw_isset(cmd,"-loop"); + stoponerr = cmd_sw_isset(cmd,"-stoponerror"); + if (cmd_sw_value(cmd,"-cca",&x)) cca = atoi(x); + if (cmd_sw_value(cmd,"-arena",&x)) arenanum = atoi(x); + + printf("Available memory arenas:\n"); + while (cfe_arena_enum(arena, &arena_type, &arena_start, &arena_size, FALSE) == 0) { + phys_addr = (long) arena_start; /* actual physical address */ + mem_base = PHYS_TO_XKPHYS(cca, phys_addr); /* virtual address */ + xprintf("phys = %016llX, virt = %016llX, size = %016llX\n", phys_addr, mem_base, arena_size); + arena++; + } + + printf("\nTesting memory.\n"); + do { + + passcnt++; + if (forever) { + if (console_status()) break; + printf("***** Iteration %d *****\n",passcnt); + } + + arena = 0; + exitLoop = 0; + error = 0; + + while (cfe_arena_enum(arena, &arena_type, &arena_start, &arena_size, FALSE) == 0) { + + if ((arenanum >= 0) && (arena != arenanum)) { + arena++; + continue; + } + + test_data[0] = 0xAAAAAAAAAAAAAAAA; + test_data[1] = 0x5555555555555555; + test_data[2] = 0xCCCCCCCCCCCCCCCC; + test_data[3] = 0x3333333333333333; + + phys_addr = (long) arena_start; /* actual physical address */ + mem_base = PHYS_TO_XKPHYS(cca, phys_addr); /* virtual address */ + cache_mem_base = PHYS_TO_K0(phys_addr); + + xprintf("\n"); + xprintf("Testing: phys = %016llX, virt = %016llX, size = %016llX\n", phys_addr, mem_base, arena_size); + + xprintf("Writing: a/5/c/3\n"); + + for (offset = 0; (offset < arena_size); offset += CACHE_LINE_LEN) { + dst_adr = (long*)(mem_base+offset); + uacwrite(test_data, dst_adr); + } + + xprintf("Reading: a/5/c/3\n"); + + for (offset = 0; (offset < arena_size); offset += CACHE_LINE_LEN) { + dst_adr = (long*)(mem_base+offset); + cache_dst_adr = (long*)(mem_base+offset); + for (i = 0; i < TEST_DATA_LEN; i++) { + cda = cache_dst_adr[i]; + tda = test_data[i]; + if (cda != tda) { + xprintf("mem[%016llX] %016llX != %016llX\n", + mem_base+offset+(i*8), cda, tda); + exitLoop = 1; + } + } + if (exitLoop) break; + } + + + if (exitLoop) { + exitLoop = 0; + error++; + arena++; + continue; + } + + xprintf("Writing: address|5555/inv/aaaa|address\n"); + exitLoop = 0; + + for (offset = 0; (offset < arena_size); offset += CACHE_LINE_LEN) { + dst_adr = (long*)(mem_base+offset); + test_data[0] = ((long)dst_adr<<32)|0x55555555; + test_data[1] = ~test_data[0]; + test_data[2] = 0xaaaaaaaa00000000|((long)dst_adr & 0xffffffff); + test_data[3] = ~test_data[2]; + uacwrite(test_data, dst_adr); + } + + xprintf("Reading: address|5555/inv/aaaa|address\n"); + + for (offset = 0; (offset < arena_size); offset += CACHE_LINE_LEN) { + dst_adr = (long*)(mem_base+offset); + test_data[0] = ((long)dst_adr<<32)|0x55555555; + test_data[1] = ~test_data[0]; + test_data[2] = 0xaaaaaaaa00000000|((long)dst_adr & 0xffffffff); + test_data[3] = ~test_data[2]; + cache_dst_adr = (long*)(mem_base+offset); + for (i = 0; i < TEST_DATA_LEN; i++) { + cda = cache_dst_adr[i]; + tda = test_data[i]; + if (cda != tda) { + xprintf("mem[%016llX] %016llX != %016llX\n", + mem_base+offset+(i*8),cda,tda); + exitLoop = 1; + } + } + if (exitLoop) break; + } + + if (exitLoop) { + error++; + exitLoop = 0; + if (stoponerr) forever = 0; + } + + arena++; + } + } while (forever); + + if (error) printf("Failing address: %016llX\n",mem_base+offset); + + return error ? -1 : 0; +} + +#endif + + + + diff --git a/cfe/cfe/arch/mips/cpu/SIBYTE_PRIVATE_FILES b/cfe/cfe/arch/mips/cpu/SIBYTE_PRIVATE_FILES new file mode 100644 index 0000000..1e7d4b6 --- /dev/null +++ b/cfe/cfe/arch/mips/cpu/SIBYTE_PRIVATE_FILES @@ -0,0 +1,2 @@ +bcmcore +bcm1400 diff --git a/cfe/cfe/arch/mips/cpu/bcmcore/include/bcm4710.h b/cfe/cfe/arch/mips/cpu/bcmcore/include/bcm4710.h new file mode 100644 index 0000000..f499bc9 --- /dev/null +++ b/cfe/cfe/arch/mips/cpu/bcmcore/include/bcm4710.h @@ -0,0 +1,58 @@ +/* + Copyright 2001, Broadcom Corporation + All Rights Reserved. + + This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + the contents of this file may not be disclosed to third parties, copied or + duplicated in any form, in whole or in part, without the prior written + permission of Broadcom Corporation. +*/ +/* + * BCM4710 address space map and definitions + * + * Think twice before adding to this file, this is not the kitchen sink + * These definitions are not guaranteed for all 47xx chips, only the 4710 + * + * Copyright (C) 2000 Broadcom Corporation + * $Id: bcm4710.h,v 1.1 2001/10/31 18:49:25 mpl Exp $ + */ + +#ifndef _bcm4710_h_ +#define _bcm4710_h_ + +/* Address map */ +#define BCM4710_SDRAM 0x00000000 /* Physical SDRAM */ +#define BCM4710_PCI_MEM 0x08000000 /* Host Mode PCI memory access space (64 MB) */ +#define BCM4710_PCI_CFG 0x0c000000 /* Host Mode PCI configuration space (64 MB) */ +#define BCM4710_PCI_DMA 0x40000000 /* Client Mode PCI memory access space (1 GB) */ +#define BCM4710_SDRAM_SWAPPED 0x10000000 /* Byteswapped Physical SDRAM */ +#define BCM4710_ENUM 0x18000000 /* Beginning of core enumeration space */ + +/* Core register space */ +#define BCM4710_REG_SDRAM 0x18000000 /* SDRAM core registers */ +#define BCM4710_REG_ILINE20 0x18001000 /* InsideLine20 core registers */ +#define BCM4710_REG_EMAC0 0x18002000 /* Ethernet MAC 0 core registers */ +#define BCM4710_REG_CODEC 0x18003000 /* Codec core registers */ +#define BCM4710_REG_USB 0x18004000 /* USB core registers */ +#define BCM4710_REG_PCI 0x18005000 /* PCI core registers */ +#define BCM4710_REG_MIPS 0x18006000 /* MIPS core registers */ +#define BCM4710_REG_EXTIF 0x18007000 /* External Interface core registers */ +#define BCM4710_REG_EMAC1 0x18008000 /* Ethernet MAC 1 core registers */ + +#define BCM4710_EXTIF 0x1f000000 /* External Interface base address */ +#define BCM4710_EJTAG 0xff200000 /* MIPS EJTAG space (2M) */ + +#define BCM4710_UART (BCM4710_REG_EXTIF + 0x00000300) + +#define BCM4710_EUART (BCM4710_EXTIF + 0x00800000) +#define BCM4710_LED (BCM4710_EXTIF + 0x00900000) + +#ifdef CONFIG_VSIM +#define BCM4710_TRACE(trval) do { *((int *)0xa0002ff8) = (trval); } while (0) +#else +#define BCM4710_TRACE(trval) do { *((unsigned char *)KSEG1ADDR(BCM4710_LED)) = (trval); \ + *((int *)0xa0002ff8) = (trval); } while (0) +#endif + + +#endif /* _bcm4710_h_ */ diff --git a/cfe/cfe/arch/mips/cpu/bcmcore/include/bcm47xx.h b/cfe/cfe/arch/mips/cpu/bcmcore/include/bcm47xx.h new file mode 100644 index 0000000..eb752e5 --- /dev/null +++ b/cfe/cfe/arch/mips/cpu/bcmcore/include/bcm47xx.h @@ -0,0 +1,8 @@ +#ifndef _BCM47XX_H
+#define _BCM47XX_H
+
+/* uart defaults */
+#define DIV_LO 0x36
+#define DIV_HI 0
+
+#endif
diff --git a/cfe/cfe/arch/mips/cpu/bcmcore/include/bcmnvram.h b/cfe/cfe/arch/mips/cpu/bcmcore/include/bcmnvram.h new file mode 100644 index 0000000..b9d37e6 --- /dev/null +++ b/cfe/cfe/arch/mips/cpu/bcmcore/include/bcmnvram.h @@ -0,0 +1,123 @@ +/* + Copyright 2001, Broadcom Corporation + All Rights Reserved. + + This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + the contents of this file may not be disclosed to third parties, copied or + duplicated in any form, in whole or in part, without the prior written + permission of Broadcom Corporation. +*/ +/* + * NVRAM variable manipulation + * + * Copyright (C) 2001 Broadcom Corporation + * + * $Id: bcmnvram.h,v 1.1 2001/10/31 18:49:25 mpl Exp $ + */ + +#ifndef _bcmnvram_h_ +#define _bcmnvram_h_ + +#ifndef _LANGUAGE_ASSEMBLY + +struct nvram_header { + unsigned long magic; + unsigned long len; + unsigned long crc_ver_init; /* 0:7 crc, 8:15 ver, 16:27 init, mem. test 28, 29-31 reserved */ + unsigned long config_refresh; /* 0:15 config, 16:31 refresh */ + unsigned long reserved; +}; + +struct nvram_tuple { + char *name; + char *value; + struct nvram_tuple *next; +}; + +/* Compatibility */ +typedef struct nvram_tuple EnvRec; + +/* + * Get the value of an NVRAM variable + * @param name name of variable to get + * @return value of variable or NULL if undefined + */ +extern char * nvram_get(const char *name); + +/* + * Get the value of an NVRAM variable + * @param name name of variable to get + * @return value of variable or NUL if undefined + */ +#define nvram_safe_get(name) (nvram_get(name) ? : "") + +/* + * Match an NVRAM variable + * @param name name of variable to match + * @param match value to compare against value of variable + * @return TRUE if variable is defined and its value is string equal to match or FALSE otherwise + */ +#define nvram_match(name, match) ({ \ + const char *value = nvram_get(name); \ + (value && !strcmp(value, match)); \ +}) + +/* + * Match an NVRAM variable + * @param name name of variable to match + * @param match value to compare against value of variable + * @return TRUE if variable is defined and its value is not string equal to invmatch or FALSE otherwise + */ +#define nvram_invmatch(name, invmatch) ({ \ + const char *value = nvram_get(name); \ + (value && strcmp(value, invmatch)); \ +}) + +/* + * Set the value of an NVRAM variable + * @param name name of variable to set + * @param value value of variable + * @return 0 on success and errno on failure + * NOTE: use nvram_commit to commit this change to flash. + */ +extern int nvram_set(const char *name, const char *value); + +/* + * Unset an NVRAM variable + * @param name name of variable to unset + * @return 0 on success and errno on failure + * NOTE: use nvram_commit to commit this change to flash. + */ +extern int nvram_unset(const char *name); + +/* + * Permanently commit NVRAM variables + * @return 0 on success and errno on failure + */ +extern int nvram_commit(void); + +/* + * Get all NVRAM variables (format name=value\0 ... \0\0) + * @param buf buffer to store variables + * @param count size of buffer in bytes + * @return 0 on success and errno on failure + */ +extern int nvram_getall(char *buf, int count); + +/* + * Invalidate the current NVRAM header + * @return 0 on success and errno on failure + */ +extern int nvram_invalidate(void); + +#endif /* _LANGUAGE_ASSEMBLY */ + +#define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */ +#define NVRAM_VERSION 1 +#define NVRAM_HEADER_SIZE 20 +#define NVRAM_FIRST_LOC 0xbfcf8000 +#define NVRAM_LAST_LOC 0xbfff8000 +#define NVRAM_LOC_GAP 0x100000 +#define NVRAM_SPACE 0x8000 + +#endif /* _bcmnvram_h_ */ diff --git a/cfe/cfe/arch/mips/cpu/bcmcore/include/cpu_config.h b/cfe/cfe/arch/mips/cpu/bcmcore/include/cpu_config.h new file mode 100755 index 0000000..51cf4e1 --- /dev/null +++ b/cfe/cfe/arch/mips/cpu/bcmcore/include/cpu_config.h @@ -0,0 +1,62 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * CPU Configuration file File: cpu_config.h + * + * This file contains the names of the routines to be used + * in the dispatch table in init_mips.S + * + * It lives here in the CPU directory so we can direct + * the init calls to routines named in this directory. + * + * 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. + ********************************************************************* */ + +/* + */ + +#define CPUCFG_CPUINIT bcmcore_cpuinit +#define CPUCFG_ALTCPU_START1 bcmcore_null +#define CPUCFG_ALTCPU_START2 bcmcore_null +#define CPUCFG_ALTCPU_RESET bcmcore_null +#define CPUCFG_CPURESTART bcmcore_cpurestart +#define CPUCFG_DRAMINIT board_draminit /* no dram on CPU */ +#define CPUCFG_CACHEOPS bcmcore_cacheops +#define CPUCFG_ARENAINIT bcmcore_arena_init +#define CPUCFG_PAGETBLINIT bcmcore_pagetable_init +#define CPUCFG_TLBHANDLER bcmcore_tlbhandler +#define CPUCFG_DIAG_TEST1 bcmcore_null +#define CPUCFG_DIAG_TEST2 bcmcore_null +#if CFG_CMT +#define CPUCFG_TP1_SWITCH bcmcore_tp1_switch +#else +#define CPUCFG_TP1_SWITCH bcmcore_null +#endif +/* + * The BCMCORE ticks CP0 every other cycle. + */ + +#define CPUCFG_CYCLESPERCPUTICK 2 + +/* + * Hazard macro + */ + +#define HAZARD nop ; nop ; nop ; nop ; nop ; nop ; nop +#define ERET \ + .set push ; \ + .set mips4 ; \ + eret ; \ + .set pop + + diff --git a/cfe/cfe/arch/mips/cpu/bcmcore/include/sbmips.h b/cfe/cfe/arch/mips/cpu/bcmcore/include/sbmips.h new file mode 100644 index 0000000..0f4e055 --- /dev/null +++ b/cfe/cfe/arch/mips/cpu/bcmcore/include/sbmips.h @@ -0,0 +1,670 @@ +/* ********************************************************************* + * SB1250 Board Support Package + * + * MIPS64 CPU definitions File: sbmips.h + * + * This module contains constants and macros specific to the + * SB1 MIPS64 core. + * + * Author: Mitch Lichtenberg (mitch@sibyte.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. + ********************************************************************* */ + +#ifndef _SB_MIPS_H +#define _SB_MIPS_H + +/* ********************************************************************* + * Configure language + ********************************************************************* */ + +#if defined(__ASSEMBLER__) +#define _ATYPE_ +#define _ATYPE32_ +#define _ATYPE64_ +#else +#define _ATYPE_ (__SIZE_TYPE__) +#define _ATYPE32_ (int) +#define _ATYPE64_ (long long) +#endif + + +/* ********************************************************************* + * Bitfield macros + ********************************************************************* */ + +/* + * Make a mask for 1 bit at position 'n' + */ + +#define _MM_MAKEMASK1(n) (1 << (n)) + +/* + * Make a mask for 'v' bits at position 'n' + */ + +#define _MM_MAKEMASK(v,n) (((1<<(v))-1) << (n)) + +/* + * Make a value at 'v' at bit position 'n' + */ + +#define _MM_MAKEVALUE(v,n) ((v) << (n)) + +/* + * Retrieve a value from 'v' at bit position 'n' with 'm' mask bits + */ + +#define _MM_GETVALUE(v,n,m) (((v) & (m)) >> (n)) + + + +/* ********************************************************************* + * 32-bit MIPS Address Spaces + ********************************************************************* */ + +#ifdef __ASSEMBLER__ +#define _ACAST32_ +#define _ACAST64_ +#else +#define _ACAST32_ _ATYPE_ _ATYPE32_ /* widen if necessary */ +#define _ACAST64_ _ATYPE64_ /* do _not_ narrow */ +#endif + +/* 32-bit address map */ +#define UBASE 0x00000000 /* user+ mapped */ +#define USIZE 0x80000000 +#define K0BASE (_ACAST32_ 0x80000000) /* kernel unmapped cached */ +#define K0SIZE 0x20000000 +#define K1BASE (_ACAST32_ 0xa0000000) /* kernel unmapped uncached */ +#define K1SIZE 0x20000000 +#define KSBASE (_ACAST32_ 0xc0000000) /* supervisor+ mapped */ +#define KSSIZE 0x20000000 +#define K3BASE (_ACAST32_ 0xe0000000) /* kernel mapped */ +#define K3SIZE 0x20000000 + +/* 64-bit address map additions to the above (sign-extended) ranges */ +#define XUBASE (_ACAST64_ 0x0000000080000000) /* user+ mapped */ +#define XUSIZE (_ACAST64_ 0x00000FFF80000000) +#define XSSEGBASE (_ACAST64_ 0x4000000000000000) /* supervisor+ mapped */ +#define XSSEGSIZE (_ACAST64_ 0x0000100000000000) +#define XKPHYSBASE (_ACAST64_ 0x8000000000000000) /* kernel unmapped */ +#define XKPHYSSIZE (_ACAST64_ 0x0000100000000000) +#define XKSEGBASE (_ACAST64_ 0xC000000000000000) /* kernel mapped */ +#define XKSEGSIZE (_ACAST64_ 0x00000FFF80000000) + +#define GEN_VECT (_ACAST32_ 0x80000080) +#define UTLB_VECT (_ACAST32_ 0x80000000) + +/* ********************************************************************* + * Address space coercion macros + ********************************************************************* */ + +#define PHYS_TO_K0(pa) (K0BASE | (pa)) +#define PHYS_TO_K1(pa) (K1BASE | (pa)) +#define K0_TO_PHYS(va) ((va) & (K0SIZE-1)) +#define K1_TO_PHYS(va) ((va) & (K1SIZE-1)) +#define K0_TO_K1(va) ((va) | K1SIZE) +#define K1_TO_K0(va) ((va) & ~K1SIZE) + +#define PHYS_TO_XK1(p) (_ACAST64_ (0xffffffffa0000000 | (p))) +#define XK1_TO_PHYS(p) ((p) & (K1SIZE-1)) +#define PHYS_TO_XKPHYS(cca,p) (_SB_MAKEMASK1(63) | (_SB_MAKE64(cca) << 59) | (p)) +#define PHYS_TO_XKSEG_UNCACHED(p) PHYS_TO_XKPHYS(K_CALG_UNCACHED,(p)) +#define PHYS_TO_XKSEG_CACHED(p) PHYS_TO_XKPHYS(K_CALG_COH_SHAREABLE,(p)) +#define XKPHYS_TO_PHYS(p) ((p) & _SB_MAKEMASK(0,59)) + + +#if !defined(__ASSEMBLER__) +#define mips_wbflush() __asm__ __volatile__ ("sync" : : : "memory") +#define ISK0SEG(va) ((va) >= K0BASE && (va) <= (K0BASE + K0SIZE - 1)) +#define ISK1SEG(va) ((va) >= K1BASE && (va) <= (K1BASE + K1SIZE - 1)) +#endif + +/* ********************************************************************* + * Register aliases + ********************************************************************* */ + +#if defined(__ASSEMBLER__) +#define zero $0 +#define AT $1 /* assembler temporaries */ +#define v0 $2 /* value holders */ +#define v1 $3 +#define a0 $4 /* arguments */ +#define a1 $5 +#define a2 $6 +#define a3 $7 +#define t0 $8 /* temporaries */ +#define t1 $9 +#define t2 $10 +#define t3 $11 +#define t4 $12 +#define t5 $13 +#define t6 $14 +#define t7 $15 +#define ta0 $12 +#define ta1 $13 +#define ta2 $14 +#define ta3 $15 +#define s0 $16 /* saved registers */ +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 /* temporaries */ +#define t9 $25 +#define k0 $26 /* kernel registers */ +#define k1 $27 +#define gp $28 /* global pointer */ +#define sp $29 /* stack pointer */ +#define s8 $30 /* saved register */ +#define fp $30 /* frame pointer */ +#define ra $31 /* return address */ +#endif + +/* ********************************************************************* + * CP0 Registers + ********************************************************************* */ + +#if defined(__ASSEMBLER__) +#define C0_INX $0 /* CP0: TLB Index */ +#define C0_RAND $1 /* CP0: TLB Random */ +#define C0_TLBLO0 $2 /* CP0: TLB EntryLo0 */ +#define C0_TLBLO C0_TLBLO0 /* CP0: TLB EntryLo0 */ +#define C0_TLBLO1 $3 /* CP0: TLB EntryLo1 */ +#define C0_CTEXT $4 /* CP0: Context */ +#define C0_PGMASK $5 /* CP0: TLB PageMask */ +#define C0_WIRED $6 /* CP0: TLB Wired */ +#define C0_BADVADDR $8 /* CP0: Bad Virtual Address */ +#define C0_COUNT $9 /* CP0: Count */ +#define C0_TLBHI $10 /* CP0: TLB EntryHi */ +#define C0_COMPARE $11 /* CP0: Compare */ +#define C0_SR $12 /* CP0: Processor Status */ +#define C0_STATUS C0_SR /* CP0: Processor Status */ +#define C0_CAUSE $13 /* CP0: Exception Cause */ +#define C0_EPC $14 /* CP0: Exception PC */ +#define C0_PRID $15 /* CP0: Processor Revision Indentifier */ +#define C0_CONFIG $16 /* CP0: Config */ +#define C0_LLADDR $17 /* CP0: LLAddr */ +#define C0_WATCHLO $18 /* CP0: WatchpointLo */ +#define C0_WATCHHI $19 /* CP0: WatchpointHi */ +#define C0_XCTEXT $20 /* CP0: XContext */ +#define C0_ECC $26 /* CP0: ECC */ +#define C0_CACHEERR $27 /* CP0: CacheErr */ +#define C0_TAGLO $28 /* CP0: TagLo */ +#define C0_TAGHI $29 /* CP0: TagHi */ +#define C0_ERREPC $30 /* CP0: ErrorEPC */ +#else +#define C0_INX 0 /* CP0: TLB Index */ +#define C0_RAND 1 /* CP0: TLB Random */ +#define C0_TLBLO0 2 /* CP0: TLB EntryLo0 */ +#define C0_TLBLO C0_TLBLO0 /* CP0: TLB EntryLo0 */ +#define C0_TLBLO1 3 /* CP0: TLB EntryLo1 */ +#define C0_CTEXT 4 /* CP0: Context */ +#define C0_PGMASK 5 /* CP0: TLB PageMask */ +#define C0_WIRED 6 /* CP0: TLB Wired */ +#define C0_BADVADDR 8 /* CP0: Bad Virtual Address */ +#define C0_COUNT 9 /* CP0: Count */ +#define C0_TLBHI 10 /* CP0: TLB EntryHi */ +#define C0_COMPARE 11 /* CP0: Compare */ +#define C0_SR 12 /* CP0: Processor Status */ +#define C0_STATUS C0_SR /* CP0: Processor Status */ +#define C0_CAUSE 13 /* CP0: Exception Cause */ +#define C0_EPC 14 /* CP0: Exception PC */ +#define C0_PRID 15 /* CP0: Processor Revision Indentifier */ +#define C0_CONFIG 16 /* CP0: Config */ +#define C0_LLADDR 17 /* CP0: LLAddr */ +#define C0_WATCHLO 18 /* CP0: WatchpointLo */ +#define C0_WATCHHI 19 /* CP0: WatchpointHi */ +#define C0_XCTEXT 20 /* CP0: XContext */ +#define C0_ECC 26 /* CP0: ECC */ +#define C0_CACHEERR 27 /* CP0: CacheErr */ +#define C0_TAGLO 28 /* CP0: TagLo */ +#define C0_TAGHI 29 /* CP0: TagHi */ +#define C0_ERREPC 30 /* CP0: ErrorEPC */ +#endif + +/* ********************************************************************* + * CP1 (floating point) control registers + ********************************************************************* */ + +#define FPA_IRR 0 /* CP1: Implementation/Revision */ +#define FPA_CSR 31 /* CP1: Control/Status */ + +/* ********************************************************************* + * Macros for generating assembly language routines + ********************************************************************* */ + +#if defined(__ASSEMBLER__) + +/* global leaf function (does not call other functions) */ +#define LEAF(name) \ + .globl name; \ + .ent name; \ +name: + +/* global alternate entry to (local or global) leaf function */ +#define XLEAF(name) \ + .globl name; \ + .aent name; \ +name: + +/* end of a global function */ +#define END(name) \ + .size name,.-name; \ + .end name + +/* local leaf function (does not call other functions) */ +#define SLEAF(name) \ + .ent name; \ +name: + +/* local alternate entry to (local or global) leaf function */ +#define SXLEAF(name) \ + .aent name; \ +name: + +/* end of a local function */ +#define SEND(name) \ + END(name) + +/* define & export a symbol */ +#define EXPORT(name) \ + .globl name; \ +name: + +/* import a symbol */ +#define IMPORT(name, size) \ + .extern name,size + +/* define a zero-fill common block (BSS if not overridden) with a global name */ +#define COMM(name,size) \ + .comm name,size + +/* define a zero-fill common block (BSS if not overridden) with a local name */ +#define LCOMM(name,size) \ + .lcomm name,size + +#endif + + +/* Floating-Point Control register bits */ +#define CSR_C 0x00800000 +#define CSR_EXC 0x0003f000 +#define CSR_EE 0x00020000 +#define CSR_EV 0x00010000 +#define CSR_EZ 0x00008000 +#define CSR_EO 0x00004000 +#define CSR_EU 0x00002000 +#define CSR_EI 0x00001000 +#define CSR_TV 0x00000800 +#define CSR_TZ 0x00000400 +#define CSR_TO 0x00000200 +#define CSR_TU 0x00000100 +#define CSR_TI 0x00000080 +#define CSR_SV 0x00000040 +#define CSR_SZ 0x00000020 +#define CSR_SO 0x00000010 +#define CSR_SU 0x00000008 +#define CSR_SI 0x00000004 +#define CSR_RM 0x00000003 + +/* Status Register */ +#define M_SR_CUMASK _MM_MAKEMASK(4,28) /* coprocessor usable bits */ +#define M_SR_CU3 _MM_MAKEMASK1(31) /* coprocessor 3 usable */ +#define M_SR_CU2 _MM_MAKEMASK1(30) /* coprocessor 2 usable */ +#define M_SR_CU1 _MM_MAKEMASK1(29) /* coprocessor 1 usable */ +#define M_SR_CU0 _MM_MAKEMASK1(28) /* coprocessor 0 usable */ + +#define M_SR_RP _MM_MAKEMASK1(27) /* reduced power mode */ +#define M_SR_FR _MM_MAKEMASK1(26) /* fpu regs any data */ +#define M_SR_RE _MM_MAKEMASK1(25) /* reverse endian */ +#define M_SR_MX _MM_MAKEMASK1(24) /* MDMX */ +#define M_SR_PX _MM_MAKEMASK1(23) /* 64-bit ops in user mode */ +#define M_SR_BEV _MM_MAKEMASK1(22) /* boot exception vectors */ +#define M_SR_TS _MM_MAKEMASK1(21) /* TLB is shut down */ +#define M_SR_SR _MM_MAKEMASK1(20) /* soft reset */ +#define M_SR_NMI _MM_MAKEMASK1(19) /* nonmaskable interrupt */ + +#define M_SR_IMASK _MM_MAKEMASK(8,8) /* all interrupt mask bits */ + +#define M_SR_IBIT8 _MM_MAKEMASK1(15) /* individual bits */ +#define M_SR_IBIT7 _MM_MAKEMASK1(14) +#define M_SR_IBIT6 _MM_MAKEMASK1(13) +#define M_SR_IBIT5 _MM_MAKEMASK1(12) +#define M_SR_IBIT4 _MM_MAKEMASK1(11) +#define M_SR_IBIT3 _MM_MAKEMASK1(10) +#define M_SR_IBIT2 _MM_MAKEMASK1(9) +#define M_SR_IBIT1 _MM_MAKEMASK1(8) + +#define M_SR_IMASK8 0 /* masks for nested int levels */ +#define M_SR_IMASK7 _MM_MAKEMASK(1,15) +#define M_SR_IMASK6 _MM_MAKEMASK(2,14) +#define M_SR_IMASK5 _MM_MAKEMASK(3,13) +#define M_SR_IMASK4 _MM_MAKEMASK(4,12) +#define M_SR_IMASK3 _MM_MAKEMASK(5,11) +#define M_SR_IMASK2 _MM_MAKEMASK(6,10) +#define M_SR_IMASK1 _MM_MAKEMASK(7,9) +#define M_SR_IMASK0 _MM_MAKEMASK(8,8) + +#define M_SR_KX _MM_MAKEMASK1(7) /* 64-bit access for kernel */ +#define M_SR_SX _MM_MAKEMASK1(6) /* .. for supervisor */ +#define M_SR_UX _MM_MAKEMASK1(5) /* .. for user */ + +#define S_SR_KSU 3 /* base operating mode mode */ +#define M_SR_KSU _MM_MAKEMASK(2,S_SR_KSU) +#define V_SR_KSU(x) _MM_MAKEVALUE(x,S_SR_KSU) +#define G_SR_KSU(x) _MM_GETVALUE(x,S_SR_KSU,M_SR_KSU) +#define K_SR_KSU_KERNEL 0 +#define K_SR_KSU_SUPR 1 +#define K_SR_KSU_USER 2 + +#define M_SR_UM _MM_MAKEMASK1(4) +#define M_SR_ERL _MM_MAKEMASK1(2) +#define M_SR_EXL _MM_MAKEMASK1(1) +#define M_SR_IE _MM_MAKEMASK1(0) + +/* + * Cause Register + */ +#define M_CAUSE_BD _MM_MAKEMASK1(31) /* exception in BD slot */ + +#define S_CAUSE_CE 28 /* coprocessor error */ +#define M_CAUSE_CE _MM_MAKEMASK(2,S_CAUSE_CE) +#define V_CAUSE_CE(x) _MM_MAKEVALUE(x,S_CAUSE_CE) +#define G_CAUSE_CE(x) _MM_GETVALUE(x,S_CAUSE_CE,M_CAUSE_CE) + +#define M_CAUSE_IV _MM_MAKEMASK1(23) /* special interrupt */ +#define M_CAUSE_WP _MM_MAKEMASK1(22) /* watch interrupt deferred */ + +#define S_CAUSE_IPMASK 8 +#define M_CAUSE_IPMASK _MM_MAKEMASK(8,S_CAUSE_IPMASK) +#define M_CAUSE_IP8 _MM_MAKEMASK1(15) /* hardware interrupts */ +#define M_CAUSE_IP7 _MM_MAKEMASK1(14) +#define M_CAUSE_IP6 _MM_MAKEMASK1(13) +#define M_CAUSE_IP5 _MM_MAKEMASK1(12) +#define M_CAUSE_IP4 _MM_MAKEMASK1(11) +#define M_CAUSE_IP3 _MM_MAKEMASK1(10) +#define M_CAUSE_SW2 _MM_MAKEMASK1(9) /* software interrupts */ +#define M_CAUSE_SW1 _MM_MAKEMASK1(8) + +#define S_CAUSE_EXC 2 +#define M_CAUSE_EXC _MM_MAKEMASK(5,S_CAUSE_EXC) +#define V_CAUSE_EXC(x) _MM_MAKEVALUE(x,S_CAUSE_EXC) +#define G_CAUSE_EXC(x) _MM_GETVALUE(x,S_CAUSE_EXC,M_CAUSE_EXC) + +/* Exception Code */ +#define K_CAUSE_EXC_INT 0 /* External interrupt */ +#define K_CAUSE_EXC_MOD 1 /* TLB modification */ +#define K_CAUSE_EXC_TLBL 2 /* TLB miss (Load or Ifetch) */ +#define K_CAUSE_EXC_TLBS 3 /* TLB miss (Save) */ +#define K_CAUSE_EXC_ADEL 4 /* Address error (Load or Ifetch) */ +#define K_CAUSE_EXC_ADES 5 /* Address error (Save) */ +#define K_CAUSE_EXC_IBE 6 /* Bus error (Ifetch) */ +#define K_CAUSE_EXC_DBE 7 /* Bus error (data load or store) */ +#define K_CAUSE_EXC_SYS 8 /* System call */ +#define K_CAUSE_EXC_BP 9 /* Break point */ +#define K_CAUSE_EXC_RI 10 /* Reserved instruction */ +#define K_CAUSE_EXC_CPU 11 /* Coprocessor unusable */ +#define K_CAUSE_EXC_OVF 12 /* Arithmetic overflow */ +#define K_CAUSE_EXC_TRAP 13 /* Trap exception */ +#define K_CAUSE_EXC_VCEI 14 /* Virtual Coherency Exception (I) */ +#define K_CAUSE_EXC_FPE 15 /* Floating Point Exception */ +#define K_CAUSE_EXC_CP2 16 /* Cp2 Exception */ +#define K_CAUSE_EXC_WATCH 23 /* Watchpoint exception */ +#define K_CAUSE_EXC_VCED 31 /* Virtual Coherency Exception (D) */ + +#define K_NTLBENTRIES 64 + +#define HI_HALF(x) ((x) >> 16) +#define LO_HALF(x) ((x) & 0xffff) + +/* FPU stuff */ + +#if defined(__ASSEMBLER__) +#define C1_CSR $31 +#define C1_FRID $0 +#else +#define C1_CSR 31 +#define C1_FRID 0 +#endif + +#define S_FCSR_CAUSE 12 +#define M_FCSR_CAUSE _MM_MAKEMASK(5,S_FCSR_CAUSE) +#define V_FCSR_CAUSE(x) _MM_MAKEVALUE(x,S_FCSR_CAUSE) +#define G_FCSR_CAUSE(x) _MM_GETVALUE(x,S_FCSR_CAUSE,M_FCSR_CAUSE) + +#define S_FCSR_ENABLES 7 +#define M_FCSR_ENABLES _MM_MAKEMASK(5,S_FCSR_ENABLES) +#define V_FCSR_ENABLES(x) _MM_MAKEVALUE(x,S_FCSR_ENABLES) +#define G_FCSR_ENABLES(x) _MM_GETVALUE(x,S_FCSR_ENABLES,M_FCSR_ENABLES) + +#define S_FCSR_FLAGS 2 +#define M_FCSR_FLAGS _MM_MAKEMASK(5,S_FCSR_FLAGS) +#define V_FCSR_FLAGS(x) _MM_MAKEVALUE(x,S_FCSR_FLAGS) +#define G_FCSR_FLAGS(x) _MM_GETVALUE(x,S_FCSR_FLAGS,M_FCSR_FLAGS) + + +/* + * MIPS64 Config Register (select 0) + */ +#define M_CFG_CFG1 _MM_MAKEMASK1(31) /* config1 select1 is impl */ +#define M_CFG_BE _MM_MAKEMASK1(15) /* big-endian mode */ + +#define S_CFG_AT 13 /* Architecture Type */ +#define M_CFG_AT _MM_MAKEMASK(2,S_CFG_AT) +#define V_CFG_AT(x) _MM_MAKEVALUE(x,S_CFG_AT) +#define G_CFG_AT(x) _MM_GETVALUE(x,S_CFG_AT,M_CFG_AT) +#define K_CFG_AT_MIPS32 0 +#define K_CFG_AT_MIPS64_32 1 +#define K_CFG_AT_MIPS64 2 + +#define S_CFG_AR 10 /* Architecture Revision */ +#define M_CFG_AR _MM_MAKEMASK(3,S_CFG_AR) +#define V_CFG_AR(x) _MM_MAKEVALUE(x,S_CFG_AR) +#define G_CFG_AR(x) _MM_GETVALUE(x,S_CFG_AR,M_CFG_AR) +#define K_CFG_AR_REV1 0 + +#define S_CFG_MMU 7 /* MMU Type */ +#define M_CFG_MMU _MM_MAKEMASK(3,S_CFG_MMU) +#define V_CFG_MMU(x) _MM_MAKEVALUE(x,S_CFG_MMU) +#define G_CFG_MMU(x) _MM_GETVALUE(x,S_CFG_MMU,M_CFG_MMU) +#define K_CFG_MMU_NONE 0 +#define K_CFG_MMU_TLB 1 +#define K_CFG_MMU_BAT 2 +#define K_CFG_MMU_FIXED 3 + +#define S_CFG_K0COH 0 /* K0seg coherency */ +#define M_CFG_K0COH _MM_MAKEMASK(3,S_CFG_K0COH) +#define V_CFG_K0COH(x) _MM_MAKEVALUE(x,S_CFG_K0COH) +#define G_CFG_K0COH(x) _MM_GETVALUE(x,S_CFG_K0COH,M_CFG_K0COH) +#define K_CFG_K0COH_UNCACHED 2 +#define K_CFG_K0COH_CACHEABLE 3 +#define K_CFG_K0COH_COHERENT 5 + +/* + * MIPS64 Config Register (select 1) + */ + +#define M_CFG_CFG2 _MM_MAKEMASK1(31) /* config2 select2 is impl */ + +#define S_CFG_MMUSIZE 25 +#define M_CFG_MMUSIZE _MM_MAKEMASK(6,S_CFG_MMUSIZE) + +#define S_CFG_IS 22 +#define M_CFG_IS _MM_MAKEMASK(3,S_CFG_IS) +#define V_CFG_IS(x) _MM_MAKEVALUE(x,S_CFG_IS) +#define G_CFG_IS(x) _MM_GETVALUE(x,S_CFG_IS,M_CFG_IS) + +#define S_CFG_IL 19 +#define M_CFG_IL _MM_MAKEMASK(S_CFG_IL,3) +#define V_CFG_IL(x) _MM_MAKEVALUE(x,S_CFG_IL) +#define G_CFG_IL(x) _MM_GETVALUE(x,S_CFG_IL,M_CFG_IL) + +#define S_CFG_IA 16 +#define M_CFG_IA _MM_MAKEMASK(3,S_CFG_IA) +#define V_CFG_IA(x) _MM_MAKEVALUE(x,S_CFG_IA) +#define G_CFG_IA(x) _MM_GETVALUE(x,S_CFG_IA,M_CFG_IA) + +#define S_CFG_DS 13 +#define M_CFG_DS _MM_MAKEMASK(3,S_CFG_DS) +#define V_CFG_DS(x) _MM_MAKEVALUE(x,S_CFG_DS) +#define G_CFG_DS(x) _MM_GETVALUE(x,S_CFG_DS,M_CFG_DS) + +#define S_CFG_DL 10 +#define M_CFG_DL _MM_MAKEMASK(3,S_CFG_DL) +#define V_CFG_DL(x) _MM_MAKEVALUE(x,S_CFG_DL) +#define G_CFG_DL(x) _MM_GETVALUE(x,S_CFG_DL,M_CFG_DL) + +#define S_CFG_DA 7 +#define M_CFG_DA _MM_MAKEMASK(3,S_CFG_DA) +#define V_CFG_DA(x) _MM_MAKEVALUE(x,S_CFG_DA) +#define G_CFG_DA(x) _MM_GETVALUE(x,S_CFG_DA,M_CFG_DA) + +#define M_CFG_PC _MM_MAKEMASK1(4) /* perf ctrs present */ +#define M_CFG_WR _MM_MAKEMASK1(3) /* watch regs present */ +#define M_CFG_CA _MM_MAKEMASK1(2) /* MIPS16 present */ +#define M_CFG_EP _MM_MAKEMASK1(1) /* EJTAG present */ +#define M_CFG_FP _MM_MAKEMASK1(0) /* FPU present */ + + + +/* + * Primary Cache TagLo + */ + +#define S_TAGLO_PTAG 8 +#define M_TAGLO_PTAG _MM_MAKEMASK(56,S_TAGLO_PTAG) + +#define S_TAGLO_PSTATE 6 +#define M_TAGLO_PSTATE _MM_MAKEMASK(2,S_TAGLO_PSTATE) +#define V_TAGLO_PSTATE(x) _MM_MAKEVALUE(x,S_TAGLO_PSTATE) +#define G_TAGLO_PSTATE(x) _MM_GETVALUE(x,S_TAGLO_PSTATE,M_TAGLO_PSTATE) +#define K_TAGLO_PSTATE_INVAL 0 +#define K_TAGLO_PSTATE_SHARED 1 +#define K_TAGLO_PSTATE_CLEAN_EXCL 2 +#define K_TAGLO_PSTATE_DIRTY_EXCL 3 + +#define M_TAGLO_LOCK _MM_MAKEMASK1(5) +#define M_TAGLO_PARITY _MM_MAKEMASK1(0) + + +/* + * CP0 CacheErr register + */ +#define M_CERR_DATA _MM_MAKEMASK1(31) /* err in D space */ +#define M_CERR_SCACHE _MM_MAKEMASK1(30) /* err in l2, not l1 */ +#define M_CERR_DERR _MM_MAKEMASK1(29) /* data error */ +#define M_CERR_TERR _MM_MAKEMASK1(28) /* tag error */ +#define M_CERR_EXTRQ _MM_MAKEMASK1(27) /* external req caused err */ +#define M_CERR_BPAR _MM_MAKEMASK1(26) /* bus parity err */ +#define M_CERR_ADATA _MM_MAKEMASK1(25) /* additional data */ +#define M_CERR_IDX _MM_MAKEMASK(22,0) + + + +/* + * Primary Cache operations + */ +#define Index_Invalidate_I 0x0 /* 0 0 */ +#define Index_Writeback_Inv_D 0x1 /* 0 1 */ +#define Index_Invalidate_SI 0x2 /* 0 2 */ +#define Index_Writeback_Inv_SD 0x3 /* 0 3 */ +#define Index_Load_Tag_I 0x4 /* 1 0 */ +#define Index_Load_Tag_D 0x5 /* 1 1 */ +#define Index_Load_Tag_SI 0x6 /* 1 2 */ +#define Index_Load_Tag_SD 0x7 /* 1 3 */ +#define Index_Store_Tag_I 0x8 /* 2 0 */ +#define Index_Store_Tag_D 0x9 /* 2 1 */ +#define Index_Store_Tag_SI 0xA /* 2 2 */ +#define Index_Store_Tag_SD 0xB /* 2 3 */ +#define Create_Dirty_Exc_D 0xD /* 3 1 */ +#define Create_Dirty_Exc_SD 0xF /* 3 3 */ +#define Hit_Invalidate_I 0x10 /* 4 0 */ +#define Hit_Invalidate_D 0x11 /* 4 1 */ +#define Hit_Invalidate_SI 0x12 /* 4 2 */ +#define Hit_Invalidate_SD 0x13 /* 4 3 */ +#define Fill_I 0x14 /* 5 0 */ +#define Hit_Writeback_Inv_D 0x15 /* 5 1 */ +#define Hit_Writeback_Inv_SD 0x17 /* 5 3 */ +#define Hit_Writeback_I 0x18 /* 6 0 */ +#define Hit_Writeback_D 0x19 /* 6 1 */ +#define Hit_Writeback_SD 0x1B /* 6 3 */ +#define Hit_Set_Virtual_SI 0x1E /* 7 2 */ +#define Hit_Set_Virtual_SD 0x1F /* 7 3 */ + +/* Watchpoint Register */ +#define M_WATCH_PA 0xfffffff8 +#define M_WATCH_R 0x00000002 +#define M_WATCH_W 0x00000001 + + +/* TLB entries */ +#define M_TLBHI_ASID _MM_MAKEMASK(0,8) +#define M_TLBHI_VPN2 _MM_MAKEMASK(27,13) + +#define M_TLBLO_G _MM_MAKEMASK1(0) +#define M_TLBLO_V _MM_MAKEMASK1(1) +#define M_TLBLO_D _MM_MAKEMASK1(2) + +#define S_TLBLO_CALG 3 +#define M_TLBLO_CALG _MM_MAKEMASK(3,S_TLBLO_CALG) +#define V_TLBLO_CALG(x) _MM_MAKEVALUE(x,S_TLBLO_CALG) +#define G_TLBLO_CALG(x) _MM_GETVALUE(x,S_TLBLO_CALG,M_TLBLO_CALG) + +#define K_CALG_COH_EXCL1_NOL2 0 +#define K_CALG_COH_SHRL1_NOL2 1 +#define K_CALG_UNCACHED 2 +#define K_CALG_NONCOHERENT 3 +#define K_CALG_COH_EXCL 4 +#define K_CALG_COH_SHAREABLE 5 +#define K_CALG_NOTUSED 6 +#define K_CALG_UNCACHED_ACCEL 7 + +#define S_TLBLO_PFNMASK 6 +#define M_TLBLO_PFNMASK _MM_MAKEMASK(24,S_TLBLO_PFNMASK) +#define V_TLBLO_PFNMASK(x) _MM_MAKEVALUE(x,S_TLBLO_PFNMASK) +#define G_TLBLO_PFNMASK(x) _MM_GETVALUE(x,S_TLBLO_PFNMASK,M_TLBLO_PFNMASK) + + + +#endif /* _SB_MIPS_H */ + + diff --git a/cfe/cfe/arch/mips/cpu/bcmcore/include/sbsdram.h b/cfe/cfe/arch/mips/cpu/bcmcore/include/sbsdram.h new file mode 100644 index 0000000..80e93e3 --- /dev/null +++ b/cfe/cfe/arch/mips/cpu/bcmcore/include/sbsdram.h @@ -0,0 +1,92 @@ +/* + Copyright 2001, Broadcom Corporation + All Rights Reserved. + + This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + the contents of this file may not be disclosed to third parties, copied or + duplicated in any form, in whole or in part, without the prior written + permission of Broadcom Corporation. +*/ +/* + * BCM47XX Sonics SiliconBackplane SDRAM controller core hardware definitions. + * + * $Id: sbsdram.h,v 1.1 2001/10/31 18:49:26 mpl Exp $ + */ + +#ifndef _SBSDRAM_H +#define _SBSDRAM_H + +#ifndef _LANGUAGE_ASSEMBLY + +/* Sonics side: SDRAM core registers */ +typedef volatile struct sbsdramregs { + uint32 initcontrol; /* Generates external SDRAM initialization sequence */ + uint32 config; /* Initializes external SDRAM mode register */ + uint32 refresh; /* Controls external SDRAM refresh rate */ + uint32 pad1; + uint32 pad2; +} sbsdramregs_t; + +#endif + +/* SDRAM initialization control (initcontrol) register bits */ +#define SDRAM_CBR 0x0001 /* Writing 1 generates refresh cycle and toggles bit */ +#define SDRAM_PRE 0x0002 /* Writing 1 generates precharge cycle and toggles bit */ +#define SDRAM_MRS 0x0004 /* Writing 1 generates mode register select cycle and toggles bit */ +#define SDRAM_EN 0x0008 /* When set, enables access to SDRAM */ +#define SDRAM_16Mb 0x0000 /* Use 16 Megabit SDRAM */ +#define SDRAM_64Mb 0x0010 /* Use 64 Megabit SDRAM */ +#define SDRAM_128Mb 0x0020 /* Use 128 Megabit SDRAM */ +#define SDRAM_RSVMb 0x0030 /* Use special SDRAM */ +#define SDRAM_RST 0x0080 /* Writing 1 causes soft reset of controller */ +#define SDRAM_SELFREF 0x0100 /* Writing 1 enables self refresh mode */ +#define SDRAM_PWRDOWN 0x0200 /* Writing 1 causes controller to power down */ +#define SDRAM_32BIT 0x0400 /* When set, indicates 32 bit SDRAM interface */ +#define SDRAM_9BITCOL 0x0800 /* When set, indicates 9 bit column */ + +/* SDRAM configuration (config) register bits */ +#define SDRAM_BURSTFULL 0x0000 /* Use full page bursts */ +#define SDRAM_BURST8 0x0001 /* Use burst of 8 */ +#define SDRAM_BURST4 0x0002 /* Use burst of 4 */ +#define SDRAM_BURST2 0x0003 /* Use burst of 2 */ +#define SDRAM_CAS3 0x0000 /* Use CAS latency of 3 */ +#define SDRAM_CAS2 0x0004 /* Use CAS latency of 2 */ + +/* SDRAM refresh control (refresh) register bits */ +#define SDRAM_REF(p) (((p)&0xff) | SDRAM_REF_EN) /* Refresh period */ +#define SDRAM_REF_EN 0x8000 /* Writing 1 enables periodic refresh */ + +/* SDRAM Core Init values (OCP ID 0x803) */ + +#define SDRAM_CONFIG SDRAM_BURSTFULL +#define SDRAM_REFRESH SDRAM_REF(0x40) + +#if defined(MEM1MX16_KM) +#define SDRAM_INIT 0x009 +#elif defined(MEM1MX16X2_KM) +#define SDRAM_INIT 0x409 +#elif defined(MEM2MX8X2_KM) +#define SDRAM_INIT 0x809 +#elif defined(MEM2MX8X4_KM) +#define SDRAM_INIT 0xc09 +#elif defined(MEM2MX32_KM) +#define SDRAM_INIT 0x439 +#elif defined(MEM4MX16_KM) +#define SDRAM_INIT 0x019 +#elif defined(MEM4MX16X2_KM) +#define SDRAM_INIT 0x419 +#elif defined(MEM8MX8X2_KM) +#define SDRAM_INIT 0x819 +#elif defined(MEM8MX8X4_KM) +#define SDRAM_INIT 0xc19 +#elif defined(MEM8MX16_KM) +#define SDRAM_INIT 0x829 +#elif defined(MEM8MX16X2_KM) +#define SDRAM_INIT 0xc29 +#elif defined(MEM4MX32_KM) +#define SDRAM_INIT 0x429 +#else /* DEFAULT MEM */ +#define SDRAM_INIT 0x419 +#endif + +#endif /* _SBSDRAM_H */ diff --git a/cfe/cfe/arch/mips/cpu/bcmcore/src/Makefile b/cfe/cfe/arch/mips/cpu/bcmcore/src/Makefile new file mode 100755 index 0000000..76662a0 --- /dev/null +++ b/cfe/cfe/arch/mips/cpu/bcmcore/src/Makefile @@ -0,0 +1,8 @@ + +ALLOBJS += bcmcore_cpuinit.o bcmcore_l1cache.o +ifeq ($(strip ${CFG_RAMAPP}),1) +ALLOBJS += bcmcore_arena.o +endif +CFLAGS += -mips32 -D_MIPSREGS32_ -mno-abicalls -fPIC +# CFLAGS += -mips2 -D_MIPSREGS32_ + diff --git a/cfe/cfe/arch/mips/cpu/bcmcore/src/bcmcore_arena.c b/cfe/cfe/arch/mips/cpu/bcmcore/src/bcmcore_arena.c new file mode 100755 index 0000000..b368158 --- /dev/null +++ b/cfe/cfe/arch/mips/cpu/bcmcore/src/bcmcore_arena.c @@ -0,0 +1,170 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Physical Memory (arena) manager File: bcmcore_arena.c + * + * This module describes the physical memory available to the + * firmware. + * + * 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 "sbmips.h" + +#include "lib_types.h" +#include "lib_string.h" +#include "lib_queue.h" +#include "lib_malloc.h" +#include "lib_printf.h" +#include "lib_arena.h" + +#include "cfe_error.h" + +#include "cfe.h" +#include "cfe_mem.h" + +#include "initdata.h" + +#define _NOPROTOS_ +#include "cfe_boot.h" +#undef _NOPROTOS_ + + +/* ********************************************************************* + * Macros + ********************************************************************* */ + +#define ARENA_RANGE(bottom,top,type) arena_markrange(&cfe_arena,(uint64_t)(bottom), \ + (uint64_t)(top)-(uint64_t)bottom+1,(type),NULL) + +#define MEG (1024*1024) +#define KB 1024 +#define PAGESIZE 4096 +#define CFE_BOOTAREA_SIZE (256*KB) +#define CFE_BOOTAREA_ADDR 0x20000000 + +/* ********************************************************************* + * Globals + ********************************************************************* */ + +extern arena_t cfe_arena; + +unsigned int mem_bootarea_start; +unsigned int mem_bootarea_size; + +void bcmcore_arena_init(void); +void bcmcore_pagetable_init(uint64_t *ptaddr,unsigned int physaddr); + + +/* ********************************************************************* + * bcmcore_arena_init() + * + * Create the initial map of physical memory + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +void bcmcore_arena_init(void) +{ + int64_t memleft; + +#if 1 /* defined(CONFIG_MIPS_BRCM) */ + arena_init(&cfe_arena,0x0,0x0); /* 2^32 physical bytes */ +#else + arena_init(&cfe_arena,0x0,0x100000000); /* 2^32 physical bytes */ +#endif + + /* + * Mark the ranges from the SB1250's memory map + */ + + ARENA_RANGE(0x0000000000,0x000FFFFFFF,MEMTYPE_DRAM_NOTINSTALLED); + + /* + * Now, fix up the map with what is known about *this* system. + * + * Do each 256MB chunk. + */ + + memleft = ((int64_t) mem_totalsize) << 20; + + arena_markrange(&cfe_arena,0x00000000,memleft,MEMTYPE_DRAM_AVAILABLE,NULL); + + /* + * Do the boot ROM + */ + + arena_markrange(&cfe_arena,0x1FC00000,2*1024*1024,MEMTYPE_BOOTROM,NULL); + +} + + +/* ********************************************************************* + * BCMCORE_PAGETABLE_INIT(ptaddr,physaddr) + * + * This routine constructs the page table. 256KB is mapped + * starting at physical address 'physaddr' - the resulting + * table entries are placed at 'ptaddr' + * + * Input parameters: + * ptaddr - base of page table + * physaddr - starting physical addr of area to map + * + * Return value: + * nothing + ********************************************************************* */ + +void bcmcore_pagetable_init(uint64_t *ptaddr,unsigned int physaddr) +{ + int idx; + + for (idx = 0; idx < (CFE_BOOTAREA_SIZE/PAGESIZE); idx++) { + ptaddr[idx] = (physaddr >> 6) | + V_TLBLO_CALG(K_CALG_NONCOHERENT) | + M_TLBLO_V | + M_TLBLO_D; + physaddr += PAGESIZE; + } + +} + diff --git a/cfe/cfe/arch/mips/cpu/bcmcore/src/bcmcore_cpuinit.S b/cfe/cfe/arch/mips/cpu/bcmcore/src/bcmcore_cpuinit.S new file mode 100755 index 0000000..7c04b51 --- /dev/null +++ b/cfe/cfe/arch/mips/cpu/bcmcore/src/bcmcore_cpuinit.S @@ -0,0 +1,490 @@ +/* ********************************************************************* + * SB1250 Board Support Package + * + * CPU initialization File: bcmcore_cpuinit.S + * + * This module contains code to initialize the CPU cores. + * + * Note: all the routines in this module rely on registers only, + * since DRAM may not be active yet. + * + * 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 "sbmips.h" +#include "exception.h" +#include "bsp_config.h" +#include "mipsmacros.h" +#include "cpu_config.h" /* for ERET and HAZARD */ + + + .text + + +/* ********************************************************************* + * Macros + ********************************************************************* */ + +#define LINESIZE 16 + +#define CACHEOP(cachename,op) ((cachename) | ((op) << 2)) + +#define CACHE_OP_IDXINVAL 0 +#define CACHE_OP_IDXLOADTAG 1 +#define CACHE_OP_IDXSTORETAG 2 +#define CACHE_OP_IMPLRSVD 3 +#define CACHE_OP_HITINVAL 4 +#define CACHE_OP_FILL 5 +#define CACHE_OP_HITWRITEBACK_INVAL 5 +#define CACHE_OP_HITWRITEBACK 6 +#define CACHE_OP_FETCHLOCK 7 + +#define L2C 3 +#define L1C_I 0 +#define L1C_D 1 + + +/* + * Duplicates from cfe_iocb.h -- warning! + */ + +#define CFE_CACHE_FLUSH_D 1 +#define CFE_CACHE_INVAL_I 2 +#define CFE_CACHE_INVAL_D 4 +#define CFE_CACHE_INVAL_L2 8 +#define CFE_CACHE_FLUSH_L2 16 +#define CFE_CACHE_INVAL_RANGE 32 +#define CFE_CACHE_FLUSH_RANGE 64 + +#define BCMCORE_NTLBENTRIES 32 + + + +#define SENDCHAR(c) \ + li t0,0xBF800000 ; \ + li t1,c ; \ + sb t1,0(t0) + + +#define R_CPU_CP0INIT _TBLIDX(0) +#define R_CPU_L1CINIT _TBLIDX(1) +#define R_CPU_SETLEDS _TBLIDX(2) +#define R_CPU_L1CFLASHD _TBLIDX(3) +#define R_CPU_L1CINVALI _TBLIDX(4) + +#define SETLEDS1(a,b,c,d) \ + li a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ; \ + CALLINIT_KSEG1(cpuinit_table,R_CPU_SETLEDS) +#define SETLEDS(a,b,c,d) \ + li a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ; \ + CALLINIT_KSEG0(cpuinit_table,R_CPU_SETLEDS) + +cpuinit_table: + _LONG_ bcmcore_cp0_init # [ 0 ] R_CPU_CP0INIT + _LONG_ bcmcore_l1cache_init # [ 1 ] R_CPU_L1CINIT + _LONG_ board_setleds # [ 2 ] R_CPU_SETLEDS + _LONG_ bcmcore_l1cache_flush_d # [ 3 ] R_CPU_L1CFLASHD + _LONG_ bcmcore_l1cache_inval_i # [ 4 ] R_CPU_L1CINVALI + + +/* ********************************************************************* + * BCMCORE_CP0_INIT() + * + * Initialize an BCMCORE CPU's CP0 registers + * + * Input parameters: + * nothing + * + * Return value: + * nothing + * + * Registers used: + * all + ********************************************************************* */ + + +LEAF(bcmcore_cp0_init) + + .set noreorder + + mtc0 zero,C0_WATCHLO # Watch registers. + mtc0 zero,C0_WATCHHI + mtc0 zero,C0_CAUSE # must clear before writing SR + + mfc0 v0,C0_SR # Get status register + and v0,M_SR_SR # preserve soft reset +#ifdef DEBUG_ENV_ICE + and v0,~M_SR_BEV +#else + or v0,M_SR_BEV # exceptions to boot vector +#endif + mtc0 v0,C0_SR # set up the status register + + + mfc0 v0,C0_CONFIG # get current CONFIG register + srl v0,v0,3 # strip out K0 bits + sll v0,v0,3 # k0 bits now zero + or v0,v0,K_CFG_K0COH_CACHEABLE # K0 is cacheable. + mtc0 v0,C0_CONFIG + nop + + mtc0 zero,C0_WATCHLO # Watch registers. + mtc0 zero,C0_WATCHHI + + mtc0 zero,C0_TLBHI # TLB entry (high half) + nop + + + # + # This is probably not the right init value for C0_COMPARE, + # but it seems to be necessary for the sim model right now. + # + + li v0,-1 + mtc0 v0,C0_COMPARE + nop + + # + # Initialize all the TLB entries to some invalid value + # + + mtc0 zero,C0_TLBLO0 /* tlblo0 = invalid */ + nop + mtc0 zero,C0_TLBLO1 /* tlblo1 = invalid */ + nop + mtc0 zero,C0_PGMASK /* 4K pages */ + nop + + li t0,K1BASE /* tlbhi = impossible vpn */ + li t1,(BCMCORE_NTLBENTRIES-1) /* index */ + + + nop +1: mtc0 t0,C0_TLBHI + nop + mtc0 t1,C0_INX + nop + addu t0,0x2000 /* inc vpn */ + tlbwi + bnez t1,1b + subu t1,1 # BDSLOT + .set reorder + + +/* + * XXX What other CP0 initialization do I need? + */ + + jr ra + + +END(bcmcore_cp0_init) + + +/* ********************************************************************* + * BCMCORE_CPUINIT + * + * Do initialization of the Broadcom core + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + + +LEAF(bcmcore_cpuinit) + + move fp,ra + + SETLEDS1('C','P','U','I') + CALLINIT_KSEG1(cpuinit_table,R_CPU_CP0INIT) + + SETLEDS1('L','1','C','I') + CALLINIT_KSEG1(cpuinit_table,R_CPU_L1CINIT) + + move ra,fp + j ra + +END(bcmcore_cpuinit) + + +/* ********************************************************************* + * BCMCORE_KSEG0_SWITCH + * + * Return to the address of the routine that called us, except + * in K0seg instead of K1seg + * + * Input parameters: + * nothing - ra is return address + * + * Return value: + * ra = same return address in K0 + ********************************************************************* */ + +LEAF(bcmcore_kseg0_switch) + + and ra,(K0SIZE-1) + or ra,K0BASE + jr ra + +END(bcmcore_kseg0_switch) + +/* ********************************************************************* + * BCMCORE_NULL + * + * Dummy handler for routines we don't need to implement, like + * the multiprocessor stuff + * + * Input parameters: + * nothing + * + * Return value: + * nothing + * + * Registers used: + * none + ********************************************************************* */ + +LEAF(bcmcore_null) + + j ra + +END(bcmcore_null) + + +/* ********************************************************************* + * BCMCORE_CPURESTART + * + * This routine is called when someone soft-exits to CFE. We + * reinitialize any CP0 stuff here. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(bcmcore_cpurestart) + + j ra + +END(bcmcore_cpurestart) + + +/* ********************************************************************* + * BCMCORE_CACHEOPS + * + * Perform various cache operations on a BCM Core + * + * Input parameters: + * a0 - flag bits (CFE_CACHE_xxx) + * + * Return value: + * nothing + * + * Registers used: + * t0,t1,t2,t3,v1,s0 + ********************************************************************* */ + +LEAF(bcmcore_cacheops) + + move s0,ra + + move v1,a0 + + /* + * With no flags, we flush L1D and invalid L1I + */ + + bne v1,zero,1f + li v1,CFE_CACHE_FLUSH_D | CFE_CACHE_INVAL_I +1: + + /* + * Flush the D-Cache, since the program we loaded is "data". + */ + + and a0,v1,CFE_CACHE_FLUSH_D + beq a0,zero,1f + CALLINIT_KSEG1(cpuinit_table,R_CPU_L1CFLASHD) +1: + + /* + * Invalidate the I-Cache, so that addresses in the program + * region will miss and need to be filled from the data we + * just flushed above. + */ + + and a0,v1,CFE_CACHE_INVAL_I + beq a0,zero,1f + CALLINIT_KSEG1(cpuinit_table,R_CPU_L1CINVALI) +1: + + + .set push + .set mips32 + + /* + * Invalidate cache range + */ + + and a0,v1,CFE_CACHE_INVAL_RANGE + beq a0,zero,2f + + move t0,a1 +1: cache CACHEOP(L1C_D,CACHE_OP_HITINVAL),0(t0) + add t0,LINESIZE + blt t0,a2,1b + + /* + * Flush cache range + */ + + +2: + and a0,v1,CFE_CACHE_FLUSH_RANGE + beq a0,zero,2f + + move t0,a1 +1: cache CACHEOP(L1C_D,CACHE_OP_HITWRITEBACK_INVAL),0(t0) + add t0,LINESIZE + blt t0,a2,1b + +2: + + .set pop + + + move ra,s0 + j ra + +END(bcmcore_cacheops) + + + +/* ********************************************************************* + * BCMCORE_TLBHANDLER + * + * This is the TLB exception handler for the bcmcore + * + * Note: only K0 and K1 are available to us at this time. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + + +LEAF(bcmcore_tlbhandler) + .set noreorder + .set noat + +/* + * XXX XXX XXX XXX XXX + * + * This won't work as-is on the BCMCORE. The CONTEXT register is not + * wide enough! In fact, it's broken on all pre-mips4 CPUs. + * + * XXX XXX XXX XXX XXX + */ + +/* + * This requires a bit of explanation: We only support 256KB + * of mapped space for the boot program. This space will be + * mapped from 0x2000_0000 to 0x2004_0000 to some physical + * memory allocated by the firmware. This is 64 pages + * of 4KB each. + * + * We know our BadVPN2 will be in the range + * 0x100000 to 0x1001F0, since the memory is mapped from + * 0x2000_0000 to 0x2004_0000. BadVPN2 plus the four bits + * of zeroes at the end are bits 31..9 + * + * We also want to place the PTEbase on something other than + * a 16MB boundary. Each entry is 16 bytes, and there + * are 64 entries, so we need only 10 bits to address + * the entire table (it can therefore be aligned on a + * 1KB boundary). + * + * To make this work, we'll shift PTEbase to the right, leaving + * the bottom ten bits for the page number, as: + * + * Bits 31..10: PTEbase + * Bits 9..4: BadVPN + * Bits 3..0: 16 bytes for table entry + * + * Therefore: + * PTEbase gets shifted right 13 bits. + * BadVPN gets masked at 6 bits (mask is 0x3F0) + * The bottom 4 bits are zero. + * + * To range check the address, we can shift the Bad VPN + * right by 9 bits, and check for values of 0x1000 and + * 0x1001. + */ + + + /* + * This part range checks the VPN2 field in the + * context register. We only handle + * VPN2s in the range 0x100000 to 0x1001F0 + */ + mfc0 k0,C0_TLBHI + + mfc0 k0,C0_CTEXT # Get context + sra k0,8 # keep hi part + and k0,0x1FFF # of VPN2 + li k1,0x1000 # 0x1000 is ok + beq k0,k1,1f # + nop # BDSLOT + li k1,0x1001 # 0x1001 is ok + beq k0,k1,1f # + nop # BDSLOT + + li k0,XTYPE_TLBFILL # all other bits are not + b _exc_entry + nop # BDSLOT + +1: mfc0 k0,C0_CTEXT # Get context + sra k0,13 # Shift PTEbase + li k1,0x3FF # Generate mask to kill + not k1 # BadVPN2 bits + and k0,k1 # keep only PTEBase part. + + mfc0 k1,C0_CTEXT # Get Context + and k1,0x3F0 # Keep only BadVPN2 bits + or k1,k0 # Replace PTEBase + + ld k0,0(k1) # Load entrylo0 + ld k1,8(k1) # Load entrylo1 + mtc0 k0,C0_TLBLO0 # and write to CP0 + mtc0 k1,C0_TLBLO1 + tlbwr # put it in the TLB + ERET + nop + + .set reorder + .set at + +END(bcmcore_tlbhandler) + + +/* ********************************************************************* + * End + ********************************************************************* */ + diff --git a/cfe/cfe/arch/mips/cpu/bcmcore/src/bcmcore_l1cache.S b/cfe/cfe/arch/mips/cpu/bcmcore/src/bcmcore_l1cache.S new file mode 100755 index 0000000..fa39bfd --- /dev/null +++ b/cfe/cfe/arch/mips/cpu/bcmcore/src/bcmcore_l1cache.S @@ -0,0 +1,219 @@ +/* ********************************************************************* + * SB1250 Board Support Package + * + * L1C initialization File: bcmcore_l1cache.S + * + * This module contains code to initialize the CPU's caches + * + * Note: all the routines in this module rely on registers only, + * since DRAM may not be active yet. + * + * 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 "sbmips.h" +#include "bsp_config.h" + + .text + + .set push + .set mips32 + +/* ********************************************************************* + * Macros + ********************************************************************* */ + +#define CP0_CFG_ISMSK (0x7 << 22) +#define CP0_CFG_ISSHF 22 +#define CP0_CFG_ILMSK (0x7 << 19) +#define CP0_CFG_ILSHF 19 +#define CP0_CFG_IAMSK (0x7 << 16) +#define CP0_CFG_IASHF 16 +#define CP0_CFG_DSMSK (0x7 << 13) +#define CP0_CFG_DSSHF 13 +#define CP0_CFG_DLMSK (0x7 << 10) +#define CP0_CFG_DLSHF 10 +#define CP0_CFG_DAMSK (0x7 << 7) +#define CP0_CFG_DASHF 7 + +#define cacheop(kva, size, linesize, op) \ + .set noreorder; \ + addu t1, kva, size; \ + subu t2, linesize, 1; \ + not t2; \ + and t0, kva, t2; \ + addu t1, -1; \ + and t1, t2; \ +10: cache op, 0(t0); \ + bne t0, t1, 10b; \ + addu t0, linesize; \ +11: \ + .set reorder + +#define size_icache(size, linesize) \ + mfc0 t7, C0_CONFIG, 1; \ + and t0, t7, CP0_CFG_ILMSK; \ + srl t0, t0, CP0_CFG_ILSHF; \ + move linesize, zero; \ + beq t0, zero,1f; \ + add t0, 1; \ + li linesize, 1; \ + sll linesize, t0; \ +1: and t0, t7, CP0_CFG_ISMSK; \ + srl t0, t0, CP0_CFG_ISSHF; \ + li size, 64; \ + sll size, t0; \ + and t0, t7, CP0_CFG_IAMSK; \ + srl t0, t0, CP0_CFG_IASHF; \ + add t0, 1; \ + mult size, t0; \ + mflo size; \ + mult size, linesize; \ + mflo size + +#define size_dcache(size, linesize) \ + mfc0 t7, C0_CONFIG, 1; \ + and t0, t7, CP0_CFG_DLMSK; \ + srl t0, t0, CP0_CFG_DLSHF; \ + move linesize, zero; \ + beq t0, zero,1f; \ + add t0, 1; \ + li linesize, 1; \ + sll linesize, t0; \ +1: and t0, t7, CP0_CFG_DSMSK; \ + srl t0, t0, CP0_CFG_DSSHF; \ + li size, 64; \ + sll size, t0; \ + and t0, t7, CP0_CFG_DAMSK; \ + srl t0, t0, CP0_CFG_DASHF; \ + add t0, 1; \ + mult size, t0; \ + mflo size; \ + mult size, linesize; \ + mflo size + + +/* ********************************************************************* + * BCMCORE_L1CACHE_INIT() + * + * Initialize the L1 Cache + * + * Input parameters: + * nothing + * + * Return value: + * nothing + * + * Registers used: + * t0,t1,t2 + ********************************************************************* */ + +LEAF(bcmcore_l1cache_init) + + mtc0 zero, C0_TAGLO # Initialize TAGLO register + mtc0 zero, C0_TAGLO,1 # Initialize DataLo register + + li a0, K0BASE # Initialise primary instruction cache. + size_icache(a1, a2) + cacheop(a0, a1, a2, Index_Store_Tag_I) + + li a0, K0BASE # Initialise primary data cache. + size_dcache(a1, a2) + cacheop(a0, a1, a2, Index_Store_Tag_D) + + jr ra + +END(bcmcore_l1cache_init) + +/* ********************************************************************* + * BCMCORE_L1CACHE_INVAL_I() + * + * Invalidate the entire ICache + * + * Input parameters: + * nothing + * + * Return value: + * nothing + * + * Registers used: + * t0,t1,t2 + ********************************************************************* */ +LEAF(bcmcore_l1cache_inval_i) + + li a0, K0BASE + size_icache(a1, a2) + cacheop(a0, a1, a2, Index_Invalidate_I) + + j ra + +END(bcmcore_l1cache_inval_i) + +/* ********************************************************************* + * BCMCORE_L1CACHE_FLUSH_D() + * + * Flush the entire DCache + * + * Input parameters: + * nothing + * + * Return value: + * nothing + * + * Registers used: + * t0,t1,t2 + ********************************************************************* */ +LEAF(bcmcore_l1cache_flush_d) + + li a0, K0BASE + size_dcache(a1, a2) + +# before flushing cache clear tags pointing to flash memory to avoid writes into flash + addu t1, a0, a1 + subu t2, a2, 1 + not t2 + and t0, a0, t2 + addu t1, -1 + and t1, t2 +1: + cache Index_Load_Tag_D, 0(t0) + nop + nop + nop + nop + nop + nop + mfc0 t2, C0_TAGLO # Read TAGLO register + and t2, 0x1f000000 # check address + li t3, 0x1f000000 + bne t2, t3, 2f + mtc0 zero, C0_TAGLO + cache Index_Store_Tag_D, 0(t0) # Reset tag for flash memory locations +2: + .set noreorder; + bne t0, t1, 1b + addu t0, a2 + .set reorder + + cacheop(a0, a1, a2, Index_Writeback_Inv_D) + + j ra + +END(bcmcore_l1cache_flush_d) + + .set pop + +/* ********************************************************************* + * End + ********************************************************************* */ + |