-- SetGMTUsingEthernetOne.mesa (September 1, 1982 4:25 pm by Taft) DIRECTORY EthernetOneFace USING [ AddCleanup, ControlBlock, controlBlockSize, DeviceHandle, GetEthernet1Address, GetNextDevice, GetPacketLength, GetStatus, GlobalStatePtr, globalStateSize, nullDeviceHandle, QueueInput, QueueOutput, RemoveCleanup, TurnOff, TurnOn], Environment USING [Base, Byte, first64K, Long], Inline USING [BITAND], PilotMP USING [cClient, cTimeNotAvailable], ProcessorFace USING [GreenwichMeanTime, SetGreenwichMeanTime, SetMP], ResidentHeap USING [MakeNode], System USING [gmtEpoch, LocalTimeParameters, WestEast], TemporarySetGMT USING [], Zone USING []; SetGMTUsingEthernetOne: PROGRAM IMPORTS EthernetOneFace, Inline, ProcessorFace, ResidentHeap EXPORTS TemporarySetGMT = BEGIN OPEN System; SetGMT: PUBLIC PROC RETURNS [ valid: BOOLEAN, params: LocalTimeParameters] = BEGIN valid _ FALSE; DO ProcessorFace.SetMP[PilotMP.cTimeNotAvailable]; IF EthernetExists[] THEN BEGIN time: ProcessorFace.GreenwichMeanTime; [time: time, ltp: params] _ GetTime[]; IF time#gmtEpoch THEN {ProcessorFace.SetGreenwichMeanTime[time]; valid _ TRUE; ProcessorFace.SetMP[PilotMP.cClient]; RETURN}; END; ENDLOOP; END; -- Following started as a copy of GTime.mesa as edited by Johnsson on July 12, 1979 8:31 AM NetTime: TYPE = MACHINE DEPENDENT RECORD [ -- this is what comes in an AltoTimeReply Pup timeHigh, timeLow: CARDINAL, direction: WestEast, -- System.WestEast agrees with Pup AltoTimeReply format zone: [0..127], zoneMinutes: [0..255], beginDST, endDST: CARDINAL]; PacketTypePup: CARDINAL = 1000B; AltoTimeRequest: CARDINAL = 206B; AltoTimeReply: CARDINAL = 207B; SocMiscServices: CARDINAL = 4; PupHeader: TYPE = MACHINE DEPENDENT RECORD [ eDest, eSource: Environment.Byte, eWord2, pupLength: CARDINAL, transportControl, pupType: Environment.Byte, pupID1, pupID2: CARDINAL, destNet, destHost: Environment.Byte, destSocket1, destSocket2: CARDINAL, sourceNet, sourceHost: Environment.Byte, sourceSocket1, sourceSocket2: CARDINAL, xSum: CARDINAL]; PupOverhead: CARDINAL = SIZE[PupHeader]; Pup: TYPE = MACHINE DEPENDENT RECORD [ head: PupHeader, data: ARRAY [0..0) OF WORD]; iocb: EthernetOneFace.ControlBlock; DriverNeedsSomeGlobalStorage: PUBLIC ERROR = CODE; GetTime: PROC RETURNS [time: ProcessorFace.GreenwichMeanTime, ltp: LocalTimeParameters] = BEGIN OPEN EthernetOneFace; ether: DeviceHandle = GetNextDevice[nullDeviceHandle]; global: GlobalStatePtr; -- Allocate space when needed inputSize: CARDINAL = PupOverhead + SIZE[NetTime] + slop; slop: CARDINAL = 12; ipup: ARRAY [0..inputSize + 3) OF CARDINAL; opup: ARRAY [0..PupOverhead + 3) OF CARDINAL; request: POINTER TO PupHeader = Inline.BITAND[@opup + 3, -4]; answer: POINTER TO Pup = Inline.BITAND[@ipup + 3, -4]; myHost: Environment.Byte; id1: WORD = 1234B; id2: WORD = 56710B; IF globalStateSize # 0 THEN ERROR DriverNeedsSomeGlobalStorage; [, myHost] _ GetEthernet1Address[ether]; request^ _ [ eDest: 0, eSource: myHost, eWord2: PacketTypePup, pupLength: 2*(PupOverhead - 2), transportControl: 0, pupType: AltoTimeRequest, pupID1: id1, pupID2: id2, destNet: 0, destHost: 0, destSocket1: 0, destSocket2: SocMiscServices, sourceNet: 0, sourceHost: myHost, sourceSocket1: 0, sourceSocket2: SocMiscServices, xSum: 177777B]; AddCleanup[ether]; THROUGH [0..3) DO THROUGH [0..3) DO TurnOff[ether]; TurnOn[ether, myHost, 0, 0, global]; answer.head.eWord2 _ 0; QueueOutput[ether, request, PupOverhead, iocb]; THROUGH [0..LAST[CARDINAL]/2) DO IF GetStatus[iocb] # pending THEN BEGIN IF GetStatus[iocb] = ok AND GetPacketLength[iocb] = PupOverhead + SIZE[NetTime] AND answer.head.eWord2 = PacketTypePup AND answer.head.pupType = AltoTimeReply AND answer.head.pupID1 = id1 AND answer.head.pupID2 = id2 AND answer.head.destHost = myHost AND answer.head.destSocket1 = 0 AND answer.head.destSocket2 = SocMiscServices AND answer.head.sourceSocket1 = 0 AND answer.head.sourceSocket2 = SocMiscServices THEN BEGIN nt: POINTER TO NetTime = LOOPHOLE[@answer.head.xSum]; LOOPHOLE[time, Environment.Long] _ [num[lowbits: nt.timeLow, highbits: nt.timeHigh]]; ltp _ [direction: nt.direction, zone: nt.zone, zoneMinutes: nt.zoneMinutes, beginDST: nt.beginDST, endDST: nt.endDST]; TurnOff[ether]; RemoveCleanup[ether]; RETURN END; -- Start (another) read either because the send just finshed or we didn't like the packet that just arrived. QueueInput[ether, answer, inputSize, iocb]; END; ENDLOOP; ENDLOOP; ENDLOOP; TurnOff[ether]; RemoveCleanup[ether]; time _ gmtEpoch; RETURN END; EthernetExists: PROCEDURE RETURNS [BOOLEAN] = BEGIN OPEN EthernetOneFace; RETURN[GetNextDevice[nullDeviceHandle] # nullDeviceHandle]; END; -- Initialization BEGIN base: Environment.Base RELATIVE POINTER; [node: base] _ ResidentHeap.MakeNode[ n: EthernetOneFace.controlBlockSize, alignment: a4]; iocb _ @Environment.first64K[base]; END; END. April 15, 1980 1:23 PM McJones Create from SystemImpl of Feb 26, 1980 12:22 PM April 21, 1980 2:16 PM Murray Convert to use face; trap for globalState June 26, 1980 5:02 PM McJones OISProcessorFace=>ProcessorFace July 30, 1980 1:42 PM Murray/Howard Fix bugs re timeouts August 20, 1980 2:18 PM BLyon EthernetFace=>EthernetOneFace January 19, 1981 3:13 PM Jose SetGMTUsingEthernet=>SetGMTUsingEthernetOne; iocb from Resident Heap rather than local frame January 28, 1981 10:23 AM McJones LocalTimeParameters February 4, 1981 5:44 PM McJones SystemExtras=>System March 12, 1981 9:31 PM Yokota Bug fix in SetGMT, MP is set to 937 if time is not set properly March 19, 1981 3:57 PM Yokota 990 instead of 930 is set at the exit from SetGMT. 937 is set at the beginning of the loop. (635)