DIRECTORY
BufferDefs USING [BufferAccessHandle, defaultSystemBufferPoolSize, defaultSystemBuffersToReserve, FreeBufferPool, MakeBufferPool, systemAccessHandle],
StatsDefs USING [StatIncr],
CommUtilDefs USING [FriendOfCopyLong, LockCode, UnlockCode, SetDebuggingPointer],
CommFlags USING [doDebug, doStats],
DriverDefs USING [Glitch, GiantVector, GetPupRouter, GetOisRouter, GetWordsPerIocb, SetWordsPerIocb, CreateDefaultEthernetOneDrivers, CreateDefaultEthernetDrivers, Network, DispatcherOff, DispatcherOn, DispatcherImpl, BufferMgr],
OISCP USING [],
PupDefs USING [],
SpecialCommunication USING [PhysicalMedium],
NSAddress USING [NetworkNumber];
Boss:
MONITOR
IMPORTS BufferDefs, StatsDefs, CommUtilDefs, DriverDefs
EXPORTS DriverDefs, OISCP, PupDefs, SpecialCommunication
SHARES BufferDefs, DriverDefs =
BEGIN OPEN CommUtilDefs, DriverDefs, NSAddress, SpecialCommunication;
SemiPublic things for others
firstNetwork: PUBLIC Network ← NIL;
giantVector: PUBLIC POINTER TO GiantVector ← @bigBoy; -- Debugging only
bigBoy: GiantVector;
increasedBufferUseCount, useCount: PUBLIC CARDINAL ← 0;
state: {off, ready} ← off; -- on is ready with useCount>0
IocbNotBigEnough: PUBLIC ERROR = CODE;
CommPackageNotActive: PUBLIC ERROR = CODE;
NetworkNonExistent: PUBLIC ERROR = CODE;
SystemBufferPoolConfused: PUBLIC ERROR = CODE;
GetUseCount: PUBLIC PROCEDURE RETURNS [CARDINAL] = BEGIN RETURN[useCount]; END;
GetDoStats: PUBLIC PROCEDURE RETURNS [BOOLEAN] = BEGIN RETURN[CommFlags.doStats]; END;
GetGiantVector:
PUBLIC
PROCEDURE
RETURNS [
POINTER
TO GiantVector] =
BEGIN RETURN[giantVector]; END;
This code is a bit delicate. There are probably many funny cases that won't work correctly. In particular, there is a race condition between adding/deleting a driver and adding/deleting a router.
AddDeviceToChain:
PUBLIC
PROCEDURE [network: Network, iocbSize:
CARDINAL] =
BEGIN
Add new drivers to the end of the chain so that the normal Ethernet driver will be network zero.
tail: Network ← firstNetwork;
i: CARDINAL ← 1;
UNTIL (iocbSize MOD 4) = 0 DO iocbSize ← iocbSize + 1; ENDLOOP;
IF state = off THEN SetWordsPerIocb[MAX[GetWordsPerIocb[], iocbSize]]
ELSE IF iocbSize > GetWordsPerIocb[] THEN Glitch[IocbNotBigEnough];
IF state = ready THEN LockCode[network.interrupt];
IF useCount > 0
THEN
BEGIN
network.activateDriver[];
DriverDefs.GetPupRouter[].addNetwork[network];
DriverDefs.GetOisRouter[].addNetwork[network];
END;
IF firstNetwork =
NIL
THEN
BEGIN firstNetwork ← network; network.index ← 1; RETURN; END;
UNTIL tail.next = NIL DO tail ← tail.next; i ← i + 1; ENDLOOP;
tail.next ← network;
network.index ← i + 1;
END;
RemoveDeviceFromChain:
PUBLIC
ENTRY
PROCEDURE [network: Network] =
BEGIN
tail: Network ← firstNetwork;
IF useCount > 0
THEN
BEGIN
DriverDefs.GetPupRouter[].removeNetwork[network];
DriverDefs.GetOisRouter[].removeNetwork[network];
network.deactivateDriver[];
END;
IF state = ready THEN UnlockCode[network.interrupt];
IF firstNetwork = network THEN firstNetwork ← network.next
ELSE
BEGIN
UNTIL tail.next = network DO tail ← tail.next; ENDLOOP;
tail.next ← network.next;
END;
network.index is not updated. It is used only to collect Gateway statistics.
END;
ChangeNumberOfInputBuffers:
PUBLIC
ENTRY
PROCEDURE [
increaseTheBuffers: BOOLEAN] =
BEGIN
IF state # ready THEN Glitch[CommPackageNotActive];
IF increaseTheBuffers
THEN
BEGIN
increasedBufferUseCount ← increasedBufferUseCount + 1;
IF increasedBufferUseCount>1 THEN RETURN;
END
ELSE
BEGIN
IF increasedBufferUseCount=0 THEN RETURN; -- donot go negative
increasedBufferUseCount ← increasedBufferUseCount - 1;
IF increasedBufferUseCount#0 THEN RETURN;
END;
FOR net: Network ← firstNetwork, net.next
UNTIL net =
NIL
DO
IF net.changeNumberOfInputBuffers=NIL THEN LOOP;
net.changeNumberOfInputBuffers[increaseTheBuffers];
ENDLOOP;
END;
GetDeviceChain:
PUBLIC
PROCEDURE
RETURNS [Network] =
BEGIN
IF state # ready THEN Glitch[CommPackageNotActive];
RETURN[firstNetwork];
END;
SmashDeviceChain: PUBLIC PROCEDURE = BEGIN firstNetwork ← NIL; END;
The drivers may have to be told what its network numbers are.
This is certainly true if this is the first machine running on a network.
Physical order is the location of the network on the network device chain .
SetNetworkID:
PUBLIC
ENTRY
PROCEDURE [
physicalOrder: CARDINAL, medium: PhysicalMedium, newNetID: NetworkNumber]
RETURNS [oldNetID: NetworkNumber] =
BEGIN
ENABLE UNWIND => NULL;
net: Network;
net ← GetNthDevice[physicalOrder, medium];
oldNetID ← net.netNumber;
net.netNumber ← newNetID;
DriverDefs.GetPupRouter[].stateChanged[net];
DriverDefs.GetOisRouter[].stateChanged[net];
END;
This procedure returns the OisNetID the Nth Network Object on the network device
chain. (where N=physicalOrder).
GetNetworkID:
PUBLIC
ENTRY
PROCEDURE [
physicalOrder: CARDINAL, medium: PhysicalMedium] RETURNS [NetworkNumber] =
BEGIN
ENABLE UNWIND => NULL;
RETURN[GetNthDevice[physicalOrder, medium].netNumber];
END;
This procedure find the Nth (where N=physicalOrder) network of the specified medium
on the network device chain. This assumes that we locked (protected).
GetNthDevice:
PRIVATE
PROCEDURE [
physicalOrder: CARDINAL, medium: PhysicalMedium] RETURNS [net: Network] =
BEGIN
i: CARDINAL ← 0;
FOR net ← firstNetwork, net.next
UNTIL net=
NIL
DO
IF net.device = medium THEN IF (i ← i + 1) = physicalOrder THEN RETURN;
ENDLOOP;
ERROR NetworkNonExistent;
END;
This may be called at any time. It does nothing if already ready.
OiscpPackageReady,
PupPackageReady:
PUBLIC
ENTRY
PROCEDURE =
BEGIN CommPackageReady[]; END;
CommPackageReady:
INTERNAL
PROCEDURE =
BEGIN
extra: CARDINAL ← 0;
IF useCount = 0
AND firstNetwork =
NIL
THEN
BEGIN
[] ← CreateDefaultEthernetDrivers[];
[] ← CreateDefaultEthernetOneDrivers[];
END;
IF state = ready THEN RETURN;
On the Alto, MakeImage forgets low memory
IF CommFlags.doDebug THEN CommUtilDefs.SetDebuggingPointer[giantVector];
IF CommFlags.doStats THEN LockCode[StatsDefs.StatIncr];
LockCode[DriverDefs.DispatcherImpl];
LockCode[DriverDefs.BufferMgr];
LockCode[CommUtilDefs.FriendOfCopyLong];
FOR network: Network ← firstNetwork, network.next
UNTIL network =
NIL
DO
extra ← extra + network.buffers; ENDLOOP;
IF BufferDefs.systemAccessHandle # NIL THEN Glitch[SystemBufferPoolConfused];
BufferDefs.systemAccessHandle ← BufferDefs.MakeBufferPool[
total: BufferDefs.defaultSystemBufferPoolSize + extra,
reserve: BufferDefs.defaultSystemBuffersToReserve];
DispatcherOn[];
FOR network: Network ← firstNetwork, network.next
UNTIL network =
NIL
DO
LockCode[network.interrupt]; ENDLOOP;
state ← ready;
END;
CommPackageGo:
PUBLIC
ENTRY
PROCEDURE =
BEGIN
On the Alto, MakeImage forgets low memory
IF CommFlags.doDebug THEN CommUtilDefs.SetDebuggingPointer[giantVector];
CommPackageReady[];
IF (useCount ← useCount + 1) > 1 THEN RETURN;
FOR network: Network ← firstNetwork, network.next
UNTIL network =
NIL
DO
network.activateDriver[]; ENDLOOP;
END;
CommPackageOff:
PUBLIC
ENTRY
PROCEDURE =
BEGIN
IF (useCount ← useCount - 1) # 0 THEN RETURN;
FOR network: Network ← firstNetwork, network.next
UNTIL network =
NIL
DO
network.deactivateDriver[]; UnlockCode[network.interrupt]; ENDLOOP;
DispatcherOff[];
IF BufferDefs.systemAccessHandle = NIL THEN Glitch[SystemBufferPoolConfused];
BufferDefs.FreeBufferPool[BufferDefs.systemAccessHandle];
BufferDefs.systemAccessHandle ← NIL;
IF CommFlags.doStats THEN UnlockCode[StatsDefs.StatIncr];
UnlockCode[CommUtilDefs.FriendOfCopyLong];
UnlockCode[DriverDefs.BufferMgr];
UnlockCode[DriverDefs.DispatcherImpl];
state ← off;
END;
initialization
IF CommFlags.doDebug
THEN
BEGIN
CommUtilDefs.SetDebuggingPointer[giantVector];
giantVector.slaThings ← giantVector.prThings ← NIL;
END;
START DriverDefs.DispatcherImpl;
START DriverDefs.BufferMgr;
END.