/* ********************************************************************* * 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 "ui_command.h" #include "cfe_mem.h" #include "cfe.h" #include "exception.h" #include "bsp_config.h" #include "segtable.h" #include "initdata.h" #if CFG_PCI #include "pcivar.h" #endif /* ********************************************************************* * 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); extern void cfe_device_poll(void *x); extern int ui_init_envcmds(void); extern int ui_init_devcmds(void); extern int ui_init_netcmds(void); extern int ui_init_memcmds(void); extern int ui_init_loadcmds(void); extern int ui_init_pcicmds(void); extern int ui_init_examcmds(void); extern int ui_init_flashcmds(void); extern int ui_init_misccmds(void); #if CFG_VAPI extern int ui_init_vapicmds(void); #endif #if CFG_VENDOR_EXTENSIONS extern int ui_init_vendorcmds(void); #endif void cfe_command_restart(uint64_t status); extern segtable_t *_getsegtbl(void); extern const char *builddate; extern const char *builduser; #if CFG_MULTI_CPUS extern int altcpu_cmd_start(uint64_t,uint64_t *); extern int altcpu_cmd_stop(uint64_t); #endif /* ********************************************************************* * Globals ********************************************************************* */ const char *cfe_boardname = CFG_BOARDNAME; unsigned int cfe_startflags = #if CFG_PCI CFE_INIT_PCI | #endif 0; /* ********************************************************************* * 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); } xsprintf(buffer,"%d",mem_totalsize); env_setenv("CFE_MEMORYSIZE",buffer,ENV_FLG_BUILTIN | ENV_FLG_READONLY); } /* ********************************************************************* * cfe_init_ui() * * Call all the other UI initialization modules. Each of these * modules usually calls back to the UI dispatcher to add command * tables. * * Input parameters: * nothing * * Return value: * nothing ********************************************************************* */ #if CFG_MINIMAL_SIZE #define OPTIONAL(x) #else #define OPTIONAL(x) x #endif static void cfe_init_ui(void) { ui_init_cmddisp(); ui_init_envcmds(); OPTIONAL(ui_init_devcmds()); #if CFG_NETWORK ui_init_netcmds(); #endif ui_init_loadcmds(); OPTIONAL(ui_init_memcmds()); #if CFG_PCI ui_init_pcicmds(); #endif OPTIONAL(ui_init_examcmds()); ui_init_flashcmds(); #if CFG_VAPI ui_init_vapicmds(); #endif #if CFG_VENDOR_EXTENSIONS ui_init_vendorcmds(); #endif OPTIONAL(ui_init_misccmds()); } /* ********************************************************************* * 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) { 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); } /* ********************************************************************* * cfe_say_hello() * * Print out the CFE startup message and copyright notice * * Input parameters: * nothing * * Return value: * nothing ********************************************************************* */ static void cfe_say_hello(void) { xprintf("\n\n"); xprintf("CFE version 2.0.2" #ifdef CFE_VER_RELEASE ".%d" #endif " for DGN2200v2 (%s)\n", //CFE_VER_MAJOR,CFE_VER_MINOR,CFE_VER_BUILD, #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,2001,2002,2003 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) { SETLEDS("RUN!"); cfe_launch(ept); } /* ********************************************************************* * cfe_startup_info() * * Display startup memory configuration messages * * Input parameters: * nothing * * Return value: * nothing ********************************************************************* */ static void cfe_startup_info(void) { segtable_t *segtbl; segtbl = _getsegtbl(); xprintf("CPU type 0x%X: ",(uint32_t)cpu_prid); if (cfe_cpu_speed < 1000000) xprintf("%dKHz\n",cfe_cpu_speed/1000); else xprintf("%dMHz\n",cfe_cpu_speed/1000000); xprintf("Total memory: 0x%llX bytes (%dMB)\n", (((uint64_t)mem_totalsize) << 20),(uint32_t)mem_totalsize); xprintf("\n"); xprintf("Total memory used by CFE: 0x%08X - 0x%08X (%d)\n", (uint32_t) mem_bottomofmem, (uint32_t) mem_topofmem, (uint32_t) mem_topofmem-mem_bottomofmem); xprintf("Initialized Data: 0x%08X - 0x%08X (%d)\n", (uint32_t) (segtbl[R_SEG_FDATA] + mem_datareloc), (uint32_t) (segtbl[R_SEG_EDATA] + mem_datareloc), (uint32_t) (segtbl[R_SEG_EDATA] - segtbl[R_SEG_FDATA])); xprintf("BSS Area: 0x%08X - 0x%08X (%d)\n", (uint32_t) (segtbl[R_SEG_FBSS] + mem_datareloc), (uint32_t) (segtbl[R_SEG_END] + mem_datareloc), (uint32_t) (segtbl[R_SEG_END] - segtbl[R_SEG_FBSS])); xprintf("Local Heap: 0x%08X - 0x%08X (%d)\n", (uint32_t)(mem_heapstart), (uint32_t)(mem_heapstart + (CFG_HEAP_SIZE*1024)), (CFG_HEAP_SIZE*1024)); xprintf("Stack Area: 0x%08X - 0x%08X (%d)\n", (uint32_t)(mem_heapstart + (CFG_HEAP_SIZE*1024)), (uint32_t)(mem_heapstart + (CFG_HEAP_SIZE*1024) + STACK_SIZE), STACK_SIZE); xprintf("Text (code) segment: 0x%08X - 0x%08X (%d)\n", (uint32_t)mem_textbase, (uint32_t)(mem_textbase+mem_textsize), (uint32_t) mem_textsize); xprintf("Boot area (physical): 0x%08X - 0x%08X\n", mem_bootarea_start,mem_bootarea_start+mem_bootarea_size); xprintf("Relocation Factor: I:%08X - D:%08X\n", (uint32_t) mem_textreloc,(uint32_t) mem_datareloc); } /* ********************************************************************* * cfe_autostart() * * Process automatic commands at startup * * Input parameters: * nothing * * Return value: * nothing ********************************************************************* */ static void cfe_autostart(void) { char *env; int noauto = 0; char ch; env = env_getenv("STARTUP"); if (!env) return; while (console_status()) { console_read(&ch,1); if (ch == 3) noauto = TRUE; /* Ctrl-C means no auto */ } if (noauto) { xprintf("Automatic startup canceled via Ctrl-C\n"); return; } ui_docommands(env); } /* ********************************************************************* * 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(); cfe_timer_init(); /* Timer process */ cfe_bg_add(cfe_device_poll,NULL); /* * Initialize the memory allocator */ SETLEDS("KMEM"); KMEMINIT((unsigned char *) (uintptr_t) mem_heapstart, ((CFG_HEAP_SIZE)*1024)); /* * Initialize the console. It is done before the other devices * get turned on. The console init also sets the variable that * contains the CPU speed. */ SETLEDS("CONS"); board_console_init(); /* * Set up the exception vectors */ cfe_setup_exceptions(); /* * Say hello. */ SETLEDS("CIOK"); cfe_say_hello(); /* * Initialize the other devices. */ SETLEDS("AREN"); xprintf("Initializing Arena.\n"); cfe_arena_init(); #if CFG_PCI if (cfe_startflags & CFE_INIT_PCI) { pci_flags_t flags = PCI_FLG_NORMAL | PCI_FLG_LDT_PREFETCH; char *str; extern cons_t pci_optnames[]; flags = PCI_FLG_NORMAL | PCI_FLG_LDT_PREFETCH; #if CFG_LDT_REV_017 flags |= PCI_FLG_LDT_REV_017; #endif str = env_getenv("PCI_OPTIONS"); setoptions(pci_optnames,str,&flags); xprintf("Initializing PCI. [%s]\n",str ? str : "normal"); pci_configure(flags); } #endif SETLEDS("DEVI"); xprintf("Initializing Devices.\n"); board_device_init(); cfe_startup_info(); SETLEDS("ENVI"); cfe_setup_default_env(); xprintf("\n"); cfe_init_ui(); board_final_init(); cfe_autostart(); cfe_command_loop(); } /* ********************************************************************* * cfe_command_restart() * * This routine is called when an application wants to restart * the firmware's command processor. Reopen the console and * jump back into the command loop. * * Input parameters: * status - A0 value of program returning to firmware * * Return value: * does not return ********************************************************************* */ void cfe_command_restart(uint64_t status) { /* * Stop alternate CPU(s). If they're already stopped, this * command will make sure they're stopped. */ #if CFG_MULTI_CPUS altcpu_cmd_stop(1); /* stop CPU 1 (XXX more CPUs?) */ #endif /* * Call board reset functions */ board_device_reset(); /* * Reset devices */ cfe_device_reset(); /* * Reset timers */ cfe_timer_init(); /* * Reopen console */ console_open(console_name); /* * Display program return status */ xprintf("*** program exit status = %d\n", (int)status); /* * Back to processing user commands */ 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; SETLEDS("CFE "); for (;;) { prompt = env_getenv("PROMPT"); #if CFG_RAMAPP SETLEDS("CFE*"); if (!prompt) prompt = "CFE_RAM> "; #else if (!prompt) prompt = "CFE> "; #endif console_readline(prompt,buffer,sizeof(buffer)); status = ui_docommands(buffer); if (status != CMD_ERR_BLANK) { xprintf("*** command status = %d\n", status); } } }