mirror of https://github.com/wwarthen/RomWBW.git
committed by
GitHub
25 changed files with 3787 additions and 4 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1 @@ |
|||
DMAmon is a program to verify operation of the Z80 MBC DMA board |
|||
@ -0,0 +1,19 @@ |
|||
@echo off |
|||
setlocal |
|||
|
|||
set TOOLS=../../Tools |
|||
set BIN=..\..\Binary |
|||
|
|||
set PATH=%TOOLS%\tasm32;%PATH% |
|||
|
|||
set TASMTABS=%TOOLS%\tasm32 |
|||
|
|||
set ZXBINDIR=%TOOLS%/cpm/bin/ |
|||
set ZXLIBDIR=%TOOLS%/cpm/lib/ |
|||
set ZXINCDIR=%TOOLS%/cpm/include/ |
|||
|
|||
tasm -t180 -g3 -fFF -DAPPBOOT hdiag.asm hdiag.com hdiag_com.lst || exit /b |
|||
tasm -t180 -g3 -fFF -DROMBOOT hdiag.asm hdiag.rom hdiag_rom.lst || exit /b |
|||
|
|||
copy hdiag.rom %BIN% || exit /b |
|||
copy hdiag.com %BIN% || exit /b |
|||
@ -0,0 +1,7 @@ |
|||
@echo off |
|||
setlocal |
|||
|
|||
if exist *.bin del *.bin |
|||
if exist *.com del *.com |
|||
if exist *.lst del *.lst |
|||
if exist *.hex del *.hex |
|||
@ -0,0 +1,20 @@ |
|||
OBJECTS = hdiag.com hdiag.rom |
|||
DEST = ../../Binary |
|||
TOOLS = ../../Tools |
|||
include $(TOOLS)/Makefile.inc |
|||
|
|||
TASMFLAGS=-t hd64180 |
|||
|
|||
hdiag.com: hdiag.asm |
|||
$(TASM) $(TASMFLAGS) -dAPPBOOT $< $@ $*.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
|
|||
|
|||
@ -0,0 +1,70 @@ |
|||
; |
|||
;======================================================================= |
|||
; HDIAG ACIA Driver |
|||
;======================================================================= |
|||
; |
|||
acia_cmd .equ $80 |
|||
acia_dat .equ $81 |
|||
; |
|||
; |
|||
; |
|||
acia_jptbl: |
|||
jp acia_cinit ; Initialize serial port |
|||
jp acia_cin ; Read byte |
|||
jp acia_cout ; Write byte |
|||
jp acia_cist ; Input status |
|||
jp acia_cost ; Output Status |
|||
; |
|||
; |
|||
; |
|||
acia_cinit: |
|||
; Detect ACIA |
|||
ld a,$03 ; master reset |
|||
out (acia_cmd),a ; apply it |
|||
in a,(acia_cmd) ; get status |
|||
or a ; check for zero (expected) |
|||
ret nz ; abort if not |
|||
ld a,$02 ; clear master reset |
|||
out (acia_cmd),a ; apply it |
|||
in a,(acia_cmd) ; get status again |
|||
and %00001110 ; isolate reliable bits |
|||
cp %00000010 ; check for expected value |
|||
ret nz ; abort if not |
|||
; Initialize ACIA |
|||
ld a,%00010110 ; default config |
|||
out (acia_cmd),a ; apply it |
|||
xor a ; signal success |
|||
ret |
|||
; |
|||
; |
|||
; |
|||
acia_cin: |
|||
call acia_cist ; check for char ready |
|||
jr z,acia_cin ; if not, loop |
|||
in a,(acia_dat) ; read byte |
|||
ret ; done |
|||
; |
|||
; |
|||
; |
|||
acia_cout: |
|||
push af ; save incoming |
|||
acia_cout1: |
|||
call acia_cost ; ready for char? |
|||
jr z,acia_cout1 ; loop if not |
|||
pop af ; restore incoming |
|||
out (acia_dat),a ; write byte |
|||
ret ; and done |
|||
; |
|||
; |
|||
; |
|||
acia_cist: |
|||
in a,(acia_cmd) ; get status |
|||
and $01 ; isolate rx ready |
|||
ret ; done |
|||
; |
|||
; |
|||
; |
|||
acia_cost: |
|||
in a,(acia_cmd) ; get status |
|||
and $02 ; isolate tx empty |
|||
ret ; done |
|||
@ -0,0 +1,89 @@ |
|||
; |
|||
;======================================================================= |
|||
; HDIAG ASCI Driver |
|||
;======================================================================= |
|||
; |
|||
; ASCI0 is programmed with a fixed divisor of 480, resulting in a |
|||
; baud rate of 38400 at the standard cpu frequency of 18.432 MHz |
|||
; |
|||
; The Z180 may relocate it's internal I/O to begin at different |
|||
; starting port addresses. This driver relies upon an HDIAG global |
|||
; variable to dynamically adjust to the right port address. |
|||
; |
|||
; |
|||
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 |
|||
; |
|||
; |
|||
; |
|||
asci_cinit: |
|||
; Detect ASCI |
|||
ld a,(hd_cpu) ; get cpu type |
|||
cp 1 |
|||
jr c, asci_cinit1 ; less than Z180, abort |
|||
cp 4 |
|||
jr nc, asci_cinit1 ; greater than Z180, abort |
|||
; |
|||
; Initialize ASCI |
|||
ld a,%01100100 ; rcv enable, xmit enable, no parity |
|||
out0 (z180_cntla0),a ; set cntla |
|||
ld a,%00100000 ; div 30, div 16, div 1 (38400 baud for 18.432mhz cpu) |
|||
out0 (z180_cntlb0),a ; set cntlb |
|||
ld a,%01100110 ; no cts, no dcd, no break detect |
|||
out0 (z180_asext0),a ; set asext |
|||
xor a ; no interrupts |
|||
out0 (z180_stat0),a ; set stat0 |
|||
xor a ; signal success |
|||
ret ; done |
|||
; |
|||
asci_cinit1: |
|||
or $FF ; signal error |
|||
ret ; done |
|||
; |
|||
; |
|||
; |
|||
asci_cin: |
|||
call asci_cist ; check for char ready |
|||
jr z,asci_cin ; if not, loop |
|||
in0 a,(z180_rdr0) ; get char |
|||
ret ; done |
|||
; |
|||
; |
|||
; |
|||
asci_cout: |
|||
push af ; save incoming |
|||
asci_cout1: |
|||
call asci_cost ; ready for char? |
|||
jr z,asci_cout1 ; loop if not |
|||
pop af ; restore incoming |
|||
out0 (z180_tdr0),a ; write byte |
|||
ret ; and done |
|||
; |
|||
; |
|||
; |
|||
asci_cist: |
|||
in0 a,(z180_stat0) ; get status |
|||
push af ; save status |
|||
and $70 ; line error? |
|||
jr z,asci_cist1 ; continue if no errors |
|||
; |
|||
; clear line error(s) or nothing further can be received!!! |
|||
in0 a,(z180_cntla0) ; read cntla |
|||
res 3,a ; clear efr (error flag reset) |
|||
out0 (z180_cntla0),a ; update cntla |
|||
; |
|||
asci_cist1: |
|||
pop af ; recover original status |
|||
and $80 ; data ready? |
|||
ret |
|||
; |
|||
; |
|||
; |
|||
asci_cost: |
|||
in0 a,(z180_stat0) ; get status |
|||
and $02 ; isolate bit 5 |
|||
ret ; a != 0 if char ready, else 0 |
|||
@ -0,0 +1,588 @@ |
|||
; |
|||
; |
|||
;======================================================================= |
|||
; HDIAG Diagmostic ROM |
|||
;======================================================================= |
|||
; |
|||
; HDIAG is a framework for a diagnotic environment intended to be |
|||
; suitable for all systems supported by RomWBW. RomWBW expects hardware |
|||
; to be fully functional making it difficult to use it to initially |
|||
; check out a system. HDIAG is explicitly constructed to be as simple |
|||
; as possible. |
|||
; |
|||
; There is only a single variant of HDIAG that is built. HDIAG is |
|||
; designed to detect the environment it is operating under at startup |
|||
; and dynamically adapt to it. |
|||
; |
|||
; HDIAG can be assembled to boot in one of 2 modes (rom or application) |
|||
; as described below. When compiled, you must define exactly one of the |
|||
; following macros: |
|||
; |
|||
; - ROMBOOT: Boot from a rom bank |
|||
; |
|||
; When ROMBOOT is defined, the file is assembled to be imbedded at the |
|||
; start of a rom assuming that the cpu will start execution at address |
|||
; 0. |
|||
; |
|||
; - 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) |
|||
; OS. |
|||
; |
|||
#include "z180.inc" |
|||
; |
|||
;======================================================================= |
|||
; Page Zero Definition |
|||
;======================================================================= |
|||
; |
|||
; Generic page zero setup. Only applies to ROMBOOT startup mode. |
|||
; |
|||
#ifdef ROMBOOT |
|||
; |
|||
.org $0000 |
|||
; |
|||
jp hd_start ; rst $00: jump to boot code |
|||
.fill ($08-$) |
|||
ret ; rst $08 |
|||
.fill ($10-$) |
|||
ret ; rst $10 |
|||
.fill ($18-$) |
|||
ret ; rst $18 |
|||
.fill ($20-$) |
|||
ret ; rst $20 |
|||
.fill ($28-$) |
|||
ret ; rst $28 |
|||
.fill ($30-$) |
|||
ret ; rst $30 |
|||
.fill ($38-$) |
|||
reti ; h/w int return |
|||
.fill ($66-$) |
|||
retn ; h/w nmi return |
|||
.fill ($100-$) ; pad remainder of page zero |
|||
; |
|||
#else |
|||
.org $0100 |
|||
; |
|||
#endif |
|||
; |
|||
;======================================================================= |
|||
; Startup |
|||
;======================================================================= |
|||
; |
|||
; Before transitioning to RAM, we need to determine the memory |
|||
; manager to use because some platforms will not have any RAM mapped |
|||
; to the upper 32K of CPU address space until the memory manager |
|||
; is initialized. |
|||
; |
|||
hd_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 |
|||
; |
|||
; |
|||
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 |
|||
; |
|||
; Test for Z180 using mlt |
|||
ld de,$0506 ; 5 x 6 |
|||
mlt de ; de = 30 if Z180 |
|||
ld a,e ; check if multiply happened |
|||
cp 30 |
|||
jr nz,hd_tryZ280 ; if != 30, not a Z180, try Z280 |
|||
inc l ; Z80180 or better |
|||
; |
|||
#ifdef APPBOOT |
|||
; |
|||
; Reset Z180 internal register base to zero |
|||
xor a |
|||
out0 ($7F),a |
|||
out0 ($BF),a |
|||
out0 ($FF),a |
|||
; |
|||
#endif |
|||
; |
|||
; 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 |
|||
; |
|||
; Test for newer S-class (rev N) |
|||
; On older S-class, asci time constant reg does not exist |
|||
; and will always read back as $FF |
|||
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 |
|||
; |
|||
hd_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 |
|||
; |
|||
hd_z80res: |
|||
ld a,$01 |
|||
out (0),a |
|||
; Reset Z80 here (is there anything?) |
|||
jr hd_cpu1 |
|||
; |
|||
hd_z180res: |
|||
; |
|||
; Reset z180 registers here |
|||
; Set CPU speed to oscillator X 1 |
|||
xor a |
|||
out0 (z180_cmr),a |
|||
ld a,$80 |
|||
out0 (z180_ccr),a |
|||
; Set default wait states |
|||
ld a,$%00000100 ; mem wait=0, i/o wait=+1 |
|||
out0 (z180_dcntl),a |
|||
; |
|||
#ifdef ROMBOOT |
|||
; Setup Z180 MMU |
|||
; Keep ROM page zero in lower 32K!!! |
|||
ld a,$80 ; Common Base @ 32K, Bank Base @ 0K |
|||
out0 (z180_cbar),a |
|||
xor a ; Physical address zero |
|||
out0 (z180_cbr),a ; ... for Common Base |
|||
out0 (z180_bbr),a ; ... and Bank Base |
|||
#else |
|||
xor a ; Physical address zero |
|||
out0 (z180_cbr),a ; ... for Common Base |
|||
#endif |
|||
; |
|||
jr hd_cpu1 |
|||
; |
|||
hd_z280res: |
|||
; Reset Z280 registers here |
|||
; Make sure memmgr is reset to defaults! |
|||
jr hd_cpu1 |
|||
; |
|||
hd_cpu1: |
|||
ld a,$02 |
|||
out ($0D),a |
|||
; |
|||
; Reset Zeta 2 memory manager (in case it exists) |
|||
#ifdef ROMBOOT |
|||
xor a ; disable value |
|||
out ($7C),a ; write it |
|||
xor a ; 16K ROM page 0 |
|||
out ($78),a |
|||
inc a ; 16K ROM page 1 |
|||
out ($79),a |
|||
#endif |
|||
ld a,2 ; 16K ROM page 2 |
|||
out ($7A),a |
|||
inc a ; 16K ROM page 3 |
|||
out ($7B),a |
|||
; |
|||
; Reset N8 supplemental memory manager |
|||
; *** Need to implement this *** |
|||
; |
|||
ld a,$03 |
|||
out ($0D),a |
|||
; |
|||
; If SBC memmgr, RAM is already in himem, otherwise ROM |
|||
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! |
|||
; |
|||
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 |
|||
#ifdef ROMBOOT |
|||
xor a ; ROM page 0 |
|||
out ($78),a |
|||
inc a ; ROM page 1 |
|||
out ($79),a |
|||
#endif |
|||
ld a,$20 ; first RAM page |
|||
out ($7A),a |
|||
inc a ; second RAM page |
|||
out ($7B),a |
|||
ld a,1 ; enable paging |
|||
out ($7C),a |
|||
; |
|||
ld a,$05 |
|||
out ($0D),a |
|||
; |
|||
; Test himem RAM again |
|||
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 ; 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 |
|||
or a ; Z80? |
|||
jr nz,hd_z180init ; if no, do 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: |
|||
|
|||
|
|||
ld a,$07 |
|||
out ($0D),a |
|||
|
|||
|
|||
ld hl,str_halt |
|||
call prtstr |
|||
halt ; give up |
|||
; |
|||
hd_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 |
|||
|
|||
hd_N8init: |
|||
; Initialize N8 memory manager |
|||
ld h,3 |
|||
jr hd_cpu2 |
|||
|
|||
hd_z280init: |
|||
; Initialize Z280 memory manager |
|||
ld h,4 |
|||
jr hd_cpu2 |
|||
; |
|||
hd_cpu2: |
|||
ld a,$08 |
|||
out ($0D),a |
|||
; |
|||
ld ($8000),hl ; stash cpu/memmgr at $8000 |
|||
; |
|||
; Transition to upper memory (omit page zero) |
|||
; |
|||
ld hl,$0000+$100 |
|||
ld de,$8000+$100 |
|||
ld bc,$8000-$100 |
|||
ldir |
|||
jp hd_start2 |
|||
; |
|||
.org $ + $8000 |
|||
; |
|||
; |
|||
;======================================================================= |
|||
; Post-relocation Startup |
|||
;======================================================================= |
|||
; |
|||
hd_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 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 |
|||
; |
|||
ld hl,($8000) |
|||
ld (hd_cpu),hl |
|||
; |
|||
; Probe and initialize serial port console driver. We just go |
|||
; through the options stopping at the first one that works. The |
|||
; order of polling below is intended to find the most reasonable |
|||
; console port. |
|||
; |
|||
; |
|||
ld a,$0A |
|||
out ($0D),a |
|||
; |
|||
; Z280 UART |
|||
ld ix,z2u_jptbl |
|||
call jpix |
|||
jr z,hd_start3 |
|||
; ASCI |
|||
ld ix,asci_jptbl |
|||
call jpix |
|||
jr z,hd_start3 |
|||
; UART |
|||
ld ix,uart_jptbl |
|||
call jpix |
|||
jr z,hd_start3 |
|||
; ACIA |
|||
ld ix,acia_jptbl |
|||
call jpix |
|||
jr z,hd_start3 |
|||
; SIO |
|||
ld ix,sio_jptbl |
|||
call jpix |
|||
jr z,hd_start3 |
|||
; |
|||
; Ugh, nothing worked |
|||
ld a,$0C |
|||
out ($0D),a |
|||
halt |
|||
; |
|||
; |
|||
; |
|||
hd_start3: |
|||
; |
|||
ld a,$0D |
|||
out ($0D),a |
|||
; |
|||
; Copy selected console serial driver vector table into place |
|||
; |
|||
push ix |
|||
pop hl |
|||
ld de,hd_serjptbl |
|||
ld bc,5*3 |
|||
ldir |
|||
; |
|||
; |
|||
; |
|||
; Map a RAM page to lower 32K |
|||
; |
|||
; Setup zero page in lower 32K |
|||
; |
|||
; |
|||
; |
|||
hd_start4: |
|||
; |
|||
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 |
|||
; |
|||
; |
|||
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 |
|||
; |
|||
call cin |
|||
jp hd_start4 |
|||
; |
|||
; |
|||
; |
|||
jp hd_halt |
|||
; |
|||
;======================================================================= |
|||
; Helper functions |
|||
;======================================================================= |
|||
; |
|||
; |
|||
;======================================================================= |
|||
; Include various utility code modules |
|||
;======================================================================= |
|||
; |
|||
#include "util.asm" |
|||
; |
|||
;======================================================================= |
|||
; Console I/O |
|||
;======================================================================= |
|||
; |
|||
; 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 |
|||
; |
|||
#include "uart.asm" |
|||
#include "asci.asm" |
|||
#include "acia.asm" |
|||
#include "sio.asm" |
|||
#include "z2u.asm" |
|||
; |
|||
;======================================================================= |
|||
; Working literals and internal variables |
|||
;======================================================================= |
|||
; |
|||
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_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_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 |
|||
;======================================================================= |
|||
; |
|||
; This area is defined here, but copied to the top page of RAM at |
|||
; initialization! |
|||
; |
|||
; The top page (256 bytes) of CPU address space is used to maintain |
|||
; a jump table of functions available to all diagnostic modules. |
|||
; It also contains some global variables at fixed locations for use |
|||
; by diagnostic modules. |
|||
; |
|||
ffpgimg .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 |
|||
; |
|||
.fill $FF80-$ |
|||
hd_cpu .db 0 ; CPU type |
|||
hd_mmgr .db 0 ; Memory manager type |
|||
.end |
|||
|
|||
|
|||
File diff suppressed because it is too large
@ -0,0 +1,108 @@ |
|||
; |
|||
;======================================================================= |
|||
; HDIAG SIO Driver |
|||
;======================================================================= |
|||
; |
|||
; Assumes the UART port conventions for RC2014. Command/status port |
|||
; at $80 and read/write data port at $81. |
|||
; Assuming a UART clock frequency of 1.8432 MHz, the baud rate |
|||
; will be 38400. |
|||
; |
|||
sio_cmd .equ $80 ; SIO command/status port |
|||
sio_dat .equ $81 ; SIO read/write port |
|||
; |
|||
sio_jptbl: |
|||
jp sio_cinit ; Initialize serial port |
|||
jp sio_cin ; Read byte |
|||
jp sio_cout ; Write byte |
|||
jp sio_cist ; Input status |
|||
jp sio_cost ; Output Status |
|||
; |
|||
; |
|||
; |
|||
sio_cinit: |
|||
; Detect SIO here... |
|||
; Zero the int vector register |
|||
ld a,2 ; select WR2 (int vector) |
|||
out (sio_cmd+2),a ; do it |
|||
xor a ; zero accum |
|||
out (sio_cmd+2),a ; write to WR2 |
|||
; Read the int vector register and check for zero |
|||
ld a,2 ; select WR2 (int vector) |
|||
out (sio_cmd+2),a ; do it |
|||
in a,(sio_cmd+2) ; get int vector value |
|||
and $F0 ; only top nibble |
|||
ret nz ; abort if not zero |
|||
; Set test value in int vector register |
|||
ld a,2 ; select WR2 (int vector) |
|||
out (sio_cmd+2),a ; do it |
|||
ld a,$FF ; test value |
|||
out (sio_cmd+2),a ; write to WR2 |
|||
; Read the int vector register to confirm value written |
|||
ld a,2 ; select WR2 (int vector) |
|||
out (sio_cmd+2),a ; do it |
|||
in a,(sio_cmd+2) ; get int vector value |
|||
and $F0 ; only top nibble |
|||
cp $F0 ; compare |
|||
ret nz ; abort if miscompare |
|||
; |
|||
; Program the SIO, just channel A |
|||
ld c,sio_cmd ; command port |
|||
ld hl,sio_initregs ; point to init values |
|||
ld b,sio_initlen ; count of bytes to write |
|||
otir ; write all values |
|||
; |
|||
xor a ; signal success |
|||
ret ; done |
|||
; |
|||
; |
|||
; |
|||
sio_cin: |
|||
call sio_cist ; check for char ready |
|||
jr z,sio_cin ; if not, loop |
|||
in a,(sio_dat) ; read byte |
|||
ret ; done |
|||
; |
|||
; |
|||
; |
|||
sio_cout: |
|||
push af ; save incoming |
|||
sio_cout1: |
|||
call sio_cost ; ready for char? |
|||
jr z,sio_cout1 ; loop if not |
|||
pop af ; restore incoming |
|||
out (sio_dat),a ; write byte |
|||
ret ; and done |
|||
; |
|||
; |
|||
; |
|||
sio_cist: |
|||
xor a ; select WR0 |
|||
out (sio_cmd),a ; do it |
|||
in a,(sio_cmd) ; get status |
|||
and $01 ; isolate rx ready |
|||
ret ; a != 0 if rx ready, else 0 |
|||
; |
|||
; |
|||
; |
|||
sio_cost: |
|||
xor a ; select WR0 |
|||
out (sio_cmd),a ; do it |
|||
in a,(sio_cmd) ; get status |
|||
and $04 ; isolate tx ready (empty) |
|||
ret ; a != 0 if tx ready, else 0 |
|||
; |
|||
; Table for chip register initialization. Simple setup for clock |
|||
; divided by 64. Assuming a system clock of 7.3728 MHz, this will |
|||
; result in a baud rate of 115200 which is standard for RC2014. |
|||
; |
|||
sio_initregs: |
|||
.db $00, $18 ; wr0: channel reset cmd |
|||
.db $04, $C4 ; wr4: clk baud parity stop bit |
|||
.db $01, $00 ; wr1: no interrupts |
|||
.db $02, $00 ; wr2: im2 vec offset |
|||
.db $03, $E1 ; wr3: 8 bit rcv, cts/dcd auto, rx enable |
|||
.db $05, $EA ; wr5: dtr, 8 bits send, tx enable, rts 1 11 0 1 0 1 0 (1=dtr,11=8bits,0=sendbreak,1=txenable,0=sdlc,1=rts,0=txcrc) |
|||
; |
|||
sio_initlen .equ $-sio_initregs |
|||
|
|||
@ -0,0 +1,106 @@ |
|||
; |
|||
;======================================================================= |
|||
; HDIAG UART Driver |
|||
;======================================================================= |
|||
; |
|||
; Assumes the UART conventions for SBC/MBC/Zeta, base port at $68. |
|||
; Assuming a UART clock frequency of 1.8432 MHz, the baud rate |
|||
; will be 38400. |
|||
; |
|||
uart_iob .equ $68 |
|||
uart_osc .equ 1843200 |
|||
uart_baudrate .equ 38400 |
|||
uart_divisor .equ uart_osc / uart_baudrate / 16 |
|||
; |
|||
uart_rbr .equ uart_iob + 0 ; dlab=0: rcvr buffer reg (read only) |
|||
uart_thr .equ uart_iob + 0 ; dlab=0: xmit holding reg (write only) |
|||
uart_ier .equ uart_iob + 1 ; dlab=0: int enable reg |
|||
uart_iir .equ uart_iob + 2 ; int ident register (read only) |
|||
uart_fcr .equ uart_iob + 2 ; fifo control reg (write only) |
|||
uart_lcr .equ uart_iob + 3 ; line control reg |
|||
uart_mcr .equ uart_iob + 4 ; modem control reg |
|||
uart_lsr .equ uart_iob + 5 ; line status reg |
|||
uart_msr .equ uart_iob + 6 ; modem status reg |
|||
uart_scr .equ uart_iob + 7 ; scratch register |
|||
uart_dll .equ uart_iob + 0 ; dlab=1: divisor latch (ls) |
|||
uart_dlm .equ uart_iob + 1 ; dlab=1: divisor latch (ms) |
|||
; |
|||
; |
|||
; |
|||
uart_jptbl: |
|||
jp uart_cinit ; Initialize serial port |
|||
jp uart_cin ; Read byte |
|||
jp uart_cout ; Write byte |
|||
jp uart_cist ; Input status |
|||
jp uart_cost ; Output Status |
|||
; |
|||
; |
|||
; |
|||
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 |
|||
; |
|||
uart_cinit1: |
|||
ld a,$80 ; lcr := dlab on |
|||
out (uart_lcr),a ; set lcr |
|||
ld a,uart_divisor & $ff ; low byte of divisor |
|||
out (uart_dll),a ; set divisor (lsb) |
|||
ld a,uart_divisor / $100 ; high byte of divisor |
|||
out (uart_dlm),a ; set divisor (msb) |
|||
xor a ; zero accum |
|||
out (uart_ier),a ; init ier (no ints) |
|||
ld a,$03 ; value for lcr and mcr |
|||
out (uart_lcr),a ; lcr := 3, dlab off, 8 data, 1 stop, no parity |
|||
out (uart_mcr),a ; mcr := 3, dtr on, rts on |
|||
ld a,$07 ; enable & reset fifo's |
|||
out (uart_fcr),a ; do it |
|||
xor a ; signal success |
|||
ret |
|||
; |
|||
; |
|||
; |
|||
uart_cin: |
|||
call uart_cist ; received char ready? |
|||
jr z,uart_cin ; loop if not |
|||
in a,(uart_rbr) ; read byte |
|||
ret ; and done |
|||
; |
|||
; |
|||
; |
|||
uart_cout: |
|||
push af ; save incoming |
|||
uart_cout1: |
|||
call uart_cost ; ready for char? |
|||
jr z,uart_cout1 ; loop if not |
|||
pop af ; restore incoming |
|||
out (uart_thr),a ; write byte |
|||
ret ; and done |
|||
; |
|||
; |
|||
; |
|||
uart_cist: |
|||
in a,(uart_lsr) ; get status |
|||
and $01 ; isolate bit 0 (receive data ready) |
|||
ret ; a != 0 if char ready, else 0 |
|||
; |
|||
; |
|||
; |
|||
uart_cost: |
|||
in a,(uart_lsr) ; get status |
|||
and $20 ; isolate bit 5 |
|||
ret ; a != 0 if char ready, else 0 |
|||
@ -0,0 +1,106 @@ |
|||
; |
|||
;======================================================================= |
|||
; HDIAG Utility Functions |
|||
;======================================================================= |
|||
; |
|||
; Print string at HL on console, null terminated. |
|||
; HL and AF are trashed. |
|||
; |
|||
prtstr: |
|||
ld a,(hl) ; get next character |
|||
or a ; set flags |
|||
inc hl ; bump pointer regardless |
|||
ret z ; done if null |
|||
call cout ; display character |
|||
jr prtstr ; loop till done |
|||
; |
|||
; Print the hex byte value in A |
|||
; |
|||
prthex8: |
|||
push af |
|||
push de |
|||
call hexascii |
|||
ld a,d |
|||
call cout |
|||
ld a,e |
|||
call cout |
|||
pop de |
|||
pop af |
|||
ret |
|||
; |
|||
; Print the hex word value in BC |
|||
; |
|||
prthex16: |
|||
push af |
|||
ld a,b |
|||
call prthex8 |
|||
ld a,c |
|||
call prthex8 |
|||
pop af |
|||
ret |
|||
; |
|||
; Print the hex dword value in DE:HL |
|||
; |
|||
prthex32: |
|||
push bc |
|||
push de |
|||
pop bc |
|||
call prthex16 |
|||
push hl |
|||
pop bc |
|||
call prthex16 |
|||
pop bc |
|||
ret |
|||
; |
|||
; Convert binary value in A to ASCII hex characters in DE |
|||
; |
|||
hexascii: |
|||
ld d,a |
|||
call hexconv |
|||
ld e,a |
|||
ld a,d |
|||
rlca |
|||
rlca |
|||
rlca |
|||
rlca |
|||
call hexconv |
|||
ld d,a |
|||
ret |
|||
; |
|||
; Convert low nibble of A to ASCII hex |
|||
; |
|||
hexconv: |
|||
and $0F ; low nibble only |
|||
add a,$90 |
|||
daa |
|||
adc a,$40 |
|||
daa |
|||
ret |
|||
|
|||
; |
|||
; Jump to address in HL/IX/IY |
|||
; |
|||
; No registers affected |
|||
; Typically used as "call jphl" to call a routine |
|||
; at address in HL register. |
|||
; |
|||
jphl: |
|||
jp (hl) |
|||
; |
|||
jpix: |
|||
jp (ix) |
|||
; |
|||
jpiy: |
|||
jp (iy) |
|||
; |
|||
; Add hl,a |
|||
; |
|||
; A register is destroyed! |
|||
; |
|||
addhla: |
|||
add a,l |
|||
ld l,a |
|||
ret nc |
|||
inc h |
|||
ret |
|||
|
|||
@ -0,0 +1,71 @@ |
|||
; |
|||
;======================================================================= |
|||
; Z180 Internal I/O Ports |
|||
;======================================================================= |
|||
; |
|||
; These are offsets from the Z180 I/O base address. |
|||
; |
|||
z180_cntla0 .equ $00 ; asci0 control a |
|||
z180_cntla1 .equ $01 ; asci1 control a |
|||
z180_cntlb0 .equ $02 ; asci0 control b |
|||
z180_cntlb1 .equ $03 ; asci1 control b |
|||
z180_stat0 .equ $04 ; asci0 status |
|||
z180_stat1 .equ $05 ; asci1 status |
|||
z180_tdr0 .equ $06 ; asci0 transmit |
|||
z180_tdr1 .equ $07 ; asci1 transmit |
|||
z180_rdr0 .equ $08 ; asci0 receive |
|||
z180_rdr1 .equ $09 ; asci1 receive |
|||
z180_cntr .equ $0a ; csi/o control |
|||
z180_trdr .equ $0b ; csi/o transmit/receive |
|||
z180_tmdr0l .equ $0c ; timer 0 data lo |
|||
z180_tmdr0h .equ $0d ; timer 0 data hi |
|||
z180_rldr0l .equ $0e ; timer 0 reload lo |
|||
z180_rldr0h .equ $0f ; timer 0 reload hi |
|||
z180_tcr .equ $10 ; timer control |
|||
; |
|||
z180_asext0 .equ $12 ; asci0 extension control (z8s180) |
|||
z180_asext1 .equ $13 ; asci1 extension control (z8s180) |
|||
; |
|||
z180_tmdr1l .equ $14 ; timer 1 data lo |
|||
z180_tmdr1h .equ $15 ; timer 1 data hi |
|||
z180_rldr1l .equ $16 ; timer 1 reload lo |
|||
z180_rldr1h .equ $17 ; timer 1 reload hi |
|||
z180_frc .equ $18 ; free running counter |
|||
; |
|||
z180_astc0l .equ $1a ; asci0 time constant lo (z8s180) |
|||
z180_astc0h .equ $1b ; asci0 time constant hi (z8s180) |
|||
z180_astc1l .equ $1c ; asci1 time constant lo (z8s180) |
|||
z180_astc1h .equ $1d ; asci1 time constant hi (z8s180) |
|||
z180_cmr .equ $1e ; clock multiplier (latest z8s180) |
|||
z180_ccr .equ $1f ; cpu control (z8s180) |
|||
; |
|||
z180_sar0l .equ $20 ; dma0 source addr lo |
|||
z180_sar0h .equ $21 ; dma0 source addr hi |
|||
z180_sar0b .equ $22 ; dma0 source addr bank |
|||
z180_dar0l .equ $23 ; dma0 dest addr lo |
|||
z180_dar0h .equ $24 ; dma0 dest addr hi |
|||
z180_dar0b .equ $25 ; dma0 dest addr bank |
|||
z180_bcr0l .equ $26 ; dma0 byte count lo |
|||
z180_bcr0h .equ $27 ; dma0 byte count hi |
|||
z180_mar1l .equ $28 ; dma1 memory addr lo |
|||
z180_mar1h .equ $29 ; dma1 memory addr hi |
|||
z180_mar1b .equ $2a ; dma1 memory addr bank |
|||
z180_iar1l .equ $2b ; dma1 i/o addr lo |
|||
z180_iar1h .equ $2c ; dma1 i/o addr hi |
|||
z180_iar1b .equ $2d ; dma1 i/o addr bank (z8s180) |
|||
z180_bcr1l .equ $2e ; dma1 byte count lo |
|||
z180_bcr1h .equ $2f ; dma1 byte count hi |
|||
z180_dstat .equ $30 ; dma status |
|||
z180_dmode .equ $31 ; dma mode |
|||
z180_dcntl .equ $32 ; dma/wait control |
|||
z180_il .equ $33 ; interrupt vector load |
|||
z180_itc .equ $34 ; int/trap control |
|||
; |
|||
z180_rcr .equ $36 ; refresh control |
|||
; |
|||
z180_cbr .equ $38 ; mmu common base register |
|||
z180_bbr .equ $39 ; mmu bank base register |
|||
z180_cbar .equ $3a ; mmu common/bank area register |
|||
; |
|||
z180_omcr .equ $3e ; operation mode control |
|||
z180_icr .equ $3f ; i/o control register |
|||
@ -0,0 +1,49 @@ |
|||
; |
|||
;======================================================================= |
|||
; HDIAG Z180 UART Driver |
|||
;======================================================================= |
|||
; |
|||
z2u_jptbl: |
|||
jp z2u_cinit ; Initialize serial port |
|||
jp z2u_cin ; Read byte |
|||
jp z2u_cout ; Write byte |
|||
jp z2u_cist ; Input status |
|||
jp z2u_cost ; Output Status |
|||
; |
|||
; |
|||
; |
|||
z2u_cinit: |
|||
; initialize port here |
|||
or $FF ; signal failure for now |
|||
ret |
|||
; |
|||
; |
|||
; |
|||
z2u_cin: |
|||
call z2u_cist ; check for char ready |
|||
jr z,z2u_cin ; if not, loop |
|||
; read byte here |
|||
ret ; done |
|||
; |
|||
; |
|||
; |
|||
z2u_cout: |
|||
push af ; save incoming |
|||
z2u_cout1: |
|||
call z2u_cost ; ready for char? |
|||
jr z,z2u_cout1 ; loop if not |
|||
pop af ; restore incoming |
|||
; write byte here |
|||
ret ; and done |
|||
; |
|||
; |
|||
; |
|||
z2u_cist: |
|||
; check input status here |
|||
ret |
|||
; |
|||
; |
|||
; |
|||
z2u_cost: |
|||
; check output status here |
|||
ret ; a != 0 if char ready, else 0 |
|||
Loading…
Reference in new issue