1074 lines
26 KiB
C
1074 lines
26 KiB
C
/* tag: openbios forth environment, executable code
|
|
*
|
|
* Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
|
|
*
|
|
* See the file "COPYING" for further information about
|
|
* the copyright and warranty status of this work.
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "libopenbios/openbios.h"
|
|
#include "libopenbios/bindings.h"
|
|
#include "libopenbios/console.h"
|
|
#include "drivers/drivers.h"
|
|
#include "asm/types.h"
|
|
#include "dict.h"
|
|
#include "kernel/kernel.h"
|
|
#include "kernel/stack.h"
|
|
#include "arch/common/nvram.h"
|
|
#include "packages/nvram.h"
|
|
#include "../../drivers/timer.h" // XXX
|
|
#include "libopenbios/sys_info.h"
|
|
#include "openbios.h"
|
|
#include "boot.h"
|
|
#include "romvec.h"
|
|
#include "openprom.h"
|
|
#include "psr.h"
|
|
#include "libopenbios/video.h"
|
|
#define NO_QEMU_PROTOS
|
|
#include "arch/common/fw_cfg.h"
|
|
#include "arch/sparc32/ofmem_sparc32.h"
|
|
|
|
#define MEMORY_SIZE (128*1024) /* 128K ram for hosted system */
|
|
#define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
|
|
#define FW_CFG_SUN4M_DEPTH (FW_CFG_ARCH_LOCAL + 0x00)
|
|
|
|
int qemu_machine_type;
|
|
|
|
struct hwdef {
|
|
uint64_t iommu_base, slavio_base;
|
|
uint64_t intctl_base, counter_base, nvram_base, ms_kb_base, serial_base;
|
|
unsigned long fd_offset, counter_offset, intr_offset;
|
|
unsigned long aux1_offset, aux2_offset;
|
|
uint64_t dma_base, esp_base, le_base;
|
|
uint64_t tcx_base;
|
|
uint32_t simm_size;
|
|
int intr_ncpu;
|
|
int mid_offset;
|
|
int machine_id_low, machine_id_high;
|
|
};
|
|
|
|
static const struct hwdef hwdefs[] = {
|
|
/* SS-5 */
|
|
{
|
|
.iommu_base = 0x10000000,
|
|
.tcx_base = 0x50000000,
|
|
.slavio_base = 0x71000000,
|
|
.ms_kb_base = 0x71000000,
|
|
.serial_base = 0x71100000,
|
|
.nvram_base = 0x71200000,
|
|
.fd_offset = 0x00400000,
|
|
.counter_offset = 0x00d00000,
|
|
.intr_offset = 0x00e00000,
|
|
.intr_ncpu = 1,
|
|
.aux1_offset = 0x00900000,
|
|
.aux2_offset = 0x00910000,
|
|
.dma_base = 0x78400000,
|
|
.esp_base = 0x78800000,
|
|
.le_base = 0x78c00000,
|
|
.simm_size = 0x2000000,
|
|
.mid_offset = 0,
|
|
.machine_id_low = 32,
|
|
.machine_id_high = 63,
|
|
},
|
|
/* SS-10, SS-20 */
|
|
{
|
|
.iommu_base = 0xfe0000000ULL,
|
|
.tcx_base = 0xe20000000ULL,
|
|
.slavio_base = 0xff1000000ULL,
|
|
.ms_kb_base = 0xff1000000ULL,
|
|
.serial_base = 0xff1100000ULL,
|
|
.nvram_base = 0xff1200000ULL,
|
|
.fd_offset = 0x00700000, // 0xff1700000ULL,
|
|
.counter_offset = 0x00300000, // 0xff1300000ULL,
|
|
.intr_offset = 0x00400000, // 0xff1400000ULL,
|
|
.intr_ncpu = 4,
|
|
.aux1_offset = 0x00800000, // 0xff1800000ULL,
|
|
.aux2_offset = 0x00a01000, // 0xff1a01000ULL,
|
|
.dma_base = 0xef0400000ULL,
|
|
.esp_base = 0xef0800000ULL,
|
|
.le_base = 0xef0c00000ULL,
|
|
.simm_size = 0x4000000,
|
|
.mid_offset = 8,
|
|
.machine_id_low = 64,
|
|
.machine_id_high = 65,
|
|
},
|
|
/* SS-600MP */
|
|
{
|
|
.iommu_base = 0xfe0000000ULL,
|
|
.tcx_base = 0xe20000000ULL,
|
|
.slavio_base = 0xff1000000ULL,
|
|
.ms_kb_base = 0xff1000000ULL,
|
|
.serial_base = 0xff1100000ULL,
|
|
.nvram_base = 0xff1200000ULL,
|
|
.fd_offset = -1,
|
|
.counter_offset = 0x00300000, // 0xff1300000ULL,
|
|
.intr_offset = 0x00400000, // 0xff1400000ULL,
|
|
.intr_ncpu = 4,
|
|
.aux1_offset = 0x00800000, // 0xff1800000ULL,
|
|
.aux2_offset = 0x00a01000, // 0xff1a01000ULL, XXX should not exist
|
|
.dma_base = 0xef0081000ULL,
|
|
.esp_base = 0xef0080000ULL,
|
|
.le_base = 0xef0060000ULL,
|
|
.simm_size = 0x4000000,
|
|
.mid_offset = 8,
|
|
.machine_id_low = 66,
|
|
.machine_id_high = 66,
|
|
},
|
|
};
|
|
|
|
static const struct hwdef *hwdef;
|
|
|
|
void setup_timers(void)
|
|
{
|
|
}
|
|
|
|
void udelay(unsigned int usecs)
|
|
{
|
|
}
|
|
|
|
void mdelay(unsigned int msecs)
|
|
{
|
|
}
|
|
|
|
static void mb86904_init(void)
|
|
{
|
|
PUSH(32);
|
|
fword("encode-int");
|
|
push_str("cache-line-size");
|
|
fword("property");
|
|
|
|
PUSH(512);
|
|
fword("encode-int");
|
|
push_str("cache-nlines");
|
|
fword("property");
|
|
|
|
PUSH(0x23);
|
|
fword("encode-int");
|
|
push_str("mask_rev");
|
|
fword("property");
|
|
}
|
|
|
|
static void tms390z55_init(void)
|
|
{
|
|
push_str("");
|
|
fword("encode-string");
|
|
push_str("ecache-parity?");
|
|
fword("property");
|
|
|
|
push_str("");
|
|
fword("encode-string");
|
|
push_str("bfill?");
|
|
fword("property");
|
|
|
|
push_str("");
|
|
fword("encode-string");
|
|
push_str("bcopy?");
|
|
fword("property");
|
|
|
|
push_str("");
|
|
fword("encode-string");
|
|
push_str("cache-physical?");
|
|
fword("property");
|
|
|
|
PUSH(0xf);
|
|
fword("encode-int");
|
|
PUSH(0xf8fffffc);
|
|
fword("encode-int");
|
|
fword("encode+");
|
|
PUSH(4);
|
|
fword("encode-int");
|
|
fword("encode+");
|
|
|
|
PUSH(0xf);
|
|
fword("encode-int");
|
|
fword("encode+");
|
|
PUSH(0xf8c00000);
|
|
fword("encode-int");
|
|
fword("encode+");
|
|
PUSH(0x1000);
|
|
fword("encode-int");
|
|
fword("encode+");
|
|
|
|
PUSH(0xf);
|
|
fword("encode-int");
|
|
fword("encode+");
|
|
PUSH(0xf8000000);
|
|
fword("encode-int");
|
|
fword("encode+");
|
|
PUSH(0x1000);
|
|
fword("encode-int");
|
|
fword("encode+");
|
|
|
|
PUSH(0xf);
|
|
fword("encode-int");
|
|
fword("encode+");
|
|
PUSH(0xf8800000);
|
|
fword("encode-int");
|
|
fword("encode+");
|
|
PUSH(0x1000);
|
|
fword("encode-int");
|
|
fword("encode+");
|
|
push_str("reg");
|
|
fword("property");
|
|
}
|
|
|
|
static void rt625_init(void)
|
|
{
|
|
PUSH(32);
|
|
fword("encode-int");
|
|
push_str("cache-line-size");
|
|
fword("property");
|
|
|
|
PUSH(512);
|
|
fword("encode-int");
|
|
push_str("cache-nlines");
|
|
fword("property");
|
|
|
|
}
|
|
|
|
static void bad_cpu_init(void)
|
|
{
|
|
printk("This CPU is not supported yet, freezing.\n");
|
|
for(;;);
|
|
}
|
|
|
|
struct cpudef {
|
|
unsigned long iu_version;
|
|
const char *name;
|
|
int psr_impl, psr_vers, impl, vers;
|
|
int dcache_line_size, dcache_lines, dcache_assoc;
|
|
int icache_line_size, icache_lines, icache_assoc;
|
|
int ecache_line_size, ecache_lines, ecache_assoc;
|
|
int mmu_nctx;
|
|
void (*initfn)(void);
|
|
};
|
|
|
|
static const struct cpudef sparc_defs[] = {
|
|
{
|
|
.iu_version = 0x00 << 24, /* Impl 0, ver 0 */
|
|
.name = "FMI,MB86900",
|
|
.initfn = bad_cpu_init,
|
|
},
|
|
{
|
|
.iu_version = 0x04 << 24, /* Impl 0, ver 4 */
|
|
.name = "FMI,MB86904",
|
|
.psr_impl = 0,
|
|
.psr_vers = 4,
|
|
.impl = 0,
|
|
.vers = 4,
|
|
.dcache_line_size = 0x10,
|
|
.dcache_lines = 0x200,
|
|
.dcache_assoc = 1,
|
|
.icache_line_size = 0x20,
|
|
.icache_lines = 0x200,
|
|
.icache_assoc = 1,
|
|
.ecache_line_size = 0x20,
|
|
.ecache_lines = 0x4000,
|
|
.ecache_assoc = 1,
|
|
.mmu_nctx = 0x100,
|
|
.initfn = mb86904_init,
|
|
},
|
|
{
|
|
.iu_version = 0x05 << 24, /* Impl 0, ver 5 */
|
|
.name = "FMI,MB86907",
|
|
.psr_impl = 0,
|
|
.psr_vers = 5,
|
|
.impl = 0,
|
|
.vers = 5,
|
|
.dcache_line_size = 0x20,
|
|
.dcache_lines = 0x200,
|
|
.dcache_assoc = 1,
|
|
.icache_line_size = 0x20,
|
|
.icache_lines = 0x200,
|
|
.icache_assoc = 1,
|
|
.ecache_line_size = 0x20,
|
|
.ecache_lines = 0x4000,
|
|
.ecache_assoc = 1,
|
|
.mmu_nctx = 0x100,
|
|
.initfn = mb86904_init,
|
|
},
|
|
{
|
|
.iu_version = 0x10 << 24, /* Impl 1, ver 0 */
|
|
.name = "LSI,L64811",
|
|
.initfn = bad_cpu_init,
|
|
},
|
|
{
|
|
.iu_version = 0x11 << 24, /* Impl 1, ver 1 */
|
|
.name = "CY,CY7C601",
|
|
.psr_impl = 1,
|
|
.psr_vers = 1,
|
|
.impl = 1,
|
|
.vers = 1,
|
|
.mmu_nctx = 0x10,
|
|
.initfn = bad_cpu_init,
|
|
},
|
|
{
|
|
.iu_version = 0x13 << 24, /* Impl 1, ver 3 */
|
|
.name = "CY,CY7C611",
|
|
.initfn = bad_cpu_init,
|
|
},
|
|
{
|
|
.iu_version = 0x40000000,
|
|
.name = "TI,TMS390Z55",
|
|
.psr_impl = 4,
|
|
.psr_vers = 0,
|
|
.impl = 0,
|
|
.vers = 4,
|
|
.dcache_line_size = 0x20,
|
|
.dcache_lines = 0x80,
|
|
.dcache_assoc = 4,
|
|
.icache_line_size = 0x40,
|
|
.icache_lines = 0x40,
|
|
.icache_assoc = 5,
|
|
.ecache_line_size = 0x20,
|
|
.ecache_lines = 0x8000,
|
|
.ecache_assoc = 1,
|
|
.mmu_nctx = 0x10000,
|
|
.initfn = tms390z55_init,
|
|
},
|
|
{
|
|
.iu_version = 0x41000000,
|
|
.name = "TI,TMS390S10",
|
|
.psr_impl = 4,
|
|
.psr_vers = 1,
|
|
.impl = 4,
|
|
.vers = 1,
|
|
.dcache_line_size = 0x10,
|
|
.dcache_lines = 0x80,
|
|
.dcache_assoc = 4,
|
|
.icache_line_size = 0x20,
|
|
.icache_lines = 0x80,
|
|
.icache_assoc = 5,
|
|
.ecache_line_size = 0x20,
|
|
.ecache_lines = 0x8000,
|
|
.ecache_assoc = 1,
|
|
.mmu_nctx = 0x10000,
|
|
.initfn = tms390z55_init,
|
|
},
|
|
{
|
|
.iu_version = 0x42000000,
|
|
.name = "TI,TMS390S10",
|
|
.psr_impl = 4,
|
|
.psr_vers = 2,
|
|
.impl = 4,
|
|
.vers = 2,
|
|
.dcache_line_size = 0x10,
|
|
.dcache_lines = 0x80,
|
|
.dcache_assoc = 4,
|
|
.icache_line_size = 0x20,
|
|
.icache_lines = 0x80,
|
|
.icache_assoc = 5,
|
|
.ecache_line_size = 0x20,
|
|
.ecache_lines = 0x8000,
|
|
.ecache_assoc = 1,
|
|
.mmu_nctx = 0x10000,
|
|
.initfn = tms390z55_init,
|
|
},
|
|
{
|
|
.iu_version = 0x43000000,
|
|
.name = "TI,TMS390S10",
|
|
.psr_impl = 4,
|
|
.psr_vers = 3,
|
|
.impl = 4,
|
|
.vers = 3,
|
|
.dcache_line_size = 0x10,
|
|
.dcache_lines = 0x80,
|
|
.dcache_assoc = 4,
|
|
.icache_line_size = 0x20,
|
|
.icache_lines = 0x80,
|
|
.icache_assoc = 5,
|
|
.ecache_line_size = 0x20,
|
|
.ecache_lines = 0x8000,
|
|
.ecache_assoc = 1,
|
|
.mmu_nctx = 0x10000,
|
|
.initfn = tms390z55_init,
|
|
},
|
|
{
|
|
.iu_version = 0x44000000,
|
|
.name = "TI,TMS390S10",
|
|
.psr_impl = 4,
|
|
.psr_vers = 4,
|
|
.impl = 4,
|
|
.vers = 4,
|
|
.dcache_line_size = 0x10,
|
|
.dcache_lines = 0x80,
|
|
.dcache_assoc = 4,
|
|
.icache_line_size = 0x20,
|
|
.icache_lines = 0x80,
|
|
.icache_assoc = 5,
|
|
.ecache_line_size = 0x20,
|
|
.ecache_lines = 0x8000,
|
|
.ecache_assoc = 1,
|
|
.mmu_nctx = 0x10000,
|
|
.initfn = tms390z55_init,
|
|
},
|
|
{
|
|
.iu_version = 0x1e000000,
|
|
.name = "Ross,RT625",
|
|
.psr_impl = 1,
|
|
.psr_vers = 14,
|
|
.impl = 1,
|
|
.vers = 7,
|
|
.dcache_line_size = 0x20,
|
|
.dcache_lines = 0x80,
|
|
.dcache_assoc = 4,
|
|
.icache_line_size = 0x40,
|
|
.icache_lines = 0x40,
|
|
.icache_assoc = 5,
|
|
.ecache_line_size = 0x20,
|
|
.ecache_lines = 0x8000,
|
|
.ecache_assoc = 1,
|
|
.mmu_nctx = 0x10000,
|
|
.initfn = rt625_init,
|
|
},
|
|
{
|
|
.iu_version = 0x1f000000,
|
|
.name = "Ross,RT620",
|
|
.psr_impl = 1,
|
|
.psr_vers = 15,
|
|
.impl = 1,
|
|
.vers = 7,
|
|
.dcache_line_size = 0x20,
|
|
.dcache_lines = 0x80,
|
|
.dcache_assoc = 4,
|
|
.icache_line_size = 0x40,
|
|
.icache_lines = 0x40,
|
|
.icache_assoc = 5,
|
|
.ecache_line_size = 0x20,
|
|
.ecache_lines = 0x8000,
|
|
.ecache_assoc = 1,
|
|
.mmu_nctx = 0x10000,
|
|
.initfn = rt625_init,
|
|
},
|
|
{
|
|
.iu_version = 0x20000000,
|
|
.name = "BIT,B5010",
|
|
.initfn = bad_cpu_init,
|
|
},
|
|
{
|
|
.iu_version = 0x50000000,
|
|
.name = "MC,MN10501",
|
|
.initfn = bad_cpu_init,
|
|
},
|
|
{
|
|
.iu_version = 0x90 << 24, /* Impl 9, ver 0 */
|
|
.name = "Weitek,W8601",
|
|
.initfn = bad_cpu_init,
|
|
},
|
|
{
|
|
.iu_version = 0xf2000000,
|
|
.name = "GR,LEON2",
|
|
.initfn = bad_cpu_init,
|
|
},
|
|
{
|
|
.iu_version = 0xf3000000,
|
|
.name = "GR,LEON3",
|
|
.initfn = bad_cpu_init,
|
|
},
|
|
};
|
|
|
|
static const struct cpudef *
|
|
id_cpu(void)
|
|
{
|
|
unsigned long iu_version;
|
|
unsigned int i;
|
|
|
|
asm("rd %%psr, %0\n"
|
|
: "=r"(iu_version) :);
|
|
iu_version &= 0xff000000;
|
|
|
|
for (i = 0; i < sizeof(sparc_defs)/sizeof(struct cpudef); i++) {
|
|
if (iu_version == sparc_defs[i].iu_version)
|
|
return &sparc_defs[i];
|
|
}
|
|
printk("Unknown cpu (psr %lx), freezing!\n", iu_version);
|
|
for (;;);
|
|
}
|
|
|
|
static void setup_cpu(int mid_offset)
|
|
{
|
|
uint32_t temp;
|
|
unsigned int i;
|
|
const struct cpudef *cpu;
|
|
|
|
// Add cpus
|
|
temp = fw_cfg_read_i32(FW_CFG_NB_CPUS);
|
|
|
|
printk("CPUs: %x", temp);
|
|
cpu = id_cpu();
|
|
printk(" x %s\n", cpu->name);
|
|
for (i = 0; i < temp; i++) {
|
|
push_str("/");
|
|
fword("find-device");
|
|
|
|
fword("new-device");
|
|
|
|
push_str(cpu->name);
|
|
fword("device-name");
|
|
|
|
push_str("cpu");
|
|
fword("device-type");
|
|
|
|
PUSH(cpu->psr_impl);
|
|
fword("encode-int");
|
|
push_str("psr-implementation");
|
|
fword("property");
|
|
|
|
PUSH(cpu->psr_vers);
|
|
fword("encode-int");
|
|
push_str("psr-version");
|
|
fword("property");
|
|
|
|
PUSH(cpu->impl);
|
|
fword("encode-int");
|
|
push_str("implementation");
|
|
fword("property");
|
|
|
|
PUSH(cpu->vers);
|
|
fword("encode-int");
|
|
push_str("version");
|
|
fword("property");
|
|
|
|
PUSH(4096);
|
|
fword("encode-int");
|
|
push_str("page-size");
|
|
fword("property");
|
|
|
|
PUSH(cpu->dcache_line_size);
|
|
fword("encode-int");
|
|
push_str("dcache-line-size");
|
|
fword("property");
|
|
|
|
PUSH(cpu->dcache_lines);
|
|
fword("encode-int");
|
|
push_str("dcache-nlines");
|
|
fword("property");
|
|
|
|
PUSH(cpu->dcache_assoc);
|
|
fword("encode-int");
|
|
push_str("dcache-associativity");
|
|
fword("property");
|
|
|
|
PUSH(cpu->icache_line_size);
|
|
fword("encode-int");
|
|
push_str("icache-line-size");
|
|
fword("property");
|
|
|
|
PUSH(cpu->icache_lines);
|
|
fword("encode-int");
|
|
push_str("icache-nlines");
|
|
fword("property");
|
|
|
|
PUSH(cpu->icache_assoc);
|
|
fword("encode-int");
|
|
push_str("icache-associativity");
|
|
fword("property");
|
|
|
|
PUSH(cpu->ecache_line_size);
|
|
fword("encode-int");
|
|
push_str("ecache-line-size");
|
|
fword("property");
|
|
|
|
PUSH(cpu->ecache_lines);
|
|
fword("encode-int");
|
|
push_str("ecache-nlines");
|
|
fword("property");
|
|
|
|
PUSH(cpu->ecache_assoc);
|
|
fword("encode-int");
|
|
push_str("ecache-associativity");
|
|
fword("property");
|
|
|
|
PUSH(2);
|
|
fword("encode-int");
|
|
push_str("ncaches");
|
|
fword("property");
|
|
|
|
PUSH(cpu->mmu_nctx);
|
|
fword("encode-int");
|
|
push_str("mmu-nctx");
|
|
fword("property");
|
|
|
|
PUSH(8);
|
|
fword("encode-int");
|
|
push_str("sparc-version");
|
|
fword("property");
|
|
|
|
push_str("");
|
|
fword("encode-string");
|
|
push_str("cache-coherence?");
|
|
fword("property");
|
|
|
|
PUSH(i + mid_offset);
|
|
fword("encode-int");
|
|
push_str("mid");
|
|
fword("property");
|
|
|
|
cpu->initfn();
|
|
|
|
fword("finish-device");
|
|
}
|
|
}
|
|
|
|
static void dummy_mach_init(uint64_t base)
|
|
{
|
|
}
|
|
|
|
struct machdef {
|
|
uint16_t machine_id;
|
|
const char *banner_name;
|
|
const char *model;
|
|
const char *name;
|
|
void (*initfn)(uint64_t base);
|
|
};
|
|
|
|
static const struct machdef sun4m_defs[] = {
|
|
{
|
|
.machine_id = 32,
|
|
.banner_name = "SPARCstation 5",
|
|
.model = "SUNW,501-3059",
|
|
.name = "SUNW,SPARCstation-5",
|
|
.initfn = ss5_init,
|
|
},
|
|
{
|
|
.machine_id = 33,
|
|
.banner_name = "SPARCstation Voyager",
|
|
.model = "SUNW,501-2581",
|
|
.name = "SUNW,SPARCstation-Voyager",
|
|
.initfn = dummy_mach_init,
|
|
},
|
|
{
|
|
.machine_id = 34,
|
|
.banner_name = "SPARCstation LX",
|
|
.model = "SUNW,501-2031",
|
|
.name = "SUNW,SPARCstation-LX",
|
|
.initfn = dummy_mach_init,
|
|
},
|
|
{
|
|
.machine_id = 35,
|
|
.banner_name = "SPARCstation 4",
|
|
.model = "SUNW,501-2572",
|
|
.name = "SUNW,SPARCstation-4",
|
|
.initfn = ss5_init,
|
|
},
|
|
{
|
|
.machine_id = 36,
|
|
.banner_name = "SPARCstation Classic",
|
|
.model = "SUNW,501-2326",
|
|
.name = "SUNW,SPARCstation-Classic",
|
|
.initfn = dummy_mach_init,
|
|
},
|
|
{
|
|
.machine_id = 37,
|
|
.banner_name = "Tadpole S3 GX",
|
|
.model = "S3",
|
|
.name = "Tadpole_S3GX",
|
|
.initfn = ss5_init,
|
|
},
|
|
{
|
|
.machine_id = 64,
|
|
.banner_name = "SPARCstation 10 (1 X 390Z55)",
|
|
.model = "SUNW,S10,501-2365",
|
|
.name = "SUNW,SPARCstation-10",
|
|
.initfn = ob_eccmemctl_init,
|
|
},
|
|
{
|
|
.machine_id = 65,
|
|
.banner_name = "SPARCstation 20 (1 X 390Z55)",
|
|
.model = "SUNW,S20,501-2324",
|
|
.name = "SUNW,SPARCstation-20",
|
|
.initfn = ob_eccmemctl_init,
|
|
},
|
|
{
|
|
.machine_id = 66,
|
|
.banner_name = "SPARCsystem 600(1 X 390Z55)",
|
|
.model = NULL,
|
|
.name = "SUNW,SPARCsystem-600",
|
|
.initfn = ob_eccmemctl_init,
|
|
},
|
|
};
|
|
|
|
static const struct machdef *
|
|
id_machine(uint16_t machine_id)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < sizeof(sun4m_defs)/sizeof(struct machdef); i++) {
|
|
if (machine_id == sun4m_defs[i].machine_id)
|
|
return &sun4m_defs[i];
|
|
}
|
|
printk("Unknown machine (ID %d), freezing!\n", machine_id);
|
|
for (;;);
|
|
}
|
|
|
|
static void setup_machine(uint64_t base)
|
|
{
|
|
uint16_t machine_id;
|
|
const struct machdef *mach;
|
|
|
|
machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID);
|
|
mach = id_machine(machine_id);
|
|
|
|
push_str("/");
|
|
fword("find-device");
|
|
push_str(mach->banner_name);
|
|
fword("encode-string");
|
|
push_str("banner-name");
|
|
fword("property");
|
|
|
|
if (mach->model) {
|
|
push_str(mach->model);
|
|
fword("encode-string");
|
|
push_str("model");
|
|
fword("property");
|
|
}
|
|
push_str(mach->name);
|
|
fword("encode-string");
|
|
push_str("name");
|
|
fword("property");
|
|
|
|
mach->initfn(base);
|
|
}
|
|
|
|
/* Add /uuid */
|
|
static void setup_uuid(void)
|
|
{
|
|
static uint8_t qemu_uuid[16];
|
|
|
|
fw_cfg_read(FW_CFG_UUID, (char *)qemu_uuid, 16);
|
|
|
|
printk("UUID: " UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1], qemu_uuid[2],
|
|
qemu_uuid[3], qemu_uuid[4], qemu_uuid[5], qemu_uuid[6],
|
|
qemu_uuid[7], qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
|
|
qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], qemu_uuid[14],
|
|
qemu_uuid[15]);
|
|
|
|
push_str("/");
|
|
fword("find-device");
|
|
|
|
PUSH((long)&qemu_uuid);
|
|
PUSH(16);
|
|
fword("encode-bytes");
|
|
push_str("uuid");
|
|
fword("property");
|
|
}
|
|
|
|
static void setup_stdio(void)
|
|
{
|
|
char nographic;
|
|
const char *stdin, *stdout;
|
|
phandle_t display_ph;
|
|
|
|
fw_cfg_read(FW_CFG_NOGRAPHIC, &nographic, 1);
|
|
|
|
/* Check to see if any framebuffer present */
|
|
display_ph = dt_iterate_type(0, "display");
|
|
if (display_ph == 0) {
|
|
nographic = 1;
|
|
}
|
|
|
|
if (nographic) {
|
|
obp_stdin = PROMDEV_TTYA;
|
|
obp_stdout = PROMDEV_TTYA;
|
|
stdin = "ttya";
|
|
stdout = "ttya";
|
|
} else {
|
|
obp_stdin = PROMDEV_KBD;
|
|
obp_stdout = PROMDEV_SCREEN;
|
|
stdin = "keyboard";
|
|
stdout = "screen";
|
|
}
|
|
|
|
push_str(stdin);
|
|
push_str("input-device");
|
|
fword("$setenv");
|
|
|
|
push_str(stdout);
|
|
push_str("output-device");
|
|
fword("$setenv");
|
|
|
|
obp_stdin_path = stdin;
|
|
obp_stdout_path = stdout;
|
|
}
|
|
|
|
static void init_memory(void)
|
|
{
|
|
phys_addr_t phys;
|
|
ucell virt;
|
|
|
|
/* Claim the memory from OFMEM */
|
|
phys = ofmem_claim_phys(-1, MEMORY_SIZE, PAGE_SIZE);
|
|
if (!phys)
|
|
printk("panic: not enough physical memory on host system.\n");
|
|
|
|
virt = ofmem_claim_virt(OF_CODE_START - MEMORY_SIZE, MEMORY_SIZE, 0);
|
|
if (!virt)
|
|
printk("panic: not enough virtual memory on host system.\n");
|
|
|
|
/* Generate the mapping (and lock translation into the TLBs) */
|
|
ofmem_map(phys, virt, MEMORY_SIZE, ofmem_arch_default_translation_mode(phys));
|
|
|
|
/* we push start and end of memory to the stack
|
|
* so that it can be used by the forth word QUIT
|
|
* to initialize the memory allocator
|
|
*/
|
|
|
|
PUSH(virt);
|
|
PUSH(virt + MEMORY_SIZE);
|
|
}
|
|
|
|
/* ( size -- virt ) */
|
|
static void
|
|
dma_alloc(void)
|
|
{
|
|
ucell size = POP();
|
|
unsigned long *va;
|
|
|
|
va = dvma_alloc(size);
|
|
|
|
PUSH(pointer2cell(va));
|
|
}
|
|
|
|
/* ( virt devaddr size -- ) */
|
|
static void
|
|
dma_sync(void)
|
|
{
|
|
ucell size = POP();
|
|
POP();
|
|
ucell virt = POP();
|
|
|
|
dvma_sync(cell2pointer(virt), size);
|
|
}
|
|
|
|
/* ( virt size cacheable? -- devaddr ) */
|
|
static void
|
|
dma_map_in(void)
|
|
{
|
|
unsigned int iova;
|
|
|
|
POP();
|
|
POP();
|
|
ucell virt = POP();
|
|
|
|
iova = dvma_map_in(cell2pointer(virt));
|
|
PUSH((ucell)iova);
|
|
}
|
|
|
|
static void
|
|
arch_init( void )
|
|
{
|
|
char *cmdline;
|
|
const char *kernel_cmdline;
|
|
uint32_t temp;
|
|
uint16_t machine_id;
|
|
char buf[256];
|
|
unsigned long mem_size;
|
|
|
|
fw_cfg_init();
|
|
|
|
fw_cfg_read(FW_CFG_SIGNATURE, buf, 4);
|
|
buf[4] = '\0';
|
|
|
|
printk("Configuration device id %s", buf);
|
|
|
|
temp = fw_cfg_read_i32(FW_CFG_ID);
|
|
machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID);
|
|
|
|
printk(" version %d machine id %d\n", temp, machine_id);
|
|
|
|
if (temp != 1) {
|
|
printk("Incompatible configuration device version, freezing\n");
|
|
for(;;);
|
|
}
|
|
|
|
graphic_depth = fw_cfg_read_i16(FW_CFG_SUN4M_DEPTH);
|
|
|
|
openbios_init();
|
|
modules_init();
|
|
ob_init_mmu(hwdef->simm_size);
|
|
ob_init_iommu(hwdef->iommu_base);
|
|
|
|
bind_func("(sparc32-dma-alloc)", dma_alloc);
|
|
feval("['] (sparc32-dma-alloc) to (dma-alloc)");
|
|
bind_func("(sparc32-dma-sync)", dma_sync);
|
|
feval("['] (sparc32-dma-sync) to (dma-sync)");
|
|
bind_func("(sparc32-dma-map-in)", dma_map_in);
|
|
feval("['] (sparc32-dma-map-in) to (dma-map-in)");
|
|
|
|
#ifdef CONFIG_DRIVER_OBIO
|
|
mem_size = fw_cfg_read_i32(FW_CFG_RAM_SIZE);
|
|
ob_obio_init(hwdef->slavio_base, hwdef->fd_offset,
|
|
hwdef->counter_offset, hwdef->intr_offset, hwdef->intr_ncpu,
|
|
hwdef->aux1_offset, hwdef->aux2_offset,
|
|
mem_size);
|
|
|
|
setup_machine(hwdef->slavio_base);
|
|
|
|
nvconf_init();
|
|
#endif
|
|
#ifdef CONFIG_DRIVER_SBUS
|
|
#ifdef CONFIG_DEBUG_CONSOLE_VIDEO
|
|
setup_video();
|
|
#endif
|
|
ob_sbus_init(hwdef->iommu_base + 0x1000ULL, qemu_machine_type);
|
|
#endif
|
|
device_end();
|
|
|
|
setup_cpu(hwdef->mid_offset);
|
|
|
|
setup_stdio();
|
|
/* Initialiase openprom romvec */
|
|
romvec = init_openprom();
|
|
|
|
kernel_size = fw_cfg_read_i32(FW_CFG_KERNEL_SIZE);
|
|
if (kernel_size) {
|
|
kernel_image = fw_cfg_read_i32(FW_CFG_KERNEL_ADDR);
|
|
|
|
/* Map krnel memory a similar way to SILO */
|
|
ofmem_map(PAGE_ALIGN(kernel_image), IMAGE_VIRT_ADDR, PAGE_ALIGN(kernel_size), -1);
|
|
}
|
|
|
|
kernel_cmdline = (const char *) fw_cfg_read_i32(FW_CFG_KERNEL_CMDLINE);
|
|
if (kernel_cmdline) {
|
|
cmdline = strdup(kernel_cmdline);
|
|
} else {
|
|
cmdline = strdup("");
|
|
}
|
|
obp_arg.argv[1] = cmdline;
|
|
qemu_cmdline = (uint32_t)cmdline;
|
|
|
|
initrd_size = fw_cfg_read_i32(FW_CFG_INITRD_SIZE);
|
|
if (initrd_size) {
|
|
initrd_image = fw_cfg_read_i32(FW_CFG_INITRD_ADDR);
|
|
|
|
/* Map krnel memory a similar way to SILO */
|
|
ofmem_map(PAGE_ALIGN(initrd_image), INITRD_VIRT_ADDR, PAGE_ALIGN(initrd_size), -1);
|
|
}
|
|
|
|
if (kernel_size)
|
|
printk("kernel phys 0x%x virt 0x%x size 0x%x\n", kernel_image, 0x4000, kernel_size);
|
|
if (initrd_size)
|
|
printk("initrd phys 0x%x virt 0x%x size 0x%x\n", initrd_image, INITRD_VIRT_ADDR, initrd_size);
|
|
|
|
/* Setup nvram variables */
|
|
push_str("/options");
|
|
fword("find-device");
|
|
push_str(cmdline);
|
|
fword("encode-string");
|
|
push_str("boot-file");
|
|
fword("property");
|
|
|
|
boot_device = fw_cfg_read_i16(FW_CFG_BOOT_DEVICE);
|
|
|
|
switch (boot_device) {
|
|
case 'a':
|
|
push_str("floppy");
|
|
break;
|
|
case 'c':
|
|
push_str("disk:a disk");
|
|
break;
|
|
default:
|
|
case 'd':
|
|
push_str("cdrom:d cdrom");
|
|
break;
|
|
case 'n':
|
|
push_str("net");
|
|
break;
|
|
}
|
|
|
|
fword("encode-string");
|
|
push_str("boot-device");
|
|
fword("property");
|
|
|
|
device_end();
|
|
|
|
bind_func("platform-boot", boot );
|
|
bind_func("(arch-go)", setup_romvec );
|
|
|
|
/* Set up other properties */
|
|
push_str("/chosen");
|
|
fword("find-device");
|
|
|
|
setup_uuid();
|
|
|
|
/* Enable interrupts */
|
|
temp = get_psr();
|
|
temp = (temp & ~PSR_PIL) | (13 << 8); /* Enable CPU timer interrupt (level 14) */
|
|
put_psr(temp);
|
|
}
|
|
|
|
extern struct _console_ops arch_console_ops;
|
|
|
|
int openbios(void)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < sizeof(hwdefs) / sizeof(struct hwdef); i++) {
|
|
if (hwdefs[i].machine_id_low <= qemu_machine_type &&
|
|
hwdefs[i].machine_id_high >= qemu_machine_type) {
|
|
hwdef = &hwdefs[i];
|
|
break;
|
|
}
|
|
}
|
|
if (!hwdef)
|
|
for(;;); // Internal inconsistency, hang
|
|
|
|
#ifdef CONFIG_DEBUG_CONSOLE
|
|
init_console(arch_console_ops);
|
|
#endif
|
|
/* Make sure we setup OFMEM before the MMU as we need malloc() to setup page tables */
|
|
ofmem_init();
|
|
|
|
#ifdef CONFIG_DRIVER_SBUS
|
|
init_mmu_swift();
|
|
#endif
|
|
#ifdef CONFIG_DEBUG_CONSOLE
|
|
#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
|
|
escc_uart_init(hwdef->serial_base | (CONFIG_SERIAL_PORT? 0ULL: 4ULL),
|
|
CONFIG_SERIAL_SPEED);
|
|
#endif
|
|
#ifdef CONFIG_DEBUG_CONSOLE_VIDEO
|
|
kbd_init(hwdef->ms_kb_base);
|
|
#endif
|
|
#endif
|
|
|
|
collect_sys_info(&sys_info);
|
|
|
|
dict = (unsigned char *)sys_info.dict_start;
|
|
dicthead = (cell)sys_info.dict_end;
|
|
last = sys_info.dict_last;
|
|
dictlimit = sys_info.dict_limit;
|
|
|
|
forth_init();
|
|
|
|
#ifdef CONFIG_DEBUG_BOOT
|
|
printk("forth started.\n");
|
|
printk("initializing memory...");
|
|
#endif
|
|
|
|
init_memory();
|
|
|
|
#ifdef CONFIG_DEBUG_BOOT
|
|
printk("done\n");
|
|
#endif
|
|
|
|
PUSH_xt( bind_noname_func(arch_init) );
|
|
fword("PREPOST-initializer");
|
|
|
|
PC = (ucell)findword("initialize-of");
|
|
|
|
if (!PC) {
|
|
printk("panic: no dictionary entry point.\n");
|
|
return -1;
|
|
}
|
|
#ifdef CONFIG_DEBUG_DICTIONARY
|
|
printk("done (%d bytes).\n", dicthead);
|
|
printk("Jumping to dictionary...\n");
|
|
#endif
|
|
|
|
enterforth((xt_t)PC);
|
|
|
|
free(dict);
|
|
return 0;
|
|
}
|