📄 start.s
字号:
/* $Id: start.S,v 1.3 2004/05/17 10:39:22 wlin Exp $ *//* * Copyright (c) 2001 Opsycon AB (www.opsycon.se) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Opsycon AB, Sweden. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. * */#ifndef _KERNEL#define _KERNEL#endif#include <asm.h>#include <regnum.h>#include <cpu.h>#include <pte.h>#include "pmon/dev/ns16550.h"#include "target/i82371eb.h"#include "target/prid.h"#include "target/sbd.h"#include "target/bonito.h"#include "target/i8254.h"#include "target/pc97307.h"#include "target/isapnpreg.h"#define DEBUG_LOCORE#undef DEBUG_DIMM_SPD#ifdef DEBUG_LOCORE#define TTYDBG(x) \ .rdata;98: .asciz x; .text; la a0, 98b; bal stringserial; nop#else#define TTYDBG(x)#endif#define PRINTSTR(x) \ .rdata;98: .asciz x; .text; la a0, 98b; bal stringserial; nop#define tmpsize s1#define msize s2#define sdShape s3#define bonito s4#define dbg s5#define sdCfg s6#define CFG_IB 0x00000020#define CFG_DB 0x00000010#define CFG_C_WBACK 3#define CFG_BE 0x00008000#define CFG_EPMASK 0x0f000000#define CFG_EPD 0x00000000#define CFG_EM_R4K 0x00000000#define CFG_EMMASK 0x00c00000#define CFG_AD 0x00800000/* * Register usage: * * s0 link versus load offset, used to relocate absolute adresses. * s1 free * s2 memory size. * s3 sdShape. * s4 Bonito base address. * s5 dbg. * s6 sdCfg. * s7 rasave. * s8 L3 Cache size. */ .set noreorder .globl _start .globl start .globl __main_start:start: .globl stackstack = start - 0x4000 /* Place PMON stack below PMON start in RAM *//* NOTE!! Not more that 16 instructions here!!! Right now it's FULL! */ mtc0 zero, COP_0_STATUS_REG mtc0 zero, COP_0_CAUSE_REG li t0, SR_BOOT_EXC_VEC /* Exception to Boostrap Location */ mtc0 t0, COP_0_STATUS_REG la sp, stack la gp, _gp bal uncached /* Switch to uncached address space */ nop bal locate /* Get current execute address */ nopuncached: or ra, UNCACHED_MEMORY_ADDR j ra nop/* * Reboot vector usable from outside pmon. */ .align 8ext_map_and_reboot: bal CPU_TLBClear nop li a0, 0xc0000000 li a1, 0x40000000 bal CPU_TLBInit nop la v0, tgt_reboot la v1, start subu v0, v1 lui v1, 0xffc0 addu v0, v1 jr v0 nop/* * Exception vectors here for rom, before we are up and running. Catch * whatever comes up before we have a fully fledged exception handler. */ .align 9 /* bfc00200 */ la a0, v200_msg bal stringserial nop b exc_common .align 7 /* bfc00280 */ la a0, v280_msg bal stringserial nop b exc_common/* Cache error */ .align 8 /* bfc00300 */ PRINTSTR("\r\nPANIC! Unexpected Cache Error exception! ") mfc0 a0, COP_0_CACHE_ERR bal hexserial nop b exc_common/* General exception */ .align 7 /* bfc00380 */ la a0, v380_msg bal stringserial nop b exc_common .align 8 /* bfc00400 */ la a0, v400_msg bal stringserial nop exc_common: PRINTSTR("\r\nERRORPC=") mfc0 a0, COP_0_ERROR_PC bal hexserial nop PRINTSTR("\r\nEPC=") mfc0 a0, COP_0_EXC_PC bal hexserial nop PRINTSTR("\r\nDERR0=") cfc0 a0, COP_0_DERR_0 bal hexserial nop PRINTSTR("\r\nDERR1=") cfc0 a0, COP_0_DERR_1 bal hexserial nop// b ext_map_and_reboot nop .align 8 nop .align 8 .word read .word write .word open .word close .word nullfunction .word printf .word vsprintf .word nullfunction .word nullfunction .word getenv .word nullfunction .word nullfunction .word nullfunction .word nullfunction/* * We get here from executing a bal to get the PC value of the current execute * location into ra. Check to see if we run from ROM or if this is ramloaded. */locate: la s0,start subu s0,ra,s0 and s0,0xffff0000 li t0,SR_BOOT_EXC_VEC mtc0 t0,COP_0_STATUS_REG mtc0 zero,COP_0_CAUSE_REG .set noreorder li bonito,PHYS_TO_UNCACHED(BONITO_REG_BASE)#if 0locate: la s0, start /* RA set from BAL above! */ subu s0, ra, s0 /* s0 is now load vs. link offset */ and s0, 0xffff0000 /* Mask off lower bits */ mfc0 t0,COP_0_PRID mfc0 v0,COP_0_STATUS_REG mtc0 zero,COP_0_WATCH_LO mtc0 zero,COP_0_WATCH_HI and v0,SR_SOFT_RESET # preserve Soft Reset or v0,SR_BOOT_EXC_VEC # set Boot Exceptions beq t0,0x0a11,1f # R4200 rev 1.1: disable cache errors nop beq t0,0x5413,1f # R5432 rev 1.3: disable cache errors nop b 2f nop1: or v0,SR_DIAG_DE2:/* * Clean out and initialize the TLB */ bal CPU_TLBClear nop li a0, 0xc0000000 li a1, 0x40000000 bal CPU_TLBInit nop/* * Turn off all high decoders to avoid address conflicts. */ mtc0 v0,COP_0_STATUS_REG mtc0 zero,COP_0_CAUSE_REG mfc0 t1,COP_0_CONFIG mfc0 t2,COP_0_PRID # get PrID mtc0 zero,$18 # C0_IWATCH/C0_WATCHLO mtc0 zero,$19 # C0_DWATCH/C0_WATCHHI li bonito,PHYS_TO_UNCACHED(BONITO_REG_BASE) srl t2,8 and t2,0xff bne t2,PRID_R4650,2f nop mtc0 zero,$0 # C0_IBASE mtc0 zero,$1 # C0_IBOUND mtc0 zero,$2 # C0_DBASE mtc0 zero,$3 # C0_DBOUND b 3f nop 2: and t1,~0x3f # set bits 5..0 only or t1,CFG_IB | CFG_DB | CFG_C_WBACK and t1,~CFG_EPMASK or t1,CFG_EPD bne t2,PRID_R5400,1f nop and t1,~CFG_EMMASK or t1,CFG_EM_R4K b 2f nop1: and t1,~CFG_AD2: mtc0 t1,COP_0_CONFIG3: mfc0 t1,COP_0_STATUS_REG # get Status mtc0 zero,COP_0_CAUSE_REG and t1,SR_SOFT_RESET # leave the SoftReset bit or t1,SR_BOOT_EXC_VEC # force Boot Exception Vec mtc0 t1,COP_0_STATUS_REG#endif#define MOD_MASK 0x00000003#define MOD_B 0x00000000 /* byte "modifier" */#define MOD_H 0x00000001 /* halfword "modifier" */#define MOD_W 0x00000002 /* word "modifier" */#if __mips64# define MOD_D 0x00000003 /* doubleword "modifier" */#endif#define OP_MASK 0x000000fc#define OP_EXIT 0x00000000 /* exit (status) */#define OP_DELAY 0x00000008 /* delay (cycles) */#define OP_RD 0x00000010 /* read (addr) */#define OP_WR 0x00000014 /* write (addr, val) */#define OP_RMW 0x00000018 /* read-modify-write (addr, and, or) */#define OP_WAIT 0x00000020 /* wait (addr, mask, value) */#define WR_INIT(mod,addr,val) \ .word OP_WR|mod,PHYS_TO_UNCACHED(addr);\ .word (val),0 #define RD_INIT(mod,addr) \ .word OP_RD|mod,PHYS_TO_UNCACHED(addr);\ .word 0,0 #define RMW_INIT(mod,addr,and,or) \ .word OP_RMW|mod,PHYS_TO_UNCACHED(addr);\ .word (and),(or) #define WAIT_INIT(mod,addr,and,or) \ .word OP_WAIT|mod,PHYS_TO_UNCACHED(addr);\ .word (mask),(val)#define DELAY_INIT(cycles) \ .word OP_DELAY,(cycles);\ .word 0,0 #define EXIT_INIT(status) \ .word OP_EXIT,(status);\ .word 0,0#define BONITO_INIT(r,v) WR_INIT(MOD_W,BONITO_BASE+/**/r,v)#define BONITO_BIS(r,b) RMW_INIT(MOD_W,BONITO_BASE+(r),~0,b)#define BONITO_BIC(r,b) RMW_INIT(MOD_W,BONITO_BASE+(r),~(b),0)#define BONITO_RMW(r,c,s) RMW_INIT(MOD_W,BONITO_BASE+(r),~(c),s) #define CFGADDR(idsel,function,reg) ((1<<(11+(idsel)))+((function)<<8)+(reg))#define _ISABWR_INIT(mod,function,isabreg,val) \ WR_INIT(MOD_W,BONITO_BASE+BONITO_PCIMAP_CFG,CFGADDR(PCI_IDSEL_I82371,function,isabreg)>>16) ; \ RD_INIT(MOD_W,BONITO_BASE+BONITO_PCIMAP_CFG) ; \ WR_INIT(mod,PCI_CFG_SPACE+(CFGADDR(PCI_IDSEL_I82371,function,isabreg)&0xffff),val) #define _ISABRD_INIT(mod,function,isabreg) \ WR_INIT(MOD_W,BONITO_BASE+BONITO_PCIMAP_CFG,CFGADDR(PCI_IDSEL_I82371,function,isabreg)>>16) ; \ RD_INIT(MOD_W,BONITO_BASE+BONITO_PCIMAP_CFG) ; \ RD_INIT(mod,PCI_CFG_SPACE+(CFGADDR(PCI_IDSEL_I82371,function,isabreg)&0xffff))#define _ISAWR_INIT(isareg,val) \ WR_INIT(MOD_B,PCI_IO_SPACE+(isareg),val) #define _ISARD_INIT(isareg) \ RD_INIT(MOD_B,PCI_IO_SPACE+(isareg)) #define ISABBWR_INIT(function,isabreg,val) \ _ISABWR_INIT(MOD_B,function,(isabreg),val)#define ISABHWR_INIT(function,isabreg,val) \ _ISABWR_INIT(MOD_H,function,(isabreg),val)#define ISABWWR_INIT(function,isabreg,val) \ _ISABWR_INIT(MOD_W,function,isabreg,val)#define ISAWR_INIT(isareg,val) \ _ISAWR_INIT(isareg,val)#define ISARD_INIT(isareg) \ _ISARD_INIT(isareg) bal 1f nop /* bonito endianess */ BONITO_BIC(BONITO_BONPONCFG,BONITO_BONPONCFG_CPUBIGEND) BONITO_BIC(BONITO_BONGENCFG,BONITO_BONGENCFG_BYTESWAP|BONITO_BONGENCFG_MSTRBYTESWAP) BONITO_BIS(BONITO_BONPONCFG, BONITO_BONPONCFG_IS_ARBITER) /* * In certain situations it is possible for the Bonito ASIC * to come up with the PCI registers uninitialised, so do them here */#define PCI_CLASS_BRIDGE 0x06#define PCI_CLASS_SHIFT 24#define PCI_SUBCLASS_BRIDGE_HOST 0x00#define PCI_SUBCLASS_SHIFT 16#define PCI_COMMAND_IO_ENABLE 0x00000001#define PCI_COMMAND_MEM_ENABLE 0x00000002#define PCI_COMMAND_MASTER_ENABLE 0x00000004#define PCI_COMMAND_STATUS_REG 0x04#define PCI_MAP_IO 0X00000001#define PCI_DEV_I82371 17#define PCI_CFG_SPACE BONITO_PCICFG_BASE BONITO_INIT(BONITO_PCICLASS,(PCI_CLASS_BRIDGE << PCI_CLASS_SHIFT) | (PCI_SUBCLASS_BRIDGE_HOST << PCI_SUBCLASS_SHIFT)) BONITO_INIT(BONITO_PCICMD, BONITO_PCICMD_PERR_CLR|BONITO_PCICMD_SERR_CLR|BONITO_PCICMD_MABORT_CLR|BONITO_PCICMD_MTABORT_CLR|BONITO_PCICMD_TABORT_CLR|BONITO_PCICMD_MPERR_CLR) BONITO_INIT(BONITO_PCILTIMER, 0) BONITO_INIT(BONITO_PCIBASE0, 0) BONITO_INIT(BONITO_PCIBASE1, 0) BONITO_INIT(BONITO_PCIBASE2, 0) BONITO_INIT(BONITO_PCIEXPRBASE, 0) BONITO_INIT(BONITO_PCIINT, 0) BONITO_BIS(BONITO_PCICMD, BONITO_PCICMD_PERRRESPEN) BONITO_BIS(BONITO_PCICMD, PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE|PCI_COMMAND_MASTER_ENABLE) /* enable i/o buffer cache and other go faster bits */ BONITO_BIS(BONITO_BONGENCFG, \ BONITO_BONGENCFG_BUSERREN| \ BONITO_BONGENCFG_PREFETCHEN| \ BONITO_BONGENCFG_WBEHINDEN| \ BONITO_BONGENCFG_PCIQUEUE| \ BONITO_BONGENCFG_SNOOPEN) BONITO_BIC(BONITO_BONGENCFG, 0x80) #½ûÖ¹iobc# BONITO_BIS(BONITO_BONGENCFG, BONITO_BONGENCFG_BUSERREN) /* Set debug mode */ BONITO_BIS(BONITO_BONGENCFG, BONITO_BONGENCFG_DEBUGMODE) /* Turn most special purpose pins into GPIO; set ISA mode */ ISABWWR_INIT(0, I82371_GENCFG, I82371_GENCFG_CFG) /* disable RTC & KBD chip selects */ ISABHWR_INIT(0, I82371_XBCS, 0) /* Enable PCI 2.1 timing support */ ISABBWR_INIT(0, I82371_DLC, I82371_DLC_DT /* | I82371_DLC_PR */ | I82371_DLC_USBPR | I82371_DLC_DTTE) /* Set top of memory to 16MB, so all ISA bus master & DMA accesses are forwarded to PCI mem space */ ISABBWR_INIT(0, I82371_TOM, I82371_TOM_TOM(16) | I82371_TOM_FWD_LBIOS | I82371_TOM_FWD_AB | I82371_TOM_FWD_89) /* Set the SMB base address */ ISABWWR_INIT(3, I82371_PCI3_SMBBA, SMB_PORT|PCI_MAP_IO) /* enable the host controller */ ISABBWR_INIT(3, I82371_PCI3_SMBHSTCFG, I82371_PCI3_SMB_HST_EN) /* enable the SMB IO ports */ ISABBWR_INIT(3, PCI_COMMAND_STATUS_REG, PCI_COMMAND_IO_ENABLE) ISABWWR_INIT(3, I82371_PCI3_PMBA, 0x8000|PCI_MAP_IO) ISABBWR_INIT(3, I82371_PCI3_PMREGMISC, 0x01) /* 15us ISA bus refresh clock */#define ISAREFRESH (PT_CRYSTAL/(1000000/15)) ISARD_INIT(CTC_PORT+PT_CONTROL) /* program i8254 ISA refresh counter */ ISAWR_INIT(CTC_PORT+PT_CONTROL,PTCW_SC(PT_REFRESH)|PTCW_16B|PTCW_MODE(MODE_RG)) ISAWR_INIT(CTC_PORT+PT_REFRESH, ISAREFRESH & 0xff) ISAWR_INIT(CTC_PORT+PT_REFRESH, ISAREFRESH >> 8) /* program ISA ICU */ ISAWR_INIT(ICU1_PORT, 0x11) /* ICW1 */ ISAWR_INIT(ICU1_PORT+1,0x00) /* ICW2: vector */ ISAWR_INIT(ICU1_PORT+1,0x04) /* ICW3: cascade on IRQ2 */ ISAWR_INIT(ICU1_PORT+1,0x01) /* ICW4: 8086 mode */ ISAWR_INIT(ICU1_PORT+1,0xff) /* OCW1: mask all */ ISAWR_INIT(ICU2_PORT, 0x11) /* ICW1 */ ISAWR_INIT(ICU2_PORT+1,0x08) /* ICW2: vector */ ISAWR_INIT(ICU2_PORT+1,0x02) /* ICW3: */ ISAWR_INIT(ICU2_PORT+1,0x01) /* ICW4: 8086 mode */ ISAWR_INIT(ICU2_PORT+1,0xff) /* OCW1: mask all */ ISAWR_INIT(ICU1_PORT+1,~(1<<2)) /* enable IRQ2 */ /* set up ISA devices */ /* select logical device 1 (mouse) */ ISAWR_INIT(ISAPNP_MBADDR,ISAPNP_LOGICAL_DEV_NUM) ISAWR_INIT(ISAPNP_MBDATA,1) ISAWR_INIT(ISAPNP_MBADDR,ISAPNP_ACTIVATE) ISAWR_INIT(ISAPNP_MBDATA,1) /* select logical device 4 (parallel) */ ISAWR_INIT(ISAPNP_MBADDR,ISAPNP_LOGICAL_DEV_NUM) ISAWR_INIT(ISAPNP_MBDATA,4) ISAWR_INIT(ISAPNP_MBADDR,ISAPNP_IO_DESC0+ISAPNP_IO_BASE_15_8) ISAWR_INIT(ISAPNP_MBDATA,(ECP_PORT>>8) & 0xff) ISAWR_INIT(ISAPNP_MBADDR,ISAPNP_IO_DESC0+ISAPNP_IO_BASE_7_0) ISAWR_INIT(ISAPNP_MBDATA,ECP_PORT & 0xff) ISAWR_INIT(ISAPNP_MBADDR,ISAPNP_IRQ_DESC0+ISAPNP_IRQ_CONTROL) ISAWR_INIT(ISAPNP_MBDATA,ISAPNP_IRQ_HIGH) ISAWR_INIT(ISAPNP_MBADDR,ISAPNP_ACTIVATE) ISAWR_INIT(ISAPNP_MBDATA,1) /* select logical device 5 (COM2) */ ISAWR_INIT(ISAPNP_MBADDR,ISAPNP_LOGICAL_DEV_NUM) ISAWR_INIT(ISAPNP_MBDATA,5) ISAWR_INIT(ISAPNP_MBADDR,ISAPNP_ACTIVATE) ISAWR_INIT(ISAPNP_MBDATA,1) /* select logical device 6 (COM1) */ ISAWR_INIT(ISAPNP_MBADDR,ISAPNP_LOGICAL_DEV_NUM) ISAWR_INIT(ISAPNP_MBDATA,6) ISAWR_INIT(ISAPNP_MBADDR,ISAPNP_ACTIVATE) ISAWR_INIT(ISAPNP_MBDATA,1) EXIT_INIT(0)#define Init_Op 0#define Init_A0 4#define Init_A1 8#define Init_A2 12#define Init_Size 161: move a0,rareginit: /* local name */ lw t3, Init_Op(a0) lw t0, Init_A0(a0) and t4,t3,OP_MASK /* * EXIT(STATUS) */ bne t4, OP_EXIT, 8f nop move v0,t0 b .done nop /* * DELAY(CYCLES) */8: bne t4, OP_DELAY, 8f nop1: bnez t0,1b subu t0,1 b .next nop
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -