[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]