]> cloudbase.mooo.com Git - z180-stamp-cpm3.git/blobdiff - cbios/ascii.180
Remove 'inidone' initialisation bypassing.
[z180-stamp-cpm3.git] / cbios / ascii.180
index c9283548a631456676c0a9d3cc0963f4e8be9e94..3ffa931cf6da387cdf1725883377ccaa0c086d22 100644 (file)
-       page    200\r
 \r
 ; Interrupt drivers for ASCI0 and ASCI1\r
 \r
-       global  as0init\r
-       global  as0ista,as0inp\r
-       global  as0osta,as0out\r
-       global  as1init\r
-       global  as1ista,as1inp\r
-       global  as1osta,as1out\r
+       global  as0_dev,as1_dev\r
 \r
-       extrn   as_init\r
-       extrn   ff_empty,ff_get,ff_full,ff_put,ff_cnt\r
+       extrn   @ctbl,f_cpu\r
+       extrn   ff_empty,ff_get,ff_full,ff_put\r
+       extrn   ff_puth,ff_cnt,ff_gech\r
        extrn   bufinit\r
-       extrn   isv_sw\r
+       extrn   isv_sw,ijphl,add_hla,div32_r\r
+       extrn   b_st_a,b_ld_a\r
 \r
 \r
 \r
-       include config.inc\r
-       include z180reg.inc\r
+       maclib z180reg.inc\r
+       maclib config.inc\r
+       maclib ioctl.inc\r
+       maclib modebaud.inc\r
 \r
 \r
+       m2b     mbxon_bit,mb$xon$xoff\r
 \r
 ;-----------------------------------------------------\r
 \r
        dseg\r
 \r
+       dw      asci0_out\r
+       dw      asci0_osta\r
+       dw      asci0_inp\r
+       dw      asci0_ista\r
+       dw      asci_ioctl\r
+as0_dev:\r
+       db      0                       ;absolute device #\r
+       db      0                       ;relative device\r
+       db      0                       ;iflags\r
+       db      M_CREAD+M_CRTS_IFLOW+M_CCTS_OFLOW       ;fflags\r
+       db      M_CS8                   ;cflags\r
+o.absdev       equ     0\r
+o.reldev       equ     1\r
+o.iflags       equ     2\r
+o.fflags       equ     3\r
+o.cflags       equ     4\r
+\r
+       db      0\r
+o.stat         equ     5\r
+       b2m     SXOFF,0\r
+       b2m     TDC1,1\r
+       b2m     TDC3,2\r
+       b2m     TOFF,7\r
+       db      0\r
+oint.iflags    equ     as0_dev+o.iflags-s0.inbuf\r
+oint.fflags    equ     as0_dev+o.fflags-s0.inbuf\r
+oint.stat      equ     as0_dev+o.stat-s0.inbuf\r
        mkbuf   s0.rx_id, s0.inbuf, s0.rx_len\r
        mkbuf   s0.tx_id, s0.outbuf,s0.tx_len\r
+\r
+\r
+       dw      asci1_out\r
+       dw      asci1_osta\r
+       dw      asci1_inp\r
+       dw      asci1_ista\r
+       dw      asci_ioctl\r
+as1_dev:\r
+       db      0                       ;absolute device #\r
+       db      1                       ;relative device\r
+       db      0                       ;iflags\r
+       db      M_CREAD+M_IXOFF         ;fflags\r
+       db      M_CS8                   ;cflags\r
+\r
+       db      0\r
+       db      0\r
        mkbuf   s1.rx_id, s1.inbuf, s1.rx_len\r
-       mkbuf   s1.tx_id, s1.outbuf, s1.tx_len\r
+       mkbuf   s1.tx_id, s1.outbuf,s1.tx_len\r
 \r
 \r
 \r
        dseg\r
 \r
