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