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; 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 MiniEthernetDriverDLion.mesa last edited by: BLyon on: March 12, 1981 4:37 PM last edited by Sturgis: fixing GetEthernetHostNumber: September 23, 1983 2:18 pm Last Edited by: Birrell, October 31, 1983 3:34 pm Global buffer for actual data transfers. Beware of funny alignment constraints allocate global storage here following by analogy from MiniOISCPDriverImpl.SendPacket of APilot100 modified in analogy to APilot100 PilotCommUtilPup.GetEthernetHostNumber From the new OISCPCOnstants this has to go after debugging this has to go after debugging de-implemented since it is not clear they have storage to use GetEthernetHostNumber: PUBLIC PROCEDURE RETURNS [CARDINAL] = {RETURN[GetEthernet1Address[].host]}; GetEthernetNetNumber: PUBLIC PROCEDURE RETURNS [CARDINAL] = BEGIN net: CARDINAL = GetEthernet1Address[].net; RETURN[IF active THEN myNet ELSE net]; END; should check words that arrived against pupLength? check here for routing table if we ever get that complicated following procedures in anaogy to apilot100 minioiscpdriverimpl.mesa Ê ˜šœ™Jšœ1™1JšœP™PJ˜—Jšœ1™1šÏk ˜ Jšœœ˜J˜ Jšœ œ˜"Jšœ œ%˜6J˜ J˜Jšœ œ,˜Jš˜J˜Jšœœ˜+Jšœœ˜Jšœ˜J˜—šŸ œ œœœ˜+Jšœœ>˜E—J˜šŸ œœ œ˜J˜J˜J˜J˜Jšœœœ˜Jšœœ˜Jš˜Jšœ œœ˜&šœ˜#J˜<—Jšœœœ2˜SJšœœ˜(J˜J˜ J˜J˜J˜Jšœ˜J˜—JšœE™EJšœ œœ˜šŸ œ œ˜J˜J˜$J˜%J˜)Jš˜Jšœœ˜+J˜.J˜(J˜AJšœ!œ˜9˜J˜D—J˜J˜J˜7Jšœ˜J˜—šŸ œœ œ˜ J˜Jšœœœ˜Jšœœ˜Jš˜J˜Jšœ œœ˜&Jšœ œœ˜+J˜>J˜J˜2J˜Jšœ˜J˜—š Ÿœ œœœ œ˜:Jš˜Jšœ œ!˜3Jšœœœ˜4J˜IJ˜&J˜J˜#J˜J˜ J˜Jšœ˜J˜—šŸ œ œ œ˜)Jš˜Jšœœž ˜QJ˜&˜ JšœœœI˜j—šœœœ˜Jšœœœ˜)šœœ˜Jš˜J˜J˜Jšœ˜—Jšœ˜—Jšœ˜J˜—JšœG™GJšœœ˜!Jšœœ˜"šŸœ œœ˜(J˜3Jš˜Jšœœ˜+š œ œœ œœ˜*Jšœ œœ˜;—Jš œ œœœ œ˜Eš œœœ œœ˜(Jšœ œœ˜<—Jš œœœœ œ˜AJšœœ˜Jšœ#œœ#˜mJ˜Jšœ™Jšœ0œ˜Jšœ*œœ˜6šœ˜Jšœ-œœ˜7—Jšœ5œœ˜AJšœ#œœ˜/Jšœœœ˜&J˜Jšœ™J˜Jšœ1˜7Jšœ˜—Jšœ˜—Jšœ˜—Jšœ˜J˜—Jšœ=™=Jšœ<™J˜&J˜Jšœ œ˜ Jšœ˜Jšœ˜—Jšœ"œœ˜.——Jšœ2™2šœ<™