From 30d1329e8e5c029a87f657baace698d1d7031f9e Mon Sep 17 00:00:00 2001 From: Leo C Date: Tue, 28 Oct 2014 10:29:13 +0100 Subject: [PATCH] CP/M 3 compatible character i/o handling --- z180/Tupfile | 2 +- z180/bioscio.180 | 325 ++++++++++++++++++++++++++++++++++++++++++++++ z180/chario.180 | 103 +++++++++++++++ z180/conbuf-a.180 | 3 +- z180/console.180 | 10 +- z180/ddtz.180 | 120 +++++++++++------ z180/modebaud.inc | 31 +++++ z180/r3init.180 | 39 ++++-- z180/ser1-i.180 | 9 +- 9 files changed, 575 insertions(+), 67 deletions(-) create mode 100644 z180/bioscio.180 create mode 100644 z180/chario.180 create mode 100644 z180/modebaud.inc diff --git a/z180/Tupfile b/z180/Tupfile index 8b50b8a..bb88946 100644 --- a/z180/Tupfile +++ b/z180/Tupfile @@ -5,7 +5,7 @@ PROG = hdrom SRC = r3init.180 SRC += ddtz.180 #SRC += fifoio.180 msgbuf.180 ser1-i.180 console.180 -SRC += msgbuf-a.180 conbuf-a.180 ser1-i.180 console.180 +SRC += msgbuf-a.180 conbuf-a.180 ser1-i.180 bioscio.180 chario.180 # serial (asci1) console only: #SRC += ser1-i.180 console.180 SRC += romend.180 diff --git a/z180/bioscio.180 b/z180/bioscio.180 new file mode 100644 index 0000000..a3a179f --- /dev/null +++ b/z180/bioscio.180 @@ -0,0 +1,325 @@ + + .z80 + +; 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. +; +; Modified for faster character I/O by Udo Munk + +cr equ 13 +lf equ 10 +bell equ 7 +ctlQ equ 'Q'-'@' +ctlS equ 'S'-'@' + + cseg ; GENCPM puts CSEG stuff in common memory + + ; variables in system data page + +;; extrn @covec,@civec,@aovec,@aivec,@lovec ; I/O redirection vectors + + ; 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 + + + include modebaud.inc ; define mode bits + + + public @covec,@civec,@aovec,@aivec,@lovec ; I/O redirection vectors + public ?const,?conin,?cono,?list,?auxo,?auxi + public ?lists,?conos,?auxis,?auxos,?dvtbl,charini + + +@CIVEC: dw 0 ; Console Input Redirection + ; Vector (word, r/w) +@COVEC: dw 0 ; Console Output Redirection + ; Vector (word, r/w) +@AIVEC: dw 0 ; Auxiliary Input Redirection + ; Vector (word, r/w) +@AOVEC: dw 0 ; Auxiliary Output Redirection + ; Vector (word, r/w) +@LOVEC: dw 0 ; List Output Redirection + ; Vector (word, r/w) + + +charini: + + ld c,15 ; initialize all 16 character devices +c$init$loop: + push bc + call ?cinit + pop bc + dec c + jp p,c$init$loop + + ld hl,1100000000000000b ; assign console to HOST and ASCI1 + ld (@civec),hl + ld (@covec),hl + ld hl,0000000000000000b ; assign auxiliary to nothing + ld (@aivec),hl + ld (@aovec),hl + ld hl,0000000000000000b ; assign printer to nothing + ld (@lovec),hl + ret + + + ; DEVTBL + ; Return address of character device table + +?dvtbl: +devtbl: + ld hl,@ctbl + ret + + + ; CONOUT + ; Console Output. Send character in + ; to all selected devices + +?cono: +conout: + ld hl,(@covec) ; fetch console output bit vector + jr out$scan + + + ; AUXOUT + ; Auxiliary Output. Send character in + ; to all selected devices + +?auxo: +auxout: + ld hl,(@aovec) ; fetch aux output bit vector + jr out$scan + + + ; LIST + ; List Output. Send character in + ; to all selected devices. + +?list: +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 + 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. + +?conos: +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. + +?auxos: +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. + +?lists: +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 + ; + ;TODO: interrupt driven devices should xon/xoff handle + ; in isv + + 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 + + + ; AUXIST + ; Auxiliary Input Status. Return true if + ; any selected auxiliary input device + ; has an available character. +?auxis: +auxist: + ld hl,(@aivec) ; get aux input bit vector + jr ist$scan + + + ; CONST + ; Console Input Status. Return true if + ; any selected console input device + ; has an available character. +?const: +const: + ld hl,(@civec) ; get console 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 + + + ; AUXIN + ; Auxiliary Input. Return character from first + ; ready auxiliary input device. +?auxi: +auxin: + ld hl,(@aivec) + jr in$scan + + + ; CONIN + ; Console Input. Return character from first + ; ready console input device. +?conin: +conin: + ld hl,(@civec) + +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 + + + +xofflist: + db -1,-1,-1,-1,-1,-1,-1,-1 ; ctl-s clears to zero + db -1,-1,-1,-1,-1,-1,-1,-1 + + + end + diff --git a/z180/chario.180 b/z180/chario.180 new file mode 100644 index 0000000..6632690 --- /dev/null +++ b/z180/chario.180 @@ -0,0 +1,103 @@ + page 255 + .z80 + + +; CP/M 3 compatible character i/o + + public ?cinit,?ci,?co,?cist,?cost + public @ctbl + + extrn ff.init,ff.i.st,ff.in,ff.o.st,ff.out + extrn ser.init,ser.ist,ser.in,ser.ost,ser.out + + include config.inc + include z180reg.inc + include modebaud.inc ; define mode bits and baud eqautes + + +max$device equ 2 + + cseg + +; c = device + +?cinit: ; init devices + ld b,c + call vector$io + dw ff.init + dw ser.init + dw rret + +; b = device, c = output char, a = input char + +?ci: ; character input + call vector$io + dw ff.in + dw ser.in + dw null$input + +?cist: ; character input status + call vector$io + dw ff.i.st + dw ser.ist + dw null$status + +?co: ; character output + call vector$io + dw ff.out + dw ser.out + dw rret + +?cost: ; character output status + call vector$io + dw ff.o.st + dw ser.ost + dw ret$true + +vector$io: + ld a,max$device + ld e,b +vector: + pop hl + ld d,0 + cp e + jr nc,exist + ld e,a ; use null device if a >= max$device +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 'HOST ' ; device 0 + db mb$output + db baud$none + + db 'ASCI1 ' ; device 0 + db mb$in$out+mb$serial+mb$soft$baud +ser1$baud: + db baud$19200 + + db 0 ; table terminator + + end + diff --git a/z180/conbuf-a.180 b/z180/conbuf-a.180 index 3ec84d4..8534f73 100644 --- a/z180/conbuf-a.180 +++ b/z180/conbuf-a.180 @@ -4,7 +4,7 @@ ; ; FIFO channels for communication with avr ; - global ff.init,ff.in,ff.out,ff.i.st + global ff.init,ff.in,ff.out,ff.i.st,ff.o.st extrn buf.init @@ -105,6 +105,7 @@ buf.put: push bc push ix pop hl + ld a,c ld c,(ix+o.in_idx) ; ld b,0 add hl,bc diff --git a/z180/console.180 b/z180/console.180 index 07fb570..d4f4130 100644 --- a/z180/console.180 +++ b/z180/console.180 @@ -7,9 +7,9 @@ global $co - extrn ser.init,ser.instat,ser.in,ser.out - extrn ff.init,ff.i.st,ff.in,ff.out - extrn ff.out + extrn ser.init,ser.ist,ser.in,ser.ost,ser.out + extrn ff.init,ff.i.st,ff.in + extrn ff.o.st,ff.out include config.inc @@ -27,13 +27,13 @@ $coninit: $cists: call ff.i.st ret nz - call ser.instat + call ser.ist ret $ci: call ff.i.st jp nz,ff.in - call ser.instat + call ser.ist jp nz,ser.in jr $ci diff --git a/z180/ddtz.180 b/z180/ddtz.180 index 77da910..e544b08 100644 --- a/z180/ddtz.180 +++ b/z180/ddtz.180 @@ -1,7 +1,7 @@ page 255 .z80 - external $ci, $co, $cists + extrn ?const,?conin,?cono global ddtz,bpent global $stack @@ -27,7 +27,7 @@ BP_CNT equ 12 ;number of breakbpoints ;-------------------------------------------------- -; +; ; copy code to common memory and execute it there comst macro @@ -103,17 +103,17 @@ ddtz: ld hl,sysramc ld de,topcodbeg ld bc,topcodend-topcodbeg - ldir - + ldir + ld hl,vartab ld de,ddtram ld bc,vartabe-vartab - ldir + ldir exx ld a,e ld (ubbr),a - + ddtz_w: ld hl,MSG ;073c call PSTR ;073f @@ -203,29 +203,53 @@ CMD.?: call PSTR ret +$ci: + push hl + push de + push bc + call ?conin + pop bc + pop de + pop hl + ret + +$co: + push hl + push de + push bc + ld c,a + call ?cono + pop bc + pop de + pop hl + ret + DELC: - ld a,b ;07f2 - or a ;07f3 - ret z ;07f4 - ld a,BS ;07f5 - call $co ;07f7 - ld a,' ' ;07fa - call $co ;07fc - ld a,BS ;07ff - call $co ;0801 - dec hl ;0804 - dec b ;0805 - inc c ;0806 - ld a,(hl) ;0807 - cp ' ' ;0808 - ret nc ;080a - ld a,BS ;080b - call $co ;080d - ld a,' ' ;0810 - call $co ;0812 - ld a,BS ;0815 - call $co ;0817 - ret ;081a + ld a,b + or a + ret z + call DELC1 + dec hl + dec b + inc c + ld a,(hl) + cp ' ' + ret nc +DELC1: + push de + push hl + push bc + ld c,BS + call ?cono + ld c,' ' + call ?cono + ld c,BS + call ?cono + pop bc + pop hl + pop de + ret + DELL: ld a,b ;081b or a ;081c @@ -472,22 +496,34 @@ l0960h: outquote: ld a,'''' ;0979 OUTCHAR: - push hl ;097b - push af ;097c - and 07fh ;097d - call $co ;097f - ld hl,CON.COL ;0982 - inc (hl) ;0985 - pop af ;0986 - pop hl ;0987 + push hl + push de + push bc + push af + and 07fh + ld c,a + call ?cono + ld hl,CON.COL + inc (hl) + pop af + pop bc + pop de + pop hl ret ;0988 inchar: - call $cists ;0989 - and a ;098c - ret z ;098d - call $ci ;098e + push hl + push de + push bc + call ?const + and a + jr z,inch1 + call ?conin scf ;0991 +inch1: + pop bc + pop de + pop hl ret ;0992 PSTR: @@ -1816,7 +1852,7 @@ l1144h: inc hl ;1176 ld a,d ;1177 comrep ;1178 - + else ld a,(ddtrst) ;115c @@ -4649,7 +4685,7 @@ b_0x2108_start: ; 1 byte opcodes defb 08bh ;2137 defw l2561h ;2138 - defb 0c7h ;213a rst + defb 0c7h ;213a rst defb 0c7h ;213b defb 0b4h ;213c defw l231eh ;213d diff --git a/z180/modebaud.inc b/z180/modebaud.inc new file mode 100644 index 0000000..2e60e44 --- /dev/null +++ b/z180/modebaud.inc @@ -0,0 +1,31 @@ + ; 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/z180/r3init.180 b/z180/r3init.180 index 2dd1bb8..9adbdd8 100644 --- a/z180/r3init.180 +++ b/z180/r3init.180 @@ -3,7 +3,7 @@ extrn ddtz,bpent extrn $stack - extrn $coninit,$cists,$ci + extrn charini,?const,?conin extrn romend @@ -73,17 +73,20 @@ hwini0: ;---------------------------------------------------------------------- start: - push af ;003c - in0 a,(itc) ;003d Illegal opcode trap? - jp p,??st01 ;0040 - pop af ;0043 - jp bpent ;0044 yes, handle + ld (tmpstack),sp + ld sp,tmpstack + push af + in0 a,(itc) ;Illegal opcode trap? + jp m,??st01 + ld a,i ;I register == 0 ? + jr z,??st02 ; yes, harware reset ??st01: - ld a,i ;0047 I register == 0 ? - jr z,??st02 ;004b yes, harware reset - pop af ;004d - jp bpent ;004e no, allready set up + ld a,(syscbr) + out0 (cbr),a + pop af ;restore registers + ld sp,(tmpstack) ; + jp bpent ; ??st02: di ;0058 @@ -189,6 +192,8 @@ ramok: alloc: out0 (cbr),c ;01de + ld a,c + ld (syscbr),a ld sp,$stack ;01e1 ; Clear RAM using DMA0 @@ -280,7 +285,7 @@ wstart: call prt0_init - call $coninit + call charini call bufferinit @@ -289,15 +294,21 @@ wstart: im 2 ;?030e ei ;0282 - call $cists ;0284 - call $cists ;0287 + call ?const ;0284 + call ?const ;0287 or a ;028a - call nz,$ci ;028d + call nz,?conin ;028d ld a,(banktab) ; ld e,a ; jp ddtz ;0290 + + ds 8 +tmpstack: + dw 2 +syscbr: db 1 + ; ;---------------------------------------------------------------------- ; diff --git a/z180/ser1-i.180 b/z180/ser1-i.180 index 4074a9d..2410e38 100644 --- a/z180/ser1-i.180 +++ b/z180/ser1-i.180 @@ -6,8 +6,8 @@ global ser.init - global ser.instat,ser.in - global ser.out + global ser.ist,ser.in + global ser.ost,ser.out ;TODO: define a trampoline area somewhere in top ram. rtxisvjmp equ 0FF60h ;momentan frei... @@ -78,7 +78,7 @@ ser.init: ; ei ret ; -ser.instat: +ser.ist: push ix ld ix,ser1.inbuf ; @@ -126,7 +126,7 @@ bg.w1: ret ; 9 ; 153 -ser.outstat: +ser.ost: push ix ld ix,ser1.outbuf ; buf.full: @@ -148,6 +148,7 @@ buf.put: push bc push ix pop hl + ld a,c ld c,(ix+o.in_idx) ; ld b,0 add hl,bc -- 2.39.2