home *** CD-ROM | disk | FTP | other *** search
/ kermit.columbia.edu / kermit.columbia.edu.tar / kermit.columbia.edu / tpdoskermit / async.sal < prev    next >
Text File  |  1991-04-17  |  15KB  |  742 lines

  1. ; ASYNC.SAL Driver for RS232 fra Turbo Pascal V4
  2. ; Version 2.0
  3. ;     Date: 87-11-19, 20:10
  4.  
  5.             saljmp short
  6.             salcmp unsigned
  7.             salmac :=     mov &-,&+
  8.  
  9. include pascal.mac
  10.  
  11. buffers struc
  12.     PortNr  dw ?
  13.     IntNr   dw ?
  14.  
  15.     oldModemCntrReg db ?
  16.     oldLevel        db ?
  17.     oldVector       dd ?
  18.  
  19.     Inx     dw ?
  20.     R_Buf2  dw ?
  21.     OutX    dw ?
  22.     SizeX   dw ?
  23.     LimitX  dw ?
  24.  
  25.     InT     dw ?
  26.     OutT    dw ?
  27.     T_Buf2  dw ?
  28.     SizeT   dw ?
  29.     Send_T  dw ?
  30.  
  31.     Show_X  dw ?
  32.     Show_X2 dw ?
  33.  
  34.     Toggle_Xoff dd ?
  35.     RLS_user    dd ?
  36.     MODEM_user  dd ?
  37.  
  38.     Ctrl_P  db ?
  39.  
  40.     UseTInt db ?
  41.     HostX   db ?
  42.     Bfull   db ?
  43.  
  44.     AutoX   db ?
  45.     AltX    db ?
  46.  
  47.     Xoff1C  db ?
  48.     Xoff2C  db ?
  49.     Xon1C   db ?
  50.     Xon2C   db ?
  51.  
  52.     Line_Status  db ?
  53.     MODEM_Status db ?
  54.  
  55.     WaitTX  db ?
  56.     Int_Mask db ?
  57.  
  58. buffers ends
  59.  
  60. DXofs MACRO ofs
  61.     mif ofs
  62.         ife ofs - 1
  63.             inc dx
  64.         else
  65.             ife ofs + 1
  66.                 dec dx
  67.             else
  68.                 add dx,ofs
  69.             endif
  70.         endif
  71.     endif
  72. ENDM
  73.  
  74. InPort MACRO ofs
  75.     dx := [bx.PortNr]
  76.     DXofs <ofs>
  77.     in al,dx
  78. ENDM
  79.  
  80. OutPort MACRO ofs
  81.     dx := [bx.PortNr]
  82.     DXofs <ofs>
  83.     out dx,al
  84. ENDM
  85.  
  86. InPOfs MACRO ofs
  87.     DXofs <ofs>
  88.     in al,dx
  89. ENDM
  90.  
  91. OutPOfs MACRO ofs
  92.     DXofs <ofs>
  93.     out dx,al
  94. ENDM
  95.  
  96.     LineContrReg    = 3   ; (* to specify format of transmitted data *)
  97.     LowBaudRateDiv  = 0   ; (* lower byte of divisor to select baud rate *)
  98.     HighBaudRateDiv = 1   ; (* higher byte of divisor *)
  99.     LineStatusReg   = 5   ; (* holds status info on the data transfer *)
  100.     ReceiverReg     = 0   ; (* received CHAR is in this register *)
  101.     TransmitReg     = 0   ; (* CHAR to send is to put in this reg *)
  102.     IntEnableReg    = 1   ; (* to enable the selected interrupt *)
  103.     IntIdentReg     = 2   ; (* to identify the interrupt *)
  104.     ModemContrReg   = 4   ; (* controls the interface to a modem *)
  105.     ModemStatusReg  = 6   ; (* holds status of line (BREAK etc.) *)
  106.  
  107.     Icntrlw2 = 20h                     ;Interrupt controller
  108.     SEOI1    = 64h                     ;EOI for COM1
  109.     SEOI2    = 63h                     ;EOI for COM2
  110.  
  111.     FALSE    = 0
  112.     TRUE     = 1
  113.  
  114.     RLSint   = 6
  115.     RDRint   = 4
  116.     THREint  = 2
  117.     MODEMint = 0
  118.  
  119. DATA SEGMENT WORD PUBLIC
  120.     ASSUME DS:DATA
  121.  
  122. EXTRN RS_BufPtr:WORD
  123. EXTRN RS_TimeOut:WORD
  124. DATA ENDS
  125.  
  126. CODE SEGMENT BYTE PUBLIC
  127.     ASSUME CS:CODE
  128.  
  129.     public Rs_Com4int
  130. Rs_Com4int proc far
  131.     push ax
  132.     push bx
  133.     mov bx,offset DATA:rs_bufptr[12]
  134.     jmp short comcont
  135.  
  136.     public rs_com3int
  137. rs_com3int proc far
  138.     push ax
  139.     push bx
  140.     mov bx,offset DATA:rs_bufptr[8]
  141.     jmp short comcont
  142.  
  143.     public rs_com2int
  144. rs_com2int proc far
  145.     push ax
  146.     push bx
  147.     mov bx,offset DATA:rs_bufptr[4]
  148.     jmp short comcont
  149.  
  150.     public rs_com1int
  151. rs_com1int proc far
  152.     push ax
  153.     push bx
  154.     mov bx,offset DATA:rs_bufptr[0]
  155. comcont:
  156.     push ds
  157.     mov ax, DATA
  158.     mov ds,ax
  159. ASSUME DS:DATA
  160.  
  161.     mov bx,[bx]
  162.  
  163. ; Reset Video TimeOut Count
  164.     rs_timeout := 0
  165.  
  166. ;   STI                                ;Enable int's
  167.  
  168.     push cx
  169.     push dx
  170.     push di
  171.     push si
  172.     push es
  173.  
  174. repeat_int:
  175.  
  176.     CLI
  177.     InPort IntIdentReg                 ;Hvorfor er jeg her?
  178.  
  179.     if al = RDRint then
  180.         call ReadInt
  181.         jmp repeat_int
  182.     endif
  183.     if al = THREint then               ;TX int
  184.         call SendNext                  ;Restart
  185.         jmp repeat_int
  186.     endif
  187.     if al = RLSint then
  188.         InPOfs <LineStatusReg - IntIdentReg>
  189.         and al,1Eh                     ;Keep OE(2),PE(4),FE(8) and BI(10)
  190.         or [bx.Line_Status],al
  191.         jmp repeat_int
  192.     endif
  193.     if al = MODEMint then
  194.         InPOfs <ModemStatusReg-IntIdentReg> ;Restart async chip
  195.         or [bx.MODEM_Status],al
  196.         if word ptr [bx].MODEM_user <> 0 then
  197.             push bx
  198.             push ds
  199.             call dword ptr [bx+MODEM_user]
  200.             pop ds
  201.             pop bx
  202.         endif
  203.         jmp repeat_int
  204.     endif
  205.  
  206.     InPOfs <ModemStatusReg-IntIdentReg> ;Restart async chip
  207.     or [bx.MODEM_Status],al
  208.     jmp $+2
  209.     InPOfs <LineStatusReg-ModemStatusReg>
  210.     and al,1Eh                         ;Keep OE(2),PE(4),FE(8) and BI(10)
  211.     or [bx.Line_Status],al
  212.  
  213.     pop  es
  214.     pop  si
  215.     pop  di
  216.     pop  dx
  217.     pop  cx
  218.  
  219.     pop  ds
  220.     pop  bx
  221.  
  222. ; Enable HW int's
  223.  
  224.     CLI
  225.     al := 20h
  226.     out Icntrlw2,al
  227.  
  228.     pop  ax
  229.     iret
  230. rs_com1int endp
  231. rs_com2int endp
  232. rs_com3int endp
  233. rs_com4int endp
  234.  
  235. ReadInt Proc near
  236.  
  237.     InPOfs <ReceiverReg - IntIdentReg> ;Get received char
  238.  
  239. ; Test if room in buffer
  240.  
  241.     les si,dword ptr [bx.InX]          ;Get buffer Address
  242.     lea di,[si+1]
  243.     if di >= [bx.SizeX] then xor di,di
  244.  
  245.     if di <> [bx.OutX] then            ;Buffer not full
  246.         es:[si] := al
  247.         [bx.InX] := di
  248.     else
  249.         or [bx.Line_Status],20h        ;Overrun Error!
  250.     endif
  251.  
  252.     STI
  253.  
  254.     if [bx.AutoX] = FALSE then ret
  255.  
  256. ; Test if XOFF or XON
  257.     ah := al                           ; Test if XOFF or XON
  258.     and ah,7fh                         ; Use 7 low bits!
  259.  
  260.     if [bx.Ctrl_P] < 1 then
  261.             if [bx.HostX] = FALSE then
  262.                 cmp ah,[BX.Xoff1C]
  263.                 je TurnOff
  264.                 if [bx.AltX] = TRUE then
  265.                     cmp ah,[bx.Xoff2C]
  266.                     je TurnOff
  267.                 endif
  268.         endif
  269.         cmp ah,[BX.Xon1C]
  270.         je TurnOn
  271.         cmp [bx.AltX],TRUE
  272.         jne nochange
  273.         cmp ah,[bx.Xon2C]
  274.         je TurnOn
  275.         jmp short nochange
  276.     endif
  277.     if = then                          ; if [bx.Ctrl_P] = 1 then
  278.             if ah = 10h then
  279.                 [bx.Ctrl_P] := 2
  280.                 jmp short nochange
  281.             endif
  282.             cmp [bx.HostX],TRUE
  283.             je TurnOn
  284.             cmp ah,[bx.Xoff1C]
  285.             je TurnOff
  286.             jmp short nochange
  287.     endif
  288.     if [bx.Ctrl_P] = 2 then
  289.             [bx.Ctrl_P] := 3
  290.             jmp short nochange
  291.     endif
  292.     [bx.Ctrl_P] := 1
  293.     jmp short nochange
  294.  
  295. TurnOn:
  296.     [bx.HostX] := FALSE                ; Save new value
  297.     call StartSender
  298.     al := ' '
  299.     jmp short updateX
  300.  
  301. TurnOff:
  302.     [bx.HostX] := TRUE
  303.     al := 'X'
  304. UpdateX:
  305.     if [bx.Show_X2] <> 0 then
  306.         les di,dword ptr [bx.Show_X]
  307.         es:[di] := al
  308.     endif
  309. NoChange:
  310.  
  311. ; Test if buffer almost full
  312.  
  313.     dx := [bx.OutX]
  314.     di := [bx.InX]
  315.     inc di
  316.     sub dx,di                                 ;InX
  317.     if carry then add dx,[bx.SizeX]
  318.  
  319. ; dx = Free space in buffer
  320.  
  321.     cmp dx,[bx.LimitX]
  322.     jbe almost_full
  323.     ret                                ;Buffer not full, early exit
  324. Almost_Full:
  325.     test [bx.Bfull],1                  ;Is our bit set?
  326.     jnz Second_Limit                   ;Yes, check if past second limit
  327.     or [bx.Bfull],1                    ;Set our bit
  328. Stop_Rec:
  329.     if [bx.UseTint] = TRUE then
  330.             al := [bx.Xoff1C]
  331.             ah := TRUE
  332.             [bx.Send_T] := ax          ;Send before all others
  333.             call StartSender
  334.             ret                        ;Exit after XOFF sent
  335.     endif
  336.     call WaitTHRE
  337.     al := [bx.Xoff1C]
  338.     out dx,al
  339.     ret
  340.  
  341. Second_Limit:
  342.     shl dx,1
  343.     cmp dx,[bx.LimitX]
  344.     jbe Stop_Rec
  345.     ret
  346. ReadInt endp
  347.  
  348. WaitTHRE proc near
  349.     mov dx,[bx].PortNr
  350.     DXofs LineStatusReg
  351.     repeat
  352.         in al,dx
  353.         ah := al
  354.         and ah,1Eh
  355.         or [bx.Line_Status],ah
  356.     until al AND 20h true
  357.     DXofs <TransmitReg - LineStatusReg>
  358.     ret
  359. WaitTHRE endp
  360.  
  361. SendByte proc near                     ; Sending WO TX-int
  362. ; INPUT   al : byte to send
  363. ; OUTPUT  ah : status
  364. ; REG'S   dx
  365.  
  366.     push ax
  367.     call WaitTHRE
  368.     pop ax
  369.  
  370.     ah := FALSE;
  371.     if [bx.HostX] = FALSE then
  372.         out dx,al
  373.         ah := TRUE
  374.     endif
  375.  
  376.     ret
  377. SendByte EndP
  378.  
  379. SendInt Proc near
  380. ; Use buffered sending
  381. ; INPUT   al : byte to send
  382. ; OUTPUT  ah : status
  383. ; REG'S   dx,si,di,es,
  384.  
  385.     si := [bx.InT]
  386.     lea di,[si+1]
  387.     if di >= [bx.SizeT] then xor di,di
  388.  
  389.     ah := FALSE
  390.     if di <> [bx.OutT] then
  391.         es := [bx.T_Buf2]
  392.         es:[si] := al
  393.  
  394.         [bx.InT] := di                 ;Update input pointer
  395.         ah := TRUE
  396.     endif
  397.  
  398.     call StartSender                   ;Restart if neccessary
  399.  
  400.     ret
  401. SendInt endp
  402.  
  403. StartSender proc near
  404.     push ax
  405.     call SendNext
  406.                                        ;Turn on TX int's again!
  407.     InPort IntEnableReg
  408.     or al,2
  409.     out dx,al
  410.  
  411.     pop ax
  412.     ret
  413. StartSender endp
  414.  
  415. SendNoMore:
  416. ; Turn off TX int's when no more data
  417.     InPort IntEnableReg
  418.     and al,NOT 2
  419.     out dx,al
  420.     ret
  421.  
  422. SendNext Proc near                     ;SI
  423. ; INPUT
  424. ; OUTPUT
  425. ; REG'S   dx,ax,si,es
  426.  
  427.     if [bx.WaitTX] = FALSE then
  428.         InPort LineStatusReg
  429.         ah := al
  430.         and ah,1Eh
  431.         or [bx.Line_Status],ah
  432.  
  433.         if al AND 20h true then
  434.             DXofs <TransmitReg - LineStatusReg>
  435.  
  436.             xor ax,ax
  437.             xchg ax,[bx.Send_T]
  438.  
  439.             if ah <> FALSE then
  440.                 out dx,al
  441.             elseif [bx.HostX] = FALSE then
  442.                 les si, dword ptr [bx.OutT]
  443.                 if si = [bx.InT] then jmp SendNoMore
  444.                 cld
  445.                 lods byte ptr es:[si]
  446.                 if si >= [bx.SizeT] then xor si,si
  447.                 [bx.OutT] := si
  448.                 out dx,al
  449.             endif
  450.         endif
  451.     endif
  452.     STI
  453.     ret
  454. SendNext endp
  455.  
  456. avail proc near
  457. ; INPUT
  458. ; OUTPUT  cx : bytes in input buffer
  459. ; REG'S   cx
  460.  
  461.     cx := [bx.InX]
  462.     sub cx,[bx.OutX]
  463.     if carry then add cx,[bx.sizeX]
  464.     ret
  465. avail endp
  466.  
  467. checkempty proc near                   ;Local proc for read and readblock
  468. ; INPUT
  469. ; OUTPUT
  470. ; REG'S   cx,ax
  471.     if [bx.Bfull] and 1 true then
  472.         call avail
  473.         if cx <= [bx.LimitX] then
  474.             and [bx.Bfull],254
  475.             if zero then
  476.                 [bx.WaitTX] := TRUE    ;Allocate TX
  477.                 call WaitTHRE
  478.                 al := [bx.Xon1C]
  479.                 out dx,al
  480.                 [bx.WaitTX] := FALSE
  481.             endif
  482.         endif
  483.     endif
  484.     ret
  485. checkempty endp
  486.  
  487. intro MACRO com
  488.     bx := [bp+com]
  489.     shl bx,1
  490.     shl bx,1
  491.     bx := rs_bufptr[bx-4]
  492. ENDM
  493.  
  494. PasProc rs_readblock <bufs, buf, max, byts, byt, com> FAR
  495. ; REG'S   dx,cx,si,di,es,bx,ax
  496.  
  497.     intro com
  498.  
  499.     xor dx,dx                          ;zero bytes read
  500.     call avail
  501.     if cx > [bp].max then cx := [bp].max ;max bytes
  502.     jcxz skipblock
  503.  
  504.     mov si,[bx.OutX]                   ;output index
  505.  
  506.     les di,[bp].buf                    ;buffer address
  507.     cld                                ;les forover!
  508.  
  509.     dx := [bx.SizeX]                   ;Copy of size
  510.  
  511.   push ds
  512.     ds := [bx.R_buf2]                  ;Segment of buffer
  513.     push bx
  514.     xor bx,bx                          ;bytes read
  515.  
  516.     repeat
  517.         lodsb
  518.         if si >= dx then xor si,si
  519.  
  520.         ah := al
  521.         inc ah
  522.         and ah,7fh
  523.         if ah <= ' ' then
  524.             if bx <> 0 then
  525.                 if si = 0 then si := dx
  526.                 dec si
  527.                 leave
  528.             endif
  529.             stosb
  530.             inc bx
  531.             leave
  532.         endif
  533.  
  534.         stosb
  535.         inc bx
  536.     until loop
  537.  
  538.     dx := bx                           ;Save bytes read
  539.     pop bx
  540.   pop ds
  541.  
  542.     [bx.OutX] := si
  543.  
  544. skipblock:
  545.     les di,[bp].byt
  546.     es:[di] := dx                      ;bytes read in block
  547.     call checkempty
  548.  
  549. PasRet
  550.  
  551. PasProc rs_busyread <chrs, chr, dones, done, com> FAR
  552.     intro com
  553.  
  554.     si := [bx.OutX]
  555.  
  556.     ax := FALSE
  557.     if si <> [bx.InX] then
  558.         es := [bx.R_Buf2]
  559.         cld
  560.         lods byte ptr es:[si]
  561.         if si >= [bx.SizeX] then xor si,si
  562.         [bx.OutX] := si
  563.  
  564.         les di,[bp+chr]                ;ch
  565.         stosb
  566.  
  567.         call checkempty
  568.  
  569.         al := TRUE
  570.     endif
  571.  
  572.     les di,[bp.done]
  573.     stosb
  574.  
  575. PasRet
  576.  
  577. PasProc rs_getchar <chrs, chr, com> FAR
  578.  
  579.     intro com
  580.  
  581.     si := [bx.OutX]
  582.  
  583.     xor ax,ax                          ; Return value
  584.  
  585.     if si <> [bx.InX] then
  586.         es := [bx.R_Buf2]
  587.         cld
  588.         lods byte ptr es:[si]
  589.         xor dx,dx
  590.         ah := al
  591.         inc ah
  592.         and ah,7fh
  593.         if ah > ' ' then
  594.             if si >= [bx.SizeX] then xor si,si
  595.             [bx.OutX] := si
  596.  
  597.             les di,[bp+chr]            ;ch
  598.             stosb
  599.             call checkempty
  600.             dl := TRUE
  601.         endif
  602.         ax := dx
  603.     endif
  604. PasRet
  605.  
  606. PasProc rs_write <chr, dones, done, com> FAR
  607.     intro com
  608.  
  609.     al := [bp+chr]
  610.  
  611.     if [bx.UseTInt] = TRUE then
  612.         call SendInt
  613.     else
  614.         call SendByte
  615.     endif
  616.  
  617.     les di,[bp.done]
  618.     es:[di] := ah
  619. PasRet
  620.  
  621. PasProc rs_writeblock <bufs, buf, len, byts, byt, com> FAR
  622.     intro com
  623.  
  624.     cld                                ;Forward
  625.  
  626.     if [bx.UseTint] = FALSE then
  627.  
  628.         les si,[bp+buf]                ;buf
  629.         cx := [bp+len]                 ;len
  630.         dx := cx                       ;bytes sent
  631.         jcxz skipwr
  632.  
  633.         push dx
  634.         repeat
  635.             lods byte ptr es:[si]
  636.             call SendByte
  637.             if ah = FALSE then leave
  638.         until loop
  639.         pop dx
  640.         sub dx,cx
  641. skipwr:
  642.         ax := dx                       ;Bytes sent
  643.  
  644.     else                               ;Use TX int's
  645.  
  646. ; Compute free room in TX buffer
  647.  
  648.         cx := [bx.OutT]
  649.         di := [bx.InT]
  650.         lea si,[di+1]
  651.         ax := [bx.SizeT]
  652.  
  653.         sub cx,si                      ; OutT - (InT+1)
  654.         if carry then add cx,ax
  655.  
  656.         if cx > [bp+len] then cx := [bp+len] ;Min(room,len)
  657.  
  658.         push cx                            ;Bytes sent
  659.  
  660.         jcxz skipwblock                    ;Request to send zero bytes!
  661.  
  662.         es := [bx.T_Buf2]
  663. ;       di := [bx.InT]                 ; OK from start
  664.  
  665.         push ds
  666.         mov ds,[bp+bufs]
  667. ;******************* Her peker DS p bufferet, ikke p RS_Buffer!
  668.         mov si,[bp+buf]                    ;buf
  669.  
  670.         sub ax,di                          ;Size - InT
  671.         if ax < cx then                    ;Room on top of buffer?
  672.             sub cx,ax                      ;Overflow part
  673.             xchg cx,ax                     ;Room on top
  674.             rep movsb                      ;First block
  675.             xor di,di                      ;Continue from start of TX buffer
  676.             cx := ax                       ;last part
  677.         endif
  678.         rep movsb                          ;Second block
  679.  
  680.         pop ds
  681. ;******************** N er DS:BX ok igjen!
  682.  
  683.         if di >= [bx.SizeT] then xor di,di
  684.         [bx.InT] := di
  685.  
  686. skipwblock:
  687.         pop ax                         ; # of bytes sent
  688.  
  689.     endif
  690.  
  691.     les di,[bp+done]
  692.     stosw
  693.     call StartSender
  694.  
  695. PasRet
  696.  
  697. PasProc rs_avail <com> FAR
  698.     intro com
  699.     call avail
  700.     ax := cx
  701. PasRet
  702.  
  703. PasProc rs_room <com> FAR              ;Room in output buffer
  704.     intro com
  705.     ax := [bx.OutT]
  706.     dx := [bx.InT]
  707.  
  708.     inc dx
  709.     sub ax,dx
  710.     if carry then add ax,[bx].SizeT
  711.  
  712. PasRet
  713.  
  714. PasProc rs_enable <com> FAR
  715.     intro com
  716.     [bx.HostX] := FALSE
  717.     mov al,0
  718.     OutPort IntEnableReg
  719.     al := [bx].Int_Mask
  720.     out dx,al
  721.     al := TRUE
  722.     xchg al,[bx.WaitTX]
  723.     if al = FALSE then
  724.         call StartSender
  725.         [bx.WaitTX] := FALSE
  726.     endif
  727. PasRet
  728.  
  729. PasProc rs_writefirst <chr, com> FAR
  730.     intro com
  731.  
  732.     [bx.WaitTX] := TRUE                ;Allocate transmitter!
  733.     call WaitTHRE
  734.     al := [bp+chr]                     ;ch to send first
  735.     out dx,al
  736.     [bx.WaitTX] := FALSE
  737. PasRet
  738.  
  739. CODE ENDS
  740.  
  741.     END
  742.