X-Git-Url: http://cloudbase.mooo.com/gitweb/z180-stamp.git/blobdiff_plain/612a69655af9bed89a1ad9e7e9225dfb3ed3ff42..78c900276102731b2832eb623b6d7216a32bd500:/avr/cmd_boot.c diff --git a/avr/cmd_boot.c b/avr/cmd_boot.c index 448ed48..b00d062 100644 --- a/avr/cmd_boot.c +++ b/avr/cmd_boot.c @@ -1,10 +1,10 @@ /* - * (C) Copyright 2014 Leo C. + * (C) Copyright 2014-2016 Leo C. * * (C) Copyright 2000-2003 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * - * SPDX-License-Identifier: GPL-2.0+ + * SPDX-License-Identifier: GPL-2.0 */ /* @@ -16,37 +16,46 @@ #include #include "command.h" +#include "cli_readline.h" /* console_buffer[] */ +#include "cli.h" /* run_command() */ #include "env.h" #include "con-utils.h" +#include "getopt-min.h" #include "z80-if.h" -#include "z180-serv.h" +#include "z180-serv.h" /* restart_z180_serv() */ #include "debug.h" /* ugly hack to get Z180 loadfile into flash memory */ #define const const FLASH #include "../z180/hdrom.h" +#include "../z180/cfboot.h" #undef const -static void z80_load_mem(void) +static void z80_load_mem(int_fast8_t verbosity, + const FLASH unsigned char data[], + const FLASH unsigned long *sections, + const FLASH unsigned long address[], + const FLASH unsigned long length_of_sections[]) { - unsigned sec = 0; - uint32_t sec_base = hdrom_start; - - printf_P(PSTR("Loading Z180 memory... \n")); - - while (sec < hdrom_sections) { - printf_P(PSTR(" From: 0x%.5lX to: 0x%.5lX (%5li bytes)\n"), - hdrom_address[sec], - hdrom_address[sec]+hdrom_length_of_sections[sec] - 1, - hdrom_length_of_sections[sec]); - - z80_write_block_P((const FLASH unsigned char *) &hdrom[sec_base], /* src */ - hdrom_address[sec], /* dest */ - hdrom_length_of_sections[sec]); /* len */ - sec_base+=hdrom_length_of_sections[sec]; - sec++; + uint32_t sec_base = 0; + + if (verbosity > 1) + printf_P(PSTR("Loading Z180 memory... \n")); + + for (unsigned sec = 0; sec < *sections; sec++) { + if (verbosity > 0) { + printf_P(PSTR(" From: 0x%.5lX to: 0x%.5lX (%5li bytes)\n"), + address[sec], + address[sec]+length_of_sections[sec] - 1, + length_of_sections[sec]); + } + + z80_write_block_P((const FLASH unsigned char *) &data[sec_base], /* src */ + address[sec], /* dest */ + length_of_sections[sec]); /* len */ + sec_base += length_of_sections[sec]; } } @@ -62,13 +71,206 @@ command_ret_t do_loadf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] my_puts_P(PSTR("Bus timeout\n")); return CMD_RET_FAILURE; } - z80_load_mem(); + z80_load_mem(2, hdrom, + &hdrom_sections, + hdrom_address, + hdrom_length_of_sections); + z80_bus_cmd(Release); return CMD_RET_SUCCESS; } +void print_vars(char *title) +{ + uint8_t buf[5]; + zstate_t state = z80_bus_state(); + + if((state & ZST_ACQUIRED) == 0) + z80_bus_cmd(Request); + + z80_read_block(buf, 9, sizeof buf); + + if((state & ZST_ACQUIRED) == 0) + z80_bus_cmd(Release); + + printf_P(PSTR("%s: stage: %d, flag: 0x%.02x, result: %d, IDE stat/error: 0x%.02x/0x%.02x\n"), + title, buf[0], buf[1], buf[2], buf[3], buf[4]); +} + + +/* + * bootcf [options] + * + * -a address (100h) + * -s start sector (0) + * -c sector count (7) + * -i Partition id (52) + * -n load only + * -t timeout (10000) + * -v verbose + */ + +command_ret_t do_bootcf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct { + uint8_t jr[2]; + uint16_t loadaddr; + uint8_t sec_start; + uint8_t sec_cnt; + uint8_t part_id; + uint16_t timeout; + uint8_t stop_stage; + } boot_param; + + struct { + uint8_t stop_stage; + uint8_t done; + uint8_t result; + uint8_t ide_stat; + uint8_t ide_error; + } boot_res; + + int_fast8_t verbosity = 0; + uint8_t stages; + uint32_t val; + + (void) cmdtp; (void) flag; + + /* get default values */ + memcpy_P(&boot_param, cfboot, sizeof boot_param); + stages = boot_param.stop_stage; + + /* reset getopt() */ + optind = 0; + + int opt; + while ((opt = getopt(argc, argv, PSTR("vna:s:c:t:i:"))) != -1) { + switch (opt) { + case 'v': + verbosity++; + break; + case 'n': + if (boot_param.stop_stage > 0) + boot_param.stop_stage--; + break; + case 'a': + val = strtoul(optarg, NULL, 16); + if (val < 0x100 || val > 0xFE00) { + printf_P(PSTR("Address out of range: 0x%.4lX\n"), val); + return CMD_RET_FAILURE; + } + boot_param.loadaddr = val; + break; + case 's': + val = strtoul(optarg, NULL, 16); + if (val > 255) { + printf_P(PSTR("Start sector out of range: 0x%lX\n"), val); + return CMD_RET_FAILURE; + } + boot_param.sec_start = val; + break; + case 'c': + val = strtoul(optarg, NULL, 16); + if (val > 127) { + printf_P(PSTR("Sector count out of range: 0x%lX\n"), val); + return CMD_RET_FAILURE; + } + boot_param.sec_cnt = val; + break; + case 't': + val = strtoul(optarg, NULL, 10); + if (val < 0x1 || val > 0xFFFF) { + printf_P(PSTR("Timeout value out of range: 0x%lX\n"), val); + return CMD_RET_FAILURE; + } + boot_param.loadaddr = val; + break; + case 'i': + val = strtoul(optarg, NULL, 16); + if (val < 0x01 || val > 0xFF) { + printf_P(PSTR("Partition id out of range: 0x%lX\n"), val); + return CMD_RET_FAILURE; + } + boot_param.part_id = val; + break; + default: /* '?' */ + return CMD_RET_USAGE; + } + } + + /* remaining arguments */ + argc -= optind; + if (argc) { + my_puts_P(PSTR("Argument error!\n")); + return CMD_RET_USAGE; + } + + if ((val = (uint32_t) boot_param.loadaddr + boot_param.sec_cnt * 512) >= 0xFF00) { + printf_P(PSTR("Top address out of range: 0x%.4lX\n"), val); + return CMD_RET_FAILURE; + } + + + + if (z80_bus_state() & ZST_RUNNING) { + my_puts_P(PSTR("CPU is allready running!\n")); + return CMD_RET_FAILURE; + } + if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) { + my_puts_P(PSTR("Bus timeout\n")); + return CMD_RET_FAILURE; + } + z80_load_mem(verbosity, cfboot, + &cfboot_sections, + cfboot_address, + cfboot_length_of_sections); + + z80_write_block((const uint8_t *) &boot_param, + cfboot_address[0], sizeof boot_param); + z80_bus_cmd(Release); + + if (boot_param.stop_stage == 0) { + printf_P(PSTR("Bootloader loaded at: 0x%.4X\n"), (uint16_t) cfboot_address[0]); + } else { + printf_P(PSTR("Executing %d of %d Bootloader stages...\n"), + boot_param.stop_stage, stages); + + z80_bus_cmd(Run); + z80_bus_cmd(Release); + + clear_ctrlc(); /* forget any previous Control C */ + for (boot_res.done = 0; boot_res.done != 0xFF;) { + _delay_ms(8); + /* check for ctrl-c to abort... */ + if (had_ctrlc() || ctrlc()) { + break; + } + z80_bus_cmd(Request); + z80_read_block((uint8_t *) &boot_res, + cfboot_address[0]+sizeof boot_param - 1, sizeof boot_res); + z80_bus_cmd(Release); + } + + if (boot_res.done != 0xFF) { + z80_bus_cmd(Reset); + my_puts_P(PSTR("Abort\n")); + } else { + if (boot_param.stop_stage == stages) { + my_puts_P(PSTR("Booting...\n")); + } else { + z80_bus_cmd(Reset); + printf_P(PSTR("Bootloader stopped at stage %d, result: %d, IDE stat/error: 0x%.02x/0x%.02x\n"), + boot_param.stop_stage - boot_res.stop_stage, + boot_res.result, boot_res.ide_stat, boot_res.ide_error); + } + } + } + + return CMD_RET_SUCCESS; +} + command_ret_t do_busreq_pulse(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { uint16_t count=1; @@ -81,7 +283,7 @@ command_ret_t do_busreq_pulse(cmd_tbl_t *cmdtp, int flag, int argc, char * const } if (argc > 1) - count = (uint16_t) strtoul(argv[2], NULL, 16); + count = (uint16_t) strtoul(argv[1], NULL, 16); z80_bus_cmd(Request); while (count--) @@ -116,11 +318,9 @@ command_ret_t do_go(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (addr != 0) { uint8_t tmp[3]; - uint_fast8_t i; z80_bus_cmd(Request); - for (i = 0; i < 3; i++) - tmp[i] = z80_read(i); + z80_read_block (tmp, 0, 3); z80_write(0, 0xc3); z80_write(1, addr); z80_write(2, (addr >> 8)); @@ -128,8 +328,7 @@ command_ret_t do_go(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) z80_bus_cmd(Run); z80_bus_cmd(M_Cycle); z80_bus_cmd(M_Cycle); - for (i = 0; i < 3; i++) - z80_write(i, tmp[i]); + z80_write_block(tmp, 0, 3); } else z80_bus_cmd(Run); @@ -170,8 +369,9 @@ void print_con_usage(char esc) { printf_P(PSTR("\n" "------------------------------------------------\n" " ?,H - This Help\n" - " R - Reset (Restart) CPU\n" " Q,X - Return to command line\n" + " R - Reset (Restart) CPU\n" + " : - Execute monitor command\n" " \\ - code input:\n" " \\nnn 3 decimal digits character code\n" " \\Xhh 2 hexadecimal digits character code\n" @@ -191,6 +391,8 @@ command_ret_t do_console(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv (void) cmdtp; (void) flag; (void) argc; (void) argv; + printf_P(PSTR("Connecting to CPU. Escape character is '^%c'.\n"), + esc_char + 0x40); while (1) { @@ -237,6 +439,13 @@ command_ret_t do_console(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv goto quit; break; + case ':': + putchar('\n'); + int cmdlen = cli_readline(PSTR(": "), 1); + if (cmdlen > 0) + run_command(console_buffer, 0); + break; + case '\\': code = 0; state = 3; @@ -259,6 +468,11 @@ command_ret_t do_console(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv if (isdigit(ch)) { code = code * 10 + ch - '0'; state++; + } else { + if (state > 3) + z80_memfifo_putc(fifo_conin, code); + z80_memfifo_putc(fifo_conin, ch); + state = 0; } if (state > 5) { z80_memfifo_putc(fifo_conin, code); @@ -273,6 +487,11 @@ command_ret_t do_console(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv ch -= 'A' - 10; code = code * 16 + ch - '0'; state++; + }else { + if (state > 6) + z80_memfifo_putc(fifo_conin, code); + z80_memfifo_putc(fifo_conin, ch); + state = 0; } if (state > 7) { z80_memfifo_putc(fifo_conin, code);