[Back to COMM SWAG index]  [Back to Main SWAG index]  [Original]


Unit Fossil;

Interface

Uses Dos;

Type
   DriverInfo      = Record
   StrucSize       : Word;
   MajorVersion    : Byte;
   CurrentRevision : Byte;
   IDPtr           : Array[1..2] of Word;
   InputBufferSize : Word;
   InputBufferFree : Word;
   OutputBufferSize: Word;
   OutputBufferFree: Word;
   ScreenWidth     : Byte;
   ScreenHieght    : Byte;
   BaudRate        : Byte;
   DriverName      : String[80];
                     End;
   MaxStr = String[255];
   Str80  = String[80];

Var
    Regs            : Registers;
    FossilInfo      : DriverInfo;

Function Port_Status(Port:Byte):Word;
Procedure Set_Baud( Port:Byte; Speed:Byte);
Function Xmit(Port:Byte; OutChar:Char):Word;
Function CommWrite(Port:Byte; OutString:MaxStr):Word;
Function CommRead(Port:Byte):Char;
Function Init_Fossil(Port:Byte; BreakAddr:Word; Var MaxFunctionNum:Byte;
                     Var RevDoc:Byte):Word;
Procedure DeInit_Fossil(Port:Byte);
Procedure ModemDTR(Port:Byte; DTRUp:Boolean);
Procedure Get_Timer_Data(Var InterruptNum:Byte;  (* Return Timing Info *)
                         Var  TicksPerSec:Byte;
                         Var MillisecsPer:Word);
Procedure Flush_Output_Buffer(Port:Byte);
Procedure Purge_Output_Buffer(Port:Byte);
Procedure Purge_Input_Buffer(Port:Byte);
Function Xmit_Nowait(Port:Byte; OutChar:Char):Boolean;
Function Read_Ahead(Port:Byte):Char;
Function KeyRead_Nowait:Word;
Function Keyread:Word;
Procedure Flow_Control(Port:Byte; ControlMask:Byte);
Function Abort_Control(Port:Byte; Flags:Byte):Word;
Procedure Set_CursorXY(X,Y:Byte);
Procedure Get_CursorLoc(Var X,Y:Byte);
Procedure ANSI_Write(OutChar:Char);
Procedure Watchdog(Port:Byte; CarrierWatch:Boolean);
Procedure BIOS_Write(OutChar:Char);
Function TimerChain(Add:Boolean; FunctionSeg:Word; FunctionOfs:Word):Boolean;
Procedure System_Reboot(ColdBoot:Boolean);
Function ReadBlock(Port:Byte; MaxBytes:Word; Var Buffer):Word;
Function WriteBlock(Port:Byte; MaxBytes:Word; Var Buffer):Word;
Procedure SendBreak(Port:Byte; SendOn:Boolean);
Procedure Driver_Info(Port:Byte; Var FossilInfo:DriverInfo);
Function Install_Application(CodeNum:Byte; EntrySeg:Word; EntryOfs:Word):Boolean;
Function Remove_Application(CodeNum:Byte; EntrySeg:Word; EntryOfs:Word):Boolean;

implementation

Function Port_Status;
Begin
Regs.AH := $03;
Regs.DX := Port;
Intr($14,Regs);
Port_Status := Regs.AX;
End;

Procedure Set_Baud;                (* Speed  2 = 300   Baud   *)
                                   (*        3 = 600   Baud   *)
Begin                              (*        4 = 1200  Baud   *)
    Regs.AL := (Speed SHL 5) + 3;  (*        5 = 2400  Baud   *)
    Regs.DX := Port;               (*        6 = 4800  Baud   *)
    Intr($14,Regs);                (*        7 = 9600  Baud   *)
                                   (*        0 = 19200 Baud   *)
End;                               (*        1 = 38400 Baud   *)

Function Xmit;
Begin                            (* Send One character to the Port *)
    Regs.AH := $01;
    Regs.DX := Port;
    Regs.AL := Ord(OutChar);
    Intr($14,Regs);
    Xmit := Regs.AX;
End;

