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

📄 machdep.c

📁 国产CPU-龙芯(loongson)BIOS源代码
💻 C
字号:
/*	$Id: machdep.c,v 1.1.1.1 2003/11/08 08:41:42 wlin Exp $ *//* * Copyright (c) 2000-2001 Opsycon AB  (http://www.opsycon.se) * Copyright (c) 2000-2001 RTMX, Inc   (http://www.rtmx.com) *  * 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 for Rtmx, Inc 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 <ctype.h>#include <stdlib.h>#include <sys/param.h>#include <sys/kernel.h>#include <sys/syslog.h>#include <sys/systm.h> #ifdef _KERNEL#undef _KERNEL#include <sys/ioctl.h>#define _KERNEL#else#include <sys/ioctl.h>#endif#include <machine/cpu.h>#include <powerpc.h>#include <pmon.h>#include "mainbus.h"extern struct trapframe DBGREG;extern u_int32_t FPREG[];extern int memorysize;extern int trapcode, trapsize;extern int eintrcode, eintrsize;extern int isitrap, isisize;extern int dsitrap, dsisize;extern int memorysize;#if NMAINBUS > 0static int clkenable;static unsigned long clkpertick;static unsigned long clkperusec;static unsigned long _softcompare;#elsestatic unsigned long clkperusec;static void tgt_clksetup(void);#endifint copytoram (void *, void *);void initppc (int);void initppcsmp (void);void extint_handler __P((void));struct bat battable[16];	/* Translation table, PMON */char hwethadr[6];volatile struct	timeval time;/* *  This code is called from start.S to move the PROM contents to RAM *  after the initial SDRAM controller setup work has been done. */intcopytoram(void *rom, void *ram){extern u_int8_t edata[];extern u_int8_t end[];	u_int32_t *rdata, *pdata;	u_int count;	/*	 *  Copy ROM to RAM memory. 	 */	pdata = (u_int32_t *)rom;	rdata = (u_int32_t *)ram;	count = (int)end - (int)ram;	while(count > 0) {		*rdata++ = *pdata++;		count -= 4;	}	/*	 *  Verify copy ROM to RAM memory. 	 */	pdata = (u_int32_t *)rom;	rdata = (u_int32_t *)ram;	count = (int)end - (int)ram;	while(count > 0) {		if(*rdata++ != *pdata++) {			break;		}		count -= 4;	}	if(count > 0) {  /* Copy failed */		return(1);	}	/*	 *  Clear BSS.	 */	rdata = (u_int32_t *)edata;	count = (end - edata) / 4;	while(count--) {		*rdata++ = 0;	}	syncicache(rdata, (int)end - (int)ram);  /* pram issue (bel) */	return(0);}/* *  This code is called from start.S to launch PMON2000 after having *  completed the final setup. Do all setup that does not really need *  assembly code here to keep down the size of .start.S'. *  NOTE that until translation is enabled no I/O must be done so *  targets that enable caches in start.S will work. */voidinitppc(msize)	int msize;{	int i, exc, scratch;	memorysize = msize;	/*	 *  Set up an initial mapping using BAT registers.	 *  First clear all to avoid any old setting overlap.	 */        __asm__ volatile ("mtibatu 0,%0" :: "r"(0));        __asm__ volatile ("mtibatu 1,%0" :: "r"(0));        __asm__ volatile ("mtibatu 2,%0" :: "r"(0));        __asm__ volatile ("mtibatu 3,%0" :: "r"(0));        __asm__ volatile ("mtdbatu 0,%0" :: "r"(0));        __asm__ volatile ("mtdbatu 1,%0" :: "r"(0));        __asm__ volatile ("mtdbatu 2,%0" :: "r"(0));        __asm__ volatile ("mtdbatu 3,%0" :: "r"(0)); 	/*	 *  IBAT0 and DBAT0 points at first 256Mb of RAM.	 */	__asm__ volatile ("mtibatl 0,%0; mtibatu 0,%1"                      :: "r"(BATL(0x00000000, BAT_M)),			 "r"(BATU(0x00000000, BAT_256M)));	__asm__ volatile ("mtdbatl 0,%0; mtdbatu 0,%1"                      :: "r"(BATL(0x00000000, BAT_M)),			 "r"(BATU(0x00000000, BAT_256M)));#if defined(PPC604MMU)	/*         *  Then map ISA/PCI I/O space and PCI Mem space.         */	__asm__ volatile ("mtdbatl 1,%0; mtdbatu 1,%1"			:: "r"(BATL(PCI_IO_BASE, BAT_I)),			"r"(BATU(PCI_IO_BASE, BAT_256M)));	__asm__ volatile ("mtdbatl 2,%0; mtdbatu 2,%1"			:: "r"(BATL(PCI_MEM_BASE, BAT_I)),			 "r"(BATU(PCI_MEM_BASE, BAT_256M)));/*XXX*/	__asm__ volatile ("mtdbatl 3,%0; mtdbatu 3,%1"			:: "r"(BATL(0xf0000000, BAT_I)),			"r"(BATU(0xf0000000, BAT_256M)));#endif	savebat(&trapbat);	cpuinfotab[0] = md_getcpuinfoptr();	/*	 * Set up bat table for linear mapping of entire space.	 * This has to be uncached since some I/O registers will	 * be handled by the BAT spill handler when accessed.	 */	for(i = 0; i < 16; i++) {		battable[i].batu = BATU(i << 28, BAT_256M);		battable[i].batl = BATL(i << 28, BAT_I);	}	/*	 *  Set up trap vectors	 */	for (exc = EX_BEGIN; exc <= EX_END; exc += 0x100) {		switch(exc) {		case EX_DSI:			bcopy((char *)&dsitrap, (char *)exc, (size_t)&dsisize);			break;		case EX_ISI:			bcopy((char *)&isitrap, (char *)exc, (size_t)&isisize);			break;		case EX_EINT:			bcopy((char *)&eintrcode, (char *)exc, (size_t)&eintrsize);			break;		default:			bcopy((char *)&trapcode, (char *)exc, (size_t)&trapsize);			break;		}	}	syncicache((void *)EX_BEGIN, EX_END + 0x100 - EX_BEGIN);	/*	 *  Now turn on translation.	 */	__asm__ volatile ("eieio; mfmsr %0; ori %0,%0,%1; mtmsr %0; sync;isync"                      : "=r"(scratch) : "K"(PSL_IR|PSL_DR|PSL_ME|PSL_RI));        SBD_DISPLAY ("TRAN", CHKPNT_FREQ);#ifdef HAVE_TOD	/*	 * Init Real-Time Clock	 */	tgt_rtinit();#endif	/*	 *  Probe clock frequencys so delays will work properly.	 */	tgt_cpufreq();#if NMAINBUS == 0	/*	 * Setup clock variables	 */	tgt_clksetup();#endif /* PMON_SYS */	#ifdef PMON_PFLASH	/*	 * Init dynamic sized flash memory bank	 */	tgt_flashinit();#endif /* PMON_PFLASH */		/*	 *  Init PMON and debug	 */        SBD_DISPLAY ("DBG", CHKPNT_FREQ);	dbginit(NULL);	/*	 * Launch!	 */	main();}#if defined(SMP)/* *  Main code entry for second+ CPUs. */voidinitppcsmp(){	int scratch;extern void _pmon_break(void);	/*	 *  IBAT0 and DBAT0 points at first 256Mb of RAM.	 */	__asm__ volatile ("mtibatl 0,%0; mtibatu 0,%1"                      :: "r"(BATL(0x00000000, BAT_M)),			 "r"(BATU(0x00000000, BAT_256M)));	__asm__ volatile ("mtdbatl 0,%0; mtdbatu 0,%1"                      :: "r"(BATL(0x00000000, BAT_M)),			 "r"(BATU(0x00000000, BAT_256M)));	/*	 *  Now turn on translation.	 */	__asm__ volatile ("eieio; mfmsr %0; ori %0,%0,%1; mtmsr %0; sync;isync"                      : "=r"(scratch) : "K"(PSL_IR|PSL_DR|PSL_ME|PSL_RI));	if (!getenv("nocache"))		md_cacheon();	cpuinfotab[tgt_smpwhoami()] = md_getcpuinfoptr();	tgt_smpready();		/* Synchronize with CPU 0 */	_pmon_break();		/* Go idle */}/* *  Do a processor fork, eg save state, copy and setup new stack *  and schedule next processor to run with the new setup. */inttgt_smpfork(size_t copysize, char *newstack){extern int _pmon_snap(void);	if (_pmon_snap() == 0) {		char *oldstack;		struct trapframe *myinfo = cpuinfotab[tgt_smpwhoami()];		struct trapframe *soninfo = cpuinfotab[tgt_smpwhoami()+1];		oldstack = (char *)myinfo->fixreg[1];		newstack = newstack - copysize;		memcpy(newstack, oldstack, copysize);		*soninfo = *myinfo;		soninfo->fixreg[1] = (register_t)newstack;		soninfo->fixreg[3] = 1;		tgt_smpschedule(tgt_smpwhoami()+1);		return(tgt_smpwhoami()+1);	}	return(0);}#endif/* *  Return a ascii version of the processor type. */const char *md_cpuname(){	int cputype;	cputype = md_cputype();	switch((cputype >> 16) & 0xffff) {	case CPU_TYPE_601:		return("601");	case CPU_TYPE_602:		return("602");	case CPU_TYPE_603:		return("603");	case CPU_TYPE_604:		return("604");	case CPU_TYPE_603E:		return("603e");	case CPU_TYPE_603EV:		return("603ev");	case CPU_TYPE_750:		switch((cputype >> 8) & 0xff) {		case 0x00:		case 0x01:		case 0x02:		case 0x03:			return("750");		case 0x22:			return("750CX");		case 0x33:			return("750CXe");		case 0x31:		case 0x32:			return("755");		case 0x83:			return("750L");		default:			return("750??");	/* We don't really know... */		}	case CPU_TYPE_750FX:		return("750FX");	case CPU_TYPE_604E:		return("604e");	case CPU_TYPE_604EM:		return("604em");	case CPU_TYPE_7400:		return("7400");	case CPU_TYPE_7410:		return("7410");	default:		return("unknown");	}}/* *  Return the pipe-line freq. */intmd_getpipefreq(int busfreq){	int cputype;	int pipefreq = -1;	int i;static char ppc7400_pllratio[16] =	/* 0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15 */	{ 90, 75, 70,  1, 20, 65, 25, 45, 30, 55, 40, 50, 80, 60, 35, 0 };static char ppc750_pllratio[16] =	{  0, 75, 70,  1, 20, 65,100, 45, 30, 55, 40, 50, 80, 60, 35, 0 };	static char ppc750fx_pllratio[32] =	{  0,  0,  0,  0, 20, 25,  30, 35, 40, 45, 50, 55, 60, 65, 70, 75,	  80, 85, 90, 95,100,110,120,130,140, 150,160,170,180,190,200, 0 };		cputype = md_cputype();	GETHID1(i);		/* Get PLL info */ 	i = (i >> 28) & 0x0f;	switch((cputype >> 16) & 0xffff) {		case CPU_TYPE_601:		case CPU_TYPE_602:		case CPU_TYPE_603:		case CPU_TYPE_604:		case CPU_TYPE_603E:		case CPU_TYPE_603EV:		case CPU_TYPE_604E:		case CPU_TYPE_604EM:			break;		case CPU_TYPE_750:			pipefreq = (busfreq / 10) * ppc750_pllratio[i];			break;		case CPU_TYPE_750FX:			GETHID1(i);			i = (i >> 27) & 0x1f;			pipefreq = (busfreq / 10) * ppc750fx_pllratio[i];			break;		case CPU_TYPE_7400:		case CPU_TYPE_7410:			pipefreq = (busfreq / 10) * ppc7400_pllratio[i];			break;		default:			break;	}	return(pipefreq);}#if NMAINBUS > 0/* *  Microtime returns the time that have elapsed since last 'tick'. *  To be able to do that we use the decrementer to figure out *  how much time have elapsed. */voidmicrotime (tvp)	struct timeval *tvp;{static struct timeval lasttime;	unsigned long count;	long cycles;	*tvp = time;	/* work out how far we've progressed since the last "tick" */	count = get_count();	cycles = count - (_softcompare - clkpertick);	if (cycles >= 0)		tvp->tv_usec += cycles / clkperusec;	else		log(LOG_INFO, "microtime: cnt=%u cmp=%u\n", count, _softcompare);        	if (tvp->tv_usec >= 1000000) {		tvp->tv_sec += tvp->tv_usec / 1000000;		tvp->tv_usec %= 1000000;	}	if (tvp->tv_sec == lasttime.tv_sec &&	    tvp->tv_usec <= lasttime.tv_usec &&	    (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) {		tvp->tv_sec++;		tvp->tv_usec -= 1000000;	}	lasttime = *tvp;}voidstartrtclock(hz)	int hz;{	unsigned long freq;	freq = tgt_cpufreq () / 4;	/* TB ticker frequency */	/* get initial value of real time clock */	time.tv_sec = tgt_gettime ();	time.tv_usec = 0;	clkpertick = freq / hz;	clkperusec = freq / 1000000;	_softcompare = get_count() + clkpertick;	clkenable = 0;}voidenablertclock(){	clkenable = 1;}voidcpu_initclocks(){	printf("cpu_initclocks\n");}voidtgt_clkpoll (){	struct clockframe cframe;	unsigned long count;	long cycles, ticks;	if (!clkenable) {		return;	}	cframe.srr1 = 0;	cframe.srr0 = 0;	cframe.pri = 7;	cframe.depth = 0;	/* poll the free-running clock */	count = get_count ();	cycles = count - _softcompare;	if (cycles > 0) {		/* as we are polling, we could have missed a number of ticks */		ticks = (cycles / clkpertick) + 1;		_softcompare += ticks * clkpertick;	/* There is a race between reading count and setting compare	 * whereby we could set compare to a value "below" the new	 * clock value.  Check again to avoid an 80 sec. wait	 */			cycles = get_count() - _softcompare;			while (cycles > 0) {			_softcompare += clkpertick; ticks++;			cycles = get_count() - _softcompare;		}                while(ticks--) {			hardclock(&cframe);		}	}} #elsevoidtgt_clksetup(){	unsigned long freq;	freq = tgt_cpufreq () / 4;	/* TB ticker frequency */	clkperusec = freq / 1000000;}#endif /* NMAINBUS */voiddelay(int microseconds){	int total, start;	start = get_count();	total = microseconds * clkperusec;        while(total > (get_count() - start));}u_int __res_randomid(void);u_int__res_randomid(){extern int ticks;	return(ticks * get_count());	/* Just something... */}/* *  Handle an external interrupt dispatching it to registred handler. */voidextint_handler(){}voidflush_cache (type, adr)     int type;     void *adr;{    switch (type) {	case ICACHE:		flushicache((void *)0, memorysize);		break;	case DCACHE:		flushdcache((void *)0, memorysize);		break;	case IADDR:		syncicache((void *)((int)adr & ~3), 4);		break;	case ICACHE|DCACHE:		flushicache((void *)0, memorysize);		flushdcache((void *)0, memorysize);		break;    }}

⌨️ 快捷键说明

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