Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

814 lines (724 sloc) 20.068 kB
/*
* Milkymist VJ SoC (Software)
* Copyright (C) 2007, 2008, 2009, 2010, 2011 Sebastien Bourdeauducq
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <console.h>
#include <string.h>
#include <uart.h>
#include <blockdev.h>
#include <fatfs.h>
#include <crc.h>
#include <system.h>
#include <board.h>
#include <irq.h>
#include <version.h>
#include <net/mdio.h>
#include <hw/fmlbrg.h>
#include <hw/sysctl.h>
#include <hw/gpio.h>
#include <hw/flash.h>
#include <hw/minimac.h>
#include <hal/vga.h>
#include <hal/tmu.h>
#include <hal/brd.h>
#include <hal/usb.h>
#include <hal/ukb.h>
#include "boot.h"
#include "splash.h"
enum {
CSR_IE = 1, CSR_IM, CSR_IP, CSR_ICC, CSR_DCC, CSR_CC, CSR_CFG, CSR_EBA,
CSR_DC, CSR_DEBA, CSR_JTX, CSR_JRX, CSR_BP0, CSR_BP1, CSR_BP2, CSR_BP3,
CSR_WP0, CSR_WP1, CSR_WP2, CSR_WP3,
};
/* namuru registers */
/* CH0 */
#define CH0_PRN_KEY (0xa0000000)
#define CH0_CARRIER_NCO (0xa0000004)
#define CH0_CODE_NCO (0xa0000008)
#define CH0_CODE_SLEW (0xa000000c)
#define CH0_I_EARLY (0xa0000010)
#define CH0_Q_EARLY (0xa0000014)
#define CH0_I_PROMPT (0xa0000018)
#define CH0_Q_PROMPT (0xa000001c)
#define CH0_I_LATE (0xa0000020)
#define CH0_Q_LATE (0xa0000024)
#define CH0_CARRIER_MEASUREMENT (0xa0000028)
#define CH0_CODE_MEASUREMENT (0xa000002c)
#define CH0_EPOCH (0xa0000030)
#define CH0_EPOCH_CHECK (0xa0000034)
#define CH0_EPOCH_LOAD (0xa0000038)
#define CH0_ENABLES (0xa000003c)
/* Status */
#define STATUS (0xa0000380)
#define NEW_DATA (0xa0000384)
#define TIC_COUNT (0xa0000388)
#define ACCUM_COUNT (0xa000038c)
#define CLEAR_STATUS (0xa0000390)
#define HW_ID (0xa00003bc)
/* Control */
#define RESET (0xa00003c0)
#define PROG_TIC (0xa00003c4)
#define PROG_ACCUM_INT (0xa00003c8)
#define TEMP (0xa00003cc)
/* PRN Codes */
const int prn_code[38] =
{ 0, 0x3f6, 0x3ec, 0x3d8, 0x3b0, 0x04b, 0x096, 0x2cb, 0x196, 0x32c,
0x3ba, 0x374, 0x1d0, 0x3a0, 0x340, 0x280, 0x100, 0x113, 0x226,
0x04c, 0x098, 0x130, 0x260, 0x267, 0x338, 0x270, 0x0e0, 0x1c0,
0x380, 0x22b, 0x056, 0x0ac, 0x158, 0x2b0, 0x058, 0x18b, 0x316, 0x058
};
/* MMIO */
#define MM_READ(reg) (*((volatile unsigned int *)(reg)))
#define MM_WRITE(reg, val) *((volatile unsigned int *)(reg)) = val
/* General address space functions */
#define NUMBER_OF_BYTES_ON_A_LINE 16
static void dump_bytes(unsigned int *ptr, int count, unsigned addr)
{
char *data = (char *)ptr;
int line_bytes = 0, i = 0;
putsnonl("Memory dump:");
while(count > 0){
line_bytes =
(count > NUMBER_OF_BYTES_ON_A_LINE)?
NUMBER_OF_BYTES_ON_A_LINE : count;
printf("\n0x%08x ", addr);
for(i=0;i<line_bytes;i++)
printf("%02x ", *(unsigned char *)(data+i));
for(;i<NUMBER_OF_BYTES_ON_A_LINE;i++)
printf(" ");
printf(" ");
for(i=0;i<line_bytes;i++) {
if((*(data+i) < 0x20) || (*(data+i) > 0x7e))
printf(".");
else
printf("%c", *(data+i));
}
for(;i<NUMBER_OF_BYTES_ON_A_LINE;i++)
printf(" ");
data += (char)line_bytes;
count -= line_bytes;
addr += line_bytes;
}
printf("\n");
}
static void memtest1()
{
volatile unsigned int *count_addr = (volatile unsigned int *)0xa00003cc;
int i;
int j;
int errors = 0;
int pass = 0;
puts("Start \n");
unsigned int buf[100000];
for (i = 0; i != 100; i++)
for (j = 0; j != sizeof(buf); j++) {
*count_addr = buf[j];
if( *count_addr != buf[j]){
// printf("E. %u", *count_addr);
errors++;
}
pass++;
}
printf("Errors: %u \n", errors);
printf("Passed: %u \n", pass);
puts("Done \n");
}
static void namuruinit()
{
char *c;
printf("\n");
printf("Initializing Correlator: \n");
/* prog tic*/
MM_WRITE(PROG_TIC,0x18ffff);
printf("Prog TIC\n");
/* prog accum int*/
MM_WRITE(PROG_ACCUM_INT,0x1fff);
printf("Accum TIC\n");
/* prn */
MM_WRITE(CH0_PRN_KEY,0x300);
printf("CH0 PRN Key \n");
/* carrier nco */
MM_WRITE(CH0_CARRIER_NCO,0x9f0000);
printf("Carrier NCO\n");
/* code nco */
MM_WRITE(CH0_CODE_NCO,0x3ff00);
printf("CH0 Code NCO\n");
/* code slew */
MM_WRITE(CH0_CODE_SLEW,0x400); // this will be based upon a variable
printf("CH0 Code SLEW\n");
/* logic enable */
MM_WRITE(CH0_ENABLES,0xff);
printf("CH0 LOGIC ENABLED\n");
/* epoch load */
MM_WRITE(CH0_EPOCH_LOAD,0xff);
printf("CH0 Epoch Load\n");
printf("Done\n");
}
static void namurumeasure()
{
char *c;
while(1)
{
MM_WRITE(CLEAR_STATUS,0x0f);
if(readchar_nonblock())
{
c = readchar();
if(c == 'q')
break;
}
}
printf("Bye\n");
}
static void namuruaccum()
{
char *c;
printf("Accumulators: \n");
printf("I_E\tQ_E\tI_P\tQ_P\tI_L\tQ_L\n");
/* missing polling accum int pin */
while(1)
{
printf("%02d\t%02d\t%02d\t%02d\t%02d\t%02d\n",(MM_READ(CH0_I_EARLY)),(MM_READ(CH0_Q_EARLY)),(MM_READ(CH0_I_PROMPT)),(MM_READ(CH0_Q_PROMPT)),(MM_READ(CH0_I_LATE)),(MM_READ(CH0_Q_LATE)));
MM_WRITE(CLEAR_STATUS,0x0f);
MM_WRITE(CH0_ENABLES,0xff);
if(readchar_nonblock())
{
c = readchar();
if(c == 'q')
break;
}
}
printf("\n");
}
static void namurustatus()
{
char *c;
printf("\n");
printf("Status: \n");
printf("TIC_COUNT\tACCUM_COUNT\tCARRIER_MEASURE\tCODE_MEASURE\tSTATUS\tNEW_DATA\n");
while(1)
{
printf("%02d\t\t%02d\t\t%02d\t\t%02d\t\t%02d\t\t%02d\n",(MM_READ(TIC_COUNT)),(MM_READ(ACCUM_COUNT)),(MM_READ(CH0_CARRIER_MEASUREMENT)),(MM_READ(CH0_CODE_MEASUREMENT)),(MM_READ(STATUS)),(MM_READ(NEW_DATA)));
MM_WRITE(CLEAR_STATUS,0x0f);
MM_WRITE(CH0_ENABLES,0xff);
if(readchar_nonblock())
{
c = readchar();
if(c == 'q')
break;
}
}
MM_WRITE(STATUS,0x0); //clear status_read flag
printf("\n");
}
static void mr(char *startaddr, char *len)
{
char *c;
unsigned int *addr;
unsigned int length;
if(*startaddr == 0) {
printf("mr <address> [length]\n");
return;
}
addr = (unsigned *)strtoul(startaddr, &c, 0);
if(*c != 0) {
printf("incorrect address\n");
return;
}
if(*len == 0) {
length = 1;
} else {
length = strtoul(len, &c, 0);
if(*c != 0) {
printf("incorrect length\n");
return;
}
}
dump_bytes(addr, length, (unsigned)addr);
}
static void mw(char *addr, char *value, char *count)
{
char *c;
unsigned int *addr2;
unsigned int value2;
unsigned int count2;
unsigned int i;
if((*addr == 0) || (*value == 0)) {
printf("mw <address> <value> [count]\n");
return;
}
addr2 = (unsigned int *)strtoul(addr, &c, 0);
if(*c != 0) {
printf("incorrect address\n");
return;
}
value2 = strtoul(value, &c, 0);
if(*c != 0) {
printf("incorrect value\n");
return;
}
if(*count == 0) {
count2 = 1;
} else {
count2 = strtoul(count, &c, 0);
if(*c != 0) {
printf("incorrect count\n");
return;
}
}
for (i=0;i<count2;i++) *addr2++ = value2;
}
static void mc(char *dstaddr, char *srcaddr, char *count)
{
char *c;
unsigned int *dstaddr2;
unsigned int *srcaddr2;
unsigned int count2;
unsigned int i;
if((*dstaddr == 0) || (*srcaddr == 0)) {
printf("mc <dst> <src> [count]\n");
return;
}
dstaddr2 = (unsigned int *)strtoul(dstaddr, &c, 0);
if(*c != 0) {
printf("incorrect destination address\n");
return;
}
srcaddr2 = (unsigned int *)strtoul(srcaddr, &c, 0);
if(*c != 0) {
printf("incorrect source address\n");
return;
}
if(*count == 0) {
count2 = 1;
} else {
count2 = strtoul(count, &c, 0);
if(*c != 0) {
printf("incorrect count\n");
return;
}
}
for (i=0;i<count2;i++) *dstaddr2++ = *srcaddr2++;
}
static void crc(char *startaddr, char *len)
{
char *c;
char *addr;
unsigned int length;
if((*startaddr == 0)||(*len == 0)) {
printf("crc <address> <length>\n");
return;
}
addr = (char *)strtoul(startaddr, &c, 0);
if(*c != 0) {
printf("incorrect address\n");
return;
}
length = strtoul(len, &c, 0);
if(*c != 0) {
printf("incorrect length\n");
return;
}
printf("CRC32: %08x\n", crc32((unsigned char *)addr, length));
}
/* processor registers */
static int parse_csr(const char *csr)
{
if(!strcmp(csr, "ie")) return CSR_IE;
if(!strcmp(csr, "im")) return CSR_IM;
if(!strcmp(csr, "ip")) return CSR_IP;
if(!strcmp(csr, "icc")) return CSR_ICC;
if(!strcmp(csr, "dcc")) return CSR_DCC;
if(!strcmp(csr, "cc")) return CSR_CC;
if(!strcmp(csr, "cfg")) return CSR_CFG;
if(!strcmp(csr, "eba")) return CSR_EBA;
if(!strcmp(csr, "dc")) return CSR_DC;
if(!strcmp(csr, "deba")) return CSR_DEBA;
if(!strcmp(csr, "jtx")) return CSR_JTX;
if(!strcmp(csr, "jrx")) return CSR_JRX;
if(!strcmp(csr, "bp0")) return CSR_BP0;
if(!strcmp(csr, "bp1")) return CSR_BP1;
if(!strcmp(csr, "bp2")) return CSR_BP2;
if(!strcmp(csr, "bp3")) return CSR_BP3;
if(!strcmp(csr, "wp0")) return CSR_WP0;
if(!strcmp(csr, "wp1")) return CSR_WP1;
if(!strcmp(csr, "wp2")) return CSR_WP2;
if(!strcmp(csr, "wp3")) return CSR_WP3;
return 0;
}
static void rcsr(char *csr)
{
unsigned int csr2;
register unsigned int value;
if(*csr == 0) {
printf("rcsr <csr>\n");
return;
}
csr2 = parse_csr(csr);
if(csr2 == 0) {
printf("incorrect csr\n");
return;
}
switch(csr2) {
case CSR_IE: asm volatile ("rcsr %0,ie":"=r"(value)); break;
case CSR_IM: asm volatile ("rcsr %0,im":"=r"(value)); break;
case CSR_IP: asm volatile ("rcsr %0,ip":"=r"(value)); break;
case CSR_CC: asm volatile ("rcsr %0,cc":"=r"(value)); break;
case CSR_CFG: asm volatile ("rcsr %0,cfg":"=r"(value)); break;
case CSR_EBA: asm volatile ("rcsr %0,eba":"=r"(value)); break;
case CSR_DEBA: asm volatile ("rcsr %0,deba":"=r"(value)); break;
case CSR_JTX: asm volatile ("rcsr %0,jtx":"=r"(value)); break;
case CSR_JRX: asm volatile ("rcsr %0,jrx":"=r"(value)); break;
default: printf("csr write only\n"); return;
}
printf("%08x\n", value);
}
static void wcsr(char *csr, char *value)
{
char *c;
unsigned int csr2;
register unsigned int value2;
if((*csr == 0) || (*value == 0)) {
printf("wcsr <csr> <address>\n");
return;
}
csr2 = parse_csr(csr);
if(csr2 == 0) {
printf("incorrect csr\n");
return;
}
value2 = strtoul(value, &c, 0);
if(*c != 0) {
printf("incorrect value\n");
return;
}
switch(csr2) {
case CSR_IE: asm volatile ("wcsr ie,%0"::"r"(value2)); break;
case CSR_IM: asm volatile ("wcsr im,%0"::"r"(value2)); break;
case CSR_ICC: asm volatile ("wcsr icc,%0"::"r"(value2)); break;
case CSR_DCC: asm volatile ("wcsr dcc,%0"::"r"(value2)); break;
case CSR_EBA: asm volatile ("wcsr eba,%0"::"r"(value2)); break;
case CSR_DC: asm volatile ("wcsr dcc,%0"::"r"(value2)); break;
case CSR_DEBA: asm volatile ("wcsr deba,%0"::"r"(value2)); break;
case CSR_JTX: asm volatile ("wcsr jtx,%0"::"r"(value2)); break;
case CSR_JRX: asm volatile ("wcsr jrx,%0"::"r"(value2)); break;
case CSR_BP0: asm volatile ("wcsr bp0,%0"::"r"(value2)); break;
case CSR_BP1: asm volatile ("wcsr bp1,%0"::"r"(value2)); break;
case CSR_BP2: asm volatile ("wcsr bp2,%0"::"r"(value2)); break;
case CSR_BP3: asm volatile ("wcsr bp3,%0"::"r"(value2)); break;
case CSR_WP0: asm volatile ("wcsr wp0,%0"::"r"(value2)); break;
case CSR_WP1: asm volatile ("wcsr wp1,%0"::"r"(value2)); break;
case CSR_WP2: asm volatile ("wcsr wp2,%0"::"r"(value2)); break;
case CSR_WP3: asm volatile ("wcsr wp3,%0"::"r"(value2)); break;
default: printf("csr read only\n"); return;
}
}
/* CF filesystem functions */
static int lscb(const char *filename, const char *longname, void *param)
{
printf("%12s [%s]\n", filename, longname);
return 1;
}
static void ls(char *dev)
{
if(!fatfs_init(BLOCKDEV_MEMORY_CARD)) return;
fatfs_list_files(lscb, NULL);
fatfs_done();
}
static void load(char *filename, char *addr, char *dev)
{
char *c;
unsigned int *addr2;
if((*filename == 0) || (*addr == 0)) {
printf("load <filename> <address>\n");
return;
}
addr2 = (unsigned *)strtoul(addr, &c, 0);
if(*c != 0) {
printf("incorrect address\n");
return;
}
if(!fatfs_init(BLOCKDEV_MEMORY_CARD)) return;
fatfs_load(filename, (char *)addr2, 16*1024*1024, NULL);
fatfs_done();
}
static void mdior(char *reg)
{
char *c;
int reg2;
if(*reg == 0) {
printf("mdior <register>\n");
return;
}
reg2 = strtoul(reg, &c, 0);
if(*c != 0) {
printf("incorrect register\n");
return;
}
printf("%04x\n", mdio_read(brd_desc->ethernet_phyadr, reg2));
}
static void mdiow(char *reg, char *value)
{
char *c;
int reg2;
int value2;
if((*reg == 0) || (*value == 0)) {
printf("mdiow <register> <value>\n");
return;
}
reg2 = strtoul(reg, &c, 0);
if(*c != 0) {
printf("incorrect address\n");
return;
}
value2 = strtoul(value, &c, 0);
if(*c != 0) {
printf("incorrect value\n");
return;
}
mdio_write(brd_desc->ethernet_phyadr, reg2, value2);
}
/* Init + command line */
static void help()
{
puts("Milkymist(tm) BIOS (bootloader)");
puts("Don't know what to do? Try 'flashboot'.\n");
puts("Available commands:");
puts("cons - switch console mode");
puts("flush - flush FML bridge cache");
puts("mr - read address space");
puts("mw - write address space");
puts("mc - copy address space");
puts("crc - compute CRC32 of a part of the address space");
puts("rcsr - read processor CSR");
puts("wcsr - write processor CSR");
puts("ls - list files on the filesystem");
puts("load - load a file from the filesystem");
puts("netboot - boot via TFTP");
puts("serialboot - boot via SFL");
puts("fsboot - boot from the filesystem");
puts("flashboot - boot from flash");
puts("mdior - read MDIO register");
puts("mdiow - write MDIO register");
puts("version - display version");
puts("reboot - system reset");
puts("reconf - reload FPGA configuration");
puts("namuruinit - init basic essential registers");
puts("namurustatus - dump status to screen");
puts("namurumeasure - no dump,measure TPs with scope ");
puts("namuruaccum - dump accumlators to screen");
puts("memtest1 - memory speed test, use a stopwatch!");
}
static char *get_token(char **str)
{
char *c, *d;
c = (char *)strchr(*str, ' ');
if(c == NULL) {
d = *str;
*str = *str+strlen(*str);
return d;
}
*c = 0;
d = *str;
*str = c+1;
return d;
}
static void do_command(char *c)
{
char *token;
token = get_token(&c);
if(strcmp(token, "cons") == 0) vga_set_console(!vga_get_console());
else if(strcmp(token, "flush") == 0) flush_bridge_cache();
else if(strcmp(token, "mr") == 0) mr(get_token(&c), get_token(&c));
else if(strcmp(token, "mw") == 0) mw(get_token(&c), get_token(&c), get_token(&c));
else if(strcmp(token, "mc") == 0) mc(get_token(&c), get_token(&c), get_token(&c));
else if(strcmp(token, "crc") == 0) crc(get_token(&c), get_token(&c));
else if(strcmp(token, "ls") == 0) ls(get_token(&c));
else if(strcmp(token, "load") == 0) load(get_token(&c), get_token(&c), get_token(&c));
else if(strcmp(token, "netboot") == 0) netboot();
else if(strcmp(token, "serialboot") == 0) serialboot();
else if(strcmp(token, "fsboot") == 0) fsboot(BLOCKDEV_MEMORY_CARD);
else if(strcmp(token, "flashboot") == 0) flashboot();
else if(strcmp(token, "mdior") == 0) mdior(get_token(&c));
else if(strcmp(token, "mdiow") == 0) mdiow(get_token(&c), get_token(&c));
else if(strcmp(token, "version") == 0) puts(VERSION);
else if(strcmp(token, "reboot") == 0) reboot();
else if(strcmp(token, "reconf") == 0) reconf();
else if(strcmp(token, "help") == 0) help();
else if(strcmp(token, "namuruinit") == 0) namuruinit();
else if(strcmp(token, "namurustatus") == 0) namurustatus();
else if(strcmp(token, "namurumeasure") == 0) namurumeasure();
else if(strcmp(token, "namuruaccum") == 0) namuruaccum();
else if(strcmp(token, "memtest1") == 0) memtest1();
else if(strcmp(token, "rcsr") == 0) rcsr(get_token(&c));
else if(strcmp(token, "wcsr") == 0) wcsr(get_token(&c), get_token(&c));
else if(strcmp(token, "") != 0)
printf("Command not found\n");
}
static int test_user_abort()
{
char c;
puts("I: Press Q or ESC to abort boot");
CSR_TIMER0_COUNTER = 0;
CSR_TIMER0_COMPARE = 2*brd_desc->clk_frequency;
CSR_TIMER0_CONTROL = TIMER_ENABLE;
while(CSR_TIMER0_CONTROL & TIMER_ENABLE) {
if(readchar_nonblock()) {
c = readchar();
if((c == 'Q')||(c == '\e')) {
puts("I: Aborted boot on user request");
return 0;
}
if(c == 0x07) {
vga_unblank();
vga_set_console(1);
netboot();
return 0;
}
}
}
return 1;
}
int rescue;
extern unsigned int _edata;
static void crcbios()
{
unsigned int offset_bios;
unsigned int length;
unsigned int expected_crc;
unsigned int actual_crc;
/*
* _edata is located right after the end of the flat
* binary image. The CRC tool writes the 32-bit CRC here.
* We also use the address of _edata to know the length
* of our code.
*/
offset_bios = rescue ? FLASH_OFFSET_RESCUE_BIOS : FLASH_OFFSET_REGULAR_BIOS;
expected_crc = _edata;
length = (unsigned int)&_edata - offset_bios;
actual_crc = crc32((unsigned char *)offset_bios, length);
if(expected_crc == actual_crc)
printf("I: BIOS CRC passed (%08x)\n", actual_crc);
else {
printf("W: BIOS CRC failed (expected %08x, got %08x)\n", expected_crc, actual_crc);
printf("W: The system will continue, but expect problems.\n");
}
}
static void print_mac()
{
unsigned char *macadr = (unsigned char *)FLASH_OFFSET_MAC_ADDRESS;
printf("I: MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", macadr[0], macadr[1], macadr[2], macadr[3], macadr[4], macadr[5]);
}
static const char banner[] =
"\nMILKYMIST(tm) v"VERSION" BIOS http://www.milkymist.org\n"
"(c) Copyright 2007, 2008, 2009, 2010, 2011 Sebastien Bourdeauducq\n\n"
"This program is free software: you can redistribute it and/or modify\n"
"it under the terms of the GNU General Public License as published by\n"
"the Free Software Foundation, version 3 of the License.\n\n";
static void boot_sequence()
{
if(test_user_abort()) {
if(rescue) {
netboot();
serialboot();
fsboot(BLOCKDEV_MEMORY_CARD);
flashboot();
} else {
fsboot(BLOCKDEV_MEMORY_CARD);
flashboot();
netboot();
serialboot();
}
printf("E: No boot medium found\n");
}
}
static void readstr(char *s, int size)
{
char c[2];
int ptr;
c[1] = 0;
ptr = 0;
while(1) {
c[0] = readchar();
switch(c[0]) {
case 0x7f:
case 0x08:
if(ptr > 0) {
ptr--;
putsnonl("\x08 \x08");
}
break;
case '\e':
vga_set_console(!vga_get_console());
break;
case 0x07:
break;
case '\r':
case '\n':
s[ptr] = 0x00;
putsnonl("\n");
return;
default:
putsnonl(c);
s[ptr] = c[0];
ptr++;
break;
}
}
}
static void ethreset_delay()
{
CSR_TIMER0_COUNTER = 0;
CSR_TIMER0_COMPARE = brd_desc->clk_frequency >> 2;
CSR_TIMER0_CONTROL = TIMER_ENABLE;
while(CSR_TIMER0_CONTROL & TIMER_ENABLE);
}
static void ethreset()
{
CSR_MINIMAC_SETUP = MINIMAC_SETUP_PHYRST;
ethreset_delay();
CSR_MINIMAC_SETUP = 0;
ethreset_delay();
}
int main(int i, char **c)
{
char buffer[64];
CSR_GPIO_OUT = GPIO_LED1;
rescue = !((unsigned int)main > FLASH_OFFSET_REGULAR_BIOS);
irq_setmask(0);
irq_enable(1);
uart_init();
vga_init(!(rescue || (CSR_GPIO_IN & GPIO_BTN2)));
putsnonl(banner);
crcbios();
brd_init();
tmu_init(); /* < for hardware-accelerated scrolling */
usb_init();
ukb_init();
if(rescue)
printf("I: Booting in rescue mode\n");
splash_display();
ethreset(); /* < that pesky ethernet PHY needs two resets at times... */
print_mac();
boot_sequence();
vga_unblank();
vga_set_console(1);
while(1) {
putsnonl("\e[1mBIOS>\e[0m ");
readstr(buffer, 64);
do_command(buffer);
}
return 0;
}
Jump to Line
Something went wrong with that request. Please try again.