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