📄 tgt_machdep.c
字号:
/* $Id: tgt_machdep.c,v 1.12 2003/08/10 18:21:42 pefo Exp $ *//* * Copyright (c) 2002 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. * */#if 1#include <sys/param.h>#include <sys/syslog.h>#include <machine/endian.h>#include <sys/device.h>#include <machine/cpu.h>#include <machine/pio.h>#include <machine/intr.h>#include <dev/pci/pcivar.h>#endif#include <sys/types.h>#include <termio.h>#include <string.h>#include <time.h>#include <stdlib.h>#include <autoconf.h>#include <machine/cpu.h>#include <machine/pio.h>#include "pflash.h"#include "dev/pflash_tgt.h"#include "target/cp7000.h"#include "pmon/dev/gt64120reg.h"#include "include/m48t37.h"#include <pmon.h>#include <pmon/netio/netio.h>#include <pmon/dev/ns16550.h>#include "flash.h"#if (NMOD_FLASH_AMD + NMOD_FLASH_INTEL) == 0#ifdef HAVE_FLASH#undef HAVE_FLASH#endif#else#define HAVE_FLASH#endif#define TOD_REG(x) (clkbase + x)extern struct trapframe DBGREG;extern char _end[];extern void *memset __P((void *, int, size_t));extern char MipsException[], MipsExceptionEnd[];static int md_pipefreq = 0;static int md_cpufreq = 0;static int clk_invalid = 0;static int nvram_invalid = 0;static int cksum __P((void *p, size_t s, int set));ConfigEntry ConfigTable[] ={ { (char *)COM1_BASE_ADDR, 0, ns16550, 256, CONS_BAUD, NS16550HZ }, { (char *)COM2_BASE_ADDR, 0, ns16550, 256, CONS_BAUD, NS16550HZ }, { 0 }};unsigned long _filebase;static void _probe_frequencies __P((void));#if 0static int cksum __P((void *, size_t, int));#endifvoid initmips __P((u_int32_t, u_int32_t));void mapMemBank01 __P((u_int32_t, u_int32_t, u_int32_t, u_int32_t));void mapMemBank23 __P((u_int32_t, u_int32_t, u_int32_t, u_int32_t));voidinitmips(msize0, msize1) u_int32_t msize0, msize1;{ u_int32_t totalSize; u_int32_t b0Size, b1Size, b2Size, b3Size; totalSize = 0; /* * First set up memory mapping. PCI to localmem mapping * is set up in PCI init. */ if(msize0 != 0 || msize1 != 0) { b0Size = letoh32(msize0) * 1024 * 1024; b1Size = 0; b2Size = letoh32(msize1) * 1024 * 1024; b3Size = 0; /* If it's a total of 64MB then it's populated in one bank */ if (b0Size == (32*1024*1024)) { b2Size = 0; } mapMemBank01(0, b0Size, b0Size, b1Size); totalSize += b0Size + b1Size; mapMemBank23(totalSize, b2Size, totalSize + b2Size, b3Size); totalSize += b2Size + b3Size; } else { totalSize = 256*1024*1024; } totalmemsize = totalSize; /* * Remap Boot rom and CS3 to high memory */ GT_PAS_CS3BOOTLO = htole32((BOOT_BLOCK_START >> 21) & 0x7ff); GT_PAS_CS3BOOTHI = htole32((BOOT_BLOCK_END >> 21) & 0x7f); /* * Probe clock frequencys so delays will work properly. */ tgt_cpufreq(); /* * Init PMON and debug */ cpuinfotab[0] = &DBGREG; dbginit(NULL); /* * Set up exception vectors. */ bcopy(MipsException, (char *)TLB_MISS_EXC_VEC, MipsExceptionEnd - MipsException); bcopy(MipsException, (char *)GEN_EXC_VEC, MipsExceptionEnd - MipsException); CPU_FlushCache(); CPU_SetSR(0, SR_BOOT_EXC_VEC); SBD_DISPLAY ("LNCH", CHKPNT_AUTO); /* * Register initial memory map. */ register_mem((void *)0, (void *)totalmemsize-1, MEM_RAM, "SDRAM"); register_mem((void *)CACHED_TO_PHYS(memtop), kmemtop-1, MEM_DATA, "Kernel data"); register_mem((void *)0, (void *)CACHED_TO_PHYS(_end)-1, MEM_CODE, "PMON2000"); register_mem((void *)CACHED_TO_PHYS(_end), (void *)CACHED_TO_PHYS(heaptop)-1, MEM_DATA, "PMON2000 heap"); register_mem((void *)IO_BLOCK_START, (void *)IO_BLOCK_END, MEM_IO, "decoded space"); register_mem((void *)PLD_BASE_ADDR, (void *)PLD_BASE_ADDR+0x7fffff, MEM_IO, "fpga control"); register_mem((void *)NVRAM_BASE_ADDR, (void *)NVRAM_BASE_ADDR+0x7fffff, MEM_IO, "RTC and NVRAM"); register_mem((void *)COM_BASE_ADDRESS, (void *)COM_BASE_ADDRESS+0x1ff, MEM_IO, "NS16552"); register_mem((void *)GT64120_BASE, (void *)GT64120_BASE+65535, MEM_IO, "internal registers"); register_mem((void *)0xffc00000, (void *)0xffc7ffff, MEM_FLASH, "boot flash"); /* * Launch! */ pmon_main();}voidmapMemBank01(b0Base, b0Size, b1Base, b1Size) u_int32_t b0Base; u_int32_t b0Size; u_int32_t b1Base; u_int32_t b1Size;{ if(b0Size > 0 || b1Size > 0) { GT_PAS_RAS10LO = htole32((b0Base >> 21) & 0x7fff); GT_PAS_RAS10HI = htole32(((b0Base + b0Size + b1Size - 1) >> 21) & 0x7f); } else { GT_PAS_RAS10LO = htole32(0xff); GT_PAS_RAS10HI = htole32(0x00); /* No mem, disable RAS 0 & 1 */ } if(b1Size > 0) { GT_DDAS_RAS1LO = htole32((b1Base >> 20) & 0xff); GT_DDAS_RAS1HI = htole32(((b1Base + b1Size - 1) >> 20) & 0xff); } else { GT_DDAS_RAS1LO = htole32(0xff); GT_DDAS_RAS1HI = htole32(0x00); /* Disable RAS 1 */ } if(b0Size > 0) { GT_DDAS_RAS0LO = htole32((b0Base >> 20) & 0xff); GT_DDAS_RAS0HI = htole32(((b0Base + b0Size - 1) >> 20) & 0xff); } else { GT_DDAS_RAS0LO = htole32(0xff); GT_DDAS_RAS0HI = htole32(0x00); /* Disable RAS 0 */ }}voidmapMemBank23(b2Base, b2Size, b3Base, b3Size) u_int32_t b2Base; u_int32_t b2Size; u_int32_t b3Base; u_int32_t b3Size;{ if(b2Size > 0 || b3Size > 0) { GT_PAS_RAS32LO = htole32((b2Base >> 21) & 0x7fff); GT_PAS_RAS32HI = htole32(((b2Base + b2Size + b3Size - 1) >> 21) & 0x7f); } else { GT_PAS_RAS32LO = htole32(0xff); GT_PAS_RAS32HI = htole32(0x00); /* No mem, disable RAS 0 & 1 */ } if(b3Size > 0) { GT_DDAS_RAS3LO = htole32((b3Base >> 20) & 0xff); GT_DDAS_RAS3HI = htole32(((b3Base + b3Size - 1) >> 20) & 0xff); } else { GT_DDAS_RAS3LO = htole32(0xff); GT_DDAS_RAS3HI = htole32(0x00); /* Disable RAS 1 */ } if(b2Size > 0) { GT_DDAS_RAS2LO = htole32((b2Base >> 20) & 0xff); GT_DDAS_RAS2HI = htole32(((b2Base + b2Size - 1) >> 20) & 0xff); } else { GT_DDAS_RAS2LO = htole32(0xff); GT_DDAS_RAS2HI = htole32(0x00); /* Disable RAS 2 */ }}/* * Put all machine dependent initialization here. This call * is done after console has been initialized so it's safe * to output configuration and debug information with printf. */voidtgt_devconfig(){ _pci_devinit(1); /* PCI device initialization */ SBD_DISPLAY("adbc",CHKPNT_PCID); config_init(); configure();}voidtgt_devinit(){ /* * Gather info about and configure caches. */ if(getenv("ocache_off")) { CpuOnboardCacheOn = 0; } else { CpuOnboardCacheOn = 1; } if(getenv("ecache_off")) { CpuExternalCacheOn = 0; } else { CpuExternalCacheOn = 1; } CPU_ConfigCache(); register_mem((void *)0xc0000000, (void *)0xffffffff, MEM_IO, "GT64120"); _pci_businit(1); /* PCI bus initialization */}voidtgt_reboot(){ void (*longreach) __P((void)); int i; /* Reset reset cause */ out8(PLD_RSTAT, in8(PLD_RSTAT)); /* Enable watchdog one tick at 1/16th second */ out8(M48T37_BASE+7, 0x84); /* Then wait... */ for(i = 0; i < 200000000; i++); /* Unreliable but try this if watchdog fails... */ printf("Watchdog reboot failed!\n"); longreach = (void *)0xbfc00000; (*longreach)(); while(1);}/* * This function makes inital HW setup for debugger and * returns the apropriate setting for the status register. */register_ttgt_enable(int machtype){ /* XXX Do any HW specific setup */ return(SR_COP_1_BIT|SR_FR_32|SR_EXL);}/* * Target dependent version printout. * Printout available target version information. */voidtgt_cmd_vers(){ printf("Board revision level: %c.\n", in8(PLD_BAR) + 'A'); printf("PLD revision levels: %d.%d and %d.%d.\n", in8(PLD_ID1) >> 4, in8(PLD_ID1) & 15, in8(PLD_ID2) >> 4, in8(PLD_ID2) & 15);}static void_probe_frequencies(){#ifdef HAVE_TOD int i, timeout, cur, sec, cnt; int clkbase = M48T37_BASE;#endif SBD_DISPLAY ("FREQ", CHKPNT_FREQ); md_pipefreq = 300000000; /* Defaults */ md_cpufreq = 100000000; clk_invalid = 1;#ifdef HAVE_TOD /* * Check if clock is stopped and start it if it is. */ if(inb(TOD_REG(TOD_SECOND)) & TOD_SECOND_ST) { outb(TOD_REG(TOD_SECOND), inb(TOD_REG(TOD_SECOND)) & ~TOD_SECOND_ST); } else { clk_invalid = 0; } /* * Do the next twice for two reasons. First make sure we run from * cache. Second make sure synched on second update. (Pun intended!) */ for(i = 2; i != 0; i--) { cnt = CPU_GetCOUNT(); timeout = 100000000; outb(TOD_REG(TOD_CTRL), inb(TOD_REG(TOD_CTRL)) | TOD_CTRL_R); /* stop update */ sec = inb(TOD_REG(TOD_SECOND)) & 0x0f; outb(TOD_REG(TOD_CTRL), inb(TOD_REG(TOD_CTRL)) & ~TOD_CTRL_R); /* start update */ do { timeout--; outb(TOD_REG(TOD_CTRL), inb(TOD_REG(TOD_CTRL)) | TOD_CTRL_R); cur = inb(TOD_REG(TOD_SECOND)) & 0x0f; outb(TOD_REG(TOD_CTRL), inb(TOD_REG(TOD_CTRL)) & ~TOD_CTRL_R); } while(timeout != 0 && cur == sec); cnt = CPU_GetCOUNT() - cnt; if(timeout == 0) { clk_invalid = 1; return; /* Get out if clock is not running */ } } /* * Calculate the external bus clock frequency. */ md_pipefreq = cnt / 10000; md_pipefreq *= 20000; /* * Calculate the external frequency. */ i = 2 - ((CPU_GetCONFIG() >> 16) & 1); md_cpufreq = md_pipefreq * 2; md_cpufreq /= (((CPU_GetCONFIG() >> 28) & 7) + 2) * i;#endif /* HAVE_TOD */}/* * Returns the CPU pipelie clock frequency */inttgt_pipefreq(){ if(md_pipefreq == 0) { _probe_frequencies(); } return(md_pipefreq);}/* * Returns the external clock frequency, usually the bus clock */inttgt_cpufreq(){ if(md_cpufreq == 0) { _probe_frequencies(); } return(md_cpufreq);}#ifdef HAVE_TOD/* * Returns the current time if a TOD clock is present or 0 * This code is defunct after 2088... (out of bits) */#define FROMBCD(x) (((x) >> 4) * 10 + ((x) & 0xf))#define TOBCD(x) (((x) / 10 * 16) + ((x) % 10)) #define YEARDAYS(year) ((((year) % 4) == 0 && \ ((year % 100) != 0 || (year % 400) == 0)) ? 366 : 365)#define SECMIN (60) /* seconds per minute */#define SECHOUR (60*SECMIN) /* seconds per hour */#define SECDAY (24*SECHOUR) /* seconds per day */#define SECYR (365*SECDAY) /* seconds per common year */static const short dayyr[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };time_ttgt_gettime(){ struct tm tm; int clkbase = M48T37_BASE; int century; time_t t; if(clk_invalid) { tm.tm_sec = 0; tm.tm_min = 0; tm.tm_hour = 0; tm.tm_wday = 0; tm.tm_mday = 1; tm.tm_mon = 1; tm.tm_year = 0; } else { outb(TOD_REG(TOD_CTRL), inb(TOD_REG(TOD_CTRL)) | TOD_CTRL_R); tm.tm_sec = FROMBCD(inb(TOD_REG(TOD_SECOND))); tm.tm_min = FROMBCD(inb(TOD_REG(TOD_MINUTE))); tm.tm_hour = FROMBCD(inb(TOD_REG(TOD_HOUR))); tm.tm_wday = FROMBCD(inb(TOD_REG(TOD_DAY))); tm.tm_mday = FROMBCD(inb(TOD_REG(TOD_DATE))); tm.tm_mon = FROMBCD(inb(TOD_REG(TOD_MONTH))) - 1; tm.tm_year = FROMBCD(inb(TOD_REG(TOD_YEAR))); century = FROMBCD(inb(TOD_REG(TOD_CENTURY)));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -