title 'Character I/O handler for z80 chip based system' ; Character I/O for the Modular CP/M 3 BIOS public ?cinit,?ci,?co,?cist,?cost public @ctbl ; maclib Z80 ; define Z80 op codes ; maclib ports ; define port addresses maclib modebaud.lib ; define mode bits and baud equates ;max$devices equ 6 cseg ?cinit: ret ; mov a,c ! cpi max$devices ! jz cent$init ; init parallel printer ; rnc ; invalid device ; mov l,c ! mvi h,0 ; make 16 bits from device number ; push h ; save device in stack ; dad h ! dad h ! dad h ; *8 ; lxi d,@ctbl+7 ! dad d ! mov l,m ; get baud rate ; mov a,l ! cpi baud$600 ; see if baud > 300 ; mvi a,44h ! jnc hi$speed ; if >= 600, use *16 mode ; mvi a,0C4h ; else, use *64 mode ;hi$speed: ; sta sio$reg$4 ; mvi h,0 ! lxi d,speed$table ! dad d ; point to counter entry ; mov a,m ! sta speed ; get and save ctc count ; pop h ; recover ; lxi d,data$ports ! dad d ; point at SIO port address ; mov a,m ! inr a ! sta sio$port ; get and save port ; lxi d,baud$ports-data$ports ! dad d ; offset to baud rate port ; mov a,m ! sta ctc$port ; get and save ; lxi h,serial$init$tbl ; jmp stream$out ; ;cent$init: ; lxi h,pio$init$tbl ; ;stream$out: ; mov a,m ! ora a ! rz ; mov b,a ! inx h ! mov c,m ! inx h ; outir ; jmp stream$out ?ci: ; character input ;ld bc,0000H ; unit 0, func 0 = CIN ld c,b ; Unit number to C ld b,00h ; HBIOS CIN Function rst 08 ; do it ld a,e ; put char in A ret ; done ; mov a,b ! cpi 6 ! jnc null$input ; can't read from centronics ;ci1: ; call ?cist ! jz ci1 ; wait for character ready ; dcr c ! inp a ; get data ; ani 7Fh ; mask parity ; ret ; ;null$input: ; mvi a,1Ah ; return a ctl-Z for no device ; ret ?cist: ; character input status ;ld bc,0200H ; unit 0, func 2 = IST ld c,b ; Unit number to C ld b,02h ; HBIOS IST Function rst 08 ; do it or a ; set flags ret z ; return w/ ZF set if no char ready or 0FFH ; else signal nothing ready ret ; done ; mov a,b ! cpi 6 ! jnc null$status ; can't read from centronics ; mov l,b ! mvi h,0 ; make device number 16 bits ; lxi d,data$ports ! dad d ; make pointer to port address ; mov c,m ! inr c ; get SIO status port ; inp a ; read from status port ; ani 1 ; isolate RxRdy ; rz ; return with zero ; ori 0FFh ; ret ;null$status: ; xra a ! ret ?co: ; character output ld e,c ; char to E ;ld bc,0100H ; unit 0, func 1 = COUT ld c,b ; Unit number to C ld b,01h ; HBIOS COUT Function rst 08 ; do it ret ; done ; mov a,b ! cpi 6 ! jz centronics$out ; jnc null$output ; mov a,c ! push psw ; save character from ; push b ; save device number ;co$spin: ; call ?cost ! jz co$spin ; wait for TxEmpty ; pop h ! mov l,h ! mvi h,0 ; get device number in ; lxi d,data$ports ! dad d ; make address of port address ; mov c,m ; get port address ; pop psw ! outp a ; send data ;null$output: ; ret ; ;centronics$out: ; in p$centstat ! ani 20h ! jnz centronics$out ; mov a,c ! out p$centdata ; give printer data ; in p$centstat ! ori 1 ! out p$centstat ; set strobe ; ani 7Eh ! out p$centstat ; clear strobe ; ret ?cost: ; character output status ;ld bc,0300H ; unit 0, func 3 = OST ld c,b ; Unit number to C ld b,03h ; HBIOS OST Function rst 08 ; do it or a ; set flags ret z ; return w/ ZF set if not ready to send or 0FFH ; else signal nothing ready ret ; done ; mov a,b ! cpi 6 ! jz cent$stat ; jnc null$status ; mov l,b ! mvi h,0 ; lxi d,data$ports ! dad d ; mov c,m ! inr c ; inp a ; get input status ; ani 4 ! rz ; test transmitter empty ; ori 0FFh ! ret ; return true if ready ; ; ;cent$stat: ; in p$centstat ! cma ; ani 20h ! rz ; ori 0FFh ! ret ;baud$ports: ; CTC ports by physical device number ; db p$baud$con1,p$baud$lpt1,p$baud$con2,p$baud$con34 ; db p$baud$con34,p$baud$lpt2 ; ;data$ports: ; serial base ports by physical device number ; db p$crt$data,p$lpt$data,p$con2data,p$con3data ; db p$con4data,p$lpt2data @ctbl db 'COM0 ' db mb$in$out+mb$serial+baud$none db baud$none db 'COM1 ' db mb$in$out+mb$serial+baud$none db baud$none db 'COM2 ' db mb$in$out+mb$serial+baud$none db baud$none db 'COM3 ' db mb$in$out+mb$serial+baud$none db baud$none db 'COM4 ' db mb$in$out+mb$serial+baud$none db baud$none db 'COM5 ' db mb$in$out+mb$serial+baud$none db baud$none db 'COM6 ' db mb$in$out+mb$serial+baud$none db baud$none db 'COM7 ' db mb$in$out+mb$serial+baud$none db baud$none db 'COM8 ' db mb$in$out+mb$serial+baud$none db baud$none db 'COM9 ' db mb$in$out+mb$serial+baud$none db baud$none db 'COM10 ' db mb$in$out+mb$serial+baud$none db baud$none db 'COM11 ' db mb$in$out+mb$serial+baud$none db baud$none db 0 ;@ctbl db 'CRT ' ; device 0, CRT port 0 ; db mb$in$out+mb$serial+mb$softbaud ; db baud$9600 ; db 'LPT ' ; device 1, LPT port 0 ; db mb$in$out+mb$serial+mb$softbaud+mb$xonxoff ; db baud$9600 ; db 'CRT1 ' ; device 2, CRT port 1 ; db mb$in$out+mb$serial+mb$softbaud ; db baud$9600 ; db 'CRT2 ' ; device 3, CRT port 2 ; db mb$in$out+mb$serial+mb$softbaud ; db baud$9600 ; db 'CRT3 ' ; device 4, CRT port 3 ; db mb$in$out+mb$serial+mb$softbaud ; db baud$9600 ; db 'VAX ' ; device 5, LPT port 1 used for VAX interface ; db mb$in$out+mb$serial+mb$softbaud ; db baud$9600 ; db 'CEN ' ; device 6, Centronics parallel printer ; db mb$output ; db baud$none ; db 0 ; table terminator ;speed$table db 0,255,255,255,233,208,104,208,104,69,52,35,26,17,13,7 ; ;serial$init$tbl ; db 2 ; two bytes to CTC ;ctc$port ds 1 ; port address of CTC ; db 47h ; CTC mode byte ;speed ds 1 ; baud multiplier ; db 7 ; 7 bytes to SIO ;sio$port ds 1 ; port address of SIO ; db 18h,3,0E1h,4 ;sio$reg$4 ds 1 ; db 5,0EAh ; db 0 ; terminator ; ;pio$init$tbl db 2,p$zpio$2b,0Fh,07h ; db 3,p$zpio$2a,0CFh,0F8h,07h ; db 0 end