From ea5293bb6ce484bf1ec9ab70befe10c3a36a70c2 Mon Sep 17 00:00:00 2001 From: Leo C Date: Thu, 14 May 2015 21:18:08 +0200 Subject: [PATCH] Initial commit --- .gitignore | 3 + cbios/.gitignore | 7 + cbios/Makefile | 141 +++++++++ cbios/ascip.180 | 126 ++++++++ cbios/bioskrnl.180 | 752 +++++++++++++++++++++++++++++++++++++++++++++ cbios/boot.180 | 179 +++++++++++ cbios/chario.180 | 149 +++++++++ cbios/conbuf.180 | 171 +++++++++++ cbios/config.inc | 1 + cbios/cpm3.lib | 180 +++++++++++ cbios/cpm3slr.lib | 179 +++++++++++ cbios/drvtbl.180 | 11 + cbios/gencpm.dat | 158 ++++++++++ cbios/misc.180 | 256 +++++++++++++++ cbios/mm.180 | 177 +++++++++++ cbios/modebaud.inc | 33 ++ cbios/move.180 | 138 +++++++++ cbios/msgbuf.180 | 484 +++++++++++++++++++++++++++++ cbios/scb.180 | 48 +++ cbios/sdio.180 | 384 +++++++++++++++++++++++ cbios/time.180 | 22 ++ cbios/z180.lib | 120 ++++++++ cbios/z180reg.inc | 1 + 23 files changed, 3720 insertions(+) create mode 100644 .gitignore create mode 100644 cbios/.gitignore create mode 100644 cbios/Makefile create mode 100644 cbios/ascip.180 create mode 100644 cbios/bioskrnl.180 create mode 100644 cbios/boot.180 create mode 100644 cbios/chario.180 create mode 100644 cbios/conbuf.180 create mode 120000 cbios/config.inc create mode 100644 cbios/cpm3.lib create mode 100644 cbios/cpm3slr.lib create mode 100644 cbios/drvtbl.180 create mode 100644 cbios/gencpm.dat create mode 100644 cbios/misc.180 create mode 100644 cbios/mm.180 create mode 100644 cbios/modebaud.inc create mode 100644 cbios/move.180 create mode 100644 cbios/msgbuf.180 create mode 100644 cbios/scb.180 create mode 100644 cbios/sdio.180 create mode 100644 cbios/time.180 create mode 100644 cbios/z180.lib create mode 120000 cbios/z180reg.inc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2214899 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/cpm3bin +/cpm3src + diff --git a/cbios/.gitignore b/cbios/.gitignore new file mode 100644 index 0000000..a6addbc --- /dev/null +++ b/cbios/.gitignore @@ -0,0 +1,7 @@ +/scratch +*.prn +*.lst +*.sym +*.rel +*.spr + diff --git a/cbios/Makefile b/cbios/Makefile new file mode 100644 index 0000000..2b7dd88 --- /dev/null +++ b/cbios/Makefile @@ -0,0 +1,141 @@ + + +SRC := bioskrnl.180 boot.180 chario.180 drvtbl.180 +SRC += move.180 misc.180 time.180 mm.180 +SRC += msgbuf.180 conbuf.180 ascip.180 sdio.180 +SRC += scb.180 + +INC := config.inc z180reg.inc z180.lib + +OBJ := $(SRC:.180=.rel) + +#CP/M emulator +CPMEMU = zxcc + +#Location of CP/M binaries +CPMBIN = /usr/local/lib/cpm/bin80 + +#AS = $(CPMEMU) $(CPMBIN)/m80.com +AS = $(CPMEMU) slr180.com +#LN = $(CPMEMU) slrnk+.com +#LN = $(CPMEMU) ccpline.com + +AS_OPT := MFS + +AS_QUIET = 1 +LN_QUIET = 1 + +#LNKCMD = +LN_VERB = /V +LN_PROG = 0 +LN_DATA = C000 + + +.suffixes: +#.suffixes: .180 .rel + +.phony: all +all: sys + +bios: bnkbios3.spr + +sys: cpm3.sys + +$(OBJ): $(INC) + +comma:= , +empty:= +space:= $(empty) $(empty) + +ccpline = $(CPMEMU) $(1) -$(subst $(space),$(comma),$(strip $(2))) + +define cpm-asm = +COMMAND="$(AS) -$(basename $<)/$(AS_OPT)"; \ +OUTPUT=$$(mktemp); echo $${COMMAND}; \ +$${COMMAND} > $${OUTPUT}; \ +grep -q '^ 0 Error(s) Detected' $${OUTPUT}; ERROR=$$? ; \ +if [ "$${ERROR}" != "0" ]; then cat $${OUTPUT}; rm -f $@; fi ; \ +exit $${ERROR} +endef + +define cpm-link = + COMMAND="$(call ccpline, slrnk+, $(basename $@)/H/M /V \ + /P:$(LN_PROG) /D:$(LN_DATA) $(basename $^) /E /Q)";\ + OUTPUT=$$(mktemp); echo $${COMMAND};\ + $${COMMAND} > $${OUTPUT} || exit 1;\ + ERROR=0;\ + cat $${OUTPUT};\ + grep -q ' Duplicate Symbol ' $${OUTPUT} && ERROR=2; \ + grep -q '\- Previously Defined' $${OUTPUT} && ERROR=2; \ + [ "$${ERROR}" = "0" ] && grep -q '^ ** ' $${OUTPUT} && ERROR=1 ; \ + [ "$${ERROR}" != "0" ] && rm -f $@; \ + exit $${ERROR} +endef + +#link80 bnkbios3[b,q]=bioskrnl,boot,chario,drvtbl,... +define cpm-bioslink = + COMMAND="$(call ccpline, link80, \ + $(basename $@)=$(basename $^))[b,q]";\ + OUTPUT=$$(mktemp); echo $${COMMAND};\ + $${COMMAND} > $${OUTPUT} || exit 1;\ + ERROR=0;\ + grep -Ev '^[@?$$. 0-9A-Z]{7} [0-9A-F]{4}' $${OUTPUT};\ + grep -q ':' $${OUTPUT} && ERROR=2; \ + [ "$${ERROR}" != "0" ] && rm -f $@; \ + exit $${ERROR} +endef + + + +#Use: MAKESYM Filename[.ext][/PXXXX][/DXXXX][/CXXXX] +#egrep '^[[:xdigit:]]{4}[[:space:]]+[[:xdigit:]]{4}[[:space:]]+D.*init\.rel' hdrom.map +define cpm-mksym = +COMMAND="$(CPMEMU) makesym -$^ -/P -D"; \ +OUTPUT=$$(mktemp); echo $${COMMAND}; \ +$${COMMAND} > $${OUTPUT}; \ +grep -q '^ 0 Error(s) Detected' $${OUTPUT}; ERROR=$$? ; \ +if [ "$${ERROR}" != "0" ]; then cat $${OUTPUT}; rm -f $@; fi ; \ +exit $${ERROR} +endef + +cpm3.sys: bnkbios3.spr + zxcc gencpm -auto + @echo + + +bnkbios3.spr : $(OBJ) + @$(cpm-bioslink) + @#ld80 -o $@ -ms $(@:.hex=.map) -P $(LN_PROG) -D $(LN_DATA) $^ + +%.rel %lst: %.180 + @$(cpm-asm) + + +.phony: clean realclean +clean: + rm -f $(OBJ) $(OBJ:.rel=.lst) $(OBJ:.rel=.sym) + +realclean: clean + rm -f *.prn *~ + + +#================================================================== + +%.REL: %.MAC + @COMMAND="$(AS) =$<"; \ + OUTPUT=$$(mktemp); echo $${COMMAND}; \ + $${COMMAND} > $${OUTPUT}; \ + grep -q 'No Fatal error(s).$$' $${OUTPUT}; ERROR=$$? ; \ + if [ "$${ERROR}" != "0" ]; then cat $${OUTPUT}; rm $@; fi ; \ + rm $${OUTPUT}; \ + exit $${ERROR} + + +%.PRN: %.MAC + @COMMAND="$(AS) ,$@=$<"; \ + OUTPUT=$$(mktemp); echo $${COMMAND}; \ + $${COMMAND} > $${OUTPUT}; \ + grep -q 'No Fatal error(s).$$' $${OUTPUT}; ERROR=$$? ; \ + if [ "$${ERROR}" != "0" ]; then cat $${OUTPUT}; fi ; \ + rm $${OUTPUT}; \ + exit $${ERROR} diff --git a/cbios/ascip.180 b/cbios/ascip.180 new file mode 100644 index 0000000..d0e9ecd --- /dev/null +++ b/cbios/ascip.180 @@ -0,0 +1,126 @@ + page 200 + +; Simple polling drivers for ASCI0 and ASCI1 + + extrn ioiniml + + global as0init + global as0ista,as0inp + global as0osta,as0out + global as1init + global as1ista,as1inp + global as1osta,as1out + + include config.inc + include z180reg.inc + + +;-------------------------------------------------------------- +; +; +; TC = (f PHI /(2*baudrate*Clock_mode)) - 2 +; +; TC = (f PHI / (32 * baudrate)) - 2 +; + + cseg +; +; Init Serial I/O for console input and output (ASCI1) +; + +; TODO: set baudrate + +as0init: + ld hl,initab0 + jp ioiniml + +as1init: + ld hl,initab1 + jp ioiniml + + + + +initab0: + db 1,stat0,0 ;Disable rx/tx interrupts + ;Enable baud rate generator + db 1,asext0,M_BRGMOD+M_DCD0DIS+M_CTS0DIS + db 2,astc0l,low 28, high 28 + db 1,cntlb0,M_MPBT ;No MP Mode, X16 + db 1,cntla0,M_RE+M_TE+M_MOD2 ;Rx/Tx enable, 8N1 + db 0 + +initab1: + db 1,stat1,0 ;Disable rx/tx ints, disable CTS1 + db 1,asext1,M_BRGMOD ;Enable baud rate generator + db 2,astc1l,low 3, high 3 + db 1,cntlb1,M_MPBT ;No MP Mode, X16 + db 1,cntla1,M_RE+M_TE+M_MOD2 ;Rx/Tx enable, 8N1 + db 0 + + +;-------------------------------------------------------------- + +as0ista: + in0 a,(stat0) + and M_RDRF + ret z + or 0ffh + ret + +as1ista: + in0 a,(stat1) + and M_RDRF + ret z + or 0ffh + ret + + +as0inp: + in0 a,(stat0) + rlca + jr nc,as0inp + in0 a,rdr0 + ret + +as1inp: + in0 a,(stat1) + rlca + jr nc,as1inp + in0 a,rdr1 + ret + + + +as0osta: + in0 a,(stat0) + and M_TDRE + ret z + or 0ffh + ret + +as1osta: + in0 a,(stat1) + and M_TDRE + ret z + or 0ffh + ret + + +as0out: + in0 a,(stat0) + and M_TDRE + jr z,as0out + out0 (tdr0),c + ld a,c + ret + +as1out: + in0 a,(stat1) + and M_TDRE + jr z,as1out + out0 (tdr1),c + ld a,c + ret + + end diff --git a/cbios/bioskrnl.180 b/cbios/bioskrnl.180 new file mode 100644 index 0000000..0929013 --- /dev/null +++ b/cbios/bioskrnl.180 @@ -0,0 +1,752 @@ + title 'Root module of relocatable BIOS for CP/M 3.0' + + ; version 1.0 15 Sept 82 + + include config.inc + include z180reg.inc + + +; Copyright (C), 1982 +; Digital Research, Inc +; P.O. Box 579 +; Pacific Grove, CA 93950 + + +; This is the invariant portion of the modular BIOS and is +; distributed as source for informational purposes only. +; All desired modifications should be performed by +; adding or changing externally defined modules. +; This allows producing "standard" I/O modules that +; can be combined to support a particular system +; configuration. + +cr equ 13 +lf equ 10 +bell equ 7 +ctlQ equ 'Q'-'@' +ctlS equ 'S'-'@' + +ccp equ 0100h ; Console Command Processor gets loaded + ; into the TPA + + cseg ; GENCPM puts CSEG stuff in common memory + + + ; variables in system data page + + extrn @covec,@civec,@aovec,@aivec,@lovec ; I/O redirection vectors + extrn @mxtpa ; addr of system entry point + extrn @bnkbf ; 128 byte scratch buffer + + ; initialization + + extrn hwinit,?init ; general initialization and signon + extrn ?ldccp,?rlccp ; load & reload CCP for BOOT & WBOOT + + ; user defined character I/O routines + + extrn ?ci,?co,?cist,?cost ; each take device in + extrn ?cinit ; (re)initialize device in + extrn @ctbl ; physical character device table + + ; disk communication data items + + extrn @dtbl ; table of pointers to XDPHs + public @adrv,@rdrv,@trk,@sect ; parameters for disk I/O + public @dma,@dbnk,@cnt ; '' '' '' '' + + ; memory control + + public @cbnk ; current bank + extrn ?xmove,?move ; select move bank, and block move + extrn ?bank ; select CPU bank + + ; clock support + + extrn ?time ; signal time operation + + ; general utility routines + + public ?pmsg,?pdec ; print message, print number from 0 to 65535 + public ?pderr ; print BIOS disk error message header + + include modebaud.inc ; define mode bits + + + ; External names for BIOS entry points + + public ?boot,?wboot,?const,?conin,?cono,?list,?auxo,?auxi + public ?home,?sldsk,?sttrk,?stsec,?stdma,?read,?write + public ?lists,?sctrn + public ?conos,?auxis,?auxos,?dvtbl,?devin,?drtbl + public ?mltio,?flush,?mov,?tim,?bnksl,?stbnk,?xmov + + public bs$stack + + + ; BIOS Jump vector. + + ; All BIOS routines are invoked by calling these + ; entry points. + +?boot: jp boot ; initial entry on cold start +?wboot: jp wboot ; reentry on program exit, warm start + +?const: jp const ; return console input status +?conin: jp conin ; return console input character +?cono: jp conout ; send console output character +?list: jp list ; send list output character +?auxo: jp auxout ; send auxiliary output character +?auxi: jp auxin ; return auxiliary input character + +?home: jp home ; set disks to logical home +?sldsk: jp seldsk ; select disk drive, return disk parameter info +?sttrk: jp settrk ; set disk track +?stsec: jp setsec ; set disk sector +?stdma: jp setdma ; set disk I/O memory address +?read: jp read ; read physical block(s) +?write: jp write ; write physical block(s) + +?lists: jp listst ; return list device status +?sctrn: jp sectrn ; translate logical to physical sector + +?conos: jp conost ; return console output status +?auxis: jp auxist ; return aux input status +?auxos: jp auxost ; return aux output status +?dvtbl: jp devtbl ; return address of device def table +?devin: jp ?cinit ; change baud rate of device + +?drtbl: jp getdrv ; return address of disk drive table +?mltio: jp multio ; set multiple record count for disk I/O +?flush: jp flush ; flush BIOS maintained disk caching + +?mov: jp ?move ; block move memory to memory +?tim: jp ?time ; Signal Time and Date operation +?bnksl: jp bnksel ; select bank for code execution and default DMA +?stbnk: jp setbnk ; select different bank for disk I/O DMA operations +?xmov: jp ?xmove ; set source and destination banks for one operation + + jp 0 ; reserved for future expansion + jp 0 ; reserved for future expansion + jp 0 ; reserved for future expansion + + + ; BOOT + ; Initial entry point for system startup. + + dseg ; this part can be banked + +boot: + ld sp,bs$stack + + call hwinit ; first time hardware initialisation + + ld c,15 ; initialize all 16 character devices +c$init$loop: + push bc + call ?cinit + pop bc + dec c + jp p,c$init$loop + + call ?init ; perform any additional system initialization + ; and print signon message + + ld bc,16*256+0 + ld hl,@dtbl ; init all 16 logical disk drives +d$init$loop: + push bc ; save remaining count and abs drive + ld e,(hl) + inc hl + ld d,(hl) + inc hl ; grab @drv entry + ld a,e + or d + jr z,d$init$next ; if null, no drive + push hl ; save @drv pointer + if 0 + ex de,hl ; XDPH address in + dec hl + dec hl + ld b,(hl) ; get relative drive code + ld (@ADRV),bc ; save absolute and relative drive code + dec hl ; point to init pointer + ld d,(hl) + dec hl + ld e,(hl) ; get init pointer + ex de,hl + call ipchl ; call init routine + else + push de + pop ix + ld b,(ix-2) + ld (@ADRV),bc ; save absolute and relative drive code + ld l,(ix-4) + ld h,(ix-3) ; get init pointer + call ipchl ; call init routine + endif + pop hl ; recover @drv pointer +d$init$next: + pop bc ; recover counter and drive # + inc c + djnz d$init$loop ; and loop for each drive + jp boot$1 + + cseg ; following in resident memory + +boot$1: + call set$jumps + call ?ldccp ; fetch CCP for first time + jp ccp + + + ; WBOOT + ; Entry for system restarts. + +wboot: + ld sp,bs$stack + call set$jumps ; initialize page zero + call ?rlccp ; reload CCP + jp ccp ; then reset jmp vectors and exit to ccp + + +set$jumps: + + if banked + ld a,1 + call ?bnksl + endif + + ld a,0C3h ; jp opcode + ld (0),a + ld (5),a ; set up jumps in page zero + ld hl,?wboot + ld (1),hl ; BIOS warm start entry + ld hl,(@MXTPA) + ld (6),hl ; BDOS system call entry + ret + + + ds 64 +bs$stack equ $ + + + ; DEVTBL + ; Return address of character device table + +devtbl: + ld hl,@ctbl + ret + + + ; GETDRV + ; Return address of drive table + +getdrv: + ld hl,@dtbl + ret + + + + ; CONOUT + ; Console Output. Send character in + ; to all selected devices + +conout: + + ld hl,(@covec) ; fetch console output bit vector + jr out$scan + + + ; AUXOUT + ; Auxiliary Output. Send character in + ; to all selected devices + +auxout: + ld hl,(@aovec) ; fetch aux output bit vector + jr out$scan + + + ; LIST + ; List Output. Send character in + ; to all selected devices. + +list: + ld hl,(@lovec) ; fetch list output bit vector + +out$scan: + ld b,0 ; start with device 0 +co$next: + add hl,hl ; shift out next bit + jr nc,not$out$device + push hl ; save the vector + push bc ; save the count and character +not$out$ready: + call coster + or a + jp z,not$out$ready + pop bc + push bc ; restore and resave the character and device + call ?co ; if device selected, print it + pop bc ; recover count and character + pop hl ; recover the rest of the vector +not$out$device: + inc b ; next device number + ld a,h + or l ; see if any devices left + jr nz,co$next ; and go find them... + ret + + + ; CONOST + ; Console Output Status. Return true if + ; all selected console output devices + ; are ready. + +conost: + ld hl,(@covec) ; get console output bit vector + jr ost$scan + + + ; AUXOST + ; Auxiliary Output Status. Return true if + ; all selected auxiliary output devices + ; are ready. + +auxost: + ld hl,(@aovec) ; get aux output bit vector + jr ost$scan + + + ; LISTST + ; List Output Status. Return true if + ; all selected list output devices + ; are ready. + +listst: + ld hl,(@lovec) ; get list output bit vector + +ost$scan: + ld b,0 ; start with device 0 +cos$next: + add hl,hl ; check next bit + push hl ; save the vector + push bc ; save the count + ld a,0FFh ; assume device ready + call c,coster ; check status for this device + pop bc ; recover count + pop hl ; recover bit vector + or a ; see if device ready + ret z ; if any not ready, return false + inc b ; drop device number + ld a,h + or l ; see if any more selected devices + jr nz,cos$next + or 0FFh ; all selected were ready, return true + ret + +coster: ; check for output device ready, including optional + ; xon/xoff support + ld l,b + ld h,0 ; make device code 16 bits + push hl ; save it in stack + add hl,hl + add hl,hl + add hl,hl ; create offset into device characteristics tbl + ld de,@ctbl+6 + add hl,de ; make address of mode byte + ld a,(hl) + and mb$xon$xoff + pop hl ; recover console number in + jp z,?cost ; not a xon device, go get output status direct + ld de,xofflist + add hl,de ; make pointer to proper xon/xoff flag + call cist1 ; see if this keyboard has character + ld a,(hl) + call nz,ci1 ; get flag or read key if any + cp ctlq + jr nz,not$q ; if its a ctl-Q, + ld a,0FFh ; set the flag ready +not$q: + cp ctls + jr nz,not$s ; if its a ctl-S, + ld a,00h ; clear the flag +not$s: + ld (hl),a ; save the flag + call cost1 ; get the actual output status, + and (hl) ; and mask with ctl-Q/ctl-S flag + ret ; return this as the status + +cist1: ; get input status with and saved + push bc + push hl + call ?cist + pop hl + pop bc + or a + ret + +cost1: ; get output status, saving & + push bc + push hl + call ?cost + pop hl + pop bc + or a + ret + +ci1: ; get input, saving & + push bc + push hl + call ?ci + pop hl + pop bc + ret + + + ; CONST + ; Console Input Status. Return true if + ; any selected console input device + ; has an available character. + +const: + ld hl,(@civec) ; get console input bit vector + jr ist$scan + + + ; AUXIST + ; Auxiliary Input Status. Return true if + ; any selected auxiliary input device + ; has an available character. + +auxist: + ld hl,(@aivec) ; get aux input bit vector + +ist$scan: + ld b,0 ; start with device 0 +cis$next: + add hl,hl ; check next bit + ld a,0 ; assume device not ready + call c,cist1 ; check status for this device + or a + ret nz ; if any ready, return true + inc b ; next device number + ld a,h + or l ; see if any more selected devices + jr nz,cis$next + xor a ; all selected were not ready, return false + ret + + + ; CONIN + ; Console Input. Return character from first + ; ready console input device. + +conin: + ld hl,(@civec) + jr in$scan + + + ; AUXIN + ; Auxiliary Input. Return character from first + ; ready auxiliary input device. + +auxin: + ld hl,(@aivec) + +in$scan: + push hl ; save bit vector + ld b,0 +ci$next: + add hl,hl ; shift out next bit + ld a,0 ; insure zero a (nonexistant device not ready). + call c,cist1 ; see if the device has a character + or a + jr nz,ci$rdy ; this device has a character + inc b ; else, next device + ld a,h + or l ; see if any more devices + jr nz,ci$next ; go look at them + pop hl ; recover bit vector + jr in$scan ; loop til we find a character + +ci$rdy: + pop hl ; discard extra stack + jp ?ci + + +; Utility Subroutines + + +ipchl: ; vectored CALL point + jp (hl) + + +?pmsg: ; print message @ up to a null + ; saves & + push bc + push de +pmsg$loop: + ld a,(hl) + or a + jr z,pmsg$exit + ld c,a + push hl + call ?cono + pop hl + inc hl + jr pmsg$loop +pmsg$exit: + pop de + pop bc + ret + +?pdec: ; print binary number 0-65535 from + ld bc,table10 + ld de,-10000 +next: + ld a,'0'-1 +pdecl: + push hl + inc a + add hl,de + jp nc,stoploop + inc sp + inc sp + jp pdecl +stoploop: + push de + push bc + ld c,a + call ?cono + pop bc + pop de +nextdigit: + pop hl + ld a,(bc) + ld e,a + inc bc + ld a,(bc) + ld d,a + inc bc + ld a,e + or d + jp nz,next + ret + +table10: + dw -1000,-100,-10,-1,0 + +?pderr: + ld hl,drive$msg + call ?pmsg ; error header + ld a,(@adrv) + add a,'A' + ld c,a + call ?cono ; drive code + ld hl,track$msg + call ?pmsg ; track header + ld hl,(@trk) + call ?pdec ; track number + ld hl,sector$msg + call ?pmsg ; sector header + ld hl,(@sect) + call ?pdec ; sector number + ret + + + ; BNKSEL + ; Bank Select. Select CPU bank for further execution. + +bnksel: + ld (@cbnk),a ; remember current bank + jp ?bank ; and go exit through users + ; physical bank select routine + + +xofflist: + db -1,-1,-1,-1,-1,-1,-1,-1 ; ctl-s clears to zero + db -1,-1,-1,-1,-1,-1,-1,-1 + + + + dseg ; following resides in banked memory + + + +; Disk I/O interface routines + + + ; SELDSK + ; Select Disk Drive. Drive code in . + ; Invoke login procedure for drive + ; if this is first select. Return + ; address of disk parameter header + ; in + +seldsk: + ld a,c ; save drive select code + ld (@adrv),a + ld b,0 ; create index from drive code + ld hl,@dtbl + add hl,bc ; get pointer to dispatch table + add hl,bc + ld a,(hl) + inc hl + ld h,(hl) + ld l,a ; point at disk descriptor + ld (@xdph),hl ; save descriptor pointer + or h + ret z ; if no entry in table, no disk + + ld a,e ; examine login bit + and 1 + ret nz + + push ix + ld ix,(@xdph) + ld a,(ix-2) + ld (@RDRV),a ; get relative drive + ld l,(ix-6) ; get address of LOGIN routine + ld h,(ix-5) + ex (sp),ix + pop de + call ipchl ; call LOGIN + ld hl,(@xdph) ; recover DPH pointer + ret + + + ; HOME + ; Home selected drive. Treated as SETTRK(0). + +home: + ld bc,0 ; same as set track zero + + + ; SETTRK + ; Set Track. Saves track address from + ; in @TRK for further operations. + +settrk: + ld (@trk),bc + ret + + + ; SETSEC + ; Set Sector. Saves sector number from + ; in @sect for further operations. + +setsec: + ld (@sect),bc + ret + + + ; SETDMA + ; Set Disk Memory Address. Saves DMA address + ; from in @DMA and sets @DBNK to @CBNK + ; so that further disk operations take place + ; in current bank. + +setdma: + ld (@dma),bc + + ld a,(@cbnk) ; default DMA bank is current bank + ; fall through to set DMA bank + + ; SETBNK + ; Set Disk Memory Bank. Saves bank number + ; in @DBNK for future disk data + ; transfers. + +setbnk: + ld (@dbnk),a + ret + + + ; SECTRN + ; Sector Translate. Indexes skew table in + ; with sector in . Returns physical sector + ; in . If no skew table (=0) then + ; returns physical=logical. + +sectrn: + ld l,c + ld h,b + ld a,d + or e + ret z + ex de,hl + add hl,bc + ld l,(hl) + ld h,0 + ret + + + ; READ + ; Read physical record from currently selected drive. + ; Finds address of proper read routine from + ; extended disk parameter header (XDPH). + +read: + ld ix,(@xdph) ; get drive descriptor pointer + ld l,(ix-8) ; get read routine entry + ld h,(ix-7) + jp (hl) + + + ; WRITE + ; Write physical sector from currently selected drive. + ; Finds address of proper write routine from + ; extended disk parameter header (XDPH). + +write: + ld ix,(@xdph) ; get drive descriptor pointer + ld l,(ix-10) ; get write routine entry + ld h,(ix- 9) + jp (hl) + + + + ; MULTIO + ; Set multiple sector count. Saves passed count in + ; @CNT + +multio: + ld (@cnt),a + ret + + + ; FLUSH + ; BIOS deblocking buffer flush. Not implemented. + +flush: + xor a + ret ; return with no error + + + + ; error message components +drive$msg: db cr,lf,bell,'BIOS Error on ',0 +track$msg: db ': T-',0 +sector$msg: db ', S-',0 + + +; disk communication data items +; do not change order. sd driver depends on this + +@xdph: ds 2 ; pointer to currently selected drives dph +@adrv: ds 1 ; currently selected disk drive +@rdrv: ds 1 ; controller relative disk drive +@cnt: db 0 ; record count for multisector transfer +@trk: ds 2 ; current track number +@sect: ds 2 ; current sector number +@dma: ds 2 ; current DMA address +@dbnk: db 0 ; bank for DMA operations + + + cseg ; common memory + +@cbnk: db 0 ; bank for processor operations + + + end diff --git a/cbios/boot.180 b/cbios/boot.180 new file mode 100644 index 0000000..0e36bcd --- /dev/null +++ b/cbios/boot.180 @@ -0,0 +1,179 @@ + title 'Boot loader module for CP/M 3.0' + + + + public hwinit,?init,?ldccp,?rlccp + + extrn ?boot,?pmsg,?conin + extrn ioini1l,msginit,mmuinit,intinit + extrn @civec,@covec,@aivec,@aovec,@lovec + extrn @cbnk,?bnksl + + include config.inc + include z180reg.inc + + +bdos equ 5 + +ccpsize equ 0c80h + + if banked +tpa$bank equ 1 + else +tpa$bank equ 0 + endif + + + dseg ; init done from banked memory + +hwinit: + ld a,(INIDONE) + cp INIDONEVAL + jr z,hwini_skip + ld hl,hwini_tab + call ioini1l + ld a,0c3h + ld hl,?boot + ld (0),a + ld (1),hl +hwini_skip: + call mmuinit ; setup mmu registers + call msginit + ret + +?init: + ld hl,0100000000000000b ; assign console to ASCI1: + ld (@civec),hl + ld (@covec),hl + ld hl,0000000000000000b ; assign printer to nothing: + ld (@lovec),hl + ld hl,0100000000000000b ; assign AUX to ASCI0: + ld (@aivec),hl + ld (@aovec),hl + + + call intinit ; setup interrupts and vectors + + xor a + ld (@cbnk),a ; right now in bank 0 + + ld hl,signon$msg + call ?pmsg ; print signon message + ret + + + cseg ; boot loading most be done from resident memory + +; This version of the boot loader loads the CCP from a file +; called CCP.COM on the system drive (A:). + + +?ldccp: + ; First time, load the A:CCP.COM file into TPA + xor a + ld (ccp$fcb+15),a ; zero extent + ld hl,0 + ld (fcb$nr),hl ; start at beginning of file + ld de,ccp$fcb + call open ; open file containing CCP + inc a + jp z,no$ccp ; error if no file... + ld de,0100h + call setdma ; start of TPA + ld de,128 + call setmulti ; allow up to 16k bytes + ld de,ccp$fcb + call read ; load the thing + ; now, + ; copy CCP to bank 0 for reloading + ld hl,0100h + ld bc,ccpsize ; clone 3K, just in case + ld a,(@cbnk) + push af ; save current bank +ld$1: + ld a,tpa$bank + call ?bnksl ; select TPA + ld a,(hl) + push af ; get a byte + ld a,2 + call ?bnksl ; select extra bank + pop af + ld (hl),a ; save the byte + inc hl + dec bc ; bump pointer, drop count + ld a,b + or c ; test for done + jp nz,ld$1 + pop af + call ?bnksl ; restore original bank + ret + +no$ccp: ; here if we couldn't find the file + ld hl,ccp$msg + call ?pmsg ; report this... + call ?conin ; get a response + jp ?ldccp ; and try again + + +?rlccp: + ld hl,0100h + ld bc,ccpsize ; clone 3K +rl$1: + ld a,2 + call ?bnksl ; select extra bank + ld a,(hl) + push af ; get a byte + ld a,tpa$bank + call ?bnksl ; select TPA + pop af + ld (hl),a ; save the byte + inc hl + dec bc ; bump pointer, drop count + ld a,b + or c ; test for done + jp nz,rl$1 + ret + + + ; CP/M BDOS Function Interfaces + +open: + ld c,15 + jp bdos ; open file control block + +setdma: + ld c,26 + jp bdos ; set data transfer address + +setmulti: + ld c,44 + jp bdos ; set record count + +read: + ld c,20 + jp bdos ; read records + + +signon$msg: + db 13,10,13,10,'CP/M Version 3.0, Z180-Stamp BIOS',13,10,0 + +ccp$msg:db 13,10,'BIOS Err on A: No CCP.COM file',0 + + +ccp$fcb:db 1,'CCP ','COM',0,0,0,0 + ds 16 +fcb$nr: db 0,0,0 + + +hwini_tab: + db (hwini0_e-$)/2 ;count + db rcr,CREFSH ;configure DRAM refresh + db dcntl,CWAITIO ;wait states + db ccr,M_NCD ;No Clock Divide + db cmr,PHI_X2 ;X2 Clock Multiplier +;TODO: db omr, ;Operation Mode Control Register +hwini0_e: + db 0 ;stop mark + + + end diff --git a/cbios/chario.180 b/cbios/chario.180 new file mode 100644 index 0000000..3b02c8d --- /dev/null +++ b/cbios/chario.180 @@ -0,0 +1,149 @@ + title 'Character I/O Module for the Modular CP/M 3 BIOS' + page 255 + .z80 + + + + public ?cinit,?ci,?co,?cist,?cost + public @ctbl + + + extrn ff.init,ff.ist,ff.in,ff.ost,ff.out + extrn as0init,as0ista,as0inp,as0osta,as0out + extrn as1init,as1ista,as1inp,as1osta,as1out + + + include config.inc + include z180reg.inc + + include modebaud.inc ; define mode bits and baud equates + +max$devices equ 3 + + cseg + +;-------------------------------------------------------------- +; Init character device +; c: device + +?cinit: ; init devices + ld b,c + call vector$io + dw ff.init + dw as0init + dw as1init + dw rret + +;-------------------------------------------------------------- +; Character input +; b: device +; return: +; a: input char + +?ci: ; character input + call vector$io + dw ff.in + dw as0inp + dw as1inp + dw null$input + +;-------------------------------------------------------------- +; Input status +; b: device +; return: +; a: 0ffh if char available, else 0 + +?cist: ; character input status + call vector$io + dw ff.ist + dw as0ista + dw as1ista + dw null$status + +;-------------------------------------------------------------- +; Character output +; b: device +; c: output char +; return: +; a: output char + +?co: ; character output + call vector$io + dw ff.out + dw as0out + dw as1out + dw rret + + +;-------------------------------------------------------------- +; Output status +; b: device +; return: +; a: 0ffh if device ready for next output char, else 0 + + +?cost: ; character output status + call vector$io + dw ff.ost + dw as0osta + dw as1osta + dw ret$true + +;-------------------------------------------------------------- + +vector$io: + ld a,max$devices + ld e,b +vector: + pop hl + ld d,0 + cp e + jr nc,exist + ld e,a ; use null device if a >= max$devices +exist: add hl,de + add hl,de + ld a,(hl) + inc hl + ld h,(hl) + ld l,a + jp (hl) + + +null$input: + ld a,1Ah +rret: + ret +ret$true: + or 0FFh + ret + +null$status: + xor a + ret + +;-------------------------------------------------------------- + +@ctbl: + db 'AVRCON' ; device 0 + db mb$in$out + db baud$none + + db 'ASCI0 ' ; device 1 + db mb$in$out+mb$serial+mb$soft$baud +ser0$baud: + db baud$19200 + + db 'ASCI1 ' ; device 2 + db mb$in$out+mb$serial+mb$soft$baud +ser1$baud: + db baud$19200 + + db 0 ; table terminator + +;-------------------------------------------------------------- + + + + + + end diff --git a/cbios/conbuf.180 b/cbios/conbuf.180 new file mode 100644 index 0000000..e8dfe31 --- /dev/null +++ b/cbios/conbuf.180 @@ -0,0 +1,171 @@ + page 255 + .z80 + +; +; FIFO channels for communication with avr +; + global ff.init,ff.in,ff.ist,ff.out,ff.ost + + extrn bufinit,fifolst + + include config.inc + if CPU_Z180 + include z180reg.inc + endif + + + cseg + + mkbuf co.fifo_id, co.fifo, co.fifo_len + mkbuf ci.fifo_id, ci.fifo, ci.fifo_len + +ico equ co.fifo_id * 3 +ici equ ci.fifo_id * 3 + + +;-------------------------------------------------------------- + +; Init Serial I/O for console input and output +; + +ff.init: + ld a,(INIDONE) + cp INIDONEVAL + ret z + + ld ix,ci.fifo + ld a,ci.fifo.mask + call bufinit + ld ix,co.fifo + ld a,co.fifo.mask + jp bufinit + +;-------------------------------------------------------------- + +ff.ist: + push ix + ld ix,(fifolst+ici) ; + +buf.empty: + ld a,(ix+o.in_idx) ; + sub (ix+o.out_idx) ; + pop ix + ret z + or 0ffh + ret + + +ff.in: + push ix + ld ix,(fifolst+ici) ; + +buf.get: + ld a,(ix+o.out_idx) ; +bg.wait: + cp (ix+o.in_idx) ; + jr z,bg.wait + + push hl ; + push ix + pop hl + add a,l + ld l,a + jr nc,bg.nc + inc h +bg.nc: + ld l,(hl) + + ld a,(ix+o.out_idx) ; + inc a + and (ix+o.mask) + ld (ix+o.out_idx),a + + ld a,l + pop hl + pop ix + ret + +;-------------------------------------------------------------- + +ff.ost: + push ix + ld ix,(fifolst+ico) ; + +buf.full: + ld a,(ix+o.in_idx) ; + inc a + and (ix+o.mask) + sub (ix+o.out_idx) ; + pop ix + ret z + or 0ffh + ret + + + if 1 +ff.out: + push ix ;15 + ld ix,(fifolst+ico) ; + +buf.put: + push hl ;11 + push bc ;11 + push ix ;15 + pop hl ;10 + ld a,c ;4 + ld c,(ix+o.in_idx) ;19 + ld b,0 ;7 + add hl,bc ;11 + ld (hl),a ;7 + ld b,a ;4 + + ld a,c ;4 + inc a ;4 + and (ix+o.mask) ;19 +bp.wait: + cp (ix+o.out_idx) ;19 + jr z,bp.wait ;12/7 + ld (ix+o.in_idx),a ;19 + + out (AVRINT6),a ;11 + ld a,b ;4 + pop bc ;10 + pop hl ;10 + pop ix ;14 + ret ;10 + + else + +ff.out: + push ix ;15 + ld ix,co.fifo ;14 + +buf.put: + push hl ;11 + push ix ;15 + pop hl ;10 + ld a,(ix+o.in_idx) ;19 + add a,l ;4 + ld l,a ;4 + jr nc,bp.1 ;12/7 + inc l ;4 + ld (hl),c ;7 + ld a,(ix+o.in_idx) ;19 + inc a ;4 + and (ix+o.mask) ;19 +bp.wait: + cp (ix+o.out_idx) ;19 + jr z,bp.wait ;12/7 + ld (ix+o.in_idx),a ;19 + + out (AVRINT6),a ;11 + ld a,c ;4 + pop hl ;10 + pop ix ;14 + ret ;10 | + + endif + +;-------------------------------------------------------------- + + end diff --git a/cbios/config.inc b/cbios/config.inc new file mode 120000 index 0000000..a046ba4 --- /dev/null +++ b/cbios/config.inc @@ -0,0 +1 @@ +../../z180-stamp/z180/config.inc \ No newline at end of file diff --git a/cbios/cpm3.lib b/cbios/cpm3.lib new file mode 100644 index 0000000..070afe7 --- /dev/null +++ b/cbios/cpm3.lib @@ -0,0 +1,180 @@ +; Macro Definitions for CP/M3 BIOS Data Structures. + + ; dtbl - drive table + + ; dph translate$table, - disk parameter header + ; disk$parameter$block, + ; checksum$size, (optional) + ; alloc$size (optional) + + ; skew sectors, - skew table + ; skew$factor, + ; first$sector$number + + ; dpb physical$sector$size, - disk parameter block + ; physical$sectors$per$track, + ; number$tracks, + ; block$size, + ; number$dir$entries, + ; track$offset, + ; checksum$vec$size (optional) + + +; Drive Table. Contains 16 one word entries. + +dtbl macro ?list + local ?n +?n set 0 + irp ?drv, +?n set ?n+1 + dw ?drv + endm + + if ?n > 16 +.' Too many drives. Max 16 allowed' + exitm + endif + + if ?n < 16 + rept (16-?n) + dw 0 + endm + endif + endm + +dph macro ?trans,?dpb,?csize,?asize + local ?csv,?alv + dw ?trans ; translate table address + db 0,0,0,0,0,0,0,0,0 ; BDOS Scratch area + db 0 ; media flag + dw ?dpb ; disk parameter block + if not nul ?csize + dw ?csv ; checksum vector + else + dw 0FFFEh ; checksum vector allocated by + endif ; GENCPM + if not nul ?asize + dw ?alv ; allocation vector + else + dw 0FFFEh ; alloc vector allocated by GENCPM + endif + dw 0fffeh,0fffeh,0fffeh ; dirbcb, dtabcb, hash alloc'd + ; by GENCPM + db 0 ; hash bank + + if not nul ?csize +?csv ds ?csize ; checksum vector + endif + if not nul ?asize +?alv ds ?asize ; allocation vector + endif + + endm + +dpb macro ?psize,?pspt,?trks,?bls,?ndirs,?off,?ncks + local ?spt,?bsh,?blm,?exm,?dsm,?drm,?al0,?al1,?cks,?psh,?psm + local ?n +;; physical sector mask and physical sector shift + ?psh set 0 + ?n set ?psize/128 + ?psm set ?n-1 + rept 8 + ?n set ?n/2 + if ?n = 0 + exitm + endif + ?psh set ?psh + 1 + endm + ?spt set ?pspt*(?psize/128) + + ?bsh set 3 + ?n set ?bls/1024 + rept 8 + ?n set ?n/2 + if ?n = 0 + exitm + endif + ?bsh set ?bsh + 1 + endm + ?blm set ?bls/128-1 + ?size set (?trks-?off)*?spt + ?dsm set ?size/(?bls/128)-1 + + ?exm set ?bls/1024 + if ?dsm > 255 + if ?bls = 1024 +.'Error, can''t have this size disk with 1k block size' + exitm + endif + ?exm set ?exm/2 + endif + ?exm set ?exm-1 + ?all set 0 + ?n set (?ndirs*32+?bls-1)/?bls + rept ?n + ?all set (?all shr 1) or 8000h + endm + ?al0 set high ?all + ?al1 set low ?all + ?drm set ?ndirs-1 + if not nul ?ncks + ?cks set ?ncks + else + ?cks set ?ndirs/4 + endif + dw ?spt ; 128 byte records per track + db ?bsh,?blm ; block shift and mask + db ?exm ; extent mask + dw ?dsm ; maximum block number + dw ?drm ; maximum directory entry number + db ?al0,?al1 ; alloc vector for directory + dw ?cks ; checksum size + dw ?off ; offset for system tracks + db ?psh,?psm ; physical sector size shift + ; and mask + endm + +; +gcd macro ?m,?n + ;; greatest common divisor of m,n + ;; produces value gcdn as result + ;; (used in sector translate table generation) + ?gcdm set ?m ;;variable for m + ?gcdn set ?n ;;variable for n + ?gcdr set 0 ;;variable for r + rept 65535 + ?gcdx set ?gcdm/?gcdn + ?gcdr set ?gcdm - ?gcdx*?gcdn + if ?gcdr = 0 + exitm + endif + ?gcdm set ?gcdn + ?gcdn set ?gcdr + endm + endm + +skew macro ?secs,?skf,?fsc +;; generate the translate table + ?nxtsec set 0 ;;next sector to fill + ?nxtbas set 0 ;;moves by one on overflow + gcd %?secs,?skf + ;; ?gcdn = gcd(?secs,skew) + ?neltst set ?secs/?gcdn + ;; neltst is number of elements to generate + ;; before we overlap previous elements + ?nelts set ?neltst ;;counter + rept ?secs ;;once for each sector + db ?nxtsec+?fsc + ?nxtsec set ?nxtsec+?skf + if ?nxtsec >= ?secs + ?nxtsec set ?nxtsec-?secs + endif + ?nelts set ?nelts-1 + if ?nelts = 0 + ?nxtbas set ?nxtbas+1 + ?nxtsec set ?nxtbas + ?nelts set ?neltst + endif + endm + endm + \ No newline at end of file diff --git a/cbios/cpm3slr.lib b/cbios/cpm3slr.lib new file mode 100644 index 0000000..2414bf4 --- /dev/null +++ b/cbios/cpm3slr.lib @@ -0,0 +1,179 @@ +; Macro Definitions for CP/M3 BIOS Data Structures. + + ; dtbl - drive table + + ; dph translate$table, - disk parameter header + ; disk$parameter$block, + ; checksum$size, (optional) + ; alloc$size (optional) + + ; skew sectors, - skew table + ; skew$factor, + ; first$sector$number + + ; dpb physical$sector$size, - disk parameter block + ; physical$sectors$per$track, + ; number$tracks, + ; block$size, + ; number$dir$entries, + ; track$offset, + ; checksum$vec$size (optional) + + +; Drive Table. Contains 16 one word entries. + +dtbl macro ?list + local ?n +?n defl 0 + irp ?drv, +?n defl ?n+1 + dw ?drv + endm + + if ?n > 16 +.' Too many drives. Max 16 allowed' + exitm + endif + + if ?n < 16 + rept (16-?n) + dw 0 + endm + endif + endm + +dph macro ?trans,?dpb,?csize,?asize + local ?csv,?alv + dw ?trans ; translate table address + db 0,0,0,0,0,0,0,0,0 ; BDOS Scratch area + db 0 ; media flag + dw ?dpb ; disk parameter block + if not nul ?csize + dw ?csv ; checksum vector + else + dw 0FFFEh ; checksum vector allocated by + endif ; GENCPM + if not nul ?asize + dw ?alv ; allocation vector + else + dw 0FFFEh ; alloc vector allocated by GENCPM + endif + dw 0fffeh,0fffeh,0fffeh ; dirbcb, dtabcb, hash alloc'd + ; by GENCPM + db 0 ; hash bank + + if not nul ?csize +?csv ds ?csize ; checksum vector + endif + if not nul ?asize +?alv ds ?asize ; allocation vector + endif + + endm + +dpb macro ?psize,?pspt,?trks,?bls,?ndirs,?off,?ncks + local ?spt,?bsh,?blm,?exm,?dsm,?drm,?al0,?al1,?cks,?psh,?psm + local ?n +;; physical sector mask and physical sector shift + ?psh defl 0 + ?n defl ?psize/128 + ?psm defl ?n-1 + rept 8 + ?n defl ?n/2 + if ?n = 0 + exitm + endif + ?psh defl ?psh + 1 + endm + ?spt defl ?pspt*(?psize/128) + + ?bsh defl 3 + ?n defl ?bls/1024 + rept 8 + ?n defl ?n/2 + if ?n = 0 + exitm + endif + ?bsh defl ?bsh + 1 + endm + ?blm defl ?bls/128-1 + ?size defl (?trks-?off)*?spt + ?dsm defl ?size/(?bls/128)-1 + + ?exm defl ?bls/1024 + if ?dsm > 255 + if ?bls = 1024 +.'Error, can''t have this size disk with 1k block size' + exitm + endif + ?exm defl ?exm/2 + endif + ?exm defl ?exm-1 + ?all defl 0 + ?n defl (?ndirs*32+?bls-1)/?bls + rept ?n + ?all defl (?all shr 1) or 8000h + endm + ?al0 defl high ?all + ?al1 defl low ?all + ?drm defl ?ndirs-1 + if not nul ?ncks + ?cks defl ?ncks + else + ?cks defl ?ndirs/4 + endif + dw ?spt ; 128 byte records per track + db ?bsh,?blm ; block shift and mask + db ?exm ; extent mask + dw ?dsm ; maximum block number + dw ?drm ; maximum directory entry number + db ?al0,?al1 ; alloc vector for directory + dw ?cks ; checksum size + dw ?off ; offset for system tracks + db ?psh,?psm ; physical sector size shift + ; and mask + endm + +; +gcd macro ?m,?n + ;; greatest common divisor of m,n + ;; produces value gcdn as result + ;; (used in sector translate table generation) + ?gcdm defl ?m ;;variable for m + ?gcdn defl ?n ;;variable for n + ?gcdr defl 0 ;;variable for r + rept 65535 + ?gcdx defl ?gcdm/?gcdn + ?gcdr defl ?gcdm - ?gcdx*?gcdn + if ?gcdr = 0 + exitm + endif + ?gcdm defl ?gcdn + ?gcdn defl ?gcdr + endm + endm + +skew macro ?secs,?skf,?fsc +;; generate the translate table + ?nxtsec defl 0 ;;next sector to fill + ?nxtbas defl 0 ;;moves by one on overflow + gcd %?secs,?skf + ;; ?gcdn = gcd(?secs,skew) + ?neltst defl ?secs/?gcdn + ;; neltst is number of elements to generate + ;; before we overlap previous elements + ?nelts defl ?neltst ;;counter + rept ?secs ;;once for each sector + db ?nxtsec+?fsc + ?nxtsec defl ?nxtsec+?skf + if ?nxtsec >= ?secs + ?nxtsec defl ?nxtsec-?secs + endif + ?nelts defl ?nelts-1 + if ?nelts = 0 + ?nxtbas defl ?nxtbas+1 + ?nxtsec defl ?nxtbas + ?nelts defl ?neltst + endif + endm + endm diff --git a/cbios/drvtbl.180 b/cbios/drvtbl.180 new file mode 100644 index 0000000..d8cf0e1 --- /dev/null +++ b/cbios/drvtbl.180 @@ -0,0 +1,11 @@ + public @dtbl + extrn sd0,sd1,sd2,sd3 + + cseg + +@dtbl dw sd0,sd1,sd2,sd3 ; drives A-D + dw 0,0,0,0 ; drives E-H non-existant + dw 0,0,0,0 ; drives I-L + dw 0,0,0,0 ; drives M-P + + end diff --git a/cbios/gencpm.dat b/cbios/gencpm.dat new file mode 100644 index 0000000..00874a9 --- /dev/null +++ b/cbios/gencpm.dat @@ -0,0 +1,158 @@ +PRTMSG = Y +PAGWID = 4F +PAGLEN = 17 +BACKSPC = N +RUBOUT = N +BOOTDRV = A +MEMTOP = EB +BNKSWT = Y +COMBAS = C0 +LERROR = Y +NUMSEGS = 03 +MEMSEG00 = 50,32,00 +MEMSEG01 = 10,B0,02 +MEMSEG02 = 00,C0,03 +MEMSEG03 = 00,C0,04 +MEMSEG04 = 00,C0,05 +MEMSEG05 = 00,C0,06 +MEMSEG06 = 00,C0,07 +MEMSEG07 = 00,C0,08 +MEMSEG08 = 00,C0,09 +MEMSEG09 = 00,C0,0A +MEMSEG0A = 00,C0,0B +MEMSEG0B = 00,C0,0C +MEMSEG0C = 00,C0,0D +MEMSEG0D = 00,C0,0E +MEMSEG0E = 00,C0,0F +MEMSEG0F = 00,C0,10 +HASHDRVA = Y +HASHDRVB = Y +HASHDRVC = Y +HASHDRVD = Y +HASHDRVE = Y +HASHDRVF = Y +HASHDRVG = Y +HASHDRVH = Y +HASHDRVI = Y +HASHDRVJ = Y +HASHDRVK = Y +HASHDRVL = Y +HASHDRVM = Y +HASHDRVN = Y +HASHDRVO = Y +HASHDRVP = Y +ALTBNKSA = Y +ALTBNKSB = Y +ALTBNKSC = Y +ALTBNKSD = Y +ALTBNKSE = N +ALTBNKSF = N +ALTBNKSG = N +ALTBNKSH = N +ALTBNKSI = N +ALTBNKSJ = N +ALTBNKSK = N +ALTBNKSL = N +ALTBNKSM = N +ALTBNKSN = N +ALTBNKSO = N +ALTBNKSP = N +NDIRRECA = 01 +NDIRRECB = 01 +NDIRRECC = 01 +NDIRRECD = 01 +NDIRRECE = 01 +NDIRRECF = 01 +NDIRRECG = 01 +NDIRRECH = 01 +NDIRRECI = 01 +NDIRRECJ = 01 +NDIRRECK = 01 +NDIRRECL = 01 +NDIRRECM = 01 +NDIRRECN = 01 +NDIRRECO = 01 +NDIRRECP = 01 +NDTARECA = 20 +NDTARECB = 20 +NDTARECC = 20 +NDTARECD = 20 +NDTARECE = 01 +NDTARECF = 01 +NDTARECG = 01 +NDTARECH = 01 +NDTARECI = 01 +NDTARECJ = 01 +NDTARECK = 01 +NDTARECL = 01 +NDTARECM = 01 +NDTARECN = 01 +NDTARECO = 01 +NDTARECP = 01 +ODIRDRVA = A +ODIRDRVB = A +ODIRDRVC = A +ODIRDRVD = A +ODIRDRVE = A +ODIRDRVF = A +ODIRDRVG = A +ODIRDRVH = A +ODIRDRVI = A +ODIRDRVJ = A +ODIRDRVK = A +ODIRDRVL = A +ODIRDRVM = A +ODIRDRVN = A +ODIRDRVO = A +ODIRDRVP = A +ODTADRVA = A +ODTADRVB = A +ODTADRVC = A +ODTADRVD = A +ODTADRVE = A +ODTADRVF = A +ODTADRVG = A +ODTADRVH = A +ODTADRVI = A +ODTADRVJ = A +ODTADRVK = A +ODTADRVL = A +ODTADRVM = A +ODTADRVN = A +ODTADRVO = A +ODTADRVP = A +OVLYDIRA = Y +OVLYDIRB = Y +OVLYDIRC = Y +OVLYDIRD = Y +OVLYDIRE = Y +OVLYDIRF = Y +OVLYDIRG = Y +OVLYDIRH = Y +OVLYDIRI = Y +OVLYDIRJ = Y +OVLYDIRK = Y +OVLYDIRL = Y +OVLYDIRM = Y +OVLYDIRN = Y +OVLYDIRO = Y +OVLYDIRP = Y +OVLYDTAA = Y +OVLYDTAB = Y +OVLYDTAC = Y +OVLYDTAD = Y +OVLYDTAE = Y +OVLYDTAF = Y +OVLYDTAG = Y +OVLYDTAH = Y +OVLYDTAI = Y +OVLYDTAJ = Y +OVLYDTAK = Y +OVLYDTAL = Y +OVLYDTAM = Y +OVLYDTAN = Y +OVLYDTAO = Y +OVLYDTAP = Y +CRDATAF = N +DBLALV = Y + \ No newline at end of file diff --git a/cbios/misc.180 b/cbios/misc.180 new file mode 100644 index 0000000..6e6e3ff --- /dev/null +++ b/cbios/misc.180 @@ -0,0 +1,256 @@ + + global add_hla + global ioiniml,ioini1l + global intinit + global bufinit + + global fifolst + + extrn ?pmsg + extrn msg.sm,hwl2phy + + include config.inc + include z180reg.inc + +;-------------------------------------------------------------- +; +; add a to hl +; +; return: +; hl = hl + a +; Flags undefined + + cseg ; (common. TODO: check for banked) + +add_hla: + add a,l + ld l,a + ret nc + inc h + ret + +;---------------------------------------------------------------------- + + ; output bytes to consecutive portaddresses + ; + ; hl: table with following structure: + ; db n, port1, val1, val2,... valn + ; db m, port1, val1, val2,... valm + ; ... + ; db 0 ; Terminate table + + + cseg ; (common for now) + +ioiniml: + push bc + xor a +ioml_lp: + ld b,(hl) + inc hl + cp b + jr z,ioml_e + + ld c,(hl) + inc hl + otimr + jr ioml_lp +ioml_e: + pop bc + ret + +;---------------------------------------------------------------------- + + ; output bytes to ports + ; + ; hl: tables of port,value pairs: + ; db n, port1,val1, port2,val2,... portn,valn + ; ... + ; db 0 ; Terminate table + + cseg ; (common for now) + +ioini1l: + push bc + jr io1_nxt +io1_lp: + ld c,(hl) ;port address + inc hl + otim + jr nz,io1_lp +io1_nxt: + ld b,(hl) ;count + inc hl + inc b + djnz io1_lp + + pop bc + ret + +;---------------------------------------------------------------------- + + dseg + +intinit: + ld hl,ivtab ; + ld a,h ; + ld i,a ; + out0 (il),l ; + im 2 + +; Let all vectors point to spurious int routines. + + ld de,sp.int0 + ld bc,sp.int.len + ld a,9 +ivt_i1: + ld (hl),e + inc l + ld (hl),d + inc l + ex de,hl + add hl,bc + ex de,hl + dec a + jr nz,ivt_i1 + ret + + +;-------------------------------------------------------------------- +; Spurious interrupt handler + + cseg ; common area +sp.int0: + ld a,00h + jr sp.i.1 +sp.int.len equ $-sp.int0 + ld a,01h + jr sp.i.1 + ld a,02h + jr sp.i.1 + ld a,03h + jr sp.i.1 + ld a,04h + jr sp.i.1 + ld a,05h + jr sp.i.1 + ld a,06h + jr sp.i.1 + ld a,07h + jr sp.i.1 + ld a,08h +sp.i.1: +; out (80h),a + + add a,'0' + ld (spi$nr),a + ld hl,spi$msg + call ?pmsg +sp.i.2: + halt + jr sp.i.2 + +spi$msg: + db 13,10,'Spurious Int: ' +spi$nr: db '0' + db 0 + + +;-------------------------------------------------------------------- + + cseg + +fifolst: + rept 4 + dw 0 + db 0 + endm + +;-------------------------------------------------------------------- + + dseg + +bufinit: + ld c,a + ld a,(ix+o.id) + cp 4 + jr nc,bfi_doit2 + + ld hl,fifolst + ld e,a + ld d,0 + add hl,de + add hl,de + add hl,de + + ld e,(hl) + inc hl + ld d,(hl) + dec hl + ld a,e + or d + jr z,bfi_doit + +; TODO: address translation + push de + pop ix + ret + +bfi_doit: + push ix + pop de +; TODO: address translation + ld (hl),e + inc hl + ld (hl),d + ld a,(ix+o.id) + or a + jr nz,bfi_doit2 + + ld hl,fifolst + ld (040h),hl + ld (040h+2),a + +bfi_doit2: + ld (ix+o.in_idx),0 ;reset pointers + ld (ix+o.out_idx),0 + ld (ix+o.mask),c ;reset "size" + + push ix ;get phys. address of fifo + pop hl + call hwl2phy + ex de,hl + ld c,a + ld a,(ix+o.id) ;fifo id + or a ;test if fifo 0 + jr nz,bfi_1 + + out (AVRINT5),a + ret + +bfi_1: + ld hl,bfi_msg_end + ld (hl),c + dec hl + ld (hl),d + dec hl + ld (hl),e + dec hl + ld (hl),a + dec hl + ld b,bfi_msg_len + call msg.sm + ret + +bfi_msg: + db 0 ;function: 0 + db 0 ;subfunc: gets overwritten with buf id + dw 0 ;physical + db 0 ; address +bfi_msg_len equ $ - bfi_msg +bfi_msg_end equ $ - 1 + +;---------------------------------------------------------------------- + + + end diff --git a/cbios/mm.180 b/cbios/mm.180 new file mode 100644 index 0000000..8f63a2b --- /dev/null +++ b/cbios/mm.180 @@ -0,0 +1,177 @@ + page 255 + .z80 + + + global mmuinit + global bnk2log,bnk2phy,hwl2phy + + include config.inc + include z180reg.inc + + +;---------------------------------------------------------------------- +; Memory Map: +; +; Common CAStart ... 0FFFF +; Bank 0 00000 ... CAStart-1 +; Bank 1 10000 ... +; Bank 2 +; +;---------------------------------------------------------------------- + + cseg + +mmuinit: + ld a,USR$CBAR + out0 (cbar),a + ret + +;-------------------------------------------------------------------- +; Return the BBR value for the given bank number +; +; in a: Bank number +; out a: bbr value + +bnk2log: + or a ; + ret z ; Bank 0 is at physical address 0 + + dec a + push bc ; + ld b,a ; + ld c,CA ; + mlt bc ; bank size * bank number + ld a,c ; + add a,10h ; add bank0 + common + pop bc ; + ret ; + +;-------------------------------------------------------------- + +;in hl: Log. Address +; a: Bank number +; +;out ahl: Phys. (linear) Address + + +bnk2phy: + call bnk2log + ; fall thru + +;-------------------------------------------------------------- +; +; hl: Log. Address +; a: Bank base (bbr) +; +; 2 0 0 +; 0 6 8 0 +; hl hhhhhhhhllllllll +; a + bbbbbbbb +; +; OP: ahl = (a<<12) + (h<<8) + l +; +;out ahl: Phys. (linear) Address + +log2phy: + push bc ; +l2p_i: + ld c,a ; + ld b,16 ; + mlt bc ; bc = a<<4 + ld a,c ; + add a,h ; + ld h,a ; + ld a,b ; + adc a,0 ; + pop bc ; + ret ; + +;-------------------------------------------------------------- +; +; de: Log. Address +; +; +; OP: ahl = (bankbase<<12) + (d<<8) + e +; +;out ahl: Phys. (linear) Address + + +hwl2phy: + push bc ; + in0 c,(cbar) ; + ld a,h ; + or 00fh ; log. addr in common1? + cp c + jr c,hlp_1 + + in0 a,(cbr) ; yes, cbr is address base + jr hl2p_x +hlp_1: + ld b,16 ; log. address in baked area? + mlt bc + ld a,h + cp c + jr c,hlp_2 + in0 a,(bbr) ; yes, bbr is address base + jr hl2p_x +hlp_2: + xor a ; common1 +hl2p_x: + jr nz,l2p_i + + pop bc ; bank part is 0, no translation + ret ; + + +;==================================================================== + + if 0 + +;-------------------------------------------------------------------- +; Return the BBR value for the given bank number + +bnk2bbr: + or a ; 4 + ret z ; 5/10 | 11 14 + + push bc ;11 | 11 + ld b,a ; 4 + ld c,CA ; 6 + mlt bc ;17 >45 + ld a,c ; 4 + add a,10h ; 6 + pop bc ; 9 | 10 + ret ; 9 | 10 76 + + push ix ;2 / 14 | 15 + ld ix,bnktbl ;4 / 12 | 14 + ld ($+3+2),a ;3 / 15 | 19 + ld a,(ix+0) ;3 / 14 | 19 + pop ix ;2 / 12 | 14 + ret ;1 / 9 | 10 15 / 76|91 + + push hl ;1 / 11 | 11 + ld hl,bnktbl ;3 / 9 | 10 + add a,l ;1 / 4 | 4 + ld l,a ;1 / 4 | 4 + ld a,0 ;1 / 6 | 7 + adc a,h ;1 / 4 | 4 + ld h,a ;1 / 4 | 4 + ld a,(hl) ;1 / 6 | 7 + pop hl ;1 / 9 | 10 + ret ;1 / 9 | 10 12 / 66|71 + + push hl ;1 / 11 | 11 + add a,low bnktbl ;2 / 6 | 7 + ld l,a ;1 / 4 | 4 + ld a,0 ;1 / 6 | 7 + adc a,high bnktbl ;2 / 6 | 7 + ld h,a ;1 / 4 | 4 + ld a,(hl) ;1 / 6 | 7 + pop hl ;1 / 9 | 10 + ret ;1 / 9 | 10 11 / 61|67 + + endif + + + end diff --git a/cbios/modebaud.inc b/cbios/modebaud.inc new file mode 100644 index 0000000..e06e0d0 --- /dev/null +++ b/cbios/modebaud.inc @@ -0,0 +1,33 @@ + ; equates for mode byte bit fields + +mb$input equ 00000001b ; device may do input +mb$output equ 00000010b ; device may do output +mb$in$out equ mb$input+mb$output + +mb$soft$baud equ 00000100b ; software selectable + ; baud rates + +mb$serial equ 00001000b ; device may use protocol +mb$xon$xoff equ 00010000b ; XON/XOFF protocol + ; enabled + +baud$none equ 0 ; no baud rate associated + ; with this device +baud$50 equ 1 ; 50 baud +baud$75 equ 2 ; 75 baud +baud$110 equ 3 ; 110 baud +baud$134 equ 4 ; 134.5 baud +baud$150 equ 5 ; 150 baud +baud$300 equ 6 ; 300 baud +baud$600 equ 7 ; 600 baud +baud$1200 equ 8 ; 1200 baud +baud$1800 equ 9 ; 1800 baud +baud$2400 equ 10 ; 2400 baud +baud$3600 equ 11 ; 3600 baud +baud$4800 equ 12 ; 4800 baud +baud$7200 equ 13 ; 7200 baud +baud$9600 equ 14 ; 9600 baud +baud$19200 equ 15 ; 19.2k baud + + + diff --git a/cbios/move.180 b/cbios/move.180 new file mode 100644 index 0000000..0ebfdfc --- /dev/null +++ b/cbios/move.180 @@ -0,0 +1,138 @@ + title 'Bank & Move Module for the Modular CP/M 3 BIOS' + +; CP/M-80 Version 3 -- Modular BIOS +; Bank and Move Module for Z180-Stamp +; Initial version 1.0 +; Compile with M80, slr180, or compatible + + public ?move,?xmove,?bank + + extrn bnk2log,bnk2phy + extrn @cbnk + + + include config.inc + include z180reg.inc + + + cseg ; must be in common memory + +?xmove: + if banked + ld (src$bnk),bc ; c -> src$bnk, b -> dst$bnk + endif + ret + +?move: + ex de,hl ; we are passed source in DE and dest in HL + if banked + ld a,(src$bnk) ; contains 0FEh if normal block move + cp 0FEh + jr nz,inter_bank_move + endif + ldir ; use Z80 block move instruction + ex de,hl ; need next address in same regs + ret + +; select bank in A + +?bank: + if banked + call bnk2log + out0 (bbr),a + endif + ret + + if banked + +inter_bank_move: ; source in HL, dest in DE, count in BC + if 0 ; *** DOES NOT WORK PROPERLY + ; (Crossing Bank boundary problems) + push bc + push de + push hl + +;TODO: check if source range crosses bank/common boundary + + ld a,(src$bnk) + call bnk2phy + + out0 (sar0l),l ; setup DMA src address + out0 (sar0h),h + out0 (sar0b),a + +;TODO: check if destination range crosses bank/common boundary + + ex de,hl + ld a,(dst$bnk) + call bnk2phy + + out0 (dar0l),l ; setup DMA dst address + out0 (dar0h),h + out0 (dar0b),a + + ld a,M_MMOD ; DMA burst mode + out0 (dmode),a + out0 (bcr0l),c ; setup DMA count + out0 (bcr0h),b + ld a,M_DE0+M_NDWE1 ; enable DMA0 + out0 (dstat),a ; move the block + + pop hl + pop de + pop bc + + add hl,bc ; src must point past end block + ex de,hl + add hl,bc ; and so must dst + ld bc,0 + + ld a,0FEh + ld (src$bnk),a + + ret ; return with src in DE, dst in HL, count = 0 + + else ; *** INNEFICIENT, BUT WORKS + + ld (tmp$sp),sp + ld sp,tmp$stk + ex af,af' ; + push af +mv$blk: + ld a,(src$bnk) ; + call ?bank + ld a,(hl) + ex af,af' ; + ld a,(dst$bnk) + call ?bank + ex af,af' ; + ld (de),a + inc hl + inc de + dec bc + ld a,b + or c + jr nz,mv$blk + ld a,(@cbnk) + call ?bank + ld a,0FEh + ld (src$bnk),a + ex de,hl + pop af + ex af,af' ; + ld sp,(tmp$sp) + ret + + ds 16 +tmp$stk: +tmp$sp: ds 2 + + endif + +src$bnk: db 0FEh +dst$bnk: db 0FEh + + + endif ;banked + + end diff --git a/cbios/msgbuf.180 b/cbios/msgbuf.180 new file mode 100644 index 0000000..92544eb --- /dev/null +++ b/cbios/msgbuf.180 @@ -0,0 +1,484 @@ + page 255 + .z80 + + + global msginit +; global msg.ist,msg.in,msg.ost,msg.out +; global msg.sout + global msg.sm,msg.recv + + extrn bufinit + extrn fifolst + + include config.inc + include z180reg.inc + + + cseg + + + mkbuf 0,mtx.fifo,mtx.fifo_len + mkbuf 1,mrx.fifo,mrx.fifo_len + +;txfifo_addr equ fifolst + (0*3) +;rxfifo_addr equ fifolst + (1*3) + +itx equ 0*3 +irx equ 1*3 + +;-------------------------------------------------------------- +; +; Init mssage fifos +; + dseg + +msginit: + ld a,(INIDONE) + cp INIDONEVAL + jr nz,msgi_1 + + ld hl,(040h) + ld a,l + or h + jr z,msgi_1 + + ld de,fifolst + ld bc,4*3 + ldir + ret + +msgi_1: + ld ix,mtx.fifo + ld a,mtx.fifo.mask + call bufinit + ld ix,mrx.fifo + ld a,mrx.fifo.mask + jp bufinit + + +;-------------------------------------------------------------- + + cseg + +msgi.st: + push ix + ld ix,(fifolst+irx) ; + +buf.empty: + ld a,(ix+o.in_idx) ; + sub (ix+o.out_idx) ; + pop ix + ret z + or 0ffh + ret + +;-------------------------------------------------------------- + +msg.in: + push ix + ld ix,(fifolst+irx) ; + +buf.get: + ld a,(ix+o.out_idx) ; +bg.wait: + cp (ix+o.in_idx) ; + jr z,bg.wait + + push hl ; + push ix + pop hl + add a,l + ld l,a + jr nc,bg.nc + inc h +bg.nc: + ld l,(hl) + + ld a,(ix+o.out_idx) ; + inc a + and (ix+o.mask) + ld (ix+o.out_idx),a + + ld a,l + pop hl + pop ix + ret + + +;---------------------------------------------------------------------- +; Receive message +; +; hl: pointer to receive buffer +; b: receive buffer size +; return: +; data in buffer, buffer[0] has len +; bc, a: destroyed + +; TODO: time out +; TODO: return number of stored chars +; TODO: result code + +msg.recv: + push de + +mr_wait_start: + call msg.in + cp 0AEh + jr nz,mr_wait_start + + call msg.in ; get message length + ld c,a + inc c + jr mr_do + +mr_next: + dec c + jr z,mr_exit ; while chars in input buffer + call msg.in ; get next +mr_do: + ld e,a + ld a,b + or a ; if room in output buffer + jr z,mr_skip + ld (hl),e ; store char + inc hl + dec b +mr_skip: + jr mr_next ; + +mr_exit: + pop de + ret + +;-------------------------------------------------------------- + +msgo.st: + push ix + ld ix,(fifolst+itx) ; + +buf.full: + ld a,(ix+o.in_idx) ; + inc a + and (ix+o.mask) + sub (ix+o.out_idx) ; + pop ix + ret z + or 0ffh + ret + +;-------------------------------------------------------------- + + if 0 + +msg.out: + push ix + ld ix,(fifolst+itx) ; + + push hl ; + push bc + push ix + pop hl + ld c,(ix+o.in_idx) ; + ld b,0 + add hl,bc + ld b,a + + ld a,c ; + inc a + and (ix+o.mask) +bp.wait: + cp (ix+o.out_idx) ; + jr z,bp.wait + ld (hl),b + ld (ix+o.in_idx),a + + ld a,b + out (AVRINT5),a + pop bc + pop hl + pop ix + ret + + endif + +;-------------------------------------------------------------- + + if 0 + +msg.out: + push ix + ld ix,(fifolst+itx) ; + + push bc + ld c,(ix+o.in_idx) ; + ld b,0 + push ix ;14 + add ix,bc ;10 + ld (ix+0),a ;15 + pop ix ;12=51 + ld b,a ; 4 + ld a,c ; + inc a ; + and (ix+o.mask) ; +bp.wait: + cp (ix+o.out_idx) ; + jr z,bp.wait ; + ld (ix+o.in_idx),a ; + + ld a,b + out (AVRINT5),a + pop bc + pop ix + ret + + endif +;-------------------------------------------------------------- + + if 0 + ; Works only, if buffer size < (128 - 3) + ; --> mask must be 03fh or less + +msg.out: + push ix + ld ix,(fifolst+itx) ; + + push bc + ld b,a ; 4 + ld a,(ix+o.in_idx) ;14 + ld ($ + 3 + 2),a ;15 + ld (ix+0),b ;15 + inc a ; + and (ix+o.mask) ; +bp.wait: + cp (ix+o.out_idx) ; + jr z,bp.wait ; + ld (ix+o.in_idx),a ; + + ld a,b + out (AVRINT5),a + pop bc + pop ix + ret + + endif + +;-------------------------------------------------------------- +; +; (hl): data + + if 0 + +msg.sout: + push ix ;14 + ld ix,(fifolst+itx) ;12 + push bc ;11 + push de ;11 + ld c,(hl) ; 6 + ld b,0 ; 6 + inc hl ; 7 +ms.ol: ; \ +TODO: ld a,low mtx.fifo ; 6 does not work with DR LINK-80 +--> (fifolst+itx+0) + add a,(ix+o.in_idx) ;14 + ld e,a ; 4 + ld a,high mtx.fifo ; 6 does not work with DR LINK-80 +--> (fifolst+itx+1) + adc a,b ; 4 + ld d,a ; 4 + + ld a,(ix+o.in_idx) ;14 + inc a ; 4 + and (ix+o.mask) ;14 +ms.wait: + cp (ix+o.out_idx) ;14 + jr z,ms.wait ; 6/8 + + ldi ;12 + ld (ix+o.in_idx),a ;15 + jp pe,ms.ol ; 6/9 -- 126 + + out (AVRINT5),a ;10 + pop de ; 9 + pop bc ; 9 + pop ix ;12 + ret ; 9 + + endif + +;-------------------------------------------------------------- +; +; (hl): data + + if 1 + +msg.sout: + push ix ;14 + ld ix,(fifolst+itx) ;12 + push bc ;11 + push de ;11 + ld b,(hl) ; 6 + inc hl ; 4 + ex de,hl ; 3 +ms.ol: ; \ + push ix ;14 + pop hl ; 9 + ld c,(ix+o.in_idx) ;14 + ld a,c ; 4 + add l ; 4 + ld l,a ; 4 + jr nc,ms.on ; 6/8 + inc h ; 4 +ms.on: + ld a,c ; 4 + inc a ; 4 + and (ix+o.mask) ;14 +ms.wait: + cp (ix+o.out_idx) ;14 + jr z,ms.wait ; 6/8 + ld c,a ; 4 + ld a,(de) ; 6 + inc de ; 4 + ld (hl),a ; 7 + ld (ix+o.in_idx),c ;15 + djnz ms.ol ; 7/9 -- 130 + + out (AVRINT5),a ;10 + ex de,hl ; 3 + pop de ; 9 + pop bc ; 9 + pop ix ;12 + ret ; 9 + + endif + +;---------------------------------------------------------------------- + + + + ; Send message + ; b: msg length + ; hl: pointer to message (netto) + +msg.snd: + push ix + ld ix,(fifolst+itx) + ld c,0AEh + call buf.put +msnd_l: + ld c,(hl) + inc hl + call buf.put + djnz msnd_l + pop ix + ret + + +;---------------------------------------------------------------------- +; +; Put char in message buffer: +; ix: buffer to put into +; c: char + +buf.put: + push ix ;15 + push bc ;11 + ld a,(ix+o.in_idx) ;19 + ld c,a ;4 + ld b,0 ;7 + add ix,bc ;11 + pop bc ;10 + ld (ix),c ;7 + pop ix ;14 + + inc a ;4 + and (ix+o.mask) ;19 =121 +bufp.wait: + cp (ix+o.out_idx) ;19 + jr z,bufp.wait ;12/7 + ld (ix+o.in_idx),a ;19 + + out (AVRINT5),a ;11 + ld a,c ;4 + ret ;10 =191 + + +;---------------------------------------------------------------------- +; Send message MEMORY +; +; hl: pointer to message (netto) +; b: msg length + +msg.sm: + push ix + ld ix,(fifolst+itx) + ld c,0AEh + call buf.put + ld c,b + call buf.put +msm_l: + ld c,(hl) + inc hl + call buf.put + djnz msm_l + pop ix + ret + + +;---------------------------------------------------------------------- +; Send message INLINE +; +; h: function +; l: subfunction +; b: msg length + + if 0 + +msg.sil: + ex (sp),hl + push ix + ld ix,(fifolst+itx) + ld c,0AEh + call buf.put + ld b,(hl) +msnd_pl: + ld c,(hl) + inc hl + call puf.put + djnz msnd_pl + ex (sp),hl + pop ix + ret + + endif + +;-------------------------------------------------------------- + + if 0 + +msg.co: + push af + push hl + ld (buf_char),a + ld hl,buf + call msg.sout + pop hl + pop af + ret + +buf: + db buf_end - $ - 1 ;output string length + db 0AEh ; message start token + db buf_end - $ - 1 ; message length + db 1 ; command + db 1 ; subcommand +buf_char: + db 0 ; pay load +buf_end: + + endif + +;-------------------------------------------------------------- + + + + end diff --git a/cbios/scb.180 b/cbios/scb.180 new file mode 100644 index 0000000..410f796 --- /dev/null +++ b/cbios/scb.180 @@ -0,0 +1,48 @@ + title 'System Control Block Definition for CP/M3 BIOS' + + public @civec, @covec, @aivec, @aovec, @lovec, @bnkbf + public @crdma, @crdsk, @vinfo, @resel, @fx, @usrcd + public @mltio, @ermde, @erdsk, @media, @bflgs + public @date, @hour, @min, @sec, ?erjmp, @mxtpa + + +scb$base equ 0FE00H ; Base of the SCB + +@civec equ scb$base+22h ; Console Input Redirection + ; Vector (word, r/w) +@covec equ scb$base+24h ; Console Output Redirection + ; Vector (word, r/w) +@aivec equ scb$base+26h ; Auxiliary Input Redirection + ; Vector (word, r/w) +@aovec equ scb$base+28h ; Auxiliary Output Redirection + ; Vector (word, r/w) +@lovec equ scb$base+2Ah ; List Output Redirection + ; Vector (word, r/w) +@bnkbf equ scb$base+35h ; Address of 128 Byte Buffer + ; for Banked BIOS (word, r/o) +@crdma equ scb$base+3Ch ; Current DMA Address + ; (word, r/o) +@crdsk equ scb$base+3Eh ; Current Disk (byte, r/o) +@vinfo equ scb$base+3Fh ; BDOS Variable "INFO" + ; (word, r/o) +@resel equ scb$base+41h ; FCB Flag (byte, r/o) +@fx equ scb$base+43h ; BDOS Function for Error + ; Messages (byte, r/o) +@usrcd equ scb$base+44h ; Current User Code (byte, r/o) +@mltio equ scb$base+4Ah ; Current Multi-Sector Count + ; (byte,r/w) +@ermde equ scb$base+4Bh ; BDOS Error Mode (byte, r/o) +@erdsk equ scb$base+51h ; BDOS Error Disk (byte,r/o) +@media equ scb$base+54h ; Set by BIOS to indicate + ; open door (byte,r/w) +@bflgs equ scb$base+57h ; BDOS Message Size Flag (byte,r/o) +@date equ scb$base+58h ; Date in Days Since 1 Jan 78 + ; (word, r/w) +@hour equ scb$base+5Ah ; Hour in BCD (byte, r/w) +@min equ scb$base+5Bh ; Minute in BCD (byte, r/w) +@sec equ scb$base+5Ch ; Second in BCD (byte, r/w) +?erjmp equ scb$base+5Fh ; BDOS Error Message Jump + ; (word, r/w) +@mxtpa equ scb$base+62h ; Top of User TPA + ; (address at 6,7)(word, r/o) + end diff --git a/cbios/sdio.180 b/cbios/sdio.180 new file mode 100644 index 0000000..2b84aea --- /dev/null +++ b/cbios/sdio.180 @@ -0,0 +1,384 @@ + TITLE 'sd disk handler' + +; CP/M-80 Version 3 -- Modular BIOS + + + dseg + + ; Disk drive dispatching tables for linked BIOS + + public sd0,sd1,sd2,sd3 + + ; Variables containing parameters passed by BDOS + + extrn @adrv,@rdrv + extrn @dma,@trk,@sect + extrn @dbnk + + ; System Control Block variables + + extrn @ermde ; BDOS error mode + + ; Utility routines in standard BIOS + + extrn ?wboot ; warm boot vector + extrn ?pmsg ; print message @ up to 00, saves & + extrn ?pdec ; print binary number in from 0 to 99. + extrn ?pderr ; print BIOS disk error header + extrn ?conin,?cono ; con in and out + extrn ?const ; get console status + + extrn bnk2phy ; + extrn msg.sm ; + extrn msg.recv ; + extrn add_hla + + + ; Port Address Equates + + include config.inc + include z180reg.inc + + ; CP/M 3 Disk definition macros + + include cpm3slr.lib + + ; Z180 macro library instruction definitions (ignored by slr180) + + include z180.lib + + ; common control characters + +cr equ 13 +lf equ 10 +bell equ 7 + + + ; Extended Disk Parameter Headers (XPDHs) + + dw sd$write + dw sd$read + dw sd$login + dw sd$init0 + db 0,0 ; relative drive zero +sd0: dph 0,dpbsimhd512 + + dw sd$write + dw sd$read + dw sd$login + dw sd$init1 + db 1,0 ; relative drive one +sd1: dph 0,dpbsimhd512 + + dw sd$write + dw sd$read + dw sd$login + dw sd$init0 + db 2,0 ; relative drive zero +sd2: dph 0,dpbsimhd512 + + dw sd$write + dw sd$read + dw sd$login + dw sd$init1 + db 3,0 ; relative drive one +sd3: dph 0,dpbsimhd512 + + + cseg ; DPB must be resident + +dpbsimhd512: + dpb 512,8,2048,4096,1024,6 + + + dseg ; rest is banked + +; Disk I/O routines for standardized BIOS interface + +; Initialization entry point. +; called for first time initialization. + +sd$init0: + ret + +sd$init1: +sd$init2: +sd$init3: + ret ; all initialization done by drive 0 + + + + +; This entry is called when a logical drive is about to +; be logged into for the purpose of density determination. +; It may adjust the parameters contained in the disk +; parameter header pointed at by + +sd$login: + ld hl,send_msg+1 + ld (hl),0 ;login function + inc hl + ld bc,(@adrv) + ld (hl),c ;@adrv + inc hl + ld (hl),b ;@rdrv + inc hl + + ex de,hl ;xdph to hl + xor a ;bank 0 + call bnk2phy ;phys. linear address + ex de,hl + ld (hl),e + inc hl + ld (hl),d + inc hl + ld (hl),a + + ld hl,send_msg + ld b,send_msg_login_len + call msg.sm + + ld hl,recv_msg + ld b,recv_msg_len ; max receive message len + call msg.recv + +; ld a,(recv_msg_rc) +; or a + ret ; + + + +; disk READ and WRITE entry points. +; these entries are called with the following arguments: +; +; absolute drive number in @adrv (8 bits) +0 +; relative drive number in @rdrv (8 bits) +1 +; multi sector count in @cnt (8 bits) +2 (currently unused) +; disk track address in @trk (16 bits) +3 +; disk sector address in @sect(16 bits) +5 +; disk transfer address in @dma (16 bits) +7 +; disk transfer bank in @dbnk (8 bits) +9 +; pointer to XDPH in +; +; they transfer the appropriate data, perform retries +; if necessary, then return an error code in + +sd$read: + ld hl,read$msg ; point at " Read " + ld a,1 + jr rw$common + +sd$write: + ld hl,write$msg ; point at " Write " + ld a,2 + ;fall thru + +; compute pysical transfer address +; prepare message +; and send it to AVR. + +rw$common: + ld (operation$name),HL ; save message for errors + ld de,send_msg+1 + ld (de),a + inc de + ld hl,@adrv ;address of arguments + ld bc,7 + ldir + push de + ld e,(hl) ;dma address + inc hl + ld d,(hl) + inc hl + ld a,(hl) ;bank + ex de,hl + call bnk2phy ;phys. linear address + ex de,hl + pop hl + ld (hl),e + inc hl + ld (hl),d + inc hl + ld (hl),a + +more$retries: + + ld hl,send_msg + ld b,send_msg_rw_len + call msg.sm + + ld hl,recv_msg + ld b,recv_msg_len ; max receive message len + call msg.recv + ld a,(recv_msg_rc) + or a + ret z ; check status and return to BDOS if no error + +; suppress error message if BDOS is returning errors to application... + + ld a,(@ermde) + cp 0ffh + jr z,hard$error + + ; Had permanent error, print message like: + ; BIOS Err on d: T-nn, S-mm, , Retry ? + + call ?pderr ; print message header + + ld hl,(operation$name) + call ?pmsg ; last function (read or write) + + ld a,(recv_msg_rc) + +;TODO: rc errorcode + + ld a,(recv_msg_rc) + tst 080h + jr z,fs_end + +fatfs_err: + + ld a,(recv_msg_rc+1) + cp 20 + jr c,fs_err1 + xor a +fs_err1 + ld hl,fr$msg0 ; point at first message + ld bc,fr$msg$size + ld e,a ; save message number + xor a + inc e +nxt_str: + dec e + jr z,fs_err_found + cpir + jr z,nxt_str + ld hl,fr$msg0 ; not found, point at first message + +fs_err_found: + call ?pmsg + +fs_end: + ld hl,error$msg + call ?pmsg ; print ", Retry (Y/N) ? " + call u$conin$echo ; get operator response + cp 'y' + jr z,more$retries ; Yes, then retry 10 more times +hard$error: + ; otherwise, + ld a,1 + ret ; return hard error to BDOS + +cancel: ; here to abort job + jp ?wboot ; leap directly to warmstart vector + + + +u$conin$echo: + ; get console input, echo it, and shift to upper case + call ?const + or a + jp z,u$c1 ; see if any char already struck + call ?conin + jp u$conin$echo ; yes, eat it and try again +u$c1: + call ?conin + push af + ld c,a + call ?cono + pop af + cp 'a' + ret c + sub 'a'-'a' ; make upper case + ret + + + +send_msg: + db 2 ; disk command + ds 1 ; subcommand (login/read/write) + ds 1 ; @adrv + ds 1 ; @rdrv + ; -read/write- -login- + ds 1 ; @cnt 3 byte + ds 2 ; @trk xdph address +send_msg_login_len equ $ - send_msg + ds 2 ; @sect + ds 3 ; transfer addr +send_msg_rw_len equ $ - send_msg + + +recv_msg: + ds 1 ; len + ds 1 ; command + ds 1 ; subcommand +recv_msg_rc: + ds 1 ; result code + ds 4 ; room for additional parameter +recv_msg_len equ $ - recv_msg + + + ; error message components + +operation$name: + dw read$msg +read$msg: + db ', Read',0 +write$msg: + db ', Write',0 + + + ; table of pointers to error message strings + +fr$msg0: db ' Unknown FatFs Error,',0 +fr$msg1: db ' DISK_ERR,',0 +fr$msg2: db ' INT_ERR,',0 +fr$msg3: db ' NOT_READY,',0 +fr$msg4: db ' NO_FILE,',0 +fr$msg5: db ' NO_PATH,',0 +fr$msg6: db ' INVALID_NAME,',0 +fr$msg7: db ' DENIED,',0 +fr$msg8: db ' EXIST,',0 +fr$msg9: db ' INVALID_OBJECT,',0 +fr$msg10: db ' WRITE_PROTECTED,',0 +fr$msg11: db ' INVALID_DRIVE,',0 +fr$msg12: db ' NOT_ENABLED,',0 +fr$msg13: db ' NO_FILE_SYSTEM,',0 +fr$msg14: db ' MKFS_ABORTED,',0 +fr$msg15: db ' TIMEOUT,',0 +fr$msg16: db ' LOCKED,',0 +fr$msg17: db ' NOT_ENOUGH_CORE,',0 +fr$msg18: db ' TOO_MANY_OPEN_FILES,',0 +fr$msg19: db ' FR_INVALID_PARAMETER,',0 +fr$msg$size equ $ - fr$msg0 + + +error$msg: + db ' Retry (Y/N) ? ',0 + + + end + +/* File function return code (FRESULT) */ + +FR_OK = 0, /* (0) Succeeded */ +FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ +FR_INT_ERR, /* (2) Assertion failed */ +FR_NOT_READY, /* (3) The physical drive cannot work */ +FR_NO_FILE, /* (4) Could not find the file */ +FR_NO_PATH, /* (5) Could not find the path */ +FR_INVALID_NAME, /* (6) The path name format is invalid */ +FR_DENIED, /* (7) Access denied due to prohibited access or directory full */ +FR_EXIST, /* (8) Access denied due to prohibited access */ +FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ +FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ +FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ +FR_NOT_ENABLED, /* (12) The volume has no work area */ +FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ +FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */ +FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ +FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ +FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ +FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */ +FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ + diff --git a/cbios/time.180 b/cbios/time.180 new file mode 100644 index 0000000..1223bb1 --- /dev/null +++ b/cbios/time.180 @@ -0,0 +1,22 @@ + title 'Time module for the Modular CP/M 3 BIOS' + + public ?time + + extrn ?bank + + extrn @date,@hour,@min,@sec + extrn @cbnk + extrn @bios$stack + + include config.inc + include z180reg.inc + + + + + cseg ; time must be done from resident memory + +?time: + ret ; no time (yet) + + end diff --git a/cbios/z180.lib b/cbios/z180.lib new file mode 100644 index 0000000..ffe0ab7 --- /dev/null +++ b/cbios/z180.lib @@ -0,0 +1,120 @@ + .xlist +;; +;; Z180 / HD64180 MACRO LIBRARY +;; + +IFNDEF SLP + +;; +;; +;; HD64180 instructions: +;; +;; SLP ; Enter SLEEP mode +;; MLT RR ; 8 bit multiply with 16 bit result +;; IN0 R,P ; Input from internal port +;; OUT0 P,R ; Output to internal port +;; OTIM ; Block output, increment +;; OTIMR ; Block output, increment and repeat +;; OTDM ; Block output, decrement +;; OTDMR ; Block output, decrement and repeat +;; TSTIO P ; Non destructive AND, I/O port and A +;; TST R ; Non destructive AND, reg and A +;; TST ID ; Non destructive AND, immediate data and A +;; TST (HL) ; Non destructive AND, (HL) and A +;; +;; + +??BC EQU 0 ; Double-register definitions +??DE EQU 1 +??HL EQU 2 +??SP EQU 3 + +??A EQU 7 ; Single-register defintions +??B EQU 0 +??C EQU 1 +??D EQU 2 +??E EQU 3 +??H EQU 4 +??L EQU 5 + +SLP MACRO + DEFB 0EDH,76H + ENDM + +MLT MACRO ?R + DB 0EDH,4CH+(??&?R AND 3) SHL 4 + ENDM + +IN0 MACRO ?R,?P + DB 0EDH,(??&?R AND 7) SHL 3, ?P + ENDM + +OUT0 MACRO ?P,?R + DB 0EDH,1+(??&?R AND 7) SHL 3,?P + ENDM + +OTIM MACRO + DB 0EDH,83H + ENDM + +OTIMR MACRO + DB 0EDH,93H + ENDM + +OTDM MACRO + DB 0EDH,8BH + ENDM + +OTDMR MACRO + DB 0EDH,9BH + ENDM + +TSTIO MACRO ?P + DB 0EDH,74H,?P + ENDM + +TSTR MACRO ?R + DB 0EDH,4+(??&?R AND 7) SHL 3 + ENDM + +TSTD MACRO ?P + DB 0EDH,64H,?P + ENDM + +TSTP MACRO + DB 0EDH,34H + ENDM + +TST MACRO ?R + ?D: SET 0 + IRPC ?X,?R + ?D: SET ?D+1 ; Count # chars in "?R" + ENDM + IF ?D EQ 1 ; IF # chars = 1 + IRPC ?X,ABCDEHL ; Look up the character + IF ??&?X EQ ??&?R + DB 0EDH,4+(??&?R AND 7) SHL 3 + EXITM + ENDIF + ENDM + DB 0EDh,64h,?R + EXITM + ENDIF + IF (?R = 2) & (?D = 4) + ?D: SET 0 + IRPC ?X,?R + IFIDN ,<(> + DB 0EDh,34h + EXITM + ENDIF + ?D: SET ?D + 1 + ENDM + ENDIF + IF ?D NE 0 + DB 0EDH,64H,?R + ENDIF + ENDM + +ENDIF ;/* IFNDEF SLP / + .list + diff --git a/cbios/z180reg.inc b/cbios/z180reg.inc new file mode 120000 index 0000000..01c2a6b --- /dev/null +++ b/cbios/z180reg.inc @@ -0,0 +1 @@ +../../z180-stamp/z180/z180reg.inc \ No newline at end of file -- 2.39.2