HDIAG work in progress

- HDIAG updates
- Regen documentation updates from Phil
- Fix ZZR config
This commit is contained in:
Wayne Warthen
2021-09-23 15:43:51 -07:00
parent 522a7a8378
commit ddb3169c28
17 changed files with 332 additions and 270 deletions

View File

@@ -31,8 +31,8 @@
CPUOSC .SET 29491200 ; CPU OSC FREQ IN MHZ
;
RAMSIZE .SET 384 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!)
RAM_RESERVE .SET 128 ; RESERVE FIRST N KB OF RAM (USUALLY 0)
ROM_RESERVE .SET 0 ; RESERVE FIRST N KB OR ROM (USUALLY 0)
PLT_RAM_R .SET 128 ; RESERVE FIRST N KB OF RAM (USUALLY 0)
PLT_ROM_R .SET 0 ; RESERVE FIRST N KB OR ROM (USUALLY 0)
;
RAMLOC .SET 23 ; START OF RAM AS POWER OF 2 (2^N) IN PHYSICAL ADDRESS SPACE
RAMBIAS .SET (1 << (RAMLOC - 10)) ; OFFSET OF START OF RAM IN PHYSICAL ADDRESS SPACE

View File

@@ -1,7 +1,7 @@
@echo off
setlocal
if exist *.bin del *.bin
if exist *.com del *.com
if exist *.rom del *.rom
if exist *.lst del *.lst
if exist *.hex del *.hex

View File

@@ -6,15 +6,8 @@ include $(TOOLS)/Makefile.inc
TASMFLAGS=-t hd64180
hdiag.com: hdiag.asm
$(TASM) $(TASMFLAGS) -dAPPBOOT $< $@ $*.lst
$(TASM) $(TASMFLAGS) -dAPPBOOT $< $@ hdiag.com.lst
hdiag.rom: hdiag.asm
$(TASM) $(TASMFLAGS) -dROMBOOT $< $@ $*.lst
#cbios_wbw.bin: cbios.asm
# $(TASM) -dPLTWBW $< $@ cbios_wbw.lst
#
#cbios_una.bin: cbios.asm
# $(TASM) -dPLTUNA $< $@ cbios_una.lst
$(TASM) $(TASMFLAGS) -dROMBOOT $< $@ hdiag.rom.lst

View File

@@ -12,20 +12,20 @@
;
;
asci_jptbl:
jp asci_cinit ; Initialize serial port
jp asci_cin ; Read byte
jp asci_cout ; Write byte
jp asci_cist ; Input status
jp asci_cost ; Output Status
jp asci_cinit ; Initialize serial port
jp asci_cin ; Read byte
jp asci_cout ; Write byte
jp asci_cist ; Input status
jp asci_cost ; Output Status
;
;
;
asci_cinit:
; Detect ASCI
ld a,(hd_cpu) ; get cpu type
cp 1
cp hd_cpu_z180
jr c, asci_cinit1 ; less than Z180, abort
cp 4
cp hd_cpu_z280
jr nc, asci_cinit1 ; greater than Z180, abort
;
; Initialize ASCI

View File

