-- File: PupMicrocodeBooterAlto.mesa, Last Edit: HGM November 2, 1980 12:10 PM DIRECTORY Environment USING [bytesPerPage], System USING [Pulses, GetClockPulses, PulsesToMicroseconds], Lock USING [LockDisk, UnlockDisk], BootServerDefs USING [ BootFile, WhatHappened, microcodeReply, microcodeVersionNumber], ReadDefs USING [ CBZptr, CBptr, GetNextPage, ReleasePage, StartReading, StopReading], CommUtilDefs USING [CopyLong], PupDefs USING [PupBuffer, GetLocalPupAddress, GetFreePupBuffer, SendPup], PupTypes USING [PupAddress, miscSrvSoc]; PupMicrocodeBooterAlto: PROGRAM IMPORTS System, Lock, CommUtilDefs, ReadDefs, PupDefs EXPORTS BootServerDefs = BEGIN OPEN BootServerDefs; blankDisplay: BOOLEAN ← TRUE; bufferSize: CARDINAL ← 5; -- patch by hand to adjust MicrocodeBooter: PUBLIC PROCEDURE [bf: BootFile, him: PupTypes.PupAddress] RETURNS [what: WhatHappened] = BEGIN zone: ReadDefs.CBZptr; cb: ReadDefs.CBptr; pulses: System.Pulses ← System.GetClockPulses[]; packetNumber: CARDINAL ← 0; n: CARDINAL; chunk: POINTER TO ARRAY [0..0) OF WORD; me: PupTypes.PupAddress ← PupDefs.GetLocalPupAddress[ PupTypes.miscSrvSoc, @him]; IF ~Lock.LockDisk[bf.fileName, read, blankDisplay] THEN RETURN[diskBusy]; BEGIN one, two: WORD; b: PupDefs.PupBuffer; zone ← ReadDefs.StartReading[@bf.file.fID, bufferSize]; cb ← ReadDefs.GetNextPage[zone]; -- skip file system leader page ReadDefs.ReleasePage[cb]; cb ← ReadDefs.GetNextPage[zone]; -- skip boot file header page chunk ← cb.dataAddress; IF chunk[0] # microcodeVersionNumber THEN GOTO MisMatch; ReadDefs.ReleasePage[cb]; -- It takes 3 Alto words to specify a complete D0 ControlStore word. In order to simplify the EProm logic, the Boot Server sends packets that have an integral number of ControlStore words. Unfortunately that doesn't mesh with the Alto wordsPerPage. That is the story behind the following verbose clump of code. DO length: CARDINAL; -- first of three cb ← ReadDefs.GetNextPage[zone]; chunk ← cb.dataAddress; n ← cb.labelAddress.bytes; IF n = 0 THEN EXIT; length ← IF n = Environment.bytesPerPage THEN n - 2 ELSE n; b ← PupDefs.GetFreePupBuffer[]; b.dest ← him; b.source ← me; b.pupID ← [microcodeVersionNumber, packetNumber]; CommUtilDefs.CopyLong[from: @chunk[0], nwords: 255, to: @b.pupWords[0]]; one ← chunk[255]; PupDefs.SendPup[b, BootServerDefs.microcodeReply, length]; packetNumber ← packetNumber + 1; ReadDefs.ReleasePage[cb]; IF n # Environment.bytesPerPage THEN EXIT; -- second of three cb ← ReadDefs.GetNextPage[zone]; chunk ← cb.dataAddress; n ← cb.labelAddress.bytes; length ← IF n = Environment.bytesPerPage THEN n - 2 ELSE n + 2; b ← PupDefs.GetFreePupBuffer[]; b.dest ← him; b.source ← me; b.pupID ← [microcodeVersionNumber, packetNumber]; b.pupWords[0] ← one; -- copy extra word in case this is the last page CommUtilDefs.CopyLong[from: @chunk[0], nwords: 255, to: @b.pupWords[1]]; one ← chunk[254]; two ← chunk[255]; PupDefs.SendPup[b, BootServerDefs.microcodeReply, length]; packetNumber ← packetNumber + 1; ReadDefs.ReleasePage[cb]; IF n # Environment.bytesPerPage THEN EXIT; -- third of three cb ← ReadDefs.GetNextPage[zone]; chunk ← cb.dataAddress; n ← cb.labelAddress.bytes; b ← PupDefs.GetFreePupBuffer[]; b.dest ← him; b.source ← me; b.pupID ← [microcodeVersionNumber, packetNumber]; b.pupWords[0] ← one; b.pupWords[1] ← two; CommUtilDefs.CopyLong[from: @chunk[0], nwords: 256, to: @b.pupWords[2]]; PupDefs.SendPup[b, BootServerDefs.microcodeReply, n + 4]; packetNumber ← packetNumber + 1; ReadDefs.ReleasePage[cb]; IF n # Environment.bytesPerPage THEN EXIT; ENDLOOP; b ← PupDefs.GetFreePupBuffer[]; b.dest ← him; b.source ← me; b.pupID ← [microcodeVersionNumber, packetNumber]; PupDefs.SendPup[b, BootServerDefs.microcodeReply, 0]; -- End Marker for Initial ReadDefs.StopReading[zone]; pulses ← System.Pulses[System.GetClockPulses[] - pulses]; bf.count ← bf.count + 1; bf.ms ← bf.ms + System.PulsesToMicroseconds[pulses]/1000; what ← micro; EXITS MisMatch => BEGIN ReadDefs.StopReading[zone]; what ← troubles; END; END; Lock.UnlockDisk[bf.fileName, blankDisplay]; END; END.