📄 tgt_machdep.c
字号:
/* $Id: tgt_machdep.c,v 1.7 2004/05/27 04:14:49 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. * */#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>#include <sys/types.h>#include <termio.h>#include <string.h>#include <time.h>#include <stdlib.h>#include <stdarg.h>#include <autoconf.h>#include <machine/cpu.h>#include <machine/pio.h>#include "pflash.h"#include "dev/pflash_tgt.h"#include <include/it8172.h>#include <include/rtc.h>#include <pmon/dev/ns16550.h>#include <pmon.h>#include <linux/io.h>#include "mod_x86emu.h"#include "mod_x86emu_int10.h"#include "mod_vgacon.h"extern void vga_bios_init(void);extern int kbd_initialize(void);extern int write_at_cursor(char val);extern const char *kbd_error_msgs[];#include "flash.h"#if (NMOD_FLASH_AMD + NMOD_FLASH_INTEL) == 0#ifdef HAVE_FLASH#undef HAVE_FLASH#endif#else#define HAVE_FLASH#endif#if NMOD_X86EMU_INT10 == 0int vga_available=0;#endifextern int boot_i2c_read(int addr);extern int sis6326_init(int fbaddress, int ioaddress);extern int gsim_vbe_init(int fbaddress, int ioaddress);extern int fb_init(void);extern struct trapframe DBGREG;extern void *memset(void *, int, size_t);int kbd_available;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 *);#endifextern int vgaterm(int op, struct DevEntry * dev, unsigned long param, int data);extern int fbterm(int op, struct DevEntry * dev, unsigned long param, int data);extern struct pci_device *vga_dev;ConfigEntry ConfigTable[] ={ { (char *)(KSEG1 + IT8172_PCI_IO_BASE + IT_UART_BASE), 0, ns16550, 256, CONS_BAUD, NS16550HZ }, { (char *)(KSEG1 + IT8172_PCI_IO_BASE + IT_UART_BASE), 0, ns16550, 256, CONS_BAUD, NS16550HZ },#if NMOD_VGACON > 0#ifndef CONFIG_VGA_CARD_SIS6326 { (char *)1, 0, vgaterm, 256, CONS_BAUD, NS16550HZ },#else { (char *)1, 0, fbterm, 256, CONS_BAUD, NS16550HZ },#endif#endif { 0 }};unsigned long _filebase;extern int memorysize;extern int memorysize_high;extern char MipsException[], MipsExceptionEnd[];unsigned char hwethadr[6];int fb_available = 0;unsigned long fbaddress = 0;unsigned long ioaddress = 0;void initmips(unsigned int memsz);void addr_tst1(void);void addr_tst2(void);void movinv1(int iter, ulong p1, ulong p2);void test_regs(void);voidflash_gpio (int code){ *((volatile unsigned short *)0xb4013802) = 0x0550; *((volatile unsigned char *)0xb4013800) = (code & 0xf) << 2;}voidinitmips(unsigned int memsz){ memorysize = memsz; /* * Init PMON and debug */ cpuinfotab[0] = &DBGREG; dbginit(NULL); tgt_cpufreq(); /* * Set up exception vectors. */ SBD_DISPLAY("BEV1",0); 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("BEV0",0); printf("BEV in SR set to zero.\n");#if 0 /* memtest */ addr_tst1(); addr_tst2(); movinv1(2,0,~0); movinv1(2,0xaa5555aa,~0xaa5555aa); printf("memtest done\n");#endif /* * Launch! */ main(); }/* * serial printf */voidtgt_puts(char *buf){ char *p; for (p = buf; *p != '\0'; p++) tgt_putchar(*p);}inttgt_printf(const char *fmt, ...){ int len; va_list ap; char buf[200]; va_start(ap,fmt); len = vsprintf(buf, fmt, ap); tgt_puts(buf); va_end(ap); return (len);}/* * 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. *//*** LPC ***/// MB PnP configuration register#define LPC_KEY_ADDR 0x2E#define LPC_DATA_ADDR 0x2F// Device LDN#define LDN_SERIAL1 0x01 #define LDN_SERIAL2 0x02#define LDN_PARALLEL 0x03 #define LDN_KEYBOARD 0x05#define LDN_MOUSE 0x06static void LPCEnterMBPnP(void){ int i; unsigned char key[4] = {0x87, 0x01, 0x55, 0x55}; for (i = 0; i<4; i++) linux_outb(key[i], LPC_KEY_ADDR);}static void LPCExitMBPnP(void){ linux_outb(0x02, LPC_KEY_ADDR); linux_outb(0x02, LPC_DATA_ADDR);}static void LPCSetConfig(char LdnNumber, char Index, char data){ LPCEnterMBPnP(); // Enter IT8712 MB PnP mode linux_outb(0x07, LPC_KEY_ADDR); linux_outb(LdnNumber, LPC_DATA_ADDR); linux_outb(Index, LPC_KEY_ADDR); linux_outb(data, LPC_DATA_ADDR); LPCExitMBPnP();}static char LPCGetConfig(char LdnNumber, char Index){ char rtn; LPCEnterMBPnP(); // Enter IT8712 MB PnP mode linux_outb(0x07, LPC_KEY_ADDR); linux_outb(LdnNumber, LPC_DATA_ADDR); linux_outb(Index, LPC_KEY_ADDR); rtn = linux_inb(LPC_DATA_ADDR); LPCExitMBPnP(); return rtn;}static int SearchIT8712(void){ unsigned char Id1, Id2; unsigned short Id; LPCEnterMBPnP(); linux_outb(0x20, LPC_KEY_ADDR); /* chip id byte 1 */ Id1 = linux_inb(LPC_DATA_ADDR); linux_outb(0x21, LPC_KEY_ADDR); /* chip id byte 2 */ Id2 = linux_inb(LPC_DATA_ADDR); Id = (Id1 << 8) | Id2; LPCExitMBPnP(); if (Id == 0x8712) return 1; else return 0;}static void InitLPCInterface(void){ unsigned char bus, dev_fn; unsigned long data; bus = 0; dev_fn = 1<<3 | 4; /* pci cmd, SERR# Enable */ IT_WRITE(IT_CONFADDR, (bus << IT_BUSNUM_SHF) | (dev_fn << IT_FUNCNUM_SHF) | ((0x4 / 4) << IT_REGNUM_SHF)); IT_READ(IT_CONFDATA, data); data |= 0x0100; IT_WRITE(IT_CONFADDR, (bus << IT_BUSNUM_SHF) | (dev_fn << IT_FUNCNUM_SHF) | ((0x4 / 4) << IT_REGNUM_SHF)); IT_WRITE(IT_CONFDATA, data); /* setup serial irq control register */ IT_WRITE(IT_CONFADDR, (bus << IT_BUSNUM_SHF) | (dev_fn << IT_FUNCNUM_SHF) | ((0x48 / 4) << IT_REGNUM_SHF)); IT_READ(IT_CONFDATA, data); data = (data & 0xffff00ff) | 0xc400; IT_WRITE(IT_CONFADDR, (bus << IT_BUSNUM_SHF) | (dev_fn << IT_FUNCNUM_SHF) | ((0x48 / 4) << IT_REGNUM_SHF)); IT_WRITE(IT_CONFDATA, data); /* Enable I/O Space Subtractive Decode */ /* default 0x4C is 0x3f220000 */ IT_WRITE(IT_CONFADDR, (bus << IT_BUSNUM_SHF) | (dev_fn << IT_FUNCNUM_SHF) | ((0x4C / 4) << IT_REGNUM_SHF)); IT_WRITE(IT_CONFDATA, 0x3f2200f3);}/* * According to the ITE Special BIOS Note for waking up the * keyboard controller... */static int init_8712_keyboard(void){ unsigned int cmd_port = 0x64; unsigned int data_port = 0x60; unsigned char data; int i; linux_outb(0xaa, cmd_port); /* send self-test cmd */ i = 0; while (!(linux_inb(cmd_port) & 0x1)) { /* wait output buffer full */ i++; if (i > 0xffffff) return 0; } data = linux_inb(data_port); linux_outb(0xcb, cmd_port); /* set ps2 mode */ while (linux_inb(cmd_port) & 0x2) { /* wait while input buffer full */ i++; if (i > 0xffffff) return 0; } linux_outb(0x01, data_port); while (linux_inb(cmd_port) & 0x2) { /* wait while input buffer full */ i++; if (i > 0xffffff) return 0; } linux_outb(0x60, cmd_port); /* write 8042 command byte */ while (linux_inb(cmd_port) & 0x2) { /* wait while input buffer full */ i++; if (i > 0xffffff) return 0; } linux_outb(0x45, data_port); /* at interface, keyboard enabled, system flag */ while (linux_inb(cmd_port) & 0x2) { /* wait while input buffer full */ i++; if (i > 0xffffff) return 0; } linux_outb(0xae, cmd_port); /* enable interface */ return 1;}static int init_8712(void){ printf("8712 initializing..\n"); InitLPCInterface(); printf("LPC initialized\n"); if (!SearchIT8712()) { printf("8712 not found!\n"); return 0; } // enable IT8712 serial port LPCSetConfig(LDN_SERIAL1, 0x30, 0x01); /* enable */ LPCSetConfig(LDN_SERIAL1, 0x23, 0x01); /* clock selection */ if (!init_8712_keyboard()) { printf("Unable to initialize keyboard!\n"); return 0; } LPCSetConfig(LDN_KEYBOARD, 0x30, 0x1); LPCSetConfig(LDN_KEYBOARD, 0xf0, 0x2); LPCSetConfig(LDN_KEYBOARD, 0x71, 0x3); LPCSetConfig(LDN_MOUSE, 0x30, 0x1); /* enable mouse */ if ((LPCGetConfig(LDN_KEYBOARD, 0x30) == 0) || (LPCGetConfig(LDN_MOUSE, 0x30) == 0)) printf("Error: keyboard or mouse not enabled\n"); return 1;}voidtgt_devconfig(){#if NMOD_VGACON >0 int rc;#endif /* put IDE controller to normal mode * * FIXME: a bit late, pci scan won't find and configure ide interfaces. * but if we put this into starto or initmips, we will have to change * ide interface setting(pci conf space) to make base regs writable * at that time. */ *((volatile unsigned short *)0xb4015800) &= ~0x200; _pci_devinit(1); /* PCI device initialization */ SBD_DISPLAY("VGAI", 0);#if (NMOD_X86EMU_INT10 > 0) || (NMOD_X86EMU >0) vga_bios_init();#endif#ifdef CONFIG_VGA_CARD_SIS6326 if (vga_dev != NULL) { SBD_DISPLAY("FRBI", 0); fbaddress =_pci_conf_read(vga_dev->pa.pa_tag,0x10); ioaddress =_pci_conf_read(vga_dev->pa.pa_tag,0x18); fbaddress = fbaddress &0xffffff00; //laster 8 bit ioaddress = ioaddress &0xfffffff0; //laster 4 bit sis6326_init(fbaddress, ioaddress); fb_init(); fb_available=1; } else { /* hack: for gsim */ fbaddress = 0x12000000; ioaddress = 0x1cc; gsim_vbe_init(fbaddress,ioaddress); fb_init(); fb_available=1; }#endif config_init(); configure();#if NMOD_VGACON >0 init_8712(); rc=kbd_initialize(); printf("%s\n",kbd_error_msgs[rc]); if(!rc){ kbd_available=1; }#endif}#define tgt_putchar_uc(x) (*(void (*)(char)) (((long)tgt_putchar)|0x20000000)) (x)#ifdef DEEP_DEBUGvoid tgt_test_memory(void){ register unsigned i,j; register volatile char * volatile cmem; register volatile unsigned * volatile imem; register volatile unsigned * volatile imem_uc; // long long * volatile imem; printf("%s:%d executing...\n",__FUNCTION__,__LINE__); j = 0; for (i=0;i<100000;i++) { i++; } tgt_putchar('1'); if (i!=j) { tgt_putchar('2'); } else { tgt_putchar('('); } cmem = (char*)0x80400000L; imem = (unsigned *)0x80400000L; imem_uc = (unsigned *)0xa0400000L; for (i=0;i<64*1024/sizeof(*cmem);i++) { cmem[i] = 0x5a; if (cmem[i]!=0x5a) { tgt_putchar('4'); }else{ //tgt_putchar('3'); } } puts("char access test passed"); for (i=0;i<64*1024/sizeof(*imem);i++) { imem[i] = 0xaa55aa55; if (imem[i]!=0xaa55aa55) { tgt_putchar('6'); }else{ //tgt_putchar('5'); } } puts("word access test passed"); printf("executing...\n"); for (i=0,j=0x87654321;i<64*1024/sizeof(*imem);i++,j+=0x01010101) { imem[i] = j; if (imem[i] != j) printf("error1(imem[i]=0x%x,j=0x%x.\n", imem[i],j); } CPU_FlushDCache((int)imem, 64*1024); for (i=0,j=0x87654321;i<64*1024/sizeof(*imem);i++,j+=0x01010101) { if (imem_uc[i] != j) printf("%s:%d error(imem_uc[i]=0x%x,j=0x%x.\n", __FUNCTION__,__LINE__,imem_uc[i],j); } for (i=0,j=0x87654321;i<64*1024/sizeof(*imem);i++,j+=0x01010101) { if (imem[i] != j) printf("%s:%d error(imem[i]=0x%x,j=0x%x.\n", __FUNCTION__,__LINE__,imem[i],j); } printf("%s:%d executing...\n",__FUNCTION__,__LINE__); for (i=0,j=0x12345678;i<64*1024/sizeof(*imem);i++,j+=0x01010101) { imem_uc[i] = j; if (imem_uc[i] != j) printf("%s:%d error(imem_uc[i]=0x%x,j=0x%x.\n", __FUNCTION__,__LINE__,imem_uc[i],j); } CPU_HitInvalidateDCache((int)imem, 64*1024); for (i=0,j=0x12345678;i<64*1024/sizeof(*imem);i++,j+=0x01010101) { if (imem[i] != j) printf("%s:%d error(imem[i]=0x%x,j=0x%x.\n", __FUNCTION__,__LINE__,imem[i],j); } for (i=0,j=0x12345678;i<64*1024/sizeof(*imem);i++,j+=0x01010101) { if (imem_uc[i] != j) printf("%s:%d error(imem_uc[i]=0x%x,j=0x%x.\n", __FUNCTION__,__LINE__,imem_uc[i],j); }}#endifvoidtgt_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; } SBD_DISPLAY("CACH",0); CPU_ConfigCache(); SBD_DISPLAY("CAC2",0); SBD_DISPLAY("CAC3",0); _pci_businit(1); /* PCI bus initialization */}voidtgt_reboot(){ void (*longreach) __P((void)); 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(){#if 0 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);#endif}/* * 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"); }#define IT8172_RTC_ADR_REG (IT8172_PCI_IO_BASE + IT_RTC_BASE)#define IT8172_RTC_DAT_REG (IT8172_RTC_ADR_REG + 1)/* Local Variables */static volatile char *rtc_adr_reg = (volatile char*) KSEG1ADDR((volatile char *)IT8172_RTC_ADR_REG);static volatile char *rtc_dat_reg = (volatile char*) KSEG1ADDR((volatile char *)IT8172_RTC_DAT_REG); static inline unsigned char CMOS_READ (unsigned char addr){ unsigned char retval; *rtc_adr_reg = addr; retval = *rtc_dat_reg; return retval;}voidCMOS_WRITE (unsigned char data, unsigned char addr){ *rtc_adr_reg = addr; *rtc_dat_reg = data;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -