-- NewEthernetHeadDLion.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, April 7, 1988 2:41:04 pm PDT -- Last Edited by: Willie-Sue, July 2, 1984 5:09:18 pm PDT -- Need to keep map up to date!!! -- BEWARE: -- This version assumes that the IOCBs are 8 word aligned. -- It also assumes that the driver will keep the map up to date if necessary. DIRECTORY DeviceCleanup USING [Item, Await], DLionInputOutput USING [IOPage, Input, Output, InputReg, OutputReg], NSPilotSystem USING [HostNumber], PrincOpsUtils USING [BITAND, LowHalf], NewEthernetFace, NewEthernetFaceExtras; NewEthernetHeadDLion: PROGRAM IMPORTS PrincOpsUtils, DLionInputOutput, DeviceCleanup EXPORTS NewEthernetFace, NewEthernetFaceExtras = BEGIN OPEN PrincOpsUtils, NewEthernetFace; unusedSpaceOffset: CARDINAL = 111; -- 6F hex unusedSpaceMax: CARDINAL = magTapeCSBOffset - unusedSpaceOffset; magTapeCSBOffset: CARDINAL = 188; -- C0 hex magTapeCSBMax: CARDINAL = ethernetCSBOffset - magTapeCSBOffset; ethernetCSBOffset: CARDINAL = 192; -- C0 hex ethernetCSBMax: CARDINAL = moreUnusedSpaceOffset - ethernetCSBOffset; moreUnusedSpaceOffset: CARDINAL = 204; -- CC hex moreUnusedSpaceMax: CARDINAL = displayCSBOffset - moreUnusedSpaceOffset; displayCSBOffset: CARDINAL = 231; -- E7 hex -- 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. 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--; compileCheckEthernetCSBSize: BOOLEAN[TRUE..TRUE] = -- (DLionInputOutput.ethernetCSBMax >= SIZE[ControllerStatusBlock]); (ethernetCSBMax >= SIZE[ControllerStatusBlock]); IOCB: TYPE = LONG POINTER TO IOControlBlock; ShortIocb: TYPE = Base RELATIVE POINTER TO IOControlBlock; IOControlBlock: TYPE = MACHINE DEPENDENT RECORD [ length: CARDINAL, buffer: LONG POINTER, mask: WORD, -- load location for output used: CARDINAL, -- input only completion: WORD, next: ShortIocb, spare: WORD]; -- NB: Can't cross page boundry Command: TYPE = RECORD [WORD]; eEnableTrn: Command = [1B]; eEnableRcv: Command = [1B]; eTurnOff: Command = [2B]; -- completion bits collision: WORD = 100B; underRun: WORD = 40B; dribble: WORD = 20B; overRun: WORD = 10B; notGoodCRC: WORD = 4B; oddByte: WORD = 2B; -- other status bits eRcvEnabled: WORD = 2000B; eTrnEnabled: WORD = 400B; noIocb: ShortIocb = LOOPHOLE[0]; SetModeFor10MBEther: PUBLIC PROC[ mode: NewEthernetFaceExtras.ModeFor10MBEther_ normal] RETURNS[NewEthernetFaceExtras.ModeFor10MBEther] = { RETURN[mode]}; Shorten: PROCEDURE [iocb: IOCB] RETURNS [ShortIocb] = INLINE { -- Maybe we should check to be sure that the high half is zero RETURN[LOOPHOLE[PrincOpsUtils.LowHalf[iocb]]]}; MakeSureOff: PROC = INLINE { DLionInputOutput.Output[eTurnOff, EICtl]; THROUGH [0..2) UNTIL BITAND[DLionInputOutput.Input[EStatus], eRcvEnabled + eTrnEnabled] = 0 DO ENDLOOP}; -- EXPORTed TYPEs DeviceHandle: PUBLIC TYPE = RECORD [CARDINAL]; ControlBlockRecord: PUBLIC TYPE = IOControlBlock; -- EXPORTed variables nullDeviceHandle: PUBLIC DeviceHandle _ [123456B]; self: DeviceHandle = [0]; globalStateSize: PUBLIC CARDINAL _ 0; controlBlockSize: PUBLIC CARDINAL _ SIZE[IOControlBlock]; hearSelf: PUBLIC BOOLEAN _ FALSE; -- Non EXPORTed things. Note that all the state information lives in the CSBs. -- csb: CSB _ DLionInputOutput.IOPage + DLionInputOutput.ethernetCSBOffset; csb: CSB _ DLionInputOutput.IOPage + ethernetCSBOffset; QueueOutput: PUBLIC PROCEDURE [ device: DeviceHandle, buffer: LONG POINTER, length: CARDINAL, cb: IOCB] = { p: LONG POINTER _ buffer; IF device # self THEN RETURN; cb^ _ [ next: noIocb, mask: 0, spare: 1, completion: 0, used: 0, length: length - 1, buffer: buffer]; IF csb.output = noIocb THEN { -- new iocb, hardware idle csb.output _ Shorten[cb]; DLionInputOutput.Output[eEnableTrn, EOCtl]} -- poke hardware ELSE { -- output active, add to end of chain csb.lastOutput.next _ Shorten[cb]; IF csb.output = noIocb AND cb.completion = 0 THEN { -- oops, hardware went idle csb.output _ Shorten[cb]; DLionInputOutput.Output[eEnableTrn, EOCtl]}}; -- poke hardware csb.lastOutput _ cb}; QueueInput: PUBLIC PROCEDURE [ device: DeviceHandle, buffer: LONG POINTER, length: CARDINAL, cb: IOCB] = { IF device # self THEN RETURN; cb^ _ [ next: noIocb, mask: 0, spare: 0, completion: 0, used: 0, length: length, buffer: buffer]; IF csb.input # noIocb THEN csb.lastInput.next _ Shorten[cb]; IF csb.input = noIocb AND cb.completion = 0 THEN { csb.input _ Shorten[cb]; DLionInputOutput.Output[eEnableRcv, EICtl]}; csb.lastInput _ cb}; GetStatus: PUBLIC PROCEDURE [cb: IOCB] RETURNS [status: Status] = { completion: WORD; IF (completion _ cb.completion) = 0 THEN RETURN[pending]; IF cb.spare = 0 THEN { IF cb.length = 177777B THEN RETURN[packetTooLong]; status _ SELECT BITAND[completion, dribble + overRun + notGoodCRC + oddByte] FROM 0 => ok, dribble, oddByte + dribble => badAlignmentButOkCrc, notGoodCRC => crc, notGoodCRC + dribble, notGoodCRC + oddByte + dribble, notGoodCRC + oddByte => crcAndBadAlignment, overRun, overRun + dribble, overRun + notGoodCRC, overRun + notGoodCRC + dribble => overrun, ENDCASE => otherError; RETURN[status]}; IF cb.spare = 1 THEN { IF cb.mask = 0 THEN RETURN[tooManyCollisions]; RETURN[ SELECT BITAND[completion, collision + underRun] FROM 0 => ok, underRun, underRun + collision => underrun, ENDCASE => otherError]}; RETURN[otherError]}; GetRetries: PUBLIC PROCEDURE [cb: IOCB] RETURNS [CARDINAL] = { RETURN[ SELECT cb.mask FROM 1 => 0, 3 => 1, 7 => 2, 17B => 3, 37B => 4, 77B => 5, 177B => 6, 377B => 7, 777B => 8, 1777B => 9, 3777B => 10, 7777B => 11, 17777B => 12, 37777B => 13, 77777B => 14, 177777B => 15, ENDCASE => 16]}; GetPacketLength: PUBLIC PROCEDURE [cb: IOCB] RETURNS [used: CARDINAL] = BEGIN used _ cb.used; IF BITAND[cb.completion, dribble + oddByte] = dribble 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] = { IF device # self THEN RETURN; MakeSureOff[]; csb^ _ [ host: host, input: noIocb, inputWakeups: inInterrupt, output: noIocb, outputWakeups: outInterrupt, missed: 0, lastInput: NIL, lastOutput: NIL]; DLionInputOutput.Output[eEnableRcv, EICtl]}; TurnOff: PUBLIC PROCEDURE [device: DeviceHandle] = { IF device # self THEN RETURN; MakeSureOff[]}; -- There is no way to remove a cleanup procedure yet, so we have a flag to avoid duplicates. 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 => MakeSureOff[]; turnOff => {MakeSureOff[]; savedCSB _ csb^; oldHost _ csb.host}; turnOn => { -- 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. MakeSureOff[]; 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]; DLionInputOutput.Output[eEnableRcv, EICtl]}; ENDCASE; ENDLOOP}; RemoveCleanup: PUBLIC PROCEDURE [device: DeviceHandle] = {}; END. -- EthernetHeadDLion. copied from [Idun]11.0>Faces>Friends>DLionInputOutput.mesa Unused Space MagTape CSB Ethernet CSB More Unused Space Display CSB InputReg: TYPE = MACHINE DEPENDENT{ EIData(0), EStatus(1), KIData(2), KStatus(3), MStatus(5), KTest(6), IOPIData(8), IOPStatus(9), TStatus(10), (177777B)}; OutputReg: TYPE = MACHINE DEPENDENT{ IOPOData(0), IOPCtl(1), KOData(2), KCtl(3), EOData(4), EICtl(5), TCtlOrPCtl(9), MCtl(10), EOCtl(12), KCmd(13), TAddrOrClDPRq(14), TODataOrPOData(15), (177777B)}; end of copied stuff Ê@˜JšœÐ˜ÐJ˜+J˜Jšœ:˜:Jšœå˜åJ˜JšœB™BJ˜Jšœ ™ JšœÏkœ Ïc ˜-Jšœœ(˜@J˜Jšœ ™ Jšœœ ž ˜,Jšœœ(˜?J˜Jšœ ™ Jšœœ ž ˜-Jšœœ-˜EJ˜Jšœ™Jšœœ ž ˜1Jšœœ,˜HJ˜Jšœ ™ Jšœœ ž ˜,J˜J˜™#J™w—J˜šœ œœ œ™$Jšœ¢™¢—Jšœ˜Jšœ™J˜J˜Jš œ¿œœœžœ´8˜Ÿ>—…—%F(Œ