+\r
+ioctl_ftab:\r
+       dw      func_tcinit             ;(00h) CP/M 3 DEVINI function\r
+       dw      func_tcgeta             ;(01h) Get the current serial port settings.\r
+       dw      func_tcseta             ;(02h) Set the current serial port settings.\r
+       dw      func_tcsetaw            ;(03h) Allow the output buffer to drain\r
+       dw      func_tcsetaf            ;(04h) Allow the output buffer to drain, discard pending input\r
+       dw      func_tcsbrk             ;(05h) Sending a break (250ms .. 500ms)\r
+       dw      func_tcsbrkp            ;(06h) arg is timeinterval in 0.1sec\r
+       dw      func_tiocsbrk           ;(07h) Turn break on\r
+       dw      func_tioccbrk           ;(08h) Turn break off\r
+       dw      func_tcxonc             ;(09h) Software flow control (TCOOFF, TCOON, TCIOFF, TCION)\r
+       dw      func_tcflsh             ;(0Ah) Flush input/output buffer (TCIFLUSH, TCOFLUSH, TCIOFLUSH)\r
+       dw      func_fionread           ;(0Bh) Get the number of bytes in the input buffer.\r
+       dw      func_tiocoutq           ;(0Ch) Get the number of bytes in the output buffer.\r
+       dw      func_tiocmget           ;(0Dh) get the status of modem bits.\r
+       dw      func_tiocmbis           ;(0Eh) set the indicated modem bits.\r
+       dw      func_tiocmbic           ;(0Fh) clear the indicated modem bits.\r
+       dw      func_tiocmset           ;(10h) set the status of modem bits.\r
+       dw      func_tiocgsoftcar       ;(11h) Get the status of the CLOCAL flag in the c_cflag field\r
+       dw      func_tiocssoftcar       ;(12h) Set the CLOCAL flag when  *argp  is nonzero, and clear it otherwise.\r
+\r
+IOCTL_MAX equ  ($-ioctl_ftab)/2\r
+       dw      nofunc\r
+\r
+\r
 ;--------------------------------------------------------------\r
-; Init Serial I/O for input and output (ASCI 0/1)\r
 ;\r
-; b: device number\r
+; b:  device number\r
+; c:  command\r
+; de: ioctl arg pointer\r
+; hl: ptr to driver local data\r
 ;\r
 \r
+asci_ioctl:\r
+       push    hl\r
+       ex      (sp),ix\r
+       ld      (ix+o.absdev),b\r
+       ld      hl,ioctl_ftab\r
+       ld      a,IOCTL_MAX\r
+       cp      c\r
+       jr      c,$+3\r
+        ld     a,c\r
+       add     a,a\r
+       call    add_hla\r
+       ld      a,(hl)\r
+       inc     hl\r
+       ld      h,(hl)\r
+       ld      l,a\r
+       call    ijphl\r
+       pop     ix\r
+nofunc:\r
+       or      a\r
+       ret\r
 \r
-;ser.init:\r
-;      ld      a,i\r
-;      push    af                      ;save IFF\r
-;      di\r
-;---\r
-;      pop     af\r
-;      ret     po\r
-;      ei\r
-;      ret                             ;\r
-\r
-as0init:\r
-       xor     a                       ;\r
-       out0    (stat0),a               ;Disable rx/tx interrupts\r
-       ld      c,0                     ;asci channel number\r
-       call    as_init\r
-       ld hl,rtxisvjmp0                ;rx/tx int vector\r
-       ld (ivtab + IV$ASCI0),hl        ;\r
+;--------------------------------------------------------------\r
+; CP/M 3 DEVINI function\r
+; Init Serial I/O for input and output (ASCI 0/1)\r
 \r
+func_tcinit:\r
+       call    asci_stop\r
+\r
+init_st:\r
+       ld      c,asext0                ;Enable baud rate generator\r
+       ld      a,M_BRGMOD+M_DCD0DIS    ; +M_CTS0DIS +M_BREAKEN\r
+       bit     CCTS_OFLOW,(ix+o.fflags)\r
+       jr      nz,$+4\r
+        or     M_CTS0DIS\r
+       call    out_asci_reg\r
+\r
+       ld      b,(ix+o.absdev)\r
+       ld      c,8                     ;\r
+       mlt     bc                      ;\r
+       ld      hl,@ctbl+6              ;\r
+       add     hl,bc                   ;\r
+       res     IXON,(ix+o.fflags)\r
+       bit     mbxon_bit,(hl)          ;get cpm3 xon flag\r
+       jr      z,$+6\r
+        set    IXON,(ix+o.fflags)\r
+       inc     hl\r
+       ld      a,(hl)                  ;get baudrate index\r
+       call    as_br_div\r
+       ld      c,astc0l\r
+       call    out_asci_reg_hl\r
+\r
+       ld      c,cntlb0\r
+       ld      a,M_MPBT                ;No MP Mode, X16\r
+       bit     PARODD,(ix+o.iflags)\r
+       jr      z,$+4\r
+        or     M_PEO\r
+       call    out_asci_reg\r
+\r
+       ld      c,cntla0\r
+       ld      a,(ix+o.cflags)\r
+       srlan   CS8\r
+       ld      hl,mod_tab\r
+       call    add_hla\r
+       ld      a,(hl)\r
+       or      a,M_RE+M_TE+M_RTS0+M_EFR ;Rx/Tx enable\r
+       call    out_asci_reg\r
+\r
+       bit     0,(ix+o.reldev)\r
+       push    ix\r
+       jr      nz,init_1\r
+       ld      hl,rtxisvjmp0           ;rx/tx int vector\r
+       ld      (ivtab + IV$ASCI0),hl   ;\r
+       ld      ix,s0.outbuf\r
+       call    bufinit\r
        ld      ix,s0.inbuf\r
