-- 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 PMMcJonesCreate from SystemImpl of Feb 26, 1980 12:22 PM
April 21, 1980 2:16 PMMurrayConvert to use face; trap for globalState
June 26, 1980 5:02 PMMcJonesOISProcessorFace=>ProcessorFace
July 30, 1980 1:42 PMMurray/HowardFix bugs re timeouts
August 20, 1980 2:18 PMBLyonEthernetFace=>EthernetOneFace
January 19, 1981 3:13 PMJoseSetGMTUsingEthernet=>SetGMTUsingEthernetOne; iocb from Resident Heap rather than local frame
January 28, 1981 10:23 AMMcJonesLocalTimeParameters
February 4, 1981 5:44 PMMcJonesSystemExtras=>System
March 12, 1981 9:31 PMYokotaBug fix in SetGMT, MP is set to 937 if time is not set properly
March 19, 1981 3:57 PMYokota990 instead of 930 is set at the exit from SetGMT. 937 is set at the beginning of the loop.