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}