+       jr      init_2\r
+init_1:\r
+       ld      hl,rtxisvjmp1           ;rx/tx int vector\r
+       ld      (ivtab + IV$ASCI1),hl   ;\r
+       ld      ix,s1.outbuf\r
        call    bufinit\r
-       ld      ix,s0.outbuf\r
+       ld      ix,s1.inbuf\r
+init_2:\r
        call    bufinit\r
-       ld      a,M_RIE\r
-       out0    (stat0),a               ;Enable rx interrupts\r
+       pop     ix\r
+       call    asci_start\r
+       ret\r
+\r
+;--------------------------------------------------------------\r
+\r
+mod_tab:\r
+       db      000B                    ; 7N1\r
+       db      100B                    ; 8N1\r
+       db      001B                    ; 7N2\r
+       db      101B                    ; 8N2\r
+       db      010B                    ; 7P1\r
+       db      110B                    ; 8P1\r
+       db      011B                    ; 7P2\r
+       db      111B                    ; 8P2\r
+\r
+\r
+;--------------------------------------------------------------\r
+; Get the current serial port settings.\r
+\r
+func_tcgeta:\r
+       call    chk_ptr\r
+\r
+       ld      b,(ix+o.absdev)\r
+       ld      c,8                     ;\r
+       mlt     bc                      ;\r
+       ld      hl,@ctbl+6              ;\r
+       add     hl,bc                   ;\r
+       res     IXON,(ix+o.fflags)\r
+       bit     mbxon_bit,(hl)          ;get cpm3 xon flag\r
+       jr      z,$+6\r
+        set    IXON,(ix+o.fflags)\r
+       inc     hl\r
+       ld      a,(ix+o.iflags)\r
+       call    b_st_a\r
+       inc     de\r
+       ld      a,(ix+o.fflags)\r
+       call    b_st_a\r
+       inc     de\r
+       ld      a,(hl)                  ;get baudrate index\r
+       and     M_CBAUD\r
+       ld      b,a\r
+       ld      a,(ix+o.cflags)\r
+       and     ~M_CBAUD\r
+       or      b\r
+       call    b_st_a\r
+       dec     de\r
+       dec     de\r
+       xor     a\r
+       ret\r
+\r
+;--------------------------------------------------------------\r
+; Set the current serial port settings.\r
+\r
+func_tcseta:\r
+       call    chk_ptr\r
+\r
+       call    asci_stop\r
+\r
+       call    b_ld_a\r
+       ld      (ix+o.iflags),a\r
+       inc     de\r
+       call    b_ld_a\r
+       ld      (ix+o.fflags),a\r
+       inc     de\r
+\r
+       ld      b,(ix+o.absdev)\r
+       ld      c,8                     ;\r
+       mlt     bc                      ;\r
+       ld      hl,@ctbl+6              ;\r
+       add     hl,bc                   ;\r
+       res     mbxon_bit,(hl)\r
+       bit     IXON,a\r
+       jr      z,$+4\r
+        set    mbxon_bit,(hl)\r
+       inc     hl\r
+       call    b_ld_a\r
+       ld      (ix+o.cflags),a\r
+       and     M_CBAUD\r
+       ld      (hl),a                  ;set baudrate index\r
+       dec     de\r
+       dec     de\r
+       push    de\r
+       call    init_st\r
+       pop     de\r
+       xor     a\r
+       ret\r
+\r
+;--------------------------------------------------------------\r
+; Allow the output buffer to drain\r
+\r
+func_tcsetaw:\r
+\r
+;--------------------------------------------------------------\r
+; Allow the output buffer to drain, discard pending input\r
+\r
+func_tcsetaf:\r
+\r
+;--------------------------------------------------------------\r
+; Sending a break (250ms .. 500ms)\r
+\r
+func_tcsbrk:\r
+\r
+;--------------------------------------------------------------\r
+; arg is timeinterval in 0.1sec\r
+\r
+func_tcsbrkp:\r
+\r
+;--------------------------------------------------------------\r
+; Turn break on\r
+\r
+func_tiocsbrk:\r
+\r
+;--------------------------------------------------------------\r
+; Turn break off\r
+\r
+func_tioccbrk:\r
+\r
+;--------------------------------------------------------------\r
+; Software flow control (TCOOFF, TCOON, TCIOFF, TCION)\r
+\r
+func_tcxonc:\r
+\r
+;--------------------------------------------------------------\r
+; Flush input/output buffer (TCIFLUSH, TCOFLUSH, TCIOFLUSH)\r
+\r
+func_tcflsh:\r
+\r
+;--------------------------------------------------------------\r
+; Get the number of bytes in the input buffer.\r
+\r
+func_fionread:\r
+\r
+;--------------------------------------------------------------\r
+; Get the number of bytes in the output buffer.\r
+\r
+func_tiocoutq:\r
+\r
+;--------------------------------------------------------------\r
+; get the status of modem bits.\r
+\r
+func_tiocmget:\r
+\r
+;--------------------------------------------------------------\r
+; set the indicated modem bits.\r
+\r
+func_tiocmbis:\r
+\r
+;--------------------------------------------------------------\r
+; clear the indicated modem bits.\r
+\r
+func_tiocmbic:\r
+\r
+;--------------------------------------------------------------\r
+; set the status of modem bits.\r
+\r
+func_tiocmset:\r
+\r
+;--------------------------------------------------------------\r
+; Get the status of the CLOCAL flag in the c_cflag field\r
+\r
+func_tiocgsoftcar:\r
+\r
+;--------------------------------------------------------------\r
+; Set the CLOCAL flag when  *argp  is nonzero, and clear it otherwise.\r
+\r
+func_tiocssoftcar:\r
+\r
+       or      0ffh\r
+       ret\r
+\r
+;--------------------------------------------------------------\r
+\r
+chk_ptr:\r
+       ld      a,e\r
+       or      d\r
+       ret     nz\r
+       cpl\r
+       pop     hl\r
        ret\r
 \r