Function CommWrite;
Var
   I     : Byte;         (* Uninterruptable string to the port         *)
   Len   : Byte;         (* If you're not going to look for keystrokes *)
   Stat  : Byte;         (* piling up in the buffer.  This is a quick  *)
   Error : Byte;         (* way to send a whole string to the port     *)

Begin
    Len  := Length(OutString);
    Stat := 128;
    I    := 1;
    While (I < Len) and ((Stat AND 128) = 128) Do
        Begin
        Regs.AH := $01;
        Regs.AL := Ord(OutString[I]);
        Regs.DX := Port;
        Intr($14,Regs);
        Stat := Regs.AL;
        Inc(I);
        End;
CommWrite := Port_Status(Port);
End;

Function CommRead;                      (* Read one character waiting at *)
Begin                                   (* the comm port                 *)
Regs.AH := $02;
Regs.DX := Port;
Intr($14,Regs);
CommRead := Chr(Regs.AL);
End;

Function Init_Fossil;                      (* Initialize the fossil driver *)
                                           (* Raise DTR and prepare out/in *)
                                           (* buffers for communications   *)
Begin
Regs.AH := $04;
Regs.DX := Port;
If BreakAddr > 0 Then
   Begin
   Regs.BX := $4F50;
   Regs.CX := BreakAddr;
   End;
Intr($14,Regs);
MaxFunctionNum := Regs.BL;
RevDoc := Regs.BH;
Init_Fossil := Regs.AX;
End;

Procedure DeInit_Fossil;                       (* Tell Fossil that comm *)
Begin                                          (* Operations are ended  *)
Regs.AH := $05;
Regs.DX := Port;
Intr($14,Regs);
End;

Procedure ModemDTR;               (* RAISE/Lower Modem DTR   *)
Begin                             (* DTRUp = True  DTR is UP *)
Regs.AH := $06;
Regs.DX := Port;
If DTRUp Then Regs.AL := 1
         Else Regs.AL := 0;
Intr($14,Regs);
End;

Procedure Get_Timer_Data;         (* Return Timing Info *)
Begin
Regs.AH := $07;
Intr($14,Regs);
InterruptNum := Regs.AL;
TicksPerSec := Regs.AH;
MillisecsPer := Regs.DX;
End;

Procedure Flush_Output_Buffer;      (* Send any remaining Data *)
Begin
Regs.AH := $08;
Regs.DX := Port;
Intr($14,Regs);
End;

Procedure Purge_Output_Buffer;      (* Discard Data In Buffer *)
Begin
Regs.AH := $09;
Regs.DX := Port;
Intr($14,Regs);
End;

Procedure Purge_Input_Buffer;
Begin                                (* Discard all pending Input *)
Regs.AH := $0A;
Regs.DX := Port;
Intr($14,Regs);
End;

Function Xmit_Nowait;
Begin                                      (* Send character Unbuffered to  *)
Regs.AH := $0B;                            (* port.  Returns true if op was *)
Regs.DX := Port;                           (* successful (there was room in *)
Regs.AL := Ord(OutChar);                   (* the output buffer)            *)
Intr($14,Regs);
If Regs.AX = 1 Then Xmit_NoWait := True
               Else Xmit_NoWait := False;
End;

Function Read_Ahead;                    (* See what character is waiting *)
Begin                                   (* in the buffer without reading *)
Regs.AH := $0C;                         (* it out.  * PEEK *             *)
Regs.DX := Port;
Intr($14,Regs);
Read_Ahead := Chr(Regs.AX);
End;

Function KeyRead_Nowait;                 (* Does not wait for keypressed *)
Begin                                    (* Returns $FFFF if no key is   *)
Regs.AH := $0D;                          (* waiting.  Acts as "standard" *)
Intr($14,Regs);                          (* keyscan-- ScanCode in high   *)
Keyread_Nowait := Regs.AX;               (* order byte -- character in   *)
End;                                     (* low byte                     *)

Function Keyread;                        (* As above but waits for key *)
Begin
Regs.AH := $0E;
Intr($14,Regs);
KeyRead := Regs.AX;
End;

Procedure Flow_Control;
Begin                                  (* Enable/Disable Flow Control      *)
Regs.AH := $0F;                        (* ControlMask Values               *)
Regs.DX := Port;                       (* 0 = Disable                      *)
Regs.AL := (ControlMask AND 15) + $F0; (* Bit 0 Set = Enable XON/XOFF Recv *)
Intr($14,Regs);                        (* Bit 1 Set = CTS/RTS              *)
End;                                   (* Bit 2  is reserved for DSR/DTR   *)
                                       (* Bit 3 Set = Enable XON/XOFF Send *)

Function Abort_Control;
Begin                                  (* Not Well documented.             *)
Regs.AH := $10;                        (* Flags = 1 Toggle ^C ^K chek      *)
Regs.DX := Port;                       (* Flags = 2 Toggle Transmit ON/OFF *)
Regs.AL := Flags;                      (* Huh?  I guess ON/OFF is stoping  *)
Intr($14,Regs);                        (* data flow.  The present flag val *)
Abort_Control := Regs.AX;              (* is stored and returned on the    *)
End;                                   (* next call to this function       *)

Procedure Set_CursorXY;                (* Set Cursor Location               *)
Begin                                  (* X,Y is 0 relative  X=Col Y=Row    *)
Regs.AH := $11;                        (* I'm not sure if it just sets the  *)
Regs.DH := Y;                          (* cursor on the screen or produces  *)
Regs.DL := X;                          (* ANSI codes to do it on the remote *)
Intr($14,Regs);                        (* I assume since there is no port   *)
End;                                   (* that it is just the local term    *)

Procedure Get_CursorLoc;               (* Zero Relative as above            *)
Begin
Regs.AH := $12;
Intr($14,Regs);
Y:= Regs.DH;
X:= Regs.DL;
End;

Procedure ANSI_Write;                  (* Character to Screen Routed thru    *)
Begin                                  (* ANSI.SYS                           *)
Regs.AH := $13;
Regs.AL := Ord(OutChar);
Intr($14,Regs);
End;

Procedure Watchdog;
Begin                                  (* CarrierWatch = True Reboot on     *)
Regs.AH := $14;                        (* Carrier Loss.                     *)
Regs.DX := Port;
If CarrierWatch Then Regs.AL := 1
                Else Regs.AL := 0;
Intr($14,Regs);
End;

Procedure BIOS_Write;                  (* BIOS write to the screen         *)
Begin
Regs.AH := $15;
Regs.AL := Ord(OutChar);
Intr($14,Regs);
End;

Function TimerChain;                    (* Add/Delete function from timer  *)
                                        (* Chain.  Creates or deletes from *)
                                        (* dynamic list of function addr's *)
Begin                                   (* to be exec'd during timer proc  *)
Regs.AH := $16;
Regs.ES := FunctionSeg;
Regs.DX := FunctionOfs;
If Add Then Regs.AL := 1
       Else Regs.AL := 0;
Intr($14,Regs);
If Regs.AX = $FFFF Then TimerChain := False
                   Else TimerChain := True;
End;

Procedure System_Reboot;                   (* Reboot System,               *)
Begin                                      (* ColdBoot = True = Hard Reset *)
Regs.AH := $17;                            (* Coldboot = False = BootStrap *)
If Coldboot Then Regs.AL := 0
            Else Regs.AL := 1;
Intr($14,regs);
End;

Function ReadBlock;                   (* Reads Communications Buffer       *)
                                      (* Into the Untyped Array Buffer     *)
                                      (* Maxbytes is the size of the array *)
                                      (* Returns the number of Bytes       *)
                                      (* Actually Sent                     *)
Begin
Regs.AH := $18;
Regs.DX := Port;
Regs.CX := MaxBytes;
Regs.ES := OFS(Buffer);
Regs.DI := Seg(Buffer);
Intr($14,Regs);
ReadBlock := Regs.AX;
End;

Function WriteBlock;                  (* Writes To Communications buffer   *)
                                      (* From the Untyped Array Buffer.    *)
                                      (* Maxbytes is the size of the array *)
Var                                   (* Returns the number of Bytes       *)
   BufferAddr : Byte Absolute Buffer; (* Actually Sent                     *)

Begin
Regs.AH := $19;
Regs.DX := Port;
Regs.CX := MaxBytes;
Regs.ES := OFS(BufferAddr);
Regs.DI := Seg(BufferAddr);
Intr($14,Regs);
WriteBlock := Regs.AX;
End;

Procedure SendBreak;                             (* Send Break to Port til *)
Begin                                            (* Called With SendON = F *)
Regs.AH := $1A;
Regs.DX := Port;
If SendOn Then Regs.AL := 1
          Else Regs.AL := 0;
Intr($14,Regs);
End;

Procedure Driver_Info;
Var
   Temp     : String[80];            (* Return Driver Information in record *)
   Segment  : Word;                  (* Structure Type of DriverInfo        *)
   OffSet   : Word;
   InputChr : Char;

Begin
Regs.AH := $1B;
Regs.DX := Port;
Regs.ES := Seg(FossilInfo);
Regs.DI := Ofs(FossilInfo);
Regs.CX := SizeOf(FossilInfo);
Intr($14,Regs);
Segment := FossilInfo.IdPtr[2];
OffSet  := FossilInfo.IdPtr[1];
Temp := '';
InputChr := ' ';
While Ord(InputChr) <> 0 Do
    Begin
    InputChr := Chr(Mem[Segment:OffSet]);
    Inc(OffSet);
    Temp := Temp + InputChr;
    End;
FossilInfo.DriverName := Temp;
End;

Function Install_Application;
Begin
Regs.AH := $7E;
Regs.AL := CodeNum;
Regs.DX := EntryOfs;
Regs.DS := EntrySeg;
Intr($14,Regs);
If (Regs.AX = $1954) and (Regs.BH = 1) Then Install_Application := True
                                       Else Install_Application := False;
End;

Function Remove_Application;
Begin
Regs.AH := $7F;
Regs.AL := Codenum;
Regs.DX := EntryOfs;
Regs.DS := EntrySeg;
Intr($14,Regs);
If (Regs.AX = $1954) and (Regs.BH = 1) Then Remove_Application := True
                                       Else Remove_Application := False;
End;
End.

[Back to COMM SWAG index]  [Back to Main SWAG index]  [Original]