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