home *** CD-ROM | disk | FTP | other *** search
- page 58,132
- title T2KCOMM - FOSSIL Driver For The Tandy 2000 - v5.2
- .186
- subttl Overview and History
- page
-
- ; This program implements the FOSSIL (Fido, Opus, SEAdog Standard
- ; Interface Layer) communications driver for the Tandy 2000. FOSSIL
- ; functions 00h - 1Bh, 7Eh, and 7Fh are implemented.
-
- ; Written by Rick Moore
- ; Copyright 1987, 1988 by Solar Wind Computing, ALL RIGHTS RESERVED
-
- ; This code may be used and distributed in its unmodified form for ANY
- ; NONCOMMERCIAL USE WHATEVER. Modified versions of this software are NOT to
- ; be distributed without the express written consent of the author. You are
- ; not allowed to sell or otherwise make money from the use of this software
- ; without specific license from the author. You may contact the author at:
-
- ; Solar Wind Computing
- ; P.O. Box 1204
- ; Homewood, IL 60430
-
- ; You may contact the author with bug reports or suggestions for improvement
- ; via FidoNet mail at Net 115 Node 333 - Solar Wind Opus for non-commercial
- ; purposes only.
-
- ; History:
- ; v1.0 - 01/87 REM
- ; v1.1 - 02/87 REM 1. Added functions 20 and 21.
- ; 2. Fixed several mites in x-on/x-off logic
- ; 3. Optimized branch instructions for minimum
- ; overhead in the interrupt routines. Some
- ; of the code may look strange at first, but
- ; the code has been arranged to minimize
- ; instruction prefetch queue flushing.
- ; 4. Eliminated dependence on Tandy BIOS int 14h
- ; by incorporating the code to set the 8253 and
- ; 8251A in T2KCOMM. This will help minimize
- ; stack usage from within T2KCOMM, and will
- ; allow future expansion to support 19200 bps.
- ; v1.2 - 03/87 REM 1. Fixed the mistake in the implementation of
- ; (never released) functio 20, in which, due to confusion on
- ; my part, I did not implement the ability to
- ; cancel the watchdog function.
- ; 2. Added full word length, parity, and stop bit
- ; support to function 0.
- ; 3. Simplified and improved the transmitter hold
- ; logic.
- ; 4. Changed function 7 to return timer parms for
- ; the PC BIOS interrupt, 1C. This cuts by 80%
- ; the overhead associated with the timer tick.
- ; v3.00 - 05/87 REM 1. Added functions 22 and 23, bringing the driver
- ; up to compliance with Draft 3 of the FOSSIL
- ; spec.
- ; 2. Changed naming convention. The first digit of
- ; the version is the FOSSIL spec level and the
- ; decimal places represent the release version
- ; within that spec.
- ; 3. Completely changed the way parameters are passed
- ; and returned within the program. As the FOSSIL
- ; spec has added function, it has become harder
- ; and harder to keep the required parameters in
- ; the proper register(s) through the various
- ; routines. Therefore, all registers except CS
- ; are stored in a stack frame upon entry to the
- ; int 14h code. All registers except CS and SS
- ; will be restored when exiting. Therefore all
- ; return values must be stored into the stack
- ; frame before returning.
- ; 4. Fixed again, and hopefully once and for all, the
- ; mite in the x-on/x-off logic.
- ; 5. Added DSR handshaking.
- ; v3.10 - 06/87 REM 1. Reorganized and optimized the USART interrupt
- ; handler to insure reliable operation at 19.2kb
- ; and above.
- ; 2. Optimized the FOSSIL read and write routines for
- ; the same reason.
- ; 3. Swatted more mites.
- ; v3.20 - 07/87 REM 1. Increased transmit buffer size to 4k. Opus's
- ; Zmodem routine uses window sizes of 2k, so
- ; I wanted more of a pad.
- ; 2. More bulletproofing against lost interrupts
- ; 3. Added an incredible kluge to make the driver
- ; completely compatible with the Tandy BIOS. It
- ; seems that the Tandy int 14 function 3 (status)
- ; stores the next character available in the
- ; buffer (if one exists) at a displacement of 6Fh
- ; in the BIOS Communication Area. The MS/DOS
- ; device driver for the AUX: device looks for this
- ; character when the "non-destructive" read
- ; function is called. Now this driver does the
- ; same thing as the Tandy BIOS.
- ; 3.30 - 07/87 REM 1. Fixed brain-damaged logic in the Timer Tick
- ; Manager routines. Somehow, I copied old code
- ; back into the source deck. It is back the way
- ; it was supposed to be all along.
- ; 2. Corrected function 0Ch to be a non-destructive,
- ; rather than a destructive read.
- ; 3.40 - 09/87 REM 1. Eliminated three more lockup conditions.
- ; 2. Added full Xon/Xoff and CTS/RTS support, in
- ; both host and remote modes. Now supports the
- ; "Modem Steady" option at speeds up to 9.6 kbps.
- ; Special thanks to Vince Perriello for a
- ; suggestion that really made it simpler.
- ; 3. Decreased the transmit buffer size back to 1k,
- ; which seems to work better at lower speeds than
- ; larger sizes.
- ; 4.00 - 10/87 REM 1. Driver now fully implements the draft 4 FOSSIL
- ; spec, including functions 7Eh and 7FH.
- ; 2. Changed receive mode Xon/Xoff to be controlled
- ; by AL bit 08h, as specified in draft 4 spec.
- ; 3. T2KCOMM now returns the overflow, framing error,
- ; and parity error bits in AH when status is
- ; returned.
- ; 4.10 - 10/87 REM 1. Converted to device driver with support for AUX,
- ; COM1, and FOSSIL$ devices.
- ; 2. Removed kludge to support Tandy AUX driver from
- ; "status" FOSSIL BIOS call.
- ; 5.00 - 11/87 REM 1. Changed the register calling conventions to use
- ; the draft 5 specs, replacing DS:DX with ES:DX,
- ; and DS:SI with ES:DI.
- ; 2. Corrected error in transmit-with-wait and
- ; transmit-without-wait routines. Now both
- ; routines take the character to be enqueued from
- ; the stack frame rather than directly from AL.
- ; The previous method worked, but only accidently.
- ; 5.10 - 01/88 REM 1. Fixed errors in both the block read and
- ; block write routines.
- ; 5.20 - 02/88 REM 1. Implemented the change to the status call as
- ; specified in the V5 FOSSIL spec dated 02/11/88:
- ; Bit 03h of AL always returned set.
- ; 2. Removed support for status bits not defined by
- ; FOSSIL V5 spec.
- ; 3. Corrected version code returned by open.
- ;
- subttl Standard Equates And Macro Definitions
- page
- code segment public 'code'
- assume cs:code, ds:code
-
- org 0000h
-
- include C:\Usr\Include\Bioscall.Asm
- include C:\Usr\Include\Doscall.Asm
- include C:\Usr\Include\Regframe.Asm
-
- FOSSIL equ 14h ;FOSSIL interrupt number
-
- subttl Device Driver Declarations
- page
- ; Standard request header definition
-
- RequestHeader struc
- RHLen db ? ;Length of request header
- RHUnit db ? ;Unit number
- RHCmd db ? ;Command code
- RHStatus dw ? ;Status word
- db 9 dup (?)
- RHBufAdr dd ? ;I/O buffer address
- RHCount dw ? ;I/O count
- RequestHeader ends
-
- ; Maximum valid command number for device driver commands
-
- MaxCmd equ 12
-
- subttl Device Driver Headers And Command Tables
- page
- FOSSIL$ dd -1 ;Pointer to next driver
- dw 0C000h ;Driver attributes
- dw Strategy ;Offset of strategy routine
- dw FOS$Int ;Offset of interrupt routine
- db 'FOSSIL$ ' ;Device name
-
- CopyMsg db 'Copyright 1987, 1988, Solar Wind Computing,'
- db ' ALL RIGHTS RESERVED.',13,10,'$'
-
- even
-
- ; COM1 Device driver header
-
- COM1 dd -1 ;Pointer to next driver
- dw 08000h ;Driver attributes
- dw Strategy ;Offset of strategy routine
- dw COM1Int ;Offset of interrupt routine
- db 'COM1 ' ;Device name
-
- ; AUX Device driver header
-
- AUX dd -1 ;Pointer to next driver
- dw 08000h ;Driver attributes
- dw Strategy ;Offset of strategy routine
- dw AUXInt ;Offset of interrupt routine
- db 'AUX ' ;Device name
-
- ; FOSSIL$ Command Table
-
- FOS$Tab dw FInit1 ;Device initialization
- dw FNop ;Media check (not applicable)
- dw FNop ;Build BPB (not applicable)
- dw FReadCtl ;Read control string
- dw FRead ;Read
- dw FReadAhead ;Non-destructive look ahead
- dw FInStat ;Input status
- dw FInFlush ;Flush input buffer
- dw FWrite ;Write
- dw FWrite ;Write verify
- dw FOutStat ;Output status
- dw FOutFlush ;Flush output buffer
- dw FWriteCtl ;Write control string
-
- ; COM1 and AUX Command Table
-
- COM1Tab dw FInit2 ;Device initialization
- dw FNop ;Media check (not applicable)
- dw FNop ;Build BPB (not applicable)
- dw FCmdErr ;Read control string
- dw FRead ;Read
- dw FReadAhead ;Non-destructive look ahead
- dw FInStat ;Input status
- dw FInFlush ;Flush input buffer
- dw FWrite ;Write
- dw FWrite ;Write verify
- dw FOutStat ;Output status
- dw FOutFlush ;Flush output buffer
- dw FCmdErr ;Write control string
-
- subttl Device Driver Data Areas
- page
- ; I/O Packet Address
-
- PacketAddr dd 0 ;Strategy routine saves header address here
-
- ; Driver stack
-
- dw 128 dup (0)
- OurStack equ $
-
- subttl Device Driver Strategy Routine
- page
- Strategy proc far
-
- mov word ptr cs:PacketAddr,bx ;Save request header offset
- mov word ptr cs:PacketAddr+2,es ;Save request header segment
- ret ;Return to MS/DOS
-
- Strategy endp
-
- subttl FOSSIL$ Device Driver Interrupt Routine
- page
- FOS$Int proc far
-
- pusha ;Save MS/DOS's registers
- mov bx,offset FOS$Tab ;Point to FOSSIL$ command table
- xor dx,dx ;Set channel to use
- jmp short Interrupt
-
- FOS$Int endp
-
- subttl COM1 Device Driver Interrupt Routine
- page
- COM1Int proc far
-
- pusha ;Save MS/DOS's registers
- mov bx,offset COM1Tab ;Point to COM1 command table
- xor dx,dx ;Set channel to use
- jmp short Interrupt
-
- COM1Int endp
-
- subttl AUX Device Driver Interrupt Routine
- page
- AUXInt proc far
-
- pusha ;Save MS/DOS's registers
- mov bx,offset COM1Tab ;Point to COM1 command table
- xor dx,dx ;Set channel to use
- jmp short Interrupt
-
- AUXInt endp
-
- subttl Common Device Driver Interrupt Routine
- page
- Interrupt proc far
-
- push ds
- push es
- mov ax,cs ;Set up DS
- mov ds,ax
- mov cx,offset OurStack ;Set up our stack
- mov si,ss ;Save MS/DOS's SS/SP
- mov di,sp
- mov ss,ax ;Load our SS/SP
- mov sp,cx
- push si ;Save pointer to MS/DOS's stack
- push di
- les di,PacketAddr ;Point to request header
- mov es:[di].RHStatus,0 ;Zero status word
- mov al,es:[di].RHCmd ;Get command
- cmp al,MaxCmd ;Too high?
- ja BadCmd ;Yes - return error
- xor ah,ah ;Convert command to displacement
- shl ax,1
- add bx,ax ;Add displacement to table base
- call word ptr [bx] ;Call appropriate routine
- IntExit:
- or es:[di].RHStatus,0100h ;Set DONE bit
- pop di ;Restore MS/DOS's stack
- pop si
- mov ss,si
- mov sp,di
- pop es ;Restore MS/DOS's registers
- pop ds
- popa
- ret ;Return to MS/DOS
-
- BadCmd:
- or es:[di].RHStatus,8003h ;Set error + invalid cmd flags
- jmp IntExit ;Continue
-
- Interrupt endp
-
- subttl Device Driver NOP Routine
- page
- FNop proc near
-
- ret ;Return to interrupt routine
-
- FNOP endp
-
- subttl Device Driver Invalid Command Routine
- page
- FCmdErr proc near
-
- or es:[di].RHStatus,8003h ;Set error + invalid cmd flags
- ret ;Return to interrupt routine
-
- FCmdErr endp
-
- subttl Device Driver Read Control String Routine
- page
- FReadCtl proc near
-
- ret ;Return to interrupt routine
-
- FReadCtl endp
-
- subttl Device Driver Read Routine
- page
- FRead proc near
-
- mov cx,es:[di].RHCount ;Get I/O count
- les di,es:[di].RHBufAdr ;Point to MS/DOS's buffer
- FReadAgain:
- cmp cx,1 ;One character left to read?
- jb FReadExit ;Less than one - all done
- je FReadOne ;Yes - use single read
- mov ah,18h ;Set FOSSIL function
- int FOSSIL ;Call FOSSIL
- sub cx,ax ;Subtract from number requested
- add di,ax ;Add to index into buffer
- jmp FReadAgain ;Check for done
- FReadOne:
- mov ah,02h ;Set FOSSIL function
- int FOSSIL ;Call FOSSIL
- stosb ;Store in MS/DOS's buffer
- FReadExit:
- les di,PacketAddr ;Point to packet header
- ret ;Return to interrupt routine
-
- FRead endp
-
- subttl Device Driver Read-Ahead Routine
- page
- FReadAhead proc near
-
- mov ah,0Ch ;Set FOSSIL function
- int FOSSIL ;Call FOSSIL
- cmp ax,-1 ;Anything there?
- je FReadAheadBusy ;No - indicate busy
- lds si,es:[di].RHBufAdr ;Point to MS/DOS's buffer
- mov ds:[si],al ;Store it in MS/DOS's buffer
- ret ;Return to interrupt routine
- FReadAheadBusy:
- or es:[di].RHStatus,0200h ;Indicate Busy
- ret ;Return to interrupt routine
-
- FReadAhead endp
-
- subttl Device Driver Input Status Routine
- page
- FInStat proc near
-
- mov ah,03h ;Set FOSSIL function
- int FOSSIL ;Call FOSSIL
- test ah,mask ARxRdy ;Anything in receive buffer?
- jnz FInStatExit ;Yes - leave BUSY flag reset
- or es:[di].RHStatus,0200h ;No - set BUSY flag
- FInStatExit:
- ret ;Return to interrupt routine
-
- FInStat endp
-
- subttl Device Driver Input Flush Routine
- page
- FInFlush proc near
-
- mov ah,0Ah ;Set FOSSIL function
- int FOSSIL ;Call FOSSIL
- ret ;Return to interrupt routine
-
- FInFlush endp
-
- subttl Device Driver Write Routine
- page
- FWrite proc near
-
- mov cx,es:[di].RHCount ;Get I/O count
- les di,es:[di].RHBufAdr ;Point to MS/DOS's buffer
- FWriteAgain:
- cmp cx,1 ;One character left to write?
- jb FWriteExit ;Less than one - all done
- je FWriteOne ;Yes - use single write
- mov ah,19h ;Set FOSSIL function
- int FOSSIL ;Call FOSSIL
- sub cx,ax ;Subtract from number requested
- add di,ax ;Add to index into MS/DOS's buffer
- jmp FWriteAgain ;Check for done
- FWriteOne:
- mov al,es:[di] ;Get char from MS/DOS's buffer
- mov ah,01h ;Set FOSSIL function
- int FOSSIL ;Call FOSSIL
- FWriteExit:
- les di,PacketAddr ;Point to packet header
- ret ;Return to interrupt routine
-
- FWrite endp
-
- subttl Device Driver Output Status Routine
- page
- FOutStat proc near
-
- mov ah,03h ;Set FOSSIL function
- int FOSSIL ;Call FOSSIL
- test ah,mask ATxEmp ;Any room in buffer?
- jnz FOutStatExit ;Yes - leave BUSY flag reset
- or es:[di].RHStatus,0200h ;No - set BUSY flag
- FOutStatExit:
- ret ;Return to interrupt routine
-
- FOutStat endp
-
- subttl Device Driver Output Flush Routine
- page
- FOutFlush proc near
-
- mov ah,09h ;Set FOSSIL function
- int FOSSIL ;Call FOSSIL
- ret ;Return to interrupt routine
-
- FOutFlush endp
-
- subttl Device Driver Write Control String Routine
- page
- FWriteCtl proc near
-
- ret ;Return to interrupt routine
-
- FWriteCtl endp
-
- subttl BIOS Comm Equates And Definitions
- page
- ; Equates for 8251A USART
-
- MStatPort equ 00h ;Modem status port
-
- ; Bit definitions for MStatPort
-
- MSBits record MACLow:1,MFill:5,MDCD:1,MRI:1
-
- UCtrlPort equ 12h ;8251A control port
-
- ; Bit definitions for UCtrlPort
-
- UCBits record UHunt:1,UReset:1,URTS:1,UErrClr:1,UBrk:1,URxEn:1,UDTR:1,UTxEn:1
-
- UStatPort equ 12h ;8251A status port
-
- ; Bit definitions for UStatPort
-
- USBits record UDSR:1,UBrkDet:1,UFrmErr:1,UOvrErr:1,UParErr:1,UTxEmp:1,URxRdy:1,UTxRdy:1
-
- UDataPort equ 10h ;8251A data port
-
- ; Bit definitions for status returned in AX by the status function
-
- AStatAH record ATimeOut:1,ATxRdy:1,ATxEmp:1,ABrkDet:1,AFrmErr:1,AParErr:1,AOvrErr:1,ARxRdy:1
- AStatAL record ADCD:1,Fill:7
-
- ; Bit definitions for parms passed in AL to FOSSIL function 0Fh (Flow Control)
-
- FlParm record FlFill:4,FlRXon:1,FlDTR:1,FlRTS:1,FlTXon:1
-
- ; Equates for 8253-5 programmable interval timer
-
- PCnt0Port equ 40h ;Timer 0
- PCnt1Port equ 42h ;Timer 1
- PCnt2Port equ 44h ;Timer 2
- PModePort equ 46h ;Mode register
-
- ; Equates for 8259A interrupt controller
-
- OCW1A equ 62h ;8259(0) OCW1 port
- OCW2A equ 60h ;8259(0) OCW2-3 port
- NOPCmd59 equ 40h ;OCW2 for NOP
- EOICmd59 equ 62h ;OCW2 for specific EOI for level 2
- ISRCmd59 equ 0bh ;OCW3 to return IS reg
-
- ; Equates for 80186
-
- EOIReg86 equ 0FF22h ;Address of 80186 EOI register
- EOICmd86 equ 000Ch ;Specific EOI command for 80186 level 6
-
- ; Equates for ACSII characters
-
- CtlC equ 03h
- CtlK equ 0bh
- Xon equ 11h
- Xoff equ 13h
-
- Magic equ 1954h ;"Magic" value returned by FOSSIL
- MaxFun equ 27 ;Maximum function supported
- Version equ 5 ;Spec version supported
- Revision equ 2 ;Revision level within version
-
- ; Miscellaneous equates
-
- ChanFF equ 00FFh ;Channel id for dummy operations
-
- even
- TTRoutLim equ 8 ;Number of timer tick routine buckets
- TTRoutTab dd TTRoutLim dup (?) ;Timer tick routine table
- TTRoutCnt dw 0 ;Count of active timer tick routines
- OldInt1C dd 0 ;Original int 1Ch vector
-
- LastCntl db 0 ;Last control byte sent to USART
-
- XChar db 0 ;Handshake character stuffed to transmitter
- LastXChar db Xon ;Last handshake character sent
-
- RFlag db 0 ;Receiver flags
-
- ; Bit definitions of RFlag
-
- RBits record RCtlChk:1,RCtlRcv:1,ROvr:1
-
- TFlag db 0 ;Transmitter hold flags
-
- ; Bit definitions of TFlag
-
- TBits record TXonHld:1,TPrgHld:1
-
- FFlag db 0 ;Flow checking flags
-
- ; Bit definitions of FFlag
-
- FBits record FRXon:1,FTXon:1,FRTS:1
-
- ; Baud rate multiplier for 8253-5 PIT
-
- even
- RateTable label word
- dw 6 ;19.2 kbps
- dw 3 ;38.4 kbps
- dw 416 ;300 bps
- dw 208 ;600 bps
- dw 104 ;1.2 kbps
- dw 52 ;2.4 kbps
- dw 26 ;4.8 kbps
- dw 13 ;9.6 kbps
-
- even
-
- ; User appendage table
-
- UserAppTable dd 64 dup (?) ;Vectors for user functions 80h to BFh
-
- ; Buffer sizes
-
- TBufSize equ 1024 ;Transmit buffer size
- RBufSize equ 4096 ;Receive buffer size
- RBUfLimit equ 3072 ;Receive handshake point
-
- TBufFirst dw 0 ;Index to first character in xmit buffer.
- TBufNext dw 0 ;Index to first free space in xmit buffer.
- TBufCnt dw 0 ;Number of characters in xmit buffer.
- TBuf db TBufSize dup (?) ;Xmit buffer
-
- RBufFirst dw 0 ;Index to first character in recv buffer
- RBufNext dw 0 ;Index to first free space in recv buffer
- RBufCnt dw 0 ;Number of characters in rec. buffer
- RBuf db RBufSize dup (?) ;Recv buffer
-
- ; Fossil information area
-
- even
- Info equ $
- InfoSize dw 20 ;Size of info area
- InfoVer db Version ;Fossil major version
- InfoRev db Revision ;Fossil revision level
- InfoId dd 0 ;Pointer to ID string
- InfoRSize dw RBufSize ;Receive buffer size
- InfoRFree dw 0 ;Receive buffer free space
- InfoTSize dw TBufSize ;Transmit buffer size
- InfoTFree dw 0 ;Transmit buffer free space
- InfoScrW db 80 ;Video screen width
- InfoScrH db 24 ;Video screen height
- InfoBaud dw 0 ;Actual computer to modem baud rate
-
- IDString db 'T2KCOMM, Version 5.2, by Rick Moore',0
-
- subttl BIOS Comm Interrupt Handler
- page
- .sall
- even
- Int14 proc far
- jmp short Int14a ;Jump around prefix
- db 0,0,0,0
- dw Magic ;FOSSIL "magic" value
- db MaxFun ;Highest function value
- db 0
-
- Int14a: sti ;Allow interrupts
- and ah,ah ;High bit on?
- js DispatchUserApp ;Yes - dispatch user appendage
- cmp ah,MaxFun ;Regular FOSSIL function?
- ja UserAppMgr ;No - go check for appendage function
- pusha ;Set up register frame
- push ds
- push es
- cld ;Clear the direction flag
- mov bp,sp ;BP points to register frame
- mov bx,cs ;Set DS = CS
- mov ds,bx
- ; Determine type of request and call the appropriate routine
- mov si,ax ;Get function number
- shr si,8 ;Shift into low byte
- shl si,1 ;Convert into displacement
- call word ptr FuncTab[si] ;Call appropriate routine
- pop es ;Restore caller's registers
- pop ds
- popa
- Exit14: iret ;Return to point of interrupt
-
- DispatchUserApp:
- cmp ah,0BFh ;Appendage number out of range?
- ja Exit14 ;Yes - just return
- push bp ;Save bp
- sub sp,8 ;Reserve room for stack frame
- mov bp,sp ;Point to stack frame
- push ax ;Save registers used
- push bx
- mov bx,[bp]+8 ;Relocate saved bp in stack frame
- mov [bp],bx
- mov bl,ah ;Get copy of appendage number
- shl bl,1 ;Convert to displacement
- shl bl,1 ; (Discarding two high order bits)
- xor bh,bh ;Convert to word
- add bx,offset UserAppTable ;Add table base to displacement
- mov ax,cs:[bx] ;Get appendage offset
- mov [bp]+2,ax ;Store in stack frame
- mov ax,cs:[bx]+2 ;Get appendage segment
- mov [bp]+4,ax ;Store in stack frame
- mov [bp]+6,offset Exit14 ;Set up appendage return address
- mov [bp]+8,cs
- pop bx ;Restore registers used
- pop ax
- pop bp
- FarRet: ret ;Dispatch user appendage
-
- subttl Install and remove user appendages
- page
- ;
- ; This routine installs/removes user appendages into/from the FOSSIL
- ; dispatcher. Appendage numbers 80h through BFh are supported.
- ;
- ; Entry conditions:
- ; AH = 7Eh - Install an appendage
- ; 7Fh - Remove an appendage
- ; AL = Appendage number
- ; ES = Segment of appendage entry point
- ; DX = Offset of appendage entry point
- ; Exit conditions:
- ; AH = 1954h
- ; BL = Appendage number (same as AL on entry)
- ; BH = 00h - Operation unsuccessful
- ; 01h - Operation successful
- ;
- UserAppMgr:
- cmp ah,7Eh ;Check for valid appendage
- jb Exit14 ; manager function
- cmp ah,7Fh
- ja Exit14
- push ax ;Save ax
- and al,al ;Verify that appendage number
- jns UserAppErr ; is within range
- cmp al,0BFh
- ja UserAppErr
- mov bl,al ;Get copy of appendage number
- shl bl,1 ;Convert to displacement
- shl bl,1 ; (Discarding two high order bits)
- xor bh,bh ;Convert to word
- add bx,offset UserAppTable ;Add table base to displacement
- cmp ah,7Eh ;Install request?
- jne UserAppRmv ;No - must be a remove request
- cmp cs:[bx],offset FarRet ;Verify that entry in question
- jne UserAppErr ; is not already in use
- mov ax,cs
- cmp cs:[bx]+2,ax
- jne UserAppErr
- cli ;No interrupts
- mov cs:[bx],dx ;Insert offset of user appendage
- mov cs:[bx]+2,es ;Insert segment of user appendage
- sti ;Interrupts ok
- mov bh,1 ;Indicate success
- jmp short UserAppExit ;Get out
- UserAppRmv:
- cmp cs:[bx],dx ;Verify that entry points to the
- jne UserAppErr ; routine we are trying to remove
- mov ax,es
- cmp cs:[bx]+2,ax
- jne UserAppErr
- cli ;No interrupts
- mov cs:[bx],offset FarRet ;Insert default offset
- mov cs:[bx]+2,cs ;Insert default segment
- sti ;Interrupts ok
- mov bh,1 ;Indicate success
- jmp UserAppExit ;Get out
- UserAppErr:
- xor bh,bh ;Indicate failure
- UserAppExit:
- pop ax ;Restore ax
- mov bl,al ;Return appendage number assigned
- mov ax,Magic ;Indicate the FOSSIL is installed
- jmp Exit14 ;Get out
-
- Int14 endp
-
- Functab dw offset CSetChan ;Function 00h
- dw offset CTxWait ;Function 01h
- dw offset CRxWait ;Function 02h
- dw offset CStatus ;Function 03h
- dw offset COpen ;Function 04h
- dw offset CClose ;Function 05h
- dw offset CDTR ;Function 06h
- dw offset TTickParm ;Function 07h
- dw offset CFlushOut ;Function 08h
- dw offset CPurOut ;Function 09h
- dw offset CPurIn ;Function 0Ah
- dw offset CTxNowait ;Function 0Bh
- dw offset CRxNowait ;Function 0Ch
- dw offset KRxNowait ;Function 0Dh
- dw offset KRxWait ;Function 0Eh
- dw offset CFlowCtl ;Function 0Fh
- dw offset CCtlChk ;Function 10h
- dw offset DSetCurLoc ;Function 11h
- dw offset DGetCurLoc ;Function 12h
- dw offset DPutDos ;Function 13h
- dw offset CWatchDog ;Function 14h
- dw offset DPutBios ;Function 15h
- dw offset TTickMgr ;Function 16h
- dw offset Reboot ;Function 17h
- dw offset CBlockRead ;Function 18h
- dw offset CBlockWrite ;Function 19h
- dw offset CBreak ;Function 1Ah
- dw offset CInfo ;Function 1Bh
-
- subttl Set channel parameters
- page
- CSetChan proc near
- ;
- ; Sets channel parameters
- ;
- ; Entry conditions:
- ; [bp].RegAL = channel parameters
- ; [bp].RegDX = channel
- ; Exit conditions:
- ; [bp].RegAX = channel status
- ;
- cmp [bp].RegDX,ChanFF ;Dummy channel?
- je CSetChanFF ;Yes - just return
- mov dx,OCW1A ;Point to PIC(0) OCW1 port
- cli ;No interrupts
- xor bl,bl ;Clear work area
- xor ax,ax ;Clear ax
- mov al,[bp].RegAL ;Get parms from reg frame
- mov InfoBaud,ax ;Store port info in info area
- mov ah,al ;Make copy of parms
- and ah,mask CRParity ;Mask out all but parity bits
- shl ah,1 ;Convert to USART command bits
- or bl,ah ;Set bits in new USART command
- mov ah,al ;Make copy of parms
- and ah,mask CRWordLen ;Mask out all but word length bits
- shl ah,2 ;Convert to USART command bits
- or bl,ah ;Set bits in new USART command
- mov ah,al ;Make copy of parms
- and ah,mask CRStopBit ;Mask out all but # stop bits
- shl ah,5 ;Convert to USART command bits
- or ah,42h ;Set bits 6 and 1 in USART command
- or ah,bl ;Leave new USART command in ah
- mov bl,al ;Makecopy of parms
- and bl,mask CRRate ;Mask off all but rate bits
- xor bh,bh ;Zero high order byte
- shr bx,4 ;Convert to word displacement
- add bx,offset RateTable ;Point to baud rate table
- mov bx,0[bx] ;Get baud rate divisor
- mov dx,UCtrlPort ;Point to USART control port
- xor al,al ;Clear USART out with 3 nulls
- call PutWait
- call PutWait
- call PutWait
- mov al,mask UReset ;Reset the USART
- call PutWait
- mov dx,PModePort ;Point to PIT mode port
- mov al,76h ;Get PIT command
- call PutWait ;Write to PIT
- mov dx,PCnt1Port ;Point to PIT counter 1
- mov al,bl ;Get low order byte of divisor
- call PutWait ;Write to PIT
- mov al,bh ;Get high order byte of divisor
- call PutWait ;Write to PIT
- mov dx,UCtrlPort ;Point to USART control port
- mov al,ah ;Get USART mode byte
- cli ;No interrupts
- call PutWait
- mov al,mask URTS + mask UDTR + mask URxEn + mask UTxEn
- mov LastCntl,al ;Save USART control byte
- or al,mask UErrClr ;Reset USART error flags
- call PutWait ;Send it to USART control port
- sti ;Allow interrupts
- jmp CStatus ;Get status and return
-
- CSetChanFF:
- ret ;Return to caller
-
- CSetChan endp
-
- subttl Send a character to channel with wait
- page
- CTxWait proc near
- ;
- ; Enqueues a character into a channel's transmit buffer. Waits
- ; forever for space in the buffer.
- ;
- ; Entry conditions:
- ; [bp].RegAL = character to enqueue
- ; [bp].RegDX = channel
- ; Exit conditions:
- ; [bp].RegAX = channel status
- ;
- cmp [bp].RegDX,ChanFF ;Dummy channel?
- je CTxWtChanFF ;Yes - just return
- CTxWtAgain:
- cmp TBufCnt,TBufSize ;Is the transmit buffer full?
- jae CTxWtAgain ;Yes - continue on
- mov bx,TBufNext ;Point to next free char
- mov al,[bp].RegAL ;Get char from stack frame
- mov TBuf[bx],al ;Place char into buffer
- inc TBufCnt ;Increment transmit buffer count
- call TxEnable ;Enable transmitter
- cmp bx,TBufSize-1 ;Past end?
- jae CTxWaitWrap ;Yes - go wrap
- inc TBufNext ;Save pointer to next free char
- jmp short CStatus ;Get status and return
-
- CTxWaitWrap:
- mov TBufNext,0 ;Save pointer to next free char
- jmp short CStatus ;Get status and return
-
-
- CTxWtChanFF:
- ret ;Return to caller
-
- CTxWait endp
-
- subttl Receive a character from a channel with wait
- page
- CRxWait proc near
- ;
- ; Dequeues a character from a channel's receive buffer. Waits
- ; forever for a character.
- ;
- ; Entry conditions:
- ; [bp].RegDX = channel
- ; Exit conditions:
- ; [bp].RegAL = character
- ; [bp].RegAH = 00h
- ;
- cmp [bp].RegDX,ChanFF ;Dummy channel?
- je CRxWtRet ;Yes - just return
- CRxWtAgain:
- cmp RBufCnt,0 ;Anything in the buffer?
- je CRxWtAgain ;No - keep trying
- mov bx,RBufFirst ;Point to next recvd char
- mov al,byte ptr RBuf[bx] ;Get it into al
- xor ah,ah ;Clear ax
- mov [bp].RegAX,ax ;Store in register frame
- dec RBufCnt ;Decrement buffer count
- cmp RBufCnt,RBufLimit ;Below cutoff point
- ja CRxWtNoRFlow ;No - continue
- call RxUnhold ;Yes - unhold receiver
- CRxWtNoRFlow:
- cmp bx,RBufSize-1 ;Past end?
- jae CRxWtWrap ;Yes - go wrap buffer
- inc RBufFirst ;Save the new start pointer
- CRxWtRet:
- ret ;Return to caller
-
- CRxWtWrap:
- mov RBufFirst,0 ;Save the new start pointer
- ret ;Return to caller
-
- CRxWait endp
-
- subttl Get the status of a channel
- page
- CStatus proc near
- ;
- ; Gets a channel's status
- ;
- ; Entry conditions:
- ; [bp].RegDX = channel
- ; Exit conditions:
- ; [bp].RegAX = channel status
- ;
- cmp [bp].RegDX,ChanFF ;Dummy channel
- je CStatRet ;Yes - just return
- mov dx,0008h ;Initialize status
- cmp RBufCnt,0 ;Anything in receiver buffer
- je CStatTxRdy ;No - continue
- or dh,mask ARxRdy ;Yes - indicate RxRDY
- CStatTxRdy:
- cmp TBufCnt,TBufSize ;Buffer full?
- jae CStatDCD ;Yes - continue
- or dh,mask ATxEmp ;No - indicate transmit hold reg empty
- cmp TBufCnt,0 ;Anything in transmit buffer?
- jne CStatOvr ;Yes - continue
- or dh,mask ATxRdy ;No - indicate transmit shift reg empty
- CStatOvr:
- test RFlag,mask ROvr ;Has an overrun occurred?
- jz CStatDCD ;No - continue
- or dh,AOvrErr ;Indicate overrun
- and RFlag,not mask ROvr ;Reset overrun indicator
- CStatDCD:
- cli ;No interrupts
- mov al,LastCntl ;Get USART command
- or al,mask UErrClr ;Reset USART error flags
- out UCtrlPort,al ;Send command to USART
- in al,MStatPort ;Get modem status
- and al,mask MDCD ;Strip off all but DCD
- xor al,mask MDCD ;Reverse the bit
- shl al,6 ;Shift into high order bit
- sti ;Interrupts ok
- or dl,al ;Save in DL
- mov [bp].RegAX,dx ;Store status in register frame
- CStatRet:
- ret ;Return to caller
-
- CStatus endp
-
- subttl Open a channel
- page
- COpen proc near
- ;
- ; Open a channel
- ;
- ; Entry conditions:
- ; [bp].RegDX = channel
- ; Exit conditions:
- ; [bp].RegAX = 1954h
- ; [bp].RegBL = Highest function supported (not including 7E/7F)
- ; [bp].RegBH = FOSSIL spec revision supported
- ;
- cmp [bp].RegDX,ChanFF ;Dummy channel
- je COpenExit ;Yes - just return success
- call CClose ;Reset the channel
- mov [bp].RegAL,01h ;Set AL in stack frame
- call CDTR ;Cancel any flow control
- COpenExit:
- mov [bp].RegAX,Magic ;Put return values in reg frame
- mov [bp].RegBL,MaxFun ;Highest function supported
- mov [bp].RegBH,Version ;Spec revision supported
- ret ;Return to caller
-
- COpen endp
-
- subttl Close a channel
- page
- CClose proc near
- ;
- ; Close a channel
- ;
- ; Entry conditions:
- ; [bp].RegDX = channel
- ; Exit conditions:
- ; none
- ;
- cmp [bp].RegDX,ChanFF ;Dummy channel?
- je CCloseRet ;Yes - just return
- xor bx,bx
- cli ;No interrupts
- mov TBufFirst,bx ;Zero transmit buffer pointers
- mov TBufNext,bx
- mov TBufCnt,bx
- mov RBufFirst,bx ;Zero receive buffer pointers
- mov RBufNext,bx
- mov RBufCnt,bx
- mov RFlag,bl ;Reset receiver flags
- mov TFlag,bl ;Reset transmitter hold flags
- mov FFlag,bl ;Reset flow control flags
- mov XChar,bl ;Cancel any pending Xoff
- mov al,LastCntl ;Get current USART command
- and al,not mask UBrk ;Reset break bit
- or al,mask URTS + mask UTxEn + mask URxEn ;Set up USART command
- mov LastCntl,al ;Save new USART command
- or al,mask UErrCLr ;Set error clear bit
- out UCtrlPort,al ;Send new command to USART
- push [bp].RegAX ;Save AX from stack frame
- mov [bp].RegAL,0 ;Zero AL in stack frame
- sti ;Allow interrupts
- call CFlowCtl ;Cancel any flow control
- pop [bp].RegAX ;Restore AX in stack frame
- CCloseRet:
- ret ;Return to caller
-
- CClose endp
-
- subttl Toggle a channel's DTR line
- page
- CDTR proc near
- ;
- ; Toggle a channel's DTR line
- ;
- ; Entry conditions:
- ; [bp].RegAH = 06h
- ; [bp].RegAL = 00h - Lower DTR
- ; Not 00h - Raise DTR
- ; [bp].RegDX = channel
- ; Exit conditions:
- ; none
- ;
- cmp [bp].RegDX,ChanFF ;Dummy channel
- je CDTRRet ;Yes - just return
- cli ;No interrupts
- mov al,LastCntl ;Get last control byte
- cmp [bp].RegAL,00h ;Request to lower DTR?
- jne CDTRSet ;No - check for set
- and al,not mask UDTR ;Mask DTR off
- jmp short CDTRExit ;Go output control byte
- CDTRSet:
- or al,mask UDTR ;Mask DTR on
- CDTRExit:
- out UCtrlPort,al ;Send control byte to USART
- mov LastCntl,al ;Save new control byte
- nop ;Wait a bit
- nop
- sti ;Interrupts ok
- CDTRRet:
- ret ;Return to caller
-
- CDTR endp
-
-
- subttl Return timer parameters
- page
- TTickParm proc near
- ;
- ; This routine returns information about this machine's interval timer
- ;
- ; Entry conditions
- ; none
- ; Exit conditions:
- ; [bp].RegAL = timer tick interrupt #
- ; [bp].RegAH = Ticks per second
- ; [bp].RegDX = milliseconds per tick
- ;
- mov [bp].RegAL,1Ch ;Timer interrupt #
- mov [bp].RegAH,20 ;Ticks per second
- mov [bp].RegDX,50 ;Millisecs per tick
- ret ;Return to caller
-
- TTickParm endp
-
- subttl Flush a channel's transmit buffer
- page
- CFlushOut proc near
- ;
- ; Flush a channel's transmit buffer
- ;
- ; Entry conditions:
- ; [bp].RegDX = channel
- ; Exit conditions:
- ; none
- ;
- CFlushAgain:
- cmp [bp].RegDX,ChanFF ;Dummy channel
- je CFlushRet ;Yes - just return
- cmp TBufCnt,0 ;Is transmit buffer empty?
- jne CFlushAgain ;No - wait for it to be
- CFlushRet:
- ret ;Yes - return to caller
-
- CFlushOut endp
-
- subttl Purge a channel's transmit buffer
- page
- CPurOut proc near
- ;
- ; Purges (discards) a channel's transmit buffer
- ;
- ; Entry conditions:
- ; [bp].RegDX = channel
- ; Exit conditions:
- ; none
- ;
- cmp [bp].RegDX,ChanFF ;Dummy channel
- je CPurOutRet ;Yes - just return
- xor bx,bx
- cli ;Disable interrupts
- mov TBufFirst,bx ;Zero transmitter buffer pointers
- mov TBufNext,bx
- mov TBufCnt,bx
- sti ;Enable interrupts
- CPurOutRet:
- ret
-
- CPurOut endp
-
- subttl Purge a channel's receive buffer
- page
- CPurIn proc near
- ;
- ; Purges (discards) a channel's receive buffer
- ;
- ; Entry conditions:
- ; [bp].RegDX = channel
- ; Exit conditions:
- ; none
- ;
- cmp [bp].RegDX,ChanFF ;Dummy channel?
- je CPurInRet ;Yes - just return
- xor bx,bx
- cli ;No interrupts
- mov RBufFirst,bx ;Zero receiver buffer pointers
- mov RBufNext,bx
- mov RBufCnt,bx
- call RxUnhold ;Cancel any handshaking holds
- sti ;Interrupts ok
- CPurInRet:
- ret
-
- CPurIn endp
-
- subttl Send a character to a channel without wait
- page
- CTxNowait proc near
- ;
- ; Enqueue a character into the a channel's transmit buffer. Returns
- ; without waiting if buffer is full.
- ;
- ; Entry conditions:
- ; [bp].RegAL = character to enqueue
- ; [bp].RegDX = channel
- ; Exit conditions:
- ; [bp].RegAX = 0000h - operation was not successful
- ; 0001h - operation was successful
- ;
- cmp [bp].RegDX,ChanFF ;Dummy channel?
- je CTxNwRet ;Yes - just return
- cmp TBufCnt,TBufSize ;Is the transmit buffer full?
- jae CTxNwNoroom ;Yes - go indicate failure
- mov bx,TBufNext ;Point to next free char
- mov al,[bp].RegAL ;Get char from stack frame
- mov TBuf[bx],al ;Place char into buffer
- mov [bp].RegAX,1 ;Set successful return code
- inc TBufCnt ;Increment xmit buffer count
- call TxEnable ;Enable transmitter
- cmp bx,TBufSize-1 ;Past end?
- jae CTxNwWrap ;Yes - go wrap buffer
- inc TBufNext ;Save pointer to next free char
- CTxNwRet:
- ret ;Return to caller
-
- CTxNwNoroom:
- mov [bp].RegAX,0 ;Set unsuccessful return code
- ret ;Return to caller
-
- CTxNwWrap:
- mov TBufNext,0 ;Save pointer to next free char
- ret ;Return to caller
-
- CTxNowait endp
-
- subttl Receive a character from a channel without wait
- page
- CRxNowait proc near
- ;
- ; Peeks for a character from a channel's receive buffer
- ; and returns it. Returns without waiting if buffer
- ; is empty. The character is not removed from the receive
- ; buffer.
- ;
- ; Entry conditions:
- ; [bp].RegDX = channel
- ; Exit conditions:
- ; [bp].RegAX = FFFFh (operation was not successful)
- ; [bp].RegAL = char recvd (operation was successful)
- ; [bp].RegAH = 00h (operation was successful)
- ;
- cmp [bp].RegDX,ChanFF ;Dummy channel?
- je CRxNwRet ;Yes - just return
- cmp RBufCnt,0 ;Anything in the buffer?
- je CRxNwEmpty ;No - go indicate failure
- mov bx,RBufFirst ;Point to next recvd char
- mov al,byte ptr RBuf[bx] ;Get it into register
- xor ah,ah ;Clear ah
- mov [bp].RegAX,ax ;Store result in register frame
- CRxNwRet:
- ret ;Return to caller
-
- CRxNwEmpty:
- mov [bp].RegAX,0FFFFh ;Set unsuccessful return code
- ret ;Return to caller
-
- CRxNowait endp
-
- subttl Receive character from keyboard without wait
- page
- KRxNowait proc near
- ;
- ; Receives a character from the keyboard. Returns immediately
- ; if a character is not available.
- ;
- ; Entry conditions:
- ; none
- ; Exit conditions:
- ; [bp].RegAX = FFFFh (operation was not successful)
- ; [bp].RegAL = ASCII value (operation was successful)
- ; [bp].RegAH = keyboard scan code (operation was successful)
- ;
- mov ah,KeybdScan ;Set BIOS function
- int BiosKeybd ;Call the BIOS
- jnz KRxNwReady ;If char present, get out
- mov ax,0FFFFh ;Indicate no char present
- KRxNwReady:
- mov [bp].RegAX,ax ;Put result in register frame
- ret ;Return to caller
-
- KRxNowait endp
-
- subttl Receive character from keyboard with wait
- page
- KRxWait proc near
- ;
- ; Receives a character from the keyboard. Waits forever
- ; for a character.
- ;
- ; Entry conditions:
- ; none
- ; Exit conditions:
- ; [bp].RegAL = ASCII value
- ; [bp].RegAH = keyboard scan code
- ;
- mov ah,KeybdRead ;Set BIOS function
- int BiosKeybd ;Call the BIOS
- mov [bp].RegAX,ax ;Put result in register frame
- ret ;Return to caller
-
- KRxWait endp
-
- subttl Set/reset flow control
- page
- CFlowCtl proc near
- ;
- ; Enable/disable flow control. The Tandy 2000 implements
- ; CTS handshaking in hardware. There is no way to disable
- ; this handshaking, as the 8251A USART will simply not transmit
- ; data until CTS is true. DSR/DTR handshaking is not supported
- ; at this time.
- ;
- ; Entry conditions:
- ; [bp].RegAL = xxxxxxx0 - Disable transmit Xon/Xoff
- ; xxxxxxx1 - Enable transmit Xon/Xoff
- ; xxxxxx0x - Disable CTS/RTS
- ; xxxxxx1x - Enable CTS/RTS
- ; xxxx0xxx - Disable receive Xon/Xoff
- ; xxxx1xxx - Enable receive Xon/Xoff
- ; [bp].RegDX = channel
- ; Exit conditions:
- ; none
- ;
- cmp [bp].RegDX,ChanFF ;Dummy channel?
- je CFlRet ;Yes - just return
- cli ;No interrupts
- mov al,LastCntl ;Copy USART command
- test [bp].RegAL,mask FlTXon ;Enable transmit Xon/Xoff?
- jz CFlTXonOff ;No - disable it
- or FFlag,mask FTXon ;Yes - set indicator
- jmp short CFlRXon ;Check receiver Xon/Xoff
- CFlTXonOff:
- and FFlag,not mask FTXon ;Reset indicator
- test TFlag,mask TXonHld ;Has transmitter been held?
- jz CFlRXon ;Check receiver Xon/Xoff
- and TFlag,not mask TXonHld ;Cancel existing hold
- or al,mask UTxEn ;Enable transmitter
- CFlRXon:
- test [bp].RegAL,mask FlRXon ;Enable receive Xon/Xoff?
- jz CFlRXonOff ;No - disable it
- or FFlag,mask FRXon ;Set indicator
- mov XChar,0 ;Cancel any pending Xoff
- jmp short CFlRTS ;Check RTS/CTS
- CFlRXonOff:
- and FFlag,not mask FRXon ;Reset indicator
- cmp LastXChar,Xoff ;Was Xoff sent?
- jne CFlRTS ;No - check RTS/CTS
- mov XChar,Xon ;Stuff Xon into transmitter
- or al,mask UTxEn ;Enable transmitter
- CFlRTS:
- test [bp].RegAL,FlRTS ;Enable RTS handshaking?
- jz CFlRTSOff ;No - disable RTS handshaking
- or FFlag,mask FRTS ;Yes - set indicator
- jmp short CFlOut ;Output USART control byte (if needed)
- CFlRTSOff:
- and FFlag,not mask FRTS ;Reset indicator
- or al,mask URTS ;Set RTS bit in USART control byte
- CFlOut:
- cmp al,LastCntl ;Has USART control byte changed?
- je CFlEXit ;No - don't need to send it
- out UCtrlPort,al ;Send it to the USART
- mov LastCntl,al ;Save new USART control byte
- nop ;Wait a bit
- nop
- CFlExit:
- sti ;Interrupts ok
- CFlRet:
- ret ;Return to caller
-
- CFlowCtl endp
-
- subttl Set/reset CTL-C/CTL-K checking
- page
- CCtlChk proc near
- ;
- ; Enable/disable Ctl-C/Ctl-K checking; logout and clear current
- ; Ctl-C/Ctl-K mask. Also enable/disable the transmitter
- ;
- ; Entry conditions:
- ; [bp].RegAL = xxxxxxx0 - Disable Ctl-C/Ctl-K checking
- ; xxxxxxx1 - Enable Ctl-C/Ctl-K checking
- ; xxxxxx0x - Disable transmitter
- ; xxxxxx1x - Enable transmitter
- ; [bp].RegDX = channel
- ; Exit conditions:
- ; [bp].RegAX = 0000h - Ctl-C/Ctl-K not received since last logout
- ; 0001h - Ctl-C/Ctl-K received since last logout
- ;
- cmp [bp].RegDX,ChanFF ;Dummy channel?
- je CCtlRet ;Yes - just return
- test [bp].RegAL,02h ;Disable transmitter?
- jz CCtlTxEn ;No - enable it
- or TFlag,mask TPrgHld ;Indicate program hold
- jmp short CCtlCont ;Go output control byte
- CCtlTxEn:
- and TFlag,not mask TPrgHld ;Indicate no programmer hold
- call TxEnable ;Enable transmitter
- CCtlCont:
- test [bp].RegAL,01h ;Start Ctl-C/Ctl-K checking?
- cli ;No interrupts
- jz CCtlOff ;No - stop Ctl-C/Ctl-K checking?
- or RFlag,mask RCtlChk ;Indicate checking
- jmp short CCtlLog
- CCtlOff:
- and RFlag,not mask RCtlChk ;Indicate no checking
- jmp short CCtlClr ;Clear things up
- CCtlLog:
- mov [bp].RegAX,0 ;Zero mask
- test RFlag,mask RCtlRcv ;Has a break been received?
- jz CCtlClr ;No - leave mask zero
- mov [bp].RegAX,1 ;Yes - indicate break to caller
- CCtlClr:
- and RFlag,not mask RCtlRcv ;Zero break flag
- sti ;Interrupts ok
- CCtlRet:
- ret ;Return to caller
-
- CCtlChk endp
-
- subttl Set cursor location
- page
- DSetCurLoc proc near
- ;
- ; Set current cursor position
- ;
- ; Entry conditions
- ; [bp].RegDH = row
- ; [bp].RegDL = column
- ; Exit conditions:
- ; none
- ;
- mov dx,[bp].RegDX ;Get parms from register frame
- mov ah,VideoSetCurPos ;Set BIOS function
- xor bh,bh ;Select page 0
- int BiosVideo ;Call BIOS
- ret ;Return to caller
-
- DSetCurLoc endp
-
- subttl Get cursor location
- page
- DGetCurLoc proc near
- ;
- ; Get current cursor position
- ;
- ; Entry conditions
- ; none
- ; Exit conditions:
- ; [bp].RegDH = row
- ; [bp].RegDL = column
- ;
- mov ah,VideoGetCurPos ;Set BIOS function
- xor bh,bh ;Select page 0
- int BiosVideo ;Call BIOS
- mov [bp].RegDX,dx ;Store results in register frame
- ret ;Return to caller
-
- DGetCurLoc endp
-
- subttl Put character to display using ANSI.SYS
- page
- DPutDos proc near
- ;
- ; Put a character to the display via ANSI.SYS
- ;
- ; Entry conditions
- ; [bp].RegAL = char to output
- ; Exit conditions:
- ; none
-
- mov dl,[bp].RegAL ;Get char from register frame
- dir_con_io ;Write char using ANSI
- ret ;Return to caller
-
- DPutDos endp
-
- subttl Watch channel and reboot if CD lost
- page
- CWatchDog proc near
- ;
- ; This routine adds/deletes a small routine to/from the timer tick. This
- ; routine checks for CD on a channel. If CD is false, the system is
- ; rebooted.
- ;
- ; Entry conditions:
- ; [bp].RegAL = 00h - Disable watchdog
- ; [bp].RegAL = 01h - Enable watchdog
- ; [bp].RegDX = channel
- ; Exit conditions:
- ; none
- ;
- cmp [bp].RegDX,ChanFF ;Dummy channel
- je CWatchDogRet ;Yes - just return
- push [bp].RegES ;Save current stack frame values
- push [bp].RegDX
- push [bp].RegAX
- mov [bp].RegES,cs ;Get segment of watchdog routine
- mov [bp].RegDX,offset WatchDog ;Get offset
- call TTickMgr ;Install tick routine
- pop [bp].RegAX ;Restore caller's stack frame
- pop [bp].RegDX
- pop [bp].RegES
- CWatchDogRet:
- ret ;Return to caller
-
- CWatchDog endp
-
- subttl Put char to console bypassing DOS
- page
- DPutBios proc near
- ;
- ; Put a character to the display bypassing DOS
- ;
- ; Entry conditions
- ; [bp].RegAL = char to output
- ; Exit conditions:
- ; none
- ;
- mov al,[bp].RegAL
- mov ah,VideoWrTty ;Set BIOS function
- int BiosVideo ;Call BIOS
- ret ;Return to caller
-
- DPutBios endp
-
- subttl Manage the timer tick chain
- page
- TTickMgr proc near
- ;
- ; This routine adds and deletes routines from the timer tick chain.
- ; A maximum of eight routines are supported. If a request is
- ; made to delete a routine already present in the chain, the
- ; old version is deleted, and the new one added to the top of
- ; the chain. The chain of routines is maintained as a push/pop
- ; stack.
- ;
- ; Entry conditions:
- ; [bp].RegAL = 00h - Delete a routine from the chain
- ; [bp].RegAL = 01h - Add a routine to the chain
- ; [bp].RegES = Segment of routine
- ; [bp].RegDX = Offset of routine
- ; Exit conditions:
- ; [bp].RegAX = 0000h - Operation was successful
- ; FFFFh - Operation was unsuccessful
- ;
- test [bp].RegAL,1 ;Request to add routine?
- jz TTDelete ;No - must be delete
- call TTFind ;It is add - check for duplicate
- and ax,ax ;Check return code
- js TTAdd ;No dups - just add it
- call TTSnip ;Remove old version of routine
- and ax,ax ;Everything ok?
- js TTErr ;No - error
- TTAdd:
- call TTPush ;Push new routine pointer
- jmp short TTRet ;Get out
- TTDelete:
- call TTFind ;Find requested routine
- and ax,ax ;Found?
- js TTErr ;No - error
- call TTSnip ;Yes - snip it from chain
- TTRet:
- mov [bp].RegAX,ax ;Put return code in stack frame
- ret ;Return to caller
- TTErr:
- mov [bp].RegAX,0FFFFh ;Indicate failure
- ret ;Return to caller
-
- TTickMgr endp
-
- subttl Find a routine in the timer tick chain
- page
- TTFind proc near
-
- mov bx,offset TTRoutTab ;Get routine table address
- xor si,si ;Zero the table index
- mov cx,TTRoutCnt ;Get number of routines
- and cx,cx ;Are there any?
- jz TTFindNotFound ;No - skip the search
- TTFindLoop:
- mov ax,[bp].RegES ;Get segment of search argument
- cmp ax,[bx][si]+2 ;Equal to segment of table element?
- jne TTFindIncr ;No - try next table element
- mov ax,[bp].RegDX ;Get offset of search argument
- cmp ax,[bx][si] ;Equal to offset of table element?
- je TTFindFound ;Yes - exit loop
- TTFindIncr: ;No - keep trying
- add si,4 ;Increment the table index
- loop TTFindLoop ;If more table elements, try again
- TTFindNotFound:
- mov ax,0FFFFh ;No luck - set no-hit return code
- jmp short TTFindRet ;Go return to caller
- TTFindFound: ;Search successful - convert index
- mov ax,TTRoutCnt ; to relative table entry index
- sub ax,cx
- TTFindRet:
- ret ;Return to caller
-
- TTFind endp
-
- subttl Snip a routine from the timer tick chain
- page
- TTSnip proc near
-
- mov cx,TTRoutCnt ;Get the number of routines
- and cx,cx ;Anything to delete?
- jz TTSnipErr ;No - error
- cmp ax,TTRoutCnt-1 ;Trying to delete past last routine?
- ja TTSnipErr ;Yes - error
- dec cx ;Convert to displacement
- jz TTSnipDecr ;No pop needed for last routine
- sub cx,ax ;Calculate number of moves
- mov bx,offset TTRoutTab ;Point base to routine table
- shl ax,2 ;Convert routine number to an offset
- add bx,ax ; and add it to the base
- xor si,si ;Zero the loop index
- cli ;No interrupts
- TTSnipLoop: ;Pop remaining routines
- mov ax,[bx][si]+6 ;Move segment
- mov [bx][si]+2,ax
- mov ax,[bx][si]+4 ;Move offset
- mov [bx][si],ax
- add si,4 ;Increment index
- loop TTSnipLoop ;Repeat for remaining routines
- TTSnipDecr:
- dec TTRoutCnt ;Decrement routine counter
- sti ;Allow interrupts
- xor ax,ax ;Set successful return code
- ret ;Return to caller
- TTSnipErr:
- mov ax,0FFFFh ;Set unsuccessful return code
- ret ;Return to caller
-
- TTSnip endp
-
- subttl Push a new routine onto the timer tick chain
- page
- TTPush proc near
-
- cmp TTRoutCnt,TTRoutLim ;Chain full?
- je TTPushErr ;Yes - error
- mov bx,offset TTRoutTab ;Set base to start of table
- mov cx,TTRoutCnt ;Get number of routines
- and cx,cx ;Are there any?
- jz TTPushNew ;No - just add new routine
- mov si,cx ;Get starting index
- dec si ;Convert to displacment
- shl si,2
- cli ;No interrupts
- TTPushLoop:
- mov ax,[bx][si]+2 ;Move segment
- mov [bx][si]+6,ax
- mov ax,[bx][si] ;Move offset
- mov [bx][si]+4,ax
- sub si,4 ;Decrement index
- loop TTPushLoop ;Repeat for remaining routines
- TTPushNew:
- mov ax,[bp].RegES ;Insert segment of new routine
- mov [bx]+2,ax
- mov ax,[bp].RegDX ;Insert offset of new routine
- mov [bx],ax
- inc TTRoutCnt ;Increment routine counter
- sti ;Allow interrupts
- xor ax,ax ;Indicate success
- ret ;Return to caller
- TTPushErr:
- mov ax,0FFFFh ;Indicate failure
- ret ;Return to caller
-
- TTPush endp
-
- subttl Reboot the system
- page
- Reboot proc near
- ;
- ; This routine reboots the system using the BIOS reboot interrupt.
- ; The T2K only supports hard reboots.
- ;
- ; Entry conditions:
- ; none
- ; Exit conditions:
- ; none
- ;
- int BiosBoot ;Reboot via BIOS
-
- Reboot endp
-
- subttl Dequeue a block of characters from a channel
- page
- CBlockRead proc near
- ;
- ; This routine dequeues a block of characters from a channel's
- ; receive buffer into a user provided buffer. Up to 64k
- ; characters may be dequeued with one call. The routine
- ; only as many characters as the buffer contains at the time
- ; of the call.
- ;
- ; Entry conditions:
- ; [bp].RegCX = Maximum number of characters to dequeue
- ; [bp].RegDX = channel
- ; [bp].RegES = Segment of user's buffer
- ; [bp].RegDI = Offset of user's buffer
- ; Exit conditions:
- ; [bp].RegAX = Number of characters dequeued into
- ; the user's buffer
- ;
- cmp [bp].RegDX,ChanFF ;Dummy channel?
- je CBlkRdRet ;Yes - just return
- mov bx,RBufCnt ;Get number of chars in buffer
- and bx,bx ;Buffer empty?
- jz CBlkRdEmpty ;Yes - get out
- cmp bx,[bp].RegCX ;Greater than number requested?
- jbe CBlkRdNotAll ;No - can only move what we have
- mov bx,[bp].RegCX ;Yes - move number requested
- CBlkRdNotAll:
- mov cx,RBufSize ;Get length of buffer
- sub cx,RBufFirst ;Calculate length to end of buffer
- mov es,[bp].RegES ;Point to user's buffer
- mov di,[bp].RegDI
- mov si,offset RBuf ;Point to receive buffer
- add si,RBufFirst ;Point to first char to be moved
- cmp cx,bx ;Greater than number requested?
- jb CBlkRd2Moves ;No - will take two moves
- mov cx,bx ;Yes - only one move needed
- rep movsb ;Move chars to user buffer
- sub si,offset RBuf ;Convert to displacement within buffer
- cmp si,RBufSize ;At end of buffer?
- jb CBlkRdDone ;No - finish up
- xor si,si ;Yes - wrap
- jmp short CBlkRdDone ;Finish up
- CBlkRd2Moves:
- mov ax,cx ;Save move length
- rep movsb ;Move first chars to user buffer
- mov cx,bx ;Get total move length
- sub cx,ax ;Decrement by number already moved
- mov si,offset RBuf ;Point to start of buffer
- rep movsb ;Move remaining number of chars
- sub si,offset RBuf ;Convert to displacement within buffer
- CBlkRdDone:
- mov RBufFirst,si ;Set pointer to next char in buffer
- cmp RBufCnt,RBufLimit ;Below cutoff point
- ja CBlkRdNoRFlow ;No - continue
- call RxUnhold ;Yes - unhold receiver
- CBlkRdNoRFlow:
- sub RBufCnt,bx ;Decrement count of chars in buffer
- CBlkRdEmpty:
- mov [bp].RegAX,bx ;Return total number moved
- CBlkRdRet:
- ret ;Return to caller
-
- CBlockRead endp
-
- subttl Enqueue a block of characters on a channel
- page
- CBlockWrite proc near
- ;
- ; This routine enqueues a block of characters from a user
- ; provided buffer into a channel's transmit buffer. Up to 64k
- ; characters may be enqueued with one call. The routine only
- ; enqueues as many characters as there are free in the transmit
- ; buffer at the time of the call.
- ;
- ; Entry conditions:
- ; [bp].RegCX = Maximum number of characters to enqueue
- ; [bp].RegDX = channel
- ; [bp].RegES = Segment of user's buffer
- ; [bp].RegDI = Offset of user's buffer
- ; Exit conditions:
- ; [bp].RegAX = Number of characters enqueued into
- ; the transmit buffer
- ;
- cmp [bp].RegDX,ChanFF ;Dummy channel?
- je CBlkWrRet ;Yes - just return
- mov bx,TBufSize ;Get length of buffer
- mov cx,bx ;Save a copy
- sub bx,TBufCnt ;Calculate free space
- jz CBlkWrFull ;Is buffer full?
- cmp bx,[bp].RegCX ;Greater than number requested?
- jbe CBlkWrNotAll ;No - can only move what we can hold
- mov bx,[bp].RegCX ;Yes - move number requested
- CBlkWrNotAll:
- sub cx,TBufNext ;Calculate length to end of buffer
- mov dx,cs ;Point to transmit buffer
- mov es,dx
- mov di,offset TBuf
- add di,TBufNext ;Point to free space
- mov ds,[bp].RegES ;Point to user's buffer
- mov si,[bp].RegDI
- cmp cx,bx ;Greater than number requested?
- jb CBlkWr2Moves ;No - will take two moves
- mov cx,bx ;Yes - only one move needed
- rep movsb ;Move chars to user buffer
- sub di,offset TBuf ;Convert to displacement within buffer
- cmp di,TBufSize ;At end of buffer?
- jb CBlkWrDone ;No - finish up
- xor di,di ;Yes - wrap
- jmp short CBlkWrDone ;Finish up
- CBlkWr2Moves:
- mov ax,cx ;Save move length
- rep movsb ;Move first chars to user buffer
- mov cx,bx ;Get total move length
- sub cx,ax ;Decrement by number already moved
- mov di,offset TBuf ;Point to start of buffer
- rep movsb ;Move remaining number of chars
- sub di,offset TBuf ;Convert to displacement within buffer
- CBlkWrDone:
- mov ds,dx ;Restore DX
- mov TBufNext,di ;Point to free space
- add TBufCnt,bx ;Increment count of chars in buffer
- CBlkWrFull:
- mov [bp].RegAX,bx ;Return total number moved
- call TxEnable ;Enable the transmitter
- CBlkWrRet:
- ret
-
- CBlockWrite endp
-
- subttl Start/Stop sending a break on a channel
- page
- CBreak proc near
- ;
- ; This routine starts/stops sending a break (continuous spacing) on
- ; the specified channel.
- ;
- ; Entry conditions:
- ; [bp].RegAL = 00h - Stop sending break
- ; 01h - Start sending break
- ; [bp].RegDX = channel
- ; Exit conditions:
- ; none
- ;
- cmp [bp].RegDX,ChanFF ;Dummy channel?
- je CBreakRet ;Yes - just return
- cli ;No interrupts
- mov al,LastCntl ;Get current USART command
- test [bp].RegAX,01h ;Request to start sending break?
- jz CBreakStop ;No - then stop sending break
- and TFlag,not mask TXonHld ;Cancel existing hold
- or al,mask UBrk ;Set break bit
- and al,not mask UTxEn ;Reset transmit enable bit
- jmp short CBreakOut ;Go send it to to the USART
- CBreakStop:
- and al,not mask UBrk ;Reset break bit
- or al,mask UTxEn ;Set transmit enable bit
- CBreakOut:
- out UCtrlPort,al ;Send command to USART
- mov LastCntl,al ;Save new USART command
- nop ;Wait a bit
- nop
- sti ;Allow interrupts
- CBreakRet:
- ret ;Return to caller
-
- CBreak endp
-
- subttl Return information about the driver
- page
- CInfo proc near
- ;
- ; This routine fills a user-supplied buffer with various information
- ; concerning the internal status and capabilities of the FOSSIL.
- ;
- ; Entry conditions:
- ; [bp].RegCX = Length of user-supplied buffer
- ; [bp].RegES = Segment of user-supplied buffer
- ; [bp].RegDI = Offset of user supplied buffer
- ; [bp].RegDX = channel
- ; Exit conditions:
- ; [bp].RegAX = Number of characters actually placed into
- ; the user-supplied buffer
- ;
- mov ax,RBufSize ;Calculate receive buffer free space
- sub ax,RBufCnt
- mov InfoRFree,ax ;Store it in info area
- mov ax,TBufSize ;Calculate transmit buffer free space
- sub ax,TBufCnt
- mov InfoTFree,ax ;Store it in info area
- mov si,offset Info ;Set up source pointer
- mov es,[bp].RegES ;Set up destination pointer
- mov di,[bp].RegDI
- mov cx,InfoSize ;Get length of info area
- cmp cx,[bp].RegCX ;Is user's buffer large enough?
- jae CInfoMove ;Yes - move entire area
- mov cx,[bp].RegCX ;No - just move number requested
- CInfoMove:
- mov [bp].RegAX,cx ;Store number moved in stack frame
- rep movsb ;Move info area to user buffer
- ret ;Return to caller
-
- CInfo endp
-
- subttl Output to a port and wait a while
- page
- PutWait proc near
-
- out dx,al ;Write to specified port
- nop
- nop
- nop
- ret ;Return to caller
-
- PutWait endp
-
- subttl Enable the USART transmitter
- page
- TxEnable proc near
-
- mov al,LastCntl ;Copy last USART command
- or al,mask UTxEn ;Set transmitter enable bit
- cmp al,LastCntl ;Any change?
- je TxEnableRet ;No - no action needed
- pushf ;Save interrupt state
- cli ;No interrupts
- out UCtrlPort,al ;Send command to USART
- mov LastCntl,al ;Save USART command
- nop ;Wait a bit
- nop
- popf ;Restore interrupt state
- TxEnableRet:
- ret ;Return to caller
-
- TxEnable endp
-
- subttl Cancel receiver holds
- page
- RxUnhold proc near
-
- mov al,LastCntl ;Copy last USART command
- test FFlag,mask FRXon ;Receive Xon/Xoff active?
- jz RxUnhOut ;No - output USART command
- cmp LastXChar,Xon ;Was Xon already sent?
- je RxUnhOut ;Yes - Xon not needed
- mov XChar,Xon ;Feed Xon to transmitter
- or al,mask UTxEn ;Enable transmitter
- RxUnhOut:
- or al,mask URTS ;Raise RTS
- cmp al,LastCntl ;Anything changed?
- je RxUnhRet ;No - don't output USART command
- pushf ;Save interrupt state
- cli ;No - interrupts
- out UCtrlPort,al ;Output USART command
- mov LastCntl,al ;Save new USART command
- nop ;Wait a bit
- nop
- popf ;Restore interrupt state
- RxUnhRet:
- ret ;Return to caller
-
- RxUnhold endp
-
- subttl Carrier watchdog routine
- page
- WatchDog proc far
-
- push ax ;Save caller's register
- in al,MStatPort ;Get modem status
- test al,mask MDCD ;CD true?
- jz WatchDogRet ;Yes - continue
- int BiosBoot ;No - reboot system
- WatchDogRet:
- pop ax ;Restore caller's register
- ret ;Return to caller
-
- WatchDog endp
-
- subttl 8251A USART Interrupt Handler
- page
- Int72 proc near
-
- sti ;Allow interrupts
- push ax ;Save caller's regsisters
- push bx
- push ds
- mov ax,cs ;Set DS to CS
- mov ds,ax
-
- Repoll: ;Determine source of interrupt
- in al,UStatPort ;Get USART status
- test al,mask URxRdy ;Rx ready?
- jnz RxInt ;Yes - go process receiver interrupt
- test al,mask UTxRdy ;Tx ready?
- jz Int72Ret ;No - get out
- test LastCntl,mask UTxEn ;Transmitter enabled?
- jz Int72Ret ;No - get out
- jmp TxInt ;Yes - process transmitter interrupt
-
- Int72Ret:
- ; Issue EOI to reset IS bit in 8259A. Also, check 8259A for
- ; more interrupts at this level in 80186 - if none pending,
- ; then issue EOI in 80186
- cli ;No interrupts
- mov al,EOICmd59 ;Set OCW2 to specific EOI for level 2
- out OCW2A,al ;Output OCW2 to PIC(0)
- nop
- nop
- mov al,ISRCmd59 ;Set OCW3 to return IS reg
- out OCW2A,al ;Output OCW3
- nop
- nop
- xchg bx,dx ;Save dx
- mov dx,EOIReg86 ;Point to 80186 EOI register
- in al,OCW2A ;Get PIC(0) in-service register
- or al,al ;Any other interrupts pending?
- jnz NoEOI86 ;Yes - don't clear 80186
- mov ax,EOICmd86 ;Get non-specific EOI for 80186
- out dx,ax ;Clear 80186 interrupt controller
- NoEOI86:
- xchg bx,dx ;Restore dx
- pop ds ;Restore previous context
- pop bx
- pop ax
- iret ;Return to point of interrupt
-
- page
- ; Process Receiver Interrupt
- ;
- RxInt:
- in al,UDataPort ;Get data
- test RFlag,mask RCtlChk ;Trapping Ctl-C/Ctl-K?
- jnz RxChkCtl ;Yes - check for break
- RxInt1:
- test FFlag,mask FTXon ;Transmit Xon/Xoff active?
- jnz RxTFlow ;Yes - go check for Xon/Xoff
- RxInt2:
- mov bx,RBufNext ;bx := next space in buffer
- mov byte ptr RBuf[bx],al ;Place data into buffer
- cmp RBufCnt,RBufSize ;Room for data in buffer?
- jae RxOverrun ;No - Indicate overrun
- inc RBufCnt ;Increment # of chars in buffer
- cmp RBufCnt,RBufLimit ;Receiver past handshake point?
- jbe RxNoRFlow ;Yes - go do handshake
- mov al,LastCntl ;Copy last USART control byte
- test FFlag,mask FRXon ;Receive Xon/Xoff active?
- jz RxRFlowRTS ;No - check RTS handshaking
- cmp LastXChar,Xoff ;Xoff already sent
- je RxRFlowRTS ;Yes - don't send another
- mov XChar,Xoff ;Feed Xoff to transmitter
- or al,mask UTxEn ;Enable transmitter
- RxRFlowRTS:
- test FFlag,mask FRTS ;RTS handshaking active?
- jz RxRFlowOut ;No - output USART control byte
- and al,not mask URTS ;Lower RTS
- RxRFlowOut:
- cmp al,LastCntl ;Has anything changed?
- je RxNoRFlow ;No - no need to do anything
- mov LastCntl,al ;Save new USART control byte
- out UCtrlPort,al ;Output control byte to USART
- RxNoRFlow:
- cmp bx,RBufSize-1 ;Past end of the buffer?
- jnb RxWrap ;Yes - go wrap buffer
- inc RBufNext ;Increment buffer index
- jmp Repoll ;Check for more work
-
- RxChkCtl:
- cmp al,CtlC ;Ctl-C?
- je RxSetMask ;Yes - treat specially
- cmp al,CtlK ;Ctl-K?
- jne RxInt1 ;No - go buffer char
- RxSetMask:
- or RFlag,mask RCtlRcv ;Indicate break received
- jmp Repoll ;Don't buffer char
-
- RxTFlow:
- cmp al,Xon ;Xon?
- jne RxChkXoff ;No - continue checking
- and TFlag,not mask TXonHld ;Yes - tell xmitter to proceed
- call TxEnable ;Enable transmitter
- jmp Repoll ;Don't buffer Xon
- RxChkXoff:
- cmp al,Xoff ;Xoff?
- jne RxInt2 ;No - try to buffer char
- or TFlag,mask TXonHld ;Yes - tell xmitter to hold it
- jmp Repoll ;Don't buffer Xoff
-
- RxOverrun:
- or RFlag,mask ROvr ;Indicate overrun
- jmp Repoll
-
- RxWrap:
- mov RBufNext,0 ;Zero buffer index
- jmp Repoll ;Check for more work
-
- page
- ; Process transmitter interrupt
- ;
- ;
- ; Buffer contains data - output a byte to the USART
- ;
- TxInt: cmp XChar,0 ;Need to send a flow control char?
- jne TxSendXChar ;Yes - send it
- cmp TBufCnt,0 ;Anything in buffer?
- je TxShutoff ;No - shut off transmitter
- cmp TFlag,0 ;Transmitter held?
- jne TxShutoff ;Yes - shut off transmitter
- mov bx,TBufFirst ;BX points to next char to be sent
- mov al,TBuf[bx] ;Get data from buffer
- out UDataPort,al ;Send data
- dec TBufCnt ;Decrement buffer count
- cmp bx,TBufSize-1 ;Past end?
- jnb TxWrap ;Yes - wrap buffer
- inc TBufFirst ;Increment buffer index
- jmp Repoll ;Check for RxRdy
-
- TxWrap:
- mov TBufFirst,0 ;Zero buffer index
- jmp Repoll ;Check for RxRDY
-
- TxSendXChar:
- mov al,XChar ;Get the handshake character to send
- out UDataPort,al ;Send it to the USART
- mov LastXChar,al ;Save last handshake character
- mov XChar,0 ;Clear the handshake character
- jmp Repoll ;Check for RxRdy
-
-
- TxShutoff:
- mov al,LastCntl ;Get last USART command
- and al,not mask UTxEn ;Reset TxEnable bit
- out UCtrlPort,al ;Output to USART
- mov LastCntl,al ;Save last USART command
- nop ;Wait a bit
- nop
- jmp Repoll ;Check for RxRdy
-
- Int72 endp
-
- subttl Timer tick routine
- page
- Int1C proc near
-
- push ds ;Save affected regs
- push bx
- push cx
- mov cx,cs ;Set data segment
- mov ds,cx
- mov cx,TTRoutCnt ;Get number of routines
- and cx,cx ;Are there any?
- jz Int1CSkip ;No - just return
- mov bx,offset TTRoutTab ;Point to routine table
- Int1CLoop:
- call dword ptr [bx] ;Call the routine
- add bx,4 ;Point to next routine
- loop Int1CLoop ;Continue if any more routines
- Int1CSkip:
- pop cx ;Pop affected regs
- pop bx
- pop ds
- jmp dword ptr cs:OldInt1C ;jump to BIOS tick handler
-
- Int1C endp
-
- subttl Initialization Routines
- page
- FInit1 proc near
-
- mov word ptr InfoID,offset IDString ;Place address of ID string
- mov word ptr InfoID+2,cs ; into information area
- ;
- ; Initialize the extended dispatcher address table
- ;
- mov bx,offset UserAppTable ;Point to table
- mov dx,offset FarRet ;Get address of iret instruction
- mov cx,64 ;Set up initialization loop
- InitLoop:
- mov [bx],dx ;Save offset in table entry
- mov [bx]+2,ds ;Save segment
- add bx,4 ;Point to next entry
- loop InitLoop ;Repeat for all 64 entries
-
- push ds ;Save DS
- cli ;No interrupts
- ;
- ; Install FOSSIL BIOS
- ;
- mov cx,offset Int14 ;Set up offset of new comm BIOS
- mov dx,cs ;Set up segment of new comm BIOS
- xor ax,ax
- mov ds,ax ;Point to Int 14h vector
- mov si,14h*4
- mov ds:[si],cx ;Insert new Int 14h vector
- mov ds:[si]+2,dx
- mov si,53h*4 ;Point to Int 53h vector
- mov ds:[si],cx ;Insert new Int 53h vector
- mov ds:[si]+2,dx
- ;
- ; Install new USART handler
- ;
- mov cx,offset Int72 ;Set up offset of new USART handler
- mov si,72h*4 ;Point to Int 72h vector
- mov ds:[si],cx ;Insert new Int 72h vector
- mov ds:[si]+2,dx
- ;
- ; Install timer tick manager
- ;
- mov si,1Ch*4 ;Point to timer tick vector
- mov ax,ds:[si] ;Get current tick offset
- mov word ptr cs:OldInt1C,ax ;Save current tick offset
- mov ax,ds:[si]+2 ;Get current tick segment
- mov word ptr cs:OldInt1C+2,ax ;Save current tick segment
- mov cx,offset Int1C ;Point to our tick routine
- mov ds:[si],cx ;Insert new Int 1Ch vector
- mov ds:[si]+2,dx
- sti ;Enable interrupts
- pop ds ;Restore DS
- ;
- ; Set end of driver address in request header
- ;
- mov word ptr es:[di].RHBufAdr,offset FInit1
- mov word ptr es:[di].RHBufAdr+2,cs
- ;
- ; Initialize the pointers to the secondary device driver headers
- ;
- mov word ptr FOSSIL$,offset COM1 ;Store offset
- mov word ptr FOSSIL$+2,cs ;Store segment
- mov word ptr COM1,offset AUX ;Store offset
- mov word ptr COM1+2,cs ;Store segment
- ;
- ; Init port 0 to 2400 8 N 1
- ;
- xor ah,ah ;Set FOSSIL function
- mov al,0a3h ;Set port parameters
- xor dx,dx ;Set port number
- int FOSSIL ;Call FOSSIL
- ;
- ; Let the user know everything is OK and exit
- ;
- mov dx,offset InstMsg
- call prtmsg ;Print installed message
- ;
- ; Print copyright message
- ;
- mov dx,offset CopyMsg
- call PrtMsg
- ret ;Return to interrupt routine
-
- FInit1 endp
-
- FInit2 proc near
-
- ;
- ; Set end of driver address in request header
- ;
- mov word ptr es:[di].RHBufAdr,offset FInit1
- mov word ptr es:[di].RHBufAdr+2,cs
- ret ;Return to interrupt routine
-
- FInit2 endp
-
- subttl Message Routine
- page
- PrtMsg proc near
- put_string
- ret
- PrtMsg endp
-
- InstMsg db 'T2KCOMM FOSSIL Driver, v5.2',13,10,'$'
-
- code ends
- subttl Symbol table
- end
-