Driver.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Hal Murray, May 9, 1986 4:18:43 am PDT
DIRECTORY
CommBuffer USING [Encapsulation, Overhead],
IP USING [Address],
NS USING [Host, Net],
Process USING [Priority, priorityClient1, priorityClient3],
Pup USING [Host, Net];
Driver: CEDAR DEFINITIONS = {
BYTE: TYPE = [0..100H);
Encapsulation: TYPE = CommBuffer.Encapsulation;
Type: TYPE = {none, ethernet, ethernetOne, phone, imp, spare, spare1, spare2};
SendProc: TYPE = PROC [network: Network, buffer: Buffer, bytes: NAT];
RecvProc: TYPE = PROC [network: Network, buffer: Buffer, bytes: NAT] RETURNS [Buffer];
Network: TYPE = REF NetworkObject;
NetworkObject: TYPE = RECORD [
next: Network,
ip: RECORD [
host: IP.Address,
getEncapsulation: PROC [Network, IP.Address] RETURNS [Encapsulation],
send: SendProc,
return: SendProc,
recv: RecvProc,
sendTranslate: SendProc,
recvTranslate: RecvProc,
translation: REF ANY ],
ns: RECORD [
net: NS.Net,
getEncapsulation: PROC [Network, NS.Host] RETURNS [Encapsulation],
send: SendProc,
return: SendProc,
recv: RecvProc,
sendTranslate: SendProc,
recvTranslate: RecvProc,
translation: REF ANY ],
pup: RECORD [
net: Pup.Net,
host: Pup.Host,
getEncapsulation: PROC [Network, Pup.Host] RETURNS [Encapsulation],
send: SendProc,
return: SendProc,
recv: RecvProc,
sendTranslate: SendProc,
recvTranslate: RecvProc,
translation: REF ANY ],
other: RECORD [
netHostOther: REF ANY,
getEncapsulation: PROC [Network, REF ANY] RETURNS [Encapsulation],
send: SendProc,
return: SendProc,
recv: RecvProc,
sendTranslate: SendProc,
recvTranslate: RecvProc,
translation: REF ANY ],
raw: RECORD [
send: SendProc ],
error: RECORD [
recv: PROC [network: Network, buffer: Buffer, bytes: NAT] RETURNS [Buffer] ],
setPromiscuous: PROC [network: Network, promiscuous: BOOL],
isThisForMe: PROC [network: Network, buffer: Buffer] RETURNS [yes: BOOL],
toBroadcast: PROC [network: Network, buffer: Buffer] RETURNS [yes: BOOL],
moreBuffers: PROC [network: Network, total: NAT],
interceptor: Interceptor,
stats: REF ANY,
instanceData: REF ANY,
type: Type,
speed: INT, -- Bits per second
index: CARDINAL, -- first is 1 (for forwarder)
hearSelf: BOOL,
recvSick: BOOL,
sendSick: BOOL,
dead: BOOL
];
Driver management
GetNetworkChain: PROC RETURNS [Network];
GetNumberOfNetworks: PROC RETURNS [CARDINAL];
AddNetwork: PROC [Network];
NoThankYou: PROC [Network, Buffer, NAT] RETURNS [Buffer];
Protocol Binding
SendType: TYPE = {
ip, ipReturn, ipTranslate,
ns, nsReturn, nsTranslate,
pup, pupReturn, pupTranslate,
other, otherReturn, otherTranslate,
raw };
RecvType: TYPE = {
ip, ipTranslate,
ns, nsTranslate,
pup, pupTranslate,
other, otherTranslate,
error };
InsertReceiveProc: PROC [network: Network, type: RecvType, proc: RecvProc];
network = NIL => whole chain and future additions
Buffer management
AllocBuffer: PROC RETURNS [Buffer];
FreeBuffer: PROC [Buffer];
Buffers are VM.Pinned and have IOCBs permanently assigned. They should only be created by DriverImpl. Do not NEW your own.
dataBytesInBuffer: NAT = 1500;
This breaks the compilation dependency between protocols. Each protocol must make sure their buffers fit into the space allocated in a Driver.BufferObject.
bytesInDriverTail: NAT = 10;
bytesToRead: NAT = dataBytesInBuffer+bytesInDriverTail;
Drivers must add on their encapsulation.
wordsInIocb: NAT = 12;
Buffer: TYPE = REF BufferObject;
The run time TYPE of a buffer (actually the buffer object) gets smashed as the buffer is handed back and forth between the drivers and the protocol modules. As you probably guessed, smashing TYPEs is not for the faint hearted. This is necessary in order for the correct Finalization routine to get notified. (It also bypasses a Debugger bug.) The rules are that the RC maps must be identical and all the package reference counts must be the same. In our case, all the REFs are inside the Overhead and the package use count is always 0.
BufferObject: TYPE = MACHINE DEPENDENT RECORD [
ovh: CommBuffer.Overhead,
data: PACKED ARRAY [0..dataBytesInBuffer) OF BYTE,
driverTail: PACKED ARRAY [0..bytesInDriverTail) OF BYTE ];
Priority
recvPriority: Process.Priority = Process.priorityClient3;
sendPriority: Process.Priority = Process.priorityClient3;
Disk runs at priorityClient2 = priorityForeground
watcherPriority: Process.Priority = Process.priorityClient1; -- normal
Intercepting, Spying, Lightning...
Interceptor: TYPE = REF InterceptorRep;
InterceptorRep: TYPE;
SendInterceptor: TYPE = PROC [
send: SendType,
data: REF ANY,
network: Network,
buffer: Buffer,
bytes: NAT]
RETURNS [kill: BOOLFALSE];
RecvInterceptor: TYPE = PROC [
recv: RecvType,
data: REF ANY,
network: Network,
buffer: Buffer,
bytes: NAT]
RETURNS [kill: BOOLFALSE];
CreateInterceptor: PROC [
network: Network,
sendMask: PACKED ARRAY SendType OF BOOL,
sendProc: SendInterceptor,
recvMask: PACKED ARRAY RecvType OF BOOL,
recvProc: RecvInterceptor,
data: REF ANY,
promiscuous: BOOL] RETURNS [Interceptor];
A client is expected to inspect the buffer promptly and not change anything. Multiple clients are supported. They each see all packets requested by their mask. If any client kills a packet, it is not passed through to the normal system routine. The system automatically filters out trash that promiscuous mode drags in, so clients don't need to kill that.
NB: This interface assumes that all official protocols are already hooked in. Things will get confused if anybody (else) smashes any of the procs in a NetworkObject while an any interceptor is active. That could be fixed by adding an interface to store into those procs. It would store into the saved copy rather than the NetworkObject if any interceptor is active.
DestroyInterceptor: PROC [Interceptor];
There may be a few late calls to the client's sendProc or recvProc.
}.