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