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

UNIT PKTDRVR;
{
ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
º Filename       : PKTDRVR.PAS   ³  Program / Unit : [U]               º
º Description    : Turbo Pascal  ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ
º                  Object to interface with Crynrware packet drivers.  º
º                                                                      º
ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ
º Compiler       : Turbo Pascal 7.0                                    º
º OS-Version     : MS-DOS 6.0                                          º
º Last edit      : 08-Oct-93                                           º
º Version        : 1.0                                                 º
ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ
º Author         : Oliver Rehmann                                      º
º Copyright      : (C) 1993 Oliver Rehmann                             º
º                                                                      º
º Released to public domain.                                           º
º The author can not be held responsible for any damages resulting     º
º from the use of this software.                                       º
ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ
}

INTERFACE

USES
  DOS,OBJECTS;

CONST
  { Packet driver interface classes }
  CL_NONE           = 0;
  CL_ETHERNET     = 1;
  CL_PRONET_10    = 2;
  CL_IEEE8025       = 3;
  CL_OMNINET        = 4;
  CL_APPLETALK    = 5;
  CL_SERIAL_LINE    = 6;
  CL_STARLAN        = 7;
  CL_ARCNET       = 8;
  CL_AX25             = 9;
  CL_KISS             = 10;
  CL_IEEE8023       = 11;
  CL_FDDI         = 12;
  CL_INTERNET_X25 = 13;
  CL_LANSTAR        = 14;
  CL_SLFP         = 15;
  CL_NETROM       = 16;
  NCLASS              = 17;

  { Packet driver interface types (not a complete list) }
  TC500             = 1;
  PC2000              = 10;
  WD8003              = 14;
  PC8250              = 15;
  ANYTYPE             = $ffff;

  { Packet driver function call numbers. From Appendix B. }
  DRIVER_INFO         = 1;
  ACCESS_TYPE         = 2;
  RELEASE_TYPE      = 3;
  SEND_PKT          = 4;
  TERMINATE         = 5;
  GET_ADDRESS         = 6;
  RESET_INTERFACE   = 7;
  GET_PARAMETERS    = 10;
  AS_SEND_PKT         = 11;
  SET_RCV_MODE      = 20;
  GET_RCV_MODE      = 21;
  SET_MULTICAST_LIST    = 22;
  GET_MULTICAST_LIST    = 23;
  GET_STATISTICS          = 24;
  SET_ADDRESS             = 25;

  { Packet driver error return codes. From Appendix C. }
  NO_ERROR        = 0;
  BAD_HANDLE        = 1;    { invalid handle number }
  NO_CLASS        = 2;  { no interfaces of specified class found }
  NO_TYPE             = 3;  { no interfaces of specified type found }
  NO_NUMBER       = 4;  { no interfaces of specified number found }
  BAD_TYPE        = 5;  { bad packet type specified }
  NO_MULTICAST    = 6;  { this interface does not support multicast }
  CANT_TERMINATE    = 7;    { this packet driver cannot terminate }
  BAD_MODE        = 8;  { an invalid receiver mode was specified }
  NO_SPACE        = 9;  { operation failed because of insufficient space }
  TYPE_INUSE        = 10;   { the type had previously been accessed, and not
released } BAD_COMMAND       = 11;   { the command was out of range, or not 
implemented } CANT_SEND       = 12; { the packet couldn't be sent (usually 
hardware error) } CANT_SET        = 13; { hardware address couldn't be changed
(> 1 handle open) } BAD_ADDRESS       = 14;   { hardware address has bad
length or format } CANT_RESET        = 15;   { couldn't reset interface (> 1
handle open) }

  CARRY_FLAG        = 1;

CONST
  Pkt_Sig  : String[08] = 'PKT DRVR';
  ParamLen : Byte       = 14;

