mirror of
https://github.com/Stichting-MINIX-Research-Foundation/netbsd.git
synced 2025-08-23 04:48:13 -04:00
315 lines
6.6 KiB
C
315 lines
6.6 KiB
C
/* $NetBSD: switch.c,v 1.2 2014/08/10 07:40:50 isaki Exp $ */
|
|
|
|
/*
|
|
* Copyright (c) 2014 Tetsuya Isaki. All rights reserved.
|
|
*
|
|
* 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.
|
|
*
|
|
* 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 <lib/libsa/stand.h>
|
|
#include <lib/libkern/libkern.h>
|
|
|
|
#include "switch.h"
|
|
|
|
#define SRAM_MEMSIZE (*((volatile uint32_t *)0x00ed0008))
|
|
#define SRAM_ROMADDR (*((volatile uint32_t *)0x00ed000c))
|
|
#define SRAM_RAMADDR (*((volatile uint32_t *)0x00ed0010))
|
|
#define SRAM_BOOTDEV (*((volatile uint16_t *)0x00ed0018))
|
|
|
|
#define SYSPORT_SRAM_WP (*((volatile uint8_t *)0x00e8e00d))
|
|
|
|
static int hextoi(const char *);
|
|
static void cmd_switch_help(void);
|
|
static void cmd_switch_show(void);
|
|
static void cmd_switch_show_boot(void);
|
|
static void cmd_switch_show_rom(void);
|
|
static void cmd_switch_show_memory(void);
|
|
static const char *romaddr_tostr(uint32_t);
|
|
static const char *get_romaddr_name(uint32_t);
|
|
static void cmd_switch_boot(const char *);
|
|
static void cmd_switch_rom(const char *);
|
|
static void cmd_switch_memory(const char *);
|
|
|
|
static inline void
|
|
sram_write_enable(void)
|
|
{
|
|
SYSPORT_SRAM_WP = 0x31;
|
|
}
|
|
|
|
static inline void
|
|
sram_write_disable(void)
|
|
{
|
|
SYSPORT_SRAM_WP = 0;
|
|
}
|
|
|
|
static int
|
|
hextoi(const char *in)
|
|
{
|
|
char *c;
|
|
int ret;
|
|
|
|
ret = 0;
|
|
c = (char *)in;
|
|
for (; isxdigit(*c); c++) {
|
|
ret = (ret * 16) +
|
|
(*c > '9' ? ((*c | 0x20) - 'a' + 10) : *c - '0');
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static void
|
|
cmd_switch_help(void)
|
|
{
|
|
printf(
|
|
"usage: switch <key>=<val>\n"
|
|
" boot=[std | inscsi<N> | exscsi<N> | fd<N> | rom ]\n"
|
|
" rom=[ inscsi<N> | exscsi<N> | $<addr> ]\n"
|
|
" memory=<1..12> (unit:MB)\n"
|
|
" switch show\n"
|
|
);
|
|
}
|
|
|
|
void
|
|
cmd_switch(char *arg)
|
|
{
|
|
char *val;
|
|
|
|
if (strcmp(arg, "show") == 0) {
|
|
cmd_switch_show();
|
|
return;
|
|
}
|
|
|
|
val = strchr(arg, '=');
|
|
if (val == NULL) {
|
|
cmd_switch_help();
|
|
return;
|
|
}
|
|
*val++ = '\0';
|
|
|
|
if (strcmp(arg, "boot") == 0) {
|
|
cmd_switch_boot(val);
|
|
} else if (strcmp(arg, "rom") == 0) {
|
|
cmd_switch_rom(val);
|
|
} else if (strcmp(arg, "memory") == 0) {
|
|
cmd_switch_memory(val);
|
|
} else {
|
|
cmd_switch_help();
|
|
}
|
|
}
|
|
|
|
static void
|
|
cmd_switch_show(void)
|
|
{
|
|
cmd_switch_show_boot();
|
|
cmd_switch_show_rom();
|
|
cmd_switch_show_memory();
|
|
}
|
|
|
|
static void
|
|
cmd_switch_show_boot(void)
|
|
{
|
|
uint32_t romaddr;
|
|
uint16_t bootdev;
|
|
const char *name;
|
|
|
|
bootdev = SRAM_BOOTDEV;
|
|
romaddr = SRAM_ROMADDR;
|
|
|
|
/*
|
|
* $0000: std
|
|
* $8n00: sasi<N>
|
|
* $9n70: fd<N>
|
|
* $a000: ROM
|
|
* $b000: RAM
|
|
*/
|
|
printf("boot=");
|
|
switch (bootdev >> 12) {
|
|
default:
|
|
case 0x0:
|
|
/*
|
|
* The real order is fd->sasi->rom->ram
|
|
* but it is a bit redundant..
|
|
*/
|
|
printf("std (fd -> ");
|
|
name = get_romaddr_name(romaddr);
|
|
if (name)
|
|
printf("%s)", name);
|
|
else
|
|
printf("rom$%x)", romaddr);
|
|
break;
|
|
case 0x8:
|
|
printf("sasi%d", (bootdev >> 8) & 15);
|
|
break;
|
|
case 0x9:
|
|
printf("fd%d", (bootdev >> 8) & 3);
|
|
break;
|
|
case 0xa:
|
|
printf("rom%s", romaddr_tostr(romaddr));
|
|
break;
|
|
case 0xb:
|
|
printf("ram$%x", SRAM_RAMADDR);
|
|
break;
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
static void
|
|
cmd_switch_show_rom(void)
|
|
{
|
|
uint32_t romaddr;
|
|
|
|
romaddr = SRAM_ROMADDR;
|
|
printf("rom=%s\n", romaddr_tostr(romaddr));
|
|
}
|
|
|
|
static void
|
|
cmd_switch_show_memory(void)
|
|
{
|
|
printf("memory=%d MB\n", SRAM_MEMSIZE / (1024 * 1024));
|
|
}
|
|
|
|
/* return rom address as string with name if any */
|
|
static const char *
|
|
romaddr_tostr(uint32_t addr)
|
|
{
|
|
static char buf[32];
|
|
const char *name;
|
|
|
|
name = get_romaddr_name(addr);
|
|
if (name)
|
|
snprintf(buf, sizeof(buf), "$%x (%s)", addr, name);
|
|
else
|
|
snprintf(buf, sizeof(buf), "$%x", addr);
|
|
|
|
return buf;
|
|
}
|
|
|
|
/*
|
|
* return "inscsiN" / "exscsiN" if addr is in range of SCSI boot.
|
|
* Otherwise return NULL.
|
|
*/
|
|
static const char *
|
|
get_romaddr_name(uint32_t addr)
|
|
{
|
|
static char buf[8];
|
|
|
|
if (0xfc0000 <= addr && addr < 0xfc0020 && addr % 4 == 0) {
|
|
snprintf(buf, sizeof(buf), "inscsi%d", (addr >> 2) & 7);
|
|
} else if (0xea0020 <= addr && addr < 0xea0040 && addr % 4 == 0) {
|
|
snprintf(buf, sizeof(buf), "exscsi%d", (addr >> 2) & 7);
|
|
} else {
|
|
return NULL;
|
|
}
|
|
return buf;
|
|
}
|
|
|
|
static void
|
|
cmd_switch_boot(const char *arg)
|
|
{
|
|
int id;
|
|
uint32_t romaddr;
|
|
uint16_t bootdev;
|
|
|
|
romaddr = 0xffffffff;
|
|
|
|
if (strcmp(arg, "std") == 0) {
|
|
bootdev = 0x0000;
|
|
|
|
} else if (strcmp(arg, "rom") == 0) {
|
|
bootdev = 0xa000;
|
|
|
|
} else if (strncmp(arg, "inscsi", 6) == 0) {
|
|
id = (arg[6] - '0') & 7;
|
|
bootdev = 0xa000;
|
|
romaddr = 0xfc0000 + id * 4;
|
|
|
|
} else if (strncmp(arg, "exscsi", 6) == 0) {
|
|
id = (arg[6] - '0') & 7;
|
|
bootdev = 0xa000;
|
|
romaddr = 0xea0020 + id * 4;
|
|
|
|
} else if (strncmp(arg, "fd", 2) == 0) {
|
|
id = (arg[2] - '0') & 3;
|
|
bootdev = 0x9070 | (id << 8);
|
|
|
|
} else {
|
|
cmd_switch_help();
|
|
return;
|
|
}
|
|
|
|
sram_write_enable();
|
|
SRAM_BOOTDEV = bootdev;
|
|
if (romaddr != 0xffffffff)
|
|
SRAM_ROMADDR = romaddr;
|
|
sram_write_disable();
|
|
|
|
cmd_switch_show_boot();
|
|
}
|
|
|
|
static void
|
|
cmd_switch_rom(const char *arg)
|
|
{
|
|
int id;
|
|
uint32_t romaddr;
|
|
|
|
if (strncmp(arg, "inscsi", 6) == 0) {
|
|
id = (arg[6] - '0') & 7;
|
|
romaddr = 0xfc0000 + id * 4;
|
|
|
|
} else if (strncmp(arg, "exscsi", 6) == 0) {
|
|
id = (arg[6] - '0') & 7;
|
|
romaddr = 0xea0020 + id * 4;
|
|
|
|
} else if (*arg == '$') {
|
|
romaddr = hextoi(arg + 1);
|
|
|
|
} else {
|
|
cmd_switch_help();
|
|
return;
|
|
}
|
|
|
|
sram_write_enable();
|
|
SRAM_ROMADDR = romaddr;
|
|
sram_write_disable();
|
|
|
|
cmd_switch_show_rom();
|
|
}
|
|
|
|
static void
|
|
cmd_switch_memory(const char *arg)
|
|
{
|
|
int num;
|
|
|
|
num = atoi(arg);
|
|
if (num < 1 || num > 12) {
|
|
cmd_switch_help();
|
|
return;
|
|
}
|
|
|
|
sram_write_enable();
|
|
SRAM_MEMSIZE = num * (1024 * 1024);
|
|
sram_write_disable();
|
|
|
|
cmd_switch_show_memory();
|
|
}
|