/* Copyright Motorola, Inc. 1993, 1994 ALL RIGHTS RESERVED You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE so long as this entire notice is retained without alteration in any modified and/or redistributed versions, and that such modified versions are clearly identified as such. No licenses are granted by implication, estoppel or otherwise under any patents or trademarks of Motorola, Inc. The SOFTWARE is provided on an "AS IS" basis and without warranty. To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. To the maximum extent permitted by applicable law, IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE. Motorola assumes no responsibility for the maintenance and support of the SOFTWARE. */ #include "dink.h" #include #include "errors.h" #include "toks.h" #include "arg_tb.h" #include "reg_tb.h" #include "duart.h" #include "par_tb.h" #include "asm_dsm.h" #include "drivers/i2o/i2o.h" #include "atu.h" #include "drivers/epic/epic.h" #define PCI_REG_BASE 0x80000000 #define PCI_MEM_ADR 0x80000000 #define PCI_LMBAR_REG 0x10 STATUS keyboard_open(); STATUS keyboard_read(); STATUS keyboard_close(); char last_cmd[256]; #ifdef ON_BOARD extern void config_kahlua_agent( ); #pragma Alias( config_kahlua_agent, "config_kahlua_agent" ) extern void clear_kahlua_rty( ); extern unsigned int test_kahlua_rty( ); extern unsigned int get_kahlua_pcsrbar( ); extern unsigned int get_eumbbar( ); extern unsigned long target_mode, target_addr, target_type; extern unsigned int load_runtime_reg( unsigned int eumbbar, unsigned int reg ); extern int pciKahluaProbe ( unsigned short dev_id, unsigned short vendor_id, unsigned long *dev_addr); extern STATUS CommLookChar(); extern int CommGetChar(char *jPort); extern STATUS CommPutChar(); extern void winbond_initialize(); extern void ns308defaults(); extern STATUS tok_open_input_buffer(); extern STATUS tok_close_input_buffer(); extern STATUS err_print_error(); extern STATUS tok_recognize_char(); extern int GetTAUTemp(); extern convert_char_to_string(int n, unsigned char *s); extern STATUS err_initialize_toolbox(); extern unsigned long read_PVR_from_processor(); extern int l2cr_read(); extern int pvr_read(); extern int ENVLoad(); extern int InitWithEnv(); extern STATUS breakpoint_initialize(); extern STATUS general_register_init(); extern STATUS fp_register_init(); extern STATUS special_purpose_init(); extern STATUS v_register_init(); extern STATUS init_ops_and_mnemonics(); extern STATUS compression_initialize(); extern STATUS par_about(); extern STATUS WriteCharToMemory(); extern STATUS dink_identify(); extern STATUS read_from_memory(); extern UCHAR DoInput(); extern int DoOutput(); extern void simple_leap(); extern long strtol(); extern void sysEUMBBARWrite ( unsigned long regNum, unsigned long regVal); extern unsigned long sysEUMBBARRead( unsigned long regNum); extern STATUS pciRegSet(unsigned long pciAddr, unsigned long Reg, unsigned long Value); #endif extern STATUS par_head_parser(); extern long config_addr; extern long config_data; extern long board_type; extern long dink_type; void delay(int); void excimer_bist(); char prompt_main[60]; INTEGER benchmark_in_progress = FALSE; /* This global is used to determine whether we are in the process of running the benchmark command */ INTEGER timebase_register_u = 0; /* These globals are used to return the value of the timebase register when we are running the benchmark command */ INTEGER timebase_register_l = 0; INTEGER timebase_base_run_l = 0; /* This global is used to hold the value of the timebase register on the 1st pass through the user code. The upper value will be 0 because we initialize the timebase on each pass and it will not have had time to increment that far!! */ INTEGER benchmark_addr = 0x100; /* This global is used to store the address of the beginning of the benchmark. It will be used to replace the real opcode when we begin the second pass. */ INTEGER benchmark_pass = 0; /* Global that determines which part of bench_mark() routine should be run 0 - Benchmark command just issued 1 - Returning from 1st pass 2 - Returning from 2nd pass */ INTEGER benchmark_loop = 0; /* Global that determines which pass of bench_mark() routine should be run 0 - Init value 1 - No caches 2 - Icache 3 - Dcache 4 - Icache,Dcache*/ /* These are the globals that we store the current values in during exception handling */ INTEGER current_msr = 0; INTEGER current_hid0 = 0; INTEGER current_srr0 = 0; INTEGER current_lr = 0; INTEGER current_cr = 0; INTEGER current_r3 = 0; INTEGER current_r4 = 0; INTEGER current_r5 = 0; INTEGER Push_reset_button=0; #ifdef ON_BOARD unsigned long IO_Index; unsigned long IO_Data; unsigned long KEYBOARD; unsigned long HOST; unsigned long UART_SPAN; #endif unsigned long IO_Base; unsigned long GlobalPVR; long exit_dink; char memdisp_opt = 0x00; // MD/MM global options. char regdisp_opt = 0x00; // RD/RM global options char process_type = MAX_PROCESS_TYPE; char address_map[2]; char alias_tmp[40]; char alias_map[40]; /* For a host, pmcIntLine is a global to hold the IRQ line (0-3) of an agent depending on what PMC slot the agent is in. This value is use by the host EPIC unit to set up the correct interrupt vector. pmcIntLine = 0xff - no agent detected pmcIntLine = 0 - agent at IRQ0 pmcIntLine = 1 - agent at IRQ1 pmcIntLine = 2 - agent at IRQ2 pmcIntLine = 3 - agent at IRQ3 For an agent, pmcIntLine is a flag that will be set to AGENT_DETECTED = 23 to let EPIC unit know to set up the Message Unit interrupt vector 23 */ int pmcIntLine = 0xff; #define AGENT_DETECTED 23 //--------------------------------------------------------------------------- // History -- commands are kept in a simple stack. The top of the stack // is volatile and contains the current command, good or bad, // so it is not really part of the history. This weird // restriction is due to me being prevented from grinding the // parser toolbox into bits and scattering it to the four winds. // // history[0] = current command // history[1] = last good command // ... #ifdef HISTORY_SUPPORT #define HISTORY_SIZE 10 #define HISTORY_WIDTH OVERRUN+2 // Restricted to this by parser. typedef struct hist_info { short index; char cmd[ HISTORY_WIDTH ]; } HISTINFO; int history_no; HISTINFO history[ HISTORY_SIZE ]; #endif int (*start)(); //------------------------------------------------------------------------- // MCAPS is a small 'database' of the capabilities of each board type. // Due to the (increasing) number of boards, it is now longer as // simple as detecing and MPC107 and assuming capabilities are a // given. //------------------------------------------------------------------------- MCAPS caps[] = { { YK_X2, "Yellowknife/X2", 1, 1, 1, 1, 0, M_SUPERIO, 1, M_ENVNVRAM }, { YK_X4, "Yellowknife/X4", 1, 1, 1, 1, 0, M_SUPERIO, 1, M_ENVNVRAM }, { EXCIMER, "Excimer", 0, 0, 0, 0, 0, M_DUART, 0, M_ENVSRAM }, { PMC8240, "PMC8240 Eval", 1, 0, 0, 0, 0, M_PMCUART, 0, M_ENVSRAM }, { SP_8240, "Sandpoint/MPC8240", 1, 1, 1, 1, 1, M_SUPERIO, 1, M_ENVNVRAM }, { SP_107, "Sandpoint/MPC107", 1, 1, 1, 1, 1, M_SUPERIO, 1, M_ENVNVRAM }, { UNIX, "Unix emulation", 0, 0, 0, 0, 0, M_UNIXIO, 0, M_ENVNONE } }; MCAPS *mach_info = &caps[0]; /* The baseline default is YK X2 */ //--------------------------------------------------------------------------- // SetProcessType -- using the PVR, select a "generic" type of // processor. //--------------------------------------------------------------------------- void SetProcessType() { // Get PVR. #ifdef ON_BOARD GlobalPVR = read_PVR_from_processor(); #else GlobalPVR = 0x04; #endif if (GlobalPVR == 0x01) // 601 process_type = PPC601; else if (GlobalPVR == 0x03 // 603 || GlobalPVR == 0x06 // 603e || GlobalPVR == 0x07 // 603ev || GlobalPVR == 0x81 // 8240 || GlobalPVR == 0x91) // 8245 process_type = PPC603; else if (GlobalPVR == 0x08) { // 750 process_type = PPCART; if ((pvr_read() & 0x3000) == 0x3000) // 755 process_type = PPC755; } else if (GlobalPVR == 0x04 // 604 || GlobalPVR == 0x09 // 604e || GlobalPVR == 0x0A) // 604e process_type = PPC604; else if (GlobalPVR == 0x0C // 7400 || GlobalPVR == 0x800C) // 7410 process_type = PPCMAX; else process_type = PPC603; } //--------------------------------------------------------------------------- // MapCPUName -- convert PVR into readable description of processor. //--------------------------------------------------------------------------- void MapCPUName( char *dest, short UseNickName ) { char *name; switch (GlobalPVR) { case 0x1: // ?-MPC601 name = "MPC601"; break; case 0x3: // Wart-MPC603 name = "MPC603"; break; case 0x4: // ?-MPC604 name = "MPC604"; break; case 0x6: // Stretch-MPC603e name = "MPC603e"; break; case 0x7: // Valiant, Goldeneye - MPC603ev name = "MPC603ev"; break; case 0x8: // Arthur, Conan, Doyle - 750 if ((pvr_read() & 0x3000) == 0x3000) // Goldfinger - 755 name = (UseNickName) ? "GOLDFINGER" : "MPC755"; else name = (UseNickName) ? "ARTHUR" : "MPC750"; break; case 0x9: // Sirocco-MPC604e case 0xA: name = "MPC604e"; break; case 0x81: // Kahlua-MPC8240 case 0x91: name = (UseNickName) ? "KAHLUA" : "MPC8240"; break; case 0xC: // Max-MPC7400 name = (UseNickName) ? "MAX" : "MPC7400"; break; case 0x800C: // Nitro-MPC7410 name = (UseNickName) ? "Nitro" : "MPC7410"; break; default: name = "UNKNOWN"; } strcpy( dest, name ); } #define DEFAULT_PROMPT "$d_$p >>" //--------------------------------------------------------------------------- // set_prompt -- set the prompt using the environment variable "PROMPT". // If none, use the default. // // $d => DINK identifier // $H => host/agent identifier // $p => informal processor ID // $P => formal processor ID // $T => current time // $t => TAU temperature. // $! => history index // $_ => crlf //--------------------------------------------------------------------------- void set_prompt( char *template, char *new_prompt ) { extern int TAU_Cal_Value; extern char *HexChars; char *s, *d; char tmp[80]; int temp; #ifdef RTC_SUPPORT unsigned char time[7]; extern void GetRTC( unsigned char time[] ); extern void convert_unsigned_char(); #endif // Use supplied template, or the $PROMPT variable if none, or lastly use // the default. s = template; if (template == NULL || *template == 0) { #ifdef ENV_SUPPORT extern char *GetEnv( char *name, char *tmp ); if ((s = GetEnv( "PROMPT", tmp )) == NULL) #endif s = DEFAULT_PROMPT; } // Using the template, insert the requested data. d = new_prompt; while (*s) { if (*s == '$') { switch (*++s) { case 'd': // $d -- DINK identifier if (dink_type == 1) // If MDINK, prompt accordingly *d++ = 'M'; strcpy( d, "DINK32" ); d += 6; break; case 'P': // $P -- formal processor ID MapCPUName( d, 0 ); d += strlen( d ); break; case 'H': if (target_mode == 0) { // $H -- host/agent identifier strcpy( d, "HOST" ); d += 4; } else { strcpy( d, "AGENT" ); d += 5; } break; case 'p': // $p -- informal processor ID MapCPUName( d, 1 ); d += strlen( d ); break; #ifdef RTC_SUPPORT case 'T': // $T -- current time GetRTC( time ); time[3] &= 0x7F; *d++ = HexChars[ (time[3] >> 4) & 0xF ]; *d++ = HexChars[ time[3] & 0xF ]; *d++ = ':'; *d++ = HexChars[ (time[4] >> 4) & 0xF ]; *d++ = HexChars[ time[4] & 0xF ]; *d++ = ':'; *d++ = HexChars[ (time[5] >> 4) & 0xF ]; *d++ = HexChars[ time[5] & 0xF ]; *d++ = (time[6]) ? 'P' : 'A'; *d++ = 'M'; *d = 0; break; #endif #ifdef TAU_SUPPORT case 't': // $t -- TAU temperature. temp = GetTAUTemp(); convert_char_to_string( temp , (unsigned char *) d ); d += strlen( d ); if (!TAU_Cal_Value) // Uncalibrated? *d++ = 'u'; break; #endif #ifdef HISTORY_SUPPORT case '!': // $! -- history index convert_char_to_string( history_no, (unsigned char *) d ); d += strlen( d ); break; #endif case '_': // $_ -- crlf *d++ = 0x0d; *d++ = 0x0a; break; default: // Unknown (or $$) *d++ = *s; break; } s++; } else // not %-something, just copy as-is *d++ = *s++; } *d = '\0'; } /************************************************************/ main_test() { char *terminal; int read_val = 0; /* SetStackPointer(); Initialize the stackpointer */ init_IO_values(); if((board_type == 0) || (board_type ==1)) { exit_dink = 0; winbond_initialize(); duart_initialize(); } else if(board_type == 2) {} else while(1){}; /* Stay here */ terminal = (char *)KEYBOARD; CommPutChar(terminal,'T'); PRINT("Reached point #1 !\n"); while(1) { read_val = CommGetChar(terminal); CommPutChar(terminal, (char) read_val); } } #ifdef HISTORY_SUPPORT //--------------------------------------------------------------------------- // help_hist //--------------------------------------------------------------------------- void help_hist() { PRINT( "HISTORY\n" "=======\n" "Mnemonic: history, hi\n" "Syntax: hi\n" "Description: This command lists all recent commands.\n" " Commands can be repeated with the syntax:\n" " !! -- repeat the last command\n" " !n -- repeat command #n\n", " !-n -- repeat the nth previous command\n" ); } //--------------------------------------------------------------------------- // main_history -- show command line history. //--------------------------------------------------------------------------- STATUS main_history() { int i; char *s; char tmp[ HISTORY_WIDTH ]; // This would be easy if the parser didn't insist on double-newlines. Feh. for (i = HISTORY_SIZE-1; i > 0; i--) if (history[i].index != 0) { // Any data? strcpy( tmp, history[i].cmd ); if ((s = strchr( tmp, '\n')) != NULL) *s = 0; PRINT("%5d %s\n", history[i].index, tmp); } return( SUCCESS ); } //--------------------------------------------------------------------------- // init_history -- initialize history information. //--------------------------------------------------------------------------- STATUS init_history() { int i; for (i = 0; i < HISTORY_SIZE; i++) history[i].index = 0; history_no = 1; return( SUCCESS ); } #endif //--------------------------------------------------------------------------- // dink_loop -- have the parser do all the work. Print errors if needed. // Loops forever. //--------------------------------------------------------------------------- int dink_loop() { STATUS status; while (1) { status = par_head_parser(); err_print_error( status ); #ifdef HISTORY_SUPPORT if (status == SUCCESS) { int i; history[0].index = history_no++; // Push items down on the history stack. for (i = HISTORY_SIZE-1; i > 0; i--) memcpy( &history[ i ], &history[ i-1 ], sizeof(HISTINFO) ); history[0].index = 0; } #endif #ifndef ON_BOARD if (exit_dink) break; #endif } return( SUCCESS ); } STATUS keyboard_open(fn,fp) char *fn; void **fp; { *fp = fn; return SUCCESS; } STATUS keyboard_read(start,fp,need,got) char *start; void *fp; int need; int *got; { char *in, *out; char ch; int jCnt, hi, i; in = start; jCnt = 0; need = *got; // Update and issue the prompt. set_prompt( fp, prompt_main ); PRINT( prompt_main ); ch = 0; while ((ch != '\n') && (jCnt < OVERRUN)) { ch = CommGetChar( (char *) KEYBOARD ); if ((ch == '\r' ) || (ch == '\n' )) { ch = '\n'; start[jCnt++] = ch; CommPutChar( (char *) KEYBOARD, '\r' ); CommPutChar( (char *) KEYBOARD, ch ); } else if (ch == '\b') { if (jCnt > 0) { jCnt--; CommPutChar( (char *) KEYBOARD, ch ); CommPutChar( (char *) KEYBOARD, ' ' ); CommPutChar( (char *) KEYBOARD, ch ); } } else { #ifdef FOO if(tok_recognize_char(ch)==SUCCESS) #endif start[jCnt++] = ch; CommPutChar( (char *) KEYBOARD, ch ); } } start[jCnt++] = ' '; start[jCnt++] = '\n'; start[jCnt] = '\0'; // Check for history commands. #ifdef HISTORY_SUPPORT if (start[0] == '!') { if (start[1] == '!' || start[1] == '\n') // Last command i = history_no-1; else if (start[1] == '-') // Nth last command i = history_no-strtol( &start[2], (char **) NULL, 10 ); else // Command N i = strtol( &start[1], (char **) NULL, 10 ); for (hi = 0; hi < HISTORY_SIZE; hi++) if (history[hi].index == i) break; if (hi < 1 || hi >= HISTORY_SIZE || history[hi].index == 0) { PRINT("ERROR : unknown event.\n"); start[0] = '\0'; } // Put the command in the buffer, and copy to the top of the // stack else strcpy( start, history[hi].cmd ); } #endif // Check for defined aliases. hi = 0; for (in = start, out = alias_tmp; *in; in++, out++) if (*in == ' ' || *in == '\t' || *in == '\n') { hi++; break; } else if ('a' <= (*in) && (*in) <= 'z') *out = (*in) - 0x20; else *out = *in; *out = 0; if (hi && *alias_tmp) { if (GetEnv( alias_tmp, alias_map)) { strcpy( start, alias_map ); strcat( start, " \n" ); } } // Preserve last command under '.' as well. if (*start == '.') strcpy(start,last_cmd); else strcpy(last_cmd,start); strncpy( (char *) &history[0].cmd, start, HISTORY_WIDTH ); history[0].index = history_no; // Return new command. *got = strlen(start); return SUCCESS; } STATUS keyboard_close() { return SUCCESS; } //--------------------------------------------------------------------------- // init_IO_values -- set up IO values based on board type and selected // IO drivers (could change dynamically). //--------------------------------------------------------------------------- init_IO_values() { #ifdef ON_BOARD unsigned long tmp_addr; // For the YK, SP and PPMC systems, setup pointers to SuperI/O and // initialize it. We may not necessarily use the SuperI/O for the // PPMC, but it is an option. if ((mach_info->IODrivers == M_SUPERIO) // YK, SP || (mach_info->IODrivers == M_PMCUART)) { // PPMC tmp_addr = config_addr; tmp_addr = tmp_addr >> 16; if (tmp_addr == CHRP_REG_ADDR) { IO_Index = (unsigned long) 0xFE00015C; IO_Data = (unsigned long) 0xFE00015D; IO_Base = (unsigned long) 0xFE000000; strcpy(address_map, "B"); // CHRP is map B } else { IO_Index = (unsigned long) 0x8000015C; IO_Data = (unsigned long) 0x8000015D; IO_Base = (unsigned long) 0x80000000; strcpy(address_map, "A"); // PREP is map A } ns308defaults(); // Initialize the SuperIO } // Setup pointer to COM1/COM2. If this is a target (Agent-mode PPMC in // a slot), switch from COM1 to COM2 to allow simultaneous operation. if (mach_info->IODrivers == M_SUPERIO) { // YK, SP if (target_mode == 0) { // Host mode KEYBOARD = IO_Base + COM1; HOST = IO_Base + COM2; } else { // Agent mode KEYBOARD = IO_Base + COM2; HOST = IO_Base + COM1; } } // DUART using the Excimer/Maximer address map. else if (mach_info->IODrivers == M_DUART) { IO_Base = 0x40400000; KEYBOARD = 0x40400000; // Channel 1 HOST = 0x40000000; // Channel 2 } // For PPMCUART (stand-alone PPMC's), we use the on-board UART. There // are two types: The PPMC8240 which has a UART on RCS1 in 64-bit mode // (all it can support), or the MPC107- or MPC8245-based PPMC cards, // which have 8-bit support on RCS3. To decide between the two, just // go by PVR: RCS1/64 for '8240, RCS3/8 for all others. else if (mach_info->IODrivers == M_PMCUART) { if (GlobalPVR == 0x81) { // 8240 KEYBOARD = 0xFFE00008; // Channel 1 HOST = 0xFFE00000; // Channel 2 } else { KEYBOARD = 0x78000000; // Channel 1 HOST = 0x78000000; // Channel 2 (same) } } #else IO_Base = (unsigned long) 0x0; #endif } //--------------------------------------------------------------------------- // dink_initialize -- initialize devices. //--------------------------------------------------------------------------- STATUS dink_initialize() { unsigned long v; short i; // PRINT("Found %ld meg \n",(int)find_memory()); mem_start = 0x00000000; mem_end = 0xFFFFFFFF; *alias_string = '\0'; *last_cmd = '\0'; // Determine whether we are DINK or MDINK. Do this early! dink_identify(); SetProcessType(); logging_enabled = 0; // Disable logging feature. init_IO_values(); // init. IO ports duart_initialize(); // initialize duart to have keyboard // Initialize the tokenizer, the dink tokens, and the error handler. dink_toks_initialize(); err_initialize_toolbox(); // If enabled, re-configure using environment variables (which are // stored in a persistent medium somewhere). #ifdef ENV_SUPPORT ENVLoad(); InitWithEnv(); #endif // Now that the ENV has possibly initialized the cache, indicate the // current status. i = 0; PRINT( "Caches Enabled: [ " ); #ifdef ICACHEON PRINT( "L1-ICache " ); i++; #endif #ifdef DCACHEON PRINT( "L1-DCache " ); i++; #endif #ifdef L2_BACKSIDE_ON if ((process_type == PPCART) || (process_type == PPC755) || (process_type == PPCMAX)) { v = l2cr_read(); if (v & 0x80000000) { PRINT( "L2-BacksideCache(" ); i++; switch (v & 0x30000000) { case 0x00000000: PRINT("2M)"); break; case 0x10000000: PRINT("256K)"); break; case 0x20000000: PRINT("512K)"); break; case 0x30000000: PRINT("1M)"); break; } } } #endif #ifdef L2CACHE PRINT( " MPC106 L2/L3Cache" ); i++; #endif if (!i) // Number of caches enabled. PRINT(" none "); PRINT( " ]\n" ); // Initialize the breakpoint toolbox. breakpoint_initialize(); //-------------------------------------------------------------------------- // Initialize the GPR/FPR/VPR/SPR register files. PRINT("Register Inits: [ "); general_register_init(); PRINT("32 GPRs"); fp_register_init(); PRINT(", 32 FPRs"); i = special_purpose_init(); PRINT(", %d SPRs", i); if (process_type == PPCMAX) { v_register_init(); PRINT(", 32 VECs"); } PRINT(" ]\n"); // Initialize the asm/dsm mnemonics. PRINT("Assembler Init: [ "); #ifdef ASM_DSM_AVAILABLE init_ops_and_mnemonics(); #endif PRINT(" ]\n"); // The SRecord decompressed needs to be initialized too. compression_initialize(); // If this restart was caused by dink or user taking a Reset Exception // indicate it here. if (Push_reset_button != 0) PRINT("\nA Reset Exception '0x100' initiated this restart\n"); else Push_reset_button = 1; // Lastly, show the main menu. par_about(); return( 1 ); } void delay(deciseconds) int deciseconds; { int j,k; k = 0xfffff; for(j=0;jRAM copy worked */ delay(0x400000); /* Wait 1 second */ *(char *)(0x40600000) = 0x1A; /* Place in loop mode */ delay(0x400000); *(char *)(0x40400000) = 0x2E; /* Send '.' out duart */ delay(0x400000); loop_char = *(char *)(0x40400000); if(loop_char == '.') { *(char *)(0x40200000) = 0x0A; /* Turn off the STAT LED */ *(char *)(0x40600000) = 0x0A; /* Place in normal mode */ PRINT("Duart loopback Success\n"); } else { /* Leave the LED on */ *(char *)(0x40600000) = 0x0A; /* Place in normal mode */ PRINT("Duart loopback Failure: Expected a: . got a: "); *(char *)(0x40400000) = loop_char; PRINT("\n"); } return; } //--------------------------------------------------------------------------- // main -- main DINK loop //--------------------------------------------------------------------------- main() { int countdown,status,bootline; exit_dink = 0; mach_info = &caps[ board_type ]; // Initialize all of DINK now. dink_initialize(); if (mach_info->HasWinbond) winbond_initialize(); /* We need to check to see if we are on Excimer. If we are and this is a Minimum dink build then we need to check for a 'boot block' in sector ___TBD and if present perform a countdown (3 seconds) to allow the user a specified amount of time to interrupt the automatic jump to this boot sector. If the user performs a keyboard entry in this 3 seconds then they will be placed at an Excimer prompt. */ if((board_type == 2) && (dink_type == 1)) { PRINT("Performing self test ....\n"); excimer_bist(); status = read_from_memory(0xffc00100,&bootline); if(bootline != 0xffffffff) { PRINT("Auto boot in progress ...."); PRINT(" press any key to abort\n"); countdown = 5; while(countdown != 0) { #ifdef ICACHEON delay(0x200000); /* additional delay */ #endif delay(0x70000); if(CommLookChar((char *)KEYBOARD)) { PRINT("\n... auto boot halted\n"); break; } if(countdown == 5) CommPutChar((char *)KEYBOARD,'5'); if(countdown == 4) CommPutChar((char *)KEYBOARD,'4'); if(countdown == 3) CommPutChar((char *)KEYBOARD,'3'); if(countdown == 2) CommPutChar((char *)KEYBOARD,'2'); if(countdown == 1) CommPutChar((char *)KEYBOARD,'1'); countdown = countdown - 1; if(countdown == 0) { PRINT("\n.........Jumping to boot Sector!\n"); simple_leap(0xffc00100); } } } } else if((board_type == 2) && (dink_type == 0)) { *(char *)(0x40600000) = 0x02; /* Turn on the LED */ *(char *)(0x40600000) = 0x0A; /* Turn off the LED */ } /* first thing is to open a new input buffer so that we can accept input from the keyboard. */ tok_open_input_buffer(NULL,keyboard_open,keyboard_read,keyboard_close); tok_mode_direct_input(); /* this is the whole of the main loop. We simply need to catch and display the error (if there was one) after we parse the input and execute the commands in question. Note the conditional compilation for the case where we are on the board and if we are not. */ /* if we are on the board we always want to loop. we cannot exit the loop. Notice that tok_close_input_buffer() and return 1; will NEVER be executed by the system. */ /* ** Try to enable a Kahlua slave device. This is only enabled for Map B. */ if (address_map[0] == 'B') { if (target_mode == 0) { int device_number; /* PCI Device number */ /* probe PCI to see if we have a kahlua */ device_number = pciKahluaProbe( KAHLUA_ID_LO, VENDOR_ID_HI, &target_addr); if (device_number > -1) { PRINT("Host ....\n"); config_kahlua_agent( ); /* compute PMC Interrupt Line using PCI Devcie Number minus constant 13. The constant 13 is dericed from the Sandpoint System Device Number / IDSEL lines 13 - 16 being tied to PMC Interrupt Lines 0 -3. For example: device 13 will map to PMC line 0. If the PCI device is in slot 1 (second nearest to PPMC) its IDSEL is 13, its intA line will be connected to the PPMC IRQ0 line. The Interrupt Service Routine for IRQ0 will be installed to EPIC Interrupt Vector 0 when the EPIC unit is initialized. Store the IRQ line to pmcIntLine global for host EPIC unit. tpeters */ pmcIntLine = device_number - 13; PRINT("Kahlua agent at IRQ: %d detected.\n", pmcIntLine); } } else if (target_type == (( KAHLUA_ID_LO << 16 ) | VENDOR_ID_HI )) { PRINT("Agent ....\n"); /* Inbound address translation */ sysEUMBBARWrite(L_ATU_ITWR, ATU_BASE|ATU_IW_64K); pciRegSet(PCI_REG_BASE, PCI_LMBAR_REG, PCI_MEM_ADR); /* Outbound address translation */ sysEUMBBARWrite(L_ATU_OTWR, 0x100000|ATU_IW_64K); sysEUMBBARWrite(L_ATU_OMBAR, 0x81000000); /* set AGENT_DETECTED flag in pmcIntLine global for Agent EPIC unit. The Agent's Message Unit interrupt will be enabled when the EPIC unit is initialized. */ pmcIntLine = AGENT_DETECTED; } } // If initialization complete, reset FAIL LED on Sandpoint. if (mach_info->BoardID == SP_8240 || mach_info->BoardID == SP_107) { DoOutput( (char *) IO_Base + 0x0700, 0x03 ); // LED's off (1=off) DoOutput( (char *) IO_Base + 0x0700, 0x03 ); // LED's off (1=off) } // Startup DINK! #ifdef HISTORY_SUPPORT init_history(); #endif start = &dink_loop; dink_loop(); }