]> cloudbase.mooo.com Git - z180-stamp.git/blame - avr/cmd_boot.c
Update attach help text
[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"
14#include <stdlib.h>
8a7decea 15#include <ctype.h>
89adce76 16#include <util/atomic.h>
534e1dfc
L
17
18#include "command.h"
04b3ea0e
L
19#include "cli_readline.h" /* console_buffer[] */
20#include "cli.h" /* run_command() */
612a6965 21#include "env.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;
124 uint8_t stop_stage;
125 } boot_param;
126
127 struct {
128 uint8_t stop_stage;
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;
136 uint8_t stages;
137 uint32_t val;
138
139 (void) cmdtp; (void) flag;
140
141 /* get default values */
142 memcpy_P(&boot_param, cfboot, sizeof boot_param);
143 stages = boot_param.stop_stage;
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':
155 if (boot_param.stop_stage > 0)
156 boot_param.stop_stage--;
157 break;
158 case 'a':
159 val = strtoul(optarg, NULL, 16);
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':
167 val = strtoul(optarg, NULL, 16);
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':
175 val = strtoul(optarg, NULL, 16);
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':
183 val = strtoul(optarg, NULL, 10);
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 }
188 boot_param.loadaddr = val;
189 break;
190 case 'i':
191 val = strtoul(optarg, NULL, 16);
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
234 if (boot_param.stop_stage == 0) {
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"),
238 boot_param.stop_stage, stages);
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 {
260 if (boot_param.stop_stage == stages) {
261 my_puts_P(PSTR("Booting...\n"));
262 } else {
263 z80_bus_cmd(Reset);
264 printf_P(PSTR("Bootloader stopped at stage %d, result: %d, IDE stat/error: 0x%.02x/0x%.02x\n"),
265 boot_param.stop_stage - boot_res.stop_stage,
266 boot_res.result, boot_res.ide_stat, boot_res.ide_error);
267 }
268 }
269 }
270
271 return CMD_RET_SUCCESS;
272}
273
d0581f88 274command_ret_t do_busreq_pulse(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
534e1dfc 275{
f338df2a 276 uint16_t count=1;
534e1dfc 277
f338df2a 278 (void) cmdtp; (void) flag;
534e1dfc 279
6035a17b 280 if (!(z80_bus_state() & ZST_RUNNING)) {
f338df2a 281 printf_P(PSTR("## CPU is not running!\n"));
d0581f88 282 return CMD_RET_FAILURE;
534e1dfc
L
283 }
284
f338df2a 285 if (argc > 1)
19a463f4 286 count = (uint16_t) strtoul(argv[1], NULL, 16);
f338df2a 287
62f624d3 288 z80_bus_cmd(Request);
f338df2a 289 while (count--)
62f624d3 290 z80_bus_cmd(M_Cycle);
534e1dfc 291
d0581f88 292 return CMD_RET_SUCCESS;
f338df2a
L
293}
294
295
d0581f88 296command_ret_t do_go(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
f338df2a
L
297{
298 uint32_t addr;
299
300 (void) cmdtp; (void) flag;
6035a17b 301
f338df2a
L
302 if (argc < 2)
303 return CMD_RET_USAGE;
304 addr = strtoul(argv[1], NULL, 16);
305 if (addr >= (1UL<<16)) {
534e1dfc
L
306 printf_P(PSTR("## Startaddress 0x%05lx too high.\n"
307 " (Out of logical address space (0x00000-0x0ffff))\n"),
308 addr);
d0581f88 309 return CMD_RET_FAILURE;
6035a17b 310 }
f338df2a 311
6035a17b 312 if (z80_bus_state() & ZST_RUNNING) {
f338df2a 313 printf_P(PSTR("## CPU allready running!\n"));
d0581f88 314 return CMD_RET_FAILURE;
534e1dfc
L
315 }
316
f338df2a
L
317 printf_P(PSTR("## Starting application at 0x%04lx ...\n"), addr);
318
319 if (addr != 0) {
320 uint8_t tmp[3];
6035a17b 321
62f624d3 322 z80_bus_cmd(Request);
19a463f4 323 z80_read_block (tmp, 0, 3);
f338df2a
L
324 z80_write(0, 0xc3);
325 z80_write(1, addr);
326 z80_write(2, (addr >> 8));
327
62f624d3
L
328 z80_bus_cmd(Run);
329 z80_bus_cmd(M_Cycle);
330 z80_bus_cmd(M_Cycle);
19a463f4 331 z80_write_block(tmp, 0, 3);
f338df2a 332 } else
62f624d3 333 z80_bus_cmd(Run);
6035a17b 334
62f624d3 335 z80_bus_cmd(Release);
f338df2a 336
d0581f88 337 return CMD_RET_SUCCESS;
534e1dfc
L
338}
339
8a7decea
L
340static
341void reset_cpu(bus_cmd_t mode)
342{
343 restart_z180_serv();
344 z80_bus_cmd(mode);
345}
346
347
d0581f88 348command_ret_t do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
534e1dfc
L
349{
350 (void) cmdtp; (void) flag; (void) argc; (void) argv;
351
612a6965 352 printf_P(PSTR("CPU now in reset state.\n"));
534e1dfc 353
8a7decea 354 reset_cpu(Reset);
d0581f88 355 return CMD_RET_SUCCESS;
534e1dfc
L
356}
357
d0581f88 358command_ret_t do_restart(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
534e1dfc
L
359{
360 (void) cmdtp; (void) flag; (void) argc; (void) argv;
361
8a7decea 362 reset_cpu(Restart);
534e1dfc 363
d0581f88 364 return CMD_RET_SUCCESS;
534e1dfc
L
365}
366
8a7decea
L
367static
368void print_con_usage(char esc)
369{ printf_P(PSTR("\n"
370 "------------------------------------------------\n"
371 " ?,H - This Help\n"
8a7decea 372 " Q,X - Return to command line\n"
b08e079d
L
373 " R - Reset (Restart) CPU\n"
374 " : - Execute monitor command\n"
612a6965
L
375 " \\ - code input:\n"
376 " \\nnn 3 decimal digits character code\n"
377 " \\Xhh 2 hexadecimal digits character code\n"
378 " ^%c - (Escape char) Type again to send itself\n"
8a7decea
L
379 "key>"
380 ), esc + 0x40);
381}
89adce76
L
382
383command_ret_t do_console(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
384{
385 int ch;
8a7decea
L
386 uint8_t pending;
387// uint8_t help_prompt = 0;
388 uint8_t code = 0;
389 uint8_t state = 0;
612a6965 390 char esc_char = (char) getenv_ulong(PSTR(ENV_ESC_CHAR), 16, CONFIG_ESC_CHAR);
ea6971b8 391
89adce76
L
392 (void) cmdtp; (void) flag; (void) argc; (void) argv;
393
b08e079d
L
394 printf_P(PSTR("Connecting to CPU. Escape character is '^%c'.\n"),
395 esc_char + 0x40);
89adce76
L
396
397 while (1) {
398
8a7decea 399 ATOMIC_BLOCK(ATOMIC_FORCEON) {
89adce76
L
400 pending = (Stat & S_CON_PENDING) != 0;
401 Stat &= ~S_CON_PENDING;
402 }
3ad4143b
L
403 if (pending) {
404 uint8_t count = 100;
405 while ((ch = z80_memfifo_getc(fifo_conout)) >= 0 && --count)
89adce76 406 putchar(ch);
3ad4143b 407 }
89adce76
L
408
409 if ((ch = my_getchar(0)) >= 0) {
410 switch (state) {
411 case 0:
612a6965 412 if (ch == esc_char) {
89adce76
L
413 state = 1;
414 /* TODO: Timer starten */
415 } else {
416 z80_memfifo_putc(fifo_conin, ch);
ea6971b8 417 }
89adce76 418 break;
8a7decea
L
419 case 2:
420 printf_P(PSTR("\n"
421 "------------------------------------------------\n"));
89adce76 422 case 1:
8a7decea
L
423 state = 0;
424 switch (toupper(ch)) {
89adce76 425
8a7decea
L
426 case '?':
427 case 'H':
612a6965 428 print_con_usage(esc_char);
8a7decea 429 state = 2;
89adce76
L
430 break;
431
8a7decea
L
432 case 'R':
433 reset_cpu(Restart);
89adce76
L
434 break;
435
8a7decea 436 case 'X':
89adce76 437 case 'Q':
889202c4 438 printf_P(PSTR("\n"));
89adce76
L
439 goto quit;
440 break;
441
b08e079d
L
442 case ':':
443 putchar('\n');
8ed66016 444 int cmdlen = cli_readline(PSTR(": "), 1);
b08e079d
L
445 if (cmdlen > 0)
446 run_command(console_buffer, 0);
447 break;
448
8a7decea
L
449 case '\\':
450 code = 0;
451 state = 3;
452 break;
453
8a7decea 454 default:
612a6965
L
455 if (ch == esc_char)
456 z80_memfifo_putc(fifo_conin, ch);
8a7decea
L
457 break;
458 }
459 break;
460 case 3:
461 if (toupper(ch) == 'X') {
462 state = 6;
463 break;
464 }
465 /* fall thru */
466 case 4:
467 case 5:
468 if (isdigit(ch)) {
469 code = code * 10 + ch - '0';
470 state++;
b08e079d
L
471 } else {
472 if (state > 3)
473 z80_memfifo_putc(fifo_conin, code);
474 z80_memfifo_putc(fifo_conin, ch);
475 state = 0;
8a7decea
L
476 }
477 if (state > 5) {
478 z80_memfifo_putc(fifo_conin, code);
479 state = 0;
480 }
481 break;
482 case 6:
483 case 7:
484 if (isxdigit(ch)) {
485 ch = toupper(ch);
486 if (ch >= 'A')
487 ch -= 'A' - 10;
488 code = code * 16 + ch - '0';
489 state++;
b08e079d
L
490 }else {
491 if (state > 6)
492 z80_memfifo_putc(fifo_conin, code);
493 z80_memfifo_putc(fifo_conin, ch);
494 state = 0;
8a7decea
L
495 }
496 if (state > 7) {
497 z80_memfifo_putc(fifo_conin, code);
498 state = 0;
89adce76 499 }
89adce76
L
500 break;
501 }
502 }
89adce76
L
503 }
504quit:
89adce76
L
505 return CMD_RET_SUCCESS;
506}