X-Git-Url: http://cloudbase.mooo.com/gitweb/z180-stamp-cpm3.git/blobdiff_plain/81ba3c8469440da99c8f9ff70457a8e2f05398b7..7c72cfe363cdc89093e62ddcd47fc2e1df98e5cf:/cbios/ascii.180 diff --git a/cbios/ascii.180 b/cbios/ascii.180 index 7d6afbf..0ee942d 100644 --- a/cbios/ascii.180 +++ b/cbios/ascii.180 @@ -1,107 +1,484 @@ - page 200 ; Interrupt drivers for ASCI0 and ASCI1 - global as0init - global as0ista,as0inp - global as0osta,as0out - global as1init - global as1ista,as1inp - global as1osta,as1out + global as0_dev,as1_dev - extrn as_init + extrn @ctbl,f_cpu extrn ff_empty,ff_get,ff_full,ff_put extrn ff_puth,ff_cnt,ff_gech extrn bufinit - extrn isv_sw + extrn isv_sw,ijphl,add_hla,div32_r + extrn b_st_a,b_ld_a - include config.inc - include z180reg.inc + maclib z180reg.inc + maclib config.inc + maclib ioctl.inc + maclib modebaud.inc + m2b mbxon_bit,mb$xon$xoff ;----------------------------------------------------- dseg + dw asci0_out + dw asci0_osta + dw asci0_inp + dw asci0_ista + dw asci_ioctl +as0_dev: + db 0 ;absolute device # + db 0 ;relative device + db 0 ;iflags + db 0 ;fflags + db M_CS8 ;cflags +o.absdev equ 0 +o.reldev equ 1 +o.iflags equ 2 +o.fflags equ 3 +o.cflags equ 4 + + db 0 + db 0 +oint.iflags equ as0_dev+o.iflags-s0.inbuf +oint.fflags equ as0_dev+o.fflags-s0.inbuf mkbuf s0.rx_id, s0.inbuf, s0.rx_len - mkbuf 0, s0.instatbuf, s0.rx_len mkbuf s0.tx_id, s0.outbuf,s0.tx_len + + + dw asci1_out + dw asci1_osta + dw asci1_inp + dw asci1_ista + dw asci_ioctl +as1_dev: + db 0 ;absolute device # + db 1 ;relative device + db 0 ;iflags + db 0 ;fflags + db M_CS8 ;cflags + + db 0 + db 0 mkbuf s1.rx_id, s1.inbuf, s1.rx_len - mkbuf 0, s1.instatbuf, s1.rx_len mkbuf s1.tx_id, s1.outbuf,s1.tx_len dseg + +ioctl_ftab: + dw func_tcinit ;(00h) CP/M 3 DEVINI function + dw func_tcgeta ;(01h) Get the current serial port settings. + dw func_tcseta ;(02h) Set the current serial port settings. + dw func_tcsetaw ;(03h) Allow the output buffer to drain + dw func_tcsetaf ;(04h) Allow the output buffer to drain, discard pending input + dw func_tcsbrk ;(05h) Sending a break (250ms .. 500ms) + dw func_tcsbrkp ;(06h) arg is timeinterval in 0.1sec + dw func_tiocsbrk ;(07h) Turn break on + dw func_tioccbrk ;(08h) Turn break off + dw func_tcxonc ;(09h) Software flow control (TCOOFF, TCOON, TCIOFF, TCION) + dw func_tcflsh ;(0Ah) Flush input/output buffer (TCIFLUSH, TCOFLUSH, TCIOFLUSH) + dw func_fionread ;(0Bh) Get the number of bytes in the input buffer. + dw func_tiocoutq ;(0Ch) Get the number of bytes in the output buffer. + dw func_tiocmget ;(0Dh) get the status of modem bits. + dw func_tiocmbis ;(0Eh) set the indicated modem bits. + dw func_tiocmbic ;(0Fh) clear the indicated modem bits. + dw func_tiocmset ;(10h) set the status of modem bits. + dw func_tiocgsoftcar ;(11h) Get the status of the CLOCAL flag in the c_cflag field + dw func_tiocssoftcar ;(12h) Set the CLOCAL flag when *argp is nonzero, and clear it otherwise. + +IOCTL_MAX equ ($-ioctl_ftab)/2 + dw nofunc + + ;-------------------------------------------------------------- -; Init Serial I/O for input and output (ASCI 0/1) ; -; b: device number +; b: device number +; c: command +; de: ioctl arg pointer +; hl: ptr to driver local data ; +asci_ioctl: + push hl + ex (sp),ix + ld (ix+o.absdev),b + ld hl,ioctl_ftab + ld a,IOCTL_MAX + cp c + jr c,$+3 + ld a,c + add a,a + call add_hla + ld a,(hl) + inc hl + ld h,(hl) + ld l,a + call ijphl + pop ix +nofunc: + or a + ret -;ser.init: -; ld a,i -; push af ;save IFF -; di -;--- -; pop af -; ret po -; ei -; ret ; +;-------------------------------------------------------------- +; CP/M 3 DEVINI function +; Init Serial I/O for input and output (ASCI 0/1) -as0init: - xor a ; - out0 (stat0),a ;Disable rx/tx interrupts - ld c,0 ;asci channel number - call as_init - ld hl,rtxisvjmp0 ;rx/tx int vector - ld (ivtab + IV$ASCI0),hl ; +func_tcinit: + call asci_stop + +init_st: + ld c,asext0 ;Enable baud rate generator + ld a,M_BRGMOD+M_DCD0DIS ; +M_CTS0DIS +M_BREAKEN + bit CCTS_OFLOW,(ix+o.fflags) + jr nz,$+4 + or M_CTS0DIS + call out_asci_reg + + ld b,(ix+o.absdev) + ld c,8 ; + mlt bc ; + ld hl,@ctbl+7 ; + add hl,bc ; + ld a,(hl) ;get baudrate index + call as_br_div + ld c,astc0l + ld a,l + call out_asci_reg + inc c + ld a,h + call out_asci_reg + + + ld c,cntlb0 + ld a,M_MPBT ;No MP Mode, X16 + bit PARODD,(ix+o.iflags) + jr z,$+4 + or M_PEO + call out_asci_reg + + ld c,cntla0 + ld a,(ix+o.cflags) + srlan CS8 + ld hl,mod_tab + call add_hla + ld a,(hl) + or a,M_RE+M_TE+M_RTS0+M_EFR ;Rx/Tx enable + call out_asci_reg + push ix + bit 0,(ix+o.reldev) + jr nz,init_1 + ld hl,rtxisvjmp0 ;rx/tx int vector + ld (ivtab + IV$ASCI0),hl ; + ld ix,s0.outbuf + call bufinit ld ix,s0.inbuf + jr init_2 +init_1: + ld hl,rtxisvjmp1 ;rx/tx int vector + ld (ivtab + IV$ASCI1),hl ; + ld ix,s1.outbuf call bufinit - ld ix,s0.outbuf + ld ix,s1.inbuf +init_2: call bufinit - ld a,M_RIE - out0 (stat0),a ;Enable rx interrupts + pop ix + call asci_start ret -as1init: +;-------------------------------------------------------------- + +mod_tab: + db 000B ; 7N1 + db 100B ; 8N1 + db 001B ; 7N2 + db 101B ; 8N2 + db 010B ; 7P1 + db 110B ; 8P1 + db 011B ; 7P2 + db 111B ; 8P2 + + +;-------------------------------------------------------------- +; Get the current serial port settings. + +func_tcgeta: + ld a,d + or e + ld a,0ffh + jr z,fgeta_e + + ld a,(ix+o.iflags) + call b_st_a + inc de + ld a,(ix+o.fflags) + call b_st_a + inc de + + ld b,(ix+o.absdev) + ld c,8 ; + mlt bc ; + ld hl,@ctbl+7 ; + add hl,bc ; + ld a,(hl) ;get baudrate index + and M_CBAUD + ld b,a + ld a,(ix+o.cflags) + and ~M_CBAUD + or b + call b_st_a + dec de + dec de + xor a +fgeta_e: + ret + + +;-------------------------------------------------------------- +; Set the current serial port settings. + +func_tcseta: + ld a,d + or e + ld a,0ffh + jr z,fseta_e + + call asci_stop + + call b_ld_a + ld (ix+o.iflags),a + inc de + call b_ld_a + ld (ix+o.fflags),a + inc de + + ld b,(ix+o.absdev) + ld c,8 ; + mlt bc ; + ld hl,@ctbl+7 ; + add hl,bc ; + call b_ld_a + ld (ix+o.cflags),a + and M_CBAUD + ld (hl),a ;set baudrate index + dec de + dec de + push de + call init_st + pop de + xor a +fseta_e: + ret + + +;-------------------------------------------------------------- +; Allow the output buffer to drain + +func_tcsetaw: + +;-------------------------------------------------------------- +; Allow the output buffer to drain, discard pending input + +func_tcsetaf: + +;-------------------------------------------------------------- +; Sending a break (250ms .. 500ms) + +func_tcsbrk: + +;-------------------------------------------------------------- +; arg is timeinterval in 0.1sec + +func_tcsbrkp: + +;-------------------------------------------------------------- +; Turn break on + +func_tiocsbrk: + +;-------------------------------------------------------------- +; Turn break off + +func_tioccbrk: + +;-------------------------------------------------------------- +; Software flow control (TCOOFF, TCOON, TCIOFF, TCION) + +func_tcxonc: + +;-------------------------------------------------------------- +; Flush input/output buffer (TCIFLUSH, TCOFLUSH, TCIOFLUSH) + +func_tcflsh: + +;-------------------------------------------------------------- +; Get the number of bytes in the input buffer. + +func_fionread: + +;-------------------------------------------------------------- +; Get the number of bytes in the output buffer. + +func_tiocoutq: + +;-------------------------------------------------------------- +; get the status of modem bits. + +func_tiocmget: + +;-------------------------------------------------------------- +; set the indicated modem bits. + +func_tiocmbis: + +;-------------------------------------------------------------- +; clear the indicated modem bits. + +func_tiocmbic: + +;-------------------------------------------------------------- +; set the status of modem bits. + +func_tiocmset: + +;-------------------------------------------------------------- +; Get the status of the CLOCAL flag in the c_cflag field + +func_tiocgsoftcar: + +;-------------------------------------------------------------- +; Set the CLOCAL flag when *argp is nonzero, and clear it otherwise. + +func_tiocssoftcar: + + or 0ffh + ret + +;-------------------------------------------------------------- + +asci_stop: + ld c,stat0 ;Disable rx/tx interrupts xor a ; - out0 (stat1),a ;Disable rx/tx interrupts - ld c,1 ;asci channel number - call as_init + call out_asci_reg - ld hl,rtxisvjmp1 ;rx/tx int vector - ld (ivtab + IV$ASCI1),hl ; + ld c,cntla0 ;Disable receiver and transmitter + ld a,M_RTS0+M_EFR ;RTS/CKA1 + jr out_asci_reg - push ix - ld ix,s1.inbuf - call bufinit - ld ix,s1.outbuf - call bufinit - pop ix +;-------------------------------------------------------------- + +asci_start: + ld c,stat0 ; ld a,M_RIE - out0 (stat1),a ;Enable rx interrupts + jr out_asci_reg + +;-------------------------------------------------------------- +; output to asci0/1 register +; +; c: register address +; a: value +; + +out_asci_reg: + push bc + ld b,a + ld a,c + cp astc0l ;astc0/1 are 16 bit + jr c,$+5 + add a,(ix+o.reldev) + add a,(ix+o.reldev) + ld c,a + ld a,b + ld b,0 + out (c),a + pop bc ret +;-------------------------------------------------------------- +; baud rate divider +; +; a: index +; return +; hl: divider + +as_br_div: + push de + push bc + and 0fh + add a,a ;get factor + ld hl,bd150_tab + call add_hla + ld c,(hl) + inc hl + ld b,(hl) + ld hl,(f_cpu) + ld de,(f_cpu+2) + call div32_r + ld bc,32*150 + call div32_r + ld de,2 + or a + sbc hl,de + pop bc + pop de + ret nc + ld hl,0 + ret - cseg -rtxisvjmp0: - call isv_sw - dw rxtxi0 -rtxisvjmp1: - call isv_sw - dw rxtxi1 +bd150_tab: +; factor index baudrate orig. cp/m + dw 19200/150 ; 0 19200 - + dw 28800/150 ; 1 28800 50 + dw 38400/150 ; 2 38400 75 + dw 57600/150 ; 3 57600 110 + dw 11520/15 ; 4 115200 134.5 + dw 150/150 ; 5 150 + dw 300/150 ; 6 300 + dw 600/150 ; 7 600 + dw 1200/150 ; 8 1200 + dw 1800/150 ; 9 1800 + dw 2400/150 ;10 2400 + dw 3600/150 ;11 3600 + dw 4800/150 ;12 4800 + dw 7200/150 ;13 7200 + dw 9600/150 ;14 9600 + dw 19200/150 ;15 19200 + + +;-------------------------------------------------------------- + + if 0 + +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 +init_br_off equ $ - initab0 + dw 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 + endif ;-------------------------------------------------------------- dseg -as0ista: +asci0_ista: push ix ld ix,s0.inbuf ; call ff_empty @@ -110,7 +487,7 @@ as0ista: ;-------------------------------------------------------------- -as1ista: +asci1_ista: push ix ld ix,s1.inbuf ; call ff_empty @@ -120,7 +497,7 @@ as1ista: ;-------------------------------------------------------------- ; Get an input character -as0inp: +asci0_inp: push ix ld ix,s0.inbuf ; call ff_gech @@ -141,7 +518,7 @@ a0i_1: ;-------------------------------------------------------------- ; Get an input character -as1inp: +asci1_inp: push ix ld ix,s1.inbuf ; call ff_gech @@ -151,7 +528,7 @@ as1inp: ;-------------------------------------------------------------- ; Output status -as0osta: +asci0_osta: push ix ld ix,s0.outbuf ; call ff_full @@ -161,7 +538,7 @@ as0osta: ;-------------------------------------------------------------- ; Output status -as1osta: +asci1_osta: push ix ld ix,s1.outbuf ; call ff_full @@ -173,7 +550,7 @@ as1osta: ; destroys hl, bc ; returns output char in a -as0out: +asci0_out: push ix ; ld ix,s0.outbuf ; call ff_puth @@ -190,7 +567,7 @@ as0out: ; destroys hl, bc ; returns output char in a -as1out: +asci1_out: push ix ; ld ix,s1.outbuf ; call ff_puth @@ -203,38 +580,59 @@ as1out: ret -;------------------------------------------ +;-------------------------------------------------------------- + + cseg +rtxisvjmp0: + call isv_sw + dw rxtxi0 +rtxisvjmp1: + call isv_sw + dw rxtxi1 + +;-------------------------------------------------------------- ; ASCI 0 Transmit/Receive interupt routines dseg rxtxi0: push ix -rxtxi0_loop: - in0 e,(stat0) ;receive flag set? +rxtxi0_lp0: + ld ix,s0.inbuf ; +rxtxi0_lp1: + in0 a,(stat0) ;receive flag set? jp p,rxtxi0_1 ;RDRF == Bit 7 + and M_OVRN+M_PERR+M_FE + ld e,a - -rxi_0 - in0 a,(asext0) ;todo: break detection + in0 a,(asext0) and M_BREAK or e ld e,a in0 d,(cntla0) ; res EFR,d ; + out0 (cntla0),d + - ld ix,s0.inbuf ; ld c,(ix+o.in_idx) ; ld b,0 ld hl,s0.inbuf ; add hl,bc + in0 a,(rdr0) ; ld (hl),a + ;todo: break detection + ;todo: parity, framing overrun error + + + ld e,(ix+oint.fflags) + bit IXON,e + jr z,rxtxi0_2 + + ;todo: test XON/XOFF + +rxtxi0_2: - ld hl,s0.instatbuf ;save error status - add hl,bc - ld (hl),e - ;todo: error handling and break detection ld a,c ;increment buffer in pointer inc a ; @@ -243,19 +641,34 @@ rxi_0 ld c,a sub (ix+o.out_idx) ; - jr z,$+5 ;skip if buffer is full - ld (ix+o.in_idx),c ; + jr z,rxtxi0_lp1 ;skip if buffer is full + + ld (ix+o.in_idx),c ; + jr nc,$+3 ; adc b ; + cp s0.tx_len*3/4 - jr c,$+4 - set RTS0,d ;RTS inactive -?0ri_1: + jr c,rxi0_noflow + + bit CRTS_IFLOW,e + jr z,rxtxi0_4 + + set EFR,d + set RTS0,d ;RTS inactive out0 (cntla0),d ; - jr rxtxi0_loop + +rxtxi0_4: + bit IXOFF,e + jr z,rxtxi0_lp1 + ;todo: send XOFF + +rxi0_noflow: + jr rxtxi0_lp1 rxtxi0_1: + ld e,a bit TDRE,e ;TX int? jr z,rxtxi0_e ; @@ -276,7 +689,7 @@ rxtxi0_1: inc a and (ix+o.mask) ld (ix+o.out_idx),a - jr rxtxi0_loop + jr rxtxi0_lp0 ?0ti_2: res TIE,e ;disable tx-int @@ -287,7 +700,7 @@ rxtxi0_e: ret -;------------------------------------------ +;-------------------------------------------------------------- ; ASCI 1 Transmit/Receive interupt routines dseg