⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 machdep.c

📁 国产CPU-龙芯(loongson)BIOS源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*	$Id: machdep.c,v 1.1.1.1 2003/11/08 08:41:42 wlin Exp $ *//* * Copyright (c) 2000 Opsycon AB  (http://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 Open System Consulting 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. * *//* * Pmon architecture dependent (and possibly cpu type dependent) code. */#include <stdio.h>#include <termio.h>#include <ctype.h>#include <stdlib.h>#include <string.h>#ifdef _KERNEL#undef _KERNEL#include <sys/ioctl.h>#define _KERNEL#else#include <sys/ioctl.h>#endif#include <machine/cpu.h>#include <machine/frame.h>#include <machine/regnum.h>#include <machine/trap.h>#include <pmon.h>extern int memorysize;extern u_int8_t end[];#ifdef GODSONEV1extern int global_div_num;#endif/* *  CPU type markers. */#define CPU_ALL		0x000f		/* Belongs to mask */#define	CPU_7		0x0001		/* RM7000 */#define	CPU_5		0x0002		/* R5000 */#define CPU_GOD1	0x0004#define CPU_GOD2	0x0008#define	CPU_41		0x0010		/* R4100 */#define	F_FMT	0x1000		/* Field uses format */struct RegMap {	char	width;	char	bit;	short	flags;	const char * const name;	union {		const char * const fmt;/* XXX Tell me why i must cast initializers for the next union? */		const char * const *vn;	} fe;};static void dsp_rregs __P((int *));static void dsp_fregs __P((int *));static int cputype;/* *  Return a ascii version of the processor type. */const char *md_cpuname(){/* XXX make more sophisticated dealing with rev numbers and 52x0 more precisely */	/* Handle the SandCraft SR71000 */	if (((md_cputype() >> 8) & 0xffff) == 0x0504) {		cputype = CPU_7;		return ("SR71000");	}	switch((md_cputype() >> 8) & 0xff) {	case MIPS_E9000:		cputype = CPU_7;		return("E9000");	case MIPS_RM7000:		cputype = CPU_7;		return("RM7000");	case MIPS_RM52X0:		cputype = CPU_5;		return("RM52x0");	case MIPS_GODSON2:		cputype = CPU_GOD2; // ?????????????		return("GODSON2");	case MIPS_GODSON1:		cputype=CPU_GOD1;		return("GODSON1");	default:		return("unidentified");	}}/* *  Dump out exception info for an unscheduled exception */voidmd_dumpexc(struct trapframe *tf){	int w = 100;        printf("\r\nException Cause=%s, SR=%p, PC=%p\r\n",                md_getexcname(tf), (int)md_getsr(tf), md_getpc(tf));	printf("CONTEXT=%llp, XCONTEXT=%llp\r\n", tf->context, tf->xcontext);	printf("BADVADDR=%llp, ENTHI=%llp\r\n", tf->badvaddr, tf->enthi);	printf("ENTLO0=%llp, ENTLO1=%llp\r\n\r\n", tf->entlo0, tf->entlo1);	dsp_rregs(&w);	printf("\r\n");	md_do_stacktrace(0, 0, 0, 0);}/* *  Set PC to a new value. */voidmd_setpc(struct trapframe *tf, register_t pc){	if (tf == NULL)		tf = cpuinfotab[whatcpu];	tf->pc = (int)pc;}/* *  This function clears all client registers for launch. */voidmd_clreg(struct trapframe *tf){	if (tf == NULL)		tf = cpuinfotab[whatcpu];//	md_fpsave(tf);}/* *  This function sets the client stack pointer. */voidmd_setsp(struct trapframe *tf, register_t sp){	if (tf == NULL)		tf = cpuinfotab[whatcpu];	tf->sp = sp;}/* *  This function sets the client sr to the given value. */voidmd_setsr(struct trapframe *tf, register_t sr){	if (tf == NULL)		tf = cpuinfotab[whatcpu];	tf->sr = sr;}/* *  This function returns the value of the clients sr. */register_tmd_getsr(struct trapframe *tf){	if (tf == NULL)		tf = cpuinfotab[whatcpu];	return(tf->sr);}/* *  This function sets the client sr to do a trace. */voidmd_settrace(){}/* *  This function sets the client sr to do a trace. */voidmd_setlr(struct trapframe *tf, register_t lr){	if (tf == NULL)		tf = cpuinfotab[whatcpu];	tf->ra = lr;}/* *  This function returns true if the address range given is *  invalid for load, eg will overwrite PMON or its working *  areas or other protected memory areas or load into *  existing memory. */intmd_valid_load_addr(first_addr, last_addr)	paddr_t first_addr;	paddr_t last_addr;{	first_addr = CACHED_TO_PHYS(first_addr);	last_addr = CACHED_TO_PHYS(last_addr);	if((first_addr < (paddr_t)CACHED_TO_PHYS(end)) ||	   (last_addr > (paddr_t)memorysize)) {		printf("first_addr 0x%x\tend 0x%x\tlast_addr 0x%x\tmemsize 0x%x\n",first_addr,(paddr_t)CACHED_TO_PHYS(end),last_addr,(paddr_t)memorysize);		return(1);	}	return(0);} /* *  This function sets the SP to the new value given if it's *  non zero. The old value of sp is returned. */register_tmd_adjstack(struct trapframe *tf, register_t newsp){	register_t oldsp;	if (tf == NULL)		tf = cpuinfotab[whatcpu];	oldsp = tf->sp;	if(newsp != 0) {		tf->sp = newsp;	}	return(oldsp);}/* *  This function sets the arguments to client code so *  the client sees the arguments as if it was called *  with the arguments. */voidmd_setargs(struct trapframe *tf, register_t a1, register_t a2,		register_t a3, register_t a4){	if (tf == NULL)		tf = cpuinfotab[whatcpu];	tf->a0 = a1;	tf->a1 = a2;	tf->a2 = a3;	tf->a3 = a4;}voidmd_setentry(struct trapframe *tf, register_t pc){	if (tf == NULL)		tf = cpuinfotab[whatcpu];	tf->pc = pc;}/* *  This function returns the PC value that is supposed *  to be used at restore to client state. Do not confuse *  with the value of the exception PC. (Diff on some arches). */void *md_getpc(struct trapframe *tf){	if (tf == NULL)		tf = cpuinfotab[whatcpu];	return((void *)(int)tf->pc);}/* *  This function is called from exception(). It's purpose *  is to decode the exception and return the exception *  type to the caller for further processing. */intmd_exc_type(struct trapframe *frame){	switch((frame->cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT) {	case T_BREAK:	case T_TRAP:		return(EXC_BPT);	case T_IWATCH:	case T_DWATCH:		return(EXC_WTCH);	case T_RES_INST:#ifdef BONITOEL		return(EXC_RES);#endif	case T_INT:	case T_TLB_MOD:	case T_TLB_LD_MISS:	case T_TLB_ST_MISS:	case T_ADDR_ERR_LD:	case T_ADDR_ERR_ST:	case T_BUS_ERR_IFETCH:	case T_BUS_ERR_LD_ST:	case T_SYSCALL:	case T_COP_UNUSABLE:	case T_OVFLOW:	case T_FPE:		return(EXC_BAD);		case T_VCEI:	case T_VCED:		return(EXC_BAD);	}	return(EXC_BAD);}/* *  This function returns the value of the RA reg */register_tmd_getlink(struct trapframe *tf){	if (tf == NULL)		tf = cpuinfotab[whatcpu];	return(tf->ra);}/* *  This function returns a pointer from the value of the *  PC reg when an exception have been taken. */void *md_get_excpc(struct trapframe *tf){	if (tf == NULL)		tf = cpuinfotab[whatcpu];	return((void *)(int)tf->pc);}const char *md_getexcname(struct trapframe *tf){	switch((tf->cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT) {	case T_INT:		return("interrupt pending");	case T_TLB_MOD:		return("TLB modified");	case T_TLB_LD_MISS:		return("TLB miss on load or ifetch");	case T_TLB_ST_MISS:		return("TLB miss on store");	case T_ADDR_ERR_LD:		return("address error on load or ifetch");	case T_ADDR_ERR_ST:		return("address error on store");	case T_BUS_ERR_IFETCH:		return("bus error on ifetch");	case T_BUS_ERR_LD_ST:		return("bus error on load or store");	case T_SYSCALL:		return("system call");	case T_BREAK:		return("breakpoint");	case T_RES_INST:		return("reserved instruction");	case T_COP_UNUSABLE:		return("coprocessor unusable");	case T_OVFLOW:		return("arithmetic overflow");	case T_TRAP:		return("trap instruction");	case T_VCEI:		return("virtual coherency instruction");	case T_FPE:		return("floating point");	case T_IWATCH:		return("iwatch");	case T_DWATCH:		return("dwatch");	case T_VCED:		return("virtual coherency data");	}	return("exception unknown");}/* *  ator returns either 32 bit or 64 bit conversion *  depending on CPU word length. */intmd_ator(register_t *vp, char *p, int base){  if (sizeof(register_t)==4) 	return(atob(vp,p,base));  else#ifdef HAVE_QUAD	return(llatob(vp, p, base));#else	return(0);#endif}/* *  Returns true and sets the location pointed by vp to the value *  of the specified register or false if not recognized. Register *  names can be n the form <regno> r<nr> or sp. *  Some special registers are also detected. *//* *  Floating point status register. */char * const rmvalues[] = {    "rn", "rz", "rp", "rm", 0};const struct RegMap fsrmap[] = {    {1, 24, CPU_ALL|F_FMT, "fs", {" %*b"}},    {1, 23, CPU_ALL|F_FMT, "c",  {" %*b"}},    {1, 17, CPU_ALL|F_FMT, "ce", {" %*b"}},    {1, 16, CPU_ALL|F_FMT, "cv", {" %*b"}},    {1, 15, CPU_ALL|F_FMT, "cz", {" %*b"}},    {1, 14, CPU_ALL|F_FMT, "co", {" %*b"}},    {1, 13, CPU_ALL|F_FMT, "cu", {" %*b"}},    {1, 12, CPU_ALL|F_FMT, "ci", {" %*b"}},    {1, 11, CPU_ALL|F_FMT, "ev", {" %*b"}},    {1, 10, CPU_ALL|F_FMT, "ez", {" %*b"}},    {1, 9,  CPU_ALL|F_FMT, "eo", {" %*b"}},    {1, 8,  CPU_ALL|F_FMT, "eu", {" %*b"}},    {1, 7,  CPU_ALL|F_FMT, "ei", {" %*b"}},    {1, 6,  CPU_ALL|F_FMT, "fv", {" %*b"}},    {1, 5,  CPU_ALL|F_FMT, "fz", {" %*b"}},    {1, 4,  CPU_ALL|F_FMT, "fo", {" %*b"}},    {1, 3,  CPU_ALL|F_FMT, "fu", {" %*b"}},    {1, 2,  CPU_ALL|F_FMT, "fi", {" %*b"}},    {2, 0,  CPU_ALL,       "rm", {(const char * const)rmvalues}},    {0}};const char * const ksuvalues[] = {    "kern", "supv", "user", "????", 0};const struct RegMap statmap[] = {    {1, 31, CPU_5|CPU_7|F_FMT, "xx",  {" %*b"}},    {4, 28, CPU_ALL|F_FMT,     "cu",  {" %*b"}},    {1, 27, CPU_ALL|F_FMT,     "rp",  {" %*b"}},    {1, 26, CPU_ALL|F_FMT,     "fr",  {" %*b"}},    {1, 25, CPU_ALL|F_FMT,     "re",  {" %*b"}},    {1, 24, CPU_ALL|F_FMT,     "its", {" %*b"}},    {1, 22, CPU_ALL|F_FMT,     "bev", {" %*b"}},    {1, 21, CPU_ALL|F_FMT,     "ts",  {" %*b"}},    {1, 20, CPU_ALL|F_FMT,     "sr",  {" %*b"}},    {1, 18, CPU_ALL|F_FMT,     "ch",  {" %*b"}},    {1, 17, CPU_ALL|F_FMT,     "ce",  {" %*b"}},    {1, 16, CPU_ALL|F_FMT,     "de",  {" %*b"}},    {8, 8,  CPU_ALL|F_FMT,     "im",  {" %*b"}},    {1, 7,  CPU_ALL|F_FMT,     "kx",  {" %*b"}},    {1, 6,  CPU_ALL|F_FMT,     "sx",  {" %*b"}},    {1, 5,  CPU_ALL|F_FMT,     "ux",  {" %*b"}},    {2, 3,  CPU_ALL,           "ksu", {(const char * const)ksuvalues}},    {1, 2,  CPU_ALL|F_FMT,     "erl", {" %*b"}},    {1, 1,  CPU_ALL|F_FMT,     "exl", {" %*b"}},    {1, 0,  CPU_ALL|F_FMT,     "ie",  {" %*b"}},    {0}};const char * const excodes[] = {    "Int",  "MOD",  "TLBL", "TLBS",    "AdEL", "AdES", "IBE",  "DBE",    "Sys",  "Bp",   "RI",   "CpU",     "Ovf",  "Trap", "VCEI", "FPE",     "Cp2",  "Resv", "Resv", "Resv",    "Resv", "Resv", "Resv", "Wtch",    "Resv", "Resv", "Resv", "Resv",    "Resv", "Resv", "Resv", "VCED",    0};const struct RegMap causemap[] = {    {1, 31, CPU_ALL|F_FMT,          "bd",       {" %*b"}},    {2, 28, CPU_ALL|F_FMT,          "ce",       {" %*d"}},    {1, 26, CPU_7|F_FMT,            "w2",       {" %*b"}},    {1, 25, CPU_7|F_FMT,            "w1",       {" %*b"}},    {1, 24, CPU_7|F_FMT,            "iv",       {" %*b"}},    {16, 8, CPU_7|F_FMT,            "ipending", {" %*b"}},    {8,  8, (CPU_ALL&~CPU_7)|F_FMT, "ipending", {" %*b"}},    {4,  2, CPU_ALL,                "excode",   {(const char * const)excodes}},    {0}};/* RM7000 interrupt control register */const struct RegMap icrmap[] = {    {8, 8, CPU_ALL|F_FMT, "im", {" %*b"}},    {1, 7, CPU_ALL|F_FMT, "te", {" %*b"}},    {5, 0, CPU_ALL|F_FMT, "vs", {" %*x"}},    {0}};const struct RegMap pridmap[] = {    {8, 8, CPU_ALL|F_FMT, "imp", {" %*d"}},    {8, 0, CPU_ALL|F_FMT, "rev", {" %*d"}},    {0}};const char * const epvalues[] = {    "DD", "DDx", "DDxx", "DxDx", "DDxxx", "DDxxxx", "DxxDxx", "DDxxxxx",

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -