HackPupHostNumber.mesa
Copyright © 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.)
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
If the machine has a real EthernetOne then get the address from the device.
ether ← EthernetOneFace.GetNextDevice[EthernetOneFace.nullHandle];
IF ether # EthernetOneFace.nullHandle THEN {
myHostNumber ← [EthernetOneFace.GetHostNumber[ether]];
RETURN[myHostNumber]; };
Hard case: There is no EthernetOne, so ask the name servers for our address.
ProcessorFace.SetMP[MPCodes.findingPupAddress];
myHostNumber ← GetPupHostNumberFromServer[];
ProcessorFace.SetMP[MPCodes.emptyMP];
RETURN[myHostNumber];
};
Snitched from Germ (MiniEthernetDriverDLion) after pitching OISCP. HGM, November 1, 1985
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;
}....