2006-05-18 21:57:08 +00:00
|
|
|
/*
|
|
|
|
|
* OpenBIOS Sparc OBIO driver
|
|
|
|
|
*
|
|
|
|
|
* (C) 2004 Stefan Reinauer <stepan@openbios.org>
|
|
|
|
|
* (C) 2005 Ed Schouten <ed@fxq.nl>
|
|
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
|
* version 2
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "openbios/config.h"
|
|
|
|
|
#include "openbios/bindings.h"
|
|
|
|
|
#include "openbios/kernel.h"
|
|
|
|
|
#include "libc/byteorder.h"
|
|
|
|
|
#include "libc/vsprintf.h"
|
|
|
|
|
|
|
|
|
|
#include "openbios/drivers.h"
|
2006-05-22 22:10:54 +00:00
|
|
|
#include "openbios/nvram.h"
|
|
|
|
|
#include "obio.h"
|
|
|
|
|
|
|
|
|
|
#define REGISTER_NAMED_NODE( name, path ) do { \
|
|
|
|
|
bind_new_node( name##_flags_, name##_size_, \
|
|
|
|
|
path, name##_m, sizeof(name##_m)/sizeof(method_t)); \
|
|
|
|
|
} while(0)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* DECLARE data structures for the nodes. */
|
|
|
|
|
DECLARE_UNNAMED_NODE( ob_obio, INSTALL_OPEN, sizeof(int) );
|
2006-05-18 21:57:08 +00:00
|
|
|
|
|
|
|
|
static void
|
2006-05-22 22:10:54 +00:00
|
|
|
ob_new_obio_device(const char *name, const char *type)
|
2006-05-18 21:57:08 +00:00
|
|
|
{
|
2006-05-22 22:10:54 +00:00
|
|
|
push_str("/obio");
|
2006-05-18 21:57:08 +00:00
|
|
|
fword("find-device");
|
2006-05-22 22:10:54 +00:00
|
|
|
fword("new-device");
|
|
|
|
|
|
|
|
|
|
push_str(name);
|
|
|
|
|
fword("device-name");
|
|
|
|
|
|
|
|
|
|
if (type) {
|
|
|
|
|
push_str(type);
|
|
|
|
|
fword("device-type");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static unsigned long
|
|
|
|
|
ob_reg(unsigned long base, unsigned long offset, unsigned long size, int map)
|
|
|
|
|
{
|
|
|
|
|
PUSH(0);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
PUSH(offset);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
fword("encode+");
|
|
|
|
|
PUSH(size);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
fword("encode+");
|
|
|
|
|
push_str("reg");
|
|
|
|
|
fword("property");
|
|
|
|
|
|
|
|
|
|
if (map) {
|
|
|
|
|
unsigned long addr;
|
|
|
|
|
|
|
|
|
|
addr = (unsigned long)map_io(base + offset, size);
|
|
|
|
|
|
|
|
|
|
PUSH(addr);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
PUSH(4);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
fword("encode+");
|
|
|
|
|
push_str("address");
|
|
|
|
|
fword("property");
|
|
|
|
|
return addr;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ob_intr(int intr)
|
|
|
|
|
{
|
|
|
|
|
PUSH(intr);
|
2006-05-18 21:57:08 +00:00
|
|
|
fword("encode-int");
|
2006-05-22 22:10:54 +00:00
|
|
|
PUSH(0);
|
2006-05-18 21:57:08 +00:00
|
|
|
fword("encode-int");
|
|
|
|
|
fword("encode+");
|
2006-05-22 22:10:54 +00:00
|
|
|
push_str("intr");
|
2006-05-18 21:57:08 +00:00
|
|
|
fword("property");
|
2006-05-22 22:10:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ob_zs_init(unsigned long base, unsigned long offset, int intr, int slave, int keyboard)
|
|
|
|
|
{
|
|
|
|
|
ob_new_obio_device("zs", "serial");
|
|
|
|
|
|
|
|
|
|
ob_reg(base, offset, ZS_REGS, 1);
|
|
|
|
|
|
|
|
|
|
PUSH(slave);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
push_str("slave");
|
|
|
|
|
fword("property");
|
|
|
|
|
|
|
|
|
|
if (keyboard) {
|
|
|
|
|
PUSH(-1);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
push_str("keyboard");
|
|
|
|
|
fword("property");
|
|
|
|
|
|
|
|
|
|
PUSH(-1);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
push_str("mouse");
|
|
|
|
|
fword("property");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ob_intr(intr);
|
|
|
|
|
|
|
|
|
|
fword("finish-device");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *nvram;
|
|
|
|
|
struct qemu_nvram_v1 nv_info;
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
arch_nvram_get(char *data)
|
|
|
|
|
{
|
|
|
|
|
memcpy(data, nvram, NVRAM_SIZE);
|
|
|
|
|
}
|
2006-05-18 21:57:08 +00:00
|
|
|
|
2006-05-22 22:10:54 +00:00
|
|
|
void
|
|
|
|
|
arch_nvram_put(char *data)
|
|
|
|
|
{
|
|
|
|
|
memcpy(nvram, data, NVRAM_SIZE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
arch_nvram_size(void)
|
|
|
|
|
{
|
|
|
|
|
return NVRAM_SIZE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ob_nvram_init(unsigned long base, unsigned long offset)
|
|
|
|
|
{
|
|
|
|
|
extern uint32_t kernel_image;
|
|
|
|
|
extern uint32_t kernel_size;
|
|
|
|
|
extern uint32_t cmdline;
|
|
|
|
|
extern uint32_t cmdline_size;
|
|
|
|
|
extern char boot_device;
|
|
|
|
|
|
|
|
|
|
ob_new_obio_device("eeprom", NULL);
|
|
|
|
|
|
|
|
|
|
nvram = (char *)ob_reg(base, offset, NVRAM_SIZE, 1);
|
|
|
|
|
|
|
|
|
|
memcpy(&nv_info, nvram, sizeof(nv_info));
|
|
|
|
|
|
|
|
|
|
printk("Nvram id %s, version %d\n", nv_info.id_string, nv_info.version);
|
|
|
|
|
if (strcmp(nv_info.id_string, "QEMU_BIOS") || nv_info.version != 1) {
|
|
|
|
|
printk("Unknown nvram, freezing!\n");
|
|
|
|
|
for (;;);
|
|
|
|
|
}
|
|
|
|
|
kernel_image = nv_info.kernel_image;
|
|
|
|
|
kernel_size = nv_info.kernel_size;
|
|
|
|
|
cmdline = nv_info.cmdline;
|
|
|
|
|
cmdline_size = nv_info.cmdline_size;
|
|
|
|
|
boot_device = nv_info.boot_device;
|
|
|
|
|
|
|
|
|
|
push_str("mk48t08");
|
|
|
|
|
fword("model");
|
|
|
|
|
|
|
|
|
|
fword("finish-device");
|
|
|
|
|
|
|
|
|
|
push_str("/");
|
2006-05-18 21:57:08 +00:00
|
|
|
fword("find-device");
|
|
|
|
|
|
2006-05-22 22:10:54 +00:00
|
|
|
PUSH((long)&nvram[NVRAM_IDPROM]);
|
|
|
|
|
PUSH(32);
|
|
|
|
|
fword("encode-bytes");
|
|
|
|
|
push_str("idprom");
|
|
|
|
|
fword("property");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ob_fd_init(unsigned long base, unsigned long offset, int intr)
|
|
|
|
|
{
|
|
|
|
|
ob_new_obio_device("SUNW,fdtwo", "block");
|
|
|
|
|
|
|
|
|
|
ob_reg(base, offset, FD_REGS, 0);
|
|
|
|
|
|
|
|
|
|
ob_intr(intr);
|
|
|
|
|
|
|
|
|
|
fword("finish-device");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ob_sconfig_init(unsigned long base, unsigned long offset)
|
|
|
|
|
{
|
|
|
|
|
ob_new_obio_device("slavioconfig", NULL);
|
|
|
|
|
|
|
|
|
|
ob_reg(base, offset, SCONFIG_REGS, 0);
|
|
|
|
|
|
|
|
|
|
fword("finish-device");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ob_auxio_init(unsigned long base, unsigned long offset)
|
|
|
|
|
{
|
|
|
|
|
ob_new_obio_device("auxio", NULL);
|
|
|
|
|
|
|
|
|
|
ob_reg(base, offset, AUXIO_REGS, 0);
|
|
|
|
|
|
|
|
|
|
fword("finish-device");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ob_power_init(unsigned long base, unsigned long offset, int intr)
|
|
|
|
|
{
|
|
|
|
|
ob_new_obio_device("power", NULL);
|
|
|
|
|
|
|
|
|
|
ob_reg(base, offset, POWER_REGS, 0);
|
|
|
|
|
|
|
|
|
|
ob_intr(intr);
|
|
|
|
|
|
|
|
|
|
fword("finish-device");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ob_counter_init(unsigned long base, unsigned long offset)
|
|
|
|
|
{
|
|
|
|
|
volatile struct sun4m_timer_regs *regs;
|
|
|
|
|
|
|
|
|
|
ob_new_obio_device("counter", NULL);
|
|
|
|
|
|
|
|
|
|
PUSH(0);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
PUSH(offset);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
fword("encode+");
|
|
|
|
|
PUSH(COUNTER_REGS);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
fword("encode+");
|
|
|
|
|
PUSH(0);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
fword("encode+");
|
|
|
|
|
PUSH(offset + 0x10000);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
fword("encode+");
|
|
|
|
|
PUSH(COUNTER_REGS);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
fword("encode+");
|
|
|
|
|
push_str("reg");
|
|
|
|
|
fword("property");
|
|
|
|
|
|
|
|
|
|
fword("finish-device");
|
|
|
|
|
|
|
|
|
|
regs = map_io(base + offset, sizeof(*regs));
|
|
|
|
|
regs->l10_timer_limit = (((1000000/100) + 1) << 10);
|
|
|
|
|
regs->cpu_timers[0].l14_timer_limit = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ob_interrupt_init(unsigned long base, unsigned long offset)
|
|
|
|
|
{
|
|
|
|
|
volatile struct sun4m_intregs *regs;
|
|
|
|
|
|
|
|
|
|
ob_new_obio_device("interrupt", NULL);
|
|
|
|
|
|
|
|
|
|
PUSH(0);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
PUSH(offset);
|
2006-05-18 21:57:08 +00:00
|
|
|
fword("encode-int");
|
2006-05-22 22:10:54 +00:00
|
|
|
fword("encode+");
|
|
|
|
|
PUSH(INTERRUPT_REGS);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
fword("encode+");
|
|
|
|
|
PUSH(0);
|
2006-05-18 21:57:08 +00:00
|
|
|
fword("encode-int");
|
|
|
|
|
fword("encode+");
|
2006-05-22 22:10:54 +00:00
|
|
|
PUSH(offset + 0x10000);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
fword("encode+");
|
|
|
|
|
PUSH(INTERRUPT_REGS);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
fword("encode+");
|
|
|
|
|
push_str("reg");
|
2006-05-18 21:57:08 +00:00
|
|
|
fword("property");
|
2006-05-22 22:10:54 +00:00
|
|
|
|
|
|
|
|
fword("finish-device");
|
|
|
|
|
|
|
|
|
|
regs = map_io(base + offset, sizeof(*regs));
|
|
|
|
|
regs->set = ~SUN4M_INT_MASKALL;
|
|
|
|
|
regs->cpu_intregs[0].clear = ~0x17fff;
|
2006-05-18 21:57:08 +00:00
|
|
|
}
|
|
|
|
|
|
2006-05-22 22:10:54 +00:00
|
|
|
|
2006-05-18 21:57:08 +00:00
|
|
|
static void
|
2006-05-22 22:10:54 +00:00
|
|
|
ob_obio_open(__attribute__((unused))int *idx)
|
2006-05-18 21:57:08 +00:00
|
|
|
{
|
|
|
|
|
int ret=1;
|
|
|
|
|
RET ( -ret );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2006-05-22 22:10:54 +00:00
|
|
|
ob_obio_close(__attribute__((unused))int *idx)
|
2006-05-18 21:57:08 +00:00
|
|
|
{
|
|
|
|
|
selfword("close-deblocker");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2006-05-22 22:10:54 +00:00
|
|
|
ob_obio_initialize(__attribute__((unused))int *idx)
|
2006-05-18 21:57:08 +00:00
|
|
|
{
|
2006-05-22 22:10:54 +00:00
|
|
|
push_str("/");
|
|
|
|
|
fword("find-device");
|
|
|
|
|
fword("new-device");
|
|
|
|
|
|
|
|
|
|
push_str("obio");
|
|
|
|
|
fword("device-name");
|
|
|
|
|
|
|
|
|
|
push_str("hierarchical");
|
|
|
|
|
fword("device-type");
|
|
|
|
|
|
|
|
|
|
PUSH(2);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
push_str("#address-cells");
|
|
|
|
|
fword("property");
|
|
|
|
|
|
|
|
|
|
PUSH(1);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
push_str("#size-cells");
|
|
|
|
|
fword("property");
|
|
|
|
|
|
|
|
|
|
fword("finish-device");
|
2006-05-18 21:57:08 +00:00
|
|
|
}
|
|
|
|
|
|
2006-05-22 22:10:54 +00:00
|
|
|
static void
|
|
|
|
|
ob_set_obio_ranges(unsigned long base)
|
|
|
|
|
{
|
|
|
|
|
push_str("/obio");
|
|
|
|
|
fword("find-device");
|
|
|
|
|
PUSH(0);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
PUSH(0);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
fword("encode+");
|
|
|
|
|
PUSH(0);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
fword("encode+");
|
|
|
|
|
PUSH(base);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
fword("encode+");
|
|
|
|
|
PUSH(SLAVIO_SIZE);
|
|
|
|
|
fword("encode-int");
|
|
|
|
|
fword("encode+");
|
|
|
|
|
push_str("ranges");
|
|
|
|
|
fword("property");
|
|
|
|
|
}
|
2006-05-18 21:57:08 +00:00
|
|
|
|
2006-05-22 22:10:54 +00:00
|
|
|
static void
|
|
|
|
|
ob_obio_decodeunit(__attribute__((unused)) int *idx)
|
|
|
|
|
{
|
|
|
|
|
fword("decode-unit-sbus");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ob_obio_encodeunit(__attribute__((unused)) int *idx)
|
|
|
|
|
{
|
|
|
|
|
fword("encode-unit-sbus");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NODE_METHODS(ob_obio) = {
|
2006-05-18 21:57:08 +00:00
|
|
|
{ NULL, ob_obio_initialize },
|
|
|
|
|
{ "open", ob_obio_open },
|
|
|
|
|
{ "close", ob_obio_close },
|
2006-05-22 22:10:54 +00:00
|
|
|
{ "encode-unit", ob_obio_encodeunit },
|
|
|
|
|
{ "decode-unit", ob_obio_decodeunit },
|
2006-05-18 21:57:08 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2006-05-22 22:10:54 +00:00
|
|
|
int
|
|
|
|
|
ob_obio_init(unsigned long slavio_base)
|
2006-05-18 21:57:08 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
|
|
//printk("Initializing OBIO devices...\n");
|
2006-05-22 22:10:54 +00:00
|
|
|
#if 0 // XXX
|
|
|
|
|
REGISTER_NAMED_NODE(ob_obio, "/obio");
|
|
|
|
|
device_end();
|
|
|
|
|
ob_set_obio_ranges(slavio_base);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
ob_zs_init(slavio_base, SLAVIO_ZS, ZS_INTR, 1, 1);
|
|
|
|
|
|
|
|
|
|
ob_zs_init(slavio_base, SLAVIO_ZS1, ZS_INTR, 0, 0);
|
|
|
|
|
|
|
|
|
|
ob_nvram_init(slavio_base, SLAVIO_NVRAM);
|
|
|
|
|
|
|
|
|
|
ob_fd_init(slavio_base, SLAVIO_FD, FD_INTR);
|
|
|
|
|
|
|
|
|
|
ob_sconfig_init(slavio_base, SLAVIO_SCONFIG);
|
|
|
|
|
|
|
|
|
|
ob_auxio_init(slavio_base, SLAVIO_AUXIO);
|
|
|
|
|
|
|
|
|
|
ob_power_init(slavio_base, SLAVIO_POWER, POWER_INTR);
|
|
|
|
|
|
|
|
|
|
ob_counter_init(slavio_base, SLAVIO_COUNTER);
|
|
|
|
|
|
|
|
|
|
ob_interrupt_init(slavio_base, SLAVIO_INTERRUPT);
|
|
|
|
|
|
2006-05-18 21:57:08 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|