From 226d32211880a061265faf6b8eadaf6ca1ec7a38 Mon Sep 17 00:00:00 2001 From: Leo C Date: Sat, 8 Sep 2018 09:39:06 +0200 Subject: [PATCH] New command cpuchk move z80_load_mem() to z80-if.c --- avr/Tupfile | 6 +- avr/cmd_boot.c | 27 ------ avr/cmd_cpu.c | 90 ++++++++++++++++++++ avr/command_tbl.c | 6 ++ avr/z80-if.c | 31 +++++++ include/cmd_cpu.h | 14 ++++ include/z80-if.h | 5 ++ z180/Tupfile | 4 + z180/cpuinfo.180 | 204 ++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 357 insertions(+), 30 deletions(-) create mode 100644 avr/cmd_cpu.c create mode 100644 include/cmd_cpu.h create mode 100644 z180/cpuinfo.180 diff --git a/avr/Tupfile b/avr/Tupfile index b74b305..68a6ae0 100644 --- a/avr/Tupfile +++ b/avr/Tupfile @@ -7,7 +7,7 @@ FATFS = $(FATFSD)/ff.c $(FATFSD)/ffunicode.c SRC = main.c SRC += cli.c cli_readline.c command.c command_tbl.c -SRC += cmd_run.c cmd_boot.c cmd_misc.c +SRC += cmd_run.c cmd_boot.c cmd_misc.c cmd_cpu.c SRC += cmd_date.c cmd_mem.c cmd_gpio.c cmd_attach.c SRC += cmd_loadihex.c cmd_loadcpm3.c cmd_sd.c cmd_fat.c SRC += env.c con-utils.c print-utils.c getopt-min.c eval_arg.c @@ -23,7 +23,7 @@ SRC += ../time/system_time.c ../time/set_system_time.c ASRC += ../time/system_tick.S -SRC_Z = ../z180/hdrom.c ../z180/cfboot.c +SRC_Z = ../z180/hdrom.c ../z180/cfboot.c ../z180/cpuinfo.c #TARGETS = $(PROG).elf @@ -112,7 +112,7 @@ LDFLAGS += -Wl,--cref !SIZE = |> ^ SIZE^ $(SIZE) %f |> : foreach $(ASRC) |> !as |> {objs} -: foreach $(SRC) | ../z180/hdrom.h ../z180/cfboot.h |> !cc |> {objs} +: foreach $(SRC) | ../z180/hdrom.h ../z180/cfboot.h ../z180/cpuinfo.h |> !cc |> {objs} : foreach $(SRC_Z) |> !cc -D'const=const __flash' |> {objs} : {objs} |> !LINK |> $(PROG).elf diff --git a/avr/cmd_boot.c b/avr/cmd_boot.c index 600bad3..2159608 100644 --- a/avr/cmd_boot.c +++ b/avr/cmd_boot.c @@ -31,33 +31,6 @@ #undef const - -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[]) -{ - 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]; - } -} - command_ret_t do_loadf(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED) { if (z80_bus_state() & ZST_RUNNING) diff --git a/avr/cmd_cpu.c b/avr/cmd_cpu.c new file mode 100644 index 0000000..de627c6 --- /dev/null +++ b/avr/cmd_cpu.c @@ -0,0 +1,90 @@ +/* + * (C) Copyright 2018 Leo C. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include "cmd_cpu.h" +//#include +//#include + +#include "z80-if.h" +#include "con-utils.h" +//#include "env.h" +//#include "eval_arg.h" +//#include "getopt-min.h" +//#include "debug.h" + +/* hack to get Z180 loadfile into flash memory */ +#define const const FLASH +#include "../z180/cpuinfo.h" +#undef const + + +static const FLASH char * const FLASH cpu_strings[] = { + FSTR("Unknown CPU"), + FSTR("8080"), + FSTR("8085"), + FSTR("Z80"), + FSTR("x180"), + FSTR("HD64180"), + FSTR("Z80180"), + FSTR("Z80S180"), +}; + +command_ret_t do_cpuchk(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED) +{ + uint8_t done = 0; + uint8_t cputype; + ERRNUM err = ESUCCESS; + uint8_t ram_save[cpuinfo_length]; + + if (z80_bus_state() & ZST_RUNNING) { + err = ERUNNING; + } else { + z80_bus_request_or_exit(); + z80_read_block(ram_save, 0, cpuinfo_length); + z80_load_mem(0, cpuinfo, + &cpuinfo_sections, + cpuinfo_address, + cpuinfo_length_of_sections); + z80_bus_cmd(Release); + + if (argv[1] && (argv[1][0] == 'n')) + goto donot; + + z80_bus_cmd(Run); + + clear_ctrlc(); /* forget any previous Control C */ + while (done != 0xFF) { + _delay_ms(8); + /* check for ctrl-c to abort... */ + if (had_ctrlc() || ctrlc()) { + err = EINTR; + break; + } + z80_bus_cmd(Request); + done = z80_read(3); + if (done == 0xFF) + cputype = z80_read(4); + z80_bus_cmd(Release); + } + z80_bus_cmd(Reset); + z80_bus_cmd(Request); +// z80_write_block(ram_save, 0, cpuinfo_length); + z80_bus_cmd(Release); + } + +donot: + + if (err) + cmd_error(CMD_RET_FAILURE, err, NULL); + + if (done == 0xFF) { + if (cputype >= ARRAY_SIZE(cpu_strings)) + cputype = 0; + printf_P(PSTR("Detected CPU: %S\n"), cpu_strings[cputype]); + } + + return CMD_RET_SUCCESS; +} diff --git a/avr/command_tbl.c b/avr/command_tbl.c index 5d185ba..9968dc0 100644 --- a/avr/command_tbl.c +++ b/avr/command_tbl.c @@ -8,6 +8,7 @@ #include "command.h" #include "cmd_mem.h" #include "cmd_boot.h" +#include "cmd_cpu.h" #include "cmd_misc.h" #include "cmd_date.h" #include "cmd_run.h" @@ -125,6 +126,11 @@ CMD_TBL_ITEM_TOP( cmd_tbl_env ), +CMD_TBL_ITEM( + chkcpu, CONFIG_SYS_MAXARGS, CTBL_RPT, do_cpuchk, + "Check CPU", + "" +), CMD_TBL_ITEM( loadf, 1, 0, do_loadf, "load srec_cat prepared image from controller flash", diff --git a/avr/z80-if.c b/avr/z80-if.c index 180a27f..7a953f0 100644 --- a/avr/z80-if.c +++ b/avr/z80-if.c @@ -506,6 +506,8 @@ int32_t z80_memsize_detect(void) return addr; } +/*--------------------------------------------------------------------------*/ + void z80_write(uint32_t addr, uint8_t data) { z80_setaddress(addr); @@ -605,6 +607,7 @@ void z80_read_block (uint8_t *dest, uint32_t src, size_t length) Z80_O_MREQ = 1; } +/*--------------------------------------------------------------------------*/ /* 0179' rx.bs_mask: ds 1 ; (buf_len - 1) @@ -745,3 +748,31 @@ void z80_memfifo_putc(fifo_t f, uint8_t val) z80_write(fifo_dsc[f].base+FIFO_INDEX_IN, fifo_dsc[f].idx_in); z80_bus_cmd(Release); } + +/*--------------------------------------------------------------------------*/ + +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[]) +{ + 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]; + } +} diff --git a/include/cmd_cpu.h b/include/cmd_cpu.h new file mode 100644 index 0000000..d590468 --- /dev/null +++ b/include/cmd_cpu.h @@ -0,0 +1,14 @@ +/* + * (C) Copyright 2018 Leo C. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef CMD_CPU_H +#define CMD_CPU_H + +#include "command.h" + +command_ret_t do_cpuchk(cmd_tbl_t *, uint_fast8_t, int, char * const []); + +#endif /* CMD_CPU_H */ diff --git a/include/z80-if.h b/include/z80-if.h index 0ad14f5..7225cf4 100644 --- a/include/z80-if.h +++ b/include/z80-if.h @@ -58,3 +58,8 @@ int z80_memfifo_is_full(const fifo_t f); int z80_memfifo_getc(const fifo_t f); uint8_t z80_memfifo_getc_wait(const fifo_t f); void z80_memfifo_putc(fifo_t f, uint8_t val); + +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[]); diff --git a/z180/Tupfile b/z180/Tupfile index c7d79fb..0c3f95e 100644 --- a/z180/Tupfile +++ b/z180/Tupfile @@ -2,6 +2,7 @@ include_rules PROG = hdrom CFBOOT = cfboot +CPUINFO = cpuinfo SRC = init.180 SRC += ddtz.180 @@ -52,6 +53,9 @@ rm -f ${OUTPUT}; exit ${ERROR} \ : $(CFBOOT).180 |> $(AS) -%B/HFS |> %B.hex | %B.lst : $(CFBOOT).hex |> srec_cat -o %o -c_array %B -C_COMpressed -include %f -Intel |> $(CFBOOT).c | $(CFBOOT).h +: $(CPUINFO).180 |> $(AS) -%B/HFS |> %B.hex | %B.lst +: $(CPUINFO).hex |> srec_cat -o %o -c_array %B -C_COMpressed -include %f -Intel |> $(CPUINFO).c | $(CPUINFO).h + #COMMAND="$(AS) -%B/$(AS_OPT)"; \ diff --git a/z180/cpuinfo.180 b/z180/cpuinfo.180 new file mode 100644 index 0000000..8629aa5 --- /dev/null +++ b/z180/cpuinfo.180 @@ -0,0 +1,204 @@ + .z80 ; for M80, ignored by SLR assembler + include z180reg.inc + +RUN_TPA equ 0 + +UUNKNOWN equ 0 ;Unknown CPU +U8080 equ 1 ;8080 +U8085 equ 2 ;8085 +UZ80 equ 3 ;Z80 +UX180 equ 4 ;HD64180 or higher +UHD64180 equ 5 ;HD64180 +UZ80180 equ 6 ;Z80180 +UZ8S180 equ 7 ;Z8S180, Z8L180 + + +;------------------------------------------------------------------------------- + + + if RUN_TPA +base equ 0100h + else +base equ 0 + endif + + + aseg + org base + jp start + +done: db 0 +result: db 0 + +;------------------------------------------------------------------------------- +; Read internal register at address in L and IOBASE in H. +; + +reg_in: + ld a,h + add a,l + ld c,a + ld b,0 + in a,(c) + ret + +;------------------------------------------------------------------------------- +; Write internal register at address in L and IOBASE in H. +; + +reg_out: + ld b,a + ld a,h + add a,l + ld c,a + ld a,b + ld b,0 + out (c),a + ret + +;------------------------------------------------------------------------------- +; Check if register C exists. D holds mask of bit to test. +; return nz, if register exists + +chk_reg: + call reg_in + cp 0ffh + ret nz ; + + ; check, if register is changeable + + xor d ; set bit(s) in register to 0 + call reg_out + call reg_in ; get it back + ex af,af' + ld a,0ffh ; set to register original state + call reg_out + ex af,af' + cpl + and d + ret + +;------------------------------------------------------------------------------- +; Check CPU +; +; +; return: +; E = 0 Unknown +; E = 1 8080 +; E = 2 8085 +; E = 3 Z80 +; E = 4 HD64180 or higher +; E = 5 HD64180 +; E = 6 Z80180 +; E = 7 Z8S180, Z8L180 +; +;------------------------------------------------------------------------------- +; Registers only in Z180+, not in HD64180 +; 3E OMCR +; +; Registers only in Z8S180/Z8L180 +; 12 ASEXT0 +; 13 ASEXT1 +; 1A ASTC0L +; 1B ASTC0H +; 1C ASTC1L +; 1D ASTC1H +; 1E CMR +; 1F CCR +; 2D IAR1B +; +; Reserved registers +; 11 +; 19 +; 35 +; 37 +; 3B - 3D + +check: + ld e,U8080 ; Init return val, assume 8080 + xor a + dec a ; 00 --> 0FFH 8080/8085: even parity; Z80+: No overflow + jp po,chk_z80 ; Z80+ if P/V flag reset + + ; The 8085 logical AND instructions always set the auxiliary flag ON. + ; The 8080 logical AND instructions set the flag to reflect the + ; logical OR of bit 3 of the values involved in the AND operation. + ; (8080/8085 ASSEMBLY LANGUAGE PROGRAMMING MANUAL, 1977, 1978) + + xor a + and a ; 8085 sets, 8080 resets half carry. + daa ; A=06 (8085) or A=00 (8080) + ret z + inc e + ret + +chk_z80: + ld e,UZ80 ; Assume Z80 + daa ; Z80: 099H, x180+: 0F9H + cp 99h ; Result on 180 type cpus is F9 here. Thanks Hitachi + ret z + inc e ; x180 + + ; At least Hitachi HD64180 + ; Test differences in certain internal registers + ; to determine the 180 variant. + ; First, search the internal register bank. + + ld h,00H ; I/O Base +find_base_loop: + ld l,icr + call reg_in + and 11011111b ; mask I/O Stop bit + xor h + cp 01FH + jr nz,nxt_base + + ;TODO: additional plausibility checks + + jr z,base_found +nxt_base: + ld a,h + add a,040H + ld h,a + jr nc,find_base_loop + ret ;I/O registers not found + + ; Register (base) found. + +base_found: + inc e ; HD64180 + ld l,omcr ; Check, if CPU has OMCR register + ld d,M_IOC ; + call chk_reg ; + ret z ; Register does not exist. It's a HD64180 + + inc e ; Z80180 + ld l,cmr ; Check, if CPU has CMR register + ld d,M_LNC ; + call chk_reg ; + ret z ; register does not exist. It's a Z80180 + + inc e ; S180/L180 (class) detected. + + ret + +;------------------------------------------------------------------------------- + +start: + ld sp,stack + call check + + ld hl,result + ld (hl),e + dec hl + ld (hl),0ffH + halt + jp $-1 + + rept 8 + dw 0 + endm +stack: + end + +; vim:set ts=8 noet nowrap -- 2.39.2