@@ -1,5 +1,4 @@
;
;
;=======================================================================
; HDIAG Diagmostic ROM
;=======================================================================
@@ -27,9 +26,12 @@
; - APPBOOT: Boot as a CP/M style application file
;
; When APPBOOT is defined, the file is assembled as a CP/M application
; assuming that it will be loaded at 100h by the cp/m (or compatible)
; assuming that it will be loaded at 100h by the CP/M (or compatible)
; OS.
;
.module MAIN
;
#include "hdiag.inc"
#include "z180.inc"
;
;=======================================================================
@@ -42,7 +44,7 @@
;
.org $0000
;
jp hd_start ; rst $00: jump to boot code
jp _start ; rst $00: jump to boot code
.fill ($08-$)
ret ; rst $08
.fill ($10-$)
@@ -75,46 +77,41 @@
; to the upper 32K of CPU address space until the memory manager
; is initialized.
;
hd_start:
_start:
;
; Discover CPU Type and Memory Manager
;
; Some of this code is derived from UNA by John Coffman
;
; CPU Type:
; 0: Z80
; 1: Z80180 - ORIGINAL Z180 (EQUIVALENT TO HD64180)
; 2: Z8S180 - ORIGINAL S-CLASS, REV. K, AKA SL1960, NO ASCI BRG
; 3: Z8S180 - REVISED S-CLASS, REV. N, W/ ASCI BRG
; 4: Z8280
;
; Memory Manager:
; 0: SBC/MBC/Zeta 1
; 1: Zeta 2/RC2014
; 2: Z180
; 3: N8?
; 4: Z280
;
; CPU and memory manager constants are defined in hdiag.inc.
;
di ; no interrupts allowed
;
ld a,$80
out ($0D),a
;
; Use H for memory manager, and L for CPU Type
ld hl,0 ; assume Z80 and SBC
; Use D for memory manager, and E for CPU Type
ld de,0 ; assume unknown for both
;
; Start with CPU type detection
;
; Check for Z80
inc e ; not sure how to do it, just assume it
;
; Test for Z180 using mlt
ex de,hl ; save DE to HL for test
ld de,$0506 ; 5 x 6
mlt de ; de = 30 if Z180
ld a,e ; check if multiply happened
ex de,hl ; restore DE now
cp 30
jr nz,hd_tryZ280 ; if != 30, not a Z180, try Z280
inc l ; Z80180 or better
jr nz,_tryZ280 ; if != 30, not a Z180, try Z280
inc e ; Z80180 or better
;
#ifdef APPBOOT
;
; Reset Z180 internal register base to zero
; Reset Z180 internal register base to zero no matter where
; it might have previously been mapped.
xor a
out0 ($7F),a
out0 ($BF),a
@@ -125,8 +122,8 @@ hd_start:
; Test for older S-class (rev K)
in0 a,(z180_ccr) ; supposedly only on s-class
inc a ; FF -> 0
jr z,hd_z180res ; if zero, pre-S, HD61480 or equiv
inc l ; Z8S180 rev K (SL1960) or better
jr z,_z180res ; if zero, pre-S, HD61480 or equiv
inc e ; Z8S180 rev K (SL1960) or better
;
; Test for newer S-class (rev N)
; On older S-class, asci time constant reg does not exist
@@ -134,30 +131,30 @@ hd_start:
out0 (z180_astc1l),d ; d = 0 at this point
in0 a,(z180_astc1l) ; asci time constant reg
inc a ; FF -> 0
jr z,hd_z180res ; if zero, rev-K
inc l ; otherwise Z8S180 rev N w/ asci brg
jr hd_z180res ; go to Z180 reset
jr z,_z180res ; if zero, rev-K
inc e ; otherwise Z8S180 rev N w/ asci brg
jr _z180res ; go to Z180 reset
;
hd_tryZ280:
_tryZ280:
; Test for Z280 per Zilog doc
ld a,$40 ; initialize the operand
.db $cb,$37 ; this instruction will set the s flag
; on the Z80 cpu and clear the s flag
; on the Z280 mpu.
jp m,hd_z80res ; if not Z280, we are Z80
ld l,4 ; we are Z280
jr hd_z280res ; handle Z280 initialization
jp m,_z80res ; if not Z280, we are Z80
ld l,hd_cpu_z280 ; we are Z280
jr _z280res ; handle Z280 initialization
;
hd_z80res:
_z80res:
ld a,$01
out (0),a
; Reset Z80 here (is there anything?)
jr hd_cpu1
jr _cpu1
;
hd_z180res:
_z180res:
;
; Reset z180 registers here
; Set CPU speed to oscillator X 1
; Set CPU speed to oscillator x 1
xor a
out0 (z180_cmr),a
ld a,$80
@@ -179,14 +176,19 @@ hd_z180res:
out0 (z180_cbr),a ; ... for Common Base
#endif
;
jr hd_cpu1
jr _cpu1
;
hd_z280res:
_z280res:
; Reset Z280 registers here
; Make sure memmgr is reset to defaults!
jr hd_cpu1
jr _cpu1
;
hd_cpu1:
; At this point, we should have the cpu type in the L register.
; Now determine the memory manager. In general, we just attempt to
; enable the different memory managers and keep testing to see if
; a RAM bank has appeared in the common area.
;
_cpu1:
ld a,$02
out ($0D),a
;
@@ -210,19 +212,24 @@ hd_cpu1:
ld a,$03
out ($0D),a
;
; If SBC memmgr, RAM is already in himem, otherwise ROM
; There is no way to disable the common (himem) RAM bank
; under the SBC memory manager. Here, we just see if there
; is RAM in himem and, if so, assume the SBC memory manager.
; If not, we continue on to test the other possible memory
; managers.
inc d ; assume SBC memory manager
ld ix,$FFFF ; point to himem
ld a,$A5 ; an unlikely bit pattern
ld (ix),a ; write the value
cp (ix+0) ; check value written
jr z,hd_cpu2 ; SBC memory manager, we are done!
jr z,_cpu2 ; SBC memory manager, we are done!
;
ld a,$04
out ($0D),a
;
; Now test for Zeta 2 memory manager
; Start by initializing and enabling the page registers
inc h ; assume Zeta 2 memory manager
inc d ; assume Zeta 2 memory manager
#ifdef ROMBOOT
xor a ; ROM page 0
out ($78),a
@@ -244,56 +251,54 @@ hd_cpu1:
ld a,$A5 ; an unlikely bit pattern
ld (ix),a ; write the value
cp (ix+0) ; check value written
jr z,hd_cpu2 ; Zeta 2 memory manager, we are done!
jr z,_cpu2 ; Zeta 2 memory manager, we are done!
;
ld a,$06
out ($0D),a
;
; If neither SBC nor Zeta 2, then we assume the memory
; manager is the native memory manager onboard the CPU
ld a,l ; get cpu type
cp 4 ; Z280?
jr z,hd_z280init ; handle it
ld a,e ; get cpu type
cp hd_cpu_z280 ; Z280?
jr z,_z280init ; handle it
or a ; Z80?
jr nz,hd_z180init ; if no, do handle Z180
jr nz,_z180init ; if no, go handle Z180
;
; If we get here, we are stuck. We believe we are a Z80
; but both of the Z80 memory manager tests failed.
hd_halt:
_halt:
ld a,$07
out ($0D),a
ld hl,str_halt
;
ld hl,_str_halt
call prtstr
halt ; give up
;
hd_z180init:
_z180init:
; Initialize Z180 memory manager
; Put first RAM page into himem (commmon)
ld a,$80
out0 (z180_cbr),a
;
ld h,2
jr hd_cpu2
ld d,hd_mm_z180
jr _cpu2
hd_N8init:
_N8init:
; Initialize N8 memory manager
ld h,3
jr hd_cpu2
ld d,hd_mm_n8
jr _cpu2
hd_z280init:
_z280init:
; Initialize Z280 memory manager
ld h,4
jr hd_cpu2
ld d,hd_mm_z280
jr _cpu2
;
hd_cpu2:
_cpu2:
ld a,$08
out ($0D),a
;
ld ($8000),hl ; stash cpu/memmgr at $8000
ex de,hl ; cpu/memmgr values to HL
ld sp,hl ; and stash SP reg
;
; Transition to upper memory (omit page zero)
;
@@ -301,7 +306,7 @@ hd_cpu2:
ld de,$8000+$100
ld bc,$8000-$100
ldir
jp hd_start2
jp _start2
;
.org $ + $8000
;
@@ -310,27 +315,28 @@ hd_cpu2:
; Post-relocation Startup
;=======================================================================
;
hd_start2:
_start2:
;
ld a,$09
out ($0D),a
;
ld sp,$FF00 ; Stack just below FF page
;
; Copy FF page image to real location. Use a decrementing copy
; just in case page image is within $100 bytes of $FF00. Very
; unlikely, but just to be safe.
;
ld hl,ffpgimg+$FF ; Start at end of image
ld hl,_ffimg+$FF ; Start at end of image
ld de,$FFFF ; To top of RAM
ld bc,$100 ; Copy 1 page
lddr ; Execute
;
; Recover cpu/memmgr codes stashed at $8000 and
; save them in FFpg
; Recover cpu/memmgr codes stashed in SP and
; save them in FF page
;
ld hl,($8000)
ld (hd_cpu),hl
ld (_cpu),sp
;
; Now we establish a real stack (finally!)
;
ld sp,$FF00 ; Stack just below FF page
;
; Probe and initialize serial port console driver. We just go
; through the options stopping at the first one that works. The
@@ -340,27 +346,30 @@ hd_start2:
;
ld a,$0A
out ($0D),a
;
;
; This should be table driven!!!
;
; Z280 UART
ld ix,z2u_jptbl
ld ix,ser_z2u
call jpix
jr z,hd_start3
jr z,_start3
; ASCI
ld ix,asci_jptbl
ld ix,ser_asci
call jpix
jr z,hd_start3
jr z,_start3
; UART
ld ix,uart_jptbl
ld ix,ser_uart
call jpix
jr z,hd_start3
jr z,_start3
; ACIA
ld ix,acia_jptbl
ld ix,ser_acia
call jpix
jr z,hd_start3
jr z,_start3
; SIO
ld ix,sio_jptbl
ld ix,ser_sio
call jpix
jr z,hd_start3
jr z,_start3
;
; Ugh, nothing worked
ld a,$0C
@@ -369,7 +378,7 @@ hd_start2:
;
;
;
hd_start3:
_start3:
;
ld a,$0D
out ($0D),a
@@ -378,185 +387,115 @@ hd_start3:
;
push ix
pop hl
ld de,hd_serjptbl
ld de,_jptbl
ld bc,5*3
ldir
;
;
;
; Map a RAM page to lower 32K
; Setup memory manager
;
; Map RAM page 0 to lower 32K
;
; Setup zero page in lower 32K
;
;
;
hd_start4:
_restart:
;
ld hl,str_banner
ld hl,_str_banner
call prtstr
;
ld hl,str_cputag
call prtstr
ld a,($8000) ; cpu type
;call prthex8
rlca
ld hl,str_cpu
call addhla
ld a,(hl)
inc hl
ld h,(hl)
ld l,a
call prtstr
; Print CPU model
ld de,_str_cputag
ld hl,_str_cpu
ld a,(hd_cpu)
call prtstrtbl
;
;
ld hl,str_mmtag
call prtstr
ld a,($8001) ; memory manager
;call prthex8
rlca
ld hl,str_mm
call addhla
ld a,(hl)
inc hl
ld h,(hl)
ld l,a
call prtstr
; Print memory manager
ld de,_str_mmtag
ld hl,_str_mm
ld a,(hd_mmgr)
call prtstrtbl
;
call cin
jp hd_start4
jp _restart
;
;
;
jp hd_halt
jp _halt
;
;=======================================================================
; Helper functions
;=======================================================================
;
;
;=======================================================================
; Include various utility code modules
;=======================================================================
;
#include "util.asm"
;
;=======================================================================
; Console I/O
; Console I/O modules
;=======================================================================
;
; Internal serial driver routing jump table. The console serial
; port is detected at startup and the following table is populated
; dynamically at that time.
;
hd_serjptbl:
jp 0 ; Console port initialization
jp 0 ; Console read byte
jp 0 ; Console write byte
jp 0 ; Console input status
jp 0 ; Console output status
;
; Wrapper functions for console I/O handles routing abstraction and
; ensures that no registers are modified other than AF for input
; functions.
;
hd_cinit:
push af
push bc
push de
push hl
call hd_serjptbl + 0
pop hl
pop de
pop bc
pop af
ret
;
hd_cin:
push bc
push de
push hl
call hd_serjptbl + 3
pop hl
pop de
pop bc
ret
;
hd_cout:
push af
push bc
push de
push hl
call hd_serjptbl + 6
pop hl
pop de
pop bc
pop af
ret
;
hd_cist:
push bc
push de
push hl
call hd_serjptbl + 9
pop hl
pop de
pop bc
ret
;
hd_cost:
push af
push bc
push de
push hl
call hd_serjptbl + 12
pop hl
pop de
pop bc
pop af
ret
;
; Include all serial drivers
;
.module UART
ser_uart .equ $
#include "uart.asm"
;
.module ASCI
ser_asci .equ $
#include "asci.asm"
;
.module ACIA
ser_acia .equ $
#include "acia.asm"
;
.module SIO
ser_sio .equ $
#include "sio.asm"
;
.module Z2U
ser_z2u .equ $
#include "z2u.asm"
;
.module MAIN
;
;=======================================================================
; Working literals and internal variables
; Internal variables and literals
;=======================================================================
;
str_banner .db "\r\n\r\nHDIAG v0.90",0
str_cputag .db "\r\nCPU Model: ",0
str_mmtag .db "\r\nMemory Manager: ",0
str_halt .db "\r\n\r\n*** System HALTed ***",0
_str_banner .db "\r\n\r\nHDIAG v0.90",0
_str_cputag .db "\r\nCPU Model: ",0
_str_mmtag .db "\r\nMemory Manager: ",0
_str_halt .db "\r\n\r\n*** System HALTed ***",0
;
str_cpu:
.dw str_cpuz80
.dw str_cpuz180
.dw str_cpuz180K
.dw str_cpuz180N
.dw str_cpuz280
_str_cpu:
.dw _str_unknown
.dw _str_cpuz80
.dw _str_cpuz180
.dw _str_cpuz180K
.dw _str_cpuz180N
.dw _str_cpuz280
;
str_cpuz80 .db "Z80",0
str_cpuz180 .db "Z80180",0
str_cpuz180K .db "Z8S180-K",0
str_cpuz180N .db "Z8S180-N",0
str_cpuz280 .db "Z80280",0
_str_unknown .db "Unknown",0
_str_cpuz80 .db "Z80",0
_str_cpuz180 .db "Z80180",0
_str_cpuz180K .db "Z8S180-K",0
_str_cpuz180N .db "Z8S180-N",0
_str_cpuz280 .db "Z80280",0
;
str_mm:
.dw str_mmsbc
.dw str_mmz2
.dw str_mmz180
.dw str_mmn8
.dw str_mmz280
_str_mm:
.dw _str_unknown
.dw _str_mmsbc
.dw _str_mmz2
.dw _str_mmz180
.dw _str_mmn8
.dw _str_mmz280
;
str_mmsbc .db "SBC/MBC",0
str_mmz2 .db "Zeta2/RC2014",0
str_mmz180 .db "Z180 Native",0
str_mmn8 .db "Z180 Native (N8)",0
str_mmz280 .db "Z280 Native",0
_str_mmsbc .db "SBC/MBC",0
_str_mmz2 .db "Zeta2/RC2014",0
_str_mmz180 .db "Z180 Native",0
_str_mmn8 .db "Z180 Native (N8)",0
_str_mmz280 .db "Z280 Native",0
;
;=======================================================================
; Top page of CPU RAM, global variables and function jump table
@@ -570,19 +509,25 @@ str_mmz280 .db "Z280 Native",0
; It also contains some global variables at fixed locations for use
; by diagnostic modules.
;
ffpgimg .equ $
; The console function addresses are set dynamically based on the
; console driver that is installed at boot.
;
_ffimg .equ $
;
.org $FF00 ; Set code org
;
hd_jptbl:
cinit jp hd_cinit ; Console port initialization
cin jp hd_cin ; Console read byte
cout jp hd_cout ; Console write byte
cist jp hd_cist ; Console input status
cost jp hd_cost ; Console output status
_jptbl:
cinit jp 0 ; Console port initialization
cin jp 0 ; Console read byte
cout jp 0 ; Console write byte
cist jp 0 ; Console input status
cost jp 0 ; Console output status
;
.fill $FF80-$
hd_cpu .db 0 ; CPU type
hd_mmgr .db 0 ; Memory manager type
_cpu .db 0 ; CPU type
_mmgr .db 0 ; Memory manager type
;
.fill $10000-$
.end

