DIRECTORY Basics USING [bytesPerWord, LongMult, LongDiv], BufferDefs USING [OisBuffer], Checksums USING [ComputeChecksum], CommunicationInternal USING [], CommUtilDefs USING [], DriverDefs USING [GetInputBuffer, ReturnFreeBuffer], DriverTypes USING [Encapsulation], EthernetFace USING [ControlBlock, DeviceHandle, GlobalStatePtr, globalStateSize, GetNextDevice, GetPacketLength, GetStatus, nullDeviceHandle, QueueInput, QueueOutput, TurnOff, TurnOn], EthernetOneFace USING [DeviceHandle, GetEthernet1Address, GetNextDevice, nullDeviceHandle], MPCodes USING [findPupAddress, emptyMP], NSAddress USING [broadcastHostNumber, HostNumber, nullNetworkNumber, NetworkAddress, ProcessorID, SocketNumber], OISCPTypes USING [bytesPerPktHeader, PacketType, BufferBody], PrincOpsUtils USING [Copy, LongCopy, LowHalf], Process USING [MsecToTicks, SecondsToTicks, Ticks], ProcessorFace USING [GetClockPulses, microsecondsPerHundredPulses, processorID, SetMP], PupDefs USING [], --EXPORTS Time Conversion stuff PupStream USING [Tocks], --EXPORTS Time Conversion stuff PupTypes USING [PupAddress, PupHostID], VM USING [AddressForPageNumber, Allocate, Free, Interval, lowCore, PageNumberForAddress, PagesForWords, Pin]; PilotCommUtil: MONITOR IMPORTS Checksums, DriverDefs, EthernetFace, EthernetOneFace, PrincOpsUtils, Process, ProcessorFace, VM EXPORTS CommunicationInternal, CommUtilDefs, DriverDefs, PupDefs, PupStream SHARES BufferDefs = { MixedIocbSize: ERROR = CODE; iocbSize: CARDINAL _ 0; IocbType: TYPE = RECORD[ next: LONG POINTER TO IocbType, rest: SEQUENCE COMPUTED CARDINAL OF WORD]; freeIocb: LONG POINTER TO IocbType _ NIL; AllocateIocb: PUBLIC ENTRY PROC [nwords: CARDINAL] RETURNS [i: LONG POINTER] = { IF iocbSize = 0 THEN iocbSize _ nwords; IF iocbSize # nwords THEN Glitch[MixedIocbSize]; IF freeIocb # NIL THEN { i _ freeIocb; freeIocb _ freeIocb.next } ELSE i _ VM.lowCore.NEW[IocbType[iocbSize-SIZE[IocbType[0]]]]; }; FreeIocb: PUBLIC ENTRY PROC [iocbPtr: LONG POINTER] = { i: LONG POINTER TO IocbType = LOOPHOLE[iocbPtr]; i.next _ freeIocb; freeIocb _ i; }; AllocateBuffers: PUBLIC PROC [nwords: CARDINAL] RETURNS [base: LONG POINTER] = { interval: VM.Interval = VM.Allocate[VM.PagesForWords[nwords]]; VM.Pin[interval]; base _ VM.AddressForPageNumber[interval.page]; }; FreeBuffers: PUBLIC PROC [base: LONG POINTER, nwords: CARDINAL] = { VM.Free[[page: VM.PageNumberForAddress[base], count: VM.PagesForWords[nwords]]]; }; Zero: PUBLIC PROC [p: POINTER, l: CARDINAL] = { IF l = 0 THEN RETURN; p^ _ 0; PrincOpsUtils.Copy[from: p, to: p + 1, nwords: l - 1]; }; TockConversionTroubles: PUBLIC ERROR = CODE; SecondsToTocks: PUBLIC SAFE PROC [t: CARDINAL] RETURNS [PupStream.Tocks] = CHECKED { tks: Process.Ticks = Process.SecondsToTicks[t]; IF tks = LAST[Process.Ticks] THEN ERROR TockConversionTroubles; RETURN[[tks]]; }; MsToTocks: PUBLIC SAFE PROC [t: CARDINAL] RETURNS [PupStream.Tocks] = CHECKED { IF t = 0 THEN ERROR TockConversionTroubles; RETURN[[Process.MsecToTicks[t]]]; }; errorHandler: PROC [ERROR] _ DefaultErrorHandler; CaptureErrors: PUBLIC PROC [proc: PROC [ERROR]] = {errorHandler _ proc}; DefaultErrorHandler: PROC [why: ERROR] = { SIGNAL LOOPHOLE[why, SIGNAL] }; Glitch: PUBLIC PROC [why: ERROR] = {DO errorHandler[why] ENDLOOP}; FriendOfCopyLong: PUBLIC PROC [from: LONG POINTER, nwords: CARDINAL, to: LONG POINTER] = { PrincOpsUtils.LongCopy[from, nwords, to]; }; myHostNumber: CARDINAL _ 0; SmashMyHostNumber: PUBLIC ENTRY PROC [new: CARDINAL] = { myHostNumber _ new; }; GetEthernetHostNumber: PUBLIC ENTRY PROC RETURNS [CARDINAL] = { ether: EthernetOneFace.DeviceHandle; IF myHostNumber#0 THEN RETURN[myHostNumber]; -- easy known case ether _ EthernetOneFace.GetNextDevice[EthernetOneFace.nullDeviceHandle]; IF ether#EthernetOneFace.nullDeviceHandle THEN { net, host: [0..256); [net, host] _ EthernetOneFace.GetEthernet1Address[ether]; RETURN[myHostNumber _ host]; }; ProcessorFace.SetMP[MPCodes.findPupAddress]; myHostNumber _ GetPupHostNumber[]; ProcessorFace.SetMP[MPCodes.emptyMP]; RETURN[myHostNumber]; }; global: EthernetFace.GlobalStatePtr _ LOOPHOLE[LONG[NIL]]; wordsPerPupHeader: CARDINAL = 11; -- includes checksum, not encapsulaton bytesPerPupHeader: CARDINAL = wordsPerPupHeader*2; translationRequest: CARDINAL = 1; translationResponse: CARDINAL = 2; GetPupHostNumber: PROC RETURNS [host: PupTypes.PupHostID] = { oisBuf: BufferDefs.OisBuffer _ LOOPHOLE[DriverDefs.GetInputBuffer[]]; Request: TYPE = MACHINE DEPENDENT RECORD [ id0, id1: CARDINAL, arg: WORD, who: NSAddress.ProcessorID]; request: LONG POINTER TO Request = LOOPHOLE[@oisBuf.ois.oisWords[0]]; Reply: TYPE = MACHINE DEPENDENT RECORD [ id0, id1: CARDINAL, arg: WORD, answer: PupTypes.PupAddress]; reply: LONG POINTER TO Reply = LOOPHOLE[@oisBuf.ois.oisWords[0]]; pulsesPerSec: LONG CARDINAL _ Basics.LongMult[1000, Basics.LongDiv[100000, ProcessorFace.microsecondsPerHundredPulses]+1]; timeoutPulses: LONG CARDINAL _ 0; i: CARDINAL _ 1; mySocket: NSAddress.SocketNumber _ LOOPHOLE[PrincOpsUtils.LowHalf[LOOPHOLE[ProcessorFace.GetClockPulses[]]]]; pupAddressTranslation: NSAddress.SocketNumber _ LOOPHOLE[9]; pupAddrTransPacket: OISCPTypes.PacketType _ LOOPHOLE[6]; minWordsPerEthernetPacket: CARDINAL = (64/2)-2; --*** Should move to DriverTypes myID: NSAddress.ProcessorID _ LOOPHOLE[ProcessorFace.processorID]; ether: EthernetFace.DeviceHandle _ EthernetFace.GetNextDevice[EthernetFace.nullDeviceHandle]; IF ether = EthernetFace.nullDeviceHandle THEN ERROR No10MBDriverAndNo3MBDriver; THROUGH [0..15] DO timeoutPulses _ timeoutPulses + pulsesPerSec; ENDLOOP; DO startPulses: LONG CARDINAL = ProcessorFace.GetClockPulses[]; EthernetFace.TurnOff[ether]; EthernetFace.TurnOn[ether, LOOPHOLE[myID], 0, 0, global]; i _ i + 1; request^ _ [i, i, translationRequest, myID]; oisBuf.encapsulation.ethernetDest _ NSAddress.broadcastHostNumber; oisBuf.encapsulation.ethernetType _ ois; oisBuf.ois.pktLength _ OISCPTypes.bytesPerPktHeader + SIZE[Request, Basics.bytesPerWord]; oisBuf.ois.transCntlAndPktTp _ [[FALSE, 0, 0], pupAddrTransPacket]; oisBuf.ois.source _ [ net: NSAddress.nullNetworkNumber, host: myID, socket: mySocket]; oisBuf.ois.destination _ [ net: NSAddress.nullNetworkNumber, host: NSAddress.broadcastHostNumber, socket: pupAddressTranslation]; SetOisChecksum[oisBuf]; oisBuf.encapsulation.ethernetSource _ myID; EthernetFace.QueueOutput[ ether, @oisBuf.encapsulation, MAX[SIZE[DriverTypes.Encapsulation]+WdsPerEthernetPacket[oisBuf.ois.pktLength], minWordsPerEthernetPacket], oisBuf.iocbChain]; WHILE (ProcessorFace.GetClockPulses[] - startPulses) <= timeoutPulses DO IF EthernetFace.GetStatus[oisBuf.iocbChain]#pending THEN EXIT; REPEAT FINISHED => { EthernetFace.TurnOff[ether]; EthernetFace.TurnOn[ether, LOOPHOLE[myID], 0, 0, global]; }; ENDLOOP; WHILE (ProcessorFace.GetClockPulses[] - startPulses) <= timeoutPulses DO oisBuf.encapsulation.ethernetType _ LOOPHOLE[0]; EthernetFace.QueueInput[ ether, @oisBuf.encapsulation, oisBuf.length, oisBuf.iocbChain]; WHILE (ProcessorFace.GetClockPulses[] - startPulses) <= timeoutPulses DO IF EthernetFace.GetStatus[oisBuf.iocbChain] = pending THEN LOOP; IF EthernetFace.GetStatus[oisBuf.iocbChain] # ok THEN EXIT; IF oisBuf.encapsulation.ethernetType # ois THEN EXIT; IF oisBuf.ois.destination.host # myID THEN EXIT; IF oisBuf.ois.source.socket # pupAddressTranslation THEN EXIT; IF oisBuf.ois.destination.socket # mySocket THEN EXIT; IF EthernetFace.GetPacketLength[oisBuf.iocbChain] < WdsPerEthernetPacket[oisBuf.ois.pktLength] THEN EXIT; IF oisBuf.ois.pktLength < OISCPTypes.bytesPerPktHeader THEN EXIT; IF (reply.arg # translationResponse) THEN EXIT; IF ~TestOisChecksum[oisBuf] THEN EXIT; EthernetFace.TurnOff[ether]; DriverDefs.ReturnFreeBuffer[oisBuf]; RETURN[reply.answer.host] ENDLOOP; ENDLOOP; ENDLOOP; }; SetOisChecksum: PROC [b: BufferDefs.OisBuffer] = { b.ois.checksum _ Checksums.ComputeChecksum[ 0, (b.ois.pktLength + 1 - 2)/2, @b.ois.pktLength]; }; TestOisChecksum: PROC [b: BufferDefs.OisBuffer] RETURNS [BOOL] = { RETURN[ b.ois.checksum = Checksums.ComputeChecksum[ 0, (b.ois.pktLength + 1 - 2)/2, @b.ois.pktLength] OR b.ois.checksum = 177777B]; }; WdsPerEthernetPacket: PROC [bodyBytes: CARDINAL] RETURNS[wds: CARDINAL] = { minWdsPerEthernetPacket: CARDINAL = ((64-4)/Basics.bytesPerWord); wds _ SIZE[DriverTypes.Encapsulation] + (bodyBytes + Basics.bytesPerWord-1)/Basics.bytesPerWord; wds _ MAX[wds, minWdsPerEthernetPacket]; }; No10MBDriverAndNo3MBDriver: PUBLIC ERROR = CODE; DriverNeedsSomeGlobalStorage: PUBLIC ERROR = CODE; IF EthernetFace.globalStateSize # 0 THEN ERROR DriverNeedsSomeGlobalStorage; }.... fPilotCommUtil.mesa - implementation module for Pilot provided utilities Copyright c 1985 by Xerox Corporation. All rights reserved. Russ Atkinson (RRA) October 17, 1985 6:08:37 pm PDT Hal Murray November 1, 1985 3:23:45 pm PST Heap nodes. All these are currently resident, and in first 64K IOCB allocation. Clumps of pages Other goodies TimeCoversion for Pup package implement with Process.Tick = Tock Code depends upon Process.MsecToTicks corectly rounding up the argument before caculating the result, and SecondsToTicks returning LAST[Ticks] for large seconds. this assumes that a tock is longer than an millisecond Communication error handler if the machine has a real ethernetOne then get the address from the device Hard case: there is no EthernetOne, so ask the name servers for our address. Snitched from Germ (MiniEthernetDriverDLion) after pitching OISCP. HGM, November 1, 1985 This is a conservative (high) estimate of the # of pulses in a second From the new OISCPCOnstants RRA: Since we don't trust the multiplication to stay within the bounds supported by microcode, we do this in a simple-minded loop. Κ 6˜codešœG™GKšœ Οmœ1™—Kšœ˜K˜—š  œžœžœžœ žœžœ˜7Kš œžœžœžœ žœ ˜0K˜ Kšœ˜K˜—Kšœ™K˜š œžœžœ žœžœžœžœ˜PKšœ žœ žœ žœ˜>Kšžœ˜Kšœžœ%˜.Kšœ˜K˜—š   œžœžœžœžœ žœ˜CKšžœ žœ$žœ˜PKšœ˜K˜——šœ ™ K˜š  œžœžœžœžœ˜/Kšžœžœžœ˜K˜Kšœ6˜6Kšœ˜K˜—Kšœ™Kšœ"™"Kšœ.™.Kšœ6™6Kšœ;™;K˜Kšœžœžœžœ˜,K˜š œžœžœžœžœžœžœ˜TK˜/Kšžœžœžœžœ˜?Kšžœ˜Kšœ˜K˜—Kšœ6™6K˜š  œžœžœžœžœžœžœ˜OKšžœžœžœ˜+Kšžœ˜!Kšœ˜K˜—Kšœ™K˜Kšœžœžœ˜1K˜Kš   œžœžœžœžœ˜HK˜š œžœžœžœžœžœžœ˜JK˜—Kš  œžœžœžœžœžœ˜BK˜š œžœžœžœžœ žœžœžœ˜ZKšœ)˜)Kšœ˜K˜—Kšœžœ˜K˜š  œžœžœžœžœ˜8K˜Kšœ˜K˜—š  œžœžœžœžœžœ˜?K˜$KšžœžœžœŸ˜@KšœJ™JK˜Hšžœ(žœ˜0K˜K˜9Kšžœ˜—KšœL™LK˜,Kšœ"˜"K˜%Kšžœ˜Kšœ˜K˜—K™XKšœ&žœžœžœ˜:K˜Kšœžœ Ÿ&˜JKšœžœ˜2K˜Kšœžœ˜!Kšœžœ˜"šœžœžœ˜=Kšœžœ˜Eš œ žœžœž œžœ˜*Kšœ žœžœ˜;—Kš œ žœžœžœ žœ˜Eš œžœžœž œžœ˜(Kšœ žœžœ˜<—Kš œžœžœžœ žœ˜Ašœžœžœ_˜zKšœE™E—Kšœžœžœ˜!Kšœžœ˜Kšœ#žœžœ#˜mK˜Kšœ™Kšœ0žœ˜šžœžœ˜Kšœ˜Kšœž œ˜<—Kšžœ˜ —šžœAž˜HKšœ$žœ˜0šœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—šžœAž˜HKšžœ4žœžœ˜@Kšžœ/žœžœ˜;Kšžœ)žœžœ˜5Kšžœ$žœžœ˜0Kšžœ2žœžœ˜>Kšžœ*žœžœ˜6Kšžœ]žœžœ˜iKšžœ5žœžœ˜AKšžœ#žœžœ˜/Kšžœžœžœ˜&Kšœ˜Kšœ$˜$Kšžœ˜Kšžœ˜—Kšžœ˜—Kšžœ˜—Kšœ˜K˜—š œžœ˜2˜+K˜2—˜K˜——š œžœžœžœ˜Bšžœ˜˜+K˜1—Kšžœ˜—šœ˜K˜——š  œžœ žœžœžœ˜KKšœžœ ˜A˜Kšžœ˜!K˜8—Kšœžœ˜(—šœ˜K˜—Kšœžœžœžœ˜0Kšœžœžœžœ˜2Kšžœ"žœžœ˜LK˜Kšœ˜——…—!Έ0T