DIRECTORY CrRPC USING [Error, Handle, CreateClientHandle, DestroyClientHandle], HostNickNameTable USING [LookUp], DragOpsCross, DragOpsCrossUtils, RapunzelP2200V0, Rope USING [ROPE], SoftcardOps, SoftcardPrivate, XNS USING [unknownSocket], XNSName USING [Address, AddressFromRope]; SoftcardOpsImpl: CEDAR PROGRAM IMPORTS CrRPC, DragOpsCrossUtils, HostNickNameTable, Rapunzel: RapunzelP2200V0, XNSName, SoftcardOps EXPORTS SoftcardOps = BEGIN OPEN SoftcardPrivate; ROPE: TYPE = Rope.ROPE; Addr: TYPE = SoftcardOps.Addr; EUPBusCmd: TYPE = SoftcardOps.EUPBusCmd; -- tbd IFUPBusCmd: TYPE = SoftcardOps.IFUPBusCmd; EUInternal: TYPE = SoftcardOps.EUInternal; -- tbd IFUInternalState: TYPE = SoftcardOps.IFUInternalState; -- tbd ClockControl: TYPE = SoftcardOps.ClockControl; ControlBit: TYPE = SoftcardOps.ControlBit; StatusBit: TYPE = SoftcardOps.StatusBit; OneBit: TYPE = SoftcardPrivate.OneBit; Control1Bits: TYPE = SoftcardPrivate.Control1Bits; Control2Bits: TYPE = SoftcardPrivate.Control2Bits; StatusBits: TYPE = SoftcardPrivate.StatusBits; FullWordeuPBusCmd: TYPE = MACHINE DEPENDENT RECORD [ unspecifiedAsYet (0: 0..7): [0..377B] _ 0, unused (0: 8..15): [0..377B] _ 0 ]; FullWordifuPBusCmd: TYPE = MACHINE DEPENDENT RECORD [ reserved (0: 0..2): [0..7B] _ 0, ifuPBusCmd (0: 3..3): IFUPBusCmd _ noAccess, r1 (0: 4..6): [0..7B] _ 0, userMode (0: 7..7): BOOL _ FALSE, r2 (0: 8..15): [0..377B] _ 0 ]; crHandle: CrRPC.Handle; Error: PUBLIC SIGNAL[code: ATOM, explanation: ROPE _ NIL] = CODE; EstablishConnection: PUBLIC PROC[host: ROPE] RETURNS[ok: BOOL] = { Ec: PROC = { netAddr: ROPE = HostNickNameTable.LookUp[host]; socket: XNSName.Address = XNSName.AddressFromRope[netAddr, XNS.unknownSocket]; crHandle _ CrRPC.CreateClientHandle[$SPP, socket, 0]; }; CarefullyApply[proc: Ec, nilHandleOK: TRUE]; RETURN[crHandle # NIL]; }; CloseConnection: PUBLIC PROC = { CrRPC.DestroyClientHandle[crHandle]; crHandle _ NIL; }; SetEUBrkPtAddr: PUBLIC PROC[addr: Addr] = { Seu: PROC = { [] _ Rapunzel.PokeLong[crHandle, BkptEUH, addr ] }; CarefullyApply[Seu]; }; SetIFUBrkPtAddr: PUBLIC PROC[addr: Addr] = { Sifu: PROC = { [] _ Rapunzel.PokeLong[crHandle, BkptIFUH, addr] }; CarefullyApply[Sifu]; }; ReadEUCmd: PUBLIC PROC RETURNS[euPBusCmd: EUPBusCmd] = { Reuc: PROC = { user: FullWordifuPBusCmd = LOOPHOLE[ReadShort[SpyCmd2]]; most: FullWordeuPBusCmd = LOOPHOLE[ReadShort[SpyCmd1]]; euPBusCmd.userMode _ user.userMode; euPBusCmd.unspecifiedAsYet _ most.unspecifiedAsYet; }; CarefullyApply[Reuc]; }; ReadIFUCmd: PUBLIC PROC RETURNS[ifuPBusCmd: IFUPBusCmd] = { ifuPBusCmd _ LOOPHOLE[ReadShort[SpyCmd2], FullWordifuPBusCmd].ifuPBusCmd }; ReadEUPBusData: PUBLIC PROC RETURNS[value: DragOpsCross.Word] = { Reup: PROC = { value _ DragOpsCrossUtils.CardToWord[Rapunzel.PeekLong[crHandle, SpyEUDataH] ] }; CarefullyApply[Reup]; }; ReadIFUPBusData: PUBLIC PROC RETURNS[value: DragOpsCross.Word] = { Rifup: PROC = { value _ DragOpsCrossUtils.CardToWord[Rapunzel.PeekLong[crHandle, SpyEUDataH] ] }; CarefullyApply[Rifup]; }; ReadClock: PUBLIC PROC RETURNS[value: LONG CARDINAL] = { Rc: PROC = { value _ Rapunzel.PeekLong[crHandle, ClockH] }; CarefullyApply[Rc]; }; ReadEUInternalRegsiter: PUBLIC PROC[which: EUInternal] RETURNS[value, extra: DragOpsCross.Word] = { RETURN[DragOpsCross.ZerosWord, DragOpsCross.ZerosWord] }; WriteEUInternalRegsiter: PUBLIC PROC[ which: EUInternal, value, extra: DragOpsCross.Word] = { }; ReadIFUInternalState: PUBLIC PROC RETURNS[ifuState: IFUInternalState] = { }; WriteIFUInternalState: PUBLIC PROC[ifuState: IFUInternalState] = { }; ReadClockControl: PUBLIC PROC RETURNS[clockControl: ClockControl] = { Rcc: PROC = { clockControl _ LOOPHOLE[Rapunzel.PeekShort[crHandle, ClockControlAddr]] }; CarefullyApply[Rcc]; }; WriteClockControl: PUBLIC PROC[clockControl: ClockControl] = { Wcc: PROC = { Rapunzel.PokeShort[crHandle, ClockControlAddr, LOOPHOLE[clockControl, CARDINAL]] }; CarefullyApply[Wcc]; }; ReadControlBit: PUBLIC PROC[which: ControlBit] RETURNS[current: BOOL] = { isControl1: BOOL = IsControl1[which]; value: CARDINAL = ReadShort[IF isControl1 THEN Consult1 ELSE Consult2]; RETURN[ReturnBit[which, isControl1, value]]; }; SetControlBit: PUBLIC PROC[which: ControlBit] RETURNS[previous: BOOL] = { value: CARDINAL = ReadShort[GetControlResetAddr[which] + 2]; RETURN[ReturnBit[which, IsControl1[which], value]]; }; ResetControlBit: PUBLIC PROC[which: ControlBit] RETURNS[previous: BOOL] = { value: CARDINAL = ReadShort[GetControlResetAddr[which]]; RETURN[ReturnBit[which, IsControl1[which], value]]; }; ResetIFUCacheStateMachine: PUBLIC PROC = {}; ResetEUCacheStateMachine: PUBLIC PROC = {}; DisableIFUCache: PUBLIC PROC = { [] _ ReadShort[CarIFUCache] }; DisableEUCache: PUBLIC PROC = { [] _ ReadShort[CarEUCache] }; FlushIFUCache: PUBLIC PROC = { [] _ ReadShort[CarIFUCache]; [] _ ReadShort[CasIFUCache] }; FlushEUCache: PUBLIC PROC = { [] _ ReadShort[CarEUCache]; [] _ ReadShort[CasEUCache] }; ResetCounter: PUBLIC PROC = { [] _ ReadShort[CarCounter] }; IsControl1: PROC[which: ControlBit] RETURNS[BOOL] = { SELECT which FROM iopIntToDragon, mesaIntToDragon => RETURN[FALSE]; ENDCASE => RETURN[TRUE]; }; GetControlResetAddr: PROC[which: ControlBit] RETURNS[Addr] = { SELECT which FROM interruptDragonToIOP => RETURN[CarInterrurptDragonToIOP]; interruptDragonToMesa => RETURN[CarInterruptDragonToMesa]; writeParity => RETURN[CarWriteParity]; virtualMemAccessIOP => RETURN[CarVirtualMemAccessIOP]; virtualMemAccessMesa => RETURN[CarVirtualMemAccessMesa]; virtualMemAccessIFU => RETURN[CarVirtualMemAccessIFU]; virtualMemAccessEU => RETURN[CarVirtualMemAccessEU]; ifuBreakpointEnabled => RETURN[CarEnableIFUBkpt]; euBreakpointEnabled => RETURN[CarEnableEUBkpt]; iopIntToDragon => RETURN[CarIOPIntToDragon]; mesaIntToDragon => RETURN[CarMesaIntToDragon]; ENDCASE => ERROR; }; ReturnBit: PROC[which: ControlBit, isControl1: BOOL, value: CARDINAL] RETURNS[BOOL] = { control1Bits: Control1Bits; control2Bits: Control2Bits; IF isControl1 THEN control1Bits _ LOOPHOLE[value] ELSE control2Bits _ LOOPHOLE[value]; SELECT which FROM interruptDragonToIOP => RETURN[control1Bits.interrurptDragonToIOP]; interruptDragonToMesa => RETURN[control1Bits.interrurptDragonToMesa]; writeParity => RETURN[control1Bits.writeParity]; virtualMemAccessIOP => RETURN[control1Bits.virtualMemAccessIOP]; virtualMemAccessMesa => RETURN[control1Bits.virtualMemAccessMesa]; virtualMemAccessIFU => RETURN[control1Bits.virtualMemAccessIFU]; virtualMemAccessEU => RETURN[control1Bits.virtualMemAccessEU]; ifuBreakpointEnabled => RETURN[control1Bits.enableIFUBkpt]; euBreakpointEnabled => RETURN[control1Bits.enableEUBkpt]; iopIntToDragon => RETURN[control2Bits.iopIntToDragon]; mesaIntToDragon => RETURN[control2Bits.mesaIntToDragon]; ENDCASE => ERROR; }; ReadStatusBit: PUBLIC PROC[which: StatusBit] RETURNS[current: BOOL] = { all: StatusBits = LOOPHOLE[ReadShort[ConsultStatusAddr]]; RETURN[SelectStatusBit[which, all] ]; }; ResetStatusBit: PUBLIC PROC[which: StatusBit] RETURNS[previous: BOOL] = { all: StatusBits = LOOPHOLE[ReadShort[SelectStatusResetAddr[which]]]; RETURN[SelectStatusBit[which, all] ]; }; SelectStatusBit: PROC[which: StatusBit, all: StatusBits] RETURNS[BOOL] = { SELECT which FROM periodicIntToDragon => RETURN[all.periodicIntToDragon]; memoryError => RETURN[all.memoryError]; euBkptReached => RETURN[all.euBkptReached]; ifuBkptReached => RETURN[all.ifuBkptReached]; mapError => RETURN[all.mapError]; ENDCASE => ERROR; }; SelectStatusResetAddr: PROC[which: StatusBit] RETURNS[Addr] = { SELECT which FROM periodicIntToDragon => RETURN[CarPeriodicIntToDragon]; memoryError => RETURN[CarMemoryError]; euBkptReached => RETURN[CarEUBrkptReached]; ifuBkptReached => RETURN[CarIFUBrkptReached]; mapError => RETURN[CarMapError]; ENDCASE => ERROR; }; MesaMapIndex: TYPE = SoftcardOps.MesaMapIndex; MesaMapEntry: TYPE = SoftcardOps.MesaMapEntry; ReadMesaMap: PUBLIC PROC[index: MesaMapIndex] RETURNS[value: MesaMapEntry] = { RETURN[LOOPHOLE[ReadShort[MesaMapAddr + 2*LONG[index] + 1], MesaMapEntry] ] }; WriteMesaMap: PUBLIC PROC[index: MesaMapIndex, value: MesaMapEntry] = { WriteShort[MesaMapAddr+2*LONG[index]+1, LOOPHOLE[value, CARDINAL] ] }; DragonMapIndex: TYPE = SoftcardOps.DragonMapIndex; DragonMapEntry: TYPE = SoftcardOps.DragonMapEntry; ReadDragonMap: PUBLIC PROC[index: DragonMapIndex] RETURNS[value: DragonMapEntry] = { RETURN[LOOPHOLE[ReadShort[DragonMapAddr+2*index+1], DragonMapEntry] ] }; WriteDragonMap: PUBLIC PROC[index: DragonMapIndex, value: DragonMapEntry] = { WriteShort[DragonMapAddr+2*index+1, LOOPHOLE[value, CARDINAL] ] }; CarefullyApply: PROC[proc: PROC, nilHandleOK: BOOL _ FALSE] = { cText: ROPE; BEGIN ENABLE CrRPC.Error => { cText _ text; GOTO error; }; IF ~nilHandleOK AND crHandle = NIL THEN SIGNAL SoftcardOps.Error[$noConnection, "open a connection first"]; proc[]; EXITS error => SIGNAL SoftcardOps.Error[$crRPCError, cText]; END; }; ReadShort: PROC[addr: Addr] RETURNS[value: CARDINAL] = { Rs: PROC = { value _ Rapunzel.PeekShort[crHandle, addr] }; CarefullyApply[Rs]; }; WriteShort: PROC[addr: Addr, value: CARDINAL] = { Ws: PROC = { Rapunzel.PokeShort[crHandle, addr, value] }; CarefullyApply[Ws]; }; ConstructReadnBitSeq: PROC[num: CARDINAL] RETURNS[tSeq: Rapunzel.SeqCmd] = { index: CARDINAL _ 1; psDragonRun: Rapunzel.PeekShortCmd = [CarDragonRun]; psShiftA: Rapunzel.PeekShortCmd = [DebugShiftA]; psShiftB: Rapunzel.PeekShortCmd = [DebugShiftB]; psConsultStatus: Rapunzel.PeekShortCmd = [ConsultStatusAddr]; tSeq _ NEW[Rapunzel.SeqCmdObject[1+1+3*num]]; TRUSTED { tSeq[0] _ [peekShort[psDragonRun]]; -- stop the Dragon first FOR i: CARDINAL IN [0..num) DO tSeq[index _ index + 1] _ [peekShort[psShiftA]]; tSeq[index _ index + 1] _ [peekShort[psShiftB]]; tSeq[index _ index + 1] _ [peekShort[psConsultStatus]]; -- read the bit ENDLOOP; }; }; ConstructWritenBitSeq: PROC[num: CARDINAL] RETURNS[tSeq: Rapunzel.SeqCmd] = { index: CARDINAL _ 0; psDragonRun: Rapunzel.PeekShortCmd = [CarDragonRun]; psShiftA: Rapunzel.PeekShortCmd = [DebugShiftA]; psShiftB: Rapunzel.PeekShortCmd = [DebugShiftB]; tSeq _ NEW[Rapunzel.SeqCmdObject[1+1+3*num]]; TRUSTED { FOR i: CARDINAL IN [0..num) DO tSeq[index _ index + 1] _ [peekShort[psShiftA]]; tSeq[index _ index + 1] _ [peekShort[psShiftB]]; index _ index + 1; -- write the bit goes here ENDLOOP; tSeq[1+1+3*num-1-1] _ [peekShort[psDragonRun]]; -- stop the Dragon before the write }; }; END. ÒSoftcardOpsImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Willie-Sue, October 9, 1986 4:47:55 pm PDT for compiling purposes -- various CmdSeqences to be shared read32BitsSeq: Rapunzel.SeqCmd; -- for some eu registers write32BitsSeq: Rapunzel.SeqCmd; this may be good enough ************************* not all the internal registers are 32-bits long not all the internal registers are 32-bits long the IFU has only one internal state register format tbd Rifui: PROC = { resultSeq: Rapunzel.SeqResult; psReadIFU: Rapunzel.PeekShortCmd = [DebugReadIFU]; IF read32BitsSeq = NIL THEN read32BitsSeq _ ConstructReadnBitSeq[32]; TRUSTED { read32BitsSeq[1] _ [peekShort[psReadIFU]] }; resultSeq _ Rapunzel.DoCmds[crHandle, read32BitsSeq]; value _ DragOpsCross.ZerosWord; don't ask why the following numbers are used - just believe FOR i: CARDINAL _ 4, i+3 UNTIL i>=resultSeq.length DO res: Rapunzel.Result = resultSeq.body[i]; WITH res: res SELECT FROM peekShort => { read: StatusBits = LOOPHOLE[res.peekShort.value]; value _ DragOpsCrossUtils.SingleWordShiftLeft[value, 1]; value _ DragOpsCrossUtils.AddDelta[read.dOutIFU, value]; }; pokeShort => ERROR; ENDCASE => ERROR; ENDLOOP; }; CarefullyApply[Rifui]; the IFU has only one internal state register - format tbd Wifui: PROC = { resultSeq: Rapunzel.SeqResult; psWriteIFU: Rapunzel.PeekShortCmd = [DebugWriteIFU]; inInfo: DebugInfoEntry; eachBit: Rapunzel.PokeShortCmd; eachBit.address _ DebugInfo; IF write32BitsSeq = NIL THEN write32BitsSeq _ ConstructWritenBitSeq[32]; TRUSTED { write32BitsSeq[1+3*32] _ [peekShort[psWriteIFU]] }; don't ask why the following numbers are used - just believe FOR i: CARDINAL _ 1, i+3 UNTIL i>=write32BitsSeq.length DO inInfo.debugInIFU _ value[0]; eachBit.value _ LOOPHOLE[inInfo, CARDINAL]; value _ DragOpsCrossUtils.SingleWordShiftLeft[value, 1]; ENDLOOP; resultSeq _ Rapunzel.DoCmds[crHandle, write32BitsSeq]; }; CarefullyApply[Wifui]; ************************* ************************* Control and status bits. These are accessed only through Read operations. Some locations allow one to read a word of (up to) 16 of those bits without changing any of the bits. Reading other locations allows one to set or reset one particular bit, while still returning the previous value of all the bits. ***** ***** ***** ***** ***** ***** ***** ***** ************************* ************************* The mapping between 2 megabytes of daybreak physical address space and Dragon memory ************************* Access to the Dragon Map ************************* Utilities construct a CmdSeq of PeekShorts to read n-bits of internal state tSeq[1] _ [peekShort[DebugReadIFU/DebugReadEU]]; -- filled in by caller shift and read 32 bits of an ifu/eu shift register construct a CmdSeq of PokeShorts to write n-bits of internal state shift and read 32 bits of an ifu/eu shift register tSeq[1+1+3*num-1] _ [peekShort[DebugWriteIFU/DebugWriteEU]]; -- filled in by caller *********************************** Ê„˜codešœ™Kšœ Ïmœ1™šŸœžœ˜ Kšœ1žœžœ˜U—K˜K˜—J˜—™Kšœ:Ïbœõ™³K˜š Ÿœžœžœžœ žœ˜IKšœ žœ˜%Kš œžœ žœ žœ žœ ˜GKšžœ&˜,K˜—K˜š Ÿ œžœžœžœ žœ˜IKšœžœ-˜šžœž˜Kšœžœ˜9Kšœžœ¢˜:Kšœžœ¢œ˜&Kšœžœ¢œ˜6Kšœžœ¢œ˜8Kšœžœ¢œ˜6Kšœžœ¢œ˜4Kšœžœ¢œ˜1Kšœžœ¢œ˜/Kšœžœ¢œ˜,Kšœžœ¢œ˜.Kšžœžœ˜—K˜—K˜š Ÿ œžœ žœ žœžœžœ˜WK˜K˜Kš žœ žœžœžœžœ˜Všžœž˜Kšœžœ%˜CKšœžœ$¢˜EKšœžœ¢œ˜0Kšœžœ!¢œ˜@Kšœžœ"¢œ˜BKšœžœ!¢œ˜@Kšœžœ ¢œ˜>Kšœžœ¢œ˜;Kšœžœ¢œ˜9Kšœžœ¢œ˜6Kšœžœ¢œ˜8Kšžœžœ˜—K˜—K™K™K˜š Ÿ œžœžœžœ žœ˜GKšœžœ˜9Kšžœ˜%Kšœ˜—K˜š Ÿœžœžœžœ žœ˜IKšœžœ*˜DKšžœ˜%K˜—K˜šŸœžœ$žœžœ˜Jšžœž˜Kšœž¢œ¢˜7Kšœž¢œ¢˜'Kšœž¢œ¢˜+Kšœž¢œ¢˜-Kšœ ž¢œ¢˜!Kšžœžœ˜—K˜K˜—šŸœžœžœ ˜?šžœž˜Kšœž¢œ¢˜6Kšœž¢œ¢ ˜&Kšœž¢œ¢˜+Kšœž¢œ¢˜-Kšœ ž¢œ¢ ˜ Kšžœžœ˜—K˜K˜—K™—™K™TK˜Kšœžœ˜.Kšœžœ˜.K˜šŸ œžœžœžœ˜LKšœžœžœžœ ˜P—K˜šŸ œžœžœ,˜EKšœžœ žœžœ˜H—K™—™K™K˜Kšœžœ˜2Kšœžœ˜2K˜šŸ œžœžœžœ˜RKšœžœžœ9˜J—K˜šŸœžœžœ0˜KKšœ&žœžœ˜D——K˜™K™ K™š Ÿœžœžœžœžœ˜?Kšœžœ˜ šžœžœ˜Kšœ ˜ Kšžœ˜ K˜—˜šžœžœ žœž˜'Kšžœ=˜C—˜K˜šž˜Kšœ žœ'˜6——Kšžœ˜—K˜—K™šŸ œžœ žœžœ˜8šŸœžœ˜ Kšœ/˜/—K˜K˜—K˜šŸ œžœžœ˜1šŸœžœ˜ Kšœ.˜.—K˜K˜—K˜šŸœžœžœžœ˜MK™AKšœžœ˜Kšœ4˜4Kšœ0˜0Kšœ0˜0Kšœ=˜=K˜Kšœžœ#˜-šžœ˜ Kšœ% ˜=Kšœ1 ™GK™Kšœ2™2šžœžœžœ ž˜Kšœ ¢œ¢œ˜0Kšœ ¢œ¢œ˜0Kšœ ¢œ¢œ# ˜HKšžœ˜—K˜—K˜K˜—šŸœžœžœžœ˜NK™BKšœžœ˜Kšœ4˜4Kšœ0˜0Kšœ0˜0K˜Kšœžœ#˜-šžœ˜ K™Kšœ2™2šžœžœžœ ž˜Kšœ ¢œ¢œ˜0Kšœ ¢œ¢œ˜0Kšœ¢œ¢œ ˜.Kšžœ˜—Kšœ0 #˜SKšœ> ™TK˜—K˜——K˜™#K˜K™Kšžœ˜K˜—J˜—…—(ÌD"