📄 tgt_machdep.c
字号:
/* $Id: tgt_machdep.c,v 1.3 2003/06/13 09:00:48 pefo 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. * */#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 <dev/ic/ds15x1reg.h>#include <autoconf.h>#include <machine/cpu.h>#include <machine/pio.h>#include "pflash.h"#include "dev/pflash_tgt.h"#include "include/ev64240.h"#include <pmon/dev/gt64240reg.h>#include <pmon/dev/ns16550.h>#include <pmon.h>#include "mod_x86emu.h"extern void vga_bios_init(void);#include "flash.h"#if (NMOD_FLASH_AMD + NMOD_FLASH_INTEL) == 0#ifdef HAVE_FLASH#undef HAVE_FLASH#endif#else#define HAVE_FLASH#endifextern int boot_i2c_read(int addr);extern struct trapframe DBGREG;extern void *memset(void *, int, size_t);static int md_pipefreq = 0;static int md_cpufreq = 0;static int clk_invalid = 0;static int nvram_invalid = 0;static int cksum(void *p, size_t s, int set);static void _probe_frequencies(void);#ifndef NVRAM_IN_FLASHvoid nvram_get(char *);void nvram_put(char *);#endifConfigEntry 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;extern int memorysize;extern char MipsException[], MipsExceptionEnd[];unsigned char hwethadr[6];void initmips(void);voidinitmips(){ int m1size, m2size; int m1banks, m2banks; int lo0, lo1, hi0, hi1;SBD_DISPLAY ("MSIZ", CHKPNT_AUTO); if (boot_i2c_read(0x600) < 0) { m1size = 0; } else { m1banks = boot_i2c_read(0x605); m1size = boot_i2c_read(0x611); m1size *= boot_i2c_read(0x61f); m1size *= m1banks * 0x100000; } if (boot_i2c_read(0x400) < 0) { m2size = 0; } else { m2banks = boot_i2c_read(0x405); m2size = boot_i2c_read(0x411); m2size *= boot_i2c_read(0x41f); m2size *= m2banks * 0x100000; } memorysize = m1size + m2size; /* * Set up memory address decoders to map entire memory. * But first move away bootrom map to high memory. */ GT_WRITE(BOOTCS_LOW_DECODE_ADDRESS, BOOT_BASE >> 20); GT_WRITE(BOOTCS_HIGH_DECODE_ADDRESS, (BOOT_BASE + BOOT_SIZE - 1) >> 20); lo0 = lo1 = 0xfff; hi0 = hi1 = 0x000; if (m2size > 0) { lo0 = m1size >> 20; hi0 = (m1size + m2size - 1) >> 20; if (m2banks > 1) { hi1 = hi0; lo1 = (m1size + (m2size >> 1)) >> 20; hi0 = lo1 - 1; } } GT_WRITE(SCS_2_LOW_DECODE_ADDRESS, lo0); GT_WRITE(SCS_2_HIGH_DECODE_ADDRESS, hi0); GT_WRITE(SCS_3_LOW_DECODE_ADDRESS, lo1); GT_WRITE(SCS_3_HIGH_DECODE_ADDRESS, hi1); lo0 = lo1 = 0xfff; hi0 = hi1 = 0x000; if (m1size > 0) { lo0 = 0; hi0 = (m1size - 1) >> 20; if (m1banks > 1) { hi1 = hi0; lo1 = m1size >> 21; hi0 = lo1 - 1; } } GT_WRITE(SCS_0_LOW_DECODE_ADDRESS, lo0); GT_WRITE(SCS_0_HIGH_DECODE_ADDRESS, hi0); GT_WRITE(SCS_1_LOW_DECODE_ADDRESS, lo1); GT_WRITE(SCS_1_HIGH_DECODE_ADDRESS, hi1); /* * 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); /* * Launch! */ pmon_main();}/* * 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(){ /* Set the PHY addresses for the GT ethernet */ GT_WRITE(ETH_PHY_ADDR_REG, 0x18a4); GT_WRITE(MAIN_ROUTING_REGISTER, 0x007ffe38); GT_WRITE(SERIAL_PORT_MULTIPLEX, 0x00000102); /* Route Multi Purpose Pins */ GT_WRITE(MPP_CONTROL0, 0x43541717); GT_WRITE(MPP_CONTROL1, 0x44009911); GT_WRITE(MPP_CONTROL2, 0x40091818); GT_WRITE(MPP_CONTROL3, 0x00090066); _pci_devinit(1); /* PCI device initialization */ config_init(); configure();#if NMOD_X86EMU >= 0 vga_bios_init();#endif}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(); _pci_businit(1); /* PCI bus initialization */}voidtgt_reboot(){ void (*longreach) __P((void)); 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);}/* * Display any target specific logo. */voidtgt_logo(){ printf("\n"); printf("[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[\n"); printf("[[[ [[[[ [[[[[[[[[[ [[[[ [[[[ [[[[[[[ [[\n"); printf("[[ [[[[[[[[ [[[ [[[[[[[[ [[[ [[[[[[[[ [[[ [[[[[[ [[\n"); printf("[[ [[[[[[[[[[ [[[ [ [[[[[[ [ [[[ [[[[[[[[[[ [[[ [ [[[[[ [[\n"); printf("[[ [[[[[[[[[[ [[[ [[ [[[[ [[ [[[ [[[[[[[[[[ [[[ [[ [[[[ [[\n"); printf("[[ [[[[[[[[ [[[ [[[ [[ [[[ [[[ [[[[[[[[[[ [[[ [[[ [[[ [[\n"); printf("[[ [[[[ [[[[ [[[[ [[[ [[[[[[[[[[ [[[ [[[[ [[ [[\n"); printf("[[ [[[[[[[[[[[[[[[ [[[[[ [[[[[ [[[ [[[[[[[[[[ [[[ [[[[[ [ [[\n"); printf("[[ [[[[[[[[[[[[[[[ [[[[[[[[[[[[ [[[ [[[[[[[[[[ [[[ [[[[[[ [[\n"); printf("[[ [[[[[[[[[[[[[[[ [[[[[[[[[[[[ [[[ [[[[[[[[ [[[ [[[[[[[ [[\n"); printf("[[ [[[[[[[[[[[[[[[ [[[[[[[[[[[[ [[[[ [[[[ [[[[[[[[ [[\n"); printf("[[[[[[[2000][[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[\n"); }static void_probe_frequencies(){#ifdef HAVE_TOD int i, timeout, cur, sec, cnt;#endifextern void tgt_setpar100mhz __P((void)); 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. */ i = inb(RTC_BASE + DS_REG_CTLB); outb(RTC_BASE + DS_REG_CTLB, i | DS_CTLB_TE); i = inb(RTC_BASE + DS_REG_MONTH) & 0x3f; outb(RTC_BASE + DS_REG_MONTH, i | DS_MONTH_E32K); /* * 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 = 10000000; sec = inb(RTC_BASE + DS_REG_SEC); do { timeout--; cur = inb(RTC_BASE + DS_REG_SEC); } while(timeout != 0 && cur == sec); cnt = CPU_GetCOUNT() - cnt; if(timeout == 0) { break; /* Get out if clock is not running */ } } /* * Get PLL programming info. */ i = 2 - ((CPU_GetCONFIG() >> 16) & 1); /* Halfclock bit */ i = (((CPU_GetCONFIG() >> 28) & 7) + 2) * i; /* Multiplier */ /* * Calculate the external bus clock frequency. */ if (timeout != 0) { clk_invalid = 0; md_pipefreq = cnt / 10000; md_pipefreq *= 20000; md_cpufreq = (md_pipefreq * 2) / i; } else { md_pipefreq = (md_cpufreq * i) / 2; } /* * Hack to change timing of GT64240 if not 125Mhz FSB. */ if(md_cpufreq < 110000000) { tgt_setpar100mhz(); }#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 ctrlbsave; time_t t; if(!clk_invalid) { /* Freeze readout data regs */ ctrlbsave = inb(RTC_BASE + DS_REG_CTLB); outb(RTC_BASE + DS_REG_CTLB, ctrlbsave & ~DS_CTLB_TE); tm.tm_sec = FROMBCD(inb(RTC_BASE + DS_REG_SEC)); tm.tm_min = FROMBCD(inb(RTC_BASE + DS_REG_MIN)); tm.tm_hour = FROMBCD(inb(RTC_BASE + DS_REG_HOUR)); tm.tm_wday = FROMBCD(inb(RTC_BASE + DS_REG_WDAY)); tm.tm_mday = FROMBCD(inb(RTC_BASE + DS_REG_DATE)); tm.tm_mon = FROMBCD(inb(RTC_BASE + DS_REG_MONTH) & 0x1f) - 1; tm.tm_year = FROMBCD(inb(RTC_BASE + DS_REG_YEAR)); tm.tm_year += 100 * (FROMBCD(inb(RTC_BASE + DS_REG_CENT)) - 19); outb(RTC_BASE + DS_REG_CTLB, ctrlbsave | DS_CTLB_TE); tm.tm_isdst = tm.tm_gmtoff = 0; t = gmmktime(&tm); } else { t = 957960000; /* Wed May 10 14:00:00 2000 :-) */ } return(t);}/* * Set the current time if a TOD clock is present */voidtgt_settime(time_t t){ struct tm *tm; int ctrlbsave; if(!clk_invalid) { tm = gmtime(&t); /* Enable register writing */ ctrlbsave = inb(RTC_BASE + DS_REG_CTLB); outb(RTC_BASE + DS_REG_CTLB, ctrlbsave & ~DS_CTLB_TE); outb(RTC_BASE + DS_REG_CENT, TOBCD(tm->tm_year / 100 + 19)); outb(RTC_BASE + DS_REG_YEAR, TOBCD(tm->tm_year % 100)); outb(RTC_BASE + DS_REG_MONTH,TOBCD(tm->tm_mon + 1)); outb(RTC_BASE + DS_REG_DATE, TOBCD(tm->tm_mday)); outb(RTC_BASE + DS_REG_WDAY, TOBCD(tm->tm_wday)); outb(RTC_BASE + DS_REG_HOUR, TOBCD(tm->tm_hour)); outb(RTC_BASE + DS_REG_MIN, TOBCD(tm->tm_min)); outb(RTC_BASE + DS_REG_SEC, TOBCD(tm->tm_sec)); /* Transfer new time to counters */ outb(RTC_BASE + DS_REG_CTLB, ctrlbsave | DS_CTLB_TE); }}#elsetime_ttgt_gettime(){ return(957960000); /* Wed May 10 14:00:00 2000 :-) */}#endif /* HAVE_TOD *//* * Print out any target specific memory information */voidtgt_memprint(){ printf("Primary Instruction cache size %dkb (%d line, %d way)\n", CpuPrimaryInstCacheSize / 1024, CpuPrimaryInstCacheLSize, CpuNWayCache); printf("Primary Data cache size %dkb (%d line, %d way)\n", CpuPrimaryDataCacheSize / 1024, CpuPrimaryDataCacheLSize, CpuNWayCache); if(CpuSecondaryCacheSize != 0) { printf("Secondary cache size %dkb\n", CpuSecondaryCacheSize / 1024); } if(CpuTertiaryCacheSize != 0) { printf("Tertiary cache size %dkb\n", CpuTertiaryCacheSize / 1024); }}voidtgt_machprint(){ printf("Copyright 2000-2002, Opsycon AB, Sweden.\n"); printf("CPU %s @", md_cpuname());} /* * Return a suitable address for the client stack. * Usually top of RAM memory. */register_ttgt_clienttos(){ return((register_t)(int)PHYS_TO_UNCACHED(memorysize & ~7) - 64);}#ifdef HAVE_FLASH/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -