--- /dev/null
+\r
+ .z80\r
+\r
+; Copyright (C), 1982\r
+; Digital Research, Inc\r
+; P.O. Box 579\r
+; Pacific Grove, CA 93950\r
+\r
+; This is the invariant portion of the modular BIOS and is\r
+; distributed as source for informational purposes only.\r
+; All desired modifications should be performed by\r
+; adding or changing externally defined modules.\r
+; This allows producing "standard" I/O modules that\r
+; can be combined to support a particular system\r
+; configuration.\r
+;\r
+; Modified for faster character I/O by Udo Munk\r
+\r
+cr equ 13\r
+lf equ 10\r
+bell equ 7\r
+ctlQ equ 'Q'-'@'\r
+ctlS equ 'S'-'@'\r
+\r
+ cseg ; GENCPM puts CSEG stuff in common memory\r
+\r
+ ; variables in system data page\r
+\r
+;; extrn @covec,@civec,@aovec,@aivec,@lovec ; I/O redirection vectors\r
+ \r
+ ; user defined character I/O routines\r
+\r
+ extrn ?ci,?co,?cist,?cost ; each take device in <B>\r
+ extrn ?cinit ; (re)initialize device in <C>\r
+ extrn @ctbl ; physical character device table\r
+\r
+\r
+ include modebaud.inc ; define mode bits\r
+\r
+\r
+ public @covec,@civec,@aovec,@aivec,@lovec ; I/O redirection vectors\r
+ public ?const,?conin,?cono,?list,?auxo,?auxi\r
+ public ?lists,?conos,?auxis,?auxos,?dvtbl,charini\r
+\r
+\r
+@CIVEC: dw 0 ; Console Input Redirection\r
+ ; Vector (word, r/w)\r
+@COVEC: dw 0 ; Console Output Redirection\r
+ ; Vector (word, r/w)\r
+@AIVEC: dw 0 ; Auxiliary Input Redirection\r
+ ; Vector (word, r/w)\r
+@AOVEC: dw 0 ; Auxiliary Output Redirection\r
+ ; Vector (word, r/w)\r
+@LOVEC: dw 0 ; List Output Redirection\r
+ ; Vector (word, r/w)\r
+\r
+\r
+charini:\r
+\r
+ ld c,15 ; initialize all 16 character devices\r
+c$init$loop:\r
+ push bc\r
+ call ?cinit\r
+ pop bc\r
+ dec c\r
+ jp p,c$init$loop\r
+\r
+ ld hl,1100000000000000b ; assign console to HOST and ASCI1\r
+ ld (@civec),hl\r
+ ld (@covec),hl\r
+ ld hl,0000000000000000b ; assign auxiliary to nothing\r
+ ld (@aivec),hl\r
+ ld (@aovec),hl\r
+ ld hl,0000000000000000b ; assign printer to nothing\r
+ ld (@lovec),hl\r
+ ret\r
+\r
+\r
+ ; DEVTBL\r
+ ; Return address of character device table\r
+\r
+?dvtbl:\r
+devtbl:\r
+ ld hl,@ctbl\r
+ ret\r
+\r
+\r
+ ; CONOUT\r
+ ; Console Output. Send character in <C>\r
+ ; to all selected devices\r
+\r
+?cono:\r
+conout:\r
+ ld hl,(@covec) ; fetch console output bit vector\r
+ jr out$scan\r
+\r
+\r
+ ; AUXOUT\r
+ ; Auxiliary Output. Send character in <C>\r
+ ; to all selected devices\r
+\r
+?auxo:\r
+auxout:\r
+ ld hl,(@aovec) ; fetch aux output bit vector\r
+ jr out$scan\r
+\r
+\r
+ ; LIST\r
+ ; List Output. Send character in <C>\r
+ ; to all selected devices.\r
+\r
+?list:\r
+list:\r
+ ld hl,(@lovec) ; fetch list output bit vector\r
+\r
+out$scan:\r
+ ld b,0 ; start with device 0\r
+co$next:\r
+ add hl,hl ; shift out next bit\r
+ jr nc,not$out$device\r
+ push hl ; save the vector\r
+ push bc ; save the count and character\r
+ call ?co ; if device selected, print it\r
+ pop bc ; recover count and character\r
+ pop hl ; recover the rest of the vector\r
+not$out$device:\r
+ inc b ; next device number\r
+ ld a,h\r
+ or l ; see if any devices left\r
+ jr nz,co$next ; and go find them...\r
+ ret\r
+\r
+\r
+ ; CONOST\r
+ ; Console Output Status. Return true if\r
+ ; all selected console output devices\r
+ ; are ready.\r
+\r
+?conos:\r
+conost:\r
+ ld hl,(@covec) ; get console output bit vector\r
+ jr ost$scan\r
+\r
+\r
+ ; AUXOST\r
+ ; Auxiliary Output Status. Return true if\r
+ ; all selected auxiliary output devices\r
+ ; are ready.\r
+\r
+?auxos:\r
+auxost:\r
+ ld hl,(@aovec) ; get aux output bit vector\r
+ jr ost$scan\r
+\r
+\r
+ ; LISTST\r
+ ; List Output Status. Return true if\r
+ ; all selected list output devices\r
+ ; are ready.\r
+\r
+?lists:\r
+listst:\r
+ ld hl,(@lovec) ; get list output bit vector\r
+\r
+ost$scan:\r
+ ld b,0 ; start with device 0\r
+cos$next:\r
+ add hl,hl ; check next bit\r
+ push hl ; save the vector\r
+ push bc ; save the count\r
+ ld a,0FFh ; assume device ready\r
+ call c,coster ; check status for this device\r
+ pop bc ; recover count\r
+ pop hl ; recover bit vector\r
+ or a ; see if device ready\r
+ ret z ; if any not ready, return false\r
+ inc b ; drop device number\r
+ ld a,h\r
+ or l ; see if any more selected devices\r
+ jr nz,cos$next\r
+ or 0FFh ; all selected were ready, return true\r
+ ret\r
+\r
+coster: ; check for output device ready, including optional\r
+ ; xon/xoff support\r
+ ;\r
+ ;TODO: interrupt driven devices should xon/xoff handle\r
+ ; in isv\r
+\r
+ ld l,b\r
+ ld h,0 ; make device code 16 bits\r
+ push hl ; save it in stack\r
+ add hl,hl\r
+ add hl,hl\r
+ add hl,hl ; create offset into device characteristics tbl\r
+ ld de,@ctbl+6\r
+ add hl,de ; make address of mode byte\r
+ ld a,(hl)\r
+ and mb$xon$xoff\r
+ pop hl ; recover console number in <HL>\r
+ jp z,?cost ; not a xon device, go get output status direct\r
+ ld de,xofflist\r
+ add hl,de ; make pointer to proper xon/xoff flag\r
+ call cist1 ; see if this keyboard has character\r
+ ld a,(hl)\r
+ call nz,ci1 ; get flag or read key if any\r
+ cp ctlq\r
+ jr nz,not$q ; if its a ctl-Q,\r
+ ld a,0FFh ; set the flag ready\r
+not$q:\r
+ cp ctls\r
+ jr nz,not$s ; if its a ctl-S,\r
+ ld a,00h ; clear the flag\r
+not$s:\r
+ ld (hl),a ; save the flag\r
+ call cost1 ; get the actual output status,\r
+ and (hl) ; and mask with ctl-Q/ctl-S flag\r
+ ret ; return this as the status\r
+\r
+cist1: ; get input status with <BC> and <HL> saved\r
+ push bc\r
+ push hl\r
+ call ?cist\r
+ pop hl\r
+ pop bc\r
+ or a\r
+ ret\r
+\r
+cost1: ; get output status, saving <BC> & <HL>\r
+ push bc\r
+ push hl\r
+ call ?cost\r
+ pop hl\r
+ pop bc\r
+ or a\r
+ ret\r
+\r
+ci1: ; get input, saving <BC> & <HL>\r
+ push bc\r
+ push hl\r
+ call ?ci\r
+ pop hl\r
+ pop bc\r
+ ret\r
+\r
+\r
+ ; AUXIST\r
+ ; Auxiliary Input Status. Return true if\r
+ ; any selected auxiliary input device\r
+ ; has an available character.\r
+?auxis:\r
+auxist:\r
+ ld hl,(@aivec) ; get aux input bit vector\r
+ jr ist$scan\r
+\r
+\r
+ ; CONST\r
+ ; Console Input Status. Return true if\r
+ ; any selected console input device\r
+ ; has an available character.\r
+?const:\r
+const:\r
+ ld hl,(@civec) ; get console input bit vector\r
+\r
+\r
+ist$scan:\r
+ ld b,0 ; start with device 0\r
+cis$next:\r
+ add hl,hl ; check next bit\r
+ ld a,0 ; assume device not ready\r
+ call c,cist1 ; check status for this device\r
+ or a\r
+ ret nz ; if any ready, return true\r
+ inc b ; next device number\r
+ ld a,h\r
+ or l ; see if any more selected devices\r
+ jr nz,cis$next\r
+ xor a ; all selected were not ready, return false\r
+ ret\r
+\r
+\r
+ ; AUXIN\r
+ ; Auxiliary Input. Return character from first\r
+ ; ready auxiliary input device.\r
+?auxi:\r
+auxin:\r
+ ld hl,(@aivec)\r
+ jr in$scan\r
+\r
+\r
+ ; CONIN\r
+ ; Console Input. Return character from first\r
+ ; ready console input device.\r
+?conin:\r
+conin:\r
+ ld hl,(@civec)\r
+\r
+in$scan:\r
+ push hl ; save bit vector\r
+ ld b,0\r
+ci$next:\r
+ add hl,hl ; shift out next bit\r
+ ld a,0 ; insure zero a (nonexistant device not ready).\r
+ call c,cist1 ; see if the device has a character\r
+ or a\r
+ jr nz,ci$rdy ; this device has a character\r
+ inc b ; else, next device\r
+ ld a,h\r
+ or l ; see if any more devices\r
+ jr nz,ci$next ; go look at them\r
+ pop hl ; recover bit vector\r
+ jr in$scan ; loop til we find a character\r
+ci$rdy:\r
+ pop hl ; discard extra stack\r
+ jp ?ci\r
+\r
+\r
+\r
+xofflist:\r
+ db -1,-1,-1,-1,-1,-1,-1,-1 ; ctl-s clears to zero\r
+ db -1,-1,-1,-1,-1,-1,-1,-1\r
+\r
+\r
+ end\r
+\r