-as1init:\r
+;--------------------------------------------------------------\r
+\r
+asci_stop:\r
+       ld      c,stat0                 ;Disable rx/tx interrupts\r
        xor     a                       ;\r
-       out0    (stat1),a               ;Disable rx/tx interrupts\r
-       ld      c,1                     ;asci channel number\r
-       call    as_init\r
+       call    out_asci_reg\r
 \r
-       ld hl,rtxisvjmp1                ;rx/tx int vector\r
-       ld (ivtab + IV$ASCI1),hl        ;\r
+       ld      c,cntla0                ;Disable receiver and transmitter\r
+       ld      a,M_RTS0+M_EFR          ;RTS/CKA1\r
+       jr      out_asci_reg\r
 \r
-       push    ix\r
-       ld      ix,s1.inbuf\r
-       call    bufinit\r
-       ld      ix,s1.outbuf\r
-       call    bufinit\r
-       pop     ix\r
+;--------------------------------------------------------------\r
+\r
+asci_start:\r
+       bit     0,(ix+o.reldev)\r
+       jr      nz,asci_st1\r
+       in0     a,cntla0                ;asci0\r
+       and     ~M_RTS0                 ;Activate RTS\r
+       or      M_EFR\r
+       out0    (cntla0),a\r
+asci_st1:\r
+       ld      c,stat0                 ;\r
        ld      a,M_RIE\r
-       out0    (stat1),a               ;Enable rx interrupts\r
+       jr      out_asci_reg\r
+\r
+;--------------------------------------------------------------\r
+; output to asci0/1 register\r
+;\r
+; c:  register address\r
+; a:  value\r
+;\r
+\r
+out_asci_reg:\r
+       push    bc\r
+       bit     0,(ix+o.reldev)\r
+       jr      z,$+3\r
+        inc    c\r
+       ld      b,0\r
+       out     (c),a\r
+       pop     bc\r
        ret\r
 \r
+;--------------------------------------------------------------\r
+; output 16 bit value to asci0/1 register\r
+;\r
+; c:   register address\r
+; hl:  value\r
+; a destroyed\r
+\r
+out_asci_reg_hl:\r
+       ld      a,b                     ;save b\r
+       bit     0,(ix+o.reldev)\r
+       jr      z,$+4\r
+        inc    c\r
+        inc    c\r
+       ld      b,0\r
+       out     (c),l\r
+       inc     c\r
+       out     (c),h\r
+       ld      b,a\r
+       ret\r
 \r
