DIRECTORY DeviceCleanup USING [Item, Await], DoradoInputOutput USING [Output, IOAddress], NSPilotSystem USING [HostNumber], PrincOps USING [zMISC], PrincOpsUtils USING [BITAND, BITOR, LowHalf], NewEthernetFace, NewEthernetFaceExtras; NewEthernetHeadDorado: PROGRAM IMPORTS DeviceCleanup, DoradoInputOutput, PrincOpsUtils EXPORTS NewEthernetFace, NewEthernetFaceExtras = BEGIN OPEN PrincOpsUtils, NewEthernetFace; CSB: TYPE = LONG POINTER TO ControllerStatusBlock; ControllerStatusBlock: TYPE = MACHINE DEPENDENT RECORD [ host: NSPilotSystem.HostNumber, input: ShortIocb, inputWakeups: WORD, output: ShortIocb, outputWakeups: WORD, missed: CARDINAL, lastInput: IOCB, -- last IOCB on input queue, valid if input#noIocb lastOutput: IOCB]; -- last IOCB on output queue, valid if output#noIocb Base: TYPE = LONG BASE POINTER--Environment.Base--; IOCB: TYPE = LONG POINTER TO IOControlBlock; ShortIocb: TYPE = Base RELATIVE POINTER TO IOControlBlock; IOControlBlock: TYPE = MACHINE DEPENDENT RECORD [ bufferLen: CARDINAL, -- length is in BYTES, not words buffer: LONG POINTER, retries: WORD_ 0, -- set by device packetLen: CARDINAL, -- input only, length of the received packet, in bytes completion: CompletionStatus_ nullCompletion, -- raw status from microcode, nonzero at end next: ShortIocb]; Command: TYPE = RECORD [WORD]; eEnableTrn: Command = [1B]; -- (Start Tx) Dispatch to TIOA_ with 047777B eTurnOn: Command = [0B]; -- Dispatch to the startup code with T_ Normal reset eByPassOn: Command = [2B]; -- Dispatch to the startup code with T_ Bypass eTurnNSOff: Command = [3]; -- Dispatch to TIOA_ with T_A0 ECtl: DoradoInputOutput.IOAddress = 26B; CompletionStatus: TYPE = MACHINE DEPENDENT RECORD [ hardware (0: 0..15): SELECT OVERLAID * FROM input => [ overflow (0: 0..0): BOOLEAN, noDribble (0: 1..1): BOOLEAN, fill1 (0: 2..2): [0..1)_ 0, goodCRC (0: 3..3): BOOLEAN, fill2 (0: 4..5): [0..3)_ 0, oddByte (0: 6..6): BOOLEAN, overRun (0: 7..7): BOOLEAN, fill3 (0: 8..15): [0..400B)_ 0], output => [ fill4 (0: 0..7): [0..400B)_ 0, rxOn (0: 8..8): BOOLEAN, txOn (0: 9..9): BOOLEAN, loopBack (0: 10..10): BOOLEAN, IECByPass (0: 11..11): BOOLEAN, -- error if found one by the head noWakeups (0: 12..12): BOOLEAN, -- error if found one by the head txStatus (0: 13..14): {txOK (0), underRun (1), collision (2), maxCollisions (3)}, txDataParityError (0: 15..15): BOOLEAN], ENDCASE]; pendingCompletion: CompletionStatus = LOOPHOLE[0]; nullCompletion: CompletionStatus = LOOPHOLE[0]; inputStatusBits: input CompletionStatus = LOOPHOLE[177400B]; inputGoodStatus: input CompletionStatus = [input[overflow: FALSE, noDribble: TRUE, goodCRC: TRUE, oddByte: FALSE, overRun: FALSE]]; outputErrorMask: output CompletionStatus = [output[rxOn: FALSE, txOn: FALSE, loopBack: FALSE, IECByPass: TRUE, noWakeups: TRUE, txStatus: maxCollisions, txDataParityError: TRUE]]; outputStatusBits: CompletionStatus = LOOPHOLE[377B]; noIocb: ShortIocb = LOOPHOLE[0]; csb: CSB_ LOOPHOLE[LONG[177700B]]; Shorten: PROCEDURE [iocb: IOCB] RETURNS [ShortIocb] = INLINE { RETURN[LOOPHOLE[PrincOpsUtils.LowHalf[iocb]]]}; Reset10MBEther: PROC = MACHINE CODE { PrincOps.zMISC, 250B}; DeviceHandle: PUBLIC TYPE = RECORD [CARDINAL]; ControlBlockRecord: PUBLIC TYPE = IOControlBlock; nullDeviceHandle: PUBLIC DeviceHandle _ [123456B]; self: DeviceHandle = [0]; globalStateSize: PUBLIC CARDINAL _ 0; controlBlockSize: PUBLIC CARDINAL _ SIZE[IOControlBlock]; hearSelf: PUBLIC BOOLEAN _ FALSE; HWMode: TYPE = MACHINE DEPENDENT {hwNormal (173000B), hwLoopBack (173100B)}; ResetBits: WORD = 40B + 20B; EnableTx: WORD = 47777B; ModeFor10MBEther: TYPE = NewEthernetFaceExtras.ModeFor10MBEther; curMode: ModeFor10MBEther_ normal; hwMode: HWMode_ hwNormal; SetModeFor10MBEther: PUBLIC PROC[mode: ModeFor10MBEther_ normal] RETURNS [prev: ModeFor10MBEther] = BEGIN prev_ SELECT hwMode FROM hwNormal => normal, hwLoopBack => loopBack, ENDCASE => other; hwMode _ SELECT mode FROM normal => hwNormal, loopBack => hwLoopBack, ENDCASE => hwNormal; END; QueueOutput: PUBLIC PROCEDURE [ device: DeviceHandle, buffer: LONG POINTER, length: CARDINAL, cb: IOCB] = BEGIN p: LONG POINTER _ buffer; IF device # self THEN RETURN; cb^ _ [ next: noIocb, retries: 0, packetLen: 0, bufferLen: 2*length, buffer: buffer]; IF csb.output = noIocb THEN { -- new iocb, hardware idle csb.output _ Shorten[cb]; DoradoInputOutput.Output[EnableTx, ECtl]} -- poke hardware ELSE -- output active, add to end of chain BEGIN csb.lastOutput.next _ Shorten[cb]; IF csb.output = noIocb AND cb.completion = nullCompletion THEN { -- oops, hardware went idle csb.output _ Shorten[cb]; DoradoInputOutput.Output[EnableTx, ECtl]}; -- poke hardware END; csb.lastOutput _ cb; END; QueueInput: PUBLIC PROC[ device: DeviceHandle, buffer: LONG POINTER, length: CARDINAL, cb: IOCB] = BEGIN IF device # self THEN RETURN; cb^ _ [ next: noIocb, retries: 0, packetLen: 0, bufferLen: 2*length, buffer: buffer]; IF csb.input # noIocb THEN csb.lastInput.next _ Shorten[cb]; IF csb.input = noIocb AND cb.completion = nullCompletion THEN csb.input _ Shorten[cb]; csb.lastInput _ cb; END; GetStatus: PUBLIC PROCEDURE [cb: IOCB] RETURNS [status: Status] = { completion: CompletionStatus; -- *+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+* -- *+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+* IF (completion_ cb.completion) = pendingCompletion THEN RETURN[pending]; IF PrincOpsUtils.BITAND[LOOPHOLE[completion], LOOPHOLE[inputStatusBits]] # 0 THEN { IF LOOPHOLE[PrincOpsUtils.BITAND[LOOPHOLE[completion], LOOPHOLE[inputGoodStatus]], CompletionStatus] = inputGoodStatus THEN RETURN[ok]; RETURN[ SELECT TRUE FROM completion.overflow => packetTooLong, completion.overRun => overrun, NOT completion.goodCRC => crc, NOT completion.noDribble, completion.oddByte => badAlignmentButOkCrc ENDCASE => otherError]}; IF PrincOpsUtils.BITAND[LOOPHOLE[completion], LOOPHOLE[outputStatusBits]] # 0 THEN { IF PrincOpsUtils.BITAND[LOOPHOLE[completion], LOOPHOLE[outputErrorMask]] = 0 THEN RETURN[ok]; RETURN[ SELECT completion.txStatus FROM txOK => ok, underRun, collision => underrun, maxCollisions => tooManyCollisions, ENDCASE => otherError]}; RETURN[otherError]}; GetRetries: PUBLIC PROCEDURE [cb: IOCB] RETURNS [CARDINAL] = { IF cb.retries = 17 THEN RETURN[cb.retries-1] ELSE RETURN[cb.retries]}; GetPacketLength: PUBLIC PROCEDURE [cb: IOCB] RETURNS [used: CARDINAL] = BEGIN used _ (cb.packetLen/2); IF ~cb.completion.noDribble AND cb.completion.oddByte THEN used _ used - 1; END; GetPacketsMissed: PUBLIC PROCEDURE [device: DeviceHandle] RETURNS [CARDINAL] = { RETURN[IF device # self THEN 0 ELSE csb.missed]}; GetNextDevice: PUBLIC PROCEDURE [device: DeviceHandle] RETURNS [DeviceHandle] = { IF device = nullDeviceHandle THEN RETURN[self] ELSE RETURN[nullDeviceHandle]}; TurnOn: PUBLIC PROCEDURE [ device: DeviceHandle, host: NSPilotSystem.HostNumber, inInterrupt, outInterrupt: WORD, globalState: GlobalStatePtr] = BEGIN IF device # self THEN RETURN; Reset10MBEther[]; csb^ _ [ host: host, input: noIocb, inputWakeups: inInterrupt, output: noIocb, outputWakeups: outInterrupt, missed: 0, lastInput: NIL, lastOutput: NIL]; DoradoInputOutput.Output[PrincOpsUtils.BITOR[LOOPHOLE[hwMode], ResetBits], ECtl]; DoradoInputOutput.Output[LOOPHOLE[hwMode], ECtl]; -- turns on receiver END; TurnOff: PUBLIC PROCEDURE [device: DeviceHandle] = { IF device # self THEN RETURN; Reset10MBEther[]}; cleanupInitialized: BOOLEAN _ FALSE; savedCSB: ControllerStatusBlock; AddCleanup: PUBLIC PROCEDURE [device: DeviceHandle] = { OPEN DeviceCleanup; item: Item; oldHost: NSPilotSystem.HostNumber; IF cleanupInitialized THEN RETURN; cleanupInitialized _ TRUE; DO SELECT Await[@item] FROM kill => Reset10MBEther[]; turnOff => {Reset10MBEther[]; savedCSB _ csb^; oldHost _ csb.host}; turnOn => { Reset10MBEther[]; csb^ _ [ host: oldHost, -- Ugh, it would be nice if we could do something better input: noIocb, inputWakeups: 0, output: noIocb, outputWakeups: 0, missed: 0, lastInput: NIL, lastOutput: NIL]; DoradoInputOutput.Output[PrincOpsUtils.BITOR[LOOPHOLE[hwMode], ResetBits], ECtl]; DoradoInputOutput.Output[LOOPHOLE[hwMode], ECtl]}; ENDCASE; ENDLOOP}; RemoveCleanup: PUBLIC PROCEDURE [device: DeviceHandle] = {}; END. -- EthernetHeadDorado. NNewEthernetHeadDorado.mesa, HGM, 19-Sep-82 19:14:40 fix GetRetries and GetStatus for 16 retries, DLionInputOutput cleanup too, NewEthernetHeadDLion.mesa, HGM, 15-Mar-82 17:47:31 EthernetHeadDLion.mesa (last edited by: Sandman on: 18-Mar-81 17:20:56) EthernetHeadDLion.mesa (last edited by: Blyon on: 22-Apr-81 17:43:34) Willie-Sue, January 9, 1986 6:21:27 pm PST Last Edited by: Willie-Sue, July 12, 1984 1:09:54 pm PDT These are the data structures that the microcode knows about. If some other module (for example, a diagnostic) ever needs this info, it should probably get split out into a separate module. For now, it is lumped in here to avoid cluttering up the world with yet another file. If the first word of the HostNumber is all ones then the input mode is to accept all packets!! The NS Ethernet uses TIOA = 26b as NSControl when output and as NSStatus when it is read. The data reg is TIOA=25b. EtherNetOne uses 177600B for input and 177610B for output Maybe we should check to be sure that the high half is zero Reset 10 MB Ethernet hardware and tasks (should be in DoradoInputOutput) Does NOT turn on either the transmittor or the receiver EXPORTed TYPEs EXPORTed variables private stuff the following HWMode values match those in PilotNSEther.mc, for turning on the 10MB receiver in either regular or loopback mode Question--Question--Question--Question--Question--Question It would be best to talk to Hal about the bad alignmend and dribble wehn we are allowing odd number of bytes. These translations may need to be changed so that the odd byte user has no problems it doing it properly and the normal user still sees an odd byte packet as an error. There is no way to remove a cleanup procedure yet, so we have a flag to avoid duplicates. Note that this does NOT really put things back together. It simply smashes things to a safe state. The intention is that the driver will notice that nothing is happening and then call TurnOff+TurnOn to reset things. That allows Pilot to reset the GMT clock on the way back from the debugger without getting tangled up with the normal Ethernet driver. Κ ¦˜Jšœ3™3JšœK™KJšœ2™2JšœG™GšœE™EIcode™*—J˜Jšœ8™8J˜šΟk ˜ Jšœœ˜"Jšœœ˜,Jšœœ˜!Jšœ œ ˜Jšœœœœ ˜-J˜J˜J˜—šœ˜Jšœ0˜7Jšœ)˜0Jšœœ ˜*—J˜Jšœ•™•J˜Jšœ^™^Jš œœœœœ˜2J˜š œœœ œœ˜8J˜J˜Jšœœ˜J˜Jšœœ˜Jšœœ˜Jšœ œΟc2˜DJšœ œž4˜HJ˜—Jš œœœœžœ˜3J˜Jš œœœœœ˜,Jš œ œœœœ˜:J˜š œœœ œœ˜1Jšœ œž!˜6Jšœœœ˜Jšœ œž˜$Jšœ œž7˜MJšœœž,˜ZJ˜J˜—Jšœ œœœ˜Jšœž,˜IJšœž4˜OJšœž.˜KJšœž˜;J™JšœœœRœ™tJšœ(˜(J˜š œœœ œœ˜3Jšœœœ˜+šœ ˜ Jšœœ˜Jšœœ˜J˜Jšœœ˜J˜Jšœœ˜Jšœœ˜Jšœ ˜ —šœ ˜ Jšœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœž!˜AJšœœž!˜AJ˜QJšœœ˜(—Jšœ˜ —J˜Jšœ&œ˜2Jšœ#œ˜/Jšœ*œ ˜<šœ)˜)Jš œœ œ œ œ œ˜Y—šœ*˜*Jš œœœ œ œ œ.œ˜ˆ—Jšœ%œ˜4J˜Jšœœ˜ J˜Jšœ9™9Jšœœœœ ˜"J˜š Οnœ œœœœ˜>Jšœ;™;Jšœœ ˜/J˜—šŸœœœ˜#Jšœ™Jšœ˜J˜—Jšœ™J˜Jš œœœœœ˜.Jšœœœ˜1J˜Jšœ™J˜Jšœœ˜2J˜Jšœœœ˜%Jšœœœœ˜9Jšœ œœœ˜!J˜Jšœ ™ J™Jšœ™J˜Jšœœœ œ,˜LJšœ œ ˜Jšœ œ ˜Jšœœ*˜@Jšœ"˜"Jšœ˜J˜šŸœ˜Jš œ!œ˜Nš˜šœœ˜Jšœ˜Jšœ˜Jšœ ˜—šœ œ˜Jšœ˜Jšœ˜Jšœ ˜——Jšœ˜—J˜šŸ œœ œ˜Jš œœœ œœ˜Iš˜Jšœœœ ˜Jšœœœ˜˜JšœM˜M—šœœž˜9Jšœ˜Jšœ+ž˜;—šœž%˜,š˜J˜"šœœ œž˜\Jšœ˜Jšœ,ž˜<——Jšœ˜—J˜—Jšœ˜J˜—šŸ œœœ"œœ œœ˜dš˜Jšœœœ˜˜JšœM˜M—Jšœœ"˜Jšœž œž œž ™:J™–˜>Jšœ1œœ ˜Hš œœœœœ˜SJšœœœœœ8œœ˜‡šœ˜šœœ˜Jšœ%˜%Jšœ˜Jšœ˜JšœA˜DJšœ˜———J˜š œœœœœ˜TJš œœœœœœ˜]šœ˜šœ˜J˜ J˜ Jšœ#˜#Jšœ˜———Jšœ˜J˜—š Ÿ œœ œœœœ˜