44
Source/HDIAG/hdiag.inc Normal file
View File

@@ -0,0 +1,44 @@
;
;=======================================================================
; HDIAG Diagnostic ROM Global Definitions
;=======================================================================
;
; Include this file in modules written to run under HDIAG to
; have access to the HDIAG global variables and jump table
; definitions.
;
; It is important to use the definitions in this file because
; the internal structure of HDIAG is very likely to change
; over time.
;
; Global Variable Addresses
;
hd_cpu .equ $FF80
hd_mmgr .equ $FF81
;
; HDIAG Function Jump Table Vectors
;
hd_jptbl .equ $FF00
hd_cinit .equ hd_jptbl + 0 ; init console
hd_cin .equ hd_jptbl + 3 ; read console byte
hd_cout .equ hd_jptbl + 6 ; write console byte
hd_cist .equ hd_jptbl + 9 ; console input status
hd_cost .equ hd_jptbl + 12 ; console output status
;
; CPU Identified Constants (value of hd_cpu)
;
hd_cpu_none .equ 0 ; unknown cpu
hd_cpu_z80 .equ 1 ; plain Z80
hd_cpu_z180 .equ 2 ; original Z180 (HD64180)
hd_cpu_z180k .equ 3 ; Zilog Z180 Rev. K
hd_cpu_z180n .equ 4 ; Zilog Z180 Rev. N
hd_cpu_z280 .equ 5 ; Zilog Z280
;
; Memory Manager Identified Constants (value of hd_mmgr)
;
hd_mm_none .equ 0 ; unknown memory manager
hd_mm_sbc .equ 1 ; SBC/MBC/Zeta 1
hd_mm_z2 .equ 2 ; Zeta 2/RC2014
hd_mm_z180 .equ 3 ; Z180 native
hd_mm_n8 .equ 4 ; Z180 on N8
hd_mm_z280 .equ 5 ; Z280 native