-       cseg\r
-rtxisvjmp0:\r
-       call    isv_sw\r
-       dw      rxtxi0\r
-rtxisvjmp1:\r
-       call    isv_sw\r
-       dw      rxtxi1\r
+;--------------------------------------------------------------\r
+; baud rate divider\r
+;\r
+;   a: index\r
+; return\r
+;   hl: divider\r
+\r
+as_br_div:\r
+       push    de\r
+       push    bc\r
+       and     0fh\r
+       add     a,a                     ;get factor\r
+       ld      hl,bd150_tab\r
+       call    add_hla\r
+       ld      c,(hl)\r
+       inc     hl\r
+       ld      b,(hl)\r
+       ld      hl,(f_cpu)\r
+       ld      de,(f_cpu+2)\r
+       call    div32_r\r
+       ld      bc,32*150\r
+       call    div32_r\r
+       ld      de,2\r
+       or      a\r
+       sbc     hl,de\r
+       pop     bc\r
+       pop     de\r
+       ret     nc\r
+       ld      hl,0\r
+       ret\r
+\r
+bd150_tab:\r
+;              factor          index   baudrate        orig. cp/m\r
+       dw      19200/150       ; 0     19200           -\r
+       dw      28800/150       ; 1     28800           50\r
+       dw      38400/150       ; 2     38400           75\r
+       dw      57600/150       ; 3     57600           110\r
+       dw      11520/15        ; 4     115200          134.5\r
+       dw      150/150         ; 5     150\r
+       dw      300/150         ; 6     300\r
+       dw      600/150         ; 7     600\r
+       dw      1200/150        ; 8     1200\r
+       dw      1800/150        ; 9     1800\r
+       dw      2400/150        ;10     2400\r
+       dw      3600/150        ;11     3600\r
+       dw      4800/150        ;12     4800\r
+       dw      7200/150        ;13     7200\r
+       dw      9600/150        ;14     9600\r
+       dw      19200/150       ;15     19200\r
+\r
+\r
+;--------------------------------------------------------------\r
+\r
+   if 0\r
+\r
+initab0:\r
+       db      1,stat0,0               ;Disable rx/tx interrupts\r
+                                       ;Enable baud rate generator\r
+       db      1,asext0,M_BRGMOD+M_DCD0DIS ; +M_CTS0DIS\r
+       db      2,astc0l\r
+init_br_off equ $ - initab0\r
+       dw      28\r
+       db      1,cntlb0,M_MPBT         ;No MP Mode, X16\r
+       db      1,cntla0,M_RE+M_TE+M_MOD2 ;Rx/Tx enable, 8N1\r
+       db      0\r
+\r
+initab1:\r
+       db      1,stat1,0               ;Disable rx/tx ints, disable CTS1\r
+       db      1,asext1,M_BRGMOD       ;Enable baud rate generator\r
+       db      2,astc1l,low 3, high 3\r
+       db      1,cntlb1,M_MPBT         ;No MP Mode, X16\r
+       db      1,cntla1,M_RE+M_TE+M_MOD2 ;Rx/Tx enable, 8N1\r
+       db      0\r
+   endif\r
 \r
 ;--------------------------------------------------------------\r
 \r
        dseg\r
-as0ista:\r
+asci0_ista:\r
        push    ix\r
        ld      ix,s0.inbuf             ;\r
        call    ff_empty\r
@@ -107,7 +524,7 @@ as0ista:
 \r
 ;--------------------------------------------------------------\r
 \r
-as1ista:\r
+asci1_ista:\r
        push    ix\r
        ld      ix,s1.inbuf             ;\r
        call    ff_empty\r
@@ -117,36 +534,83 @@ as1ista:
 ;--------------------------------------------------------------\r
 ; Get an input character\r
 \r
-as0inp:\r
+if 0\r
+asci0_inp:\r
        push    ix\r
        ld      ix,s0.inbuf             ;\r
        call    ff_cnt\r
        cp      32\r
-       jr      c,a0i_1\r
+       jr      nc,a0i_1\r
        di\r
        in0     a,(cntla0)\r
        res     RTS0,a\r
+       set     EFR,a\r
        out0    (cntla0),a\r
        ei\r
 a0i_1:\r
        call    ff_get\r
        pop     ix\r
        ret\r
+endif\r
+\r
+\r
+asci0_inp:\r
+       push    ix\r
+       ld      ix,s0.inbuf             ;\r
+       call    ff_gech\r
+       ld      a,b                     ;remaining chrs in buffer\r
+       cp      s0.rx_len/4             ; < 32?\r
+       jr      nc,a0i_2                        ; no, just get char\r
+       ld      b,(ix+oint.fflags)      ; yes, enable RTS if needed\r
+       bit     CRTS_IFLOW,b            ; yes, enable RTS if needed\r
+       jr      z,a0i_1                 ; no needed\r
+       di                              ; needed, enable\r
+       in0     a,(cntla0)\r
+       and     ~M_RTS0                 ;assert RTS\r
+       or      M_EFR                   ;don't reset error flags\r
+       ei\r
+       out0    (cntla0),a\r
+a0i_1:\r
+       bit     IXOFF,b                 ; XON/XOFF on input?\r
+       jr      z,a0i_2                 ; no\r
+       di\r
+       set     TDC1,(ix+oint.stat)     ;\r
+       in0     a,(stat0)               ;\r
+       or      M_TIE                   ;\r
+       ei\r
+       out0    (stat0),a               ;\r
+a0i_2:\r
+       ld      a,c\r
+       pop     ix\r
+       ret\r
 \r
 ;--------------------------------------------------------------\r
 ; Get an input character\r
 \r
