DIRECTORY Basics USING [bytesPerWord], BasicTime USING [GetClockPulses, MicrosecondsToPulses, Pulses], CommBuffer USING [], Checksum USING [ComputeChecksum], Driver USING [AllocBuffer, Buffer, dataBytesInBuffer, FreeBuffer, GetNetworkChain, Network], DriverType USING [Encapsulation, ethernetEncapsulationBytes, ethernetEncapsulationOffset, ethernetMinBytes], EthernetFace USING [Handle, GetNextDevice, GetStatusAndCollisions, GetStatusAndLength, nullHandle, QueueInput, QueueOutput, Status, TurnOff, TurnOn], EthernetOneFace USING [Handle, GetHostNumber, GetNextDevice, nullHandle], MPCodes USING [emptyMP, findingPupAddress, serverSaysNoPupAddress], NS USING [Address, broadcastHost, GetThisHost, Host, Socket, unknownNet], ProcessorFace USING [SetMP], Pup USING [Address, Host, nullHost]; HackPupHostNumber: CEDAR PROGRAM IMPORTS BasicTime, Checksum, Driver, EthernetFace, EthernetOneFace, NS, ProcessorFace EXPORTS CommBuffer = { Encapsulation: PUBLIC TYPE = DriverType.Encapsulation; Network: TYPE = Driver.Network; BYTE: TYPE = [0..100H); myHostNumber: Pup.Host _ Pup.nullHost; SmashPupHostNumber: PROC [new: Pup.Host] = { myHostNumber _ new; }; GetPupHostNumber: PROC RETURNS [Pup.Host] = { ether: EthernetOneFace.Handle; IF myHostNumber # Pup.nullHost THEN RETURN[myHostNumber]; -- easy known case ether _ EthernetOneFace.GetNextDevice[EthernetOneFace.nullHandle]; IF ether # EthernetOneFace.nullHandle THEN { myHostNumber _ [EthernetOneFace.GetHostNumber[ether]]; RETURN[myHostNumber]; }; ProcessorFace.SetMP[MPCodes.findingPupAddress]; myHostNumber _ GetPupHostNumberFromServer[]; ProcessorFace.SetMP[MPCodes.emptyMP]; RETURN[myHostNumber]; }; BufferBody: TYPE = RECORD [ checksum: CARDINAL, bytes: CARDINAL, -- in bytes, includes header transportControl: BYTE, packetType: BYTE, dest, source: NS.Address]; translationRequest: CARDINAL = 1; translationResponse: CARDINAL = 2; translationError: CARDINAL = 3; pupAddressTranslation: NS.Socket _ [0, 9]; pupAddrTransPacket: BYTE _ 6; bytesOnWire: NAT = DriverType.ethernetMinBytes + DriverType.ethernetEncapsulationBytes; GetPupHostNumberFromServer: PROC RETURNS [host: Pup.Host] = TRUSTED { buffer: Driver.Buffer _ Driver.AllocBuffer[]; packet: LONG POINTER TO BufferBody = LOOPHOLE[@buffer.data]; packetBytes: NAT = SIZE[BufferBody, Basics.bytesPerWord]; Request: TYPE = MACHINE DEPENDENT RECORD [ id0, id1: CARDINAL, arg: WORD, who: NS.Host]; requestBytes: NAT = packetBytes + SIZE[Request, Basics.bytesPerWord]; request: LONG POINTER TO Request = LOOPHOLE[packet+SIZE[BufferBody]]; Reply: TYPE = MACHINE DEPENDENT RECORD [ id0, id1: CARDINAL, arg: WORD, answer: Pup.Address]; reply: LONG POINTER TO Reply = LOOPHOLE[packet+SIZE[BufferBody]]; replyBytes: NAT = packetBytes + SIZE[Reply, Basics.bytesPerWord]; timeout: BasicTime.Pulses _ BasicTime.MicrosecondsToPulses[15*1000000]; mySocket: NS.Socket _ pupAddressTranslation; me: NS.Host _ NS.GetThisHost[]; ether: EthernetFace.Handle _ EthernetFace.GetNextDevice[EthernetFace.nullHandle]; IF ether = EthernetFace.nullHandle THEN ERROR No10MBDriverAndNo3MBDriver; DO startPulses: BasicTime.Pulses = BasicTime.GetClockPulses[]; EthernetFace.TurnOff[ether]; EthernetFace.TurnOn[ether, 0, 0]; request^ _ [0, 0, translationRequest, me]; buffer.ovh.encap _ Encapsulation[ ethernet [ ethernetDest: NS.broadcastHost, ethernetSource: me, ethernetType: ns ]]; packet.bytes _ requestBytes; packet.transportControl _ 0; packet.packetType _ pupAddrTransPacket; packet.dest _ [ net: NS.unknownNet, host: NS.broadcastHost, socket: pupAddressTranslation]; packet.source _ [ net: NS.unknownNet, host: me, socket: mySocket]; SetChecksum[packet]; EthernetFace.QueueOutput[ ether, @buffer.ovh.encap+DriverType.ethernetEncapsulationOffset, bytesOnWire, buffer.ovh.iocb]; WHILE (BasicTime.GetClockPulses[] - startPulses) <= timeout DO IF EthernetFace.GetStatusAndCollisions[buffer.ovh.iocb].status # pending THEN EXIT; REPEAT FINISHED => { EthernetFace.TurnOff[ether]; EthernetFace.TurnOn[ether, 0, 0]; }; ENDLOOP; WHILE (BasicTime.GetClockPulses[] - startPulses) <= timeout DO buffer.ovh.encap.ethernetType _ LOOPHOLE[0]; EthernetFace.QueueInput[ ether, @buffer.ovh.encap + DriverType.ethernetEncapsulationOffset, Driver.dataBytesInBuffer + DriverType.ethernetEncapsulationBytes, buffer.ovh.iocb]; WHILE (BasicTime.GetClockPulses[] - startPulses) <= timeout DO status: EthernetFace.Status; bytes: NAT; [status, bytes] _ EthernetFace.GetStatusAndLength[buffer.ovh.iocb]; IF status = pending THEN LOOP; IF status # ok THEN EXIT; IF buffer.ovh.encap.ethernetType # ns THEN EXIT; IF packet.dest.host # me THEN EXIT; IF packet.dest.socket # mySocket THEN EXIT; IF packet.source.socket # pupAddressTranslation THEN EXIT; IF bytes < bytesOnWire THEN EXIT; IF packet.bytes < replyBytes THEN EXIT; IF ~TestChecksum[packet] THEN EXIT; IF reply.arg = translationError THEN ProcessorFace.SetMP[MPCodes.serverSaysNoPupAddress]; IF reply.arg # translationResponse THEN EXIT; EthernetFace.TurnOff[ether]; host _ reply.answer.host; Driver.FreeBuffer[buffer]; RETURN ENDLOOP; ENDLOOP; ENDLOOP; }; SetChecksum: PROC [b: LONG POINTER TO BufferBody] = TRUSTED { words: CARDINAL _ ((b.bytes + Basics.bytesPerWord - 1) / Basics.bytesPerWord)-1; b.checksum _ Checksum.ComputeChecksum[0, words, @b.bytes]; }; TestChecksum: PROC [b: LONG POINTER TO BufferBody] RETURNS [BOOL] = TRUSTED { words: CARDINAL _ ((b.bytes + Basics.bytesPerWord - 1) / Basics.bytesPerWord)-1; checksum: WORD = Checksum.ComputeChecksum[0, words, @b.bytes]; IF b.checksum = 0FFFFH THEN RETURN[TRUE]; IF b.checksum = checksum THEN RETURN[TRUE]; RETURN[FALSE]; }; No10MBDriverAndNo3MBDriver: PUBLIC ERROR = CODE; FOR network: Network _ Driver.GetNetworkChain[], network.next UNTIL network = NIL DO IF network.type # ethernet THEN LOOP; IF network.pup.host # Pup.nullHost THEN LOOP; -- ???? network.pup.host _ GetPupHostNumber[]; ENDLOOP; }.... HackPupHostNumber.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Hal Murray, May 24, 1986 8:00:29 pm PDT If the NS world were alive and well, we could use it to talk to the back door on the Pup name server. This module is a hack. It grabs the ethernet by the face. (That turns out to be a good way to debug the code in EthernetDriver that resets things if they don't seem to be working.) 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 Κ˜codešœ™Kšœ Οmœ1™KšžœGžœžœ˜Sšžœžœ˜Kšœ˜Kšœ$˜$—Kšžœ˜ —šžœ7ž˜>Kšœ žœ˜,šœ˜Kšœ˜Kšœ;˜;KšœA˜AKšœ˜—šžœ7ž˜>K˜Kšœžœ˜ KšœC˜CKšžœžœžœ˜Kšžœ žœžœ˜Kšžœ$žœžœ˜0Kšžœžœžœ˜#Kšžœžœžœ˜+Kšžœ.žœžœ˜:Kšžœžœžœ˜!Kšžœžœžœ˜'Kšžœžœžœ˜#šžœž˜$Kšœ4˜4—Kšžœ!žœžœ˜-Kšœ˜Kšœ˜Kšœ˜Kšž˜Kšžœ˜—Kšžœ˜—Kšžœ˜—Kšœ˜K˜—š Ÿ œžœžœžœžœžœ˜=KšœžœA˜PKšœ:˜:˜K˜——šŸ œžœžœžœžœ žœžœžœ˜MKšœžœA˜PKšœ žœ0˜>Kšžœžœžœžœ˜)Kšžœžœžœžœ˜+Kšžœžœ˜šœ˜K˜——KšŸœžœžœžœ˜0K˜šžœ;žœ žœž˜TKšžœžœžœ˜%Kšžœ!žœžœ ˜5Kšœ&˜&Kšžœ˜—K˜Kšœ˜——…— §