View File

@@ -38,22 +38,22 @@ uart_jptbl:
;
uart_cinit:
; Test for existence
xor a ; zero accum
out (uart_ier),a ; ier := 0
ld a,$80 ; dlab bit on
out (uart_lcr),a ; output to lcr (dlab regs now active)
ld a,$5A ; load test value
out (uart_dlm),a ; output to dlm
in a,(uart_dlm) ; read it back
cp $5A ; check for test value
ret nz ; nope, unknown uart or not present
xor a ; dlab bit off
out (uart_lcr),a ; output to lcr (dlab regs now inactive)
in a,(uart_ier) ; read ier
cp $5A ; check for test value
jr nz,uart_cinit1 ; if *not* $5A, good to go
or $FF ; signal error
ret ; done
;;;xor a ; zero accum
;;;out (uart_ier),a ; ier := 0
;;;ld a,$80 ; dlab bit on
;;;out (uart_lcr),a ; output to lcr (dlab regs now active)
;;;ld a,$5A ; load test value
;;;out (uart_dlm),a ; output to dlm
;;;in a,(uart_dlm) ; read it back
;;;cp $5A ; check for test value
;;;ret nz ; nope, unknown uart or not present
;;;xor a ; dlab bit off
;;;out (uart_lcr),a ; output to lcr (dlab regs now inactive)
;;;in a,(uart_ier) ; read ier
;;;cp $5A ; check for test value
;;;jr nz,uart_cinit1 ; if *not* $5A, good to go
;;;or $FF ; signal error
;;;ret ; done
;
uart_cinit1:
ld a,$80 ; lcr := dlab on

View File

@@ -14,6 +14,24 @@ prtstr:
call cout ; display character
jr prtstr ; loop till done
;
; Print a string from a lookup table pointed to by HL, entry A
; with a prefix string at DE. HL, DE, and A are trashed.
;
prtstrtbl:
push af
ex de,hl
call prtstr
ex de,hl
pop af
rlca
call addhla
ld a,(hl)
inc hl
ld h,(hl)
ld l,a
call prtstr
ret
;
; Print the hex byte value in A
;
prthex8:

View File

@@ -2,4 +2,4 @@
#DEFINE RMN 1
#DEFINE RUP 1
#DEFINE RTP 0
#DEFINE BIOSVER "3.1.1-pre.117"
#DEFINE BIOSVER "3.1.1-pre.118"

View File

@@ -3,5 +3,5 @@ rmn equ 1
rup equ 1
rtp equ 0
biosver macro
db "3.1.1-pre.117"
db "3.1.1-pre.118"
endm