-as1inp:\r
+asci1_inp:\r
        push    ix\r
        ld      ix,s1.inbuf             ;\r
-       call    ff_get\r
+       call    ff_gech\r
+       ld      a,b                     ; remaining chars in buffer\r
+       cp      s0.rx_len/4             ; == 25% full?\r
+       jr      nz,a1i_2                ; no, just get char\r
+       bit     IXOFF,(ix+oint.fflags)  ; XON/XOFF on input?\r
+       jr      z,a1i_2                 ; no\r
+       di\r
+       set     TDC1,(ix+oint.stat)     ;\r
+       in0     a,(stat1)               ;\r
+       or      M_TIE                   ;\r
+       out0    (stat1),a               ;\r
+       ei\r
+a1i_2:\r
+       ld      a,c                     ; get back the char\r
        pop     ix\r
        ret\r
 \r
 ;--------------------------------------------------------------\r
 ; Output status\r
 \r
-as0osta:\r
+asci0_osta:\r
        push    ix\r
        ld      ix,s0.outbuf            ;\r
        call    ff_full\r
@@ -156,7 +620,7 @@ as0osta:
 ;--------------------------------------------------------------\r
 ; Output status\r
 \r
-as1osta:\r
+asci1_osta:\r
        push    ix\r
        ld      ix,s1.outbuf            ;\r
        call    ff_full\r
@@ -166,165 +630,200 @@ as1osta:
 ;--------------------------------------------------------------\r
 ; put character in c in buffer\r
 ; destroys hl, bc\r
-; returns output char in a\r
 \r
-as0out:\r
+asci0_out:\r
        push    ix                      ;\r
        ld      ix,s0.outbuf            ;\r
-       call    ff_put\r
+       call    ff_puth\r
+       pop     ix                      ;\r
+       ld      a,(as0_dev+o.stat)      ;Transmitter stopped?\r
+       bit     TOFF,a                  ;\r
+       ret     nz                      ;  yes\r
        di                              ;\r
-       in0     c,(stat0)               ;\r
-       set     TIE,c                   ;\r
-       out0    (stat0),c               ;\r
+       in0     a,(stat0)               ;\r
+       or      M_TIE                   ;\r
+       out0    (stat0),a               ;\r
        ei                              ;\r
-       pop     ix                      ;\r
        ret\r
 \r
 ;--------------------------------------------------------------\r
 ; put character in c in buffer\r
 ; destroys hl, bc\r
-; returns output char in a\r
 \r
-as1out:\r
+asci1_out:\r
        push    ix                      ;\r
        ld      ix,s1.outbuf            ;\r
-       call    ff_put\r
+       call    ff_puth\r
+       pop     ix                      ;\r
+       ld      a,(as1_dev+o.stat)      ;Transmitter stopped?\r
+       bit     TOFF,a                  ;\r
+       ret     nz                      ;  yes\r
        di                              ;\r
-       in0     c,(stat1)               ;\r
-       set     TIE,c                   ;\r
-       out0    (stat1),c               ;\r
+       in0     a,(stat1)               ;\r
+       or      M_TIE                   ;\r
+       out0    (stat1),a               ;\r
        ei                              ;\r
-       pop     ix                      ;\r
        ret\r
 \r
 \r
-;------------------------------------------\r
-; ASCI 1 Transmit/Receive interupt routines\r
-\r
-       dseg\r
-rxtxi0:\r
-       in0     e,(stat0)               ;receive flag set?      5\r
-       jp      p,txisv0                ;\r
-\r
-       in0     a,(rdr0)                ;todo: break detection  9\r
-       in0     d,(cntla0)              ;                       1\r
-       res     EFR,d                   ;\r
-       bit     FE,e                    ;framing error?\r
-       jr      nz,?0ri_1\r
+;--------------------------------------------------------------\r
 \r
-       push    ix\r
-       ld      ix,s0.inbuf             ;\r
-       ld      hl,s0.inbuf             ;\r
-       ld      c,(ix+o.in_idx)         ;\r
-       ld      b,0\r
-       add     hl,bc\r
-       ld      (hl),a\r
+       cseg\r
+rtxisvjmp0:\r
+       call    isv_sw\r
+       dw      asci0_int\r
 \r
-       ld      a,c                     ;\r
-       inc     a\r
-       and     (ix+o.mask)\r
-       ld      c,a\r
-       sub     (ix+o.out_idx)          ;\r
-       jr      z,$+5                   ;skip if buffer is full\r
-       ld      (ix+o.in_idx),c\r
-       jr      nc,$+6\r
-       add     (ix+o.mask)\r
-       inc     a\r
-       cp      96\r
-       jr      c,$+4\r
-       set     RTS0,d                  ;RTS inactive\r
-       pop     ix\r
-?0ri_1:\r
-       out0    (cntla0),d              ;                       1\r
+rtxisvjmp1:\r
+       call    isv_sw\r
+       dw      asci1_int\r
 \r