TYPE
  TPKTSTATUS  = (NO_PKTDRVR,INITIALIZED,NOT_INITIALIZED);
  TACCESSTYPE = RECORD
      if_class      : Byte;    { Interface class  }
        if_type       : Word;    { Interface Type   }
        if_number     : Byte;    { Interface number }
        type_         : Pointer;
        typelen       : Word;    { length of type_, set to 0 if
                                   you want to receive all pkts }
        receiver      : Pointer; { receive handler }
    END;

  TPKTPARAMS   = RECORD
      major_rev     : Byte; { Major revision ID of packet specs }
        minor_rev     : Byte; { Minor revision ID of packet specs }
        length        : Byte; { Length of structure in Bytes      }
        addr_len      : Byte; { Length of a MAC address           }
        mtu           : Word; { MTU, including MAC headers        }
        multicast_aval: Word; { buffer size for multicast addr.   }
        rcv_bufs      : Word; { (# of back-to-back MTU rcvs) - 1  }
        xmt_bufs      : Word; { (# of successive xmits) - 1       }
        int_num       : Word; { Interrupt # to hook for post-EOI
                                      processing, 0 == none }
  END;

  TDRVRINFO    = RECORD
      Version       : Word; { Packet driver version   }
        Class         : Byte; { Driver class  }
        Type_         : Word; { Driver type   }
        Number        : Byte; { Driver number }
        pName         : Pointer;
        Functionality : Byte; { How good is this driver }
    END;

  TSTATISTICS = RECORD
      packets_in    : LongInt;
        packets_out   : LongInt;
        bytes_in      : LongInt;
        bytes_out     : LongInt;
        errors_in     : LongInt;
        errors_out    : LongInt;
        packets_lost  : LongInt;
    END;

  TPKTDRVR = OBJECT(TOBJECT)
    private
        pktInt         : Integer;
        pktHandle      : Integer;
        pktRecvHandler : Pointer;
        pktStatus      : TPKTSTATUS;
        pktError       : Byte;
        pktRegs        : Registers;

        pktAccessInfo  : TACCESSTYPE;

        PROCEDURE   TestForPktDriver;

    public
        CONSTRUCTOR Init(IntNo : Integer);
        DESTRUCTOR  Done; VIRTUAL;

        PROCEDURE   ScanForPktDriver;

        FUNCTION    GetStatus                          : TPKTSTATUS;
        FUNCTION    GetError                           : Byte;
        FUNCTION    GetHandle                          : Word;

        PROCEDURE   GetAccessType   (VAR pktAccessType : TACCESSTYPE);
        PROCEDURE   DriverInfo      (VAR pktInfo       : TDRVRINFO  );

        PROCEDURE   AccessType      (VAR pktAccessType : TACCESSTYPE);
        PROCEDURE   ReleaseType;
        PROCEDURE   TerminateDriver;

        PROCEDURE   GetAddress      (Buffer : Pointer;BufLen : Word; VAR
BufCopied : Word); PROCEDURE ResetInterface; PROCEDURE   GetParameters   (VAR
pktParams : TPKTPARAMS);

        PROCEDURE   SendPkt         (Buffer : Pointer;BufLen : Word );
        PROCEDURE   As_SendPkt      (Buffer : Pointer;BufLen : Word;Upcall :
Pointer     );

        PROCEDURE   SetRCVmode      (Mode   : Word);
        FUNCTION    GetRCVmode              : Word;

        PROCEDURE   SetMulticastList(VAR mcList : Pointer; VAR mcLen : Word);
        PROCEDURE   GetMulticastList(VAR mcList : Pointer; VAR mcLen : Word);

        PROCEDURE   GetStatistics   (VAR pktStatistics : TSTATISTICS       );
        PROCEDURE   SetAddress      (Address : Pointer; VAR AddrLen  : Word);
  END;


IMPLEMENTATION
CONSTRUCTOR TPKTDRVR.Init(IntNo : Integer);
BEGIN
  Inherited Init;

  pktInt    := IntNo;
  pktStatus := NOT_INITIALIZED;
  FillChar(pktAccessInfo,SizeOf(pktAccessInfo),#00);

  TestForPktDriver;
END;


DESTRUCTOR TPKTDRVR.Done;
BEGIN
  { Release allocated handle }
  IF (pktStatus = INITIALIZED) THEN
  BEGIN
    ReleaseType;
  END;

  Inherited Done;
END;


FUNCTION TPKTDRVR.GetStatus : TPKTSTATUS;
BEGIN
  GetStatus := pktStatus;
END;

PROCEDURE TPKTDRVR.GetAccessType(VAR pktAccessType : TACCESSTYPE);
BEGIN
  pktAccessType := pktAccessInfo;
END;

PROCEDURE TPKTDRVR.TestForPktDriver;
(* Tests if the assigned interrupt points to a valid packet driver. *)
VAR tPointer  : Pointer;
    Signature : String[08];
    I         : Integer;
BEGIN
  Signature := '';
  GetIntVec(pktInt,tPointer);
  FOR I := 3 TO 10 DO
  BEGIN
    Signature := Signature + Chr(Mem[Seg(tPointer^):Ofs(tPointer^)+I]);
  END;
  IF (POS(Pkt_Sig,Signature) = 0) THEN
    pktStatus := NO_PKTDRVR
  ELSE
    pktStatus := INITIALIZED;
END;

PROCEDURE TPKTDRVR.ScanForPktDriver;
(* Scans interrupts ($60-$7F) for a packet driver. *)
(* Stops if it has found a valid driver.           *)
VAR I : Integer;
BEGIN
  I := $60; { Lower range of possible pktdrvr interrupt }
  REPEAT
    pktInt := I;
    TestForPktDriver;
    Inc(I);
  UNTIL (I = $80) OR (pktStatus = INITIALIZED);
END;

PROCEDURE TPKTDRVR.DriverInfo(VAR pktInfo : TDRVRINFO);
BEGIN
  WITH pktRegs DO
  BEGIN
    AH := DRIVER_INFO;
    AL := $FF;
    BX := pktHandle;
    Intr(pktInt,pktRegs); { Call Packet Driver }
    IF (pktRegs.Flags AND Carry_Flag) = Carry_Flag THEN
      pktError := DH
    ELSE
    BEGIN
      pktError := 0;
      IF (pktError = NO_ERROR) THEN
      BEGIN
    pktInfo.Version       := BX;
    pktInfo.Class         := CH;
    pktInfo.Type_         := DX;
    pktInfo.Number        := CL;
    pktInfo.pName         := Ptr(DS,SI);
    pktInfo.Functionality := AL;
      END;
    END;
  END;
END;

PROCEDURE TPKTDRVR.AccessType(VAR pktAccessType : TACCESSTYPE);
(* Accesses the packet driver.  *)
BEGIN
  WITH pktRegs DO
  BEGIN
    AH := ACCESS_TYPE;
    AL := pktAccessType.if_class;
    BX := pktAccessType.if_type;
    CX := pktAccessType.typelen;
    DL := pktAccessType.if_number;
    DS := Seg(pktAccessType.type_^);
    SI := Ofs(pktAccessType.type_^);
    ES := Seg(pktAccessType.receiver^);
    DI := Ofs(pktAccessType.receiver^);
    Intr(pktInt,pktRegs);
    IF (Flags AND Carry_Flag) = Carry_Flag THEN
      pktError      := DH
    ELSE
    BEGIN
      pktError      := 0;
      pktHandle     := AX;
      pktAccessInfo := pktAccessType;
    END;
  END;
END;

PROCEDURE TPKTDRVR.ReleaseType;
(* Releases a specific type handle *)
BEGIN
  WITH pktRegs DO
  BEGIN
    AH := RELEASE_TYPE;
    BX := pktHandle;
    Intr(pktInt,pktRegs);
    IF (Flags AND Carry_Flag) = Carry_Flag THEN
      pktError := DH
    ELSE
      pktError := 0;
  END;
END;

PROCEDURE TPKTDRVR.SendPkt(Buffer : Pointer;BufLen : Word);
BEGIN
  WITH pktRegs DO
  BEGIN
    AH := SEND_PKT;
    CX := BufLen;
    DS := Seg(Buffer^);
    ES := DS;
    SI := Ofs(Buffer^);
    Intr(pktInt,pktRegs);
    IF (Flags AND Carry_Flag) = Carry_Flag THEN
      pktError := DH
    ELSE
      pktError := 0;
  END;
END;

PROCEDURE   TPKTDRVR.TerminateDriver;
(* Terminates the Driver associated with pktHandle *)
BEGIN
  WITH pktRegs DO
  BEGIN
    AH := TERMINATE;
    BX := pktHandle;
    Intr(pktInt,pktRegs);
    IF (Flags AND Carry_Flag) = Carry_Flag THEN
      pktError := DH
    ELSE
      pktError := 0;
  END;
END;

PROCEDURE TPKTDRVR.GetAddress (Buffer : Pointer;BufLen : Word; VAR BufCopied :
Word);
BEGIN
  WITH pktRegs DO
  BEGIN
    AH := GET_ADDRESS;
    BX := pktHandle;
    CX := BufLen;
    ES := Seg(Buffer^);
    DI := Ofs(Buffer^);
    Intr(pktInt,pktRegs);
    IF (Flags AND Carry_Flag) = Carry_Flag THEN
      pktError  := DH
    ELSE
    BEGIN
      pktError  := 0;
      BufCopied := CX;
    END;
  END;
END;

PROCEDURE TPKTDRVR.ResetInterface;
BEGIN
  WITH pktRegs DO
  BEGIN
    AH := RESET_INTERFACE;
    BX := pktHandle;
    Intr(pktInt,pktRegs);
    IF (Flags AND Carry_Flag) = Carry_Flag THEN
      pktError := DH
    ELSE
      pktError := 0;
  END;
END;

PROCEDURE TPKTDRVR.GetParameters(VAR pktParams : TPKTPARAMS);
(* Description   : ³ Gets specific parameters from the driver. *)
(* Not all drivers support this function.                      *)
VAR b : Byte;
BEGIN
  WITH pktRegs DO
  BEGIN
    AH := GET_PARAMETERS;
    Intr(pktInt,pktRegs);
    IF (Flags AND Carry_Flag) = Carry_Flag THEN
      pktError := DH
    ELSE
    BEGIN
      pktError := 0;
      FOR b := 0 TO ParamLen-1 DO  { Copy contents of structure }
    Mem[Seg(pktParams):Ofs(PktParams)+b] := Mem[ES:DI+b];
    END;
  END;
END;


PROCEDURE TPKTDRVR.As_SendPkt(Buffer : Pointer;BufLen : Word;Upcall :
Pointer);
(* Sends a data packet by accessing the packet driver.  *)
(* Upcall is called when order was placed.              *)
BEGIN
  WITH pktRegs DO
  BEGIN
    AH := AS_SEND_PKT;
    CX := BufLen;
    DS := Seg(Buffer);
    SI := Ofs(Buffer);
    ES := Seg(Upcall^);
    DI := Ofs(Upcall^);
    Intr(pktInt,pktRegs);
    IF (Flags AND Carry_Flag) = Carry_Flag THEN
      pktError := DH
    ELSE
      pktError := 0;
  END;
END;

PROCEDURE TPKTDRVR.SetRCVmode(Mode : Word);

BEGIN
  WITH pktRegs DO
  BEGIN
    AH := SET_RCV_MODE;
    BX := pktHandle;
    CX := Mode;
    Intr(pktInt,pktRegs);
    IF (Flags AND Carry_Flag) = Carry_Flag THEN
      pktError := DH
    ELSE
      pktError := 0;
  END;
END;

FUNCTION TPKTDRVR.GetRCVmode : Word;
BEGIN
  WITH pktRegs DO
  BEGIN
    AH := GET_RCV_MODE;
    BX := pktHandle;
    Intr(pktInt,pktRegs);
    IF (Flags AND Carry_Flag) = Carry_Flag THEN
      pktError   := DH
    ELSE
    BEGIN
      pktError   := 0;
      GetRCVmode := AX;
    END;
  END;
END;

PROCEDURE TPKTDRVR.SetMulticastList(VAR mcList : Pointer; VAR mcLen : Word);
BEGIN
  WITH pktRegs DO
  BEGIN
    AH := SET_MULTICAST_LIST;
    CX := mcLen;
    ES := Seg(mcList^);
    DI := Ofs(mcList^);
    Intr(pktInt,pktRegs);
    IF (Flags AND Carry_Flag) = Carry_Flag THEN
      pktError := DH
    ELSE
      pktError := 0;
  END;
END;

PROCEDURE TPKTDRVR.GetMulticastList(VAR mcList : Pointer; VAR mcLen : Word);
BEGIN
  WITH pktRegs DO
  BEGIN
    AH := GET_MULTICAST_LIST;
    Intr(pktInt,pktRegs);
    IF (Flags AND Carry_Flag) = Carry_Flag THEN
      pktError := DH
    ELSE
    BEGIN
      pktError := 0;
      mcList   := Ptr(ES,DI);
      mcLen    := CX;
    END;
  END;
END;

PROCEDURE TPKTDRVR.GetStatistics(VAR pktStatistics : TSTATISTICS);
VAR b : Byte;
BEGIN
  WITH pktRegs DO
  BEGIN
    AH := GET_STATISTICS;
    Intr(pktInt,pktRegs);
    IF (Flags AND Carry_Flag) = Carry_Flag THEN
      pktError := DH
    ELSE
    BEGIN
      pktError := 0;
      FOR b := 0 TO SizeOf(TSTATISTICS)-1 DO  { Copy contents of structure }
    Mem[Seg(pktStatistics):Ofs(pktStatistics)+b] := Mem[DS:SI+b];
    END;
  END;
END;

PROCEDURE TPKTDRVR.SetAddress(Address : Pointer; VAR AddrLen : Word);
BEGIN
  WITH pktRegs DO
  BEGIN
    AH := SET_ADDRESS;
    CX := AddrLen;
    ES := Seg(Address^);
    DI := Ofs(Address^);
    Intr(pktInt,pktRegs);
    IF (Flags AND Carry_Flag) = Carry_Flag THEN
      pktError := DH
    ELSE
    BEGIN
      pktError := 0;
      AddrLen  := CX;
    END;
  END;
END;

FUNCTION TPKTDRVR.GetError  : Byte;
BEGIN
  GetError := pktError;
END;

FUNCTION TPKTDRVR.GetHandle : Word;
BEGIN
  GetHandle := pktHandle;
END;

BEGIN
END.
{end}

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