summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo C2018-09-08 09:39:06 +0200
committerLeo C2018-09-08 09:39:06 +0200
commit226d32211880a061265faf6b8eadaf6ca1ec7a38 (patch)
tree7e3acd41732e9e53cd65160ace61a5e74e85bd04
parentf66d9570ec64ecaa1f879619a0e4fed8d5fa7803 (diff)
downloadz180-stamp-226d32211880a061265faf6b8eadaf6ca1ec7a38.zip
New command cpuchk
move z80_load_mem() to z80-if.c
-rw-r--r--avr/Tupfile6
-rw-r--r--avr/cmd_boot.c27
-rw-r--r--avr/cmd_cpu.c90
-rw-r--r--avr/command_tbl.c6
-rw-r--r--avr/z80-if.c31
-rw-r--r--include/cmd_cpu.h14
-rw-r--r--include/z80-if.h5
-rw-r--r--z180/Tupfile4
-rw-r--r--z180/cpuinfo.180204
9 files changed, 357 insertions, 30 deletions
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. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include "cmd_cpu.h"
+//#include <ctype.h>
+//#include <util/atomic.h>
+
+#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"
@@ -126,6 +127,11 @@ CMD_TBL_ITEM_TOP(
),
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. <erbl259-lmu@yahoo.de>
+ *
+ * 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