-txisv0:\r
-       bit     TDRE,e\r
-       ret     z\r
+;--------------------------------------------------------------\r
+; ASCI 0/1 Transmit/Receive interupt routines\r
 \r
+       .lall\r
+asci_int macro dev\r
        push    ix\r
-       ld      ix,s0.outbuf            ;\r
-\r
-       ld      a,(ix+o.out_idx)        ;\r
-       cp      (ix+o.in_idx)           ;if index.in == index.out\r
-       jr      z,?0ti_2                ;       buffer empty\r
-\r
-       ld      hl,s0.outbuf            ;\r
+       ld      ix,s&dev&.inbuf         ;\r
+       ld      d,(ix+oint.fflags)\r
+rxtxi&dev&_lp1:\r
+       in0     e,(stat&dev)            ;get asci status\r
+       jp      p,txi&dev               ;RDRF == Bit 7\r
+\r
+       ; RX Interrupt\r
+\r
+       res     BREAK,e\r
+       in0     a,(asext&dev)           ;get break status\r
+       and     M_BREAK\r
+       or      e                       ;merge to other error flags\r
+       ld      e,a\r
+\r
+       in0     a,(cntla&dev)           ;reset all error flags\r
+       and     ~M_EFR                  ;\r
+       out0    (cntla&dev),a           ;\r
+\r
+       ld      c,(ix+o.in_idx)         ;get input index\r
+       ld      b,0                     ;\r
+       ld      hl,s&dev&.inbuf         ;  + base = input buffer pointer\r
+       add     hl,bc                   ;\r
+\r
+       in0     b,(rdr&dev)             ;get char\r
+                                       ;todo: break detection\r
+                                       ;todo: parity, framing, overrun error\r
+       ld      (hl),b\r
+       bit     IXON,d\r
+       jr      z,rxi&dev&_x3\r
+                                       ;test XON/XOFF\r
+       ld      a,DC3\r
+       cp      b\r
+       jr      nz,rxi&dev&_x1\r
+       set     TOFF,(ix+oint.stat)     ;Stop transmitter\r
+       jr      rxtxi&dev&_lp1\r
+rxi&dev&_x1:\r
+       ld      a,DC1\r
+       cp      b\r
+       jr      nz,rxi&dev&_x2\r
+       res     TOFF,(ix+oint.stat)     ;Enable transmitter\r
+       jr      rxi&dev&_txen\r
+rxi&dev&_x2:\r
+       bit     IXANY,d\r
+       jr      z,rxi&dev&_x3\r
+       res     TOFF,(ix+oint.stat)     ;Enable transmitter\r
+rxi&dev&_x3:\r
+\r
+       ld      a,c                     ;increment input index\r
+       inc     a                       ;\r
+       ld      b,(ix+o.mask)           ;\r
+       and     b                       ;\r
        ld      c,a\r
-       ld      b,0\r
-       add     hl,bc\r
-       ld      l,(hl)\r
-       out0    (tdr0),l                ;                       7\r
-\r
-       inc     a\r
-       and     (ix+o.mask)\r
-       ld      (ix+o.out_idx),a\r
-       jr      ?0ti_3\r
-?0ti_2:\r
-       res     TIE,e                   ;disable tx-int\r
-       out0    (stat0),e               ;                       5\r
-?0ti_3:\r
-       pop     ix\r
-       ret\r
-\r
-;------------------------------------------\r
-; ASCI 1 Transmit/Receive interupt routines\r
-\r
-       dseg\r
-rxtxi1:\r
-       in0     e,(stat1)               ;receive flag set?      5\r
-       jp      p,txisv1                ;\r
 \r
