[Back to NETWORK SWAG index] [Back to Main SWAG index] [Original]
UNIT IPX;
(****************************************************************************)
(* *)
(* PROJEKT : PASCAL Treiber fuer Novell-NetWare *)
(* MODULE : IPX.PAS *)
(* VERSION : 1.10C *)
(* COMPILER : Turbo Pascal V 6.0 *)
(* DATUM : 13.06.91 *)
(* AUTOR : R. Gilomen *)
(* GEPRUEFT : R. Gilomen *)
(* *)
(*--------------------------------------------------------------------------*)
(* *)
(* BESCHREIBUNG : Bibliothek mit den IPX-Grunfunktionen. Dieses Modul *)
(* wurde mit IPX Version 2.12 getestet. *)
(* *)
(*--------------------------------------------------------------------------*)
(* *)
(* MODIFIKATIONEN : *)
(* *)
(* Version 1.00A 20.02.91 R. Gilomen Initial Version *)
(* Version 1.10A 28.02.91 R. Gilomen Neue Funktionen *)
(* IPX_To_Addr *)
(* IPX_From_Addr *)
(* IPX_Internetwork_Address *)
(* Version 1.10B 07.03.91 R. Gilomen Fehler in Funktion IPX_Done *)
(* behoben. Bei SEND wurde *)
(* Source.Socket veraendert. *)
(* Version 1.10C 13.06.91 R. Gilomen Defaultwert fuer Parameter *)
(* STAY_OPEN auf $FF gesetzt. *)
(* *)
(****************************************************************************)
(*//////////////////////////////////////////////////////////////////////////*)
INTERFACE
(*//////////////////////////////////////////////////////////////////////////*)
(*==========================================================================*)
(* DEKLARATIONEN / DEFINITIONEN *)
(*==========================================================================*)
CONST
(* Allgemeine Deklarationen *)
MAX_SOCKETS = 20; (* Maximale Anzahl konfigurierte *)
(* Kommunikationssockel. *)
MAX_DATA_SIZE = 546; (* Maximale Datenlaenge *)
NET_LENGTH = 4; (* Laenge Netzwerkadresse *)
NODE_LENGTH = 6; (* Laenge Knotenadresse *)
(* Code Deklarationen *)
SEND = $10;
RECEIVE = $20;
(* Deklaration der Rueckgabewerte *)
SUCCESS = $00;
NOT_ENDED = $10;
PARAMETER_ERROR = $20;
NO_DESTINATION = $21;
DEVICE_SW_ERROR = $30;
SOCKET_TABLE_FULL = $31;
PACKET_BAD = $32;
PACKET_UNDELIVERIABLE = $33;
PACKET_OVERFLOW = $34;
DEVICE_HW_ERROR = $40;
TYPE S4Byte = ARRAY [1..4] OF BYTE; (* Datentyp fuer Network *)
S6Byte = ARRAY [1..6] OF BYTE; (* Datentyp fuer Node *)
(* Datentyp fuer Daten *)
Data_Packet = ARRAY [1..MAX_DATA_SIZE] OF CHAR;
SData = RECORD (* Daten und Laenge *)
Data : Data_Packet;
Length : WORD;
END;
Network_Address = RECORD (* Datentyp fuer NW-Adr. *)
Network : S4Byte;
Node : S6Byte;
Socket : WORD;
END;
(*==========================================================================*)
(* PROZEDUREN / FUNKTIONEN *)
(*==========================================================================*)
FUNCTION IPX_Setup : BYTE;
(*--------------------------------------------------------------------------*)
(* *)
(* BESCHREIBUNG : Die Routine initialisiert die IPX-Software und deren *)
(* Funktion. *)
(* *)
(* *)
(* PARAMETER : IN : - *)
(* *)
(* OUT: Rueckgabewert = Fehlercode *)
(* *)
(*--------------------------------------------------------------------------*)
FUNCTION IPX_Open_Socket ( VAR Socket : WORD ) : BYTE;
(*--------------------------------------------------------------------------*)
(* *)
(* BESCHREIBUNG : Die Routine eroeffnet einen Kommunikationssockel. *)
(* *)
(* *)
(* PARAMETER : IN : Socket = Nummer des Sockels, der eroeffnet *)
(* werden soll. *)
(* *)
(* OUT: Socket = Nummer des Sockels, der effektiv *)
(* geoeffnet wurde. *)
(* *)
(* Rueckgabewert = Fehlercode *)
(* *)
(*--------------------------------------------------------------------------*)
FUNCTION IPX_Close_Socket ( Socket : WORD ) : BYTE;
(*--------------------------------------------------------------------------*)
(* *)
(* BESCHREIBUNG : Die Routine schliesst einen Kommunikationssockel. *)
(* *)
(* *)
(* PARAMETER : IN : Socket = Nummer des Sockels, der geschlos- *)
(* sen werden soll. *)
(* *)
(* OUT: Rueckgabewert = Fehlercode *)
(* *)
(*--------------------------------------------------------------------------*)
FUNCTION IPX_Send ( Socket : WORD;
Dest_Addr : Network_Address;
Buffer : SData
) : BYTE;
(*--------------------------------------------------------------------------*)
(* *)
(* BESCHREIBUNG : Die Routine dient zum senden von Daten an eine oder *)
(* mehrere Gegenstationen. *)
(* *)
(* *)
(* PARAMETER : IN : Socket = Sockelnummer, auf der gesendet *)
(* werden soll. *)
(* Dest_Addr = Vollstaendige Netwerkadresse der *)
(* Gegenstation(en). *)
(* Buffer = Daten die gesendet werden und *)
(* dessen Laenge. *)
(* *)
(* OUT: Rueckgabewert = Fehlercode *)
(* *)
(*--------------------------------------------------------------------------*)
FUNCTION IPX_Receive ( Socket : WORD ) : BYTE;
(*--------------------------------------------------------------------------*)
(* *)
(* BESCHREIBUNG : Die Routine dient zum Empfangen von Daten einer Gegen- *)
(* station. Die Daten koennen, wenn das Kommando beendet *)
(* ist, mit der Funktion IPX_Done vom Netzwerk abgeholt *)
(* werden. *)
(* *)
(* PARAMETER : IN : Socket = Sockelnummer, auf der empfangen *)
(* werden soll. *)
(* *)
(* OUT: Rueckgabewert = Fehlercode *)
(* *)
(*--------------------------------------------------------------------------*)
FUNCTION IPX_Done ( Socket : WORD;
Code : BYTE;
VAR Source_Addr : Network_Address;
VAR Buffer : SData
) : BYTE;
(*--------------------------------------------------------------------------*)
(* *)
(* BESCHREIBUNG : Die Funktion liefert den Status einer vorher abgesetz- *)
(* ten Routine. Zurueckgegeben wird, ob die Routine schon *)
(* beendet ist oder nicht sowie eventuelle Daten. *)
(* *)
(* *)
(* PARAMETER : IN : Socket = Sockelnummer, auf der die Funktion *)
(* ausgefuehrt werden soll. *)
(* Code = Routine, deren Status ueberprueft *)
(* werden soll. *)
(* *)
(* OUT: Source_Addr = Vollstaendige Netzwerkadresse der *)
(* Gegenstation, von der Daten einge- *)
(* troffen sind. *)
(* Buffer = Buffer, in dem eventuelle Daten *)
(* abgelegt werden koennen. *)
(* Rueckgabewert = Fehlercode *)
(* *)
(*--------------------------------------------------------------------------*)
FUNCTION IPX_Internetwork_Address ( VAR Network : S4Byte;
VAR Node : S6Byte
) : BYTE;
(*--------------------------------------------------------------------------*)
(* *)
(* BESCHREIBUNG : Die Funktion liefert die Internetzwerkadresse der *)
(* jeweiligen Station. *)
(* *)
(* *)
(* PARAMETER : OUT: Network = Netzwerkadresse *)
(* Node = Knotenadresse *)
(* Rueckgabewert = Fehlercode *)
(* *)
(*--------------------------------------------------------------------------*)
FUNCTION IPX_To_Addr ( Network : String;
Node : String;
Socket : String;
VAR Addr : Network_Address
) : BYTE;
(*--------------------------------------------------------------------------*)
(* *)
(* BESCHREIBUNG : Die Routine konvertiert die Eingabestrings in die Daten- *)
(* struktur Network_Address. *)
(* *)
(* *)
(* PARAMETER : IN : Network = Netzwerkadresse die konvertiert *)
(* werden soll. *)
(* Node = Knotenadresse die konvertiert *)
(* werden soll. *)
(* Socket = Sockelnummer die konvertiert *)
(* werden soll. *)
(* *)
(* OUT: Addr = Konvertierte vollsaendige Netz- *)
(* werkadresse. *)
(* Rueckgabewert = Fehlercode *)
(* *)
(*--------------------------------------------------------------------------*)
FUNCTION IPX_From_Addr ( Addr : Network_Address;
VAR Network : String;
VAR Node : String;
VAR Socket : String
) : BYTE;
(*--------------------------------------------------------------------------*)
(* *)
(* BESCHREIBUNG : Die Routine konvertiert die vollstaendige Netzwerk- *)
(* adresse in String's. *)
(* *)
(* *)
(* PARAMETER : IN : Addr = Vollstaendige Netzwerkadresse *)
(* *)
(* OUT: Network = Netzwerkadresse die konvertiert *)
(* wurde. *)
(* Node = Knotenadresse die konvertiert *)
(* wurde. *)
(* Socket = Sockelnummer die konvertiert *)
(* wurde. *)
(* Rueckgabewert = Fehlercode *)
(* *)
(*--------------------------------------------------------------------------*)
(*//////////////////////////////////////////////////////////////////////////*)
IMPLEMENTATION
(*//////////////////////////////////////////////////////////////////////////*)
(*==========================================================================*)
(* UNITS IMPORT *)
(*==========================================================================*)
USES Dos;
(*==========================================================================*)
(* DEKLARATIONEN / DEFINITIONEN *)
(*==========================================================================*)
CONST
(* Allgemeine Definitionen *)
HEADER = 30; (* Groesse IPX-Header *)
PACKET_SIZE = 576; (* IPX-Paket groesse *)
(* Definitionen der IPX-Funktionen *)
IPX_TST = $7A00; (* Vorbereiten fuer IPX Test *)
MUX_INTR = $2F; (* Multiplex Interrupt *)
OPEN_SOCKET = $0000; (* Oeffnet einen Sockel *)
CLOSE_SOCKET = $0001; (* Schliesst einen Sockel *)
GET_TARGET = $0002; (* Pruefe Gegenstation *)
DO_SEND = $0003; (* Sendet ein Paket *)
DO_RECEIVE = $0004; (* Empfaengt Pakete *)
GET_ADDR = $0009; (* Bestimmt Internetzwerkadresse *)
(* Definitionen der IPX-Parameter *)
STAY_OPEN = $FF; (* $00 : Sockel bleibt geoeffnet, *)
(* bis er explizit geschlossen wird *)
(* oder das Programm terminiert. *)
(* $FF : Sockel bleibt geoeffnet, *)
(* bis er explizit geschlossen wird. *)
(* Wird benoetigt fuer TSR-Programme.*)
(* Definitionen der IPX-Rueckgabewerte *)
IPX_LOADED = $FF; (* IPX ist geladen *)
OPENED = $00; (* Sockel erfolgreich geoeffnet *)
ALREADY_OPEN = $FF; (* Sockel ist bereits goeffnet *)
TABLE_FULL = $FE; (* Sockel Tabelle ist voll *)
EXIST = $00; (* Weg zu Gegenstation existiert *)
NO_SOCKET = $FF; (* Sockel existiert nicht *)
SEND_OK = $00; (* Senden war erfolgreich *)
SOCKET_ERROR = $FC; (* Sockel existiert nicht mehr *)
SIZE_ERROR = $FD; (* Paketgroesse nicht korrekt *)
UNDELIV = $FE; (* Paket nicht ausgeliefert *)
OVERFLOW = $FD; (* Buffer zu klein *)
HW_ERROR = $FF; (* Hardware defekt *)
REC_OK = $00; (* Paket erfolgreich empfangen *)
(* Definition der ECB-Parameter *)
FINISHED = $00; (* Routine beendet *)
FRAG_COUNT = 1; (* Anzahl Fragmente *)
UNKNOWN = 0; (* Unbekannter Paket Typ *)
(* Deklarationen *)
TYPE S12Byte = ARRAY [1..12] OF BYTE; (* Interner Datentyp *)
IPX_Packet = RECORD (* IPX-Paket Struktur *)
CheckSum : WORD;
Length : WORD;
TransportControl : BYTE;
PacketType : BYTE;
Destination : Network_Address;
Source : Network_Address;
IPX_Data : Data_Packet;
END;
ECB_Fragment = RECORD (* Fragment der ECB Struktur *)
Address : ^IPX_Packet;
Size : WORD;
END;
ECB = RECORD (* ECB Datenstruktur *)
Link_Adress : S4Byte;
ESR_Address : ^BYTE;
InUseFlag : BYTE;
CompletionCode : BYTE;
SocketNumber : WORD;
IPX_Workspace : S4Byte;
DriverWorkspace : S12Byte;
ImmediateAddress : S6Byte;
FragmentCount : WORD;
FragDescr : ECB_Fragment;
END;
Int_Addr = RECORD (* Datenstruktur Internetzwerkadr. *)
Network : S4Byte;
Node : S6Byte;
END;
VAR IPX_Location : ARRAY [1..2] OF WORD; (* Adresse von IPX *)
(* Array in dem die ECB's *)
(* verwaltet werden. *)
ECB_Table : ARRAY [1..MAX_SOCKETS] OF ^ECB;
(*==========================================================================*)
(* PROZEDUREN / FUNKTIONEN *)
(*==========================================================================*)
PROCEDURE IPX_Call ( VAR Regs : Registers );
(*--------------------------------------------------------------------------*)
(* *)
(* BESCHREIBUNG : Diese Prozedur setzt die in Regs spezifizierten *)
(* Register des Prozessors. Anschliessend wird ein IPX- *)
(* Call ausgefuehrt und die Register wieder ausgelesen. *)
(* Es werden nicht alle Register der Datenstruktur *)
(* Regs uebernommen! *)
(* *)
(* PARAMETER : IN : Regs = Register, die gesetzt werden *)
(* sollen. *)
(* *)
(* OUT: Regs = Register, die vom IPX gesetzt *)
(* wurden (Return values). *)
(* *)
(*--------------------------------------------------------------------------*)
VAR Temp_AX, Temp_BX, Temp_CX, Temp_DX,
Temp_ES, Temp_SI, Temp_DI : WORD;
BEGIN
Temp_AX := Regs.AX;
Temp_BX := Regs.BX;
Temp_CX := Regs.CX;
Temp_DX := Regs.DX;
Temp_SI := Regs.SI;
Temp_ES := Regs.ES;
Temp_DI := Regs.DI;
ASM
PUSH BP (* Register sichern *)
PUSH SP
PUSH SS
PUSH DS
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH ES
PUSH DI
MOV AX, Temp_AX (* Register setzen *)
MOV BX, Temp_BX
MOV CX, Temp_CX
MOV DX, Temp_DX
MOV SI, Temp_SI
MOV ES, Temp_ES
MOV DI, Temp_DI
CALL DWORD PTR IPX_Location (* IPX aufrufen *)
MOV Temp_AX, AX (* Register auslesen *)
MOV Temp_BX, BX
MOV Temp_CX, CX
MOV Temp_DX, DX
MOV Temp_SI, SI
MOV Temp_ES, ES
MOV Temp_DI, DI
POP DI
POP ES (* Gesicherte Register wieder *)
POP SI (* zuruecksetzen. *)
POP DX
POP CX
POP BX
POP AX
POP DS
POP SS
POP SP
POP BP
END;
Regs.AX := Temp_AX;
Regs.BX := Temp_BX;
Regs.CX := Temp_CX;
Regs.DX := Temp_DX;
Regs.SI := Temp_SI;
Regs.ES := Temp_ES;
Regs.DI := Temp_DI;
END;
FUNCTION IPX_Setup : BYTE;
(*--------------------------------------------------------------------------*)
(* *)
(* BESCHREIBUNG : Die Routine initialisiert die IPX-Software und deren *)
(* Funktion. *)
(* *)
(* *)
(* PARAMETER : IN : - *)
(* *)
(* OUT: Rueckgabewert = Fehlercode *)
(* *)
(*--------------------------------------------------------------------------*)
VAR i : INTEGER; (* Laufvariable *)
Temp_Reg : Registers; (* Temporaere Register fuer Int. *)
BEGIN
Temp_Reg.AX := IPX_TST; (* Test ob IPX geladen. *)
Intr (MUX_INTR,Temp_Reg);
IF (Temp_Reg.AL <> IPX_LOADED) THEN
BEGIN
IPX_Setup := DEVICE_SW_ERROR; (* IPX nicht geladen *)
EXIT;
END;
Temp_Reg.AX := Temp_Reg.ES;
IPX_Location[1] := Temp_Reg.DI; (* Adresse von IPX sichern *)
IPX_Location[2] := Temp_Reg.AX;
FOR i := 1 TO MAX_SOCKETS DO (* Array fuer ECB init. *)
ECB_Table[i] := NIL;
IPX_Setup := SUCCESS; (* Initialisierung erfolgreich *)
END;
FUNCTION IPX_Open_Socket ( VAR Socket : WORD ) : BYTE;
(*--------------------------------------------------------------------------*)
(* *)
(* BESCHREIBUNG : Die Routine eroeffnet einen Kommunikationssockel. *)
(* *)
(* *)
(* PARAMETER : IN : Socket = Nummer des Sockels, der eroeffnet *)
(* werden soll. *)
(* *)
(* OUT: Socket = Nummer des Sockels, der effektiv *)
(* geoeffnet wurde. *)
(* *)
(* Rueckgabewert = Fehlercode *)
(* *)
(*--------------------------------------------------------------------------*)
VAR i : INTEGER; (* Laufvariable *)
Index : INTEGER; (* Index auf ECB_Table *)
Temp_Reg : Registers; (* Temporaere Register fuer IPX-Call *)
BEGIN
Socket := Swap(Socket); (* In Motorola Format konvertieren *)
FOR i := 1 TO MAX_SOCKETS DO (* Pruefen, ob Sockel existiert *)
IF ECB_Table[i] <> NIL THEN
IF Socket = ECB_Table[i]^.SocketNumber THEN
BEGIN
IPX_Open_Socket := PARAMETER_ERROR;
EXIT;
END;
Index := 1;
WHILE (ECB_Table[Index] <> NIL) DO (* Pruefen, ob alle Sockel belegt *)
BEGIN (* falls es noch freie ECB hat, *)
IF Index >= MAX_SOCKETS THEN (* steht Index auf einem solchen. *)
BEGIN
IPX_Open_Socket := SOCKET_TABLE_FULL;
EXIT;
END;
Index := Index + 1;
END;
Temp_Reg.BX := OPEN_SOCKET; (* Register fuer Call vorbereiten *)
Temp_Reg.AL := STAY_OPEN;
Temp_Reg.DX := Socket;
IPX_Call (Temp_Reg);
Socket := Temp_Reg.DX; (* Register auslesen *)
IF Temp_Reg.AL <> OPENED THEN (* IPX nicht i.O. *)
BEGIN
IPX_Open_Socket := DEVICE_SW_ERROR;
EXIT;
END;
NEW (ECB_Table[Index]); (* Vollstaendiger ECB erzeugen *)
NEW (ECB_Table[Index]^.FragDescr.Address);
ECB_Table[Index]^.SocketNumber := Socket;
Socket := Swap(Socket); (* Zurueck in INTEL Format konv. *)
IPX_Open_Socket := SUCCESS;
END;
FUNCTION IPX_Close_Socket ( Socket : WORD ) : BYTE;
(*--------------------------------------------------------------------------*)
(* *)
(* BESCHREIBUNG : Die Routine schliesset einen Kommunikationssockel. *)
(* *)
(* *)
(* PARAMETER : IN : Socket = Nummer des Sockels, der geschlos- *)
(* sen werden soll. *)
(* *)
(* OUT: Rueckgabewert = Fehlercode *)
(* *)
(*--------------------------------------------------------------------------*)
VAR Index : INTEGER; (* Index auf ECB_Table *)
Temp_Reg : Registers; (* Temporaere Register fuer IPX-Call *)
BEGIN
Socket := Swap(Socket); (* In Motorola Format konvertieren *)
Index := 1; (* Sockel suchen *)
WHILE (ECB_Table[Index]^.SocketNumber <> Socket) DO
BEGIN
IF Index >= MAX_SOCKETS THEN
BEGIN
IPX_Close_Socket := PARAMETER_ERROR; (* Sockel existiert nicht *)
EXIT;
END;
Index := Index + 1;
END;
Temp_Reg.BX := CLOSE_SOCKET; (* Register fuer Call vorbereiten *)
Temp_Reg.DX := Socket;
IPX_Call (Temp_Reg);
(* Allozierter Speicher freigeben *)
DISPOSE (ECB_Table[Index]^.FragDescr.Address);
ECB_Table[Index]^.FragDescr.Address := NIL;
DISPOSE (ECB_Table[Index]);
ECB_Table[Index] := NIL;
IPX_Close_Socket := SUCCESS;
END;
FUNCTION IPX_Send ( Socket : WORD;
Dest_Addr : Network_Address;
Buffer : SData
) : BYTE;
(*--------------------------------------------------------------------------*)
(* *)
(* BESCHREIBUNG : Die Routine dient zum senden von Daten an eine oder *)
(* mehrere Gegenstation(en). *)
(* *)
(* *)
(* PARAMETER : IN : Socket = Sockelnummer, auf der gesendet *)
(* werden soll. *)
(* Dest_Addr = Vollstaendige Netwerkadresse der *)
(* Gegenstation(en). *)
(* Buffer = Daten die gesendet werden und *)
(* dessen Laenge. *)
(* *)
(* OUT: Rueckgabewert = Fehlercode *)
(* *)
(*--------------------------------------------------------------------------*)
VAR i : INTEGER; (* Laufvariable *)
Index : INTEGER; (* Index auf ECB_Table *)
Temp_Reg : Registers; (* Temporaere Register fuer IPX-Call *)
Temp_Imm_Addr : S6Byte; (* Temporaere ImmdediateAddress *)
Temp_Addr : S12Byte; (* Temporaere Internetworkadresse *)
BEGIN
Socket := Swap(Socket); (* In Motorola Format konvertieren *)
Dest_Addr.Socket := Swap(Dest_Addr.Socket);
Index := 1; (* Sockel suchen *)
WHILE (ECB_Table[Index]^.SocketNumber <> Socket) DO
BEGIN
IF Index >= MAX_SOCKETS THEN
BEGIN
IPX_Send := PARAMETER_ERROR; (* Sockel existiert nicht *)
EXIT;
END;
Index := Index + 1;
END;
IF Buffer.Length > MAX_DATA_SIZE THEN (* Laenge der Daten pruefen *)
BEGIN
IPX_Send := PARAMETER_ERROR;
EXIT;
END;
WITH Dest_Addr DO (* Pruefe ob Gegenstation erreichbar *)
BEGIN
FOR i := 1 TO NET_LENGTH DO (* Internetzwerkadresse zusammenst. *)
Temp_Addr[i] := Network[i];
FOR i := 1 TO NODE_LENGTH DO
Temp_Addr[i + NET_LENGTH] := Node[i];
Temp_Addr[11] := Lo(Socket); (* Low-Byte *)
Temp_Addr[12] := HI(Socket); (* High-Byte *)
END;
Temp_Reg.ES := Seg(Temp_Addr); (* Register fuer Call vorbereiten *)
Temp_Reg.SI := Ofs(Temp_Addr);
Temp_Reg.DI := Ofs(Temp_Imm_Addr);
Temp_Reg.BX := GET_TARGET;
IPX_Call (Temp_Reg);
ECB_Table[Index]^.ImmediateAddress := Temp_Imm_Addr;
IF Temp_Reg.AL <> EXIST THEN
BEGIN
IPX_Send := NO_DESTINATION; (* Weg nicht verfuegbar *)
EXIT;
END;
WITH ECB_Table[Index]^ DO (* ECB mit Parametern fuellen *)
BEGIN
ESR_Address := NIL;
SocketNumber := Socket;
InUseFlag := FINISHED;
FragmentCount := FRAG_COUNT;
WITH FragDescr.Address^ DO (* IPX-Header vorbereiten *)
BEGIN
PacketType := UNKNOWN;
WITH Destination DO
BEGIN
Network := Dest_Addr.Network;
Node := Dest_Addr.Node;
Socket := Dest_Addr.Socket;
END;
IPX_Data := Buffer.Data;
END;
FragDescr.Size := Buffer.Length + 30;
END;
Temp_Reg.ES := Seg(ECB_Table[Index]^); (* Register fuer Call vorbereiten *)
Temp_Reg.SI := Ofs(ECB_Table[Index]^);
Temp_Reg.BX := DO_SEND;
IPX_Call (Temp_Reg);
IPX_Send := SUCCESS;
END;
FUNCTION IPX_Receive ( Socket : WORD ) : BYTE;
(*--------------------------------------------------------------------------*)
(* *)
(* BESCHREIBUNG : Die Routine dient zum Empfangen von Daten einer Gegen- *)
(* station. Die Daten koennen, wenn das Kommando beendet *)
(* ist, mit der Funktion IPX_Done vom Netzwerk abgeholt *)
(* werden. *)
(* *)
(* PARAMETER : IN : Socket = Sockelnummer, auf der empfangen *)
(* werden soll. *)
(* *)
(* OUT: Rueckgabewert = Fehlercode *)
(* *)
(*--------------------------------------------------------------------------*)
VAR Index : INTEGER; (* Index auf ECB *)
i : INTEGER; (* Laufvariable *)
Temp_Reg : Registers; (* Temporaere Register fuer IPX-Call *)
BEGIN
Socket := Swap(Socket); (* In Motorola Format konvertieren *)
Index := 1; (* Sockel suchen *)
WHILE (ECB_Table[Index]^.SocketNumber <> Socket) DO
BEGIN
IF Index >= MAX_SOCKETS THEN
BEGIN
IPX_Receive := PARAMETER_ERROR; (* Sockel existiert nicht *)
EXIT;
END;
Index := Index + 1;
END;
WITH ECB_Table[Index]^ DO (* ECB mit Parametern fuellen *)
BEGIN
ESR_Address := NIL;
FragmentCount := FRAG_COUNT;
FragDescr.Size := PACKET_SIZE;
InUseFlag := FINISHED;
END;
Temp_Reg.ES := Seg(ECB_Table[Index]^); (* Register vorbereiten *)
Temp_Reg.SI := Ofs(ECB_Table[Index]^);
Temp_Reg.BX := DO_RECEIVE;
IPX_Call (Temp_Reg);
IF Temp_Reg.AL = NO_SOCKET THEN
BEGIN
IPX_Receive := DEVICE_SW_ERROR;
EXIT;
END;
IPX_Receive := SUCCESS;
END;
FUNCTION IPX_Done ( Socket : WORD;
Code : BYTE;
VAR Source_Addr : Network_Address;
VAR Buffer : SData
) : BYTE;
(*--------------------------------------------------------------------------*)
(* *)
(* BESCHREIBUNG : Die Funktion liefert den Status einer vorher abgesetz- *)
(* ten Routine. Zurueckgegeben wird, ob die Routine schon *)
(* beendet ist oder nicht sowie eventuelle Daten. *)
(* *)
(* *)
(* PARAMETER : IN : Socket = Sockelnummer, auf der die Funktion *)
(* ausgefuehrt werden soll. *)
(* Code = Routine, deren Status ueberprueft *)
(* werden soll. *)
(* *)
(* OUT: Source_Addr = Vollstaendige Netzwerkadresse der *)
(* Gegenstation, von der Daten einge- *)
(* troffen sind. *)
(* Buffer = Buffer, in dem eventuelle Daten *)
(* abgelegt werden koennen. *)
(* Rueckgabewert = Fehlercode *)
(* *)
(*--------------------------------------------------------------------------*)
VAR i : INTEGER; (* Laufvariable *)
Index : INTEGER; (* Index auf ECB_Table *)
Temp_Reg : Registers; (* Temporaere Register fuer IPX-Call *)
BEGIN
Socket := Swap(Socket); (* In Motorola Format konvertieren *)
Index := 1; (* Sockel suchen *)
WHILE (ECB_Table[Index]^.SocketNumber <> Socket) DO
BEGIN
IF Index >= MAX_SOCKETS THEN
BEGIN
IPX_Done := PARAMETER_ERROR; (* Sockel existiert nicht *)
EXIT;
END;
Index := Index + 1;
END;
(* Test ob Funktion beendet *)
IF ECB_Table[Index]^.InUseFlag <> FINISHED THEN
BEGIN
IPX_Done := NOT_ENDED;
EXIT;
END;
CASE Code OF
SEND :
BEGIN (* Send Completion Code auswerten *)
CASE ECB_Table[Index]^.CompletionCode OF
SEND_OK : ;
SOCKET_ERROR : BEGIN
IPX_Done := DEVICE_SW_ERROR;
EXIT;
END;
SIZE_ERROR : BEGIN
IPX_Done := PACKET_BAD;
EXIT;
END;
UNDELIV : BEGIN
IPX_Done := PACKET_UNDELIVERIABLE;
EXIT;
END;
HW_ERROR : BEGIN
IPX_Done := DEVICE_HW_ERROR;
EXIT;
END
ELSE BEGIN
IPX_Done := DEVICE_SW_ERROR;
EXIT;
END;
END;
END;
RECEIVE :
BEGIN (* Receive Completion Code auswerten *)
CASE ECB_Table[Index]^.CompletionCode OF
REC_OK : BEGIN (* Daten in Benutzerbuffer kopieren *)
WITH ECB_Table[Index]^.FragDescr DO
BEGIN
Buffer.Data := Address^.IPX_Data;
Buffer.Length := Swap(Address^.Length) - HEADER;
END;
(* Netzwerkadresse umkopieren *)
WITH ECB_Table[Index]^.FragDescr.Address^.Source DO
BEGIN
Source_Addr.Network := Network;
Source_Addr.Node := Node;
Source_Addr.Socket := Swap(Socket);
END;
END;
SOCKET_ERROR : BEGIN
IPX_Done := DEVICE_SW_ERROR;
EXIT;
END;
OVERFLOW : BEGIN
IPX_Done := PACKET_OVERFLOW;
EXIT;
END;
NO_SOCKET : BEGIN
IPX_Done := DEVICE_SW_ERROR;
EXIT;
END
ELSE BEGIN
IPX_Done := DEVICE_SW_ERROR;
EXIT;
END;
END;
END
ELSE BEGIN
IPX_Done := PARAMETER_ERROR;
EXIT;
END;
END;
IPX_Done := SUCCESS;
END;
FUNCTION IPX_Internetwork_Address ( VAR Network : S4Byte;
VAR Node : S6Byte
) : BYTE;
(*--------------------------------------------------------------------------*)
(* *)
(* BESCHREIBUNG : Die Funktion liefert die Internetzwerkadresse der *)
(* jeweiligen Station. *)
(* *)
(* *)
(* PARAMETER : OUT: Network = Netzwerkadresse *)
(* Node = Knotenadresse *)
(* Rueckgabewert = Fehlercode *)
(* *)
(*--------------------------------------------------------------------------*)
VAR Temp_Reg : Registers; (* Temporaere Register fuer IPX-Call *)
Reply_Buffer : Int_Addr; (* Temporaerer Buffer fuer Adressen *)
BEGIN
Temp_Reg.ES := Seg(Reply_Buffer); (* Register vorbereiten *)
Temp_Reg.SI := Ofs(Reply_Buffer);
Temp_Reg.BX := GET_ADDR;
IPX_Call (Temp_Reg);
Network := Reply_Buffer.Network; (* Daten umkopieren *)
Node := Reply_Buffer.Node;
IPX_Internetwork_Address := SUCCESS;
END;
FUNCTION IPX_To_Addr ( Network : String;
Node : String;
Socket : String;
VAR Addr : Network_Address
) : BYTE;
(*--------------------------------------------------------------------------*)
(* *)
(* BESCHREIBUNG : Die Routine konvertiert die Eingabestrings in die Daten- *)
(* struktur Network_Address. *)
(* *)
(* *)
(* PARAMETER : IN : Network = Netzwerkadresse die konvertiert *)
(* werden soll. *)
(* Node = Knotenadresse die konvertiert *)
(* werden soll. *)
(* Socket = Sockelnummer die konvertiert *)
(* werden soll. *)
(* *)
(* OUT: Addr = Konvertierte vollsaendige Netz- *)
(* werkadresse. *)
(* Rueckgabewert = Fehlercode *)
(* *)
(*--------------------------------------------------------------------------*)
VAR i,n,Code : INTEGER;
c : CHAR;
Temp : BYTE;
BEGIN
(* Pruefe Netzwerk und Node Laenge *)
IF (ORD(Network[0]) <> (2 * NET_LENGTH)) OR
(ORD(Node[0]) <> (2 * NODE_LENGTH)) THEN
BEGIN
IPX_To_Addr := PARAMETER_ERROR;
EXIT;
END;
(* Netzwerkadresse konvertieren *)
i := 1;
n := 1;
WHILE ( i <= (2 * NET_LENGTH)) DO
BEGIN
c := UPCASE(Network[i]);
CASE c OF
'A'..'F': Addr.Network[n] := ORD(c) - 55;
'0'..'9': Addr.Network[n] := ORD(c) - 48
ELSE BEGIN
IPX_To_Addr := PARAMETER_ERROR;
EXIT;
END;
END;
Addr.Network[n] := Addr.Network[n] SHL 4;
c := UPCASE(Network[i + 1]);
CASE c OF
'A'..'F': Temp := ORD(c) - 55;
'0'..'9': Temp := ORD(c) - 48;
ELSE BEGIN
IPX_To_Addr := PARAMETER_ERROR;
EXIT;
END;
END;
Addr.Network[n] := Addr.Network[n] + Temp;
i := i + 2;
n := n + 1;
END;
(* Node-Adresse konvertieren *)
i := 1;
n := 1;
WHILE ( i <= (2 * NODE_LENGTH)) DO
BEGIN
c := UPCASE(Node[i]);
CASE c OF
'A'..'F': Addr.Node[n] := ORD(c) - 55;
'0'..'9': Addr.Node[n] := ORD(c) - 48;
ELSE BEGIN
IPX_To_Addr := PARAMETER_ERROR;
EXIT;
END;
END;
Addr.Node[n] := Addr.Node[n] SHL 4;
c := UPCASE(Node[i + 1]);
CASE c OF
'A'..'F': Temp := ORD(c) - 55;
'0'..'9': Temp := ORD(c) - 48;
ELSE BEGIN
IPX_To_Addr := PARAMETER_ERROR;
EXIT;
END;
END;
Addr.Node[n] := Addr.Node[n] + Temp;
i := i + 2;
n := n + 1;
END;
(* Sockelnummer konvertieren *)
VAL (Socket,Addr.Socket,Code);
IF Code <> 0 THEN
BEGIN
IPX_To_Addr := PARAMETER_ERROR;
EXIT;
END;
IPX_To_Addr := SUCCESS;
END;
FUNCTION IPX_From_Addr ( Addr : Network_Address;
VAR Network : String;
VAR Node : String;
VAR Socket : String
) : BYTE;
(*--------------------------------------------------------------------------*)
(* *)
(* BESCHREIBUNG : Die Routine konvertiert die vollstaendige Netzwerk- *)
(* adresse in String's. *)
(* *)
(* *)
(* PARAMETER : IN : Addr = Vollstaendige Netzwerkadresse *)
(* *)
(* OUT: Network = Netzwerkadresse die konvertiert *)
(* wurde. *)
(* Node = Knotenadresse die konvertiert *)
(* wurde. *)
(* Socket = Sockelnummer die konvertiert *)
(* wurde. *)
(* Rueckgabewert = Fehlercode *)
(* *)
(*--------------------------------------------------------------------------*)
VAR i,n,Code : INTEGER;
c : CHAR;
TempHi,TempLo : BYTE;
BEGIN
(* Netzwerkadresse konvertieren *)
i := 1;
n := 1;
WHILE ( i <= (2 * NET_LENGTH)) DO
BEGIN
TempHi := Addr.Network[n] DIV 16; (* Hi-Nibble *)
CASE TempHi OF
10..15 : Network[i] := CHR(TempHi + 55);
0..9 : Network[i] := CHR(TempHi + 48)
ELSE BEGIN
IPX_From_Addr := PARAMETER_ERROR;
EXIT;
END;
END;
i := i + 1;
TempLo := Addr.Network[n] MOD 16; (* Lo-Nibble *)
CASE TempLo OF
10..15 : Network[i] := CHR(TempLo + 55);
0..9 : Network[i] := CHR(TempLo + 48)
ELSE BEGIN
IPX_From_Addr := PARAMETER_ERROR;
EXIT;
END;
END;
i := i + 1;
n := n + 1;
END;
Network[0] := CHR(i); (* Laenge Netzwerkadresse fuer String *)
(* Node-Adresse konvertieren *)
i := 1;
n := 1;
WHILE ( i <= (2 * NODE_LENGTH)) DO
BEGIN
TempHi := Addr.Node[n] DIV 16; (* Hi-Nibble *)
CASE TempHi OF
10..15 : Node[i] := CHR(TempHi + 55);
0..9 : Node[i] := CHR(TempHi + 48)
ELSE BEGIN
IPX_From_Addr := PARAMETER_ERROR;
EXIT;
END;
END;
i := i + 1;
TempLo := Addr.Node[n] MOD 16; (* Lo-Nibble *)
CASE TempLo OF
10..15 : Node[i] := CHR(TempLo + 55);
0..9 : Node[i] := CHR(TempLo + 48)
ELSE BEGIN
IPX_From_Addr := PARAMETER_ERROR;
EXIT;
END;
END;
i := i + 1;
n := n + 1;
END;
Node[0] := CHR(i - 1); (* Laenge Knotenadr. fuer String *)
(* Sockelnummer konvertieren *)
STR (Addr.Socket,Socket);
IPX_From_Addr := SUCCESS;
END;
END.
[Back to NETWORK SWAG index] [Back to Main SWAG index] [Original]