<> <> <> <> DIRECTORY Basics USING[bytesPerWord], BufferDefs, Checksums USING [ComputeChecksum], DriverTypes USING [Encapsulation, EthernetPacketType], EthernetFace, MiniEthernetDefs, OISCPTypes USING[bytesPerPktHeader, PacketType, BufferBody], PrincOpsUtils USING [LongCOPY, LowHalf], ProcessorFace USING [GetClockPulses, ProcessorID, processorID, SetMP], PupTypes, NSAddress USING [broadcastHostNumber, HostNumber, nullNetworkNumber, NetworkAddress, ProcessorID, SocketNumber]; MiniEthernetDriverDLion: PROGRAM IMPORTS Checksums, EthernetFace, PrincOpsUtils, ProcessorFace EXPORTS MiniEthernetDefs SHARES BufferDefs = BEGIN OPEN EthernetFace; active: BOOLEAN _ FALSE; last: {in,out,reset}; knowBoardLocation: BOOLEAN _ FALSE; myID: NSAddress.ProcessorID _ LOOPHOLE[ProcessorFace.processorID]; myHost: PupTypes.PupHostID; myNet: PupTypes.PupNetID; hisPupHost: PupTypes.PupHostID; hisEthernetAddress: NSAddress.HostNumber; <> b: BufferDefs.PupBuffer; pupBufferSize: CARDINAL; ether: DeviceHandle; longIocb: ControlBlock; global: GlobalStatePtr _ LOOPHOLE[LONG[NIL]]; wordsPerPupHeader: CARDINAL = 11; -- includes checksum, not encapsulaton? bytesPerPupHeader: CARDINAL = wordsPerPupHeader*2; BoardLocationUnknown: PUBLIC ERROR = CODE; DriverNotActive: PUBLIC ERROR = CODE; BufferOverflow: PUBLIC ERROR = CODE; ReturnToStrangePlace: PUBLIC ERROR = CODE; DriverNeedsSomeGlobalStorage: PUBLIC ERROR = CODE; DontKnowHowToTranslateThings: ERROR = CODE; ActivateDriver: PUBLIC PROCEDURE [ dataBuffer: LONG POINTER, -- quad word aligned!! length: CARDINAL, iocb: LONG POINTER, avoidCleanup: BOOLEAN _ FALSE] RETURNS [BOOLEAN] = BEGIN encapsulationOffset: CARDINAL = LOOPHOLE[ @LOOPHOLE[0, POINTER TO BufferDefs.PupBufferObject].encapsulation]; IF ~FindTheBoard[] THEN RETURN[FALSE]; knowBoardLocation _ TRUE; <> b _ dataBuffer-encapsulationOffset+3; pupBufferSize _ length-3-SIZE[DriverTypes.Encapsulation]; longIocb _ iocb; [host: myHost, net: myNet] _ GetEthernet1Address[]; IF ~avoidCleanup THEN AddCleanup[ether]; <> TurnOn[ether,myID,0,0,global]; active _ TRUE; last _ reset; RETURN[TRUE]; END; KillDriver: PUBLIC PROCEDURE [avoidCleanup: BOOLEAN _ FALSE] = BEGIN TurnOff[ether]; IF ~avoidCleanup THEN RemoveCleanup[ether]; knowBoardLocation _ FALSE; END; FindTheBoard: PROCEDURE RETURNS [BOOLEAN] = {RETURN[(ether _ GetNextDevice[nullDeviceHandle])#nullDeviceHandle]}; SendPacket: PUBLIC PROCEDURE [ dest: PupTypes.PupAddress, me: PupTypes.PupSocketID, type: PupTypes.PupType, id: PupTypes.Pair, data: LONG POINTER, bytes: CARDINAL] = BEGIN IF ~active THEN ERROR DriverNotActive; IF dest.host=PupTypes.allHosts THEN b.encapsulation.ethernetDest _ NSAddress.broadcastHostNumber ELSE IF dest.host=hisPupHost THEN b.encapsulation.ethernetDest _ hisEthernetAddress ELSE ERROR DontKnowHowToTranslateThings; b.pupType _ type; b.pupID _ id; b.dest _ dest; b.source _ [myNet, myHost, me]; SendPup[data, bytes]; END; <> ByteCount: TYPE = CARDINAL; SendOisPacket: PROCEDURE[ dataLength: ByteCount, type: OISCPTypes.PacketType, sourceSocket: NSAddress.SocketNumber, dest: NSAddress.NetworkAddress] = BEGIN oisBuf: BufferDefs.OisBuffer _ LOOPHOLE[b]; oisBuf.encapsulation.ethernetDest _ dest.host; oisBuf.encapsulation.ethernetType _ ois; oisBuf.ois.pktLength _ dataLength + OISCPTypes.bytesPerPktHeader; oisBuf.ois.transCntlAndPktTp _ [[FALSE, 0, 0], type]; oisBuf.ois.source _ [ net: NSAddress.nullNetworkNumber, host: myID, socket: sourceSocket]; oisBuf.ois.destination _ dest; SetOisChecksum[oisBuf]; SendBuffer[WdsPerEthernetPacket[oisBuf.ois.pktLength]]; END; ReturnPacket: PUBLIC PROCEDURE [ type: PupTypes.PupType, data: LONG POINTER, bytes: CARDINAL] = BEGIN temp: PupTypes.PupAddress; IF ~active THEN ERROR DriverNotActive; IF last#in THEN ERROR ReturnToStrangePlace; b.encapsulation.ethernetDest _ b.encapsulation.ethernetSource; b.pupType _ type; temp _ b.dest; b.dest _ b.source; b.source _ temp; SendPup[data, bytes]; END; SendPup: PROCEDURE [data: LONG POINTER, bytes: CARDINAL] = BEGIN pupWords: CARDINAL = wordsPerPupHeader+(bytes+1)/2; IF pupWords>pupBufferSize THEN ERROR BufferOverflow; PrincOpsUtils.LongCOPY[to: @b.pupWords, from: data, nwords: (bytes+1)/2]; b.pupLength _ bytesPerPupHeader+bytes; b.pupTransportControl _ 0; b.encapsulation.ethernetType _ pup; SetPupChecksum[b]; last _ out; SendBuffer[pupWords]; END; SendBuffer: PROCEDURE [words: CARDINAL] = BEGIN minWordsPerEthernetPacket: CARDINAL = (64/2)-2; --*** Should move to DriverTypes b.encapsulation.ethernetSource _ myID; QueueOutput[ ether, @b.encapsulation, MAX[SIZE[DriverTypes.Encapsulation]+words, minWordsPerEthernetPacket], longIocb]; THROUGH [0..LAST[CARDINAL]) DO IF GetStatus[longIocb]#pending THEN EXIT; REPEAT FINISHED => BEGIN TurnOff[ether]; TurnOn[ether,myID,0,0,global]; END; ENDLOOP; END; <> translationRequest: CARDINAL = 1; translationResponse: CARDINAL = 2; GetEthernet1Address: PROCEDURE RETURNS [ net: PupTypes.PupNetID, host: PupTypes.PupHostID] = BEGIN oisBuf: BufferDefs.OisBuffer _ LOOPHOLE[b]; 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]]; i: CARDINAL _ 1; mySocket: NSAddress.SocketNumber _ LOOPHOLE[PrincOpsUtils.LowHalf[LOOPHOLE[ProcessorFace.GetClockPulses[]]]]; <> pupAddressTranslation: NSAddress.SocketNumber _ LOOPHOLE[9]; pupAddrTransPacket: OISCPTypes.PacketType _ LOOPHOLE[6]; <> ProcessorFace.SetMP[9157]; DO TurnOff[ether]; TurnOn[ether, myID, 0, 0, global]; i _ i + 1; request^ _ [i, i, translationRequest, myID]; SendOisPacket[ SIZE[Request]*2, pupAddrTransPacket, mySocket, [NSAddress.nullNetworkNumber, NSAddress.broadcastHostNumber, pupAddressTranslation] ]; THROUGH [0..3) DO oisBuf.encapsulation.ethernetType _ LOOPHOLE[0]; QueueInput[ ether, @b.encapsulation, pupBufferSize+SIZE[DriverTypes.Encapsulation], longIocb]; THROUGH [0..LAST[CARDINAL]/2) DO IF GetStatus[longIocb] = pending THEN LOOP; IF GetStatus[longIocb] # 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 GetPacketLength[longIocb] < 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; TurnOff[ether]; <> ProcessorFace.SetMP[915]; RETURN [net: reply.answer.net, host: reply.answer.host] ENDLOOP; ENDLOOP; ENDLOOP; END; <> <> <<{RETURN[GetEthernet1Address[].host]};>> <> <> <> <> <> RecvPacket: PUBLIC PROCEDURE [ source: LONG POINTER TO PupTypes.PupAddress, me: PupTypes.PupSocketID, data: LONG POINTER, words: CARDINAL, timeout: PROCEDURE RETURNS [BOOLEAN]] RETURNS [bytes: CARDINAL, id: PupTypes.Pair, type: PupTypes.PupType] = BEGIN IF ~active THEN ERROR DriverNotActive; DO QueueInput[ ether, @b.encapsulation, pupBufferSize+SIZE[DriverTypes.Encapsulation], longIocb]; UNTIL GetStatus[longIocb]#pending DO IF timeout[] THEN BEGIN TurnOff[ether]; TurnOn[ether,myID,0,0,global]; last _ reset; RETURN[MiniEthernetDefs.timedOut,[0,0],LOOPHOLE[0]]; END; ENDLOOP; IF GetStatus[longIocb]#ok THEN LOOP; IF b.encapsulation.ethernetType=translation THEN BEGIN -- See EthernetDriver OPEN raw: LOOPHOLE[b, BufferDefs.Buffer]; AddressPair: TYPE = MACHINE DEPENDENT RECORD [ big: NSAddress.ProcessorID, small: PupTypes.PupHostID, filler: [0..377B]]; request: LONG POINTER TO AddressPair = LOOPHOLE[@raw.rawWords[1]]; translationRequest: CARDINAL = 10101B; translationResponse: CARDINAL = 7070B; IF raw.rawWords[0]#translationRequest THEN LOOP; IF request.small#myHost THEN LOOP; b.encapsulation.ethernetDest _ b.encapsulation.ethernetSource; raw.rawWords[0] _ translationResponse; request.big _ myID; SendBuffer[1+SIZE[AddressPair]]; LOOP; END; IF b.encapsulation.ethernetType#pup THEN LOOP; <> <> IF myNet#0 AND myNet#b.dest.net AND b.dest.net#0 THEN LOOP; IF myHost#b.dest.host THEN LOOP; -- Can't recv broadcast IF me#b.dest.socket THEN LOOP; IF source.net#0 AND source.net#b.source.net AND b.source.net#0 THEN LOOP; IF source.host#0 AND source.host#b.source.host THEN LOOP; IF source.socket#[0,0] AND source.socket#b.source.socket THEN LOOP; IF ~TestPupChecksum[b] THEN LOOP; IF myNet=0 THEN myNet _ b.dest.net; IF (b.pupLength-bytesPerPupHeader)>words*2 THEN LOOP; bytes _ b.pupLength-bytesPerPupHeader; PrincOpsUtils.LongCOPY[to: data, from: @b.pupWords, nwords: (bytes+1)/2]; IF source.net=0 THEN source.net _ b.source.net; IF source.host=0 THEN source.host _ b.source.host; IF source.socket=[0,0] THEN source.socket _ b.source.socket; last _ in; hisPupHost _ source.host; hisEthernetAddress _ b.encapsulation.ethernetSource; RETURN[bytes,b.pupID,b.pupType]; ENDLOOP; END; SetPupChecksum: PUBLIC PROCEDURE [b: BufferDefs.PupBuffer] = BEGIN buf: LONG POINTER = @b.pupLength; size: CARDINAL = (b.pupLength-1)/2; (buf+size)^ _ Checksums.ComputeChecksum[cs: 0, nWords: size, p: buf]; END; TestPupChecksum: PUBLIC PROC [b: BufferDefs.PupBuffer] RETURNS [BOOLEAN] = BEGIN buf: LONG POINTER = @b.pupLength; size: CARDINAL = (b.pupLength-1)/2; cs: CARDINAL = (buf+size)^; RETURN[cs=177777B OR cs=Checksums.ComputeChecksum[cs: 0, nWords: size, p: buf]]; END; <> SetOisChecksum: PROCEDURE [b: BufferDefs.OisBuffer] = { b.ois.checksum _ Checksums.ComputeChecksum[ 0, (b.ois.pktLength + 1 - 2)/2, @b.ois.pktLength]}; TestOisChecksum: PROC [b: BufferDefs.OisBuffer] RETURNS [BOOLEAN] = { 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]}; IF globalStateSize # 0 THEN ERROR DriverNeedsSomeGlobalStorage; END. LOG Time: January 29, 1980 6:00 PM By: Dalal Action: fixed Core Software AR 2658. Time: February 7, 1980 11:18 PM By: Knutsen Action: ioPage now a long pointer. Initialize host socket right. INTEGER Divide Time: February 9, 1980 2:43 PM By: Knutsen/HGM Action: fix clobber of 4 words before buffer Time: April 20, 1980 4:03 PM By: HGM Action: Faceification, add ReturnPacket and timedOut Time: April 28, 1980 7:36 PM By: HGM Action: Fix QueueOutput bug (again!) in RecvPacket Time: July 2, 1980 5:44 PM By: HGM Action: Delete "DriverTypes." in front of pupEthernetPacket Time: August 20, 1980 2:23 PM By: BLyon Action: renamed EthernetFace to EthernetOneFace. Time: November 20, 1980 By: HGM+Forrest Action: DLion/EthernetTwo. Time: February 9, 1981 12:36 PM By: Luniewski/BLyon Action: XWire => Ethernet. INcrease fudge in GetEthernet1Address to 20. Time: July 25, 1983 3:45 pm: Sturgis: begin repairs to GetEtherNetHostNumber RTE: July 27, 1983 3:23 pm: SendOISPacket should not test for active driver, as it is being called during the period when driver is begin activated. Time: October 28, 1983 3:32 pm: Birrell: conversion to 5.0