X-Git-Url: http://cloudbase.mooo.com/gitweb/z180-stamp-cpm3.git/blobdiff_plain/72ba373765af20594a45142cc9bb3c5fe5bb14e6..e8b62d9ac855de6439580c15ee12f496a94c5e5d:/cbios/ascii.180 diff --git a/cbios/ascii.180 b/cbios/ascii.180 index d329de4..3ffa931 100644 --- a/cbios/ascii.180 +++ b/cbios/ascii.180 @@ -33,7 +33,7 @@ as0_dev: db 0 ;absolute device # db 0 ;relative device db 0 ;iflags - db 0 ;fflags + db M_CREAD+M_CRTS_IFLOW+M_CCTS_OFLOW ;fflags db M_CS8 ;cflags o.absdev equ 0 o.reldev equ 1 @@ -42,9 +42,15 @@ o.fflags equ 3 o.cflags equ 4 db 0 +o.stat equ 5 + b2m SXOFF,0 + b2m TDC1,1 + b2m TDC3,2 + b2m TOFF,7 db 0 oint.iflags equ as0_dev+o.iflags-s0.inbuf oint.fflags equ as0_dev+o.fflags-s0.inbuf +oint.stat equ as0_dev+o.stat-s0.inbuf mkbuf s0.rx_id, s0.inbuf, s0.rx_len mkbuf s0.tx_id, s0.outbuf,s0.tx_len @@ -58,7 +64,7 @@ as1_dev: db 0 ;absolute device # db 1 ;relative device db 0 ;iflags - db 0 ;fflags + db M_CREAD+M_IXOFF ;fflags db M_CS8 ;cflags db 0 @@ -105,14 +111,6 @@ IOCTL_MAX equ ($-ioctl_ftab)/2 ; asci_ioctl: - ld a,b - cp 1 - jr nz,asioc_1 - ld a,(INIDONE) - and 80h - cp INIDONEVAL - ret z -asioc_1: push hl ex (sp),ix ld (ix+o.absdev),b @@ -151,17 +149,17 @@ init_st: ld b,(ix+o.absdev) ld c,8 ; mlt bc ; - ld hl,@ctbl+7 ; + ld hl,@ctbl+6 ; add hl,bc ; + res IXON,(ix+o.fflags) + bit mbxon_bit,(hl) ;get cpm3 xon flag + jr z,$+6 + set IXON,(ix+o.fflags) + inc hl 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 - + call out_asci_reg_hl ld c,cntlb0 ld a,M_MPBT ;No MP Mode, X16 @@ -179,8 +177,8 @@ init_st: or a,M_RE+M_TE+M_RTS0+M_EFR ;Rx/Tx enable call out_asci_reg - push ix bit 0,(ix+o.reldev) + push ix jr nz,init_1 ld hl,rtxisvjmp0 ;rx/tx int vector ld (ivtab + IV$ASCI0),hl ; @@ -217,23 +215,24 @@ mod_tab: ; Get the current serial port settings. func_tcgeta: - ld a,d - or e - ld a,0ffh - jr z,fgeta_e + call chk_ptr + ld b,(ix+o.absdev) + ld c,8 ; + mlt bc ; + ld hl,@ctbl+6 ; + add hl,bc ; + res IXON,(ix+o.fflags) + bit mbxon_bit,(hl) ;get cpm3 xon flag + jr z,$+6 + set IXON,(ix+o.fflags) + inc hl 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 @@ -244,18 +243,13 @@ func_tcgeta: 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 chk_ptr call asci_stop @@ -269,8 +263,13 @@ func_tcseta: ld b,(ix+o.absdev) ld c,8 ; mlt bc ; - ld hl,@ctbl+7 ; + ld hl,@ctbl+6 ; add hl,bc ; + res mbxon_bit,(hl) + bit IXON,a + jr z,$+4 + set mbxon_bit,(hl) + inc hl call b_ld_a ld (ix+o.cflags),a and M_CBAUD @@ -281,10 +280,8 @@ func_tcseta: call init_st pop de xor a -fseta_e: ret - ;-------------------------------------------------------------- ; Allow the output buffer to drain @@ -370,6 +367,16 @@ func_tiocssoftcar: ;-------------------------------------------------------------- +chk_ptr: + ld a,e + or d + ret nz + cpl + pop hl + ret + +;-------------------------------------------------------------- + asci_stop: ld c,stat0 ;Disable rx/tx interrupts xor a ; @@ -382,6 +389,13 @@ asci_stop: ;-------------------------------------------------------------- asci_start: + bit 0,(ix+o.reldev) + jr nz,asci_st1 + in0 a,cntla0 ;asci0 + and ~M_RTS0 ;Activate RTS + or M_EFR + out0 (cntla0),a +asci_st1: ld c,stat0 ; ld a,M_RIE jr out_asci_reg @@ -395,19 +409,34 @@ asci_start: 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 + bit 0,(ix+o.reldev) + jr z,$+3 + inc c ld b,0 out (c),a pop bc ret +;-------------------------------------------------------------- +; output 16 bit value to asci0/1 register +; +; c: register address +; hl: value +; a destroyed + +out_asci_reg_hl: + ld a,b ;save b + bit 0,(ix+o.reldev) + jr z,$+4 + inc c + inc c + ld b,0 + out (c),l + inc c + out (c),h + ld b,a + ret + ;-------------------------------------------------------------- ; baud rate divider ; @@ -505,20 +534,52 @@ asci1_ista: ;-------------------------------------------------------------- ; Get an input character +if 0 asci0_inp: push ix ld ix,s0.inbuf ; - call ff_gech - ld a,b - cp s0.rx_len/4 + call ff_cnt + cp 32 jr nc,a0i_1 di in0 a,(cntla0) + res RTS0,a + set EFR,a + out0 (cntla0),a + ei +a0i_1: + call ff_get + pop ix + ret +endif + + +asci0_inp: + push ix + ld ix,s0.inbuf ; + call ff_gech + ld a,b ;remaining chrs in buffer + cp s0.rx_len/4 ; < 32? + jr nc,a0i_2 ; no, just get char + ld b,(ix+oint.fflags) ; yes, enable RTS if needed + bit CRTS_IFLOW,b ; yes, enable RTS if needed + jr z,a0i_1 ; no needed + di ; needed, enable + in0 a,(cntla0) and ~M_RTS0 ;assert RTS or M_EFR ;don't reset error flags ei out0 (cntla0),a a0i_1: + bit IXOFF,b ; XON/XOFF on input? + jr z,a0i_2 ; no + di + set TDC1,(ix+oint.stat) ; + in0 a,(stat0) ; + or M_TIE ; + ei + out0 (stat0),a ; +a0i_2: ld a,c pop ix ret @@ -530,6 +591,19 @@ asci1_inp: push ix ld ix,s1.inbuf ; call ff_gech + ld a,b ; remaining chars in buffer + cp s0.rx_len/4 ; == 25% full? + jr nz,a1i_2 ; no, just get char + bit IXOFF,(ix+oint.fflags) ; XON/XOFF on input? + jr z,a1i_2 ; no + di + set TDC1,(ix+oint.stat) ; + in0 a,(stat1) ; + or M_TIE ; + out0 (stat1),a ; + ei +a1i_2: + ld a,c ; get back the char pop ix ret @@ -556,34 +630,38 @@ asci1_osta: ;-------------------------------------------------------------- ; put character in c in buffer ; destroys hl, bc -; returns output char in a asci0_out: push ix ; ld ix,s0.outbuf ; call ff_puth pop ix ; + ld a,(as0_dev+o.stat) ;Transmitter stopped? + bit TOFF,a ; + ret nz ; yes di ; - in0 c,(stat0) ; - set TIE,c ; - out0 (stat0),c ; + in0 a,(stat0) ; + or M_TIE ; + out0 (stat0),a ; ei ; ret ;-------------------------------------------------------------- ; put character in c in buffer ; destroys hl, bc -; returns output char in a asci1_out: push ix ; ld ix,s1.outbuf ; call ff_puth pop ix ; + ld a,(as1_dev+o.stat) ;Transmitter stopped? + bit TOFF,a ; + ret nz ; yes di ; - in0 c,(stat1) ; - set TIE,c ; - out0 (stat1),c ; + in0 a,(stat1) ; + or M_TIE ; + out0 (stat1),a ; ei ; ret @@ -593,180 +671,159 @@ asci1_out: cseg rtxisvjmp0: call isv_sw - dw rxtxi0 + dw asci0_int + rtxisvjmp1: call isv_sw - dw rxtxi1 + dw asci1_int ;-------------------------------------------------------------- -; ASCI 0 Transmit/Receive interupt routines +; ASCI 0/1 Transmit/Receive interupt routines - dseg -rxtxi0: + .lall +asci_int macro dev push ix -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 + ld ix,s&dev&.inbuf ; + ld d,(ix+oint.fflags) +rxtxi&dev&_lp1: + in0 e,(stat&dev) ;get asci status + jp p,txi&dev ;RDRF == Bit 7 + + ; RX Interrupt - in0 a,(asext0) + res BREAK,e + in0 a,(asext&dev) ;get break status and M_BREAK - or e + or e ;merge to other error flags ld e,a - in0 d,(cntla0) ; - res EFR,d ; - out0 (cntla0),d + in0 a,(cntla&dev) ;reset all error flags + and ~M_EFR ; + out0 (cntla&dev),a ; + ld c,(ix+o.in_idx) ;get input index + ld b,0 ; + ld hl,s&dev&.inbuf ; + base = input buffer pointer + add hl,bc ; - ld c,(ix+o.in_idx) ; - ld b,0 - ld hl,s0.inbuf ; - add hl,bc - - in0 a,(rdr0) ; - ld (hl),a + in0 b,(rdr&dev) ;get char ;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 a,c ;increment buffer in pointer + ;todo: parity, framing, overrun error + ld (hl),b + bit IXON,d + jr z,rxi&dev&_x3 + ;test XON/XOFF + ld a,DC3 + cp b + jr nz,rxi&dev&_x1 + set TOFF,(ix+oint.stat) ;Stop transmitter + jr rxtxi&dev&_lp1 +rxi&dev&_x1: + ld a,DC1 + cp b + jr nz,rxi&dev&_x2 + res TOFF,(ix+oint.stat) ;Enable transmitter + jr rxi&dev&_txen +rxi&dev&_x2: + bit IXANY,d + jr z,rxi&dev&_x3 + res TOFF,(ix+oint.stat) ;Enable transmitter +rxi&dev&_x3: + + ld a,c ;increment input index inc a ; ld b,(ix+o.mask) ; and b ; ld c,a - sub (ix+o.out_idx) ; - 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,rxi0_noflow - - bit CRTS_IFLOW,e - jr z,rxtxi0_4 - - set EFR,d - set RTS0,d ;RTS inactive - out0 (cntla0),d ; - -rxtxi0_4: - bit IXOFF,e - jr z,rxtxi0_lp1 - ;todo: send XOFF - -rxi0_noflow: - jr rxtxi0_lp1 + sub (ix+o.out_idx) ;number of free places in buffer + jr z,rxtxi&dev&_lp1 ;buffer full? + and b ; + ld (ix+o.in_idx),c ; no, update input index + + cp s&dev&.tx_len*3/4 ;buffer now 75% full? + jr nz,rxtxi&dev&_lp1 + + if dev=0 ;only channel 0 has rts line + bit CRTS_IFLOW,d + jr z,rxi0_nocrts + in0 a,(cntla&dev) ; + or M_RTS0+M_EFR ;RTS inactive + out0 (cntla0),a ; +rxi0_nocrts: + endif + bit IXOFF,d + jr z,rxtxi&dev&_lp1 + ;send XOFF + set TDC3,(ix+oint.stat) +rxi&dev&_txen: + set TIE,e ; + out0 (stat&dev),e ; + jr rxtxi&dev&_lp1 -rxtxi0_1: - ld e,a +txi&dev: bit TDRE,e ;TX int? - jr z,rxtxi0_e ; - - - ld ix,s0.outbuf ; - - ld a,(ix+o.out_idx) ; - cp (ix+o.in_idx) ;if index.in == index.out - jr z,?0ti_2 ; buffer empty - - ld hl,s0.outbuf ; - ld c,a - ld b,0 - add hl,bc - ld b,(hl) - out0 (tdr0),b ; 7 + jr z,rxtxi&dev&_exit + + ; TX Interrupt + + ld a,(ix+oint.stat) ;check whether xon/xoff should be sent + tst M_TDC1+M_TDC3 ; + jr z,txi&dev&_char ; no + + ld l,DC3 ;prepare for xoff + bit TDC1,a ;request for xon (also) set? + jr z,txi&dev&_cch ; + ld l,DC1 ; +txi&dev&_cch: + out0 (tdr&dev),l ; + and ~(M_TDC1+M_TDC3) ;reset request flags + ld (ix+oint.stat),a ; + jp rxtxi&dev&_lp1 ; + +txi&dev&_char: + bit TOFF,(ix+oint.stat) + jr nz,txi&dev&_empty ; + + ld hl,s&dev&.outbuf+o.in_idx ;[in] + ld a,(hl) ; + inc hl ;[out] + ld c,(hl) ; + cp c ; + jr z,txi&dev&_empty ; + inc hl ;fifo base + ld b,0 ; + add hl,bc ; + ld a,(hl) ; + out0 (tdr&dev),a ; + inc c ; + ld a,(s&dev&.outbuf+o.mask); + and c ; + ld (s&dev&.outbuf+o.out_idx),a ; - inc a - and (ix+o.mask) - ld (ix+o.out_idx),a - jr rxtxi0_lp0 + jp rxtxi&dev&_lp1 -?0ti_2: +txi&dev&_empty: res TIE,e ;disable tx-int - out0 (stat0),e ; 5 + out0 (stat&dev),e ; -rxtxi0_e: +rxtxi&dev&_exit: pop ix ret - - -;-------------------------------------------------------------- -; ASCI 1 Transmit/Receive interupt routines + endm dseg -rxtxi1: - in0 e,(stat1) ;receive flag set? 5 - jp p,txi1_0 ; - - in0 d,(rdr1) ;todo: break detection 9 - bit FE,e ;framing error? - jr nz,??ri_1 - - push ix - ld ix,s1.inbuf ; - ld hl,s1.inbuf ; - ld c,(ix+o.in_idx) ; - ld b,0 - add hl,bc - ld (hl),d - - ld a,c ; - inc a - and (ix+o.mask) - cp (ix+o.out_idx) ; - jr z,$+5 ;skip if buffer is full - ld (ix+o.in_idx),a - pop ix -??ri_1: - in0 a,(cntla1) ; 1 - res EFR,a ; - out0 (cntla1),a ; 1 - ret - -txi1_0: - push ix - ld ix,s1.outbuf ; - - ld a,(ix+o.out_idx) ; - cp (ix+o.in_idx) ;if index.in == index.out - jr z,??ti_2 ; buffer empty +;-------------------------------------------------------------- +; ASCI 0 Transmit/Receive interupt routines - ld hl,s1.outbuf ; - ld c,a - ld b,0 - add hl,bc - ld l,(hl) - out0 (tdr1),l ; 7 - - inc a - and (ix+o.mask) - ld (ix+o.out_idx),a - jr ??ti_3 -??ti_2: - res TIE,e ;disable tx-int - out0 (stat1),e ; 5 -??ti_3: - pop ix - ret +asci0_int: + asci_int 0 +;-------------------------------------------------------------- +; ASCI 1 Transmit/Receive interupt routines +asci1_int: + asci_int 1 end