]> cloudbase.mooo.com Git - z180-stamp.git/blame_incremental - avr/cmd_boot.c
Remove compiler warnings
[z180-stamp.git] / avr / cmd_boot.c
... / ...
CommitLineData
1/*
2 * (C) Copyright 2014-2016 Leo C. <erbl259-lmu@yahoo.de>
3 *
4 * (C) Copyright 2000-2003
5 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
6 *
7 * SPDX-License-Identifier: GPL-2.0
8 */
9
10/*
11 * Misc boot support
12 */
13#include "cmd_boot.h"
14#include <ctype.h>
15#include <util/atomic.h>
16
17#include "cli_readline.h" /* console_buffer[] */
18#include "cli.h" /* run_command() */
19#include "env.h"
20#include "eval_arg.h"
21#include "con-utils.h"
22#include "getopt-min.h"
23#include "z80-if.h"
24#include "z180-serv.h" /* restart_z180_serv() */
25#include "debug.h"
26
27/* ugly hack to get Z180 loadfile into flash memory */
28#define const const FLASH
29#include "../z180/hdrom.h"
30#include "../z180/cfboot.h"
31#undef const
32
33
34command_ret_t do_loadf(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
35{
36 if (z80_bus_state() & ZST_RUNNING)
37 cmd_error(CMD_RET_FAILURE, ERUNNING, NULL);
38 z80_bus_request_or_exit();
39 z80_load_mem(2, hdrom,
40 &hdrom_sections,
41 hdrom_address,
42 hdrom_length_of_sections);
43
44 z80_bus_cmd(Release);
45
46 return CMD_RET_SUCCESS;
47}
48
49
50void print_vars(char *title)
51{
52 uint8_t buf[5];
53 zstate_t state = z80_bus_state();
54
55 if((state & ZST_ACQUIRED) == 0)
56 z80_bus_cmd(Request);
57
58 z80_read_block(buf, 9, sizeof buf);
59
60 if((state & ZST_ACQUIRED) == 0)
61 z80_bus_cmd(Release);
62
63 printf_P(PSTR("%s: stage: %d, flag: 0x%.02x, result: %d, IDE stat/error: 0x%.02x/0x%.02x\n"),
64 title, buf[0], buf[1], buf[2], buf[3], buf[4]);
65}
66
67
68/*
69 * bootcf [options]
70 *
71 * -a address (100h)
72 * -s start sector (0)
73 * -c sector count (7)
74 * -i Partition id (52)
75 * -n load only
76 * -t timeout (10000)
77 * -v verbose
78 */
79
80command_ret_t do_bootcf(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[])
81{
82 struct {
83 uint8_t jr[2];
84 uint16_t loadaddr;
85 uint8_t sec_start;
86 uint8_t sec_cnt;
87 uint8_t part_id;
88 uint16_t timeout;
89 uint8_t stages;
90 } boot_param;
91
92 struct {
93 uint8_t stages;
94 uint8_t done;
95 uint8_t result;
96 uint8_t ide_stat;
97 uint8_t ide_error;
98 } boot_res;
99
100 int_fast8_t verbosity = 0;
101 uint8_t default_stages;
102 uint32_t val;
103
104 /* get default values */
105 memcpy_P(&boot_param, cfboot, sizeof boot_param);
106 default_stages = boot_param.stages;
107
108 int opt;
109 while ((opt = getopt(argc, argv, PSTR("vna:s:c:t:i:"))) != -1) {
110 switch (opt) {
111 case 'v':
112 verbosity++;
113 break;
114 case 'n':
115 if (boot_param.stages > 0)
116 boot_param.stages--;
117 break;
118 case 'a':
119 val = eval_arg(optarg, NULL);
120 if (val < 0x100 || val > 0xFE00) {
121 printf_P(PSTR("Address out of range: 0x%.4lX\n"), val);
122 return CMD_RET_FAILURE;
123 }
124 boot_param.loadaddr = val;
125 break;
126 case 's':
127 val = eval_arg(optarg, NULL);
128 if (val > 255) {
129 printf_P(PSTR("Start sector out of range: 0x%lX\n"), val);
130 return CMD_RET_FAILURE;
131 }
132 boot_param.sec_start = val;
133 break;
134 case 'c':
135 val = eval_arg(optarg, NULL);
136 if (val > 127) {
137 printf_P(PSTR("Sector count out of range: 0x%lX\n"), val);
138 return CMD_RET_FAILURE;
139 }
140 boot_param.sec_cnt = val;
141 break;
142 case 't':
143 val = eval_arg(optarg, NULL);
144 if (val < 0x1 || val > 0xFFFF) {
145 printf_P(PSTR("Timeout value out of range: 0x%lX\n"), val);
146 return CMD_RET_FAILURE;
147 }
148 boot_param.timeout = val;
149 break;
150 case 'i':
151 val = eval_arg(optarg, NULL);
152 if (val < 0x01 || val > 0xFF) {
153 printf_P(PSTR("Partition id out of range: 0x%lX\n"), val);
154 return CMD_RET_FAILURE;
155 }
156 boot_param.part_id = val;
157 break;
158 default: /* '?' */
159 return CMD_RET_USAGE;
160 }
161 }
162
163 /* remaining arguments */
164 argc -= optind;
165 if (argc) {
166 my_puts_P(PSTR("Argument error!\n"));
167 return CMD_RET_USAGE;
168 }
169
170 if ((val = (uint32_t) boot_param.loadaddr + boot_param.sec_cnt * 512) >= 0xFF00) {
171 printf_P(PSTR("Top address out of range: 0x%.4lX\n"), val);
172 return CMD_RET_FAILURE;
173 }
174
175 if (z80_bus_state() & ZST_RUNNING)
176 cmd_error(CMD_RET_FAILURE, ERUNNING, NULL);
177 z80_bus_request_or_exit();
178 z80_load_mem(verbosity, cfboot,
179 &cfboot_sections,
180 cfboot_address,
181 cfboot_length_of_sections);
182
183 z80_write_block((const uint8_t *) &boot_param,
184 cfboot_address[0], sizeof boot_param);
185 z80_bus_cmd(Release);
186
187 if (boot_param.stages == 0) {
188 printf_P(PSTR("Bootloader loaded at: 0x%.4X\n"), (uint16_t) cfboot_address[0]);
189 } else {
190 printf_P(PSTR("Executing %d of %d Bootloader stages...\n"),
191 boot_param.stages, default_stages);
192
193 z80_bus_cmd(Run);
194 z80_bus_cmd(Release);
195
196 clear_ctrlc(); /* forget any previous Control C */
197 for (boot_res.done = 0; boot_res.done != 0xFF;) {
198 _delay_ms(8);
199 /* check for ctrl-c to abort... */
200 if (had_ctrlc() || ctrlc()) {
201 break;
202 }
203 z80_bus_cmd(Request);
204 z80_read_block((uint8_t *) &boot_res,
205 cfboot_address[0]+sizeof boot_param - 1, sizeof boot_res);
206 z80_bus_cmd(Release);
207 }
208
209 if (boot_res.done != 0xFF) {
210 z80_bus_cmd(Reset);
211 my_puts_P(PSTR("Abort\n"));
212 } else {
213 if (boot_param.stages == default_stages &&
214 boot_res.stages == 0 &&
215 boot_res.result == 0) {
216 my_puts_P(PSTR("Booting...\n"));
217 } else {
218 z80_bus_cmd(Reset);
219 boot_res.stages++;
220 printf_P(PSTR("Bootloader stopped at stage %d, result: %d, IDE stat/error: 0x%.02x/0x%.02x\n"),
221 boot_param.stages - boot_res.stages,
222 boot_res.result, boot_res.ide_stat, boot_res.ide_error);
223 }
224 }
225 }
226
227 return CMD_RET_SUCCESS;
228}
229
230command_ret_t do_busreq_pulse(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[])
231{
232 uint16_t count=1;
233
234 if (!(z80_bus_state() & ZST_RUNNING)) {
235 printf_P(PSTR("## CPU is not running!\n"));
236 return CMD_RET_FAILURE;
237 }
238
239 if (argc > 1)
240 count = (uint16_t) eval_arg(argv[1], NULL);
241
242 z80_bus_cmd(Request);
243 while (count--)
244 z80_bus_cmd(M_Cycle);
245
246 return CMD_RET_SUCCESS;
247}
248
249
250command_ret_t do_go(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[])
251{
252 uint32_t addr;
253 bool hold = 0;
254
255 int opt;
256 while ((opt = getopt(argc, argv, PSTR("h"))) != -1) {
257 switch (opt) {
258 case 'h':
259 hold = 1;
260 break;
261 default: /* '?' */
262 return CMD_RET_USAGE;
263 }
264 }
265 argc -= optind; /* remaining arguments */
266
267 if (argc != 1)
268 return CMD_RET_USAGE;
269 addr = eval_arg(argv[optind], NULL);
270 if (addr >= (1UL<<16)) {
271 printf_P(PSTR("Invalid startaddress: 0x%05lx\n"
272 " (Out of logical address space (0x00000-0x0ffff))\n"),
273 addr);
274 return CMD_RET_FAILURE;
275 }
276
277 if (z80_bus_state() & ZST_RUNNING) {
278 printf_P(PSTR("CPU already running!\n"));
279 return CMD_RET_FAILURE;
280 }
281
282 printf_P(PSTR("Starting application at 0x%04lx ...\n"), addr);
283
284 if (addr != 0) {
285 uint8_t tmp[3];
286
287 z80_bus_cmd(Request);
288 z80_read_block (tmp, 0, 3);
289 z80_write(0, 0xc3);
290 z80_write(1, addr);
291 z80_write(2, (addr >> 8));
292
293 z80_bus_cmd(Run);
294 _delay_us(10);
295 z80_bus_cmd(M_Cycle);
296 _delay_us(10);
297 z80_bus_cmd(M_Cycle);
298 _delay_us(10);
299 z80_write_block(tmp, 0, 3);
300 } else {
301 if (!hold)
302 z80_bus_cmd(Request);
303 z80_bus_cmd(Run);
304 }
305 if (!hold)
306 z80_bus_cmd(Release);
307
308 return CMD_RET_SUCCESS;
309}
310
311static
312void reset_cpu(bus_cmd_t mode)
313{
314 restart_z180_serv();
315 z80_bus_cmd(mode);
316}
317
318
319command_ret_t do_reset(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
320{
321 printf_P(PSTR("CPU now in reset state.\n"));
322
323 reset_cpu(Reset);
324 return CMD_RET_SUCCESS;
325}
326
327command_ret_t do_restart(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
328{
329 reset_cpu(Restart);
330
331 return CMD_RET_SUCCESS;
332}
333
334static
335void print_con_usage(char esc)
336{ printf_P(PSTR("\n"
337 "------------------------------------------------\n"
338 " ?,H - This Help\n"
339 " Q,X - Return to command line\n"
340 " R - Reset (Restart) CPU\n"
341 " : - Execute monitor command\n"
342 " \\ - code input:\n"
343 " \\nnn 3 decimal digits character code\n"
344 " \\Xhh 2 hexadecimal digits character code\n"
345 " ^%c - (Escape char) Type again to send itself\n"
346 "key>"
347 ), esc + 0x40);
348}
349
350command_ret_t do_console(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
351{
352 int ch;
353 uint8_t pending;
354 uint8_t code = 0;
355 uint8_t state = 0;
356 char esc_char = (char) getenv_ulong(PSTR(ENV_ESC_CHAR), 16, CONFIG_ESC_CHAR);
357
358 printf_P(PSTR("Connecting to CPU. Escape character is '^%c'.\n"),
359 esc_char + 0x40);
360
361 while (1) {
362
363 ATOMIC_BLOCK(ATOMIC_FORCEON) {
364 pending = (Stat & S_CON_PENDING) != 0;
365 Stat &= ~S_CON_PENDING;
366 }
367 if (pending) {
368 uint8_t count = 100;
369 while ((ch = z80_memfifo_getc(fifo_conout)) >= 0 && --count)
370 putchar(ch);
371 }
372
373 if ((ch = my_getchar(0)) >= 0) {
374 switch (state) {
375 case 0:
376 if (ch == esc_char) {
377 state = 1;
378 /* TODO: Timer starten */
379 } else {
380 z80_memfifo_putc(fifo_conin, ch);
381 }
382 break;
383 case 2:
384 my_puts_P(PSTR("\n"
385 "------------------------------------------------\n"));
386 case 1:
387 state = 0;
388 switch (toupper(ch)) {
389
390 case '?':
391 case 'H':
392 print_con_usage(esc_char);
393 state = 2;
394 break;
395
396 case 'R':
397 reset_cpu(Restart);
398 break;
399
400 case 'X':
401 case 'Q':
402 putchar('\n');
403 goto quit;
404 break;
405
406 case ':':
407 putchar('\n');
408 int cmdlen = cli_readline(PSTR(": "), 1);
409 if (cmdlen > 0)
410 run_command(console_buffer, 0);
411 break;
412
413 case '\\':
414 code = 0;
415 state = 3;
416 break;
417
418 default:
419 if (ch == esc_char)
420 z80_memfifo_putc(fifo_conin, ch);
421 break;
422 }
423 break;
424 case 3:
425 if (toupper(ch) == 'X') {
426 state = 6;
427 break;
428 }
429 /* fall thru */
430 case 4:
431 case 5:
432 if (isdigit(ch)) {
433 code = code * 10 + ch - '0';
434 state++;
435 } else {
436 if (state > 3)
437 z80_memfifo_putc(fifo_conin, code);
438 z80_memfifo_putc(fifo_conin, ch);
439 state = 0;
440 }
441 if (state > 5) {
442 z80_memfifo_putc(fifo_conin, code);
443 state = 0;
444 }
445 break;
446 case 6:
447 case 7:
448 if (isxdigit(ch)) {
449 ch = toupper(ch);
450 if (ch >= 'A')
451 ch -= 'A' - 10;
452 code = code * 16 + ch - '0';
453 state++;
454 }else {
455 if (state > 6)
456 z80_memfifo_putc(fifo_conin, code);
457 z80_memfifo_putc(fifo_conin, ch);
458 state = 0;
459 }
460 if (state > 7) {
461 z80_memfifo_putc(fifo_conin, code);
462 state = 0;
463 }
464 break;
465 }
466 }
467 }
468quit:
469 return CMD_RET_SUCCESS;
470}