📄 tgt_machdep.c
字号:
/* $Id: tgt_machdep.c,v 1.4 2002/11/16 18:01:36 pefo Exp $ *//* * Copyright (c) 2000-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. * */#include <sys/types.h>#include <stdio.h>#include <setjmp.h>#include <termio.h>#include <string.h>#include <time.h>#include <ctype.h>#include <sys/device.h>#include <dev/pci/pcivar.h>#include <machine/cpu.h>#include <machine/pio.h>#include <machine/inline_asm.h>#include <autoconf.h>#include "pflash.h"#include "dev/pflash_tgt.h"#include <pmon/dev/mpc107reg.h>#include "target/vg4.h"#include <pmon.h>#include <pmon/dev/ns16550.h>extern unsigned char hwethadr[6];static int md_pipefreq = 0;static int md_cpufreq = 0;static int clk_invalid = 0;static int nvram_invalid = 0;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 int clkread __P((int));static void clkwrite __P((int, int));static void _probe_frequencies __P((void));static int cksum __P((void *, size_t, int));static void nvram_enable __P((void));static void nvram_disable __P((void));voidtgt_logo(){}/* * 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(PSL_IR|PSL_DR|PSL_FP|PSL_RI|PSL_ME|PSL_FE_DFLT);}static voidnvram_enable(){ _pci_conf_write(0x9000, 0x44, _pci_conf_read(0x9000, 0x44) | 0x40000000);}static voidnvram_disable(){ _pci_conf_write(0x9000, 0x44, _pci_conf_read(0x9000, 0x44) & ~0x40000000);}voidtgt_rtinit(){}static intclkread(reg) int reg;{ outb(CLOCK_ADDR, reg); return(inb(CLOCK_DATA));}static voidclkwrite(reg, data) int reg; int data;{ outb(CLOCK_ADDR, reg); outb(CLOCK_DATA, data);}static void_probe_frequencies(){static char pllratio[16] = /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 *//*750***{ 0, 75, 70, 1, 20, 65, 100, 45, 30, 55, 40, 50, 80, 60, 35, 0 };*//*7400*/{ 90, 75, 70, 1, 20, 65, 25, 45, 30, 55, 40, 50, 80, 60, 35, 0 }; int i, timeout, sec, cur, cnt; SBD_DISPLAY ("FREQ", CHKPNT_FREQ); md_pipefreq = 200000000; /* Defaults */ md_cpufreq = 66000000; /* * Select correct clock frequency source and 24Hr mode, BCD. */ clkwrite(0x0a, (clkread(0x0a) & 0x70) | 0x20); clkwrite(0x0b, (clkread(0x0b) & 0x08) | 0x02); /* * 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 = get_count(); timeout = 10000000; sec = clkread(0); do { timeout--; cur = clkread(0); } while(timeout != 0 && cur == sec); cnt = get_count() - cnt; if(timeout == 0) { clk_invalid = 1; return; /* Get out if clock is not running */ } } /* * Calculate the external bus clock frequency. */ md_cpufreq = (cnt + 100000) / 100000; md_cpufreq *= 400000; /* * Calculate the cpu pipeline frequency. */ GETHID1(i); /* Get PLL info */ i = (i >> 28) & 0x0f; md_pipefreq = (md_cpufreq / 10) * pllratio[i];}/* * 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);}#define FROMBCD(x) (((x) >> 4) * 10 + ((x) & 0xf))#define TOBCD(x) (((x) / 10 * 16) + ((x) % 10)) time_ttgt_gettime(){ struct tm tm; time_t t; int trys = 1000000; /* Wait for end of update in progress */ while(trys-- > 0 && clkread(0x0a) & 0x80); tm.tm_sec = FROMBCD(clkread(0)); tm.tm_min = FROMBCD(clkread(2)); tm.tm_hour = FROMBCD(clkread(4)); tm.tm_wday = FROMBCD(clkread(6)); tm.tm_mday = FROMBCD(clkread(7)); tm.tm_mon = FROMBCD(clkread(8)) - 1; tm.tm_year = FROMBCD(clkread(9)); tm.tm_isdst = tm.tm_gmtoff = 0; if(tm.tm_year < 90) { tm.tm_year += 100; } t = gmmktime(&tm); return(t);}/* * Set the current time if a TOD clock is present */voidtgt_settime(time_t t){ struct tm *tm; tm = gmtime(&t); /* Enable register writing */ clkwrite(0xb, clkread(0x0b) | 0x80); clkwrite(9, TOBCD(tm->tm_year % 100)); clkwrite(8, TOBCD(tm->tm_mon + 1)); clkwrite(7, TOBCD(tm->tm_mday)); clkwrite(6, TOBCD(tm->tm_wday)); clkwrite(4, TOBCD(tm->tm_hour)); clkwrite(2, TOBCD(tm->tm_min)); clkwrite(0, TOBCD(tm->tm_sec)); /* Transfer new time to counters */ clkwrite(0xb, clkread(0x0b) & ~0x80);}/* * Print out any target specific memory information */voidtgt_memprint(){ if(tgt_gettime() == -1) { printf("\nWARN! Date invalid, use 'date' to set time!\n"); }}voidtgt_machprint(){ printf("BSP Copyright 2000-2002, SBS Technologies, Inc.\n"); printf("CPU PowerPC %s @", md_cpuname());} /* * Return a suitable address for the client stack. * Usually top of RAM memory. */register_ttgt_clienttos(){ return((memorysize & ~7) - 64);}/* * Flash programming support code. *//* * Table of flash devices on target. See pflash_tgt.h. */struct fl_map tgt_fl_map[] = { TARGET_FLASH_DEVICES};voidtgt_flashinit(){}struct fl_map *tgt_flashmap(){ return(tgt_fl_map);}voidtgt_flashwrite_disable(){}inttgt_flashwrite_enable(){ return(1);}inttgt_flashsetpageno(int page){ if(page < 0 || page > 7) { return(-1); } return(0);}voidtgt_flashinfo(void *p, size_t *t){ struct fl_map *map; map = fl_find_map(p); if(map) { *t = map->fl_map_size; } else { *t = 0; }}voidtgt_flashprogram(void *p, int size, void *s, int endian){ printf("Programming flash %p:%p into %p\n", s, size, p); if(fl_erase_device(p, size, TRUE)) { printf("Erase failed!\n"); return; } if(fl_program_device(p, s, size, TRUE)) { printf("Programming failed!\n"); } fl_verify_device(p, s, size, TRUE);}/* * Network stuff. */voidtgt_netinit(){}inttgt_ethaddr(char *p){ bcopy((void *)&hwethadr, p, 6); return(0);}voidtgt_netreset(){}/* * --- NVRAM handling code --- *//* * Special copy that does it bytewise, guaranteed! */static void bytecopy __P((char *, char *, size_t));staticvoid bytecopy(char *src, char *dst, size_t size){ if(src == NULL) { *dst = '\0'; } else if (dst >= src && dst < src + size) { src += size; dst += size; while (size--) { *--dst = *--src; } } else while (size--) { *dst++ = *src++; }}/* * Read in environment from NV-ram and set. */voidtgt_mapenv(int (*func) __P((char *, char *))){ char *ep; char env[256]; int i; /* * Check integrity of the NVRAM env area. If not in order * initialize it to empty. */ if(cksum((void *)NVRAM_FIRST_ENV, NVRAM_SIZE_ENV, 0) != 0 || memchr((void *)NVRAM_FIRST_ENV, 0, NVRAM_SIZE_ENV) == 0) { nvram_invalid = 1; SBD_DISPLAY ("ENVC", CHKPNT_MAPV); } else { ep = (char *)NVRAM_FIRST_ENV + 2; while(*ep != 0) { char *val = 0, *p = env; i = 0; while((*p++ = *ep++) != 0 && (ep < (char *)NVRAM_LAST_ENV) && i++ < 255) { if((*(p - 1) == '=') && (val == NULL)) { *(p - 1) = '\0'; val = p; } } if(ep < (char *)NVRAM_LAST_ENV && i < 255) { (*func)(env, val); } else { nvram_invalid = 2; break; } } SBD_DISPLAY ("ENVV", CHKPNT_MAPV); bytecopy((char *)NVRAM_VXWORKS, env, sizeof(env)); for(i = 0; isprint(env[i]) && i < 255; i++ ); env[i] = '\0'; (*func)("vxWorks", env); } sprintf(env, "%d", memorysize / (1024 * 1024)); (*func)("memsize", env); sprintf(env, "%d", md_pipefreq); (*func)("cpuclock", env); sprintf(env, "%d", md_cpufreq); (*func)("busclock", env); (*func)("systype", "vg4"); SBD_DISPLAY ("ENVM", CHKPNT_MAPV);}inttgt_unsetenv(char *name){ char *ep; char *np; char *sp; if(nvram_invalid) { return(0); } ep = (char *)NVRAM_FIRST_ENV + 2; nvram_enable(); while((*ep != '\0') && (ep < (char *)NVRAM_LAST_ENV)) { np = name; sp = ep; while((*ep == *np) && (*ep != '=') && (*np != '\0')) { ep++; np++; } if((*np == '\0') && ((*ep == '\0') || (*ep == '='))) { while(*ep++); while(ep <= (char *)NVRAM_LAST_ENV) { *sp++ = *ep++; } cksum((void *)NVRAM_FIRST_ENV, NVRAM_SIZE_ENV, 1); nvram_disable(); return(1); } else if(*ep != '\0') { while(*ep++ != '\0'); } } nvram_disable(); return(0);}inttgt_setenv(char *name, char *value){ char *ep; int envlen; /* Non permanent vars. */ if(strcmp(EXPERT, name) == 0) { return(1); } /* Calculate total env mem size requiered */ envlen = strlen(name); if(envlen == 0) { return(0); } if(value != NULL) { envlen += strlen(value); } envlen += 2; /* '=' + null byte */ if(envlen > 255) { return(0); /* Are you crazy!? */ } /* If NVRAM is found to be uninitialized, reinit it. */ if(nvram_invalid) { nvram_enable(); *(char *)(NVRAM_FIRST_ENV + 2) = '\0'; *(char *)(NVRAM_FIRST_ENV + 3) = '\0'; cksum((void *)NVRAM_FIRST_ENV, NVRAM_SIZE_ENV, 1); nvram_invalid = 0; bytecopy(NVRAM_VXWORKS_DEFAULT, (char *)NVRAM_VXWORKS, sizeof(NVRAM_VXWORKS_DEFAULT)); nvram_disable(); } if(strcmp("vxWorks", name) == 0) { nvram_enable(); bytecopy(value, (char *)NVRAM_VXWORKS, envlen); nvram_disable(); return(1); } /* Remove any current setting */ tgt_unsetenv(name); /* Find end of evironment strings */ ep = (char *)NVRAM_FIRST_ENV + 2; if(*ep != '\0') { do { while(*ep++ != '\0'); } while(*ep++ != '\0'); ep--; } if((NVRAM_LAST_ENV - (int)ep) < (envlen + 1)) { return(0); /* Bummer! */ } /* * Special case heaptop must always be first since it * can change how memory allocation works. */ nvram_enable(); if(strcmp("heaptop", name) == 0) { bytecopy((char *)NVRAM_FIRST_ENV + 2, (char *)NVRAM_FIRST_ENV + 2 + envlen, (int)ep - (NVRAM_FIRST_ENV + 1)); ep = (char *)NVRAM_FIRST_ENV + 2; while(*name != '\0') { *ep++ = *name++; } if(value != NULL) { *ep++ = '='; while((*ep++ = *value++) != '\0'); } else { *ep++ = '\0'; } } else { while(*name != '\0') { *ep++ = *name++; } if(value != NULL) { *ep++ = '='; while((*ep++ = *value++) != '\0'); } else { *ep++ = '\0'; } *ep++ = '\0'; /* End of env strings */ } cksum((void *)NVRAM_FIRST_ENV, NVRAM_SIZE_ENV, 1); nvram_disable(); return(1);}/* * Calculate checksum. If 'set' checksum is calculated and set. */static intcksum(void *p, size_t s, int set){ u_int16_t sum = 0; u_int8_t *sp = p; int sz = s / 2; if(set) { *sp = 0; /* Clear checksum */ *(sp+1) = 0; /* Clear checksum */ } while(sz--) { sum += (*sp++) << 8; sum += *sp++; } if(set) { sum = -sum; *(u_int8_t *)p = sum >> 8; *((u_int8_t *)p+1) = sum; } return(sum);}/* * Simple display function to display a 4 char string or code. * Called during startup to display progress on any feasible * display before any serial port have been initialized. */voidtgt_display(char *msg, int x){ /* Have simple serial port driver */ tgt_putchar(msg[0]); tgt_putchar(msg[1]); tgt_putchar(msg[2]); tgt_putchar(msg[3]); tgt_putchar('\r'); tgt_putchar('\n');}voidtgt_devconfig(){ _pci_devinit(1); /* PCI device initialization */ config_init(); configure();}voidtgt_devinit(){ _pci_businit(1); /* PCI bus initialization */}voidtgt_machreset(){ tgt_netreset();}voidtgt_reboot(){ outb(VG4_LOCKR, VG4_LOCKR_UNLOCK); outb(VG4_WCR, VG4_WCR_ENAB|VG4_WCR_SET); while(1);}voidclrhndlrs(){}inttgt_getmachtype(){ return(md_cputype());}/* * Create stubs if network is not compiled in */#ifdef INETvoidtgt_netpoll(){ splx(splhigh());}#elsegsignal(jmp_buf jb, int sig){ if(jb != NULL) { longjmp(jb, 1); }}netopen() { return -1;}netread() { return -1;}netwrite() { return -1;}netclose() { return -1;}netlseek() { return -1;}netioctl() { return -1;}void netpoll() {}unsigned long__time(){ return(tgt_gettime());}#endif /*INET*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -