-- File: Boss.mesa, -- Last Edit: HGM January 7, 1981 1:37 AM -- Last Edit: BLyon March 4, 1981 2:37 PM 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], SpecialSystem USING [NetworkNumber]; Boss: MONITOR IMPORTS BufferDefs, StatsDefs, CommUtilDefs, DriverDefs EXPORTS DriverDefs, OISCP, PupDefs, SpecialCommunication SHARES BufferDefs, DriverDefs = BEGIN OPEN CommUtilDefs, DriverDefs, SpecialSystem, 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.