home *** CD-ROM | disk | FTP | other *** search
/ MS DOS Archives 1 / MS-DOS_Archives_Volume_One_Walnut_Creek.iso / msdos / fossil / t2kcom52.arc / T2KCOMM.ASM < prev    next >
Assembly Source File  |  1988-02-24  |  65KB  |  2,240 lines

  1.     page    58,132
  2.     title    T2KCOMM    - FOSSIL Driver    For The    Tandy 2000 - v5.2
  3.     .186
  4.     subttl    Overview and History
  5.     page
  6.  
  7. ;      This program implements the FOSSIL (Fido, Opus, SEAdog Standard
  8. ; Interface Layer) communications driver for the Tandy 2000.  FOSSIL
  9. ; functions 00h    - 1Bh,    7Eh,  and 7Fh are implemented.
  10.  
  11. ; Written by Rick Moore
  12. ; Copyright 1987, 1988 by Solar Wind Computing,  ALL RIGHTS RESERVED
  13.  
  14. ;      This code may be    used and distributed in    its unmodified form for    ANY
  15. ; NONCOMMERCIAL    USE WHATEVER.  Modified    versions of this software are NOT to
  16. ; be distributed without the express written consent of    the author.  You are
  17. ; not allowed to sell or otherwise make    money from the use of this software
  18. ; without specific license from    the author.  You may contact the author    at:
  19.  
  20. ;      Solar    Wind Computing
  21. ;      P.O. Box 1204
  22. ;      Homewood,  IL     60430
  23.  
  24. ; You may contact the author with bug reports or suggestions for improvement
  25. ; via FidoNet mail at Net 115 Node 333 - Solar Wind Opus for non-commercial
  26. ; purposes only.
  27.  
  28. ; History:
  29. ;   v1.0  - 01/87 REM
  30. ;   v1.1  - 02/87 REM      1. Added functions 20    and 21.
  31. ;              2. Fixed several mites in x-on/x-off logic
  32. ;              3. Optimized branch instructions for minimum
  33. ;                 overhead in the interrupt routines.  Some
  34. ;                 of    the code may look strange at first,  but
  35. ;                 the code has been arranged    to minimize
  36. ;                 instruction prefetch queue    flushing.
  37. ;              4. Eliminated    dependence on Tandy BIOS int 14h
  38. ;                 by    incorporating the code to set the 8253 and
  39. ;                 8251A in T2KCOMM.    This will help minimize
  40. ;                 stack usage from within T2KCOMM,  and will
  41. ;                 allow future expansion to support 19200 bps.
  42. ;   v1.2  - 03/87 REM      1. Fixed the mistake in the implementation of
  43. ;     (never released)         functio 20,  in which,  due to confusion on
  44. ;                 my    part,  I did not implement the ability to
  45. ;                 cancel the    watchdog function.
  46. ;              2. Added full    word length,  parity,  and stop    bit
  47. ;                 support to    function 0.
  48. ;              3. Simplified    and improved the transmitter hold
  49. ;                 logic.
  50. ;              4. Changed function 7    to return timer    parms for
  51. ;                 the PC BIOS interrupt, 1C.     This cuts by 80%
  52. ;                 the overhead associated with the timer tick.
  53. ;   v3.00 - 05/87 REM      1. Added functions 22    and 23,     bringing the driver
  54. ;                 up    to compliance with Draft 3 of the FOSSIL
  55. ;                 spec.
  56. ;              2. Changed naming convention.     The first digit of
  57. ;                 the version is the    FOSSIL spec level and the
  58. ;                 decimal places represent the release version
  59. ;                 within that spec.
  60. ;              3. Completely    changed    the way    parameters are passed
  61. ;                 and returned within the program.  As the FOSSIL
  62. ;                 spec has added function,  it has become harder
  63. ;                 and harder    to keep    the required parameters    in
  64. ;                 the proper    register(s) through the    various
  65. ;                 routines.    Therefore,  all    registers except CS
  66. ;                 are stored    in a stack frame upon entry to the
  67. ;                 int 14h code.  All    registers except CS and    SS
  68. ;                 will be restored when exiting.  Therefore all
  69. ;                 return values must    be stored into the stack
  70. ;                 frame before returning.
  71. ;              4. Fixed again,  and hopefully once and for all, the
  72. ;                 mite in the x-on/x-off logic.
  73. ;              5. Added DSR handshaking.
  74. ;   v3.10 - 06/87 REM      1. Reorganized and optimized the USART interrupt
  75. ;                 handler to    insure reliable    operation at 19.2kb
  76. ;                 and above.
  77. ;              2. Optimized the FOSSIL read and write routines for
  78. ;                 the same reason.
  79. ;              3. Swatted more mites.
  80. ;   v3.20 - 07/87 REM      1. Increased transmit    buffer size to 4k.  Opus's
  81. ;                 Zmodem routine uses window    sizes of 2k,  so
  82. ;                 I wanted more of a    pad.
  83. ;              2. More bulletproofing against lost interrupts
  84. ;              3. Added an incredible kluge to make the driver
  85. ;                 completely    compatible with    the Tandy BIOS.     It
  86. ;                 seems that    the Tandy int 14 function 3 (status)
  87. ;                 stores the    next character available in the
  88. ;                 buffer (if    one exists) at a displacement of 6Fh
  89. ;                 in    the BIOS Communication Area.  The MS/DOS
  90. ;                 device driver for the AUX:    device looks for this
  91. ;                 character when the    "non-destructive" read
  92. ;                 function is called.  Now this driver does the
  93. ;                 same thing    as the Tandy BIOS.
  94. ;   3.30 - 07/87 REM      1. Fixed brain-damaged logic in the Timer Tick
  95. ;                 Manager routines.    Somehow,  I copied old code
  96. ;                 back into the source deck.     It is back the    way
  97. ;                 it    was supposed to    be all along.
  98. ;              2. Corrected function    0Ch to be a non-destructive,
  99. ;                 rather than a destructive read.
  100. ;   3.40 - 09/87 REM      1. Eliminated    three more lockup conditions.
  101. ;              2. Added full    Xon/Xoff and CTS/RTS support,  in
  102. ;                 both host and remote modes.  Now supports the
  103. ;                 "Modem Steady" option at speeds up    to 9.6 kbps.
  104. ;                 Special thanks to Vince Perriello for a
  105. ;                 suggestion    that really made it simpler.
  106. ;              3. Decreased the transmit buffer size    back to    1k,
  107. ;                 which seems to work better    at lower speeds    than
  108. ;                 larger sizes.
  109. ;   4.00 - 10/87 REM      1. Driver now    fully implements the draft 4 FOSSIL
  110. ;                 spec,  including functions    7Eh and    7FH.
  111. ;              2. Changed receive mode Xon/Xoff to be controlled
  112. ;                 by    AL bit 08h,  as    specified in draft 4 spec.
  113. ;              3. T2KCOMM now returns the overflow,    framing    error,
  114. ;                 and parity    error bits in AH when status is
  115. ;                 returned.
  116. ;   4.10 - 10/87 REM      1. Converted to device driver    with support for AUX,
  117. ;                 COM1,  and    FOSSIL$    devices.
  118. ;              2. Removed kludge to support Tandy AUX driver    from
  119. ;                 "status" FOSSIL BIOS call.
  120. ;   5.00 - 11/87 REM      1. Changed the register calling conventions to use
  121. ;                 the draft 5 specs,     replacing DS:DX with ES:DX,
  122. ;                 and DS:SI with ES:DI.
  123. ;              2. Corrected error in    transmit-with-wait and
  124. ;                 transmit-without-wait routines.  Now both
  125. ;                 routines take the character to be enqueued    from
  126. ;                 the stack frame rather than directly from AL.
  127. ;                 The previous method worked,  but only accidently.
  128. ;   5.10 - 01/88 REM      1. Fixed errors in both the block read and
  129. ;                 block write routines.
  130. ;   5.20 - 02/88 REM      1. Implemented the change to the status call as
  131. ;                 specified in the V5 FOSSIL spec dated 02/11/88:
  132. ;                 Bit 03h of AL always returned set.
  133. ;              2. Removed support for status bits not defined by
  134. ;                 FOSSIL V5 spec.
  135. ;              3. Corrected version code returned by open.
  136. ;
  137.     subttl    Standard Equates And Macro Definitions
  138.     page
  139. code    segment    public 'code'
  140.     assume    cs:code, ds:code
  141.  
  142.     org    0000h
  143.  
  144.     include    C:\Usr\Include\Bioscall.Asm
  145.     include    C:\Usr\Include\Doscall.Asm
  146.     include    C:\Usr\Include\Regframe.Asm
  147.  
  148. FOSSIL    equ    14h        ;FOSSIL    interrupt number
  149.  
  150.     subttl    Device Driver Declarations
  151.     page
  152. ; Standard request header definition
  153.  
  154. RequestHeader struc
  155. RHLen      db    ?        ;Length    of request header
  156. RHUnit      db    ?        ;Unit number
  157. RHCmd      db    ?        ;Command code
  158. RHStatus  dw    ?        ;Status    word
  159.       db    9 dup (?)
  160. RHBufAdr  dd    ?        ;I/O buffer address
  161. RHCount      dw    ?        ;I/O count
  162. RequestHeader ends
  163.  
  164. ; Maximum valid    command    number for device driver commands
  165.  
  166. MaxCmd    equ    12
  167.  
  168.     subttl    Device Driver Headers And Command Tables
  169.     page
  170. FOSSIL$    dd    -1        ;Pointer to next driver
  171.     dw    0C000h        ;Driver    attributes
  172.     dw    Strategy    ;Offset    of strategy routine
  173.     dw    FOS$Int        ;Offset    of interrupt routine
  174.     db    'FOSSIL$ '    ;Device    name
  175.  
  176. CopyMsg    db    'Copyright 1987, 1988, Solar Wind Computing,'
  177.     db    '  ALL RIGHTS RESERVED.',13,10,'$'
  178.  
  179.     even
  180.  
  181. ; COM1 Device driver header
  182.  
  183. COM1    dd    -1        ;Pointer to next driver
  184.     dw    08000h        ;Driver    attributes
  185.     dw    Strategy    ;Offset    of strategy routine
  186.     dw    COM1Int        ;Offset    of interrupt routine
  187.     db    'COM1    '    ;Device    name
  188.  
  189. ; AUX Device driver header
  190.  
  191. AUX    dd    -1        ;Pointer to next driver
  192.     dw    08000h        ;Driver    attributes
  193.     dw    Strategy    ;Offset    of strategy routine
  194.     dw    AUXInt        ;Offset    of interrupt routine
  195.     db    'AUX     '    ;Device    name
  196.  
  197. ; FOSSIL$ Command Table
  198.  
  199. FOS$Tab    dw    FInit1        ;Device    initialization
  200.     dw    FNop        ;Media check (not applicable)
  201.     dw    FNop        ;Build BPB (not    applicable)
  202.     dw    FReadCtl    ;Read control string
  203.     dw    FRead        ;Read
  204.     dw    FReadAhead    ;Non-destructive look ahead
  205.     dw    FInStat        ;Input status
  206.     dw    FInFlush    ;Flush input buffer
  207.     dw    FWrite        ;Write
  208.     dw    FWrite        ;Write verify
  209.     dw    FOutStat    ;Output    status
  210.     dw    FOutFlush    ;Flush output buffer
  211.     dw    FWriteCtl    ;Write control string
  212.  
  213. ; COM1 and AUX Command Table
  214.  
  215. COM1Tab    dw    FInit2        ;Device    initialization
  216.     dw    FNop        ;Media check (not applicable)
  217.     dw    FNop        ;Build BPB (not    applicable)
  218.     dw    FCmdErr        ;Read control string
  219.     dw    FRead        ;Read
  220.     dw    FReadAhead    ;Non-destructive look ahead
  221.     dw    FInStat        ;Input status
  222.     dw    FInFlush    ;Flush input buffer
  223.     dw    FWrite        ;Write
  224.     dw    FWrite        ;Write verify
  225.     dw    FOutStat    ;Output    status
  226.     dw    FOutFlush    ;Flush output buffer
  227.     dw    FCmdErr        ;Write control string
  228.  
  229.     subttl    Device Driver Data Areas
  230.     page
  231. ; I/O Packet Address
  232.  
  233. PacketAddr dd    0        ;Strategy routine saves    header address here
  234.  
  235. ; Driver stack
  236.  
  237.     dw    128 dup    (0)
  238. OurStack equ    $
  239.  
  240.     subttl    Device Driver Strategy Routine
  241.     page
  242. Strategy proc    far
  243.  
  244.     mov    word ptr cs:PacketAddr,bx    ;Save request header offset
  245.     mov    word ptr cs:PacketAddr+2,es    ;Save request header segment
  246.     ret                    ;Return    to MS/DOS
  247.  
  248. Strategy endp
  249.  
  250.     subttl    FOSSIL$    Device Driver Interrupt    Routine
  251.     page
  252. FOS$Int    proc    far
  253.  
  254.     pusha                    ;Save MS/DOS's registers
  255.     mov    bx,offset FOS$Tab        ;Point to FOSSIL$ command table
  256.     xor    dx,dx                ;Set channel to    use
  257.     jmp    short Interrupt
  258.  
  259. FOS$Int    endp
  260.  
  261.     subttl    COM1 Device Driver Interrupt Routine
  262.     page
  263. COM1Int    proc    far
  264.  
  265.     pusha                    ;Save MS/DOS's registers
  266.     mov    bx,offset COM1Tab        ;Point to COM1 command table
  267.     xor    dx,dx                ;Set channel to    use
  268.     jmp    short Interrupt
  269.  
  270. COM1Int    endp
  271.  
  272.     subttl    AUX Device Driver Interrupt Routine
  273.     page
  274. AUXInt    proc    far
  275.  
  276.     pusha                    ;Save MS/DOS's registers
  277.     mov    bx,offset COM1Tab        ;Point to COM1 command table
  278.     xor    dx,dx                ;Set channel to    use
  279.     jmp    short Interrupt
  280.  
  281. AUXInt    endp
  282.  
  283.     subttl    Common Device Driver Interrupt Routine
  284.     page
  285. Interrupt proc    far
  286.  
  287.     push    ds
  288.     push    es
  289.     mov    ax,cs                ;Set up    DS
  290.     mov    ds,ax
  291.     mov    cx,offset OurStack        ;Set up    our stack
  292.     mov    si,ss                ;Save MS/DOS's SS/SP
  293.     mov    di,sp
  294.     mov    ss,ax                ;Load our SS/SP
  295.     mov    sp,cx
  296.     push    si                ;Save pointer to MS/DOS's stack
  297.     push    di
  298.     les    di,PacketAddr            ;Point to request header
  299.     mov    es:[di].RHStatus,0        ;Zero status word
  300.     mov    al,es:[di].RHCmd        ;Get command
  301.     cmp    al,MaxCmd            ;Too high?
  302.     ja    BadCmd                ;Yes - return error
  303.     xor    ah,ah                ;Convert command to displacement
  304.     shl    ax,1
  305.     add    bx,ax                ;Add displacement to table base
  306.     call    word ptr [bx]            ;Call appropriate routine
  307. IntExit:
  308.     or    es:[di].RHStatus,0100h        ;Set DONE bit
  309.     pop    di                ;Restore MS/DOS's stack
  310.     pop    si
  311.     mov    ss,si
  312.     mov    sp,di
  313.     pop    es                ;Restore MS/DOS's registers
  314.     pop    ds
  315.     popa
  316.     ret                    ;Return    to MS/DOS
  317.  
  318. BadCmd:
  319.     or    es:[di].RHStatus,8003h        ;Set error + invalid cmd flags
  320.     jmp    IntExit                ;Continue
  321.  
  322. Interrupt endp
  323.  
  324.     subttl    Device Driver NOP Routine
  325.     page
  326. FNop    proc    near
  327.  
  328.     ret                    ;Return    to interrupt routine
  329.  
  330. FNOP    endp
  331.  
  332.     subttl    Device Driver Invalid Command Routine
  333.     page
  334. FCmdErr    proc    near
  335.  
  336.     or    es:[di].RHStatus,8003h        ;Set error + invalid cmd flags
  337.     ret                    ;Return    to interrupt routine
  338.  
  339. FCmdErr    endp
  340.  
  341.     subttl    Device Driver Read Control String Routine
  342.     page
  343. FReadCtl proc    near
  344.  
  345.     ret                    ;Return    to interrupt routine
  346.  
  347. FReadCtl endp
  348.  
  349.     subttl    Device Driver Read Routine
  350.     page
  351. FRead    proc    near
  352.  
  353.     mov    cx,es:[di].RHCount        ;Get I/O count
  354.     les    di,es:[di].RHBufAdr        ;Point to MS/DOS's buffer
  355. FReadAgain:
  356.     cmp    cx,1                ;One character left to read?
  357.     jb    FReadExit            ;Less than one - all done
  358.     je    FReadOne            ;Yes - use single read
  359.     mov    ah,18h                ;Set FOSSIL function
  360.     int    FOSSIL                ;Call FOSSIL
  361.     sub    cx,ax                ;Subtract from number requested
  362.     add    di,ax                ;Add to    index into buffer
  363.     jmp    FReadAgain            ;Check for done
  364. FReadOne:
  365.     mov    ah,02h                ;Set FOSSIL function
  366.     int    FOSSIL                ;Call FOSSIL
  367.     stosb                    ;Store in MS/DOS's buffer
  368. FReadExit:
  369.     les    di,PacketAddr            ;Point to packet header
  370.     ret                    ;Return    to interrupt routine
  371.  
  372. FRead    endp
  373.  
  374.     subttl    Device Driver Read-Ahead Routine
  375.     page
  376. FReadAhead proc    near
  377.  
  378.     mov    ah,0Ch                ;Set FOSSIL function
  379.     int    FOSSIL                ;Call FOSSIL
  380.     cmp    ax,-1                ;Anything there?
  381.     je    FReadAheadBusy            ;No - indicate busy
  382.     lds    si,es:[di].RHBufAdr        ;Point to MS/DOS's buffer
  383.     mov    ds:[si],al            ;Store it in MS/DOS's buffer
  384.     ret                    ;Return    to interrupt routine
  385. FReadAheadBusy:
  386.     or    es:[di].RHStatus,0200h        ;Indicate Busy
  387.     ret                    ;Return    to interrupt routine
  388.  
  389. FReadAhead endp
  390.  
  391.     subttl    Device Driver Input Status Routine
  392.     page
  393. FInStat    proc    near
  394.  
  395.     mov    ah,03h                ;Set FOSSIL function
  396.     int    FOSSIL                ;Call FOSSIL
  397.     test    ah,mask    ARxRdy            ;Anything in receive buffer?
  398.     jnz    FInStatExit            ;Yes - leave BUSY flag reset
  399.     or    es:[di].RHStatus,0200h        ;No - set BUSY flag
  400. FInStatExit:
  401.     ret                    ;Return    to interrupt routine
  402.  
  403. FInStat    endp
  404.  
  405.     subttl    Device Driver Input Flush Routine
  406.     page
  407. FInFlush proc    near
  408.  
  409.     mov    ah,0Ah                ;Set FOSSIL function
  410.     int    FOSSIL                ;Call FOSSIL
  411.     ret                    ;Return    to interrupt routine
  412.  
  413. FInFlush endp
  414.  
  415.     subttl    Device Driver Write Routine
  416.     page
  417. FWrite    proc    near
  418.  
  419.     mov    cx,es:[di].RHCount        ;Get I/O count
  420.     les    di,es:[di].RHBufAdr        ;Point to MS/DOS's buffer
  421. FWriteAgain:
  422.     cmp    cx,1                ;One character left to write?
  423.     jb    FWriteExit            ;Less than one - all done
  424.     je    FWriteOne            ;Yes - use single write
  425.     mov    ah,19h                ;Set FOSSIL function
  426.     int    FOSSIL                ;Call FOSSIL
  427.     sub    cx,ax                ;Subtract from number requested
  428.     add    di,ax                ;Add to    index into MS/DOS's buffer
  429.     jmp    FWriteAgain            ;Check for done
  430. FWriteOne:
  431.     mov    al,es:[di]            ;Get char from MS/DOS's buffer
  432.     mov    ah,01h                ;Set FOSSIL function
  433.     int    FOSSIL                ;Call FOSSIL
  434. FWriteExit:
  435.     les    di,PacketAddr            ;Point to packet header
  436.     ret                    ;Return    to interrupt routine
  437.  
  438. FWrite    endp
  439.  
  440.     subttl    Device Driver Output Status Routine
  441.     page
  442. FOutStat proc    near
  443.  
  444.     mov    ah,03h                ;Set FOSSIL function
  445.     int    FOSSIL                ;Call FOSSIL
  446.     test    ah,mask    ATxEmp            ;Any room in buffer?
  447.     jnz    FOutStatExit            ;Yes - leave BUSY flag reset
  448.     or    es:[di].RHStatus,0200h        ;No - set BUSY flag
  449. FOutStatExit:
  450.     ret                    ;Return    to interrupt routine
  451.  
  452. FOutStat endp
  453.  
  454.     subttl    Device Driver Output Flush Routine
  455.     page
  456. FOutFlush proc    near
  457.  
  458.     mov    ah,09h                ;Set FOSSIL function
  459.     int    FOSSIL                ;Call FOSSIL
  460.     ret                    ;Return    to interrupt routine
  461.  
  462. FOutFlush endp
  463.  
  464.     subttl    Device Driver Write Control String Routine
  465.     page
  466. FWriteCtl proc    near
  467.  
  468.     ret                    ;Return    to interrupt routine
  469.  
  470. FWriteCtl endp
  471.  
  472.     subttl    BIOS Comm Equates And Definitions
  473.     page
  474. ; Equates for 8251A USART
  475.  
  476. MStatPort equ    00h        ;Modem status port
  477.  
  478. ;  Bit definitions for MStatPort
  479.  
  480. MSBits    record    MACLow:1,MFill:5,MDCD:1,MRI:1
  481.  
  482. UCtrlPort equ    12h        ;8251A control port
  483.  
  484. ; Bit definitions for UCtrlPort
  485.  
  486. UCBits    record    UHunt:1,UReset:1,URTS:1,UErrClr:1,UBrk:1,URxEn:1,UDTR:1,UTxEn:1
  487.  
  488. UStatPort equ    12h        ;8251A status port
  489.  
  490. ;  Bit definitions for UStatPort
  491.  
  492. USBits    record    UDSR:1,UBrkDet:1,UFrmErr:1,UOvrErr:1,UParErr:1,UTxEmp:1,URxRdy:1,UTxRdy:1
  493.  
  494. UDataPort equ    10h        ;8251A data port
  495.  
  496. ;  Bit definitions for status returned in AX by    the status function
  497.  
  498. AStatAH    record    ATimeOut:1,ATxRdy:1,ATxEmp:1,ABrkDet:1,AFrmErr:1,AParErr:1,AOvrErr:1,ARxRdy:1
  499. AStatAL    record    ADCD:1,Fill:7
  500.  
  501. ;  Bit definitions for parms passed in AL to FOSSIL function 0Fh (Flow Control)
  502.  
  503. FlParm    record    FlFill:4,FlRXon:1,FlDTR:1,FlRTS:1,FlTXon:1
  504.  
  505. ; Equates for 8253-5 programmable interval timer
  506.  
  507. PCnt0Port equ    40h        ;Timer 0
  508. PCnt1Port equ    42h        ;Timer 1
  509. PCnt2Port equ    44h        ;Timer 2
  510. PModePort equ    46h        ;Mode register
  511.  
  512. ; Equates for 8259A interrupt controller
  513.  
  514. OCW1A     equ    62h        ;8259(0) OCW1 port
  515. OCW2A     equ    60h        ;8259(0) OCW2-3    port
  516. NOPCmd59 equ    40h        ;OCW2 for NOP
  517. EOICmd59 equ    62h        ;OCW2 for specific EOI for level 2
  518. ISRCmd59 equ    0bh        ;OCW3 to return    IS reg
  519.  
  520. ; Equates for 80186
  521.  
  522. EOIReg86 equ    0FF22h        ;Address of 80186 EOI register
  523. EOICmd86 equ    000Ch        ;Specific EOI command for 80186    level 6
  524.  
  525. ; Equates for ACSII characters
  526.  
  527. CtlC    equ    03h
  528. CtlK    equ    0bh
  529. Xon    equ    11h
  530. Xoff    equ    13h
  531.  
  532. Magic    equ    1954h        ;"Magic" value returned by FOSSIL
  533. MaxFun    equ    27        ;Maximum function supported
  534. Version    equ    5        ;Spec version supported
  535. Revision equ    2        ;Revision level within version
  536.  
  537. ; Miscellaneous    equates
  538.  
  539. ChanFF    equ    00FFh        ;Channel id for    dummy operations
  540.  
  541.     even
  542. TTRoutLim equ    8        ;Number    of timer tick routine buckets
  543. TTRoutTab dd    TTRoutLim dup (?)    ;Timer tick routine table
  544. TTRoutCnt dw    0        ;Count of active timer tick routines
  545. OldInt1C dd    0        ;Original int 1Ch vector
  546.  
  547. LastCntl db    0        ;Last control byte sent    to USART
  548.  
  549. XChar    db    0        ;Handshake character stuffed to    transmitter
  550. LastXChar db    Xon        ;Last handshake    character sent
  551.  
  552. RFlag    db    0        ;Receiver flags
  553.  
  554. ;  Bit definitions of RFlag
  555.  
  556. RBits    record    RCtlChk:1,RCtlRcv:1,ROvr:1
  557.  
  558. TFlag    db    0        ;Transmitter hold flags
  559.  
  560. ;  Bit definitions of TFlag
  561.  
  562. TBits    record    TXonHld:1,TPrgHld:1
  563.  
  564. FFlag    db    0        ;Flow checking flags
  565.  
  566. ;  Bit definitions of FFlag
  567.  
  568. FBits    record    FRXon:1,FTXon:1,FRTS:1
  569.  
  570. ;  Baud    rate multiplier    for 8253-5 PIT
  571.  
  572.     even
  573. RateTable label    word
  574.     dw    6        ;19.2 kbps
  575.     dw    3        ;38.4 kbps
  576.     dw    416        ;300 bps
  577.     dw    208        ;600 bps
  578.     dw    104        ;1.2 kbps
  579.     dw    52        ;2.4 kbps
  580.     dw    26        ;4.8 kbps
  581.     dw    13        ;9.6 kbps
  582.  
  583.     even
  584.  
  585. ; User appendage table
  586.  
  587. UserAppTable dd    64 dup (?)    ;Vectors for user functions 80h    to BFh
  588.  
  589. ; Buffer sizes
  590.  
  591. TBufSize equ    1024        ;Transmit buffer size
  592. RBufSize equ    4096        ;Receive buffer    size
  593. RBUfLimit equ    3072        ;Receive handshake point
  594.  
  595. TBufFirst   dw    0        ;Index to first    character in xmit buffer.
  596. TBufNext    dw    0        ;Index to first    free space in xmit buffer.
  597. TBufCnt        dw    0        ;Number    of characters in xmit buffer.
  598. TBuf        db    TBufSize dup (?)    ;Xmit buffer
  599.  
  600. RBufFirst   dw    0        ;Index to first    character in recv buffer
  601. RBufNext    dw    0        ;Index to first    free space in recv buffer
  602. RBufCnt        dw    0        ;Number    of characters in rec. buffer
  603. RBuf        db    RBufSize dup (?)    ;Recv buffer
  604.  
  605. ; Fossil information area
  606.  
  607.     even
  608. Info    equ    $
  609. InfoSize  dw    20        ;Size of info area
  610. InfoVer      db    Version        ;Fossil    major version
  611. InfoRev      db    Revision    ;Fossil    revision level
  612. InfoId      dd    0        ;Pointer to ID string
  613. InfoRSize dw    RBufSize    ;Receive buffer    size
  614. InfoRFree dw    0        ;Receive buffer    free space
  615. InfoTSize dw    TBufSize    ;Transmit buffer size
  616. InfoTFree dw    0        ;Transmit buffer free space
  617. InfoScrW  db    80        ;Video screen width
  618. InfoScrH  db    24        ;Video screen height
  619. InfoBaud  dw    0        ;Actual    computer to modem baud rate
  620.  
  621. IDString  db    'T2KCOMM,  Version 5.2,  by Rick Moore',0
  622.  
  623.     subttl    BIOS Comm Interrupt Handler
  624.     page
  625.     .sall
  626.     even
  627. Int14    proc    far
  628.     jmp    short Int14a        ;Jump around prefix
  629.     db    0,0,0,0
  630.     dw    Magic            ;FOSSIL    "magic"    value
  631.     db    MaxFun            ;Highest function value
  632.     db    0
  633.  
  634. Int14a:    sti                ;Allow interrupts
  635.     and    ah,ah            ;High bit on?
  636.     js    DispatchUserApp        ;Yes - dispatch    user appendage
  637.     cmp    ah,MaxFun        ;Regular FOSSIL    function?
  638.     ja    UserAppMgr        ;No - go check for appendage function
  639.     pusha                ;Set up    register frame
  640.     push    ds
  641.     push    es
  642.     cld                ;Clear the direction flag
  643.     mov    bp,sp            ;BP points to register frame
  644.     mov    bx,cs            ;Set DS    = CS
  645.     mov    ds,bx
  646. ; Determine type of request and    call the appropriate routine
  647.     mov    si,ax            ;Get function number
  648.     shr    si,8            ;Shift into low    byte
  649.     shl    si,1            ;Convert into displacement
  650.     call    word ptr FuncTab[si]    ;Call appropriate routine
  651.     pop    es            ;Restore caller's registers
  652.     pop    ds
  653.     popa
  654. Exit14:    iret                ;Return    to point of interrupt
  655.  
  656. DispatchUserApp:
  657.     cmp    ah,0BFh            ;Appendage number out of range?
  658.     ja    Exit14            ;Yes - just return
  659.     push    bp            ;Save bp
  660.     sub    sp,8            ;Reserve room for stack    frame
  661.     mov    bp,sp            ;Point to stack    frame
  662.     push    ax            ;Save registers    used
  663.     push    bx
  664.     mov    bx,[bp]+8        ;Relocate saved    bp in stack frame
  665.     mov    [bp],bx
  666.     mov    bl,ah            ;Get copy of appendage number
  667.     shl    bl,1            ;Convert to displacement
  668.     shl    bl,1            ;  (Discarding two high    order bits)
  669.     xor    bh,bh            ;Convert to word
  670.     add    bx,offset UserAppTable    ;Add table base    to displacement
  671.     mov    ax,cs:[bx]        ;Get appendage offset
  672.     mov    [bp]+2,ax        ;Store in stack    frame
  673.     mov    ax,cs:[bx]+2        ;Get appendage segment
  674.     mov    [bp]+4,ax        ;Store in stack    frame
  675.     mov    [bp]+6,offset Exit14    ;Set up    appendage return address
  676.     mov    [bp]+8,cs
  677.     pop    bx            ;Restore registers used
  678.     pop    ax
  679.     pop    bp
  680. FarRet:    ret                ;Dispatch user appendage
  681.  
  682.     subttl    Install    and remove user    appendages
  683.     page
  684. ;
  685. ;    This routine installs/removes user appendages into/from    the FOSSIL
  686. ;        dispatcher.     Appendage numbers 80h through BFh are supported.
  687. ;
  688. ;    Entry conditions:
  689. ;        AH = 7Eh - Install an appendage
  690. ;             7Fh - Remove an appendage
  691. ;        AL = Appendage number
  692. ;        ES = Segment of    appendage entry    point
  693. ;        DX = Offset of appendage entry point
  694. ;    Exit conditions:
  695. ;        AH = 1954h
  696. ;        BL = Appendage number (same as AL on entry)
  697. ;        BH = 00h - Operation unsuccessful
  698. ;             01h - Operation successful
  699. ;
  700. UserAppMgr:
  701.     cmp    ah,7Eh            ;Check for valid appendage
  702.     jb    Exit14            ;  manager function
  703.     cmp    ah,7Fh
  704.     ja    Exit14
  705.     push    ax            ;Save ax
  706.     and    al,al            ;Verify    that appendage number
  707.     jns    UserAppErr        ;  is within range
  708.     cmp    al,0BFh
  709.     ja    UserAppErr
  710.     mov    bl,al            ;Get copy of appendage number
  711.     shl    bl,1            ;Convert to displacement
  712.     shl    bl,1            ;  (Discarding two high    order bits)
  713.     xor    bh,bh            ;Convert to word
  714.     add    bx,offset UserAppTable    ;Add table base    to displacement
  715.     cmp    ah,7Eh            ;Install request?
  716.     jne    UserAppRmv        ;No - must be a    remove request
  717.     cmp    cs:[bx],offset FarRet    ;Verify    that entry in question
  718.     jne    UserAppErr        ;  is not already in use
  719.     mov    ax,cs
  720.     cmp    cs:[bx]+2,ax
  721.     jne    UserAppErr
  722.     cli                ;No interrupts
  723.     mov    cs:[bx],dx        ;Insert    offset of user appendage
  724.     mov    cs:[bx]+2,es        ;Insert    segment    of user    appendage
  725.     sti                ;Interrupts ok
  726.     mov    bh,1            ;Indicate success
  727.     jmp    short UserAppExit    ;Get out
  728. UserAppRmv:
  729.     cmp    cs:[bx],dx        ;Verify    that entry points to the
  730.     jne    UserAppErr        ;  routine we are trying to remove
  731.     mov    ax,es
  732.     cmp    cs:[bx]+2,ax
  733.     jne    UserAppErr
  734.     cli                ;No interrupts
  735.     mov    cs:[bx],offset FarRet    ;Insert    default    offset
  736.     mov    cs:[bx]+2,cs        ;Insert    default    segment
  737.     sti                ;Interrupts ok
  738.     mov    bh,1            ;Indicate success
  739.     jmp    UserAppExit        ;Get out
  740. UserAppErr:
  741.     xor    bh,bh            ;Indicate failure
  742. UserAppExit:
  743.     pop    ax            ;Restore ax
  744.     mov    bl,al            ;Return    appendage number assigned
  745.     mov    ax,Magic        ;Indicate the FOSSIL is    installed
  746.     jmp    Exit14            ;Get out
  747.  
  748. Int14    endp
  749.  
  750. Functab    dw    offset CSetChan        ;Function 00h
  751.     dw    offset CTxWait        ;Function 01h
  752.     dw    offset CRxWait        ;Function 02h
  753.     dw    offset CStatus        ;Function 03h
  754.     dw    offset COpen        ;Function 04h
  755.     dw    offset CClose        ;Function 05h
  756.     dw    offset CDTR        ;Function 06h
  757.     dw    offset TTickParm    ;Function 07h
  758.     dw    offset CFlushOut    ;Function 08h
  759.     dw    offset CPurOut        ;Function 09h
  760.     dw    offset CPurIn        ;Function 0Ah
  761.     dw    offset CTxNowait    ;Function 0Bh
  762.     dw    offset CRxNowait    ;Function 0Ch
  763.     dw    offset KRxNowait    ;Function 0Dh
  764.     dw    offset KRxWait        ;Function 0Eh
  765.     dw    offset CFlowCtl        ;Function 0Fh
  766.     dw    offset CCtlChk        ;Function 10h
  767.     dw    offset DSetCurLoc    ;Function 11h
  768.     dw    offset DGetCurLoc    ;Function 12h
  769.     dw    offset DPutDos        ;Function 13h
  770.     dw    offset CWatchDog    ;Function 14h
  771.     dw    offset DPutBios        ;Function 15h
  772.     dw    offset TTickMgr        ;Function 16h
  773.     dw    offset Reboot        ;Function 17h
  774.     dw    offset CBlockRead    ;Function 18h
  775.     dw    offset CBlockWrite    ;Function 19h
  776.     dw    offset CBreak        ;Function 1Ah
  777.     dw    offset CInfo        ;Function 1Bh
  778.  
  779.     subttl    Set channel parameters
  780.     page
  781. CSetChan proc    near
  782. ;
  783. ;    Sets channel parameters
  784. ;
  785. ;    Entry conditions:
  786. ;        [bp].RegAL = channel parameters
  787. ;        [bp].RegDX = channel
  788. ;    Exit conditions:
  789. ;        [bp].RegAX = channel status
  790. ;
  791.     cmp    [bp].RegDX,ChanFF    ;Dummy channel?
  792.     je    CSetChanFF        ;Yes - just return
  793.     mov    dx,OCW1A        ;Point to PIC(0) OCW1 port
  794.     cli                ;No interrupts
  795.     xor    bl,bl            ;Clear work area
  796.     xor    ax,ax            ;Clear ax
  797.     mov    al,[bp].RegAL        ;Get parms from    reg frame
  798.     mov    InfoBaud,ax        ;Store port info in info area
  799.     mov    ah,al            ;Make copy of parms
  800.     and    ah,mask    CRParity    ;Mask out all but parity bits
  801.     shl    ah,1            ;Convert to USART command bits
  802.     or    bl,ah            ;Set bits in new USART command
  803.     mov    ah,al            ;Make copy of parms
  804.     and    ah,mask    CRWordLen    ;Mask out all but word length bits
  805.     shl    ah,2            ;Convert to USART command bits
  806.     or    bl,ah            ;Set bits in new USART command
  807.     mov    ah,al            ;Make copy of parms
  808.     and    ah,mask    CRStopBit    ;Mask out all but # stop bits
  809.     shl    ah,5            ;Convert to USART command bits
  810.     or    ah,42h            ;Set bits 6 and    1 in USART command
  811.     or    ah,bl            ;Leave new USART command in ah
  812.     mov    bl,al            ;Makecopy of parms
  813.     and    bl,mask    CRRate        ;Mask off all but rate bits
  814.     xor    bh,bh            ;Zero high order byte
  815.     shr    bx,4            ;Convert to word displacement
  816.     add    bx,offset RateTable    ;Point to baud rate table
  817.     mov    bx,0[bx]        ;Get baud rate divisor
  818.     mov    dx,UCtrlPort        ;Point to USART    control    port
  819.     xor    al,al            ;Clear USART out with 3    nulls
  820.     call    PutWait
  821.     call    PutWait
  822.     call    PutWait
  823.     mov    al,mask    UReset        ;Reset the USART
  824.     call    PutWait
  825.     mov    dx,PModePort        ;Point to PIT mode port
  826.     mov    al,76h            ;Get PIT command
  827.     call    PutWait            ;Write to PIT
  828.     mov    dx,PCnt1Port        ;Point to PIT counter 1
  829.     mov    al,bl            ;Get low order byte of divisor
  830.     call    PutWait            ;Write to PIT
  831.     mov    al,bh            ;Get high order    byte of    divisor
  832.     call    PutWait            ;Write to PIT
  833.     mov    dx,UCtrlPort        ;Point to USART    control    port
  834.     mov    al,ah            ;Get USART mode    byte
  835.     cli                ;No interrupts
  836.     call    PutWait
  837.     mov    al,mask    URTS + mask UDTR + mask    URxEn +    mask UTxEn
  838.     mov    LastCntl,al        ;Save USART control byte
  839.     or    al,mask    UErrClr        ;Reset USART error flags
  840.     call    PutWait            ;Send it to USART control port
  841.     sti                ;Allow interrupts
  842.     jmp    CStatus            ;Get status and    return
  843.  
  844. CSetChanFF:
  845.     ret                ;Return    to caller
  846.  
  847. CSetChan endp
  848.  
  849.     subttl    Send a character to channel with wait
  850.     page
  851. CTxWait    proc    near
  852. ;
  853. ;    Enqueues a character into a channel's transmit buffer.  Waits
  854. ;        forever for    space in the buffer.
  855. ;
  856. ;    Entry conditions:
  857. ;        [bp].RegAL = character to enqueue
  858. ;        [bp].RegDX = channel
  859. ;    Exit conditions:
  860. ;        [bp].RegAX = channel status
  861. ;
  862.     cmp    [bp].RegDX,ChanFF    ;Dummy channel?
  863.     je    CTxWtChanFF        ;Yes - just return
  864. CTxWtAgain:
  865.     cmp    TBufCnt,TBufSize    ;Is the    transmit buffer    full?
  866.     jae    CTxWtAgain        ;Yes - continue    on
  867.     mov    bx,TBufNext        ;Point to next free char
  868.     mov    al,[bp].RegAL        ;Get char from stack frame
  869.     mov    TBuf[bx],al        ;Place char into buffer
  870.     inc    TBufCnt            ;Increment transmit buffer count
  871.     call    TxEnable        ;Enable    transmitter
  872.     cmp    bx,TBufSize-1        ;Past end?
  873.     jae    CTxWaitWrap        ;Yes - go wrap
  874.     inc    TBufNext        ;Save pointer to next free char
  875.     jmp    short CStatus        ;Get status and    return
  876.  
  877. CTxWaitWrap:
  878.     mov    TBufNext,0        ;Save pointer to next free char
  879.     jmp    short CStatus        ;Get status and    return
  880.  
  881.  
  882. CTxWtChanFF:
  883.     ret                ;Return    to caller
  884.  
  885. CTxWait    endp
  886.  
  887.     subttl    Receive    a character from a channel with    wait
  888.     page
  889. CRxWait    proc    near
  890. ;
  891. ;    Dequeues a character from a channel's receive buffer.  Waits
  892. ;        forever for    a character.
  893. ;
  894. ;    Entry conditions:
  895. ;        [bp].RegDX = channel
  896. ;    Exit conditions:
  897. ;        [bp].RegAL = character
  898. ;        [bp].RegAH = 00h
  899. ;
  900.     cmp    [bp].RegDX,ChanFF    ;Dummy channel?
  901.     je    CRxWtRet        ;Yes - just return
  902. CRxWtAgain:
  903.     cmp    RBufCnt,0        ;Anything in the buffer?
  904.     je    CRxWtAgain        ;No - keep trying
  905.     mov    bx,RBufFirst        ;Point to next recvd char
  906.     mov    al,byte    ptr RBuf[bx]    ;Get it    into al
  907.     xor    ah,ah            ;Clear ax
  908.     mov    [bp].RegAX,ax        ;Store in register frame
  909.     dec    RBufCnt            ;Decrement buffer count
  910.     cmp    RBufCnt,RBufLimit    ;Below cutoff point
  911.     ja    CRxWtNoRFlow        ;No - continue
  912.     call    RxUnhold        ;Yes - unhold receiver
  913. CRxWtNoRFlow:
  914.     cmp    bx,RBufSize-1        ;Past end?
  915.     jae    CRxWtWrap        ;Yes - go wrap buffer
  916.     inc    RBufFirst        ;Save the new start pointer
  917. CRxWtRet:
  918.     ret                ;Return    to caller
  919.  
  920. CRxWtWrap:
  921.     mov    RBufFirst,0        ;Save the new start pointer
  922.     ret                ;Return    to caller
  923.  
  924. CRxWait    endp
  925.  
  926.     subttl    Get the    status of a channel
  927.     page
  928. CStatus    proc    near
  929. ;
  930. ;    Gets a channel's status
  931. ;
  932. ;    Entry conditions:
  933. ;        [bp].RegDX = channel
  934. ;    Exit conditions:
  935. ;        [bp].RegAX = channel status
  936. ;
  937.     cmp    [bp].RegDX,ChanFF    ;Dummy channel
  938.     je    CStatRet        ;Yes - just return
  939.     mov    dx,0008h        ;Initialize status
  940.     cmp    RBufCnt,0        ;Anything in receiver buffer
  941.     je    CStatTxRdy        ;No - continue
  942.     or    dh,mask    ARxRdy        ;Yes - indicate    RxRDY
  943. CStatTxRdy:
  944.     cmp    TBufCnt,TBufSize    ;Buffer    full?
  945.     jae    CStatDCD        ;Yes - continue
  946.     or    dh,mask    ATxEmp        ;No - indicate transmit    hold reg empty
  947.     cmp    TBufCnt,0        ;Anything in transmit buffer?
  948.     jne    CStatOvr        ;Yes - continue
  949.     or    dh,mask    ATxRdy        ;No - indicate transmit    shift reg empty
  950. CStatOvr:
  951.     test    RFlag,mask ROvr        ;Has an    overrun    occurred?
  952.     jz    CStatDCD        ;No - continue
  953.     or    dh,AOvrErr        ;Indicate overrun
  954.     and    RFlag,not mask ROvr    ;Reset overrun indicator
  955. CStatDCD:
  956.     cli                ;No interrupts
  957.     mov    al,LastCntl        ;Get USART command
  958.     or    al,mask    UErrClr        ;Reset USART error flags
  959.     out    UCtrlPort,al        ;Send command to USART
  960.     in    al,MStatPort        ;Get modem status
  961.     and    al,mask    MDCD        ;Strip off all but DCD
  962.     xor    al,mask    MDCD        ;Reverse the bit
  963.     shl    al,6            ;Shift into high order bit
  964.     sti                ;Interrupts ok
  965.     or    dl,al            ;Save in DL
  966.     mov    [bp].RegAX,dx        ;Store status in register frame
  967. CStatRet:
  968.     ret                ;Return    to caller
  969.  
  970. CStatus    endp
  971.  
  972.     subttl    Open a channel
  973.     page
  974. COpen    proc    near
  975. ;
  976. ;    Open a channel
  977. ;
  978. ;    Entry conditions:
  979. ;        [bp].RegDX = channel
  980. ;    Exit conditions:
  981. ;        [bp].RegAX = 1954h
  982. ;        [bp].RegBL = Highest function supported    (not including 7E/7F)
  983. ;        [bp].RegBH = FOSSIL spec revision supported
  984. ;
  985.     cmp    [bp].RegDX,ChanFF    ;Dummy channel
  986.     je    COpenExit        ;Yes - just return success
  987.     call    CClose            ;Reset the channel
  988.     mov    [bp].RegAL,01h        ;Set AL in stack frame
  989.     call    CDTR            ;Cancel any flow control
  990. COpenExit:
  991.     mov    [bp].RegAX,Magic    ;Put return values in reg frame
  992.     mov    [bp].RegBL,MaxFun    ;Highest function supported
  993.     mov    [bp].RegBH,Version    ;Spec revision supported
  994.     ret                ;Return    to caller
  995.  
  996. COpen    endp
  997.  
  998.     subttl    Close a    channel
  999.     page
  1000. CClose    proc    near
  1001. ;
  1002. ;    Close a    channel
  1003. ;
  1004. ;    Entry conditions:
  1005. ;        [bp].RegDX = channel
  1006. ;    Exit conditions:
  1007. ;        none
  1008. ;
  1009.     cmp    [bp].RegDX,ChanFF    ;Dummy channel?
  1010.     je    CCloseRet        ;Yes - just return
  1011.     xor    bx,bx
  1012.     cli                ;No interrupts
  1013.     mov    TBufFirst,bx        ;Zero transmit buffer pointers
  1014.     mov    TBufNext,bx
  1015.     mov    TBufCnt,bx
  1016.     mov    RBufFirst,bx        ;Zero receive buffer pointers
  1017.     mov    RBufNext,bx
  1018.     mov    RBufCnt,bx
  1019.     mov    RFlag,bl        ;Reset receiver    flags
  1020.     mov    TFlag,bl        ;Reset transmitter hold    flags
  1021.     mov    FFlag,bl        ;Reset flow control flags
  1022.     mov    XChar,bl        ;Cancel    any pending Xoff
  1023.     mov    al,LastCntl        ;Get current USART command
  1024.     and    al,not mask UBrk    ;Reset break bit
  1025.     or    al,mask    URTS + mask UTxEn + mask URxEn    ;Set up    USART command
  1026.     mov    LastCntl,al        ;Save new USART    command
  1027.     or    al,mask    UErrCLr        ;Set error clear bit
  1028.     out    UCtrlPort,al        ;Send new command to USART
  1029.     push    [bp].RegAX        ;Save AX from stack frame
  1030.     mov    [bp].RegAL,0        ;Zero AL in stack frame
  1031.     sti                ;Allow interrupts
  1032.     call    CFlowCtl        ;Cancel any flow control
  1033.     pop    [bp].RegAX        ;Restore AX in stack frame
  1034. CCloseRet:
  1035.     ret                ;Return    to caller
  1036.  
  1037. CClose    endp
  1038.  
  1039.     subttl    Toggle a channel's DTR line
  1040.     page
  1041. CDTR   proc    near
  1042. ;
  1043. ;    Toggle a channel's DTR line
  1044. ;
  1045. ;    Entry conditions:
  1046. ;        [bp].RegAH = 06h
  1047. ;        [bp].RegAL = 00h - Lower DTR
  1048. ;             Not 00h - Raise DTR
  1049. ;        [bp].RegDX = channel
  1050. ;    Exit conditions:
  1051. ;        none
  1052. ;
  1053.     cmp    [bp].RegDX,ChanFF    ;Dummy channel
  1054.     je    CDTRRet            ;Yes - just return
  1055.     cli                ;No interrupts
  1056.     mov    al,LastCntl        ;Get last control byte
  1057.     cmp    [bp].RegAL,00h        ;Request to lower DTR?
  1058.     jne    CDTRSet            ;No - check for    set
  1059.     and    al,not mask UDTR    ;Mask DTR off
  1060.     jmp    short CDTRExit        ;Go output control byte
  1061. CDTRSet:
  1062.     or    al,mask    UDTR        ;Mask DTR on
  1063. CDTRExit:
  1064.     out    UCtrlPort,al        ;Send control byte to USART
  1065.     mov    LastCntl,al        ;Save new control byte
  1066.     nop                ;Wait a    bit
  1067.     nop
  1068.     sti                ;Interrupts ok
  1069. CDTRRet:
  1070.     ret                ;Return    to caller
  1071.  
  1072. CDTR    endp
  1073.  
  1074.  
  1075.     subttl    Return timer parameters
  1076.     page
  1077. TTickParm proc    near
  1078. ;
  1079. ;    This routine returns information about this machine's interval timer
  1080. ;
  1081. ;    Entry conditions
  1082. ;        none
  1083. ;    Exit conditions:
  1084. ;        [bp].RegAL = timer tick    interrupt #
  1085. ;        [bp].RegAH = Ticks per second
  1086. ;        [bp].RegDX = milliseconds per tick
  1087. ;
  1088.     mov    [bp].RegAL,1Ch        ;Timer interrupt #
  1089.     mov    [bp].RegAH,20        ;Ticks per second
  1090.     mov    [bp].RegDX,50        ;Millisecs per tick
  1091.     ret                ;Return    to caller
  1092.  
  1093. TTickParm endp
  1094.  
  1095.     subttl    Flush a    channel's transmit buffer
  1096.     page
  1097. CFlushOut proc near
  1098. ;
  1099. ;    Flush a    channel's transmit buffer
  1100. ;
  1101. ;    Entry conditions:
  1102. ;        [bp].RegDX = channel
  1103. ;    Exit conditions:
  1104. ;        none
  1105. ;
  1106. CFlushAgain:
  1107.     cmp    [bp].RegDX,ChanFF    ;Dummy channel
  1108.     je    CFlushRet        ;Yes - just return
  1109.     cmp    TBufCnt,0        ;Is transmit buffer empty?
  1110.     jne    CFlushAgain        ;No - wait for it to be
  1111. CFlushRet:
  1112.     ret                ;Yes - return to caller
  1113.  
  1114. CFlushOut endp
  1115.  
  1116.     subttl    Purge a    channel's transmit buffer
  1117.     page
  1118. CPurOut    proc    near
  1119. ;
  1120. ;    Purges (discards) a channel's transmit buffer
  1121. ;
  1122. ;    Entry conditions:
  1123. ;        [bp].RegDX = channel
  1124. ;    Exit conditions:
  1125. ;        none
  1126. ;
  1127.     cmp    [bp].RegDX,ChanFF    ;Dummy channel
  1128.     je    CPurOutRet        ;Yes - just return
  1129.     xor    bx,bx
  1130.     cli                ;Disable interrupts
  1131.     mov    TBufFirst,bx        ;Zero transmitter buffer pointers
  1132.     mov    TBufNext,bx
  1133.     mov    TBufCnt,bx
  1134.     sti                ;Enable    interrupts
  1135. CPurOutRet:
  1136.     ret
  1137.  
  1138. CPurOut    endp
  1139.  
  1140.     subttl    Purge a    channel's receive buffer
  1141.     page
  1142. CPurIn    proc    near
  1143. ;
  1144. ;    Purges (discards) a channel's receive buffer
  1145. ;
  1146. ;    Entry conditions:
  1147. ;        [bp].RegDX = channel
  1148. ;    Exit conditions:
  1149. ;        none
  1150. ;
  1151.     cmp    [bp].RegDX,ChanFF    ;Dummy channel?
  1152.     je    CPurInRet        ;Yes - just return
  1153.     xor    bx,bx
  1154.     cli                ;No interrupts
  1155.     mov    RBufFirst,bx        ;Zero receiver buffer pointers
  1156.     mov    RBufNext,bx
  1157.     mov    RBufCnt,bx
  1158.     call    RxUnhold        ;Cancel    any handshaking    holds
  1159.     sti                ;Interrupts ok
  1160. CPurInRet:
  1161.     ret
  1162.  
  1163. CPurIn    endp
  1164.  
  1165.     subttl    Send a character to a channel without wait
  1166.     page
  1167. CTxNowait proc    near
  1168. ;
  1169. ;    Enqueue    a character into the a channel's transmit buffer.  Returns
  1170. ;        without waiting if buffer is full.
  1171. ;
  1172. ;    Entry conditions:
  1173. ;        [bp].RegAL = character to enqueue
  1174. ;        [bp].RegDX = channel
  1175. ;    Exit conditions:
  1176. ;        [bp].RegAX = 0000h    - operation was    not successful
  1177. ;                 0001h    - operation was    successful
  1178. ;
  1179.     cmp    [bp].RegDX,ChanFF    ;Dummy channel?
  1180.     je    CTxNwRet        ;Yes - just return
  1181.     cmp    TBufCnt,TBufSize    ;Is the    transmit buffer    full?
  1182.     jae    CTxNwNoroom        ;Yes - go indicate failure
  1183.     mov    bx,TBufNext        ;Point to next free char
  1184.     mov    al,[bp].RegAL        ;Get char from stack frame
  1185.     mov    TBuf[bx],al        ;Place char into buffer
  1186.     mov    [bp].RegAX,1        ;Set successful    return code
  1187.     inc    TBufCnt            ;Increment xmit    buffer count
  1188.     call    TxEnable        ;Enable    transmitter
  1189.     cmp    bx,TBufSize-1        ;Past end?
  1190.     jae    CTxNwWrap        ;Yes - go wrap buffer
  1191.     inc    TBufNext        ;Save pointer to next free char
  1192. CTxNwRet:
  1193.     ret                ;Return    to caller
  1194.  
  1195. CTxNwNoroom:
  1196.     mov    [bp].RegAX,0        ;Set unsuccessful return code
  1197.     ret                ;Return    to caller
  1198.  
  1199. CTxNwWrap:
  1200.     mov    TBufNext,0        ;Save pointer to next free char
  1201.     ret                ;Return    to caller
  1202.  
  1203. CTxNowait endp
  1204.  
  1205.     subttl    Receive    a character from a channel without wait
  1206.     page
  1207. CRxNowait proc near
  1208. ;
  1209. ;    Peeks for a character from a channel's receive buffer
  1210. ;        and    returns    it.  Returns without waiting if    buffer
  1211. ;        is empty.  The character is    not removed from the receive
  1212. ;        buffer.
  1213. ;
  1214. ;    Entry conditions:
  1215. ;        [bp].RegDX = channel
  1216. ;    Exit conditions:
  1217. ;        [bp].RegAX = FFFFh    (operation was not successful)
  1218. ;        [bp].RegAL = char recvd    (operation was successful)
  1219. ;        [bp].RegAH = 00h    (operation was successful)
  1220. ;
  1221.     cmp    [bp].RegDX,ChanFF    ;Dummy channel?
  1222.     je    CRxNwRet        ;Yes - just return
  1223.     cmp    RBufCnt,0        ;Anything in the buffer?
  1224.     je    CRxNwEmpty        ;No - go indicate failure
  1225.     mov    bx,RBufFirst        ;Point to next recvd char
  1226.     mov    al,byte    ptr RBuf[bx]    ;Get it    into register
  1227.     xor    ah,ah            ;Clear ah
  1228.     mov    [bp].RegAX,ax        ;Store result in register frame
  1229. CRxNwRet:
  1230.     ret                ;Return    to caller
  1231.  
  1232. CRxNwEmpty:
  1233.     mov    [bp].RegAX,0FFFFh    ;Set unsuccessful return code
  1234.     ret                ;Return    to caller
  1235.  
  1236. CRxNowait endp
  1237.  
  1238.     subttl    Receive    character from keyboard    without    wait
  1239.     page
  1240. KRxNowait proc near
  1241. ;
  1242. ;    Receives a character from the keyboard.     Returns immediately
  1243. ;        if a character is not available.
  1244. ;
  1245. ;    Entry conditions:
  1246. ;        none
  1247. ;    Exit conditions:
  1248. ;        [bp].RegAX = FFFFh        (operation was not successful)
  1249. ;        [bp].RegAL = ASCII value    (operation was successful)
  1250. ;        [bp].RegAH = keyboard scan code    (operation was successful)
  1251. ;
  1252.     mov    ah,KeybdScan        ;Set BIOS function
  1253.     int    BiosKeybd        ;Call the BIOS
  1254.     jnz    KRxNwReady        ;If char present, get out
  1255.     mov    ax,0FFFFh        ;Indicate no char present
  1256. KRxNwReady:
  1257.     mov    [bp].RegAX,ax        ;Put result in register    frame
  1258.     ret                ;Return    to caller
  1259.  
  1260. KRxNowait endp
  1261.  
  1262.     subttl    Receive    character from keyboard    with wait
  1263.     page
  1264. KRxWait    proc near
  1265. ;
  1266. ;    Receives a character from the keyboard.     Waits forever
  1267. ;        for    a character.
  1268. ;
  1269. ;    Entry conditions:
  1270. ;        none
  1271. ;    Exit conditions:
  1272. ;        [bp].RegAL = ASCII value
  1273. ;        [bp].RegAH = keyboard scan code
  1274. ;
  1275.     mov    ah,KeybdRead        ;Set BIOS function
  1276.     int    BiosKeybd        ;Call the BIOS
  1277.     mov    [bp].RegAX,ax        ;Put result in register    frame
  1278.     ret                ;Return    to caller
  1279.  
  1280. KRxWait    endp
  1281.  
  1282.     subttl    Set/reset flow control
  1283.     page
  1284. CFlowCtl proc    near
  1285. ;
  1286. ;    Enable/disable flow control.  The Tandy    2000 implements
  1287. ;      CTS handshaking in hardware.    There is no way    to disable
  1288. ;      this handshaking, as the 8251A USART will simply not transmit
  1289. ;      data until CTS is true.  DSR/DTR handshaking is not supported
  1290. ;      at this time.
  1291. ;
  1292. ;    Entry conditions:
  1293. ;        [bp].RegAL = xxxxxxx0 -    Disable    transmit Xon/Xoff
  1294. ;                 xxxxxxx1 -    Enable transmit    Xon/Xoff
  1295. ;                 xxxxxx0x -    Disable    CTS/RTS
  1296. ;                 xxxxxx1x -    Enable CTS/RTS
  1297. ;                 xxxx0xxx -    Disable    receive    Xon/Xoff
  1298. ;                 xxxx1xxx -    Enable receive Xon/Xoff
  1299. ;        [bp].RegDX = channel
  1300. ;    Exit conditions:
  1301. ;        none
  1302. ;
  1303.     cmp    [bp].RegDX,ChanFF    ;Dummy channel?
  1304.     je    CFlRet            ;Yes - just return
  1305.     cli                ;No interrupts
  1306.     mov    al,LastCntl        ;Copy USART command
  1307.     test    [bp].RegAL,mask    FlTXon    ;Enable    transmit Xon/Xoff?
  1308.     jz    CFlTXonOff        ;No - disable it
  1309.     or    FFlag,mask FTXon    ;Yes - set indicator
  1310.     jmp    short CFlRXon        ;Check receiver    Xon/Xoff
  1311. CFlTXonOff:
  1312.     and    FFlag,not mask FTXon    ;Reset indicator
  1313.     test    TFlag,mask TXonHld    ;Has transmitter been held?
  1314.     jz    CFlRXon            ;Check receiver    Xon/Xoff
  1315.     and    TFlag,not mask TXonHld    ;Cancel    existing hold
  1316.     or    al,mask    UTxEn        ;Enable    transmitter
  1317. CFlRXon:
  1318.     test    [bp].RegAL,mask    FlRXon    ;Enable    receive    Xon/Xoff?
  1319.     jz    CFlRXonOff        ;No - disable it
  1320.     or    FFlag,mask FRXon    ;Set indicator
  1321.     mov    XChar,0            ;Cancel    any pending Xoff
  1322.     jmp    short CFlRTS        ;Check RTS/CTS
  1323. CFlRXonOff:
  1324.     and    FFlag,not mask FRXon    ;Reset indicator
  1325.     cmp    LastXChar,Xoff        ;Was Xoff sent?
  1326.     jne    CFlRTS            ;No - check RTS/CTS
  1327.     mov    XChar,Xon        ;Stuff Xon into    transmitter
  1328.     or    al,mask    UTxEn        ;Enable    transmitter
  1329. CFlRTS:
  1330.     test    [bp].RegAL,FlRTS    ;Enable    RTS handshaking?
  1331.     jz    CFlRTSOff        ;No - disable RTS handshaking
  1332.     or    FFlag,mask FRTS        ;Yes - set indicator
  1333.     jmp    short CFlOut        ;Output    USART control byte (if needed)
  1334. CFlRTSOff:
  1335.     and    FFlag,not mask FRTS    ;Reset indicator
  1336.     or    al,mask    URTS        ;Set RTS bit in    USART control byte
  1337. CFlOut:
  1338.     cmp    al,LastCntl        ;Has USART control byte    changed?
  1339.     je    CFlEXit            ;No - don't need to send it
  1340.     out    UCtrlPort,al        ;Send it to the    USART
  1341.     mov    LastCntl,al        ;Save new USART    control    byte
  1342.     nop                ;Wait a    bit
  1343.     nop
  1344. CFlExit:
  1345.     sti                ;Interrupts ok
  1346. CFlRet:
  1347.     ret                ;Return    to caller
  1348.  
  1349. CFlowCtl endp
  1350.  
  1351.     subttl    Set/reset CTL-C/CTL-K checking
  1352.     page
  1353. CCtlChk    proc    near
  1354. ;
  1355. ;    Enable/disable Ctl-C/Ctl-K checking;  logout and clear current
  1356. ;      Ctl-C/Ctl-K mask.  Also enable/disable the transmitter
  1357. ;
  1358. ;    Entry conditions:
  1359. ;        [bp].RegAL = xxxxxxx0 -    Disable    Ctl-C/Ctl-K checking
  1360. ;                 xxxxxxx1 -    Enable Ctl-C/Ctl-K checking
  1361. ;                 xxxxxx0x -    Disable    transmitter
  1362. ;                 xxxxxx1x -    Enable transmitter
  1363. ;        [bp].RegDX = channel
  1364. ;    Exit conditions:
  1365. ;        [bp].RegAX = 0000h - Ctl-C/Ctl-K not received since last logout
  1366. ;                 0001h - Ctl-C/Ctl-K received since    last logout
  1367. ;
  1368.     cmp    [bp].RegDX,ChanFF    ;Dummy channel?
  1369.     je    CCtlRet            ;Yes - just return
  1370.     test    [bp].RegAL,02h        ;Disable transmitter?
  1371.     jz    CCtlTxEn        ;No - enable it
  1372.     or    TFlag,mask TPrgHld    ;Indicate program hold
  1373.     jmp    short CCtlCont        ;Go output control byte
  1374. CCtlTxEn:
  1375.     and    TFlag,not mask TPrgHld    ;Indicate no programmer    hold
  1376.     call    TxEnable        ;Enable    transmitter
  1377. CCtlCont:
  1378.     test    [bp].RegAL,01h        ;Start Ctl-C/Ctl-K checking?
  1379.     cli                ;No interrupts
  1380.     jz    CCtlOff            ;No - stop Ctl-C/Ctl-K checking?
  1381.     or    RFlag,mask RCtlChk    ;Indicate checking
  1382.     jmp    short CCtlLog
  1383. CCtlOff:
  1384.     and    RFlag,not mask RCtlChk    ;Indicate no checking
  1385.     jmp    short CCtlClr        ;Clear things up
  1386. CCtlLog:
  1387.     mov    [bp].RegAX,0        ;Zero mask
  1388.     test    RFlag,mask RCtlRcv    ;Has a break been received?
  1389.     jz    CCtlClr            ;No - leave mask zero
  1390.     mov    [bp].RegAX,1        ;Yes - indicate    break to caller
  1391. CCtlClr:
  1392.     and    RFlag,not mask RCtlRcv    ;Zero break flag
  1393.     sti                ;Interrupts ok
  1394. CCtlRet:
  1395.     ret                ;Return    to caller
  1396.  
  1397. CCtlChk    endp
  1398.  
  1399.     subttl    Set cursor location
  1400.     page
  1401. DSetCurLoc proc    near
  1402. ;
  1403. ;    Set current cursor position
  1404. ;
  1405. ;    Entry conditions
  1406. ;        [bp].RegDH = row
  1407. ;        [bp].RegDL = column
  1408. ;    Exit conditions:
  1409. ;        none
  1410. ;
  1411.     mov    dx,[bp].RegDX        ;Get parms from    register frame
  1412.     mov    ah,VideoSetCurPos    ;Set BIOS function
  1413.     xor    bh,bh            ;Select    page 0
  1414.     int    BiosVideo        ;Call BIOS
  1415.     ret                ;Return    to caller
  1416.  
  1417. DSetCurLoc endp
  1418.  
  1419.     subttl    Get cursor location
  1420.     page
  1421. DGetCurLoc proc    near
  1422. ;
  1423. ;    Get current cursor position
  1424. ;
  1425. ;    Entry conditions
  1426. ;        none
  1427. ;    Exit conditions:
  1428. ;        [bp].RegDH = row
  1429. ;        [bp].RegDL = column
  1430. ;
  1431.     mov    ah,VideoGetCurPos    ;Set BIOS function
  1432.     xor    bh,bh            ;Select    page 0
  1433.     int    BiosVideo        ;Call BIOS
  1434.     mov    [bp].RegDX,dx        ;Store results in register frame
  1435.     ret                ;Return    to caller
  1436.  
  1437. DGetCurLoc endp
  1438.  
  1439.     subttl    Put character to display using ANSI.SYS
  1440.     page
  1441. DPutDos    proc    near
  1442. ;
  1443. ;    Put a character    to the display via ANSI.SYS
  1444. ;
  1445. ;    Entry conditions
  1446. ;        [bp].RegAL = char to output
  1447. ;    Exit conditions:
  1448. ;        none
  1449.  
  1450.     mov    dl,[bp].RegAL        ;Get char from register    frame
  1451.     dir_con_io            ;Write char using ANSI
  1452.     ret                ;Return    to caller
  1453.  
  1454. DPutDos    endp
  1455.  
  1456.     subttl    Watch channel and reboot if CD lost
  1457.     page
  1458. CWatchDog proc    near
  1459. ;
  1460. ;    This routine adds/deletes a small routine to/from the timer tick.  This
  1461. ;        routine checks for CD on a channel.    If CD is false,     the system is
  1462. ;        rebooted.
  1463. ;
  1464. ;    Entry conditions:
  1465. ;        [bp].RegAL = 00h - Disable watchdog
  1466. ;        [bp].RegAL = 01h - Enable watchdog
  1467. ;        [bp].RegDX = channel
  1468. ;    Exit conditions:
  1469. ;        none
  1470. ;
  1471.     cmp    [bp].RegDX,ChanFF    ;Dummy channel
  1472.     je    CWatchDogRet        ;Yes - just return
  1473.     push    [bp].RegES        ;Save current stack frame values
  1474.     push    [bp].RegDX
  1475.     push    [bp].RegAX
  1476.     mov    [bp].RegES,cs        ;Get segment of    watchdog routine
  1477.     mov    [bp].RegDX,offset WatchDog    ;Get offset
  1478.     call    TTickMgr        ;Install tick routine
  1479.     pop    [bp].RegAX        ;Restore caller's stack frame
  1480.     pop    [bp].RegDX
  1481.     pop    [bp].RegES
  1482. CWatchDogRet:
  1483.     ret                ;Return    to caller
  1484.  
  1485. CWatchDog endp
  1486.  
  1487.     subttl    Put char to console bypassing DOS
  1488.     page
  1489. DPutBios proc    near
  1490. ;
  1491. ;    Put a character    to the display bypassing DOS
  1492. ;
  1493. ;    Entry conditions
  1494. ;        [bp].RegAL = char to output
  1495. ;    Exit conditions:
  1496. ;        none
  1497. ;
  1498.     mov    al,[bp].RegAL
  1499.     mov    ah,VideoWrTty        ;Set BIOS function
  1500.     int    BiosVideo        ;Call BIOS
  1501.     ret                ;Return    to caller
  1502.  
  1503. DPutBios endp
  1504.  
  1505.     subttl    Manage the timer tick chain
  1506.     page
  1507. TTickMgr proc    near
  1508. ;
  1509. ;    This routine adds and deletes routines from the    timer tick chain.
  1510. ;        A maximum of eight routines    are supported.    If a request is
  1511. ;        made to delete a routine already present in    the chain,  the
  1512. ;        old    version    is deleted,  and the new one added to the top of
  1513. ;        the    chain.    The chain of routines is maintained as a push/pop
  1514. ;        stack.
  1515. ;
  1516. ;    Entry conditions:
  1517. ;        [bp].RegAL = 00h - Delete a routine from the chain
  1518. ;        [bp].RegAL = 01h - Add a routine to the    chain
  1519. ;        [bp].RegES = Segment of    routine
  1520. ;        [bp].RegDX = Offset of routine
  1521. ;    Exit conditions:
  1522. ;        [bp].RegAX = 0000h - Operation was successful
  1523. ;                 FFFFh - Operation was unsuccessful
  1524. ;
  1525.     test    [bp].RegAL,1        ;Request to add    routine?
  1526.     jz    TTDelete        ;No - must be delete
  1527.     call    TTFind            ;It is add - check for duplicate
  1528.     and    ax,ax            ;Check return code
  1529.     js    TTAdd            ;No dups - just    add it
  1530.     call    TTSnip            ;Remove    old version of routine
  1531.     and    ax,ax            ;Everything ok?
  1532.     js    TTErr            ;No - error
  1533. TTAdd:
  1534.     call    TTPush            ;Push new routine pointer
  1535.     jmp    short TTRet        ;Get out
  1536. TTDelete:
  1537.     call    TTFind            ;Find requested    routine
  1538.     and    ax,ax            ;Found?
  1539.     js    TTErr            ;No - error
  1540.     call    TTSnip            ;Yes - snip it from chain
  1541. TTRet:
  1542.     mov    [bp].RegAX,ax        ;Put return code in stack frame
  1543.     ret                ;Return    to caller
  1544. TTErr:
  1545.     mov    [bp].RegAX,0FFFFh    ;Indicate failure
  1546.     ret                ;Return    to caller
  1547.  
  1548. TTickMgr endp
  1549.  
  1550.     subttl    Find a routine in the timer tick chain
  1551.     page
  1552. TTFind    proc    near
  1553.  
  1554.     mov    bx,offset TTRoutTab    ;Get routine table address
  1555.     xor    si,si            ;Zero the table    index
  1556.     mov    cx,TTRoutCnt        ;Get number of routines
  1557.     and    cx,cx            ;Are there any?
  1558.     jz    TTFindNotFound        ;No - skip the search
  1559. TTFindLoop:
  1560.     mov    ax,[bp].RegES        ;Get segment of    search argument
  1561.     cmp    ax,[bx][si]+2        ;Equal to segment of table element?
  1562.     jne    TTFindIncr        ;No - try next table element
  1563.     mov    ax,[bp].RegDX        ;Get offset of search argument
  1564.     cmp    ax,[bx][si]        ;Equal to offset of table element?
  1565.     je    TTFindFound        ;Yes - exit loop
  1566. TTFindIncr:                ;No - keep trying
  1567.     add    si,4            ;Increment the table index
  1568.     loop    TTFindLoop        ;If more table elements,  try again
  1569. TTFindNotFound:
  1570.     mov    ax,0FFFFh        ;No luck - set no-hit return code
  1571.     jmp    short TTFindRet        ;Go return to caller
  1572. TTFindFound:                ;Search    successful - convert index
  1573.     mov    ax,TTRoutCnt        ;  to relative table entry index
  1574.     sub    ax,cx
  1575. TTFindRet:
  1576.     ret                ;Return    to caller
  1577.  
  1578. TTFind    endp
  1579.  
  1580.     subttl    Snip a routine from the    timer tick chain
  1581.     page
  1582. TTSnip    proc    near
  1583.  
  1584.     mov    cx,TTRoutCnt        ;Get the number    of routines
  1585.     and    cx,cx            ;Anything to delete?
  1586.     jz    TTSnipErr        ;No - error
  1587.     cmp    ax,TTRoutCnt-1        ;Trying    to delete past last routine?
  1588.     ja    TTSnipErr        ;Yes - error
  1589.     dec    cx            ;Convert to displacement
  1590.     jz    TTSnipDecr        ;No pop    needed for last    routine
  1591.     sub    cx,ax            ;Calculate number of moves
  1592.     mov    bx,offset TTRoutTab    ;Point base to routine table
  1593.     shl    ax,2            ;Convert routine number    to an offset
  1594.     add    bx,ax            ;  and add it to the base
  1595.     xor    si,si            ;Zero the loop index
  1596.     cli                ;No interrupts
  1597. TTSnipLoop:                ;Pop remaining routines
  1598.     mov    ax,[bx][si]+6        ;Move segment
  1599.     mov    [bx][si]+2,ax
  1600.     mov    ax,[bx][si]+4        ;Move offset
  1601.     mov    [bx][si],ax
  1602.     add    si,4            ;Increment index
  1603.     loop    TTSnipLoop        ;Repeat    for remaining routines
  1604. TTSnipDecr:
  1605.     dec    TTRoutCnt        ;Decrement routine counter
  1606.     sti                ;Allow interrupts
  1607.     xor    ax,ax            ;Set successful    return code
  1608.     ret                ;Return    to caller
  1609. TTSnipErr:
  1610.     mov    ax,0FFFFh        ;Set unsuccessful return code
  1611.     ret                ;Return    to caller
  1612.  
  1613. TTSnip    endp
  1614.  
  1615.     subttl    Push a new routine onto    the timer tick chain
  1616.     page
  1617. TTPush    proc    near
  1618.  
  1619.     cmp    TTRoutCnt,TTRoutLim    ;Chain full?
  1620.     je    TTPushErr        ;Yes - error
  1621.     mov    bx,offset TTRoutTab    ;Set base to start of table
  1622.     mov    cx,TTRoutCnt        ;Get number of routines
  1623.     and    cx,cx            ;Are there any?
  1624.     jz    TTPushNew        ;No - just add new routine
  1625.     mov    si,cx            ;Get starting index
  1626.     dec    si            ;Convert to displacment
  1627.     shl    si,2
  1628.     cli                ;No interrupts
  1629. TTPushLoop:
  1630.     mov    ax,[bx][si]+2        ;Move segment
  1631.     mov    [bx][si]+6,ax
  1632.     mov    ax,[bx][si]        ;Move offset
  1633.     mov    [bx][si]+4,ax
  1634.     sub    si,4            ;Decrement index
  1635.     loop    TTPushLoop        ;Repeat    for remaining routines
  1636. TTPushNew:
  1637.     mov    ax,[bp].RegES        ;Insert    segment    of new routine
  1638.     mov    [bx]+2,ax
  1639.     mov    ax,[bp].RegDX        ;Insert    offset of new routine
  1640.     mov    [bx],ax
  1641.     inc    TTRoutCnt        ;Increment routine counter
  1642.     sti                ;Allow interrupts
  1643.     xor    ax,ax            ;Indicate success
  1644.     ret                ;Return    to caller
  1645. TTPushErr:
  1646.     mov    ax,0FFFFh        ;Indicate failure
  1647.     ret                ;Return    to caller
  1648.  
  1649. TTPush    endp
  1650.  
  1651.     subttl    Reboot the system
  1652.     page
  1653. Reboot    proc    near
  1654. ;
  1655. ;    This routine reboots the system    using the BIOS reboot interrupt.
  1656. ;        The    T2K only supports hard reboots.
  1657. ;
  1658. ;    Entry conditions:
  1659. ;        none
  1660. ;    Exit conditions:
  1661. ;        none
  1662. ;
  1663.     int    BiosBoot        ;Reboot    via BIOS
  1664.  
  1665. Reboot    endp
  1666.  
  1667.     subttl    Dequeue    a block    of characters from a channel
  1668.     page
  1669. CBlockRead proc    near
  1670. ;
  1671. ;    This routine dequeues a    block of characters from a channel's
  1672. ;      receive buffer into a    user provided buffer.  Up to 64k
  1673. ;      characters may be dequeued with one call.  The routine
  1674. ;      only as many characters as the buffer    contains at the    time
  1675. ;      of the call.
  1676. ;
  1677. ;    Entry conditions:
  1678. ;        [bp].RegCX = Maximum number of characters to dequeue
  1679. ;        [bp].RegDX = channel
  1680. ;        [bp].RegES = Segment of    user's buffer
  1681. ;        [bp].RegDI = Offset of user's buffer
  1682. ;    Exit conditions:
  1683. ;        [bp].RegAX = Number of characters dequeued into
  1684. ;                   the user's buffer
  1685. ;
  1686.     cmp    [bp].RegDX,ChanFF    ;Dummy channel?
  1687.     je    CBlkRdRet        ;Yes - just return
  1688.     mov    bx,RBufCnt        ;Get number of chars in    buffer
  1689.     and    bx,bx            ;Buffer    empty?
  1690.     jz    CBlkRdEmpty        ;Yes - get out
  1691.     cmp    bx,[bp].RegCX        ;Greater than number requested?
  1692.     jbe    CBlkRdNotAll        ;No - can only move what we have
  1693.     mov    bx,[bp].RegCX        ;Yes - move number requested
  1694. CBlkRdNotAll:
  1695.     mov    cx,RBufSize        ;Get length of buffer
  1696.     sub    cx,RBufFirst        ;Calculate length to end of buffer
  1697.     mov    es,[bp].RegES        ;Point to user's buffer
  1698.     mov    di,[bp].RegDI
  1699.     mov    si,offset RBuf        ;Point to receive buffer
  1700.     add    si,RBufFirst        ;Point to first    char to    be moved
  1701.     cmp    cx,bx            ;Greater than number requested?
  1702.     jb    CBlkRd2Moves        ;No - will take    two moves
  1703.     mov    cx,bx            ;Yes - only one    move needed
  1704.     rep movsb            ;Move chars to user buffer
  1705.     sub    si,offset RBuf        ;Convert to displacement within    buffer
  1706.     cmp    si,RBufSize        ;At end    of buffer?
  1707.     jb    CBlkRdDone        ;No - finish up
  1708.     xor    si,si            ;Yes - wrap
  1709.     jmp    short CBlkRdDone    ;Finish    up
  1710. CBlkRd2Moves:
  1711.     mov    ax,cx            ;Save move length
  1712.     rep movsb            ;Move first chars to user buffer
  1713.     mov    cx,bx            ;Get total move    length
  1714.     sub    cx,ax            ;Decrement by number already moved
  1715.     mov    si,offset RBuf        ;Point to start    of buffer
  1716.     rep movsb            ;Move remaining    number of chars
  1717.     sub    si,offset RBuf        ;Convert to displacement within    buffer
  1718. CBlkRdDone:
  1719.     mov    RBufFirst,si        ;Set pointer to    next char in buffer
  1720.     cmp    RBufCnt,RBufLimit    ;Below cutoff point
  1721.     ja    CBlkRdNoRFlow        ;No - continue
  1722.     call    RxUnhold        ;Yes - unhold receiver
  1723. CBlkRdNoRFlow:
  1724.     sub    RBufCnt,bx        ;Decrement count of chars in buffer
  1725. CBlkRdEmpty:
  1726.     mov    [bp].RegAX,bx        ;Return    total number moved
  1727. CBlkRdRet:
  1728.     ret                ;Return    to caller
  1729.  
  1730. CBlockRead endp
  1731.  
  1732.     subttl    Enqueue    a block    of characters on a channel
  1733.     page
  1734. CBlockWrite proc near
  1735. ;
  1736. ;    This routine enqueues a    block of characters from a user
  1737. ;      provided buffer into a channel's transmit buffer.  Up to 64k
  1738. ;      characters may be enqueued with one call.  The routine only
  1739. ;      enqueues as many characters as there are free    in the transmit
  1740. ;      buffer at the    time of    the call.
  1741. ;
  1742. ;    Entry conditions:
  1743. ;        [bp].RegCX = Maximum number of characters to enqueue
  1744. ;        [bp].RegDX = channel
  1745. ;        [bp].RegES = Segment of    user's buffer
  1746. ;        [bp].RegDI = Offset of user's buffer
  1747. ;    Exit conditions:
  1748. ;        [bp].RegAX = Number of characters enqueued into
  1749. ;                   the transmit buffer
  1750. ;
  1751.     cmp    [bp].RegDX,ChanFF    ;Dummy channel?
  1752.     je    CBlkWrRet        ;Yes - just return
  1753.     mov    bx,TBufSize        ;Get length of buffer
  1754.     mov    cx,bx            ;Save a    copy
  1755.     sub    bx,TBufCnt        ;Calculate free    space
  1756.     jz    CBlkWrFull        ;Is buffer full?
  1757.     cmp    bx,[bp].RegCX        ;Greater than number requested?
  1758.     jbe    CBlkWrNotAll        ;No - can only move what we can    hold
  1759.     mov    bx,[bp].RegCX        ;Yes - move number requested
  1760. CBlkWrNotAll:
  1761.     sub    cx,TBufNext        ;Calculate length to end of buffer
  1762.     mov    dx,cs            ;Point to transmit buffer
  1763.     mov    es,dx
  1764.     mov    di,offset TBuf
  1765.     add    di,TBufNext        ;Point to free space
  1766.     mov    ds,[bp].RegES        ;Point to user's buffer
  1767.     mov    si,[bp].RegDI
  1768.     cmp    cx,bx            ;Greater than number requested?
  1769.     jb    CBlkWr2Moves        ;No - will take    two moves
  1770.     mov    cx,bx            ;Yes - only one    move needed
  1771.     rep movsb            ;Move chars to user buffer
  1772.     sub    di,offset TBuf        ;Convert to displacement within    buffer
  1773.     cmp    di,TBufSize        ;At end    of buffer?
  1774.     jb    CBlkWrDone        ;No - finish up
  1775.     xor    di,di            ;Yes - wrap
  1776.     jmp    short CBlkWrDone    ;Finish    up
  1777. CBlkWr2Moves:
  1778.     mov    ax,cx            ;Save move length
  1779.     rep movsb            ;Move first chars to user buffer
  1780.     mov    cx,bx            ;Get total move    length
  1781.     sub    cx,ax            ;Decrement by number already moved
  1782.     mov    di,offset TBuf        ;Point to start    of buffer
  1783.     rep movsb            ;Move remaining    number of chars
  1784.     sub    di,offset TBuf        ;Convert to displacement within    buffer
  1785. CBlkWrDone:
  1786.     mov    ds,dx            ;Restore DX
  1787.     mov    TBufNext,di        ;Point to free space
  1788.     add    TBufCnt,bx        ;Increment count of chars in buffer
  1789. CBlkWrFull:
  1790.     mov    [bp].RegAX,bx        ;Return    total number moved
  1791.     call    TxEnable        ;Enable    the transmitter
  1792. CBlkWrRet:
  1793.     ret
  1794.  
  1795. CBlockWrite endp
  1796.  
  1797.     subttl    Start/Stop sending a break on a    channel
  1798.     page
  1799. CBreak    proc    near
  1800. ;
  1801. ;    This routine starts/stops sending a break (continuous spacing) on
  1802. ;        the    specified channel.
  1803. ;
  1804. ;    Entry conditions:
  1805. ;        [bp].RegAL = 00h - Stop    sending    break
  1806. ;                 01h - Start sending break
  1807. ;        [bp].RegDX = channel
  1808. ;    Exit conditions:
  1809. ;        none
  1810. ;
  1811.     cmp    [bp].RegDX,ChanFF    ;Dummy channel?
  1812.     je    CBreakRet        ;Yes - just return
  1813.     cli                ;No interrupts
  1814.     mov    al,LastCntl        ;Get current USART command
  1815.     test    [bp].RegAX,01h        ;Request to start sending break?
  1816.     jz    CBreakStop        ;No - then stop    sending    break
  1817.     and    TFlag,not mask TXonHld    ;Cancel    existing hold
  1818.     or    al,mask    UBrk        ;Set break bit
  1819.     and    al,not mask UTxEn    ;Reset transmit    enable bit
  1820.     jmp    short CBreakOut        ;Go send it to to the USART
  1821. CBreakStop:
  1822.     and    al,not mask UBrk    ;Reset break bit
  1823.     or    al,mask    UTxEn        ;Set transmit enable bit
  1824. CBreakOut:
  1825.     out    UCtrlPort,al        ;Send command to USART
  1826.     mov    LastCntl,al        ;Save new USART    command
  1827.     nop                ;Wait a    bit
  1828.     nop
  1829.     sti                ;Allow interrupts
  1830. CBreakRet:
  1831.     ret                ;Return    to caller
  1832.  
  1833. CBreak    endp
  1834.  
  1835.     subttl    Return information about the driver
  1836.     page
  1837. CInfo    proc    near
  1838. ;
  1839. ;    This routine fills a user-supplied buffer with various information
  1840. ;        concerning the internal status and capabilities of the FOSSIL.
  1841. ;
  1842. ;    Entry conditions:
  1843. ;        [bp].RegCX = Length of user-supplied buffer
  1844. ;        [bp].RegES = Segment of    user-supplied buffer
  1845. ;        [bp].RegDI = Offset of user supplied buffer
  1846. ;        [bp].RegDX = channel
  1847. ;    Exit conditions:
  1848. ;        [bp].RegAX = Number of characters actually placed into
  1849. ;                 the user-supplied buffer
  1850. ;
  1851.     mov    ax,RBufSize        ;Calculate receive buffer free space
  1852.     sub    ax,RBufCnt
  1853.     mov    InfoRFree,ax        ;Store it in info area
  1854.     mov    ax,TBufSize        ;Calculate transmit buffer free    space
  1855.     sub    ax,TBufCnt
  1856.     mov    InfoTFree,ax        ;Store it in info area
  1857.     mov    si,offset Info        ;Set up    source pointer
  1858.     mov    es,[bp].RegES        ;Set up    destination pointer
  1859.     mov    di,[bp].RegDI
  1860.     mov    cx,InfoSize        ;Get length of info area
  1861.     cmp    cx,[bp].RegCX        ;Is user's buffer large enough?
  1862.     jae    CInfoMove        ;Yes - move entire area
  1863.     mov    cx,[bp].RegCX        ;No - just move    number requested
  1864. CInfoMove:
  1865.     mov    [bp].RegAX,cx        ;Store number moved in stack frame
  1866.     rep movsb            ;Move info area    to user    buffer
  1867.     ret                ;Return    to caller
  1868.  
  1869. CInfo    endp
  1870.  
  1871.     subttl    Output to a port and wait a while
  1872.     page
  1873. PutWait    proc    near
  1874.  
  1875.     out    dx,al            ;Write to specified port
  1876.     nop
  1877.     nop
  1878.     nop
  1879.     ret                ;Return    to caller
  1880.  
  1881. PutWait    endp
  1882.  
  1883.     subttl    Enable the USART transmitter
  1884.     page
  1885. TxEnable proc    near
  1886.  
  1887.     mov    al,LastCntl        ;Copy last USART command
  1888.     or    al,mask    UTxEn        ;Set transmitter enable    bit
  1889.     cmp    al,LastCntl        ;Any change?
  1890.     je    TxEnableRet        ;No - no action    needed
  1891.     pushf                ;Save interrupt    state
  1892.     cli                ;No interrupts
  1893.     out    UCtrlPort,al        ;Send command to USART
  1894.     mov    LastCntl,al        ;Save USART command
  1895.     nop                ;Wait a    bit
  1896.     nop
  1897.     popf                ;Restore interrupt state
  1898. TxEnableRet:
  1899.     ret                ;Return    to caller
  1900.  
  1901. TxEnable endp
  1902.  
  1903.     subttl    Cancel receiver    holds
  1904.     page
  1905. RxUnhold proc    near
  1906.  
  1907.     mov    al,LastCntl        ;Copy last USART command
  1908.     test    FFlag,mask FRXon    ;Receive Xon/Xoff active?
  1909.     jz    RxUnhOut        ;No - output USART command
  1910.     cmp    LastXChar,Xon        ;Was Xon already sent?
  1911.     je    RxUnhOut        ;Yes - Xon not needed
  1912.     mov    XChar,Xon        ;Feed Xon to transmitter
  1913.     or    al,mask    UTxEn        ;Enable    transmitter
  1914. RxUnhOut:
  1915.     or    al,mask    URTS        ;Raise RTS
  1916.     cmp    al,LastCntl        ;Anything changed?
  1917.     je    RxUnhRet        ;No - don't output USART command
  1918.     pushf                ;Save interrupt    state
  1919.     cli                ;No - interrupts
  1920.     out    UCtrlPort,al        ;Output    USART command
  1921.     mov    LastCntl,al        ;Save new USART    command
  1922.     nop                ;Wait a    bit
  1923.     nop
  1924.     popf                ;Restore interrupt state
  1925. RxUnhRet:
  1926.     ret                ;Return    to caller
  1927.  
  1928. RxUnhold endp
  1929.  
  1930.     subttl    Carrier    watchdog routine
  1931.     page
  1932. WatchDog proc    far
  1933.  
  1934.     push    ax            ;Save caller's register
  1935.     in    al,MStatPort        ;Get modem status
  1936.     test    al,mask    MDCD        ;CD true?
  1937.     jz    WatchDogRet        ;Yes - continue
  1938.     int    BiosBoot        ;No - reboot system
  1939. WatchDogRet:
  1940.     pop    ax            ;Restore caller's register
  1941.     ret                ;Return    to caller
  1942.  
  1943. WatchDog endp
  1944.  
  1945.     subttl    8251A USART Interrupt Handler
  1946.     page
  1947. Int72    proc    near
  1948.  
  1949.     sti                ;Allow interrupts
  1950.     push    ax            ;Save caller's regsisters
  1951.     push    bx
  1952.     push    ds
  1953.     mov    ax,cs            ;Set DS    to CS
  1954.     mov    ds,ax
  1955.  
  1956. Repoll:                    ;Determine source of interrupt
  1957.     in    al,UStatPort        ;Get USART status
  1958.     test    al,mask    URxRdy        ;Rx ready?
  1959.     jnz    RxInt            ;Yes - go process receiver interrupt
  1960.     test    al,mask    UTxRdy        ;Tx ready?
  1961.     jz    Int72Ret        ;No - get out
  1962.     test    LastCntl,mask UTxEn    ;Transmitter enabled?
  1963.     jz    Int72Ret        ;No - get out
  1964.     jmp    TxInt            ;Yes - process transmitter interrupt
  1965.  
  1966. Int72Ret:
  1967. ;     Issue EOI    to reset IS bit    in 8259A.  Also, check 8259A for
  1968. ;    more interrupts    at this    level in 80186 - if none pending,
  1969. ;    then issue EOI in 80186
  1970.     cli                ;No interrupts
  1971.     mov    al,EOICmd59        ;Set OCW2 to specific EOI for level 2
  1972.     out    OCW2A,al        ;Output    OCW2 to    PIC(0)
  1973.     nop
  1974.     nop
  1975.     mov    al,ISRCmd59        ;Set OCW3 to return IS reg
  1976.     out    OCW2A,al        ;Output    OCW3
  1977.     nop
  1978.     nop
  1979.     xchg    bx,dx            ;Save dx
  1980.     mov    dx,EOIReg86        ;Point to 80186    EOI register
  1981.     in    al,OCW2A        ;Get PIC(0) in-service register
  1982.     or    al,al            ;Any other interrupts pending?
  1983.     jnz    NoEOI86            ;Yes - don't clear 80186
  1984.     mov    ax,EOICmd86        ;Get non-specific EOI for 80186
  1985.     out    dx,ax            ;Clear 80186 interrupt controller
  1986. NoEOI86:
  1987.     xchg    bx,dx            ;Restore dx
  1988.     pop    ds            ;Restore previous context
  1989.     pop    bx
  1990.     pop    ax
  1991.     iret                ;Return    to point of interrupt
  1992.  
  1993.     page
  1994. ; Process Receiver Interrupt
  1995. ;
  1996. RxInt:
  1997.     in    al,UDataPort        ;Get data
  1998.     test    RFlag,mask RCtlChk    ;Trapping Ctl-C/Ctl-K?
  1999.     jnz    RxChkCtl        ;Yes - check for break
  2000. RxInt1:
  2001.     test    FFlag,mask FTXon    ;Transmit Xon/Xoff active?
  2002.     jnz    RxTFlow            ;Yes - go check    for Xon/Xoff
  2003. RxInt2:
  2004.     mov    bx,RBufNext        ;bx := next space in buffer
  2005.     mov    byte ptr RBuf[bx],al    ;Place data into buffer
  2006.     cmp    RBufCnt,RBufSize    ;Room for data in buffer?
  2007.     jae    RxOverrun        ;No - Indicate overrun
  2008.     inc    RBufCnt            ;Increment # of    chars in buffer
  2009.     cmp    RBufCnt,RBufLimit    ;Receiver past handshake point?
  2010.     jbe    RxNoRFlow        ;Yes - go do handshake
  2011.     mov    al,LastCntl        ;Copy last USART control byte
  2012.     test    FFlag,mask FRXon    ;Receive Xon/Xoff active?
  2013.     jz    RxRFlowRTS        ;No - check RTS    handshaking
  2014.     cmp    LastXChar,Xoff        ;Xoff already sent
  2015.     je    RxRFlowRTS        ;Yes - don't send another
  2016.     mov    XChar,Xoff        ;Feed Xoff to transmitter
  2017.     or    al,mask    UTxEn        ;Enable    transmitter
  2018. RxRFlowRTS:
  2019.     test    FFlag,mask FRTS        ;RTS handshaking active?
  2020.     jz    RxRFlowOut        ;No - output USART control byte
  2021.     and    al,not mask URTS    ;Lower RTS
  2022. RxRFlowOut:
  2023.     cmp    al,LastCntl        ;Has anything changed?
  2024.     je    RxNoRFlow        ;No - no need to do anything
  2025.     mov    LastCntl,al        ;Save new USART    control    byte
  2026.     out    UCtrlPort,al        ;Output    control    byte to    USART
  2027. RxNoRFlow:
  2028.     cmp    bx,RBufSize-1        ;Past end of the buffer?
  2029.     jnb    RxWrap            ;Yes - go wrap buffer
  2030.     inc    RBufNext        ;Increment buffer index
  2031.     jmp    Repoll            ;Check for more    work
  2032.  
  2033. RxChkCtl:
  2034.     cmp    al,CtlC            ;Ctl-C?
  2035.     je    RxSetMask        ;Yes - treat specially
  2036.     cmp    al,CtlK            ;Ctl-K?
  2037.     jne    RxInt1            ;No - go buffer    char
  2038. RxSetMask:
  2039.     or    RFlag,mask RCtlRcv    ;Indicate break    received
  2040.     jmp    Repoll            ;Don't buffer char
  2041.  
  2042. RxTFlow:
  2043.     cmp    al,Xon            ;Xon?
  2044.     jne    RxChkXoff        ;No - continue checking
  2045.     and    TFlag,not mask TXonHld    ;Yes - tell xmitter to proceed
  2046.     call    TxEnable        ;Enable    transmitter
  2047.     jmp    Repoll            ;Don't buffer Xon
  2048. RxChkXoff:
  2049.     cmp    al,Xoff            ;Xoff?
  2050.     jne    RxInt2            ;No - try to buffer char
  2051.     or    TFlag,mask TXonHld    ;Yes - tell xmitter to hold it
  2052.     jmp    Repoll            ;Don't buffer Xoff
  2053.  
  2054. RxOverrun:
  2055.     or    RFlag,mask ROvr        ;Indicate overrun
  2056.     jmp    Repoll
  2057.  
  2058. RxWrap:
  2059.     mov    RBufNext,0        ;Zero buffer index
  2060.     jmp    Repoll            ;Check for more    work
  2061.  
  2062.     page
  2063. ; Process transmitter interrupt
  2064. ;
  2065. ;
  2066. ; Buffer contains data - output    a byte to the USART
  2067. ;
  2068. TxInt:    cmp    XChar,0            ;Need to send a    flow control char?
  2069.     jne    TxSendXChar        ;Yes - send it
  2070.     cmp    TBufCnt,0        ;Anything in buffer?
  2071.     je    TxShutoff        ;No - shut off transmitter
  2072.     cmp    TFlag,0            ;Transmitter held?
  2073.     jne    TxShutoff        ;Yes - shut off    transmitter
  2074.     mov    bx,TBufFirst        ;BX points to next char    to be sent
  2075.     mov    al,TBuf[bx]        ;Get data from buffer
  2076.     out    UDataPort,al        ;Send data
  2077.     dec    TBufCnt            ;Decrement buffer count
  2078.     cmp    bx,TBufSize-1        ;Past end?
  2079.     jnb    TxWrap            ;Yes - wrap buffer
  2080.     inc    TBufFirst        ;Increment buffer index
  2081.     jmp    Repoll            ;Check for RxRdy
  2082.  
  2083. TxWrap:
  2084.     mov    TBufFirst,0        ;Zero buffer index
  2085.     jmp    Repoll            ;Check for RxRDY
  2086.  
  2087. TxSendXChar:
  2088.     mov    al,XChar        ;Get the handshake character to    send
  2089.     out    UDataPort,al        ;Send it to the    USART
  2090.     mov    LastXChar,al        ;Save last handshake character
  2091.     mov    XChar,0            ;Clear the handshake character
  2092.     jmp    Repoll            ;Check for RxRdy
  2093.  
  2094.  
  2095. TxShutoff:
  2096.     mov    al,LastCntl        ;Get last USART    command
  2097.     and    al,not mask UTxEn    ;Reset TxEnable    bit
  2098.     out    UCtrlPort,al        ;Output    to USART
  2099.     mov    LastCntl,al        ;Save last USART command
  2100.     nop                ;Wait a    bit
  2101.     nop
  2102.     jmp    Repoll            ;Check for RxRdy
  2103.  
  2104. Int72    endp
  2105.  
  2106.     subttl    Timer tick routine
  2107.     page
  2108. Int1C    proc    near
  2109.  
  2110.     push    ds            ;Save affected regs
  2111.     push    bx
  2112.     push    cx
  2113.     mov    cx,cs            ;Set data segment
  2114.     mov    ds,cx
  2115.     mov    cx,TTRoutCnt        ;Get number of routines
  2116.     and    cx,cx            ;Are there any?
  2117.     jz    Int1CSkip        ;No - just return
  2118.     mov    bx,offset TTRoutTab    ;Point to routine table
  2119. Int1CLoop:
  2120.     call    dword ptr [bx]        ;Call the routine
  2121.     add    bx,4            ;Point to next routine
  2122.     loop    Int1CLoop        ;Continue if any more routines
  2123. Int1CSkip:
  2124.     pop    cx            ;Pop affected regs
  2125.     pop    bx
  2126.     pop    ds
  2127.     jmp    dword ptr cs:OldInt1C    ;jump to BIOS tick handler
  2128.  
  2129. Int1C    endp
  2130.  
  2131.     subttl    Initialization Routines
  2132.     page
  2133. FInit1    proc    near
  2134.  
  2135.     mov    word ptr InfoID,offset IDString    ;Place address of ID string
  2136.     mov    word ptr InfoID+2,cs        ;  into    information area
  2137. ;
  2138. ; Initialize the extended dispatcher address table
  2139. ;
  2140.     mov    bx,offset UserAppTable        ;Point to table
  2141.     mov    dx,offset FarRet        ;Get address of    iret instruction
  2142.     mov    cx,64                ;Set up    initialization loop
  2143. InitLoop:
  2144.     mov    [bx],dx                ;Save offset in    table entry
  2145.     mov    [bx]+2,ds            ;Save segment
  2146.     add    bx,4                ;Point to next entry
  2147.     loop    InitLoop            ;Repeat    for all    64 entries
  2148.  
  2149.     push    ds                ;Save DS
  2150.     cli                    ;No interrupts
  2151. ;
  2152. ; Install FOSSIL BIOS
  2153. ;
  2154.     mov    cx,offset Int14            ;Set up    offset of new comm BIOS
  2155.     mov    dx,cs                ;Set up    segment    of new comm BIOS
  2156.     xor    ax,ax
  2157.     mov    ds,ax                ;Point to Int 14h vector
  2158.     mov    si,14h*4
  2159.     mov    ds:[si],cx            ;Insert    new Int    14h vector
  2160.     mov    ds:[si]+2,dx
  2161.     mov    si,53h*4            ;Point to Int 53h vector
  2162.     mov    ds:[si],cx            ;Insert    new Int    53h vector
  2163.     mov    ds:[si]+2,dx
  2164. ;
  2165. ; Install new USART handler
  2166. ;
  2167.     mov    cx,offset Int72            ;Set up    offset of new USART handler
  2168.     mov    si,72h*4            ;Point to Int 72h vector
  2169.     mov    ds:[si],cx            ;Insert    new Int    72h vector
  2170.     mov    ds:[si]+2,dx
  2171. ;
  2172. ;     Install timer tick manager
  2173. ;
  2174.     mov    si,1Ch*4            ;Point to timer    tick vector
  2175.     mov    ax,ds:[si]            ;Get current tick offset
  2176.     mov    word ptr cs:OldInt1C,ax        ;Save current tick offset
  2177.     mov    ax,ds:[si]+2            ;Get current tick segment
  2178.     mov    word ptr cs:OldInt1C+2,ax    ;Save current tick segment
  2179.     mov    cx,offset Int1C            ;Point to our tick routine
  2180.     mov    ds:[si],cx            ;Insert    new Int    1Ch vector
  2181.     mov    ds:[si]+2,dx
  2182.     sti                    ;Enable    interrupts
  2183.     pop    ds                ;Restore DS
  2184. ;
  2185. ; Set end of driver address in request header
  2186. ;
  2187.     mov    word ptr es:[di].RHBufAdr,offset FInit1
  2188.     mov    word ptr es:[di].RHBufAdr+2,cs
  2189. ;
  2190. ; Initialize the pointers to the secondary device driver headers
  2191. ;
  2192.     mov    word ptr FOSSIL$,offset    COM1    ;Store offset
  2193.     mov    word ptr FOSSIL$+2,cs        ;Store segment
  2194.     mov    word ptr COM1,offset AUX    ;Store offset
  2195.     mov    word ptr COM1+2,cs        ;Store segment
  2196. ;
  2197. ; Init port 0 to 2400 8    N 1
  2198. ;
  2199.     xor    ah,ah                ;Set FOSSIL function
  2200.     mov    al,0a3h                ;Set port parameters
  2201.     xor    dx,dx                ;Set port number
  2202.     int    FOSSIL                ;Call FOSSIL
  2203. ;
  2204. ; Let the user know everything is OK and exit
  2205. ;
  2206.     mov    dx,offset InstMsg
  2207.     call    prtmsg                ;Print installed message
  2208. ;
  2209. ; Print    copyright message
  2210. ;
  2211.     mov    dx,offset CopyMsg
  2212.     call    PrtMsg
  2213.     ret                    ;Return    to interrupt routine
  2214.  
  2215. FInit1    endp
  2216.  
  2217. FInit2    proc    near
  2218.  
  2219. ;
  2220. ; Set end of driver address in request header
  2221. ;
  2222.     mov    word ptr es:[di].RHBufAdr,offset FInit1
  2223.     mov    word ptr es:[di].RHBufAdr+2,cs
  2224.     ret                    ;Return    to interrupt routine
  2225.  
  2226. FInit2    endp
  2227.  
  2228.     subttl    Message    Routine
  2229.     page
  2230. PrtMsg    proc    near
  2231.     put_string
  2232.     ret
  2233. PrtMsg    endp
  2234.  
  2235. InstMsg    db    'T2KCOMM FOSSIL Driver,  v5.2',13,10,'$'
  2236.  
  2237. code    ends
  2238.     subttl    Symbol table
  2239.     end
  2240.