-       in0     d,(rdr1)                ;todo: break detection  9\r
-       bit     FE,e                    ;framing error?\r
-       jr      nz,??ri_1\r
+       sub     (ix+o.out_idx)          ;number of free places in buffer\r
+       jr      z,rxtxi&dev&_lp1        ;buffer full?\r
+       and     b                       ;\r
+       ld      (ix+o.in_idx),c         ;  no, update input index\r
+\r
+       cp      s&dev&.tx_len*3/4       ;buffer now 75% full?\r
+       jr      nz,rxtxi&dev&_lp1\r
+\r
+   if dev=0                            ;only channel 0 has rts line\r
+       bit     CRTS_IFLOW,d\r
+       jr      z,rxi0_nocrts\r
+       in0     a,(cntla&dev)           ;\r
+       or      M_RTS0+M_EFR            ;RTS inactive\r
+       out0    (cntla0),a              ;\r
+rxi0_nocrts:\r
+   endif\r
+\r
+       bit     IXOFF,d\r
+       jr      z,rxtxi&dev&_lp1\r
+                                       ;send XOFF\r
+       set     TDC3,(ix+oint.stat)\r
+rxi&dev&_txen:\r
+       set     TIE,e                   ;\r
+       out0    (stat&dev),e            ;\r
+       jr      rxtxi&dev&_lp1\r
+\r
+txi&dev:\r
+       bit     TDRE,e                  ;TX int?\r
+       jr      z,rxtxi&dev&_exit\r
+\r
+       ; TX Interrupt\r
+\r
+       ld      a,(ix+oint.stat)        ;check whether xon/xoff should be sent\r
+       tst     M_TDC1+M_TDC3           ;\r
+       jr      z,txi&dev&_char         ;  no\r
+\r
+       ld      l,DC3                   ;prepare for xoff\r
+       bit     TDC1,a                  ;request for xon (also) set?\r
+       jr      z,txi&dev&_cch          ;\r
+       ld      l,DC1                   ;\r
+txi&dev&_cch:\r
+       out0    (tdr&dev),l             ;\r
+       and     ~(M_TDC1+M_TDC3)        ;reset request flags\r
+       ld      (ix+oint.stat),a        ;\r
+       jp      rxtxi&dev&_lp1          ;\r
+\r
+txi&dev&_char:\r
+       bit     TOFF,(ix+oint.stat)\r
+       jr      nz,txi&dev&_empty       ;\r
+\r
+       ld      hl,s&dev&.outbuf+o.in_idx ;[in]\r
+       ld      a,(hl)                  ;\r
+       inc     hl                      ;[out]\r
+       ld      c,(hl)                  ;\r
+       cp      c                       ;\r
+       jr      z,txi&dev&_empty        ;\r
+       inc     hl                      ;fifo base\r
+       ld      b,0                     ;\r
+       add     hl,bc                   ;\r
+       ld      a,(hl)                  ;\r
+       out0    (tdr&dev),a             ;\r
+       inc     c                       ;\r
+       ld      a,(s&dev&.outbuf+o.mask);\r
+       and     c                       ;\r
+       ld      (s&dev&.outbuf+o.out_idx),a ;\r
+\r
+       jp      rxtxi&dev&_lp1\r
+\r
+txi&dev&_empty:\r
+       res     TIE,e                   ;disable tx-int\r
+       out0    (stat&dev),e            ;\r
 \r
-       push    ix\r
-       ld      ix,s1.inbuf             ;\r
-       ld      hl,s1.inbuf             ;\r
-       ld      c,(ix+o.in_idx)         ;\r
-       ld      b,0\r
-       add     hl,bc\r
-       ld      (hl),d\r
-\r
-       ld      a,c                     ;\r
-       inc     a\r
-       and     (ix+o.mask)\r
-       cp      (ix+o.out_idx)          ;\r
-       jr      z,$+5                   ;skip if buffer is full\r
-       ld      (ix+o.in_idx),a\r
+rxtxi&dev&_exit:\r
        pop     ix\r
-??ri_1:\r
-       in0     a,(cntla1)              ;                       1\r
-       res     EFR,a                   ;\r
-       out0    (cntla1),a              ;                       1\r
        ret\r
+       endm\r
 \r
-txisv1:\r
-       push    ix\r
-       ld      ix,s1.outbuf            ;\r
-\r
-       ld      a,(ix+o.out_idx)        ;\r
-       cp      (ix+o.in_idx)           ;if index.in == index.out\r
-       jr      z,??ti_2                ;       buffer empty\r
+       dseg\r
+;--------------------------------------------------------------\r
+; ASCI 0 Transmit/Receive interupt routines\r
 \r
-       ld      hl,s1.outbuf            ;\r
-       ld      c,a\r
-       ld      b,0\r
-       add     hl,bc\r
-       ld      l,(hl)\r
-       out0    (tdr1),l                ;                       7\r
-\r
-       inc     a\r
-       and     (ix+o.mask)\r
-       ld      (ix+o.out_idx),a\r
-       jr      ??ti_3\r
-??ti_2:\r
-       res     TIE,e                   ;disable tx-int\r
-       out0    (stat1),e               ;                       5\r
-??ti_3:\r
-       pop     ix\r
-       ret\r
+asci0_int:\r
+       asci_int 0\r
 \r
+;--------------------------------------------------------------\r
+; ASCI 1 Transmit/Receive interupt routines\r
 \r
+asci1_int:\r
+       asci_int 1\r
 \r
        end\r