Home | History | Annotate | Line # | Download | only in boot
switch.c revision 1.1
      1 /*	$NetBSD: switch.c,v 1.1 2014/08/05 13:49:04 isaki Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2014 Tetsuya Isaki. All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     20  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     22  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     23  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25  * SUCH DAMAGE.
     26  */
     27 
     28 #include <sys/param.h>
     29 #include <lib/libsa/stand.h>
     30 #include <lib/libkern/libkern.h>
     31 
     32 #include "switch.h"
     33 
     34 #define SRAM_MEMSIZE	(*((volatile uint32_t *)0x00ed0008))
     35 #define SRAM_ROMADDR	(*((volatile uint32_t *)0x00ed000c))
     36 #define SRAM_RAMADDR	(*((volatile uint32_t *)0x00ed0010))
     37 #define SRAM_BOOTDEV	(*((volatile uint16_t *)0x00ed0018))
     38 
     39 #define SYSPORT_SRAM_WP	(*((volatile uint8_t *)0x00e8e00d))
     40 
     41 static int hextoi(const char *);
     42 static void cmd_switch_help(void);
     43 static void cmd_switch_show(void);
     44 static void cmd_switch_show_boot(void);
     45 static void cmd_switch_show_rom(void);
     46 static void cmd_switch_show_memory(void);
     47 static const char *romaddr_tostr(uint32_t);
     48 static const char *get_romaddr_name(uint32_t);
     49 static void cmd_switch_boot(const char *);
     50 static void cmd_switch_rom(const char *);
     51 static void cmd_switch_memory(const char *);
     52 
     53 static inline void
     54 sram_write_enable(void)
     55 {
     56 	SYSPORT_SRAM_WP = 0x31;
     57 }
     58 
     59 static inline void
     60 sram_write_disable(void)
     61 {
     62 	SYSPORT_SRAM_WP = 0;
     63 }
     64 
     65 static int
     66 atoi(const char *in)
     67 {
     68 	char *c;
     69 	int ret;
     70 
     71 	ret = 0;
     72 	c = (char *)in;
     73 	if (*c == '-')
     74 		c++;
     75 	for (; isdigit(*c); c++)
     76 		ret = (ret * 10) + (*c - '0');
     77 
     78 	return (*in == '-') ? -ret : ret;
     79 }
     80 
     81 static int
     82 hextoi(const char *in)
     83 {
     84 	char *c;
     85 	int ret;
     86 
     87 	ret = 0;
     88 	c = (char *)in;
     89 	for (; isxdigit(*c); c++) {
     90 		ret = (ret * 16) +
     91 		      (*c > '9' ? ((*c | 0x20) - 'a' + 10) : *c - '0');
     92 	}
     93 	return ret;
     94 }
     95 
     96 static void
     97 cmd_switch_help(void)
     98 {
     99 	printf(
    100 		"usage: switch <key>=<val>\n"
    101 		"         boot=[std | inscsi<N> | exscsi<N> | fd<N> | rom ]\n"
    102 		"         rom=[ inscsi<N> | exscsi<N> | $<addr> ]\n"
    103 		"         memory=<1..12> (unit:MB)\n"
    104 		"       switch show\n"
    105 	);
    106 }
    107 
    108 void
    109 cmd_switch(char *arg)
    110 {
    111 	char *val;
    112 
    113 	if (strcmp(arg, "show") == 0) {
    114 		cmd_switch_show();
    115 		return;
    116 	}
    117 
    118 	val = strchr(arg, '=');
    119 	if (val == NULL) {
    120 		cmd_switch_help();
    121 		return;
    122 	}
    123 	*val++ = '\0';
    124 
    125 	if (strcmp(arg, "boot") == 0) {
    126 		cmd_switch_boot(val);
    127 	} else if (strcmp(arg, "rom") == 0) {
    128 		cmd_switch_rom(val);
    129 	} else if (strcmp(arg, "memory") == 0) {
    130 		cmd_switch_memory(val);
    131 	} else {
    132 		cmd_switch_help();
    133 	}
    134 }
    135 
    136 static void
    137 cmd_switch_show(void)
    138 {
    139 	cmd_switch_show_boot();
    140 	cmd_switch_show_rom();
    141 	cmd_switch_show_memory();
    142 }
    143 
    144 static void
    145 cmd_switch_show_boot(void)
    146 {
    147 	uint32_t romaddr;
    148 	uint16_t bootdev;
    149 	const char *name;
    150 
    151 	bootdev = SRAM_BOOTDEV;
    152 	romaddr = SRAM_ROMADDR;
    153 
    154 	/*
    155 	 * $0000: std
    156 	 * $8n00: sasi<N>
    157 	 * $9n70: fd<N>
    158 	 * $a000: ROM
    159 	 * $b000: RAM
    160 	 */
    161 	printf("boot=");
    162 	switch (bootdev >> 12) {
    163 	default:
    164 	case 0x0:
    165 		/*
    166 		 * The real order is fd->sasi->rom->ram
    167 		 * but it is a bit redundant..
    168 		 */
    169 		printf("std (fd -> ");
    170 		name = get_romaddr_name(romaddr);
    171 		if (name)
    172 			printf("%s)", name);
    173 		else
    174 			printf("rom$%x)", romaddr);
    175 		break;
    176 	case 0x8:
    177 		printf("sasi%d", (bootdev >> 8) & 15);
    178 		break;
    179 	case 0x9:
    180 		printf("fd%d", (bootdev >> 8) & 3);
    181 		break;
    182 	case 0xa:
    183 		printf("rom%s", romaddr_tostr(romaddr));
    184 		break;
    185 	case 0xb:
    186 		printf("ram$%x", SRAM_RAMADDR);
    187 		break;
    188 	}
    189 	printf("\n");
    190 }
    191 
    192 static void
    193 cmd_switch_show_rom(void)
    194 {
    195 	uint32_t romaddr;
    196 
    197 	romaddr = SRAM_ROMADDR;
    198 	printf("rom=%s\n", romaddr_tostr(romaddr));
    199 }
    200 
    201 static void
    202 cmd_switch_show_memory(void)
    203 {
    204 	printf("memory=%d MB\n", SRAM_MEMSIZE / (1024 * 1024));
    205 }
    206 
    207 /* return rom address as string with name if any */
    208 static const char *
    209 romaddr_tostr(uint32_t addr)
    210 {
    211 	static char buf[32];
    212 	const char *name;
    213 
    214 	name = get_romaddr_name(addr);
    215 	if (name)
    216 		snprintf(buf, sizeof(buf), "$%x (%s)", addr, name);
    217 	else
    218 		snprintf(buf, sizeof(buf), "$%x", addr);
    219 
    220 	return buf;
    221 }
    222 
    223 /*
    224  * return "inscsiN" / "exscsiN" if addr is in range of SCSI boot.
    225  * Otherwise return NULL.
    226  */
    227 static const char *
    228 get_romaddr_name(uint32_t addr)
    229 {
    230 	static char buf[8];
    231 
    232 	if (0xfc0000 <= addr && addr < 0xfc0020 && addr % 4 == 0) {
    233 		snprintf(buf, sizeof(buf), "inscsi%d", (addr >> 2) & 7);
    234 	} else if (0xea0020 <= addr && addr < 0xea0040 && addr % 4 == 0) {
    235 		snprintf(buf, sizeof(buf), "exscsi%d", (addr >> 2) & 7);
    236 	} else {
    237 		return NULL;
    238 	}
    239 	return buf;
    240 }
    241 
    242 static void
    243 cmd_switch_boot(const char *arg)
    244 {
    245 	int id;
    246 	uint32_t romaddr;
    247 	uint16_t bootdev;
    248 
    249 	romaddr = 0xffffffff;
    250 
    251 	if (strcmp(arg, "std") == 0) {
    252 		bootdev = 0x0000;
    253 
    254 	} else if (strcmp(arg, "rom") == 0) {
    255 		bootdev = 0xa000;
    256 
    257 	} else if (strncmp(arg, "inscsi", 6) == 0) {
    258 		id = (arg[6] - '0') & 7;
    259 		bootdev = 0xa000;
    260 		romaddr = 0xfc0000 + id * 4;
    261 
    262 	} else if (strncmp(arg, "exscsi", 6) == 0) {
    263 		id = (arg[6] - '0') & 7;
    264 		bootdev = 0xa000;
    265 		romaddr = 0xea0020 + id * 4;
    266 
    267 	} else if (strncmp(arg, "fd", 2) == 0) {
    268 		id = (arg[2] - '0') & 3;
    269 		bootdev = 0x9070 | (id << 8);
    270 
    271 	} else {
    272 		cmd_switch_help();
    273 		return;
    274 	}
    275 
    276 	sram_write_enable();
    277 	SRAM_BOOTDEV = bootdev;
    278 	if (romaddr != 0xffffffff)
    279 		SRAM_ROMADDR = romaddr;
    280 	sram_write_disable();
    281 
    282 	cmd_switch_show_boot();
    283 }
    284 
    285 static void
    286 cmd_switch_rom(const char *arg)
    287 {
    288 	int id;
    289 	uint32_t romaddr;
    290 
    291 	if (strncmp(arg, "inscsi", 6) == 0) {
    292 		id = (arg[6] - '0') & 7;
    293 		romaddr = 0xfc0000 + id * 4;
    294 
    295 	} else if (strncmp(arg, "exscsi", 6) == 0) {
    296 		id = (arg[6] - '0') & 7;
    297 		romaddr = 0xea0020 + id * 4;
    298 
    299 	} else if (*arg == '$') {
    300 		romaddr = hextoi(arg + 1);
    301 
    302 	} else {
    303 		cmd_switch_help();
    304 		return;
    305 	}
    306 
    307 	sram_write_enable();
    308 	SRAM_ROMADDR = romaddr;
    309 	sram_write_disable();
    310 
    311 	cmd_switch_show_rom();
    312 }
    313 
    314 static void
    315 cmd_switch_memory(const char *arg)
    316 {
    317 	int num;
    318 
    319 	num = atoi(arg);
    320 	if (num < 1 || num > 12) {
    321 		cmd_switch_help();
    322 		return;
    323 	}
    324 
    325 	sram_write_enable();
    326 	SRAM_MEMSIZE = num * (1024 * 1024);
    327 	sram_write_disable();
    328 
    329 	cmd_switch_show_memory();
    330 }
    331